summaryrefslogtreecommitdiff
path: root/shared-module
diff options
context:
space:
mode:
Diffstat (limited to 'shared-module')
-rw-r--r--shared-module/_bleio/Characteristic.h13
-rw-r--r--shared-module/_bleio/ScanEntry.c14
-rw-r--r--shared-module/_eve/__init__.c4
-rw-r--r--shared-module/_pew/PewPew.c125
-rw-r--r--shared-module/_pew/__init__.c87
-rw-r--r--shared-module/_pixelbuf/PixelBuf.c48
-rw-r--r--shared-module/_stage/__init__.c2
-rw-r--r--shared-module/adafruit_bus_device/I2CDevice.c79
-rw-r--r--shared-module/adafruit_bus_device/I2CDevice.h39
-rw-r--r--shared-module/adafruit_bus_device/SPIDevice.c85
-rw-r--r--shared-module/adafruit_bus_device/SPIDevice.h44
-rw-r--r--shared-module/adafruit_bus_device/__init__.c0
-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__.c46
-rw-r--r--shared-module/canio/Match.c43
-rw-r--r--shared-module/canio/Match.h (renamed from shared-module/_pew/__init__.h)14
-rw-r--r--shared-module/canio/Message.c77
-rw-r--r--shared-module/canio/Message.h37
-rw-r--r--shared-module/canio/RemoteTransmissionRequest.c67
-rw-r--r--shared-module/canio/RemoteTransmissionRequest.h33
-rw-r--r--shared-module/displayio/Bitmap.c26
-rw-r--r--shared-module/displayio/ColorConverter.c33
-rw-r--r--shared-module/displayio/ColorConverter.h1
-rw-r--r--shared-module/displayio/Display.c62
-rw-r--r--shared-module/displayio/Display.h10
-rw-r--r--shared-module/displayio/EPaperDisplay.c64
-rw-r--r--shared-module/displayio/EPaperDisplay.h6
-rw-r--r--shared-module/displayio/FourWire.c7
-rw-r--r--shared-module/displayio/I2CDisplay.c8
-rw-r--r--shared-module/displayio/OnDiskBitmap.c5
-rw-r--r--shared-module/displayio/Palette.c5
-rw-r--r--shared-module/displayio/Palette.h1
-rw-r--r--shared-module/displayio/Shape.c78
-rw-r--r--shared-module/displayio/Shape.h5
-rw-r--r--shared-module/displayio/TileGrid.c14
-rw-r--r--shared-module/displayio/__init__.c47
-rw-r--r--shared-module/displayio/__init__.h10
-rw-r--r--shared-module/displayio/display_core.c43
-rw-r--r--shared-module/displayio/display_core.h8
-rw-r--r--shared-module/framebufferio/FramebufferDisplay.c119
-rw-r--r--shared-module/framebufferio/FramebufferDisplay.h49
-rw-r--r--shared-module/ipaddress/IPv4Address.c39
-rw-r--r--shared-module/ipaddress/IPv4Address.h (renamed from shared-module/_pew/PewPew.h)25
-rw-r--r--shared-module/ipaddress/__init__.c35
-rw-r--r--shared-module/ipaddress/__init__.h36
-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/random/__init__.c2
-rw-r--r--shared-module/rgbmatrix/RGBMatrix.c69
-rw-r--r--shared-module/rgbmatrix/RGBMatrix.h47
-rw-r--r--shared-module/rgbmatrix/allocator.h54
-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/sharpdisplay/SharpMemoryFramebuffer.c248
-rw-r--r--shared-module/sharpdisplay/SharpMemoryFramebuffer.h59
-rw-r--r--shared-module/sharpdisplay/__init__.c0
-rw-r--r--shared-module/sharpdisplay/__init__.h0
-rw-r--r--shared-module/storage/__init__.c5
-rw-r--r--shared-module/time/__init__.c2
-rw-r--r--shared-module/touchio/TouchIn.c3
-rw-r--r--shared-module/usb_hid/Device.c17
-rw-r--r--shared-module/usb_hid/Device.h2
-rw-r--r--shared-module/usb_midi/__init__.c8
-rw-r--r--shared-module/vectorio/Polygon.c29
-rw-r--r--shared-module/vectorio/VectorShape.c4
-rw-r--r--shared-module/wiznet/wiznet5k.c2
-rw-r--r--shared-module/wiznet/wiznet5k.h2
78 files changed, 2601 insertions, 487 deletions
diff --git a/shared-module/_bleio/Characteristic.h b/shared-module/_bleio/Characteristic.h
index 409a57c76..7776b1fa5 100644
--- a/shared-module/_bleio/Characteristic.h
+++ b/shared-module/_bleio/Characteristic.h
@@ -27,6 +27,9 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+// These are not the Bluetooth spec values. They are what is used by the Nordic SoftDevice.
+// The bit values are in different positions.
+
typedef enum {
CHAR_PROP_NONE = 0,
CHAR_PROP_BROADCAST = 1u << 0,
@@ -40,4 +43,14 @@ typedef enum {
} bleio_characteristic_properties_enum_t;
typedef uint8_t bleio_characteristic_properties_t;
+// Bluetooth spec property values
+#define BT_GATT_CHRC_BROADCAST 0x01
+#define BT_GATT_CHRC_READ 0x02
+#define BT_GATT_CHRC_WRITE_WITHOUT_RESP 0x04
+#define BT_GATT_CHRC_WRITE 0x08
+#define BT_GATT_CHRC_NOTIFY 0x10
+#define BT_GATT_CHRC_INDICATE 0x20
+#define BT_GATT_CHRC_AUTH 0x40
+#define BT_GATT_CHRC_EXT_PROP 0x80
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
diff --git a/shared-module/_bleio/ScanEntry.c b/shared-module/_bleio/ScanEntry.c
index 785209c4a..af9e4b347 100644
--- a/shared-module/_bleio/ScanEntry.c
+++ b/shared-module/_bleio/ScanEntry.c
@@ -56,11 +56,16 @@ bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t
if (prefixes_length == 0) {
return true;
}
+ if (len == 0) {
+ // Prefixes exist, but no data.
+ return false;
+ }
size_t i = 0;
while(i < prefixes_length) {
uint8_t prefix_length = prefixes[i];
i += 1;
size_t j = 0;
+ bool prefix_matched = false;
while (j < len) {
uint8_t structure_length = data[j];
j += 1;
@@ -71,13 +76,18 @@ bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t
if (any) {
return true;
}
- } else if (!any) {
- return false;
+ prefix_matched = true;
+ break;
}
j += structure_length;
}
+ // If all (!any), the current prefix must have matched at least one field.
+ if (!prefix_matched && !any) {
+ return false;
+ }
i += prefix_length;
}
+ // All prefixes matched some field (if !any), or none did (if any).
return !any;
}
diff --git a/shared-module/_eve/__init__.c b/shared-module/_eve/__init__.c
index 0f1e12d9f..d95c777dc 100644
--- a/shared-module/_eve/__init__.c
+++ b/shared-module/_eve/__init__.c
@@ -70,8 +70,8 @@ void common_hal__eve_Vertex2f(common_hal__eve_t *eve, mp_float_t x, mp_float_t y
void common_hal__eve_VertexFormat(common_hal__eve_t *eve, uint32_t frac)
{
- C4(eve, ((27 << 24) | ((frac & 7))));
- eve->vscale = 1 << eve->vscale;
+ C4(eve, ((39 << 24) | ((frac & 7))));
+ eve->vscale = 1 << frac;
}
diff --git a/shared-module/_pew/PewPew.c b/shared-module/_pew/PewPew.c
deleted file mode 100644
index 568dc6425..000000000
--- a/shared-module/_pew/PewPew.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Radomir Dopieralski
- *
- * 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 <stdbool.h>
-
-#include "py/mpstate.h"
-#include "py/runtime.h"
-#include "__init__.h"
-#include "PewPew.h"
-
-#include "shared-bindings/digitalio/Pull.h"
-#include "shared-bindings/digitalio/DigitalInOut.h"
-#include "shared-bindings/util.h"
-#include "samd/timers.h"
-#include "supervisor/shared/translate.h"
-#include "timer_handler.h"
-
-
-static uint8_t pewpew_tc_index = 0xff;
-
-
-void pewpew_interrupt_handler(uint8_t index) {
- if (index != pewpew_tc_index) {
- return;
- }
- Tc* tc = tc_insts[index];
- if (!tc->COUNT16.INTFLAG.bit.MC0) {
- return;
- }
-
- pew_tick();
-
- // Clear the interrupt bit.
- tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
-}
-
-void pew_init() {
- pew_obj_t* pew = MP_STATE_VM(pew_singleton);
-
- common_hal_digitalio_digitalinout_switch_to_input(pew->buttons, PULL_UP);
-
- for (size_t i = 0; i < pew->rows_size; ++i) {
- digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pew->rows[i]);
- common_hal_digitalio_digitalinout_switch_to_output(pin, false,
- DRIVE_MODE_PUSH_PULL);
- }
- for (size_t i = 0; i < pew->cols_size; ++i) {
- digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pew->cols[i]);
- common_hal_digitalio_digitalinout_switch_to_output(pin, true,
- DRIVE_MODE_OPEN_DRAIN);
- }
- if (pewpew_tc_index == 0xff) {
- // Find a spare timer.
- uint8_t index = find_free_timer();
- if (index == 0xff) {
- mp_raise_RuntimeError(translate("All timers in use"));
- }
- Tc *tc = tc_insts[index];
-
- pewpew_tc_index = index;
- set_timer_handler(true, index, TC_HANDLER_PEW);
-
- // We use GCLK0 for SAMD21 and GCLK1 for SAMD51 because they both run
- // at 48mhz making our math the same across the boards.
- #ifdef SAMD21
- turn_on_clocks(true, index, 0);
- #endif
- #ifdef SAMD51
- turn_on_clocks(true, index, 1);
- #endif
-
-
- #ifdef SAMD21
- tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
- TC_CTRLA_PRESCALER_DIV64 |
- TC_CTRLA_WAVEGEN_MFRQ;
- #endif
- #ifdef SAMD51
- tc_reset(tc);
- tc_set_enable(tc, false);
- tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16
- | TC_CTRLA_PRESCALER_DIV64;
- tc->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
- #endif
-
- tc_set_enable(tc, true);
- tc->COUNT16.CC[0].reg = 64;
-
- // Clear our interrupt in case it was set earlier
- tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
- tc->COUNT16.INTENSET.reg = TC_INTENSET_MC0;
- tc_enable_interrupts(pewpew_tc_index);
- }
-}
-
-void pew_reset(void) {
- if (pewpew_tc_index != 0xff) {
- tc_reset(tc_insts[pewpew_tc_index]);
- pewpew_tc_index = 0xff;
- }
- MP_STATE_VM(pew_singleton) = NULL;
-}
diff --git a/shared-module/_pew/__init__.c b/shared-module/_pew/__init__.c
deleted file mode 100644
index f3b23c606..000000000
--- a/shared-module/_pew/__init__.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Radomir Dopieralski
- *
- * 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 <stdbool.h>
-
-#include "py/mpstate.h"
-#include "__init__.h"
-#include "PewPew.h"
-
-#include "shared-bindings/digitalio/DigitalInOut.h"
-
-
-void pew_tick(void) {
- static uint8_t col = 0;
- static uint8_t turn = 0;
- static uint8_t pressed = 0;
- static uint8_t last_pressed = 0;
- digitalio_digitalinout_obj_t *pin;
-
- pew_obj_t* pew = MP_STATE_VM(pew_singleton);
- if (!pew) { return; }
-
- pin = MP_OBJ_TO_PTR(pew->cols[col]);
- ++col;
- if (col >= pew->cols_size) {
- pew->pressed |= last_pressed & pressed;
- last_pressed = pressed;
- pressed = 0;
- col = 0;
- ++turn;
- if (turn > 11) {
- turn = 0;
- }
- }
- if (!common_hal_digitalio_digitalinout_get_value(pew->buttons)) {
- pressed |= 1 << col;
- }
- common_hal_digitalio_digitalinout_set_value(pin, true);
- for (size_t x = 0; x < pew->rows_size; ++x) {
- pin = MP_OBJ_TO_PTR(pew->rows[x]);
- uint8_t color = pew->buffer[col * (pew->rows_size) + x];
- bool value = false;
- switch (color & 0x03) {
- case 3:
- value = true;
- break;
- case 2:
- if (turn == 2 || turn == 5 || turn == 8 || turn == 11) {
- value = true;
- }
- break;
- case 1:
- if (turn == 0) {
- value = true;
- }
- break;
- case 0:
- break;
- }
- common_hal_digitalio_digitalinout_set_value(pin, value);
- }
- pin = MP_OBJ_TO_PTR(pew->cols[col]);
- common_hal_digitalio_digitalinout_set_value(pin, false);
-}
diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c
index 9d671e454..f3e679631 100644
--- a/shared-module/_pixelbuf/PixelBuf.c
+++ b/shared-module/_pixelbuf/PixelBuf.c
@@ -132,6 +132,18 @@ void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t b
}
}
+uint8_t _pixelbuf_get_as_uint8(mp_obj_t obj) {
+ if (MP_OBJ_IS_SMALL_INT(obj)) {
+ return MP_OBJ_SMALL_INT_VALUE(obj);
+ } else if (MP_OBJ_IS_INT(obj)) {
+ return mp_obj_get_int_truncated(obj);
+ } else if (mp_obj_is_float(obj)) {
+ return (uint8_t)mp_obj_get_float(obj);
+ }
+ mp_raise_TypeError_varg(
+ translate("can't convert %q to %q"), mp_obj_get_type_qstr(obj), MP_QSTR_int);
+}
+
void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* w) {
pixelbuf_byteorder_details_t *byteorder = &self->byteorder;
// w is shared between white in NeoPixels and brightness in dotstars (so that DotStars can have
@@ -142,8 +154,8 @@ void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_
*w = 0;
}
- if (MP_OBJ_IS_INT(color)) {
- mp_int_t value = mp_obj_get_int_truncated(color);
+ if (MP_OBJ_IS_INT(color) || mp_obj_is_float(color)) {
+ mp_int_t value = MP_OBJ_IS_INT(color) ? mp_obj_get_int_truncated(color) : mp_obj_get_float(color);
*r = value >> 16 & 0xff;
*g = (value >> 8) & 0xff;
*b = value & 0xff;
@@ -155,9 +167,9 @@ void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_
mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len);
}
- *r = mp_obj_get_int_truncated(items[PIXEL_R]);
- *g = mp_obj_get_int_truncated(items[PIXEL_G]);
- *b = mp_obj_get_int_truncated(items[PIXEL_B]);
+ *r = _pixelbuf_get_as_uint8(items[PIXEL_R]);
+ *g = _pixelbuf_get_as_uint8(items[PIXEL_G]);
+ *b = _pixelbuf_get_as_uint8(items[PIXEL_B]);
if (len > 3) {
if (mp_obj_is_float(items[PIXEL_W])) {
*w = 255 * mp_obj_get_float(items[PIXEL_W]);
@@ -218,17 +230,35 @@ void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t v
_pixelbuf_set_pixel_color(self, index, r, g, b, w);
}
-void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values) {
+void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values,
+ mp_obj_tuple_t *flatten_to)
+{
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
- for (size_t i = 0; i < slice_len; i++) {
- _pixelbuf_set_pixel(self, start, values[i]);
- start+=step;
+ mp_obj_iter_buf_t iter_buf;
+ mp_obj_t iterable = mp_getiter(values, &iter_buf);
+ mp_obj_t item;
+ size_t i = 0;
+ bool flattened = flatten_to != mp_const_none;
+ if (flattened) flatten_to->len = self->bytes_per_pixel;
+ while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
+ if (flattened) {
+ flatten_to->items[i % self->bytes_per_pixel] = item;
+ if (++i % self->bytes_per_pixel == 0) {
+ _pixelbuf_set_pixel(self, start, flatten_to);
+ start+=step;
+ }
+ } else {
+ _pixelbuf_set_pixel(self, start, item);
+ start+=step;
+ }
}
if (self->auto_write) {
common_hal__pixelbuf_pixelbuf_show(self_in);
}
}
+
+
void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self_in, size_t index, mp_obj_t value) {
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
_pixelbuf_set_pixel(self, index, value);
diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c
index 0323c32cb..6dfc18880 100644
--- a/shared-module/_stage/__init__.c
+++ b/shared-module/_stage/__init__.c
@@ -45,7 +45,7 @@ void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
area.y2 = y1;
displayio_display_core_set_region_to_update(
&display->core, display->set_column_command, display->set_row_command,
- NO_COMMAND, NO_COMMAND, display->data_as_commands, false, &area);
+ NO_COMMAND, NO_COMMAND, display->data_as_commands, false, &area, display->SH1107_addressing);
while (!displayio_display_core_begin_transaction(&display->core)) {
RUN_BACKGROUND_TASKS;
diff --git a/shared-module/adafruit_bus_device/I2CDevice.c b/shared-module/adafruit_bus_device/I2CDevice.c
new file mode 100644
index 000000000..83abe80d6
--- /dev/null
+++ b/shared-module/adafruit_bus_device/I2CDevice.c
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Mark Komus
+ *
+ * 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/adafruit_bus_device/I2CDevice.h"
+#include "shared-bindings/busio/I2C.h"
+#include "py/mperrno.h"
+#include "py/nlr.h"
+#include "py/runtime.h"
+#include "lib/utils/interrupt_char.h"
+
+void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address) {
+ self->i2c = i2c;
+ self->device_address = device_address;
+}
+
+void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self) {
+ bool success = common_hal_busio_i2c_try_lock(self->i2c);
+
+ while (!success) {
+ RUN_BACKGROUND_TASKS;
+ if (mp_hal_is_interrupted()) {
+ break;
+ }
+
+ success = common_hal_busio_i2c_try_lock(self->i2c);
+ }
+}
+
+void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevice_obj_t *self) {
+ common_hal_busio_i2c_unlock(self->i2c);
+}
+
+uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) {
+ return common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length);
+}
+
+uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length, bool transmit_stop_bit) {
+ return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, transmit_stop_bit);
+}
+
+void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self) {
+ common_hal_adafruit_bus_device_i2cdevice_lock(self);
+
+ mp_buffer_info_t bufinfo;
+ mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1);
+
+ mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
+
+ uint8_t status = common_hal_adafruit_bus_device_i2cdevice_readinto(self, (uint8_t*)bufinfo.buf, 1);
+ if (status != 0) {
+ common_hal_adafruit_bus_device_i2cdevice_unlock(self);
+ mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address);
+ }
+
+ common_hal_adafruit_bus_device_i2cdevice_unlock(self);
+}
diff --git a/shared-module/adafruit_bus_device/I2CDevice.h b/shared-module/adafruit_bus_device/I2CDevice.h
new file mode 100644
index 000000000..d06adb9f5
--- /dev/null
+++ b/shared-module/adafruit_bus_device/I2CDevice.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H
+
+#include "py/obj.h"
+#include "common-hal/busio/I2C.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ busio_i2c_obj_t *i2c;
+ uint8_t device_address;
+} adafruit_bus_device_i2cdevice_obj_t;
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_I2CDEVICE_H
diff --git a/shared-module/adafruit_bus_device/SPIDevice.c b/shared-module/adafruit_bus_device/SPIDevice.c
new file mode 100644
index 000000000..e489fc7c0
--- /dev/null
+++ b/shared-module/adafruit_bus_device/SPIDevice.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Mark Komus
+ *
+ * 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/adafruit_bus_device/SPIDevice.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "py/mperrno.h"
+#include "py/nlr.h"
+#include "py/runtime.h"
+
+void common_hal_adafruit_bus_device_spidevice_construct(adafruit_bus_device_spidevice_obj_t *self, busio_spi_obj_t *spi, digitalio_digitalinout_obj_t *cs,
+ uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks) {
+ self->spi = spi;
+ self->baudrate = baudrate;
+ self->polarity = polarity;
+ self->phase = phase;
+ self->extra_clocks = extra_clocks;
+ self->chip_select = cs;
+}
+
+void common_hal_adafruit_bus_device_spidevice_enter(adafruit_bus_device_spidevice_obj_t *self) {
+ bool success = false;
+ while (!success) {
+ success = common_hal_busio_spi_try_lock(self->spi);
+ RUN_BACKGROUND_TASKS;
+ mp_handle_pending();
+ }
+
+ common_hal_busio_spi_configure(self->spi, self->baudrate, self->polarity, self->phase, 8);
+
+ if (self->chip_select != MP_OBJ_NULL) {
+ common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), false);
+ }
+}
+
+void common_hal_adafruit_bus_device_spidevice_exit(adafruit_bus_device_spidevice_obj_t *self) {
+ if (self->chip_select != MP_OBJ_NULL) {
+ common_hal_digitalio_digitalinout_set_value(MP_OBJ_TO_PTR(self->chip_select), true);
+ }
+
+ if (self->extra_clocks > 0) {
+
+ mp_buffer_info_t bufinfo;
+ mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1);
+
+ mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
+ ((uint8_t*)bufinfo.buf)[0] = 0xFF;
+
+ uint8_t clocks = self->extra_clocks / 8;
+ if ((self->extra_clocks % 8) != 0)
+ clocks += 1;
+
+ while (clocks > 0) {
+ if (!common_hal_busio_spi_write(self->spi, ((uint8_t*)bufinfo.buf), 1)) {
+ mp_raise_OSError(MP_EIO);
+ }
+ clocks--;
+ }
+ }
+
+ common_hal_busio_spi_unlock(self->spi);
+}
diff --git a/shared-module/adafruit_bus_device/SPIDevice.h b/shared-module/adafruit_bus_device/SPIDevice.h
new file mode 100644
index 000000000..1a7c70fa7
--- /dev/null
+++ b/shared-module/adafruit_bus_device/SPIDevice.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 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_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H
+
+#include "py/obj.h"
+#include "common-hal/busio/SPI.h"
+#include "common-hal/digitalio/DigitalInOut.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ busio_spi_obj_t *spi;
+ uint32_t baudrate;
+ uint8_t polarity;
+ uint8_t phase;
+ uint8_t extra_clocks;
+ digitalio_digitalinout_obj_t *chip_select;
+} adafruit_bus_device_spidevice_obj_t;
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_MODULE_BUSDEVICE_SPIDEVICE_H
diff --git a/shared-module/adafruit_bus_device/__init__.c b/shared-module/adafruit_bus_device/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/adafruit_bus_device/__init__.c
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..2f1c34e56 100644
--- a/shared-module/board/__init__.c
+++ b/shared-module/board/__init__.c
@@ -39,6 +39,11 @@
#include "shared-module/displayio/__init__.h"
#endif
+#if CIRCUITPY_SHARPDISPLAY
+#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h"
+#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
+#endif
+
#if BOARD_I2C
// Statically allocate the I2C object so it can live past the end of the heap and into the next VM.
// That way it can be used by built-in I2CDisplay displays and be accessible through board.I2C().
@@ -50,13 +55,12 @@ mp_obj_t common_hal_board_get_i2c(void) {
}
mp_obj_t common_hal_board_create_i2c(void) {
- if (i2c_singleton != NULL) {
- return i2c_singleton;
- }
+ // All callers have either already verified this or come so early that it can't be otherwise.
+ assert(i2c_singleton == NULL || common_hal_busio_i2c_deinited(i2c_singleton));
busio_i2c_obj_t *self = &i2c_obj;
self->base.type = &busio_i2c_type;
- common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 0);
+ common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 100000, 0);
i2c_singleton = (mp_obj_t)self;
return i2c_singleton;
}
@@ -74,9 +78,8 @@ mp_obj_t common_hal_board_get_spi(void) {
}
mp_obj_t common_hal_board_create_spi(void) {
- if (spi_singleton != NULL) {
- return spi_singleton;
- }
+ // All callers have either already verified this or come so early that it can't be otherwise.
+ assert(spi_singleton == NULL || common_hal_busio_spi_deinited(spi_singleton));
busio_spi_obj_t *self = &spi_obj;
self->base.type = &busio_spi_type;
@@ -123,7 +126,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);
}
@@ -134,28 +137,43 @@ void reset_board_busses(void) {
bool display_using_i2c = false;
#if CIRCUITPY_DISPLAYIO
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].i2cdisplay_bus.bus == i2c_singleton) {
+ if (displays[i].bus_base.type == &displayio_i2cdisplay_type && displays[i].i2cdisplay_bus.bus == i2c_singleton) {
display_using_i2c = true;
break;
}
}
#endif
- if (!display_using_i2c) {
- i2c_singleton = NULL;
+ if (i2c_singleton != NULL) {
+ if (!display_using_i2c) {
+ common_hal_busio_i2c_deinit(i2c_singleton);
+ i2c_singleton = NULL;
+ }
}
#endif
#if BOARD_SPI
bool display_using_spi = false;
#if CIRCUITPY_DISPLAYIO
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].fourwire_bus.bus == spi_singleton) {
+ mp_const_obj_t bus_type = displays[i].bus_base.type;
+ if (bus_type == &displayio_fourwire_type && displays[i].fourwire_bus.bus == spi_singleton) {
+ display_using_spi = true;
+ break;
+ }
+ #if CIRCUITPY_SHARPDISPLAY
+ if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type && displays[i].sharpdisplay.bus == spi_singleton) {
display_using_spi = true;
break;
}
+ #endif
}
#endif
- if (!display_using_spi) {
- spi_singleton = NULL;
+ // make sure SPI lock is not held over a soft reset
+ if (spi_singleton != NULL) {
+ common_hal_busio_spi_unlock(spi_singleton);
+ if (!display_using_spi) {
+ common_hal_busio_spi_deinit(spi_singleton);
+ spi_singleton = NULL;
+ }
}
#endif
#if BOARD_UART
diff --git a/shared-module/canio/Match.c b/shared-module/canio/Match.c
new file mode 100644
index 000000000..b4e8616e9
--- /dev/null
+++ b/shared-module/canio/Match.c
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython 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.
+ */
+
+#include "shared-module/canio/Match.h"
+
+void common_hal_canio_match_construct(canio_match_obj_t *self, int id, int mask, bool extended) {
+ self->id = id;
+ self->mask = mask;
+ self->extended = extended;
+}
+
+int common_hal_canio_match_get_id(const canio_match_obj_t *self) {
+ return self->id;
+}
+int common_hal_canio_match_get_mask(const canio_match_obj_t *self) {
+ return self->mask;
+}
+bool common_hal_canio_match_get_extended(const canio_match_obj_t *self) {
+ return self->extended;
+}
diff --git a/shared-module/_pew/__init__.h b/shared-module/canio/Match.h
index 4f953c610..b52191d7c 100644
--- a/shared-module/_pew/__init__.h
+++ b/shared-module/canio/Match.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Radomir Dopieralski
+ * 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
@@ -24,9 +24,13 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_PEW_H
-#define MICROPY_INCLUDED_PEW_H
+#pragma once
-void pew_tick(void);
+#include "py/obj.h"
-#endif // MICROPY_INCLUDED_PEW_H
+typedef struct {
+ mp_obj_base_t base;
+ int id;
+ int mask;
+ bool extended;
+} canio_match_obj_t;
diff --git a/shared-module/canio/Message.c b/shared-module/canio/Message.c
new file mode 100644
index 000000000..a1df4f693
--- /dev/null
+++ b/shared-module/canio/Message.c
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the MicroPython 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.
+ */
+
+#include "shared-module/canio/Message.h"
+
+#include <string.h>
+
+void common_hal_canio_message_construct(canio_message_obj_t *self, int id, void *data, size_t size, bool extended)
+{
+ self->id = id;
+ self->size = size;
+ self->extended = extended;
+ if (data) {
+ memcpy(self->data, data, size);
+ }
+}
+
+int common_hal_canio_message_get_id(const canio_message_obj_t *self)
+{
+ return self->id;
+}
+
+void common_hal_canio_message_set_id(canio_message_obj_t *self, int id)
+{
+ self->id = id;
+}
+
+
+const void *common_hal_canio_message_get_data(const canio_message_obj_t *self)
+{
+ return self->data;
+}
+
+const void common_hal_canio_message_set_data(canio_message_obj_t *self, const void *data, size_t size)
+{
+ self->size = size;
+ memcpy(self->data, data, size);
+}
+
+
+size_t common_hal_canio_message_get_length(const canio_message_obj_t *self)
+{
+ return self->size;
+}
+
+bool common_hal_canio_message_get_extended(const canio_message_obj_t *self)
+{
+ return self->extended;
+}
+
+void common_hal_canio_message_set_extended(canio_message_obj_t *self, bool extended)
+{
+ self->extended = extended;
+}
diff --git a/shared-module/canio/Message.h b/shared-module/canio/Message.h
new file mode 100644
index 000000000..1ca0d42e2
--- /dev/null
+++ b/shared-module/canio/Message.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython 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"
+
+typedef struct {
+ mp_obj_base_t base;
+ int id;
+ uint8_t data[8];
+ size_t size:4;
+ bool extended:1;
+} canio_message_obj_t;
diff --git a/shared-module/canio/RemoteTransmissionRequest.c b/shared-module/canio/RemoteTransmissionRequest.c
new file mode 100644
index 000000000..9b4d5632f
--- /dev/null
+++ b/shared-module/canio/RemoteTransmissionRequest.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the MicroPython 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.
+ */
+
+#include "shared-module/canio/RemoteTransmissionRequest.h"
+#include "shared-bindings/canio/RemoteTransmissionRequest.h"
+
+#include <string.h>
+
+void common_hal_canio_remote_transmission_request_construct(canio_remote_transmission_request_obj_t *self, int id, size_t size, bool extended)
+{
+ self->id = id;
+ self->size = size;
+ self->extended = extended;
+}
+
+int common_hal_canio_remote_transmission_request_get_id(const canio_remote_transmission_request_obj_t *self)
+{
+ return self->id;
+}
+
+void common_hal_canio_remote_transmission_request_set_id(canio_remote_transmission_request_obj_t *self, int id)
+{
+ self->id = id;
+}
+
+size_t common_hal_canio_remote_transmission_request_get_length(const canio_remote_transmission_request_obj_t *self)
+{
+ return self->size;
+}
+
+void common_hal_canio_remote_transmission_request_set_length(canio_remote_transmission_request_obj_t *self, size_t size)
+{
+ self->size = size;
+}
+
+bool common_hal_canio_remote_transmission_request_get_extended(const canio_remote_transmission_request_obj_t *self)
+{
+ return self->extended;
+}
+
+void common_hal_canio_remote_transmission_request_set_extended(canio_remote_transmission_request_obj_t *self, bool extended)
+{
+ self->extended = extended;
+}
diff --git a/shared-module/canio/RemoteTransmissionRequest.h b/shared-module/canio/RemoteTransmissionRequest.h
new file mode 100644
index 000000000..2f09b19c6
--- /dev/null
+++ b/shared-module/canio/RemoteTransmissionRequest.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython 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 "shared-bindings/canio/Message.h"
+
+typedef canio_message_obj_t canio_remote_transmission_request_obj_t;
diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c
index 8bcda6086..d1942efc7 100644
--- a/shared-module/displayio/Bitmap.c
+++ b/shared-module/displayio/Bitmap.c
@@ -105,6 +105,32 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
return 0;
}
+void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16_t y, displayio_bitmap_t *source,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t skip_index, bool skip_index_none) {
+ // Copy complete "source" bitmap into "self" bitmap at location x,y in the "self"
+ // Add a boolean to determine if all values are copied, or only if non-zero
+ // If skip_value is encountered in the source bitmap, it will not be copied.
+ // If skip_value is `None`, then all pixels are copied.
+
+ if (self->read_only) {
+ mp_raise_RuntimeError(translate("Read-only object"));
+ }
+
+ // simplest version - use internal functions for get/set pixels
+ for (int16_t i=0; i < (x2-x1) ; i++) {
+ if ( (x+i >= 0) && (x+i < self->width) ) {
+ for (int16_t j=0; j < (y2-y1) ; j++){
+ if ((y+j >= 0) && (y+j < self->height) ) {
+ uint32_t value = common_hal_displayio_bitmap_get_pixel(source, x1+i, y1+j);
+ if ( (skip_index_none) || (value != skip_index) ) { // write if skip_value_none is True
+ common_hal_displayio_bitmap_set_pixel(self, x+i, y+j, value);
+ }
+ }
+ }
+ }
+ }
+}
+
void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
if (self->read_only) {
mp_raise_RuntimeError(translate("Read-only object"));
diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c
index c2c3214aa..40dcd9d16 100644
--- a/shared-module/displayio/ColorConverter.c
+++ b/shared-module/displayio/ColorConverter.c
@@ -27,6 +27,9 @@
#include "shared-bindings/displayio/ColorConverter.h"
#include "py/misc.h"
+#include "py/runtime.h"
+
+#define NO_TRANSPARENT_COLOR (0x1000000)
uint32_t displayio_colorconverter_dither_noise_1 (uint32_t n)
{
@@ -41,6 +44,7 @@ uint32_t displayio_colorconverter_dither_noise_2(uint32_t x, uint32_t y) {
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t* self, bool dither) {
self->dither = dither;
+ self->transparent_color = NO_TRANSPARENT_COLOR;
}
uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888) {
@@ -54,7 +58,7 @@ uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888) {
uint32_t r8 = (color_rgb888 >> 16);
uint32_t g8 = (color_rgb888 >> 8) & 0xff;
uint32_t b8 = color_rgb888 & 0xff;
- return (r8 * 19) / 255 + (g8 * 182) / 255 + (b8 + 54) / 255;
+ return (r8 * 19 + g8 * 182 + b8 * 54) / 255;
}
uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888) {
@@ -128,9 +132,27 @@ bool common_hal_displayio_colorconverter_get_dither(displayio_colorconverter_t*
return self->dither;
}
+void common_hal_displayio_colorconverter_make_transparent(displayio_colorconverter_t* self, uint32_t transparent_color) {
+ if (self->transparent_color != NO_TRANSPARENT_COLOR) {
+ mp_raise_RuntimeError(translate("Only one color can be transparent at a time"));
+ }
+ self->transparent_color = transparent_color;
+}
+
+void common_hal_displayio_colorconverter_make_opaque(displayio_colorconverter_t* self, uint32_t transparent_color) {
+ (void) transparent_color;
+ // NO_TRANSPARENT_COLOR will never equal a valid color
+ self->transparent_color = NO_TRANSPARENT_COLOR;
+}
+
void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t* colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) {
uint32_t pixel = input_pixel->pixel;
+ if (self->transparent_color == pixel) {
+ output_color->opaque = false;
+ return;
+ }
+
if (self->dither){
uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y));
uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x+33,input_pixel->tile_y));
@@ -146,9 +168,9 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d
g8 = MIN(255,g8 + (randg&0x03));
} else {
int bitmask = 0xFF >> colorspace->depth;
- b8 = MIN(255,b8 + (randb&bitmask));
- r8 = MIN(255,r8 + (randr&bitmask));
- g8 = MIN(255,g8 + (randg&bitmask));
+ b8 = MIN(255,b8 + (randb & bitmask));
+ r8 = MIN(255,r8 + (randr & bitmask));
+ g8 = MIN(255,g8 + (randg & bitmask));
}
pixel = r8 << 16 | g8 << 8 | b8;
}
@@ -177,7 +199,8 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d
return;
} else if (colorspace->grayscale && colorspace->depth <= 8) {
uint8_t luma = displayio_colorconverter_compute_luma(pixel);
- output_color->pixel = luma >> (8 - colorspace->depth);
+ size_t bitmask = (1 << colorspace->depth) - 1;
+ output_color->pixel = (luma >> colorspace->grayscale_bit) & bitmask;
output_color->opaque = true;
return;
}
diff --git a/shared-module/displayio/ColorConverter.h b/shared-module/displayio/ColorConverter.h
index 10b1604a4..b402625ef 100644
--- a/shared-module/displayio/ColorConverter.h
+++ b/shared-module/displayio/ColorConverter.h
@@ -36,6 +36,7 @@
typedef struct {
mp_obj_base_t base;
bool dither;
+ uint32_t transparent_color;
} displayio_colorconverter_t;
bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self);
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index a3d877f1a..7c8c9280b 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -48,7 +48,9 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
uint8_t set_row_command, uint8_t write_ram_command, uint8_t set_vertical_scroll,
uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin,
uint16_t brightness_command, mp_float_t brightness, bool auto_brightness,
- bool single_byte_bounds, bool data_as_commands, bool auto_refresh, uint16_t native_frames_per_second, bool backlight_on_high) {
+ bool single_byte_bounds, bool data_as_commands, bool auto_refresh, uint16_t native_frames_per_second,
+ bool backlight_on_high, bool SH1107_addressing) {
+
// Turn off auto-refresh as we init.
self->auto_refresh = false;
uint16_t ram_width = 0x100;
@@ -68,6 +70,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
self->first_manual_refresh = !auto_refresh;
self->data_as_commands = data_as_commands;
self->backlight_on_high = backlight_on_high;
+ self->SH1107_addressing = SH1107_addressing;
self->native_frames_per_second = native_frames_per_second;
self->native_ms_per_frame = 1000 / native_frames_per_second;
@@ -104,21 +107,19 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
i += 2 + data_size;
}
- supervisor_start_terminal(width, height);
-
// Always set the backlight type in case we're reusing memory.
self->backlight_inout.base.type = &mp_type_NoneType;
if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) {
// Avoid PWM types and functions when the module isn't enabled
#if (CIRCUITPY_PULSEIO)
- pwmout_result_t result = common_hal_pulseio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 50000, false);
+ pwmout_result_t result = common_hal_pwmio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 50000, false);
if (result != PWMOUT_OK) {
self->backlight_inout.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin);
common_hal_never_reset_pin(backlight_pin);
} else {
- self->backlight_pwm.base.type = &pulseio_pwmout_type;
- common_hal_pulseio_pwmout_never_reset(&self->backlight_pwm);
+ self->backlight_pwm.base.type = &pwmio_pwmout_type;
+ common_hal_pwmio_pwmout_never_reset(&self->backlight_pwm);
}
#else
// Otherwise default to digital
@@ -137,7 +138,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) {
@@ -173,14 +174,14 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self,
// Avoid PWM types and functions when the module isn't enabled
#if (CIRCUITPY_PULSEIO)
- bool ispwm = (self->backlight_pwm.base.type == &pulseio_pwmout_type) ? true : false;
+ bool ispwm = (self->backlight_pwm.base.type == &pwmio_pwmout_type) ? true : false;
#else
bool ispwm = false;
#endif
if (ispwm) {
#if (CIRCUITPY_PULSEIO)
- common_hal_pulseio_pwmout_set_duty_cycle(&self->backlight_pwm, (uint16_t) (0xffff * brightness));
+ common_hal_pwmio_pwmout_set_duty_cycle(&self->backlight_pwm, (uint16_t) (0xffff * brightness));
ok = true;
#else
ok = false;
@@ -240,11 +241,17 @@ STATIC bool _refresh_area(displayio_display_obj_t* self, const displayio_area_t*
if (!displayio_display_core_clip_area(&self->core, area, &clipped)) {
return true;
}
- uint16_t subrectangles = 1;
uint16_t rows_per_buffer = displayio_area_height(&clipped);
uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth;
uint16_t pixels_per_buffer = displayio_area_size(&clipped);
- if (displayio_area_size(&clipped) > buffer_size * pixels_per_word) {
+
+ uint16_t subrectangles = 1;
+ // for SH1107 and other boundary constrained controllers
+ // write one single row at a time
+ if (self->SH1107_addressing) {
+ subrectangles = rows_per_buffer; // vertical (column mode) write each separately (height times)
+ rows_per_buffer = 1;
+ } else if (displayio_area_size(&clipped) > buffer_size * pixels_per_word) {
rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width(&clipped);
if (rows_per_buffer == 0) {
rows_per_buffer = 1;
@@ -286,7 +293,9 @@ STATIC bool _refresh_area(displayio_display_obj_t* self, const displayio_area_t*
}
remaining_rows -= rows_per_buffer;
- displayio_display_core_set_region_to_update(&self->core, self->set_column_command, self->set_row_command, NO_COMMAND, NO_COMMAND, self->data_as_commands, false, &subrectangle);
+ displayio_display_core_set_region_to_update(&self->core, self->set_column_command,
+ self->set_row_command, NO_COMMAND, NO_COMMAND, self->data_as_commands, false,
+ &subrectangle, self->SH1107_addressing);
uint16_t subrectangle_size_bytes;
if (self->core.colorspace.depth >= 8) {
@@ -317,11 +326,10 @@ STATIC bool _refresh_area(displayio_display_obj_t* self, const displayio_area_t*
}
STATIC void _refresh_display(displayio_display_obj_t* self) {
- if (!displayio_display_core_bus_free(&self->core)) {
- // Can't acquire display bus; skip updating this display. Try next display.
+ if (!displayio_display_core_start_refresh(&self->core)) {
+ // A refresh on this bus is already in progress. Try next display.
return;
}
- displayio_display_core_start_refresh(&self->core);
const displayio_area_t* current_area = _get_refresh_areas(self);
while (current_area != NULL) {
_refresh_area(self, current_area);
@@ -339,8 +347,10 @@ void common_hal_displayio_display_set_rotation(displayio_display_obj_t* self, in
self->core.height = tmp;
}
displayio_display_core_set_rotation(&self->core, rotation);
- supervisor_stop_terminal();
- supervisor_start_terminal(self->core.width, self->core.height);
+ if (self == &displays[0].display) {
+ supervisor_stop_terminal();
+ supervisor_start_terminal(self->core.width, self->core.height);
+ }
if (self->core.current_group != NULL) {
displayio_group_update_transform(self->core.current_group, &self->core.transform);
}
@@ -352,7 +362,7 @@ uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self
bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) {
- if (!self->auto_refresh && !self->first_manual_refresh) {
+ if (!self->auto_refresh && !self->first_manual_refresh && (target_ms_per_frame != 0xffffffff) ) {
uint64_t current_time = supervisor_ticks_ms64();
uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh;
// Test to see if the real frame time is below our minimum.
@@ -383,6 +393,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,11 +426,12 @@ 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) {
- common_hal_pulseio_pwmout_reset_ok(&self->backlight_pwm);
- common_hal_pulseio_pwmout_deinit(&self->backlight_pwm);
+ if (self->backlight_pwm.base.type == &pwmio_pwmout_type) {
+ common_hal_pwmio_pwmout_reset_ok(&self->backlight_pwm);
+ common_hal_pwmio_pwmout_deinit(&self->backlight_pwm);
} else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
common_hal_digitalio_digitalinout_deinit(&self->backlight_inout);
}
@@ -423,7 +441,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..cc9cd54c4 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"
-#include "shared-bindings/pulseio/PWMOut.h"
+#if CIRCUITPY_PWMIO
+#include "shared-bindings/pwmio/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;
- pulseio_pwmout_obj_t backlight_pwm;
+ #if CIRCUITPY_PWMIO
+ pwmio_pwmout_obj_t backlight_pwm;
+ #endif
};
uint64_t last_backlight_refresh;
uint64_t last_refresh_call;
@@ -56,6 +60,8 @@ typedef struct {
bool auto_brightness;
bool updating_backlight;
bool backlight_on_high;
+ // new quirk for sh1107
+ bool SH1107_addressing;
} displayio_display_obj_t;
void displayio_display_background(displayio_display_obj_t* self);
diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c
index 6a55687b9..3fb37ff21 100644
--- a/shared-module/displayio/EPaperDisplay.c
+++ b/shared-module/displayio/EPaperDisplay.c
@@ -43,13 +43,14 @@
#include <string.h>
void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self,
- mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len,
+ mp_obj_t bus, const uint8_t* start_sequence, uint16_t start_sequence_len,
+ const uint8_t* stop_sequence, uint16_t stop_sequence_len,
uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height,
int16_t colstart, int16_t rowstart, uint16_t rotation,
uint16_t set_column_window_command, uint16_t set_row_window_command,
uint16_t set_current_column_command, uint16_t set_current_row_command,
uint16_t write_black_ram_command, bool black_bits_inverted, uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint16_t refresh_display_command, mp_float_t refresh_time,
- const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select) {
+ const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select, bool grayscale) {
if (highlight_color != 0x000000) {
self->core.colorspace.tricolor = true;
self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(highlight_color);
@@ -72,6 +73,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t*
self->refreshing = false;
self->milliseconds_per_frame = seconds_per_frame * 1000;
self->chip_select = chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED;
+ self->grayscale = grayscale;
self->start_sequence = start_sequence;
self->start_sequence_len = start_sequence_len;
@@ -90,8 +92,6 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t*
// TODO: Clear
}
- supervisor_start_terminal(width, height);
-
// Set the group after initialization otherwise we may send pixels while we delay in
// initialization.
common_hal_displayio_epaperdisplay_show(self, &circuitpython_splash);
@@ -134,14 +134,15 @@ STATIC void wait_for_busy(displayio_epaperdisplay_obj_t* self) {
}
}
-STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self, bool should_wait_for_busy, uint8_t* sequence, uint32_t sequence_len) {
+STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self,
+ bool should_wait_for_busy, const uint8_t* sequence, uint32_t sequence_len) {
uint32_t i = 0;
while (i < sequence_len) {
- uint8_t *cmd = sequence + i;
+ const uint8_t *cmd = sequence + i;
uint8_t data_size = *(cmd + 1);
bool delay = (data_size & DELAY) != 0;
data_size &= ~DELAY;
- uint8_t *data = cmd + 2;
+ const uint8_t *data = cmd + 2;
displayio_display_core_begin_transaction(&self->core);
self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1);
self->core.send(self->core.bus, DISPLAY_DATA, self->chip_select, data, data_size);
@@ -187,6 +188,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);
@@ -196,6 +198,29 @@ mp_obj_t common_hal_displayio_epaperdisplay_get_bus(displayio_epaperdisplay_obj_
return self->core.bus;
}
+void common_hal_displayio_epaperdisplay_set_rotation(displayio_epaperdisplay_obj_t* self, int rotation){
+ bool transposed = (self->core.rotation == 90 || self->core.rotation == 270);
+ bool will_transposed = (rotation == 90 || rotation == 270);
+ if(transposed != will_transposed) {
+ int tmp = self->core.width;
+ self->core.width = self->core.height;
+ self->core.height = tmp;
+ }
+ displayio_display_core_set_rotation(&self->core, rotation);
+ if (self == &displays[0].epaper_display) {
+ supervisor_stop_terminal();
+ supervisor_start_terminal(self->core.width, self->core.height);
+ }
+ if (self->core.current_group != NULL) {
+ displayio_group_update_transform(self->core.current_group, &self->core.transform);
+ }
+}
+
+uint16_t common_hal_displayio_epaperdisplay_get_rotation(displayio_epaperdisplay_obj_t* self){
+ return self->core.rotation;
+}
+
+
bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, const displayio_area_t* area) {
uint16_t buffer_size = 128; // In uint32_ts
@@ -231,14 +256,16 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c
uint32_t mask[mask_length];
uint8_t passes = 1;
- if (self->core.colorspace.tricolor) {
+ if (self->core.colorspace.tricolor || self->grayscale) {
passes = 2;
}
for (uint8_t pass = 0; pass < passes; pass++) {
uint16_t remaining_rows = displayio_area_height(&clipped);
if (self->set_row_window_command != NO_COMMAND) {
- displayio_display_core_set_region_to_update(&self->core, self->set_column_window_command, self->set_row_window_command, self->set_current_column_command, self->set_current_row_command, false, self->chip_select, &clipped);
+ displayio_display_core_set_region_to_update(&self->core, self->set_column_window_command,
+ self->set_row_window_command, self->set_current_column_command, self->set_current_row_command,
+ false, self->chip_select, &clipped, false /* SH1107_addressing */);
}
uint8_t write_command = self->write_black_ram_command;
@@ -268,8 +295,13 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c
memset(buffer, 0, buffer_size * sizeof(buffer[0]));
self->core.colorspace.grayscale = true;
+ self->core.colorspace.grayscale_bit = 7;
if (pass == 1) {
- self->core.colorspace.grayscale = false;
+ if (self->grayscale) { // 4-color grayscale
+ self->core.colorspace.grayscale_bit = 6;
+ } else { // Tri-color
+ self->core.colorspace.grayscale = false;
+ }
}
displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer);
@@ -301,6 +333,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 +375,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);
@@ -349,9 +383,15 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) {
}
}
+bool common_hal_displayio_epaperdisplay_get_busy(displayio_epaperdisplay_obj_t* self) {
+ displayio_epaperdisplay_background(self);
+ return self->refreshing;
+}
+
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);
@@ -365,8 +405,8 @@ void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) {
void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self) {
displayio_display_core_collect_ptrs(&self->core);
- gc_collect_ptr(self->start_sequence);
- gc_collect_ptr(self->stop_sequence);
+ gc_collect_ptr((void *) self->start_sequence);
+ gc_collect_ptr((void *) self->stop_sequence);
}
bool maybe_refresh_epaperdisplay(void) {
diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h
index d08bed546..d0668ff44 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"
@@ -39,9 +38,9 @@ typedef struct {
displayio_display_core_t core;
digitalio_digitalinout_obj_t busy;
uint32_t milliseconds_per_frame;
- uint8_t* start_sequence;
+ const uint8_t* start_sequence;
uint32_t start_sequence_len;
- uint8_t* stop_sequence;
+ const uint8_t* stop_sequence;
uint32_t stop_sequence_len;
uint16_t refresh_time;
uint16_t set_column_window_command;
@@ -56,6 +55,7 @@ typedef struct {
bool black_bits_inverted;
bool color_bits_inverted;
bool refreshing;
+ bool grayscale;
display_chip_select_behavior_t chip_select;
} displayio_epaperdisplay_obj_t;
diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c
index 17e8cfa1d..e993f2480 100644
--- a/shared-module/displayio/FourWire.c
+++ b/shared-module/displayio/FourWire.c
@@ -85,9 +85,9 @@ bool common_hal_displayio_fourwire_reset(mp_obj_t obj) {
return false;
}
common_hal_digitalio_digitalinout_set_value(&self->reset, false);
- common_hal_time_delay_ms(1);
+ common_hal_mcu_delay_us(1000);
common_hal_digitalio_digitalinout_set_value(&self->reset, true);
- common_hal_time_delay_ms(1);
+ common_hal_mcu_delay_us(1000);
return true;
}
@@ -111,7 +111,8 @@ bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) {
return true;
}
-void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
+void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type,
+ display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->command, data_type == DISPLAY_DATA);
if (chip_select == CHIP_SELECT_TOGGLE_EVERY_BYTE) {
diff --git a/shared-module/displayio/I2CDisplay.c b/shared-module/displayio/I2CDisplay.c
index 0c8f2e69a..cc811e83d 100644
--- a/shared-module/displayio/I2CDisplay.c
+++ b/shared-module/displayio/I2CDisplay.c
@@ -53,6 +53,7 @@ void common_hal_displayio_i2cdisplay_construct(displayio_i2cdisplay_obj_t* self,
// Probe the bus to see if a device acknowledges the given address.
if (!common_hal_busio_i2c_probe(i2c, device_address)) {
+ self->base.type = &mp_type_NoneType;
mp_raise_ValueError_varg(translate("Unable to find I2C Display at %x"), device_address);
}
@@ -71,7 +72,9 @@ void common_hal_displayio_i2cdisplay_deinit(displayio_i2cdisplay_obj_t* self) {
common_hal_busio_i2c_deinit(self->bus);
}
- common_hal_reset_pin(self->reset.pin);
+ if (self->reset.base.type == &digitalio_digitalinout_type) {
+ common_hal_digitalio_digitalinout_deinit(&self->reset);
+ }
}
bool common_hal_displayio_i2cdisplay_reset(mp_obj_t obj) {
@@ -100,7 +103,8 @@ bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t obj) {
return common_hal_busio_i2c_try_lock(self->bus);
}
-void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
+void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type,
+ display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
if (data_type == DISPLAY_COMMAND) {
uint8_t command_bytes[2 * data_length];
diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c
index 993fc03de..c1a0ddeb7 100644
--- a/shared-module/displayio/OnDiskBitmap.c
+++ b/shared-module/displayio/OnDiskBitmap.c
@@ -57,7 +57,7 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
uint32_t compression = read_word(bmp_header, 15);
uint32_t number_of_colors = read_word(bmp_header, 23);
- bool indexed = ((bits_per_pixel <= 8) && (number_of_colors != 0));
+ bool indexed = bits_per_pixel <= 8;
self->bitfield_compressed = (compression == 3);
self->bits_per_pixel = bits_per_pixel;
self->width = read_word(bmp_header, 9);
@@ -75,6 +75,9 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
self->b_bitmask = 0x1f;
}
} else if (indexed && self->bits_per_pixel != 1) {
+ if (number_of_colors == 0) {
+ number_of_colors = 1 << bits_per_pixel;
+ }
uint16_t palette_size = number_of_colors * sizeof(uint32_t);
uint16_t palette_offset = 0xe + header_size;
diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c
index 1ef03aab4..ba5ff665c 100644
--- a/shared-module/displayio/Palette.c
+++ b/shared-module/displayio/Palette.c
@@ -35,10 +35,12 @@ void common_hal_displayio_palette_construct(displayio_palette_t* self, uint16_t
void common_hal_displayio_palette_make_opaque(displayio_palette_t* self, uint32_t palette_index) {
self->colors[palette_index].transparent = false;
+ self->needs_refresh = true;
}
void common_hal_displayio_palette_make_transparent(displayio_palette_t* self, uint32_t palette_index) {
self->colors[palette_index].transparent = true;
+ self->needs_refresh = true;
}
uint32_t common_hal_displayio_palette_get_len(displayio_palette_t* self) {
@@ -81,7 +83,8 @@ bool displayio_palette_get_color(displayio_palette_t *self, const _displayio_col
uint8_t pixel_hue = self->colors[palette_index].hue;
displayio_colorconverter_compute_tricolor(colorspace, pixel_hue, luma, color);
} else if (colorspace->grayscale) {
- *color = self->colors[palette_index].luma >> (8 - colorspace->depth);
+ size_t bitmask = (1 << colorspace->depth) - 1;
+ *color = (self->colors[palette_index].luma >> colorspace->grayscale_bit) & bitmask;
} else {
uint16_t packed = self->colors[palette_index].rgb565;
if (colorspace->reverse_bytes_in_word) {
diff --git a/shared-module/displayio/Palette.h b/shared-module/displayio/Palette.h
index da72f250f..993912cc5 100644
--- a/shared-module/displayio/Palette.h
+++ b/shared-module/displayio/Palette.h
@@ -37,6 +37,7 @@ typedef struct {
uint8_t bytes_per_cell;
uint8_t tricolor_hue;
uint8_t tricolor_luma;
+ uint8_t grayscale_bit; // The lowest grayscale bit. Normally 8 - depth.
bool grayscale;
bool tricolor;
bool pixels_in_byte_share_row;
diff --git a/shared-module/displayio/Shape.c b/shared-module/displayio/Shape.c
index ab9ca735b..b94a392bc 100644
--- a/shared-module/displayio/Shape.c
+++ b/shared-module/displayio/Shape.c
@@ -29,6 +29,7 @@
#include <string.h>
#include "py/runtime.h"
+#include "py/misc.h"
void common_hal_displayio_shape_construct(displayio_shape_t *self, uint32_t width,
uint32_t height, bool mirror_x, bool mirror_y) {
@@ -37,37 +38,77 @@ void common_hal_displayio_shape_construct(displayio_shape_t *self, uint32_t widt
self->width = width;
if (self->mirror_x) {
width /= 2;
- width += self->width % 2 - 1;
+ width += self->width % 2;
}
self->half_width = width;
self->height = height;
if (self->mirror_y) {
height /= 2;
- height += self->height % 2 - 1;
+ height += self->height % 2;
}
self->half_height = height;
self->data = m_malloc(height * sizeof(uint32_t), false);
- for (uint16_t i = 0; i <= height; i++) {
+
+ for (uint16_t i = 0; i < height; i++) {
self->data[2 * i] = 0;
self->data[2 * i + 1] = width;
}
+
+ self->dirty_area.x1=0;
+ self->dirty_area.x2=width;
+ self->dirty_area.y1=0;
+ self->dirty_area.y2=height;
}
void common_hal_displayio_shape_set_boundary(displayio_shape_t *self, uint16_t y, uint16_t start_x, uint16_t end_x) {
- if (y < 0 || y >= self->height || (self->mirror_y && y > self->half_height)) {
+ if (y < 0 || y >= self->height || (self->mirror_y && y >= self->half_height)) {
mp_raise_ValueError(translate("y value out of bounds"));
}
- if (start_x < 0 || start_x > self->width || end_x < 0 || end_x > self->width) {
+ if (start_x < 0 || start_x >= self->width || end_x < 0 || end_x >= self->width) {
mp_raise_ValueError(translate("x value out of bounds"));
}
- uint16_t half_width = self->width / 2 - 1 + self->width % 2;
- if (self->mirror_x && (start_x > half_width || end_x > half_width)) {
- mp_raise_ValueError_varg(translate("Maximum x value when mirrored is %d"), half_width);
+ if (self->mirror_x && (start_x >= self->half_width || end_x >= self->half_width)) {
+ mp_raise_ValueError_varg(translate("Maximum x value when mirrored is %d"), self->half_width);
+ }
+
+ uint16_t lower_x, upper_x, lower_y, upper_y;
+
+ // find x-boundaries for updating based on current data and start_x, end_x, and mirror_x
+ lower_x = MIN(start_x, self->data[2 * y]);
+
+ if (self->mirror_x) {
+ upper_x = self->width - lower_x + 1; // dirty rectangles are treated with max value exclusive
+ } else {
+ upper_x = MAX(end_x, self->data[2 * y + 1]) + 1; // dirty rectangles are treated with max value exclusive
+ }
+
+ // find y-boundaries based on y and mirror_y
+ lower_y = y;
+
+ if (self->mirror_y) {
+ upper_y = self->height - lower_y + 1; // dirty rectangles are treated with max value exclusive
+ } else {
+ upper_y = y + 1; // dirty rectangles are treated with max value exclusive
}
- self->data[2 * y] = start_x;
+
+ self->data[2 * y] = start_x; // update the data array with the new boundaries
self->data[2 * y + 1] = end_x;
+
+ if (self->dirty_area.x1 == self->dirty_area.x2) { // Dirty region is empty
+ self->dirty_area.x1 = lower_x;
+ self->dirty_area.x2 = upper_x;
+ self->dirty_area.y1 = lower_y;
+ self->dirty_area.y2 = upper_y;
+
+ } else { // Dirty region is not empty
+ self->dirty_area.x1 = MIN(lower_x, self->dirty_area.x1);
+ self->dirty_area.x2 = MAX(upper_x, self->dirty_area.x2);
+
+ self->dirty_area.y1 = MIN(lower_y, self->dirty_area.y1);
+ self->dirty_area.y2 = MAX(upper_y, self->dirty_area.y2);
+ }
}
uint32_t common_hal_displayio_shape_get_pixel(void *obj, int16_t x, int16_t y) {
@@ -75,10 +116,10 @@ uint32_t common_hal_displayio_shape_get_pixel(void *obj, int16_t x, int16_t y) {
if (x >= self->width || x < 0 || y >= self->height || y < 0) {
return 0;
}
- if (self->mirror_x && x > self->half_width) {
- x = self->width - 1 - x;
+ if (self->mirror_x && x >= self->half_width) {
+ x = self->width - x - 1;
}
- if (self->mirror_y && y > self->half_height) {
+ if (self->mirror_y && y >= self->half_height) {
y = self->height - y - 1;
}
uint16_t start_x = self->data[2 * y];
@@ -88,3 +129,16 @@ uint32_t common_hal_displayio_shape_get_pixel(void *obj, int16_t x, int16_t y) {
}
return 1;
}
+
+displayio_area_t* displayio_shape_get_refresh_areas(displayio_shape_t *self, displayio_area_t* tail) {
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ return tail;
+ }
+ self->dirty_area.next = tail;
+ return &self->dirty_area;
+}
+
+void displayio_shape_finish_refresh(displayio_shape_t *self) {
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = 0;
+}
diff --git a/shared-module/displayio/Shape.h b/shared-module/displayio/Shape.h
index ca054fe00..e59ad586e 100644
--- a/shared-module/displayio/Shape.h
+++ b/shared-module/displayio/Shape.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include "py/obj.h"
+#include "shared-module/displayio/area.h"
typedef struct {
mp_obj_base_t base;
@@ -41,6 +42,10 @@ typedef struct {
uint16_t* data;
bool mirror_x;
bool mirror_y;
+ displayio_area_t dirty_area;
} displayio_shape_t;
+void displayio_shape_finish_refresh(displayio_shape_t *self);
+displayio_area_t* displayio_shape_get_refresh_areas(displayio_shape_t *self, displayio_area_t* tail);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SHAPE_H
diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c
index 2766cbecd..19ea10e55 100644
--- a/shared-module/displayio/TileGrid.c
+++ b/shared-module/displayio/TileGrid.c
@@ -83,10 +83,16 @@ bool common_hal_displayio_tilegrid_get_hidden(displayio_tilegrid_t* self) {
void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t* self, bool hidden) {
self->hidden = hidden;
+ if(!hidden){
+ self->full_change = true;
+ }
}
void displayio_tilegrid_set_hidden_by_parent(displayio_tilegrid_t *self, bool hidden) {
self->hidden_by_parent = hidden;
+ if(!hidden){
+ self->full_change = true;
+ }
}
bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_area_t* area) {
@@ -499,7 +505,7 @@ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
displayio_bitmap_finish_refresh(self->bitmap);
} else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
- // TODO: Support shape changes.
+ displayio_shape_finish_refresh(self->bitmap);
} else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
// OnDiskBitmap changes will trigger a complete reload so no need to
// track changes.
@@ -543,6 +549,12 @@ displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *sel
self->full_change = true;
}
}
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
+ displayio_area_t* refresh_area = displayio_shape_get_refresh_areas(self->bitmap, tail);
+ if (refresh_area != tail) {
+ displayio_area_copy(refresh_area, &self->dirty_area);
+ self->partial_change = true;
+ }
}
self->full_change = self->full_change ||
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index c898bbb98..a9bb3b21b 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -19,14 +19,19 @@
#include "supervisor/spi_flash_api.h"
#include "py/mpconfig.h"
+#if CIRCUITPY_SHARPDISPLAY
+#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h"
+#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
+#endif
+
primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
#if CIRCUITPY_RGBMATRIX
-STATIC bool any_display_uses_this_rgbmatrix(rgbmatrix_rgbmatrix_obj_t* pm) {
+STATIC bool any_display_uses_this_framebuffer(mp_obj_base_t *obj) {
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].framebuffer_display.base.type == &framebufferio_framebufferdisplay_type) {
+ if (displays[i].display_base.type == &framebufferio_framebufferdisplay_type) {
framebufferio_framebufferdisplay_obj_t* display = &displays[i].framebuffer_display;
- if (display->framebuffer == pm) {
+ if (display->framebuffer == obj) {
return true;
}
}
@@ -35,8 +40,6 @@ STATIC bool any_display_uses_this_rgbmatrix(rgbmatrix_rgbmatrix_obj_t* pm) {
}
#endif
-// Check for recursive calls to displayio_background.
-bool displayio_background_in_progress = false;
void displayio_background(void) {
if (mp_hal_is_interrupted()) {
@@ -47,12 +50,6 @@ void displayio_background(void) {
return;
}
- if (displayio_background_in_progress) {
- // Don't allow recursive calls to this routine.
- return;
- }
-
- displayio_background_in_progress = true;
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) {
@@ -70,8 +67,6 @@ void displayio_background(void) {
}
}
- // All done.
- displayio_background_in_progress = false;
}
void common_hal_displayio_release_displays(void) {
@@ -102,10 +97,14 @@ void common_hal_displayio_release_displays(void) {
common_hal_displayio_i2cdisplay_deinit(&displays[i].i2cdisplay_bus);
} else if (bus_type == &displayio_parallelbus_type) {
common_hal_displayio_parallelbus_deinit(&displays[i].parallel_bus);
-#if CIRCUITPY_FRAMEBUFFERIO
+#if CIRCUITPY_RGBMATRIX
} else if (bus_type == &rgbmatrix_RGBMatrix_type) {
common_hal_rgbmatrix_rgbmatrix_deinit(&displays[i].rgbmatrix);
#endif
+#if CIRCUITPY_SHARPDISPLAY
+ } else if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) {
+ common_hal_sharpdisplay_framebuffer_deinit(&displays[i].sharpdisplay);
+#endif
}
displays[i].fourwire_bus.base.type = &mp_type_NoneType;
}
@@ -170,10 +169,15 @@ void reset_displays(void) {
#if CIRCUITPY_RGBMATRIX
} else if (displays[i].rgbmatrix.base.type == &rgbmatrix_RGBMatrix_type) {
rgbmatrix_rgbmatrix_obj_t * pm = &displays[i].rgbmatrix;
- if(!any_display_uses_this_rgbmatrix(pm)) {
+ if(!any_display_uses_this_framebuffer(&pm->base)) {
common_hal_rgbmatrix_rgbmatrix_deinit(pm);
}
#endif
+#if CIRCUITPY_SHARPDISPLAY
+ } else if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) {
+ sharpdisplay_framebuffer_obj_t * sharp = &displays[i].sharpdisplay;
+ common_hal_sharpdisplay_framebuffer_reset(sharp);
+#endif
} else {
// Not an active display bus.
continue;
@@ -190,9 +194,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
}
}
@@ -205,6 +207,11 @@ void displayio_gc_collect(void) {
rgbmatrix_rgbmatrix_collect_ptrs(&displays[i].rgbmatrix);
}
#endif
+#if CIRCUITPY_SHARPDISPLAY
+ if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) {
+ common_hal_sharpdisplay_framebuffer_collect_ptrs(&displays[i].sharpdisplay);
+ }
+#endif
if (displays[i].display.base.type == NULL) {
continue;
@@ -377,8 +384,8 @@ primary_display_t *allocate_display_or_raise(void) {
}
primary_display_t *allocate_display_bus(void) {
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- mp_const_obj_t display_type = displays[i].display.base.type;
- if (display_type == NULL || display_type == &mp_type_NoneType) {
+ mp_const_obj_t display_bus_type = displays[i].bus_base.type;
+ if (display_bus_type == NULL || display_bus_type == &mp_type_NoneType) {
return &displays[i];
}
}
diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h
index 9eb10c28b..44ad5a9a9 100644
--- a/shared-module/displayio/__init__.h
+++ b/shared-module/displayio/__init__.h
@@ -36,18 +36,28 @@
#include "shared-bindings/displayio/Group.h"
#include "shared-bindings/displayio/I2CDisplay.h"
#include "shared-bindings/displayio/ParallelBus.h"
+#if CIRCUITPY_RGBMATRIX
#include "shared-bindings/rgbmatrix/RGBMatrix.h"
+#endif
+#if CIRCUITPY_SHARPDISPLAY
+#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
+#endif
typedef struct {
union {
+ mp_obj_base_t bus_base;
displayio_fourwire_obj_t fourwire_bus;
displayio_i2cdisplay_obj_t i2cdisplay_bus;
displayio_parallelbus_obj_t parallel_bus;
#if CIRCUITPY_RGBMATRIX
rgbmatrix_rgbmatrix_obj_t rgbmatrix;
#endif
+#if CIRCUITPY_SHARPDISPLAY
+ sharpdisplay_framebuffer_obj_t sharpdisplay;
+#endif
};
union {
+ mp_obj_base_t display_base;
displayio_display_obj_t display;
displayio_epaperdisplay_obj_t epaper_display;
#if CIRCUITPY_FRAMEBUFFERIO
diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c
index 43f2d1937..57d33b565 100644
--- a/shared-module/displayio/display_core.c
+++ b/shared-module/displayio/display_core.c
@@ -48,6 +48,7 @@ void displayio_display_core_construct(displayio_display_core_t* self,
uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte, bool reverse_bytes_in_word) {
self->colorspace.depth = color_depth;
self->colorspace.grayscale = grayscale;
+ self->colorspace.grayscale_bit = 8 - color_depth;
self->colorspace.pixels_in_byte_share_row = pixels_in_byte_share_row;
self->colorspace.bytes_per_cell = bytes_per_cell;
self->colorspace.reverse_pixels_in_byte = reverse_pixels_in_byte;
@@ -85,7 +86,10 @@ void displayio_display_core_construct(displayio_display_core_t* self,
self->bus = bus;
- supervisor_start_terminal(width, height);
+ // (offsetof core is equal in all display types)
+ if (self == &displays[0].display.core) {
+ supervisor_start_terminal(width, height);
+ }
self->width = width;
self->height = height;
@@ -197,7 +201,7 @@ bool displayio_display_core_get_dither(displayio_display_core_t* self){
}
bool displayio_display_core_bus_free(displayio_display_core_t *self) {
- return self->bus_free(self->bus);
+ return !self->bus || self->bus_free(self->bus);
}
bool displayio_display_core_begin_transaction(displayio_display_core_t* self) {
@@ -208,7 +212,10 @@ void displayio_display_core_end_transaction(displayio_display_core_t* self) {
self->end_transaction(self->bus);
}
-void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command, uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command, bool data_as_commands, bool always_toggle_chip_select, displayio_area_t* area) {
+void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command,
+ uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command,
+ bool data_as_commands, bool always_toggle_chip_select,
+ displayio_area_t* area, bool SH1107_addressing) {
uint16_t x1 = area->x1;
uint16_t x2 = area->x2;
uint16_t y1 = area->y1;
@@ -253,8 +260,17 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self,
data[data_length++] = x2 >> 8;
data[data_length++] = x2 & 0xff;
}
+ // Quirk for SH1107 "SH1107_addressing"
+ // Note... column is y! page is x!
+ // Page address command = 0xB0
+ if (SH1107_addressing) {
+ // set the page to our x value
+ data[0] = 0xB0 | (x1 & 0x0F);
+ data_length = 1;
+ }
self->send(self->bus, data_type, chip_select, data, data_length);
displayio_display_core_end_transaction(self);
+
if (set_current_column_command != NO_COMMAND) {
uint8_t command = set_current_column_command;
displayio_display_core_begin_transaction(self);
@@ -283,7 +299,16 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self,
data[data_length++] = y2 >> 8;
data[data_length++] = y2 & 0xff;
}
+ // Quirk for SH1107 "SH1107_addressing"
+ // Note... column is y! page is x!
+ // Column lower command = 0x00, Column upper command = 0x10
+ if (SH1107_addressing) {
+ data[0] = y1 & 0x0F; // 0x00 to 0x0F
+ data[1] = (y1 >> 4 & 0x0F) | 0x10; // 0x10 to 0x17
+ data_length = 2;
+ }
self->send(self->bus, data_type, chip_select, data, data_length);
+
displayio_display_core_end_transaction(self);
if (set_current_row_command != NO_COMMAND) {
@@ -295,8 +320,17 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self,
}
}
-void displayio_display_core_start_refresh(displayio_display_core_t* self) {
+bool displayio_display_core_start_refresh(displayio_display_core_t* self) {
+ if (!displayio_display_core_bus_free(self)) {
+ // Can't acquire display bus; skip updating this display. Try next display.
+ return false;
+ }
+ if (self->refresh_in_progress) {
+ return false;
+ }
+ self->refresh_in_progress = true;
self->last_refresh = supervisor_ticks_ms64();
+ return true;
}
void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
@@ -305,6 +339,7 @@ void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
displayio_group_finish_refresh(self->current_group);
}
self->full_refresh = false;
+ self->refresh_in_progress = false;
self->last_refresh = supervisor_ticks_ms64();
}
diff --git a/shared-module/displayio/display_core.h b/shared-module/displayio/display_core.h
index e4fd62d4a..fe6cb6f3f 100644
--- a/shared-module/displayio/display_core.h
+++ b/shared-module/displayio/display_core.h
@@ -54,6 +54,7 @@ typedef struct {
int16_t colstart;
int16_t rowstart;
bool full_refresh; // New group means we need to refresh the whole display.
+ bool refresh_in_progress;
} displayio_display_core_t;
void displayio_display_core_construct(displayio_display_core_t* self,
@@ -74,11 +75,14 @@ bool displayio_display_core_bus_free(displayio_display_core_t *self);
bool displayio_display_core_begin_transaction(displayio_display_core_t* self);
void displayio_display_core_end_transaction(displayio_display_core_t* self);
-void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command, uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command, bool data_as_commands, bool always_toggle_chip_select, displayio_area_t* area);
+void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command,
+ uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command,
+ bool data_as_commands, bool always_toggle_chip_select,
+ displayio_area_t* area, bool SH1107_addressing);
void release_display_core(displayio_display_core_t* self);
-void displayio_display_core_start_refresh(displayio_display_core_t* self);
+bool displayio_display_core_start_refresh(displayio_display_core_t* self);
void displayio_display_core_finish_refresh(displayio_display_core_t* self);
void displayio_display_core_collect_ptrs(displayio_display_core_t* self);
diff --git a/shared-module/framebufferio/FramebufferDisplay.c b/shared-module/framebufferio/FramebufferDisplay.c
index f296da409..03e121c91 100644
--- a/shared-module/framebufferio/FramebufferDisplay.c
+++ b/shared-module/framebufferio/FramebufferDisplay.c
@@ -40,6 +40,11 @@
#include <stdint.h>
#include <string.h>
+#define fb_getter_default(method, default_value) \
+ (self->framebuffer_protocol->method \
+ ? self->framebuffer_protocol->method(self->framebuffer) \
+ : (default_value))
+
void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebufferdisplay_obj_t* self,
mp_obj_t framebuffer,
uint16_t rotation,
@@ -51,7 +56,7 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu
uint16_t ram_width = 0x100;
uint16_t ram_height = 0x100;
-
+ uint16_t depth = fb_getter_default(get_color_depth, 16);
displayio_display_core_construct(
&self->core,
NULL,
@@ -61,25 +66,40 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu
ram_height,
0,
0,
- rotation,
- self->framebuffer_protocol->get_color_depth(self->framebuffer),
- false,
- false,
- self->framebuffer_protocol->get_bytes_per_cell(self->framebuffer),
- false,
- false);
+ 0, // rotation
+ depth,
+ fb_getter_default(get_grayscale, (depth < 8)),
+ fb_getter_default(get_pixels_in_byte_share_row, false),
+ fb_getter_default(get_bytes_per_cell, 2),
+ fb_getter_default(get_reverse_pixels_in_byte, false),
+ fb_getter_default(get_reverse_pixels_in_word, false)
+ );
+
+ self->first_pixel_offset = fb_getter_default(get_first_pixel_offset, 0);
+ self->row_stride = fb_getter_default(get_row_stride, 0);
+ if (self->row_stride == 0) {
+ self->row_stride = self->core.width * self->core.colorspace.depth/8;
+ }
+
+ self->framebuffer_protocol->get_bufinfo(self->framebuffer, &self->bufinfo);
+ size_t framebuffer_size = self->first_pixel_offset + self->row_stride * self->core.height;
+ if (self->bufinfo.len < framebuffer_size) {
+ mp_raise_IndexError_varg(translate("Framebuffer requires %d bytes"), framebuffer_size);
+ }
self->first_manual_refresh = !auto_refresh;
- self->native_frames_per_second = self->framebuffer_protocol->get_native_frames_per_second(self->framebuffer);
+ self->native_frames_per_second = fb_getter_default(get_native_frames_per_second, 60);
self->native_ms_per_frame = 1000 / self->native_frames_per_second;
- supervisor_start_terminal(self->core.width, self->core.height);
+ if (rotation != 0) {
+ common_hal_framebufferio_framebufferdisplay_set_rotation(self, rotation);
+ }
// 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) {
@@ -109,7 +129,7 @@ bool common_hal_framebufferio_framebufferdisplay_set_auto_brightness(framebuffer
}
mp_float_t common_hal_framebufferio_framebufferdisplay_get_brightness(framebufferio_framebufferdisplay_obj_t* self) {
- if (self->framebuffer_protocol->set_brightness) {
+ if (self->framebuffer_protocol->get_brightness) {
return self->framebuffer_protocol->get_brightness(self->framebuffer);
}
return -1;
@@ -138,7 +158,8 @@ STATIC const displayio_area_t* _get_refresh_areas(framebufferio_framebufferdispl
return NULL;
}
-STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const displayio_area_t* area) {
+#define MARK_ROW_DIRTY(r) (dirty_row_bitmask[r/8] |= (1 << (r & 7)))
+STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const displayio_area_t* area, uint8_t *dirty_row_bitmask) {
uint16_t buffer_size = 128; // In uint32_ts
displayio_area_t clipped;
@@ -147,6 +168,14 @@ STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const di
return true;
}
uint16_t subrectangles = 1;
+
+ // If pixels are packed by row then rows are on byte boundaries
+ if (self->core.colorspace.depth < 8 && self->core.colorspace.pixels_in_byte_share_row) {
+ int div = 8 / self->core.colorspace.depth;
+ clipped.x1 = (clipped.x1 / div) * div;
+ clipped.x2 = ((clipped.x2 + div - 1) / div) * div;
+ }
+
uint16_t rows_per_buffer = displayio_area_height(&clipped);
uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth;
uint16_t pixels_per_buffer = displayio_area_size(&clipped);
@@ -187,6 +216,7 @@ STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const di
.x2 = clipped.x2,
.y2 = clipped.y1 + rows_per_buffer * (j + 1)
};
+
if (remaining_rows < rows_per_buffer) {
subrectangle.y2 = subrectangle.y1 + remaining_rows;
}
@@ -197,12 +227,18 @@ STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const di
displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer);
- // COULDDO: this arithmetic only supports multiple-of-8 bpp
- uint8_t *dest = self->bufinfo.buf + (subrectangle.y1 * self->core.width + subrectangle.x1) * (self->core.colorspace.depth / 8);
+ uint8_t *buf = (uint8_t *)self->bufinfo.buf, *endbuf = buf + self->bufinfo.len;
+ (void)endbuf; // Hint to compiler that endbuf is "used" even if NDEBUG
+ buf += self->first_pixel_offset;
+
+ size_t rowstride = self->row_stride;
+ uint8_t *dest = buf + subrectangle.y1 * rowstride + subrectangle.x1 * self->core.colorspace.depth / 8;
uint8_t *src = (uint8_t*)buffer;
- size_t rowsize = (subrectangle.x2 - subrectangle.x1) * (self->core.colorspace.depth / 8);
- size_t rowstride = self->core.width * (self->core.colorspace.depth/8);
+ size_t rowsize = (subrectangle.x2 - subrectangle.x1) * self->core.colorspace.depth / 8;
+
for (uint16_t i = subrectangle.y1; i < subrectangle.y2; i++) {
+ assert(dest >= buf && dest < endbuf && dest+rowsize <= endbuf);
+ MARK_ROW_DIRTY(i);
memcpy(dest, src, rowsize);
dest += rowstride;
src += rowsize;
@@ -216,15 +252,23 @@ STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const di
}
STATIC void _refresh_display(framebufferio_framebufferdisplay_obj_t* self) {
- displayio_display_core_start_refresh(&self->core);
self->framebuffer_protocol->get_bufinfo(self->framebuffer, &self->bufinfo);
+ if(!self->bufinfo.buf) {
+ return;
+ }
+ displayio_display_core_start_refresh(&self->core);
const displayio_area_t* current_area = _get_refresh_areas(self);
- while (current_area != NULL) {
- _refresh_area(self, current_area);
- current_area = current_area->next;
+ if (current_area) {
+ uint8_t dirty_row_bitmask[(self->core.height + 7) / 8];
+ memset(dirty_row_bitmask, 0, sizeof(dirty_row_bitmask));
+ self->framebuffer_protocol->get_bufinfo(self->framebuffer, &self->bufinfo);
+ while (current_area != NULL) {
+ _refresh_area(self, current_area, dirty_row_bitmask);
+ current_area = current_area->next;
+ }
+ self->framebuffer_protocol->swapbuffers(self->framebuffer, dirty_row_bitmask);
}
displayio_display_core_finish_refresh(&self->core);
- self->framebuffer_protocol->swapbuffers(self->framebuffer);
}
void common_hal_framebufferio_framebufferdisplay_set_rotation(framebufferio_framebufferdisplay_obj_t* self, int rotation){
@@ -236,8 +280,10 @@ void common_hal_framebufferio_framebufferdisplay_set_rotation(framebufferio_fram
self->core.height = tmp;
}
displayio_display_core_set_rotation(&self->core, rotation);
- supervisor_stop_terminal();
- supervisor_start_terminal(self->core.width, self->core.height);
+ if (self == &displays[0].framebuffer_display) {
+ supervisor_stop_terminal();
+ supervisor_start_terminal(self->core.width, self->core.height);
+ }
if (self->core.current_group != NULL) {
displayio_group_update_transform(self->core.current_group, &self->core.transform);
}
@@ -280,6 +326,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,16 +350,24 @@ 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_show(self, NULL);
+ self->base.type = &mp_type_NoneType;
}
void framebufferio_framebufferdisplay_collect_ptrs(framebufferio_framebufferdisplay_obj_t* self) {
gc_collect_ptr(self->framebuffer);
displayio_display_core_collect_ptrs(&self->core);
}
+
+void framebufferio_framebufferdisplay_reset(framebufferio_framebufferdisplay_obj_t* self) {
+ mp_obj_type_t *fb_type = mp_obj_get_type(self->framebuffer);
+ if(fb_type != NULL && fb_type != &mp_type_NoneType) {
+ common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, true);
+ common_hal_framebufferio_framebufferdisplay_show(self, NULL);
+ self->core.full_refresh = true;
+ } else {
+ release_framebufferdisplay(self);
+ }
+}
diff --git a/shared-module/framebufferio/FramebufferDisplay.h b/shared-module/framebufferio/FramebufferDisplay.h
index 1b68d2ab0..d73d4b9a9 100644
--- a/shared-module/framebufferio/FramebufferDisplay.h
+++ b/shared-module/framebufferio/FramebufferDisplay.h
@@ -33,7 +33,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"
@@ -48,43 +47,65 @@ typedef struct {
uint64_t last_refresh_call;
uint16_t native_frames_per_second;
uint16_t native_ms_per_frame;
+ uint16_t first_pixel_offset;
+ uint16_t row_stride;
bool auto_refresh;
bool first_manual_refresh;
} framebufferio_framebufferdisplay_obj_t;
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);
mp_obj_t common_hal_framebufferio_framebufferdisplay_get_framebuffer(framebufferio_framebufferdisplay_obj_t* self);
-typedef void (*framebuffer_get_bufinfo_fun)(mp_obj_t, mp_buffer_info_t *bufinfo);
-typedef void (*framebuffer_swapbuffers_fun)(mp_obj_t);
-typedef void (*framebuffer_deinit_fun)(mp_obj_t);
-typedef bool (*framebuffer_set_brightness_fun)(mp_obj_t, mp_float_t);
-typedef mp_float_t (*framebuffer_get_brightness_fun)(mp_obj_t);
-typedef bool (*framebuffer_set_auto_brightness_fun)(mp_obj_t, bool);
typedef bool (*framebuffer_get_auto_brightness_fun)(mp_obj_t);
-typedef int (*framebuffer_get_width_fun)(mp_obj_t);
-typedef int (*framebuffer_get_height_fun)(mp_obj_t);
-typedef int (*framebuffer_get_color_depth_fun)(mp_obj_t);
+typedef bool (*framebuffer_get_reverse_pixels_in_byte_fun)(mp_obj_t);
+typedef bool (*framebuffer_get_reverse_pixels_in_word_fun)(mp_obj_t);
+typedef bool (*framebuffer_set_auto_brightness_fun)(mp_obj_t, bool);
+typedef bool (*framebuffer_set_brightness_fun)(mp_obj_t, mp_float_t);
typedef int (*framebuffer_get_bytes_per_cell_fun)(mp_obj_t);
+typedef int (*framebuffer_get_color_depth_fun)(mp_obj_t);
+typedef int (*framebuffer_get_first_pixel_offset_fun)(mp_obj_t);
+typedef int (*framebuffer_get_grayscale_fun)(mp_obj_t);
+typedef int (*framebuffer_get_height_fun)(mp_obj_t);
typedef int (*framebuffer_get_native_frames_per_second_fun)(mp_obj_t);
+typedef bool (*framebuffer_get_pixels_in_byte_share_row_fun)(mp_obj_t);
+typedef int (*framebuffer_get_row_stride_fun)(mp_obj_t);
+typedef int (*framebuffer_get_width_fun)(mp_obj_t);
+typedef mp_float_t (*framebuffer_get_brightness_fun)(mp_obj_t);
+typedef void (*framebuffer_deinit_fun)(mp_obj_t);
+typedef void (*framebuffer_get_bufinfo_fun)(mp_obj_t, mp_buffer_info_t *bufinfo);
+typedef void (*framebuffer_swapbuffers_fun)(mp_obj_t, uint8_t *dirty_row_bitmask);
typedef struct _framebuffer_p_t {
MP_PROTOCOL_HEAD // MP_QSTR_protocol_framebuffer
+
+ // Mandatory
framebuffer_get_bufinfo_fun get_bufinfo;
framebuffer_swapbuffers_fun swapbuffers;
framebuffer_deinit_fun deinit;
framebuffer_get_width_fun get_width;
framebuffer_get_height_fun get_height;
- framebuffer_get_color_depth_fun get_color_depth;
- framebuffer_get_bytes_per_cell_fun get_bytes_per_cell;
- framebuffer_get_native_frames_per_second_fun get_native_frames_per_second;
+
+ // Optional getters
+ framebuffer_get_bytes_per_cell_fun get_bytes_per_cell; // default: 2
+ framebuffer_get_color_depth_fun get_color_depth; // default: 16
+ framebuffer_get_first_pixel_offset_fun get_first_pixel_offset; // default: 0
+ framebuffer_get_grayscale_fun get_grayscale; // default: grayscale if depth < 8
+ framebuffer_get_native_frames_per_second_fun get_native_frames_per_second; // default: 60
+ framebuffer_get_pixels_in_byte_share_row_fun get_pixels_in_byte_share_row; // default: false
+ framebuffer_get_reverse_pixels_in_byte_fun get_reverse_pixels_in_byte; // default: false
+ framebuffer_get_reverse_pixels_in_word_fun get_reverse_pixels_in_word; // default: false
+ framebuffer_get_row_stride_fun get_row_stride; // default: 0 (no extra row padding)
+
+ // Optional -- default is no brightness control
framebuffer_get_brightness_fun get_brightness;
framebuffer_set_brightness_fun set_brightness;
+
+ // Optional -- default is no automatic brightness control
framebuffer_get_auto_brightness_fun get_auto_brightness;
framebuffer_set_auto_brightness_fun set_auto_brightness;
} framebuffer_p_t;
diff --git a/shared-module/ipaddress/IPv4Address.c b/shared-module/ipaddress/IPv4Address.c
new file mode 100644
index 000000000..f573d9d0a
--- /dev/null
+++ b/shared-module/ipaddress/IPv4Address.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 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 "py/obj.h"
+
+#include "shared-bindings/ipaddress/__init__.h"
+#include "shared-bindings/ipaddress/IPv4Address.h"
+
+
+void common_hal_ipaddress_ipv4address_construct(ipaddress_ipv4address_obj_t* self, uint8_t* buf, size_t len) {
+ self->ip_bytes = mp_obj_new_bytes(buf, len);
+}
+
+mp_obj_t common_hal_ipaddress_ipv4address_get_packed(ipaddress_ipv4address_obj_t* self) {
+ return self->ip_bytes;
+}
diff --git a/shared-module/_pew/PewPew.h b/shared-module/ipaddress/IPv4Address.h
index da1cae0a2..3f2bde091 100644
--- a/shared-module/_pew/PewPew.h
+++ b/shared-module/ipaddress/IPv4Address.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Radomir Dopieralski
+ * 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
@@ -24,25 +24,14 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_PEW_PEWPEW_H
-#define MICROPY_INCLUDED_PEW_PEWPEW_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H
+#define MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H
-#include <stdint.h>
-#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
- uint8_t* buffer;
- mp_obj_t* rows;
- mp_obj_t* cols;
- digitalio_digitalinout_obj_t *buttons;
- uint8_t rows_size;
- uint8_t cols_size;
- uint8_t pressed;
-} pew_obj_t;
+ mp_obj_t ip_bytes;
+} ipaddress_ipv4address_obj_t;
-void pew_init(void);
-void pewpew_interrupt_handler(uint8_t index);
-void pew_reset(void);
-
-#endif // MICROPY_INCLUDED_PEW_PEWPEW_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H
diff --git a/shared-module/ipaddress/__init__.c b/shared-module/ipaddress/__init__.c
new file mode 100644
index 000000000..a8f8e1caf
--- /dev/null
+++ b/shared-module/ipaddress/__init__.c
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the MicroPython 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/ipaddress/__init__.h"
+#include "shared-bindings/ipaddress/IPv4Address.h"
+
+mp_obj_t common_hal_ipaddress_new_ipv4address(uint32_t value) {
+ ipaddress_ipv4address_obj_t* self = m_new_obj(ipaddress_ipv4address_obj_t);
+ self->base.type = &ipaddress_ipv4address_type;
+ common_hal_ipaddress_ipv4address_construct(self, (uint8_t*) &value, 4);
+ return MP_OBJ_FROM_PTR(self);
+}
diff --git a/shared-module/ipaddress/__init__.h b/shared-module/ipaddress/__init__.h
new file mode 100644
index 000000000..7d5f2c220
--- /dev/null
+++ b/shared-module/ipaddress/__init__.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython 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_IPADDRESS___INIT___H
+#define MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS___INIT___H
+
+#include <stdint.h>
+
+#include "py/obj.h"
+
+mp_obj_t common_hal_ipaddress_new_ipv4(uint32_t value);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS___INIT___H
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/random/__init__.c b/shared-module/random/__init__.c
index 5cc20e5b5..42499bc0a 100644
--- a/shared-module/random/__init__.c
+++ b/shared-module/random/__init__.c
@@ -44,7 +44,7 @@ STATIC uint32_t yasmarang(void)
{
if (yasmarang_pad == 0xeda4baba) {
if (!common_hal_os_urandom((uint8_t *)&yasmarang_pad, sizeof(uint32_t))) {
- yasmarang_pad = common_hal_time_monotonic() & 0xffffffff;
+ yasmarang_pad = common_hal_time_monotonic_ms() & 0xffffffff;
}
}
yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n;
diff --git a/shared-module/rgbmatrix/RGBMatrix.c b/shared-module/rgbmatrix/RGBMatrix.c
index 6dad91679..a09767b62 100644
--- a/shared-module/rgbmatrix/RGBMatrix.c
+++ b/shared-module/rgbmatrix/RGBMatrix.c
@@ -66,9 +66,9 @@ void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t *self, i
}
void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, mp_obj_t framebuffer) {
+ common_hal_rgbmatrix_timer_disable(self->timer);
if (framebuffer) {
self->framebuffer = framebuffer;
- framebuffer = mp_obj_new_bytearray_of_zeros(self->bufsize);
mp_get_buffer_raise(self->framebuffer, &self->bufinfo, MP_BUFFER_READ);
if (mp_get_buffer(self->framebuffer, &self->bufinfo, MP_BUFFER_RW)) {
self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW;
@@ -78,18 +78,19 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
// verify that the matrix is big enough
mp_get_index(mp_obj_get_type(self->framebuffer), self->bufinfo.len, MP_OBJ_NEW_SMALL_INT(self->bufsize-1), false);
} else {
- _PM_FREE(self->bufinfo.buf);
- _PM_FREE(self->core.rgbPins);
- _PM_FREE(self->core.addr);
- _PM_FREE(self->core.screenData);
+ common_hal_rgbmatrix_free_impl(self->bufinfo.buf);
+ common_hal_rgbmatrix_free_impl(self->protomatter.rgbPins);
+ common_hal_rgbmatrix_free_impl(self->protomatter.addr);
+ common_hal_rgbmatrix_free_impl(self->protomatter.screenData);
self->framebuffer = NULL;
- self->bufinfo.buf = _PM_allocator_impl(self->bufsize);
+ self->bufinfo.buf = common_hal_rgbmatrix_allocator_impl(self->bufsize);
self->bufinfo.len = self->bufsize;
self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW;
}
- ProtomatterStatus stat = _PM_init(&self->core,
+ memset(&self->protomatter, 0, sizeof(self->protomatter));
+ ProtomatterStatus stat = _PM_init(&self->protomatter,
self->width, self->bit_depth,
self->rgb_count/6, self->rgb_pins,
self->addr_count, self->addr_pins,
@@ -97,18 +98,21 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
self->doublebuffer, self->timer);
if (stat == PROTOMATTER_OK) {
- _PM_protoPtr = &self->core;
+ _PM_protoPtr = &self->protomatter;
common_hal_mcu_disable_interrupts();
common_hal_rgbmatrix_timer_enable(self->timer);
- stat = _PM_begin(&self->core);
- _PM_convert_565(&self->core, self->bufinfo.buf, self->width);
+ stat = _PM_begin(&self->protomatter);
+
+ if (stat == PROTOMATTER_OK) {
+ _PM_convert_565(&self->protomatter, self->bufinfo.buf, self->width);
+ }
common_hal_mcu_enable_interrupts();
- _PM_swapbuffer_maybe(&self->core);
+ if (stat == PROTOMATTER_OK) {
+ _PM_swapbuffer_maybe(&self->protomatter);
+ }
}
if (stat != PROTOMATTER_OK) {
- // XXX this deinit() actually makes crashy-crashy
- // can trigger it by sending inappropriate pins
common_hal_rgbmatrix_rgbmatrix_deinit(self);
switch (stat) {
case PROTOMATTER_ERR_PINS:
@@ -117,7 +121,9 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
case PROTOMATTER_ERR_ARG:
mp_raise_ValueError(translate("Invalid argument"));
break;
- case PROTOMATTER_ERR_MALLOC: /// should have already been signaled as NLR
+ case PROTOMATTER_ERR_MALLOC:
+ mp_raise_msg(&mp_type_MemoryError, NULL);
+ break;
default:
mp_raise_msg_varg(&mp_type_RuntimeError,
translate("Internal error #%d"), (int)stat);
@@ -126,7 +132,6 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
}
self->paused = 0;
-
}
STATIC void free_pin(uint8_t *pin) {
@@ -148,7 +153,7 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) {
self->timer = 0;
}
- if (_PM_protoPtr == &self->core) {
+ if (_PM_protoPtr == &self->protomatter) {
_PM_protoPtr = NULL;
}
@@ -158,14 +163,14 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) {
free_pin(&self->latch_pin);
free_pin(&self->oe_pin);
- if (self->core.rgbPins) {
- _PM_free(&self->core);
+ if (self->protomatter.rgbPins) {
+ _PM_deallocate(&self->protomatter);
}
- memset(&self->core, 0, sizeof(self->core));
+ memset(&self->protomatter, 0, sizeof(self->protomatter));
// If it was supervisor-allocated, it is supervisor-freed and the pointer
// is zeroed, otherwise the pointer is just zeroed
- _PM_FREE(self->bufinfo.buf);
+ _PM_free(self->bufinfo.buf);
self->base.type = NULL;
// If a framebuffer was passed in to the constructor, NULL the reference
@@ -175,16 +180,15 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) {
void rgbmatrix_rgbmatrix_collect_ptrs(rgbmatrix_rgbmatrix_obj_t* self) {
gc_collect_ptr(self->framebuffer);
- gc_collect_ptr(self->core.rgbPins);
- gc_collect_ptr(self->core.addr);
- gc_collect_ptr(self->core.screenData);
}
void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t* self, bool paused) {
if (paused && !self->paused) {
- _PM_stop(&self->core);
+ _PM_stop(&self->protomatter);
} else if (!paused && self->paused) {
- _PM_resume(&self->core);
+ _PM_resume(&self->protomatter);
+ _PM_convert_565(&self->protomatter, self->bufinfo.buf, self->width);
+ _PM_swapbuffer_maybe(&self->protomatter);
}
self->paused = paused;
}
@@ -194,8 +198,10 @@ bool common_hal_rgbmatrix_rgbmatrix_get_paused(rgbmatrix_rgbmatrix_obj_t* self)
}
void common_hal_rgbmatrix_rgbmatrix_refresh(rgbmatrix_rgbmatrix_obj_t* self) {
- _PM_convert_565(&self->core, self->bufinfo.buf, self->width);
- _PM_swapbuffer_maybe(&self->core);
+ if (!self->paused) {
+ _PM_convert_565(&self->protomatter, self->bufinfo.buf, self->width);
+ _PM_swapbuffer_maybe(&self->protomatter);
+ }
}
int common_hal_rgbmatrix_rgbmatrix_get_width(rgbmatrix_rgbmatrix_obj_t* self) {
@@ -206,3 +212,12 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self) {
int computed_height = (self->rgb_count / 3) << (self->addr_count);
return computed_height;
}
+
+void *common_hal_rgbmatrix_allocator_impl(size_t sz) {
+ supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, true);
+ return allocation ? allocation->ptr : NULL;
+}
+
+void common_hal_rgbmatrix_free_impl(void *ptr_in) {
+ free_memory(allocation_from_ptr(ptr_in));
+}
diff --git a/shared-module/rgbmatrix/RGBMatrix.h b/shared-module/rgbmatrix/RGBMatrix.h
index e69de29bb..6dbc6fd41 100644
--- a/shared-module/rgbmatrix/RGBMatrix.h
+++ b/shared-module/rgbmatrix/RGBMatrix.h
@@ -0,0 +1,47 @@
+/*
+ * 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 "lib/protomatter/src/core.h"
+
+extern const mp_obj_type_t rgbmatrix_RGBMatrix_type;
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t framebuffer;
+ mp_buffer_info_t bufinfo;
+ Protomatter_core protomatter;
+ void *timer;
+ uint16_t bufsize, width;
+ uint8_t rgb_pins[30];
+ uint8_t addr_pins[10];
+ uint8_t clock_pin, latch_pin, oe_pin;
+ uint8_t rgb_count, addr_count;
+ uint8_t bit_depth;
+ bool core_is_initialized;
+ bool paused;
+ bool doublebuffer;
+} rgbmatrix_rgbmatrix_obj_t;
diff --git a/shared-module/rgbmatrix/allocator.h b/shared-module/rgbmatrix/allocator.h
index 5e6f0b41d..3431046d5 100644
--- a/shared-module/rgbmatrix/allocator.h
+++ b/shared-module/rgbmatrix/allocator.h
@@ -1,29 +1,37 @@
-#ifndef MICROPY_INCLUDED_SHARED_MODULE_RGBMATRIX_ALLOCATOR_H
-#define MICROPY_INCLUDED_SHARED_MODULE_RGBMATRIX_ALLOCATOR_H
+/*
+ * 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 <stdbool.h>
#include "py/gc.h"
#include "py/misc.h"
#include "supervisor/memory.h"
-#define _PM_ALLOCATOR _PM_allocator_impl
-#define _PM_FREE(x) (_PM_free_impl((x)), (x)=NULL, (void)0)
-
-static inline void *_PM_allocator_impl(size_t sz) {
- if (gc_alloc_possible()) {
- return m_malloc(sz + sizeof(void*), true);
- } else {
- supervisor_allocation *allocation = allocate_memory(align32_size(sz), false);
- return allocation ? allocation->ptr : NULL;
- }
-}
-
-static inline void _PM_free_impl(void *ptr_in) {
- supervisor_allocation *allocation = allocation_from_ptr(ptr_in);
-
- if (allocation) {
- free_memory(allocation);
- }
-}
-
-#endif
+#define _PM_allocate common_hal_rgbmatrix_allocator_impl
+#define _PM_free(x) (common_hal_rgbmatrix_free_impl((x)), (x)=NULL, (void)0)
+extern void *common_hal_rgbmatrix_allocator_impl(size_t sz);
+extern void common_hal_rgbmatrix_free_impl(void *);
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/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c
new file mode 100644
index 000000000..4b92bd637
--- /dev/null
+++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c
@@ -0,0 +1,248 @@
+/*
+ * This file is part of the MicroPython 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.
+ */
+
+#include <string.h>
+
+#include "py/gc.h"
+
+#include "shared-bindings/board/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h"
+#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
+
+#include "supervisor/memory.h"
+
+#define SHARPMEM_BIT_WRITECMD_LSB (0x80)
+#define SHARPMEM_BIT_VCOM_LSB (0x40)
+
+STATIC uint8_t bitrev(uint8_t n) {
+ uint8_t r = 0;
+ for(int i=0;i<8;i++) r |= ((n>>i) & 1)<<(7-i);
+ return r;
+}
+
+int common_hal_sharpdisplay_framebuffer_get_width(sharpdisplay_framebuffer_obj_t *self) {
+ return self->width;
+}
+
+int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_t *self) {
+ return self->height;
+}
+
+int common_hal_sharpdisplay_framebuffer_get_row_stride(sharpdisplay_framebuffer_obj_t *self) {
+ return (self->width + 7) / 8 + 2;
+}
+
+int common_hal_sharpdisplay_framebuffer_get_first_pixel_offset(sharpdisplay_framebuffer_obj_t *self) {
+ return 2;
+}
+
+bool common_hal_sharpdisplay_framebuffer_get_reverse_pixels_in_byte(sharpdisplay_framebuffer_obj_t *self) {
+ return true;
+}
+
+bool common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(sharpdisplay_framebuffer_obj_t *self) {
+ return true;
+}
+
+void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self) {
+ if (self->bus != &self->inline_bus
+#if BOARD_SPI
+ && self->bus != common_hal_board_get_spi()
+#endif
+ ) {
+ memcpy(&self->inline_bus, self->bus, sizeof(busio_spi_obj_t));
+ self->bus = &self->inline_bus;
+ }
+}
+
+void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self) {
+ // Look up the allocation by the old pointer and get the new pointer from it.
+ supervisor_allocation* alloc = allocation_from_ptr(self->bufinfo.buf);
+ self->bufinfo.buf = alloc ? alloc->ptr : NULL;
+}
+
+void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo) {
+ if (!self->bufinfo.buf) {
+ int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self);
+ int height = common_hal_sharpdisplay_framebuffer_get_height(self);
+ self->bufinfo.len = row_stride * height + 2;
+ supervisor_allocation* alloc = allocate_memory(align32_size(self->bufinfo.len), false, true);
+ if (alloc == NULL) {
+ m_malloc_fail(self->bufinfo.len);
+ }
+ self->bufinfo.buf = alloc->ptr;
+ memset(alloc->ptr, 0, self->bufinfo.len);
+
+ uint8_t *data = self->bufinfo.buf;
+ *data++ = SHARPMEM_BIT_WRITECMD_LSB;
+
+ for(int y=0; y<height; y++) {
+ *data = bitrev(y+1);
+ data += row_stride;
+ }
+ self->full_refresh = true;
+ }
+ if (bufinfo) {
+ *bufinfo = self->bufinfo;
+ }
+}
+
+void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self) {
+ if (self->base.type != &sharpdisplay_framebuffer_type) {
+ return;
+ }
+
+ if (self->bus == &self->inline_bus) {
+ common_hal_busio_spi_deinit(self->bus);
+ }
+
+ common_hal_reset_pin(self->chip_select.pin);
+
+ free_memory(allocation_from_ptr(self->bufinfo.buf));
+
+ memset(self, 0, sizeof(*self));
+}
+
+void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, mcu_pin_obj_t *chip_select, int baudrate, int width, int height) {
+ common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
+ common_hal_never_reset_pin(chip_select);
+
+ self->bus = spi;
+ common_hal_busio_spi_never_reset(self->bus);
+
+ self->width = width;
+ self->height = height;
+ self->baudrate = baudrate;
+
+ common_hal_sharpdisplay_framebuffer_get_bufinfo(self, NULL);
+}
+
+void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask) {
+ // claim SPI bus
+ if (!common_hal_busio_spi_try_lock(self->bus)) {
+ return;
+ }
+ common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8);
+
+ // set chip select high
+ common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
+
+ // output the toggling signal
+ uint8_t *data = self->bufinfo.buf;
+ data[0] ^= SHARPMEM_BIT_VCOM_LSB;
+
+ common_hal_busio_spi_write(self->bus, data++, 1);
+
+ // output each changed row
+ size_t row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self);
+ for(int y=0; y<self->height; y++) {
+ if(self->full_refresh || (dirty_row_bitmask[y/8] & (1 << (y & 7)))) {
+ common_hal_busio_spi_write(self->bus, data, row_stride);
+ }
+ data += row_stride;
+ }
+
+ // output a trailing zero
+ common_hal_busio_spi_write(self->bus, data, 1);
+
+ // set chip select low
+ common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
+
+ // release SPI bus
+ common_hal_busio_spi_unlock(self->bus);
+
+ self->full_refresh = false;
+}
+
+STATIC void sharpdisplay_framebuffer_deinit(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ common_hal_sharpdisplay_framebuffer_deinit(self);
+}
+
+STATIC void sharpdisplay_framebuffer_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ common_hal_sharpdisplay_framebuffer_get_bufinfo(self, bufinfo);
+}
+
+STATIC int sharpdisplay_framebuffer_get_color_depth(mp_obj_t self_in) {
+ return 1;
+}
+
+STATIC int sharpdisplay_framebuffer_get_height(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ return common_hal_sharpdisplay_framebuffer_get_height(self);
+}
+
+STATIC int sharpdisplay_framebuffer_get_width(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ return common_hal_sharpdisplay_framebuffer_get_width(self);
+}
+
+STATIC int sharpdisplay_framebuffer_get_first_pixel_offset(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ return common_hal_sharpdisplay_framebuffer_get_first_pixel_offset(self);
+}
+
+STATIC bool sharpdisplay_framebuffer_get_pixels_in_byte_share_row(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ return common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(self);
+}
+
+STATIC bool sharpdisplay_framebuffer_get_reverse_pixels_in_byte(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ return common_hal_sharpdisplay_framebuffer_get_reverse_pixels_in_byte(self);
+}
+
+STATIC int sharpdisplay_framebuffer_get_row_stride(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ return common_hal_sharpdisplay_framebuffer_get_row_stride(self);
+}
+
+STATIC void sharpdisplay_framebuffer_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmask) {
+ sharpdisplay_framebuffer_obj_t *self = self_in;
+ common_hal_sharpdisplay_framebuffer_swapbuffers(self, dirty_row_bitmask);
+}
+
+const framebuffer_p_t sharpdisplay_framebuffer_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer)
+ .deinit = sharpdisplay_framebuffer_deinit,
+ .get_bufinfo = sharpdisplay_framebuffer_get_bufinfo,
+ .get_color_depth = sharpdisplay_framebuffer_get_color_depth,
+ .get_height = sharpdisplay_framebuffer_get_height,
+ .get_width = sharpdisplay_framebuffer_get_width,
+ .swapbuffers = sharpdisplay_framebuffer_swapbuffers,
+
+ .get_first_pixel_offset = sharpdisplay_framebuffer_get_first_pixel_offset,
+ .get_pixels_in_byte_share_row = sharpdisplay_framebuffer_get_pixels_in_byte_share_row,
+ .get_reverse_pixels_in_byte = sharpdisplay_framebuffer_get_reverse_pixels_in_byte,
+ .get_row_stride = sharpdisplay_framebuffer_get_row_stride,
+};
+
+void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *self) {
+ gc_collect_ptr(self->bus);
+}
diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h
new file mode 100644
index 000000000..08966a89c
--- /dev/null
+++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the MicroPython 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 "shared-bindings/busio/SPI.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-module/framebufferio/FramebufferDisplay.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ busio_spi_obj_t* bus;
+ busio_spi_obj_t inline_bus;
+ digitalio_digitalinout_obj_t chip_select;
+ mp_buffer_info_t bufinfo;
+
+ uint16_t width, height;
+ uint32_t baudrate;
+
+ bool full_refresh:1;
+} sharpdisplay_framebuffer_obj_t;
+
+void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, mcu_pin_obj_t *chip_select, int baudrate, int width, int height);
+void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask);
+void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self);
+void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo);
+int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_t *self);
+int common_hal_sharpdisplay_framebuffer_get_width(sharpdisplay_framebuffer_obj_t *self);
+void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask);
+void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self);
+void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self);
+
+extern const framebuffer_p_t sharpdisplay_framebuffer_proto;
+
+void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t*);
diff --git a/shared-module/sharpdisplay/__init__.c b/shared-module/sharpdisplay/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/sharpdisplay/__init__.c
diff --git a/shared-module/sharpdisplay/__init__.h b/shared-module/sharpdisplay/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/sharpdisplay/__init__.h
diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c
index c3d4b50c8..5864307fd 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
*
@@ -30,6 +30,7 @@
#include "extmod/vfs.h"
#include "py/mperrno.h"
+#include "py/mphal.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.h"
@@ -159,6 +160,8 @@ void common_hal_storage_remount(const char *mount_path, bool readonly, bool disa
}
void common_hal_storage_erase_filesystem(void) {
+ usb_disconnect();
+ mp_hal_delay_ms(1000);
filesystem_init(false, true); // Force a re-format.
common_hal_mcu_reset();
// We won't actually get here, since we're resetting.
diff --git a/shared-module/time/__init__.c b/shared-module/time/__init__.c
index 347e68ae0..c79a5f3ae 100644
--- a/shared-module/time/__init__.c
+++ b/shared-module/time/__init__.c
@@ -28,7 +28,7 @@
#include "supervisor/port.h"
#include "supervisor/shared/tick.h"
-uint64_t common_hal_time_monotonic(void) {
+uint64_t common_hal_time_monotonic_ms(void) {
return supervisor_ticks_ms64();
}
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/usb_hid/Device.c b/shared-module/usb_hid/Device.c
index 8e9df6f04..943c9bfed 100644
--- a/shared-module/usb_hid/Device.c
+++ b/shared-module/usb_hid/Device.c
@@ -84,14 +84,17 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type,
// Callbacks invoked when receive Set_Report request through control endpoint
void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
+ if (report_type == HID_REPORT_TYPE_INVALID) {
+ report_id = buffer[0];
+ buffer++;
+ bufsize--;
+ } else if (report_type != HID_REPORT_TYPE_OUTPUT) {
+ return;
+ }
+
usb_hid_device_obj_t* hid_device = get_hid_device(report_id);
- if ( report_type == HID_REPORT_TYPE_OUTPUT ) {
- // Check if it is Keyboard device
- if (hid_device->usage_page == HID_USAGE_PAGE_DESKTOP &&
- hid_device->usage == HID_USAGE_DESKTOP_KEYBOARD) {
- // This is LED indicator (CapsLock, NumLock)
- // TODO Light up some LED here
- }
+ if (hid_device && hid_device->out_report_length >= bufsize) {
+ memcpy(hid_device->out_report_buffer, buffer, bufsize);
}
}
diff --git a/shared-module/usb_hid/Device.h b/shared-module/usb_hid/Device.h
index 10f2ee897..93c3518b4 100644
--- a/shared-module/usb_hid/Device.h
+++ b/shared-module/usb_hid/Device.h
@@ -43,6 +43,8 @@ typedef struct {
uint8_t report_length;
uint8_t usage_page;
uint8_t usage;
+ uint8_t* out_report_buffer;
+ uint8_t out_report_length;
} usb_hid_device_obj_t;
diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c
index 73a314b99..3fb3f836c 100644
--- a/shared-module/usb_midi/__init__.c
+++ b/shared-module/usb_midi/__init__.c
@@ -40,12 +40,12 @@ supervisor_allocation* usb_midi_allocation;
void usb_midi_init(void) {
// TODO(tannewt): Make this dynamic.
- uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
- uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
- uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
+ size_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
+ size_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
+ size_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
// For each embedded MIDI Jack in the descriptor we create a Port
- usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false);
+ usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false, false);
mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr;
ports->base.type = &mp_type_tuple;
diff --git a/shared-module/vectorio/Polygon.c b/shared-module/vectorio/Polygon.c
index 0025d4bfc..e00a4696b 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) {
@@ -128,13 +143,13 @@ uint32_t common_hal_vectorio_polygon_get_pixel(void *obj, int16_t x, int16_t y)
int y2 = self->points_list[i % self->len];
VECTORIO_POLYGON_DEBUG(" (%3d, %3d)}\n", x2, y2);
if ( y1 <= y ) {
- if ( y2 > y && line_side(x1, y1, x2, y2, x, y) > 0 ) {
- // Wind up, point is to the right of the edge vector
+ if ( y2 > y && line_side(x1, y1, x2, y2, x, y) < 0 ) {
+ // Wind up, point is to the left of the edge vector
++winding_number;
VECTORIO_POLYGON_DEBUG(" wind:%2d winding_number:%2d\n", 1, winding_number);
}
- } else if ( y2 <= y && line_side(x1, y1, x2, y2, x, y) < 0 ) {
- // Wind down, point is to the left of the edge vector
+ } else if ( y2 <= y && line_side(x1, y1, x2, y2, x, y) > 0 ) {
+ // Wind down, point is to the right of the edge vector
--winding_number;
VECTORIO_POLYGON_DEBUG(" wind:%2d winding_number:%2d\n", -1, winding_number);
}
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