summaryrefslogtreecommitdiff
path: root/shared-module
diff options
context:
space:
mode:
authorAnson He <ansonhe1997@gmail.com>2020-07-28 17:03:10 +0800
committerGitHub <noreply@github.com>2020-07-28 17:03:10 +0800
commitc010cc2c414a98caa1aa510497666bf017c792ab (patch)
treedac841881017719bae0654a64cbc52f35cf6977a /shared-module
parent36ef3476de945071da9c1274e5b4d8bcdcc13d13 (diff)
parentdebbf1028adee2309ed991c90517c50d5eb13bfb (diff)
Merge pull request #1 from adafruit/main
Merged main to fork
Diffstat (limited to 'shared-module')
-rw-r--r--shared-module/audiomp3/MP3Decoder.c54
-rw-r--r--shared-module/audiomp3/MP3Decoder.h2
-rw-r--r--shared-module/bitbangio/I2C.c2
-rw-r--r--shared-module/bitbangio/SPI.c2
-rw-r--r--shared-module/board/__init__.c2
-rw-r--r--shared-module/displayio/Display.c12
-rw-r--r--shared-module/displayio/Display.h4
-rw-r--r--shared-module/displayio/EPaperDisplay.c4
-rw-r--r--shared-module/displayio/EPaperDisplay.h1
-rw-r--r--shared-module/displayio/__init__.c4
-rw-r--r--shared-module/framebufferio/FramebufferDisplay.c17
-rw-r--r--shared-module/framebufferio/FramebufferDisplay.h1
-rw-r--r--shared-module/memorymonitor/AllocationAlarm.c94
-rw-r--r--shared-module/memorymonitor/AllocationAlarm.h51
-rw-r--r--shared-module/memorymonitor/AllocationSize.c91
-rw-r--r--shared-module/memorymonitor/AllocationSize.h51
-rw-r--r--shared-module/memorymonitor/__init__.c39
-rw-r--r--shared-module/memorymonitor/__init__.h35
-rw-r--r--shared-module/network/__init__.h2
-rw-r--r--shared-module/os/__init__.c2
-rw-r--r--shared-module/sdcardio/SDCard.c466
-rw-r--r--shared-module/sdcardio/SDCard.h51
-rw-r--r--shared-module/sdcardio/__init__.c0
-rw-r--r--shared-module/sdcardio/__init__.h0
-rw-r--r--shared-module/storage/__init__.c2
-rw-r--r--shared-module/touchio/TouchIn.c3
-rw-r--r--shared-module/vectorio/Polygon.c21
-rw-r--r--shared-module/vectorio/VectorShape.c4
-rw-r--r--shared-module/wiznet/wiznet5k.c2
-rw-r--r--shared-module/wiznet/wiznet5k.h2
30 files changed, 988 insertions, 33 deletions
diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c
index 30357c616..5f3f42a51 100644
--- a/shared-module/audiomp3/MP3Decoder.c
+++ b/shared-module/audiomp3/MP3Decoder.c
@@ -36,11 +36,12 @@
#include "shared-module/audiomp3/MP3Decoder.h"
#include "supervisor/shared/translate.h"
+#include "supervisor/background_callback.h"
#include "lib/mp3/src/mp3common.h"
#define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t))
-/** Fill the input buffer if it is less than half full.
+/** Fill the input buffer unconditionally.
*
* Returns true if the input buffer contains any useful data,
* false otherwise. (The input buffer will be padded to the end with
@@ -50,10 +51,7 @@
*
* Sets self->eof if any read of the file returns 0 bytes
*/
-STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) {
- // If buffer is over half full, do nothing
- if (self->inbuf_offset < self->inbuf_length/2) return true;
-
+STATIC bool mp3file_update_inbuf_always(audiomp3_mp3file_obj_t* self) {
// If we didn't previously reach the end of file, we can try reading now
if (!self->eof) {
@@ -87,6 +85,26 @@ STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) {
return self->inbuf_offset < self->inbuf_length;
}
+/** Update the inbuf from a background callback.
+ *
+ * This variant is introduced so that at the site of the
+ * add_background_callback_core call, the prototype matches.
+ */
+STATIC void mp3file_update_inbuf_cb(void* self) {
+ mp3file_update_inbuf_always(self);
+}
+
+/** Fill the input buffer if it is less than half full.
+ *
+ * Returns the same as mp3file_update_inbuf_always.
+ */
+STATIC bool mp3file_update_inbuf_half(audiomp3_mp3file_obj_t* self) {
+ // If buffer is over half full, do nothing
+ if (self->inbuf_offset < self->inbuf_length/2) return true;
+
+ return mp3file_update_inbuf_always(self);
+}
+
#define READ_PTR(self) (self->inbuf + self->inbuf_offset)
#define BYTES_LEFT(self) (self->inbuf_length - self->inbuf_offset)
#define CONSUME(self, n) (self->inbuf_offset += n)
@@ -94,7 +112,7 @@ STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) {
// http://id3.org/d3v2.3.0
// http://id3.org/id3v2.3.0
STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) {
- mp3file_update_inbuf(self);
+ mp3file_update_inbuf_half(self);
if (BYTES_LEFT(self) < 10) {
return;
}
@@ -129,11 +147,11 @@ STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) {
*/
STATIC bool mp3file_find_sync_word(audiomp3_mp3file_obj_t* self) {
do {
- mp3file_update_inbuf(self);
+ mp3file_update_inbuf_half(self);
int offset = MP3FindSyncWord(READ_PTR(self), BYTES_LEFT(self));
if (offset >= 0) {
CONSUME(self, offset);
- mp3file_update_inbuf(self);
+ mp3file_update_inbuf_half(self);
return true;
}
CONSUME(self, MAX(0, BYTES_LEFT(self) - 16));
@@ -209,12 +227,14 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
}
void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file) {
+ background_callback_begin_critical_section();
+
self->file = file;
f_lseek(&self->file->fp, 0);
self->inbuf_offset = self->inbuf_length;
self->eof = 0;
self->other_channel = -1;
- mp3file_update_inbuf(self);
+ mp3file_update_inbuf_half(self);
mp3file_find_sync_word(self);
// It **SHOULD** not be necessary to do this; the buffer should be filled
// with fresh content before it is returned by get_buffer(). The fact that
@@ -224,7 +244,9 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file
memset(self->buffers[0], 0, MAX_BUFFER_LEN);
memset(self->buffers[1], 0, MAX_BUFFER_LEN);
MP3FrameInfo fi;
- if(!mp3file_get_next_frame_info(self, &fi)) {
+ bool result = mp3file_get_next_frame_info(self, &fi);
+ background_callback_end_critical_section();
+ if (!result) {
mp_raise_msg(&mp_type_RuntimeError,
translate("Failed to parse MP3 file"));
}
@@ -277,13 +299,15 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self,
}
// We don't reset the buffer index in case we're looping and we have an odd number of buffer
// loads
+ background_callback_begin_critical_section();
f_lseek(&self->file->fp, 0);
self->inbuf_offset = self->inbuf_length;
self->eof = 0;
self->other_channel = -1;
- mp3file_update_inbuf(self);
+ mp3file_update_inbuf_half(self);
mp3file_skip_id3v2(self);
mp3file_find_sync_word(self);
+ background_callback_end_critical_section();
}
audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* self,
@@ -321,6 +345,14 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
uint8_t *inbuf = READ_PTR(self);
int err = MP3Decode(self->decoder, &inbuf, &bytes_left, buffer, 0);
CONSUME(self, BYTES_LEFT(self) - bytes_left);
+
+ if (self->inbuf_offset >= 512) {
+ background_callback_add(
+ &self->inbuf_fill_cb,
+ mp3file_update_inbuf_cb,
+ self);
+ }
+
if (err) {
return GET_BUFFER_DONE;
}
diff --git a/shared-module/audiomp3/MP3Decoder.h b/shared-module/audiomp3/MP3Decoder.h
index 9ee1d0949..f91f102a2 100644
--- a/shared-module/audiomp3/MP3Decoder.h
+++ b/shared-module/audiomp3/MP3Decoder.h
@@ -28,6 +28,7 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H
#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H
+#include "supervisor/background_callback.h"
#include "extmod/vfs_fat.h"
#include "py/obj.h"
@@ -36,6 +37,7 @@
typedef struct {
mp_obj_base_t base;
struct _MP3DecInfo *decoder;
+ background_callback_t inbuf_fill_cb;
uint8_t* inbuf;
uint32_t inbuf_length;
uint32_t inbuf_offset;
diff --git a/shared-module/bitbangio/I2C.c b/shared-module/bitbangio/I2C.c
index 5a9ac9a99..d44aec0e7 100644
--- a/shared-module/bitbangio/I2C.c
+++ b/shared-module/bitbangio/I2C.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George, Scott Shawcroft
+ * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George, Scott Shawcroft
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c
index e0ff1184f..f3fe16029 100644
--- a/shared-module/bitbangio/SPI.c
+++ b/shared-module/bitbangio/SPI.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c
index 0fbf916cd..2c9139d8a 100644
--- a/shared-module/board/__init__.c
+++ b/shared-module/board/__init__.c
@@ -123,7 +123,7 @@ mp_obj_t common_hal_board_create_uart(void) {
#endif
common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert,
- 9600, 8, PARITY_NONE, 1, 1.0f, 64, NULL, false);
+ 9600, 8, BUSIO_UART_PARITY_NONE, 1, 1.0f, 64, NULL, false);
MP_STATE_VM(shared_uart_bus) = MP_OBJ_FROM_PTR(self);
return MP_STATE_VM(shared_uart_bus);
}
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index a3d877f1a..46bb6fdb5 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -137,7 +137,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
// Set the group after initialization otherwise we may send pixels while we delay in
// initialization.
common_hal_displayio_display_show(self, &circuitpython_splash);
- self->auto_refresh = auto_refresh;
+ common_hal_displayio_display_set_auto_refresh(self, auto_refresh);
}
bool common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
@@ -383,6 +383,13 @@ bool common_hal_displayio_display_get_auto_refresh(displayio_display_obj_t* self
void common_hal_displayio_display_set_auto_refresh(displayio_display_obj_t* self,
bool auto_refresh) {
self->first_manual_refresh = !auto_refresh;
+ if (auto_refresh != self->auto_refresh) {
+ if (auto_refresh) {
+ supervisor_enable_tick();
+ } else {
+ supervisor_disable_tick();
+ }
+ }
self->auto_refresh = auto_refresh;
}
@@ -409,6 +416,7 @@ void displayio_display_background(displayio_display_obj_t* self) {
}
void release_display(displayio_display_obj_t* self) {
+ common_hal_displayio_display_set_auto_refresh(self, false);
release_display_core(&self->core);
#if (CIRCUITPY_PULSEIO)
if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
@@ -423,7 +431,7 @@ void release_display(displayio_display_obj_t* self) {
}
void reset_display(displayio_display_obj_t* self) {
- self->auto_refresh = true;
+ common_hal_displayio_display_set_auto_refresh(self, true);
self->auto_brightness = true;
common_hal_displayio_display_show(self, NULL);
}
diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h
index 8adaf597f..861a38fd7 100644
--- a/shared-module/displayio/Display.h
+++ b/shared-module/displayio/Display.h
@@ -29,7 +29,9 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/displayio/Group.h"
+#if CIRCUITPY_PULSEIO
#include "shared-bindings/pulseio/PWMOut.h"
+#endif
#include "shared-module/displayio/area.h"
#include "shared-module/displayio/display_core.h"
@@ -39,7 +41,9 @@ typedef struct {
displayio_display_core_t core;
union {
digitalio_digitalinout_obj_t backlight_inout;
+ #if CIRCUITPY_PULSEIO
pulseio_pwmout_obj_t backlight_pwm;
+ #endif
};
uint64_t last_backlight_refresh;
uint64_t last_refresh_call;
diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c
index 6a55687b9..6d9e915b4 100644
--- a/shared-module/displayio/EPaperDisplay.c
+++ b/shared-module/displayio/EPaperDisplay.c
@@ -187,6 +187,7 @@ void displayio_epaperdisplay_finish_refresh(displayio_epaperdisplay_obj_t* self)
displayio_display_core_begin_transaction(&self->core);
self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, &self->refresh_display_command, 1);
displayio_display_core_end_transaction(&self->core);
+ supervisor_enable_tick();
self->refreshing = true;
displayio_display_core_finish_refresh(&self->core);
@@ -301,6 +302,7 @@ bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* s
if (self->refreshing && self->busy.base.type == &digitalio_digitalinout_type) {
if (common_hal_digitalio_digitalinout_get_value(&self->busy) != self->busy_state) {
+ supervisor_disable_tick();
self->refreshing = false;
// Run stop sequence but don't wait for busy because busy is set when sleeping.
send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len);
@@ -342,6 +344,7 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) {
refresh_done = supervisor_ticks_ms64() - self->core.last_refresh > self->refresh_time;
}
if (refresh_done) {
+ supervisor_disable_tick();
self->refreshing = false;
// Run stop sequence but don't wait for busy because busy is set when sleeping.
send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len);
@@ -352,6 +355,7 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) {
void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) {
if (self->refreshing) {
wait_for_busy(self);
+ supervisor_disable_tick();
self->refreshing = false;
// Run stop sequence but don't wait for busy because busy is set when sleeping.
send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len);
diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h
index d08bed546..3b9f6e368 100644
--- a/shared-module/displayio/EPaperDisplay.h
+++ b/shared-module/displayio/EPaperDisplay.h
@@ -29,7 +29,6 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/displayio/Group.h"
-#include "shared-bindings/pulseio/PWMOut.h"
#include "shared-module/displayio/area.h"
#include "shared-module/displayio/display_core.h"
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index c898bbb98..efc28470f 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -190,9 +190,7 @@ void reset_displays(void) {
common_hal_displayio_epaperdisplay_show(display, NULL);
#if CIRCUITPY_FRAMEBUFFERIO
} else if (displays[i].framebuffer_display.base.type == &framebufferio_framebufferdisplay_type) {
- framebufferio_framebufferdisplay_obj_t* display = &displays[i].framebuffer_display;
- display->auto_refresh = true;
- common_hal_framebufferio_framebufferdisplay_show(display, NULL);
+ framebufferio_framebufferdisplay_reset(&displays[i].framebuffer_display);
#endif
}
}
diff --git a/shared-module/framebufferio/FramebufferDisplay.c b/shared-module/framebufferio/FramebufferDisplay.c
index f296da409..2a90fa0d4 100644
--- a/shared-module/framebufferio/FramebufferDisplay.c
+++ b/shared-module/framebufferio/FramebufferDisplay.c
@@ -79,7 +79,7 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu
// Set the group after initialization otherwise we may send pixels while we delay in
// initialization.
common_hal_framebufferio_framebufferdisplay_show(self, &circuitpython_splash);
- self->auto_refresh = auto_refresh;
+ common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, auto_refresh);
}
bool common_hal_framebufferio_framebufferdisplay_show(framebufferio_framebufferdisplay_obj_t* self, displayio_group_t* root_group) {
@@ -280,6 +280,13 @@ bool common_hal_framebufferio_framebufferdisplay_get_auto_refresh(framebufferio_
void common_hal_framebufferio_framebufferdisplay_set_auto_refresh(framebufferio_framebufferdisplay_obj_t* self,
bool auto_refresh) {
self->first_manual_refresh = !auto_refresh;
+ if (auto_refresh != self->auto_refresh) {
+ if (auto_refresh) {
+ supervisor_enable_tick();
+ } else {
+ supervisor_disable_tick();
+ }
+ }
self->auto_refresh = auto_refresh;
}
@@ -297,12 +304,13 @@ void framebufferio_framebufferdisplay_background(framebufferio_framebufferdispla
}
void release_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self) {
+ common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, false);
release_display_core(&self->core);
self->framebuffer_protocol->deinit(self->framebuffer);
}
void reset_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self) {
- self->auto_refresh = true;
+ common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, true);
common_hal_framebufferio_framebufferdisplay_show(self, NULL);
}
@@ -310,3 +318,8 @@ void framebufferio_framebufferdisplay_collect_ptrs(framebufferio_framebufferdisp
gc_collect_ptr(self->framebuffer);
displayio_display_core_collect_ptrs(&self->core);
}
+
+void framebufferio_framebufferdisplay_reset(framebufferio_framebufferdisplay_obj_t* self) {
+ common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, true);
+ common_hal_framebufferio_framebufferdisplay_show(self, NULL);
+}
diff --git a/shared-module/framebufferio/FramebufferDisplay.h b/shared-module/framebufferio/FramebufferDisplay.h
index 1b68d2ab0..ca1ab984a 100644
--- a/shared-module/framebufferio/FramebufferDisplay.h
+++ b/shared-module/framebufferio/FramebufferDisplay.h
@@ -55,6 +55,7 @@ typedef struct {
void framebufferio_framebufferdisplay_background(framebufferio_framebufferdisplay_obj_t* self);
void release_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self);
void reset_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self);
+void framebufferio_framebufferdisplay_reset(framebufferio_framebufferdisplay_obj_t* self);
void framebufferio_framebufferdisplay_collect_ptrs(framebufferio_framebufferdisplay_obj_t* self);
diff --git a/shared-module/memorymonitor/AllocationAlarm.c b/shared-module/memorymonitor/AllocationAlarm.c
new file mode 100644
index 000000000..35f4e4c63
--- /dev/null
+++ b/shared-module/memorymonitor/AllocationAlarm.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/memorymonitor/__init__.h"
+#include "shared-bindings/memorymonitor/AllocationAlarm.h"
+
+#include "py/gc.h"
+#include "py/mpstate.h"
+#include "py/runtime.h"
+
+void common_hal_memorymonitor_allocationalarm_construct(memorymonitor_allocationalarm_obj_t* self, size_t minimum_block_count) {
+ self->minimum_block_count = minimum_block_count;
+ self->next = NULL;
+ self->previous = NULL;
+}
+
+void common_hal_memorymonitor_allocationalarm_set_ignore(memorymonitor_allocationalarm_obj_t* self, mp_int_t count) {
+ self->count = count;
+}
+
+void common_hal_memorymonitor_allocationalarm_pause(memorymonitor_allocationalarm_obj_t* self) {
+ // Check to make sure we aren't already paused. We can be if we're exiting from an exception we
+ // caused.
+ if (self->previous == NULL) {
+ return;
+ }
+ *self->previous = self->next;
+ self->next = NULL;
+ self->previous = NULL;
+}
+
+void common_hal_memorymonitor_allocationalarm_resume(memorymonitor_allocationalarm_obj_t* self) {
+ if (self->previous != NULL) {
+ mp_raise_RuntimeError(translate("Already running"));
+ }
+ self->next = MP_STATE_VM(active_allocationalarms);
+ self->previous = (memorymonitor_allocationalarm_obj_t**) &MP_STATE_VM(active_allocationalarms);
+ if (self->next != NULL) {
+ self->next->previous = &self->next;
+ }
+ MP_STATE_VM(active_allocationalarms) = self;
+}
+
+void memorymonitor_allocationalarms_allocation(size_t block_count) {
+ memorymonitor_allocationalarm_obj_t* alarm = MP_OBJ_TO_PTR(MP_STATE_VM(active_allocationalarms));
+ size_t alert_count = 0;
+ while (alarm != NULL) {
+ // Hold onto next in case we remove the alarm from the list.
+ memorymonitor_allocationalarm_obj_t* next = alarm->next;
+ if (block_count >= alarm->minimum_block_count) {
+ if (alarm->count > 0) {
+ alarm->count--;
+ } else {
+ // Uncomment the breakpoint below if you want to use a C debugger to figure out the C
+ // call stack for an allocation.
+ // asm("bkpt");
+ // Pause now because we may alert when throwing the exception too.
+ common_hal_memorymonitor_allocationalarm_pause(alarm);
+ alert_count++;
+ }
+ }
+ alarm = next;
+ }
+ if (alert_count > 0) {
+ mp_raise_memorymonitor_AllocationError(translate("Attempt to allocate %d blocks"), block_count);
+ }
+}
+
+void memorymonitor_allocationalarms_reset(void) {
+ MP_STATE_VM(active_allocationalarms) = NULL;
+}
diff --git a/shared-module/memorymonitor/AllocationAlarm.h b/shared-module/memorymonitor/AllocationAlarm.h
new file mode 100644
index 000000000..172c24f6c
--- /dev/null
+++ b/shared-module/memorymonitor/AllocationAlarm.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_MEMORYMONITOR_ALLOCATIONALARM_H
+#define MICROPY_INCLUDED_SHARED_MODULE_MEMORYMONITOR_ALLOCATIONALARM_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
+typedef struct _memorymonitor_allocationalarm_obj_t memorymonitor_allocationalarm_obj_t;
+
+#define ALLOCATION_SIZE_BUCKETS 16
+
+typedef struct _memorymonitor_allocationalarm_obj_t {
+ mp_obj_base_t base;
+ size_t minimum_block_count;
+ mp_int_t count;
+ // Store the location that points to us so we can remove ourselves.
+ memorymonitor_allocationalarm_obj_t** previous;
+ memorymonitor_allocationalarm_obj_t* next;
+} memorymonitor_allocationalarm_obj_t;
+
+void memorymonitor_allocationalarms_allocation(size_t block_count);
+void memorymonitor_allocationalarms_reset(void);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_MEMORYMONITOR_ALLOCATIONALARM_H
diff --git a/shared-module/memorymonitor/AllocationSize.c b/shared-module/memorymonitor/AllocationSize.c
new file mode 100644
index 000000000..c28e65592
--- /dev/null
+++ b/shared-module/memorymonitor/AllocationSize.c
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/memorymonitor/AllocationSize.h"
+
+#include "py/gc.h"
+#include "py/mpstate.h"
+#include "py/runtime.h"
+
+void common_hal_memorymonitor_allocationsize_construct(memorymonitor_allocationsize_obj_t* self) {
+ common_hal_memorymonitor_allocationsize_clear(self);
+ self->next = NULL;
+ self->previous = NULL;
+}
+
+void common_hal_memorymonitor_allocationsize_pause(memorymonitor_allocationsize_obj_t* self) {
+ *self->previous = self->next;
+ self->next = NULL;
+ self->previous = NULL;
+}
+
+void common_hal_memorymonitor_allocationsize_resume(memorymonitor_allocationsize_obj_t* self) {
+ if (self->previous != NULL) {
+ mp_raise_RuntimeError(translate("Already running"));
+ }
+ self->next = MP_STATE_VM(active_allocationsizes);
+ self->previous = (memorymonitor_allocationsize_obj_t**) &MP_STATE_VM(active_allocationsizes);
+ if (self->next != NULL) {
+ self->next->previous = &self->next;
+ }
+ MP_STATE_VM(active_allocationsizes) = self;
+}
+
+void common_hal_memorymonitor_allocationsize_clear(memorymonitor_allocationsize_obj_t* self) {
+ for (size_t i = 0; i < ALLOCATION_SIZE_BUCKETS; i++) {
+ self->buckets[i] = 0;
+ }
+}
+
+uint16_t common_hal_memorymonitor_allocationsize_get_len(memorymonitor_allocationsize_obj_t* self) {
+ return ALLOCATION_SIZE_BUCKETS;
+}
+
+size_t common_hal_memorymonitor_allocationsize_get_bytes_per_block(memorymonitor_allocationsize_obj_t* self) {
+ return BYTES_PER_BLOCK;
+}
+
+uint16_t common_hal_memorymonitor_allocationsize_get_item(memorymonitor_allocationsize_obj_t* self, int16_t index) {
+ return self->buckets[index];
+}
+
+void memorymonitor_allocationsizes_track_allocation(size_t block_count) {
+ memorymonitor_allocationsize_obj_t* as = MP_OBJ_TO_PTR(MP_STATE_VM(active_allocationsizes));
+ size_t power_of_two = 0;
+ block_count >>= 1;
+ while (block_count != 0) {
+ power_of_two++;
+ block_count >>= 1;
+ }
+ while (as != NULL) {
+ as->buckets[power_of_two]++;
+ as = as->next;
+ }
+}
+
+void memorymonitor_allocationsizes_reset(void) {
+ MP_STATE_VM(active_allocationsizes) = NULL;
+}
diff --git a/shared-module/memorymonitor/AllocationSize.h b/shared-module/memorymonitor/AllocationSize.h
new file mode 100644
index 000000000..3baab2213
--- /dev/null
+++ b/shared-module/memorymonitor/AllocationSize.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_MEMORYMONITOR_ALLOCATIONSIZE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_MEMORYMONITOR_ALLOCATIONSIZE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
+typedef struct _memorymonitor_allocationsize_obj_t memorymonitor_allocationsize_obj_t;
+
+#define ALLOCATION_SIZE_BUCKETS 16
+
+typedef struct _memorymonitor_allocationsize_obj_t {
+ mp_obj_base_t base;
+ uint16_t buckets[ALLOCATION_SIZE_BUCKETS];
+ // Store the location that points to us so we can remove ourselves.
+ memorymonitor_allocationsize_obj_t** previous;
+ memorymonitor_allocationsize_obj_t* next;
+ bool paused;
+} memorymonitor_allocationsize_obj_t;
+
+void memorymonitor_allocationsizes_track_allocation(size_t block_count);
+void memorymonitor_allocationsizes_reset(void);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_MEMORYMONITOR_ALLOCATIONSIZE_H
diff --git a/shared-module/memorymonitor/__init__.c b/shared-module/memorymonitor/__init__.c
new file mode 100644
index 000000000..6cb424153
--- /dev/null
+++ b/shared-module/memorymonitor/__init__.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/memorymonitor/__init__.h"
+#include "shared-module/memorymonitor/AllocationAlarm.h"
+#include "shared-module/memorymonitor/AllocationSize.h"
+
+void memorymonitor_track_allocation(size_t block_count) {
+ memorymonitor_allocationalarms_allocation(block_count);
+ memorymonitor_allocationsizes_track_allocation(block_count);
+}
+
+void memorymonitor_reset(void) {
+ memorymonitor_allocationalarms_reset();
+ memorymonitor_allocationsizes_reset();
+}
diff --git a/shared-module/memorymonitor/__init__.h b/shared-module/memorymonitor/__init__.h
new file mode 100644
index 000000000..f47f6434b
--- /dev/null
+++ b/shared-module/memorymonitor/__init__.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_MEMORYMONITOR___INIT___H
+#define MICROPY_INCLUDED_MEMORYMONITOR___INIT___H
+
+#include <stddef.h>
+
+void memorymonitor_track_allocation(size_t block_count);
+void memorymonitor_reset(void);
+
+#endif // MICROPY_INCLUDED_MEMORYMONITOR___INIT___H
diff --git a/shared-module/network/__init__.h b/shared-module/network/__init__.h
index f4eb05bb5..280cfe6c8 100644
--- a/shared-module/network/__init__.h
+++ b/shared-module/network/__init__.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2018 Nick Moore
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c
index 8060eec4f..39cf40fda 100644
--- a/shared-module/os/__init__.c
+++ b/shared-module/os/__init__.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Josef Gajdusek
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c
new file mode 100644
index 000000000..9e861279d
--- /dev/null
+++ b/shared-module/sdcardio/SDCard.c
@@ -0,0 +1,466 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// This implementation largely follows the structure of adafruit_sdcard.py
+
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-bindings/util.h"
+#include "shared-module/sdcardio/SDCard.h"
+
+#include "py/mperrno.h"
+
+#if 0
+#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print, ## __VA_ARGS__))
+#else
+#define DEBUG_PRINT(...) ((void)0)
+#endif
+
+#define CMD_TIMEOUT (200)
+
+#define R1_IDLE_STATE (1<<0)
+#define R1_ILLEGAL_COMMAND (1<<2)
+
+#define TOKEN_CMD25 (0xFC)
+#define TOKEN_STOP_TRAN (0xFD)
+#define TOKEN_DATA (0xFE)
+
+STATIC bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) {
+ if (!common_hal_busio_spi_try_lock(self->bus)) {
+ return false;
+ }
+ common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8);
+ common_hal_digitalio_digitalinout_set_value(&self->cs, false);
+ return true;
+}
+
+STATIC void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) {
+ if (!lock_and_configure_bus(self)) {
+ mp_raise_OSError(EAGAIN);
+ }
+}
+
+STATIC void clock_card(sdcardio_sdcard_obj_t *self, int bytes) {
+ uint8_t buf[] = {0xff};
+ common_hal_digitalio_digitalinout_set_value(&self->cs, true);
+ for (int i=0; i<bytes; i++) {
+ common_hal_busio_spi_write(self->bus, buf, 1);
+ }
+}
+
+STATIC void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) {
+ clock_card(self, 1);
+ common_hal_busio_spi_unlock(self->bus);
+}
+
+static uint8_t CRC7(const uint8_t* data, uint8_t n) {
+ uint8_t crc = 0;
+ for (uint8_t i = 0; i < n; i++) {
+ uint8_t d = data[i];
+ for (uint8_t j = 0; j < 8; j++) {
+ crc <<= 1;
+ if ((d & 0x80) ^ (crc & 0x80)) {
+ crc ^= 0x09;
+ }
+ d <<= 1;
+ }
+ }
+ return (crc << 1) | 1;
+}
+
+#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms
+STATIC void wait_for_ready(sdcardio_sdcard_obj_t *self) {
+ uint64_t deadline = common_hal_time_monotonic_ns() + READY_TIMEOUT_NS;
+ while (common_hal_time_monotonic_ns() < deadline) {
+ uint8_t b;
+ common_hal_busio_spi_read(self->bus, &b, 1, 0xff);
+ if (b == 0xff) {
+ break;
+ }
+ }
+}
+
+// In Python API, defaults are response=None, data_block=True, wait=True
+STATIC int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf, size_t response_len, bool data_block, bool wait) {
+ DEBUG_PRINT("cmd % 3d [%02x] arg=% 11d [%08x] len=%d%s%s\n", cmd, cmd, arg, arg, response_len, data_block ? " data" : "", wait ? " wait" : "");
+ uint8_t cmdbuf[6];
+ cmdbuf[0] = cmd | 0x40;
+ cmdbuf[1] = (arg >> 24) & 0xff;
+ cmdbuf[2] = (arg >> 16) & 0xff;
+ cmdbuf[3] = (arg >> 8) & 0xff;
+ cmdbuf[4] = arg & 0xff;
+ cmdbuf[5] = CRC7(cmdbuf, 5);
+
+ if (wait) {
+ wait_for_ready(self);
+ }
+
+ common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf));
+
+ // Wait for the response (response[7] == 0)
+ bool response_received = false;
+ for (int i=0; i<CMD_TIMEOUT; i++) {
+ common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff);
+ if ((cmdbuf[0] & 0x80) == 0) {
+ response_received = true;
+ break;
+ }
+ }
+
+ if (!response_received) {
+ return -EIO;
+ }
+
+ if (response_buf) {
+
+ if (data_block) {
+ cmdbuf[1] = 0xff;
+ do {
+ // Wait for the start block byte
+ common_hal_busio_spi_read(self->bus, cmdbuf+1, 1, 0xff);
+ } while (cmdbuf[1] != 0xfe);
+ }
+
+ common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff);
+
+ if (data_block) {
+ // Read and discard the CRC-CCITT checksum
+ common_hal_busio_spi_read(self->bus, cmdbuf+1, 2, 0xff);
+ }
+
+ }
+
+ return cmdbuf[0];
+}
+
+STATIC int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *response_buf, size_t response_len, bool data_block, bool wait) {
+ return cmd(self, cmd_, block * self->cdv, response_buf, response_len, true, true);
+}
+
+STATIC bool cmd_nodata(sdcardio_sdcard_obj_t* self, int cmd, int response) {
+ uint8_t cmdbuf[2] = {cmd, 0xff};
+
+ common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf));
+
+ // Wait for the response (response[7] == response)
+ for (int i=0; i<CMD_TIMEOUT; i++) {
+ common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff);
+ if (cmdbuf[0] == response) {
+ return 0;
+ }
+ }
+ return -EIO;
+}
+
+STATIC const compressed_string_t *init_card_v1(sdcardio_sdcard_obj_t *self) {
+ for (int i=0; i<CMD_TIMEOUT; i++) {
+ if (cmd(self, 41, 0, NULL, 0, true, true) == 0) {
+ return NULL;
+ }
+ }
+ return translate("timeout waiting for v1 card");
+}
+
+STATIC const compressed_string_t *init_card_v2(sdcardio_sdcard_obj_t *self) {
+ for (int i=0; i<CMD_TIMEOUT; i++) {
+ uint8_t ocr[4];
+ common_hal_time_delay_ms(50);
+ cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
+ cmd(self, 55, 0, NULL, 0, true, true);
+ if (cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) {
+ cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
+ if ((ocr[0] & 0x40) != 0) {
+ self->cdv = 1;
+ }
+ return NULL;
+ }
+ }
+ return translate("timeout waiting for v2 card");
+}
+
+STATIC const compressed_string_t *init_card(sdcardio_sdcard_obj_t *self) {
+ clock_card(self, 10);
+
+ common_hal_digitalio_digitalinout_set_value(&self->cs, false);
+
+ // CMD0: init card: should return _R1_IDLE_STATE (allow 5 attempts)
+ {
+ bool reached_idle_state = false;
+ for (int i=0; i<5; i++) {
+ if (cmd(self, 0, 0, NULL, 0, true, true) == R1_IDLE_STATE) {
+ reached_idle_state = true;
+ break;
+ }
+ }
+ if (!reached_idle_state) {
+ return translate("no SD card");
+ }
+ }
+
+ // CMD8: determine card version
+ {
+ uint8_t rb7[4];
+ int response = cmd(self, 8, 0x1AA, rb7, sizeof(rb7), false, true);
+ if (response == R1_IDLE_STATE) {
+ const compressed_string_t *result =init_card_v2(self);
+ if (result != NULL) {
+ return result;
+ }
+ } else if (response == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
+ const compressed_string_t *result =init_card_v1(self);
+ if (result != NULL) {
+ return result;
+ }
+ } else {
+ return translate("couldn't determine SD card version");
+ }
+ }
+
+ // CMD9: get number of sectors
+ {
+ uint8_t csd[16];
+ int response = cmd(self, 9, 0, csd, sizeof(csd), true, true);
+ if (response != 0) {
+ return translate("no response from SD card");
+ }
+ int csd_version = (csd[0] & 0xC0) >> 6;
+ if (csd_version >= 2) {
+ return translate("SD card CSD format not supported");
+ }
+
+ if (csd_version == 1) {
+ self->sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024;
+ } else {
+ uint32_t block_length = 1 << (csd[5] & 0xF);
+ uint32_t c_size = ((csd[6] & 0x3) << 10) | (csd[7] << 2) | ((csd[8] & 0xC) >> 6);
+ uint32_t mult = 1 << (((csd[9] & 0x3) << 1 | (csd[10] & 0x80) >> 7) + 2);
+ self->sectors = block_length / 512 * mult * (c_size + 1);
+ }
+ }
+
+ // CMD16: set block length to 512 bytes
+ {
+ int response = cmd(self, 16, 512, NULL, 0, true, true);
+ if (response != 0) {
+ return translate("can't set 512 block size");
+ }
+ }
+
+ return NULL;
+}
+
+void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, mcu_pin_obj_t *cs, int baudrate) {
+ self->bus = bus;
+ common_hal_digitalio_digitalinout_construct(&self->cs, cs);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);
+
+ self->cdv = 512;
+ self->sectors = 0;
+ self->baudrate = 250000;
+
+ lock_bus_or_throw(self);
+ const compressed_string_t *result = init_card(self);
+ extraclock_and_unlock_bus(self);
+
+ if (result != NULL) {
+ common_hal_digitalio_digitalinout_deinit(&self->cs);
+ mp_raise_OSError_msg(result);
+ }
+
+ self->baudrate = baudrate;
+}
+
+void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) {
+ if (!self->bus) {
+ return;
+ }
+ self->bus = 0;
+ common_hal_digitalio_digitalinout_deinit(&self->cs);
+}
+
+void common_hal_sdcardio_check_for_deinit(sdcardio_sdcard_obj_t *self) {
+ if (!self->bus) {
+ raise_deinited_error();
+ }
+}
+
+int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) {
+ common_hal_sdcardio_check_for_deinit(self);
+ return self->sectors;
+}
+
+int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) {
+ uint8_t aux[2] = {0, 0};
+ while (aux[0] != 0xfe) {
+ common_hal_busio_spi_read(self->bus, aux, 1, 0xff);
+ }
+
+ common_hal_busio_spi_read(self->bus, buf, size, 0xff);
+
+ // Read checksum and throw it away
+ common_hal_busio_spi_read(self->bus, aux, sizeof(aux), 0xff);
+ return 0;
+}
+
+int readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
+ uint32_t nblocks = buf->len / 512;
+ if (nblocks == 1) {
+ // Use CMD17 to read a single block
+ return block_cmd(self, 17, start_block, buf->buf, buf->len, true, true);
+ } else {
+ // Use CMD18 to read multiple blocks
+ int r = block_cmd(self, 18, start_block, NULL, 0, true, true);
+ if (r < 0) {
+ return r;
+ }
+
+ uint8_t *ptr = buf->buf;
+ while (nblocks--) {
+ r = readinto(self, ptr, 512);
+ if (r < 0) {
+ return r;
+ }
+ ptr += 512;
+ }
+
+ // End the multi-block read
+ r = cmd(self, 12, 0, NULL, 0, true, false);
+
+ // Return first status 0 or last before card ready (0xff)
+ while (r != 0) {
+ uint8_t single_byte;
+ common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff);
+ if (single_byte & 0x80) {
+ return r;
+ }
+ r = single_byte;
+ }
+ }
+ return 0;
+}
+
+int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
+ common_hal_sdcardio_check_for_deinit(self);
+ if (buf->len % 512 != 0) {
+ mp_raise_ValueError(translate("Buffer length must be a multiple of 512"));
+ }
+
+ lock_and_configure_bus(self);
+ int r = readblocks(self, start_block, buf);
+ extraclock_and_unlock_bus(self);
+ return r;
+}
+
+int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
+ wait_for_ready(self);
+
+ uint8_t cmd[2];
+ cmd[0] = token;
+
+ common_hal_busio_spi_write(self->bus, cmd, 1);
+ common_hal_busio_spi_write(self->bus, buf, size);
+
+ cmd[0] = cmd[1] = 0xff;
+ common_hal_busio_spi_write(self->bus, cmd, 2);
+
+ // Check the response
+ // This differs from the traditional adafruit_sdcard handling,
+ // but adafruit_sdcard also ignored the return value of SDCard._write(!)
+ // so nobody noticed
+ //
+ //
+ // Response is as follows:
+ // x x x 0 STAT 1
+ // 7 6 5 4 3..1 0
+ // with STATUS 010 indicating "data accepted", and other status bit
+ // combinations indicating failure.
+ // In practice, I was seeing cmd[0] as 0xe5, indicating success
+ for (int i=0; i<CMD_TIMEOUT; i++) {
+ common_hal_busio_spi_read(self->bus, cmd, 1, 0xff);
+ DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]);
+ if ((cmd[0] & 0b00010001) == 0b00000001) {
+ if ((cmd[0] & 0x1f) != 0x5) {
+ return -EIO;
+ } else {
+ break;
+ }
+ }
+ }
+
+ // Wait for the write to finish
+ do {
+ common_hal_busio_spi_read(self->bus, cmd, 1, 0xff);
+ } while (cmd[0] == 0);
+
+ // Success
+ return 0;
+}
+
+int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
+ common_hal_sdcardio_check_for_deinit(self);
+ uint32_t nblocks = buf->len / 512;
+ if (nblocks == 1) {
+ // Use CMD24 to write a single block
+ int r = block_cmd(self, 24, start_block, NULL, 0, true, true);
+ if (r < 0) {
+ return r;
+ }
+ r = _write(self, TOKEN_DATA, buf->buf, buf->len);
+ if (r < 0) {
+ return r;
+ }
+ } else {
+ // Use CMD25 to write multiple block
+ int r = block_cmd(self, 25, start_block, NULL, 0, true, true);
+ if (r < 0) {
+ return r;
+ }
+
+ uint8_t *ptr = buf->buf;
+ while (nblocks--) {
+ r = _write(self, TOKEN_CMD25, ptr, 512);
+ if (r < 0) {
+ return r;
+ }
+ ptr += 512;
+ }
+
+ cmd_nodata(self, TOKEN_STOP_TRAN, 0);
+ }
+ return 0;
+}
+
+int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
+ common_hal_sdcardio_check_for_deinit(self);
+ if (buf->len % 512 != 0) {
+ mp_raise_ValueError(translate("Buffer length must be a multiple of 512"));
+ }
+ lock_and_configure_bus(self);
+ int r = writeblocks(self, start_block, buf);
+ extraclock_and_unlock_bus(self);
+ return r;
+}
diff --git a/shared-module/sdcardio/SDCard.h b/shared-module/sdcardio/SDCard.h
new file mode 100644
index 000000000..76c906029
--- /dev/null
+++ b/shared-module/sdcardio/SDCard.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "py/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/objarray.h"
+
+#include "common-hal/busio/SPI.h"
+#include "common-hal/digitalio/DigitalInOut.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ busio_spi_obj_t *bus;
+ digitalio_digitalinout_obj_t cs;
+ int cdv;
+ int baudrate;
+ uint32_t sectors;
+} sdcardio_sdcard_obj_t;
+
+void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, mcu_pin_obj_t *cs, int baudrate);
+void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self);
+void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self);
+int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self);
+int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
+int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
diff --git a/shared-module/sdcardio/__init__.c b/shared-module/sdcardio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/sdcardio/__init__.c
diff --git a/shared-module/sdcardio/__init__.h b/shared-module/sdcardio/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/sdcardio/__init__.h
diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c
index c3d4b50c8..aa3bcc686 100644
--- a/shared-module/storage/__init__.c
+++ b/shared-module/storage/__init__.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Josef Gajdusek
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
diff --git a/shared-module/touchio/TouchIn.c b/shared-module/touchio/TouchIn.c
index 88d12b8b8..3fdf3e0ca 100644
--- a/shared-module/touchio/TouchIn.c
+++ b/shared-module/touchio/TouchIn.c
@@ -31,6 +31,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "shared-bindings/touchio/TouchIn.h"
+#include "shared-bindings/microcontroller/Pin.h"
// This is a capacitive touch sensing routine using a single digital
// pin. The pin should be connected to the sensing pad, and to ground
@@ -67,7 +68,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
}
void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self, const mcu_pin_obj_t *pin) {
- claim_pin(pin);
+ common_hal_mcu_pin_claim(pin);
self->digitalinout = m_new_obj(digitalio_digitalinout_obj_t);
self->digitalinout->base.type = &digitalio_digitalinout_type;
diff --git a/shared-module/vectorio/Polygon.c b/shared-module/vectorio/Polygon.c
index 0025d4bfc..c44c13fd7 100644
--- a/shared-module/vectorio/Polygon.c
+++ b/shared-module/vectorio/Polygon.c
@@ -20,7 +20,7 @@ static void _clobber_points_list(vectorio_polygon_t *self, mp_obj_t points_tuple
size_t len = 0;
mp_obj_t *items;
mp_obj_list_get(points_tuple_list, &len, &items);
- VECTORIO_POLYGON_DEBUG("polygon_points_list len: %d\n", len);
+ VECTORIO_POLYGON_DEBUG(" self.len: %d, len: %d, ", self->len, len);
if ( len < 3 ) {
mp_raise_TypeError_varg(translate("Polygon needs at least 3 points"));
@@ -28,9 +28,11 @@ static void _clobber_points_list(vectorio_polygon_t *self, mp_obj_t points_tuple
if ( self->len < 2*len ) {
if ( self->points_list != NULL ) {
+ VECTORIO_POLYGON_DEBUG("free(%d), ", sizeof(self->points_list));
gc_free( self->points_list );
}
self->points_list = gc_alloc( 2 * len * sizeof(int), false, false );
+ VECTORIO_POLYGON_DEBUG("alloc(%p, %d)", self->points_list, 2 * len * sizeof(int));
}
self->len = 2*len;
@@ -56,22 +58,35 @@ static void _clobber_points_list(vectorio_polygon_t *self, mp_obj_t points_tuple
void common_hal_vectorio_polygon_construct(vectorio_polygon_t *self, mp_obj_t points_list) {
- VECTORIO_POLYGON_DEBUG("%p polygon_construct\n", self);
+ VECTORIO_POLYGON_DEBUG("%p polygon_construct: ", self);
self->points_list = NULL;
self->len = 0;
self->on_dirty.obj = NULL;
_clobber_points_list( self, points_list );
+ VECTORIO_POLYGON_DEBUG("\n");
}
mp_obj_t common_hal_vectorio_polygon_get_points(vectorio_polygon_t *self) {
- return self->points_list;
+ VECTORIO_POLYGON_DEBUG("%p common_hal_vectorio_polygon_get_points {len: %d, points_list: %p}\n", self, self->len, self->points_list);
+ mp_obj_t list = mp_obj_new_list(self->len/2, NULL);
+
+ for (size_t i = 0; i < self->len; i += 2) {
+ mp_obj_t tuple[] = { mp_obj_new_int(self->points_list[i]), mp_obj_new_int(self->points_list[i+1]) };
+ mp_obj_list_append(
+ list,
+ mp_obj_new_tuple(2, tuple)
+ );
+ }
+ return list;
}
void common_hal_vectorio_polygon_set_points(vectorio_polygon_t *self, mp_obj_t points_list) {
+ VECTORIO_POLYGON_DEBUG("%p common_hal_vectorio_polygon_set_points: ", self);
_clobber_points_list( self, points_list );
if (self->on_dirty.obj != NULL) {
self->on_dirty.event(self->on_dirty.obj);
}
+ VECTORIO_POLYGON_DEBUG("\n");
}
void common_hal_vectorio_polygon_set_on_dirty(vectorio_polygon_t *self, vectorio_event_t notification) {
diff --git a/shared-module/vectorio/VectorShape.c b/shared-module/vectorio/VectorShape.c
index bfe8a7b25..81f46b3fa 100644
--- a/shared-module/vectorio/VectorShape.c
+++ b/shared-module/vectorio/VectorShape.c
@@ -223,8 +223,8 @@ bool vectorio_vector_shape_fill_area(vectorio_vector_shape_t *self, const _displ
pixel_to_get_x = (input_pixel.y - self->absolute_transform->dy * self->x - self->absolute_transform->y) / self->absolute_transform->dy;
pixel_to_get_y = (input_pixel.x - self->absolute_transform->dx * self->y - self->absolute_transform->x) / self->absolute_transform->dx;
} else {
- pixel_to_get_x = (input_pixel.x - self->absolute_transform->dx * self->x) / self->absolute_transform->dx;
- pixel_to_get_y = (input_pixel.y - self->absolute_transform->dy * self->y) / self->absolute_transform->dy;
+ pixel_to_get_x = (input_pixel.x - self->absolute_transform->dx * self->x - self->absolute_transform->x) / self->absolute_transform->dx;
+ pixel_to_get_y = (input_pixel.y - self->absolute_transform->dy * self->y - self->absolute_transform->y) / self->absolute_transform->dy;
}
VECTORIO_SHAPE_PIXEL_DEBUG(" get_pixel %p (%3d, %3d) -> ( %3d, %3d )", self->ishape.shape, input_pixel.x, input_pixel.y, pixel_to_get_x, pixel_to_get_y);
#ifdef VECTORIO_PERF
diff --git a/shared-module/wiznet/wiznet5k.c b/shared-module/wiznet/wiznet5k.c
index a603a5593..8ccb4ff8d 100644
--- a/shared-module/wiznet/wiznet5k.c
+++ b/shared-module/wiznet/wiznet5k.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/shared-module/wiznet/wiznet5k.h b/shared-module/wiznet/wiznet5k.h
index 19823ae55..4597a3016 100644
--- a/shared-module/wiznet/wiznet5k.h
+++ b/shared-module/wiznet/wiznet5k.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal