diff options
| author | Dan Halbert <halbert@halwitz.org> | 2021-01-10 13:52:47 -0500 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2021-01-10 13:52:47 -0500 |
| commit | ce59b543615c502b60fb1c81735ef0a244975678 (patch) | |
| tree | 6dcb40faa1d20cd23d2118d674af5fb05e4a1b20 /shared-module | |
| parent | e1a843878e4272334869b1db4a8222ae344f5cb8 (diff) | |
| parent | 55c80754c76a115e2f128931a408e6702aee6ef4 (diff) | |
Merge remote-tracking branch 'adafruit/main' into robots.txt
Diffstat (limited to 'shared-module')
50 files changed, 1225 insertions, 224 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/_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/_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/board/__init__.c b/shared-module/board/__init__.c index 2c9139d8a..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; @@ -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/canio/Match.h b/shared-module/canio/Match.h new file mode 100644 index 000000000..b52191d7c --- /dev/null +++ b/shared-module/canio/Match.h @@ -0,0 +1,36 @@ +/* + * 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; + 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 46bb6fdb5..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 @@ -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. @@ -419,9 +429,9 @@ 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); } diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h index 861a38fd7..cc9cd54c4 100644 --- a/shared-module/displayio/Display.h +++ b/shared-module/displayio/Display.h @@ -29,8 +29,8 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/displayio/Group.h" -#if CIRCUITPY_PULSEIO -#include "shared-bindings/pulseio/PWMOut.h" +#if CIRCUITPY_PWMIO +#include "shared-bindings/pwmio/PWMOut.h" #endif #include "shared-module/displayio/area.h" @@ -41,8 +41,8 @@ typedef struct { displayio_display_core_t core; union { digitalio_digitalinout_obj_t backlight_inout; - #if CIRCUITPY_PULSEIO - pulseio_pwmout_obj_t backlight_pwm; + #if CIRCUITPY_PWMIO + pwmio_pwmout_obj_t backlight_pwm; #endif }; uint64_t last_backlight_refresh; @@ -60,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 6d9e915b4..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); @@ -197,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 @@ -232,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; @@ -269,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); @@ -352,6 +383,11 @@ 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); @@ -369,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 3b9f6e368..d0668ff44 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -38,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; @@ -55,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 facb1fa73..ba5ff665c 100644 --- a/shared-module/displayio/Palette.c +++ b/shared-module/displayio/Palette.c @@ -83,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 5afcba35e..a9bb3b21b 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -26,7 +26,7 @@ primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT]; -#if CIRCUITPY_RGBMATRIX || CIRCUITPY_SHARPDISPLAY +#if CIRCUITPY_RGBMATRIX 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].display_base.type == &framebufferio_framebufferdisplay_type) { @@ -40,8 +40,6 @@ STATIC bool any_display_uses_this_framebuffer(mp_obj_base_t *obj) { } #endif -// Check for recursive calls to displayio_background. -bool displayio_background_in_progress = false; void displayio_background(void) { if (mp_hal_is_interrupted()) { @@ -52,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) { @@ -75,8 +67,6 @@ void displayio_background(void) { } } - // All done. - displayio_background_in_progress = false; } void common_hal_displayio_release_displays(void) { @@ -186,11 +176,7 @@ void reset_displays(void) { #if CIRCUITPY_SHARPDISPLAY } else if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) { sharpdisplay_framebuffer_obj_t * sharp = &displays[i].sharpdisplay; - if(any_display_uses_this_framebuffer(&sharp->base)) { - common_hal_sharpdisplay_framebuffer_reset(sharp); - } else { - common_hal_sharpdisplay_framebuffer_deinit(sharp); - } + common_hal_sharpdisplay_framebuffer_reset(sharp); #endif } else { // Not an active display bus. @@ -398,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/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 6b5346877..03e121c91 100644 --- a/shared-module/framebufferio/FramebufferDisplay.c +++ b/shared-module/framebufferio/FramebufferDisplay.c @@ -66,7 +66,7 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu ram_height, 0, 0, - rotation, + 0, // rotation depth, fb_getter_default(get_grayscale, (depth < 8)), fb_getter_default(get_pixels_in_byte_share_row, false), @@ -92,7 +92,9 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu 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. @@ -278,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); } diff --git a/shared-module/framebufferio/FramebufferDisplay.h b/shared-module/framebufferio/FramebufferDisplay.h index 89df0d27c..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" 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/ipaddress/IPv4Address.h b/shared-module/ipaddress/IPv4Address.h new file mode 100644 index 000000000..3f2bde091 --- /dev/null +++ b/shared-module/ipaddress/IPv4Address.h @@ -0,0 +1,37 @@ +/* + * 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_IPV4ADDRESS_H +#define MICROPY_INCLUDED_SHARED_MODULE_IPADDRESS_IPV4ADDRESS_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t ip_bytes; +} ipaddress_ipv4address_obj_t; + +#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/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/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c index 71e00d7f0..4b92bd637 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c @@ -38,27 +38,6 @@ #define SHARPMEM_BIT_WRITECMD_LSB (0x80) #define SHARPMEM_BIT_VCOM_LSB (0x40) -static inline void *hybrid_alloc(size_t sz) { - if (gc_alloc_possible()) { - return m_malloc(sz + sizeof(void*), true); - } else { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false); - if (!allocation) { - return NULL; - } - memset(allocation->ptr, 0, sz); - return allocation->ptr; - } -} - -static inline void hybrid_free(void *ptr_in) { - supervisor_allocation *allocation = allocation_from_ptr(ptr_in); - - if (allocation) { - free_memory(allocation); - } -} - STATIC uint8_t bitrev(uint8_t n) { uint8_t r = 0; for(int i=0;i<8;i++) r |= ((n>>i) & 1)<<(7-i); @@ -90,10 +69,6 @@ bool common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(sharpdispl } void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self) { - if (!allocation_from_ptr(self->bufinfo.buf)) { - self->bufinfo.buf = NULL; - } - if (self->bus != &self->inline_bus #if BOARD_SPI && self->bus != common_hal_board_get_spi() @@ -105,7 +80,9 @@ void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *s } 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) { @@ -113,7 +90,12 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob 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; - self->bufinfo.buf = hybrid_alloc(self->bufinfo.len); + 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; @@ -124,7 +106,9 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob } self->full_refresh = true; } - *bufinfo = self->bufinfo; + if (bufinfo) { + *bufinfo = self->bufinfo; + } } void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self) { @@ -138,7 +122,7 @@ void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t * common_hal_reset_pin(self->chip_select.pin); - hybrid_free(self->bufinfo.buf); + free_memory(allocation_from_ptr(self->bufinfo.buf)); memset(self, 0, sizeof(*self)); } @@ -155,18 +139,7 @@ void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_ self->height = height; self->baudrate = baudrate; - int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self); - self->bufinfo.len = row_stride * height + 2; - self->bufinfo.buf = gc_alloc(self->bufinfo.len, false, true); - - uint8_t *data = self->bufinfo.buf; - *data++ = SHARPMEM_BIT_WRITECMD_LSB; - - for(int y=0; y<self->height; y++) { - *data = bitrev(y+1); - data += row_stride; - } - self->full_refresh = true; + common_hal_sharpdisplay_framebuffer_get_bufinfo(self, NULL); } void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask) { @@ -271,7 +244,5 @@ const framebuffer_p_t sharpdisplay_framebuffer_proto = { }; void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *self) { - gc_collect_ptr(self->framebuffer); gc_collect_ptr(self->bus); - gc_collect_ptr(self->bufinfo.buf); } diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h index 8acacc94e..08966a89c 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h @@ -33,7 +33,6 @@ typedef struct { mp_obj_base_t base; - mp_obj_t framebuffer; busio_spi_obj_t* bus; busio_spi_obj_t inline_bus; digitalio_digitalinout_obj_t chip_select; 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/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; |
