From 9fafd7d7fdb979d889cdfffb0314693badaa1d0f Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sat, 4 Dec 2021 12:16:35 -0600 Subject: [PATCH 01/14] Initial commit --- locale/circuitpython.pot | 4 ++ shared-bindings/is31fl3741/__init__.c | 80 +++++++++++++++++++++++++++ shared-bindings/is31fl3741/__init__.h | 40 ++++++++++++++ shared-module/is31fl3741/IS31FL3741.c | 11 ++-- shared-module/is31fl3741/__init__.c | 74 +++++++++++++++++++++++++ 5 files changed, 202 insertions(+), 7 deletions(-) create mode 100644 shared-bindings/is31fl3741/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 835ef9538b96..5047615abf15 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1490,6 +1490,10 @@ msgstr "" msgid "MOSI pin init failed." msgstr "" +#: shared-bindings/is31fl3741/__init__.c +msgid "Mapping must be a tuple" +msgstr "" + #: shared-module/displayio/Shape.c #, c-format msgid "Maximum x value when mirrored is %d" diff --git a/shared-bindings/is31fl3741/__init__.c b/shared-bindings/is31fl3741/__init__.c index 90b9426a4dab..c1e127aecc08 100644 --- a/shared-bindings/is31fl3741/__init__.c +++ b/shared-bindings/is31fl3741/__init__.c @@ -24,16 +24,96 @@ * THE SOFTWARE. */ +#include "shared-bindings/is31fl3741/__init__.h" + #include +#include #include "py/obj.h" #include "py/runtime.h" +#include "shared-bindings/busio/I2C.h" #include "shared-bindings/is31fl3741/IS31FL3741.h" + +//| """Low-level neopixel implementation +//| +//| The `neopixel_write` module contains a helper method to write out bytes in +//| the 800khz neopixel protocol. +//| +//| For example, to turn off a single neopixel (like the status pixel on Express +//| boards.) +//| +//| .. code-block:: python +//| +//| import board +//| import neopixel_write +//| import digitalio +//| +//| pin = digitalio.DigitalInOut(board.NEOPIXEL) +//| pin.direction = digitalio.Direction.OUTPUT +//| pixel_off = bytearray([0, 0, 0]) +//| neopixel_write.neopixel_write(pin, pixel_off)""" +//| +//| def neopixel_write(digitalinout: digitalio.DigitalInOut, buf: ReadableBuffer) -> None: +//| """Write buf out on the given DigitalInOut. +//| +//| :param ~digitalio.DigitalInOut digitalinout: the DigitalInOut to output with +//| :param ~_typing.ReadableBuffer buf: The bytes to clock out. No assumption is made about color order""" +//| ... +// STATIC mp_obj_t is31fl3741_is31fl3741_write(mp_obj_t i2c_obj, mp_obj_t device_addr_obj, mp_obj_t mapping, mp_obj_t buf) { +STATIC mp_obj_t is31fl3741_is31fl3741_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_i2c, ARG_addr, ARG_mapping, ARG_buffer }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x30 } }, + { MP_QSTR_mapping, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_buffer, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); + + if (!mp_obj_is_tuple_compatible(args[ARG_mapping].u_obj)) { + mp_raise_ValueError(translate("Mapping must be a tuple")); + } + + mp_obj_t *map_items; + size_t map_len; + mp_obj_tuple_get(args[ARG_mapping].u_obj, &map_len, &map_items); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + + common_hal_is31fl3741_write(i2c, args[ARG_addr].u_int, map_items, (uint8_t *)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_write_obj, 0, is31fl3741_is31fl3741_write); + +STATIC mp_obj_t is31fl3741_is31fl3741_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_i2c, ARG_addr }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x30 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); + + common_hal_is31fl3741_init(i2c, args[ARG_addr].u_int); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_init_obj, 0, is31fl3741_is31fl3741_init); + STATIC const mp_rom_map_elem_t is31fl3741_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_is31fl3741) }, { MP_ROM_QSTR(MP_QSTR_IS31FL3741), MP_ROM_PTR(&is31fl3741_IS31FL3741_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_is31fl3741_init), (mp_obj_t)&is31fl3741_is31fl3741_init_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_is31fl3741_write), (mp_obj_t)&is31fl3741_is31fl3741_write_obj }, }; STATIC MP_DEFINE_CONST_DICT(is31fl3741_module_globals, is31fl3741_module_globals_table); diff --git a/shared-bindings/is31fl3741/__init__.h b/shared-bindings/is31fl3741/__init__.h new file mode 100644 index 000000000000..ba5c734f14f0 --- /dev/null +++ b/shared-bindings/is31fl3741/__init__.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H + +#include +#include + +#include "shared-bindings/busio/I2C.h" + +extern void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr); +extern void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes); +void begin_transaction(busio_i2c_obj_t *i2c); +void end_transaction(busio_i2c_obj_t *i2c); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H diff --git a/shared-module/is31fl3741/IS31FL3741.c b/shared-module/is31fl3741/IS31FL3741.c index 9d7316e1cdb2..ae2710069486 100644 --- a/shared-module/is31fl3741/IS31FL3741.c +++ b/shared-module/is31fl3741/IS31FL3741.c @@ -115,7 +115,7 @@ void common_hal_is31fl3741_IS31FL3741_reconstruct(is31fl3741_IS31FL3741_obj_t *s is31fl3741_set_current(self->i2c, self->device_address, 0xFF); // set scale (brightness) to max for all LEDs - for (int i; i < 351; i++) { + for (int i = 0; i < 351; i++) { is31fl3741_set_led(self->i2c, self->device_address, i, 0xFF, 2); } @@ -267,11 +267,8 @@ void is31fl3741_IS31FL3741_collect_ptrs(is31fl3741_IS31FL3741_obj_t *self) { gc_collect_ptr(self->mapping); } -// The following are routines to manipulate the IS31FL3741 chip -// They are not meant to be called by user code but only used -// internally. -uint8_t cur_page = 99; // set to invalid page to start +uint8_t is31fl3741_cur_page = 99; // set to invalid page to start void is31fl3741_send_unlock(busio_i2c_obj_t *i2c, uint8_t addr) { uint8_t unlock[2] = { 0xFE, 0xC5 }; // unlock command @@ -279,11 +276,11 @@ void is31fl3741_send_unlock(busio_i2c_obj_t *i2c, uint8_t addr) { } void is31fl3741_set_page(busio_i2c_obj_t *i2c, uint8_t addr, uint8_t p) { - if (p == cur_page) { + if (p == is31fl3741_cur_page) { return; } - cur_page = p; + is31fl3741_cur_page = p; is31fl3741_send_unlock(i2c, addr); uint8_t page[2] = { 0xFD, 0x00 }; // page command diff --git a/shared-module/is31fl3741/__init__.c b/shared-module/is31fl3741/__init__.c index e69de29bb2d1..5a9decfe3f2e 100644 --- a/shared-module/is31fl3741/__init__.c +++ b/shared-module/is31fl3741/__init__.c @@ -0,0 +1,74 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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/is31fl3741/__init__.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/is31fl3741/IS31FL3741.h" + +void begin_transaction(busio_i2c_obj_t *i2c) { + while (!common_hal_busio_i2c_try_lock(i2c)) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + break; + } + } +} + +void end_transaction(busio_i2c_obj_t *i2c) { + common_hal_busio_i2c_unlock(i2c); +} + +void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr) { + begin_transaction(i2c); + + uint8_t command = 0xFC; // device ID + common_hal_busio_i2c_write(i2c, addr, &command, 1, false); + uint8_t data = 0; + common_hal_busio_i2c_read(i2c, addr, &data, 1); + + is31fl3741_send_reset(i2c, addr); + is31fl3741_send_enable(i2c, addr); + is31fl3741_set_current(i2c, addr, 0xFF); + + // set scale (brightness) to max for all LEDs + for (int i = 0; i < 351; i++) { + is31fl3741_set_led(i2c, addr, i, 0xFF, 2); + } + + end_transaction(i2c); +} + +void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes) { + for (size_t i = 0; i < numBytes; i += 3) { + uint16_t ridx = mp_obj_get_int(mapping[i]); + if (ridx != 65535) { + is31fl3741_set_led(i2c, addr, ridx, IS31GammaTable[pixels[i]], 0); // red + is31fl3741_set_led(i2c, addr, mp_obj_get_int(mapping[i + 1]), IS31GammaTable[pixels[i + 1]], 0); // green + is31fl3741_set_led(i2c, addr, mp_obj_get_int(mapping[i + 2]), IS31GammaTable[pixels[i + 2]], 0); // blue + } + } +} From 11ef0b48c0f4b6d2ab82af74be250d8bd9da5b39 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Wed, 8 Dec 2021 19:28:04 -0600 Subject: [PATCH 02/14] Change map to tuple to save memory and match _write --- shared-module/is31fl3741/IS31FL3741.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-module/is31fl3741/IS31FL3741.c b/shared-module/is31fl3741/IS31FL3741.c index ae2710069486..8cd169f8e8a7 100644 --- a/shared-module/is31fl3741/IS31FL3741.c +++ b/shared-module/is31fl3741/IS31FL3741.c @@ -61,7 +61,7 @@ void common_hal_is31fl3741_IS31FL3741_construct(is31fl3741_IS31FL3741_obj_t *sel mp_obj_t *items; size_t len; - mp_obj_list_get(mapping, &len, &items); + mp_obj_tuple_get(mapping, &len, &items); if (len != (size_t)(self->scale_width * self->scale_height * 3)) { mp_raise_ValueError(translate("LED mappings must match display size")); From 7c1afb070afcfa3224e142fae4cc3fc85c189d8b Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Wed, 8 Dec 2021 21:36:19 -0600 Subject: [PATCH 03/14] Documentation fixes --- shared-bindings/is31fl3741/__init__.c | 35 +++++++++++---------------- shared-bindings/is31fl3741/__init__.h | 4 +-- shared-module/is31fl3741/__init__.c | 12 ++++++--- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/shared-bindings/is31fl3741/__init__.c b/shared-bindings/is31fl3741/__init__.c index c1e127aecc08..465fbdd86fe6 100644 --- a/shared-bindings/is31fl3741/__init__.c +++ b/shared-bindings/is31fl3741/__init__.c @@ -36,32 +36,19 @@ #include "shared-bindings/is31fl3741/IS31FL3741.h" -//| """Low-level neopixel implementation +//| """Low-level is31fl3741 implementation //| -//| The `neopixel_write` module contains a helper method to write out bytes in -//| the 800khz neopixel protocol. +//| The `is31fl3741_write` module contains a helper method to write out bytes in +//| over the I2C bus. //| -//| For example, to turn off a single neopixel (like the status pixel on Express -//| boards.) +//| def is31fl3741_write(i2c: busio.I2c, addr: int, mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: +//| """Write buf out on the given I2C bus. //| -//| .. code-block:: python -//| -//| import board -//| import neopixel_write -//| import digitalio -//| -//| pin = digitalio.DigitalInOut(board.NEOPIXEL) -//| pin.direction = digitalio.Direction.OUTPUT -//| pixel_off = bytearray([0, 0, 0]) -//| neopixel_write.neopixel_write(pin, pixel_off)""" -//| -//| def neopixel_write(digitalinout: digitalio.DigitalInOut, buf: ReadableBuffer) -> None: -//| """Write buf out on the given DigitalInOut. -//| -//| :param ~digitalio.DigitalInOut digitalinout: the DigitalInOut to output with +//| :param ~busio.I2C i2c: the I2C bus to output with +//| :param ~int addr: the I2C address of the IS31FL3741 device +//| :param ~Tuple[int, ...] mapping: map the pixels in the buffer to the order addressed by the driver chip //| :param ~_typing.ReadableBuffer buf: The bytes to clock out. No assumption is made about color order""" //| ... -// STATIC mp_obj_t is31fl3741_is31fl3741_write(mp_obj_t i2c_obj, mp_obj_t device_addr_obj, mp_obj_t mapping, mp_obj_t buf) { STATIC mp_obj_t is31fl3741_is31fl3741_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_i2c, ARG_addr, ARG_mapping, ARG_buffer }; static const mp_arg_t allowed_args[] = { @@ -92,6 +79,12 @@ STATIC mp_obj_t is31fl3741_is31fl3741_write(size_t n_args, const mp_obj_t *pos_a } MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_write_obj, 0, is31fl3741_is31fl3741_write); +//| def is31fl3741_init(i2c: busio.I2c, addr: int) -> None: +//| """Initialize the IS31FL3741 device. +//| +//| :param ~busio.I2C i2c: the I2C bus to output with +//| :param ~int addr: the I2C address of the IS31FL3741 device +//| ... STATIC mp_obj_t is31fl3741_is31fl3741_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_i2c, ARG_addr }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/is31fl3741/__init__.h b/shared-bindings/is31fl3741/__init__.h index ba5c734f14f0..cf4e2bcee67a 100644 --- a/shared-bindings/is31fl3741/__init__.h +++ b/shared-bindings/is31fl3741/__init__.h @@ -34,7 +34,7 @@ extern void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr); extern void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes); -void begin_transaction(busio_i2c_obj_t *i2c); -void end_transaction(busio_i2c_obj_t *i2c); +void is31fl3741_begin_transaction(busio_i2c_obj_t *i2c); +void is31fl3741_end_transaction(busio_i2c_obj_t *i2c); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H diff --git a/shared-module/is31fl3741/__init__.c b/shared-module/is31fl3741/__init__.c index 5a9decfe3f2e..e6808bba45db 100644 --- a/shared-module/is31fl3741/__init__.c +++ b/shared-module/is31fl3741/__init__.c @@ -29,7 +29,7 @@ #include "shared-bindings/busio/I2C.h" #include "shared-bindings/is31fl3741/IS31FL3741.h" -void begin_transaction(busio_i2c_obj_t *i2c) { +void is31fl3741_begin_transaction(busio_i2c_obj_t *i2c) { while (!common_hal_busio_i2c_try_lock(i2c)) { RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { @@ -38,12 +38,12 @@ void begin_transaction(busio_i2c_obj_t *i2c) { } } -void end_transaction(busio_i2c_obj_t *i2c) { +void is31fl3741_end_transaction(busio_i2c_obj_t *i2c) { common_hal_busio_i2c_unlock(i2c); } void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr) { - begin_transaction(i2c); + is31fl3741_begin_transaction(i2c); uint8_t command = 0xFC; // device ID common_hal_busio_i2c_write(i2c, addr, &command, 1, false); @@ -59,10 +59,12 @@ void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr) { is31fl3741_set_led(i2c, addr, i, 0xFF, 2); } - end_transaction(i2c); + is31fl3741_end_transaction(i2c); } void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes) { + is31fl3741_begin_transaction(i2c); + for (size_t i = 0; i < numBytes; i += 3) { uint16_t ridx = mp_obj_get_int(mapping[i]); if (ridx != 65535) { @@ -71,4 +73,6 @@ void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_ob is31fl3741_set_led(i2c, addr, mp_obj_get_int(mapping[i + 2]), IS31GammaTable[pixels[i + 2]], 0); // blue } } + + is31fl3741_end_transaction(i2c); } From bb8ad7f61112c82440b0cb0076c398c7c8ef3b39 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Tue, 14 Dec 2021 22:44:27 -0600 Subject: [PATCH 04/14] Fixed doc --- shared-bindings/is31fl3741/__init__.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared-bindings/is31fl3741/__init__.c b/shared-bindings/is31fl3741/__init__.c index 465fbdd86fe6..8ccbd2e37f03 100644 --- a/shared-bindings/is31fl3741/__init__.c +++ b/shared-bindings/is31fl3741/__init__.c @@ -39,9 +39,9 @@ //| """Low-level is31fl3741 implementation //| //| The `is31fl3741_write` module contains a helper method to write out bytes in -//| over the I2C bus. +//| over the I2C bus.""" //| -//| def is31fl3741_write(i2c: busio.I2c, addr: int, mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: +//| def is31fl3741_write(i2c: busio.I2C, addr: int, mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: //| """Write buf out on the given I2C bus. //| //| :param ~busio.I2C i2c: the I2C bus to output with @@ -83,7 +83,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_write_obj, 0, is31fl3741_is31fl //| """Initialize the IS31FL3741 device. //| //| :param ~busio.I2C i2c: the I2C bus to output with -//| :param ~int addr: the I2C address of the IS31FL3741 device +//| :param ~int addr: the I2C address of the IS31FL3741 device""" //| ... STATIC mp_obj_t is31fl3741_is31fl3741_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_i2c, ARG_addr }; From cf2c8eeec4710b7a5ee054e9f73ddd589f296c8e Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Mon, 17 Jan 2022 16:13:27 -0600 Subject: [PATCH 05/14] Moved init functions to helper python library --- shared-bindings/is31fl3741/__init__.c | 30 --------------------------- shared-bindings/is31fl3741/__init__.h | 1 - shared-module/is31fl3741/__init__.c | 20 ------------------ 3 files changed, 51 deletions(-) diff --git a/shared-bindings/is31fl3741/__init__.c b/shared-bindings/is31fl3741/__init__.c index 8ccbd2e37f03..72b8806c495c 100644 --- a/shared-bindings/is31fl3741/__init__.c +++ b/shared-bindings/is31fl3741/__init__.c @@ -35,12 +35,6 @@ #include "shared-bindings/busio/I2C.h" #include "shared-bindings/is31fl3741/IS31FL3741.h" - -//| """Low-level is31fl3741 implementation -//| -//| The `is31fl3741_write` module contains a helper method to write out bytes in -//| over the I2C bus.""" -//| //| def is31fl3741_write(i2c: busio.I2C, addr: int, mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: //| """Write buf out on the given I2C bus. //| @@ -79,33 +73,9 @@ STATIC mp_obj_t is31fl3741_is31fl3741_write(size_t n_args, const mp_obj_t *pos_a } MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_write_obj, 0, is31fl3741_is31fl3741_write); -//| def is31fl3741_init(i2c: busio.I2c, addr: int) -> None: -//| """Initialize the IS31FL3741 device. -//| -//| :param ~busio.I2C i2c: the I2C bus to output with -//| :param ~int addr: the I2C address of the IS31FL3741 device""" -//| ... -STATIC mp_obj_t is31fl3741_is31fl3741_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_i2c, ARG_addr }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_i2c, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x30 } }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); - - common_hal_is31fl3741_init(i2c, args[ARG_addr].u_int); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_init_obj, 0, is31fl3741_is31fl3741_init); - STATIC const mp_rom_map_elem_t is31fl3741_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_is31fl3741) }, { MP_ROM_QSTR(MP_QSTR_IS31FL3741), MP_ROM_PTR(&is31fl3741_IS31FL3741_type) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_is31fl3741_init), (mp_obj_t)&is31fl3741_is31fl3741_init_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_is31fl3741_write), (mp_obj_t)&is31fl3741_is31fl3741_write_obj }, }; diff --git a/shared-bindings/is31fl3741/__init__.h b/shared-bindings/is31fl3741/__init__.h index cf4e2bcee67a..d451b3c389cf 100644 --- a/shared-bindings/is31fl3741/__init__.h +++ b/shared-bindings/is31fl3741/__init__.h @@ -32,7 +32,6 @@ #include "shared-bindings/busio/I2C.h" -extern void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr); extern void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes); void is31fl3741_begin_transaction(busio_i2c_obj_t *i2c); void is31fl3741_end_transaction(busio_i2c_obj_t *i2c); diff --git a/shared-module/is31fl3741/__init__.c b/shared-module/is31fl3741/__init__.c index e6808bba45db..abe03566367d 100644 --- a/shared-module/is31fl3741/__init__.c +++ b/shared-module/is31fl3741/__init__.c @@ -42,26 +42,6 @@ void is31fl3741_end_transaction(busio_i2c_obj_t *i2c) { common_hal_busio_i2c_unlock(i2c); } -void common_hal_is31fl3741_init(busio_i2c_obj_t *i2c, uint8_t addr) { - is31fl3741_begin_transaction(i2c); - - uint8_t command = 0xFC; // device ID - common_hal_busio_i2c_write(i2c, addr, &command, 1, false); - uint8_t data = 0; - common_hal_busio_i2c_read(i2c, addr, &data, 1); - - is31fl3741_send_reset(i2c, addr); - is31fl3741_send_enable(i2c, addr); - is31fl3741_set_current(i2c, addr, 0xFF); - - // set scale (brightness) to max for all LEDs - for (int i = 0; i < 351; i++) { - is31fl3741_set_led(i2c, addr, i, 0xFF, 2); - } - - is31fl3741_end_transaction(i2c); -} - void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes) { is31fl3741_begin_transaction(i2c); From 563d8f297ce3d3e809edaf575ff39de0ae9db96d Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sun, 23 Jan 2022 13:12:37 -0600 Subject: [PATCH 06/14] Major refractor to make a common base object --- py/circuitpy_defns.mk | 1 + shared-bindings/is31fl3741/FrameBuffer.c | 303 ++++++++++++++++++ shared-bindings/is31fl3741/FrameBuffer.h | 50 +++ shared-bindings/is31fl3741/IS31FL3741.c | 261 +++------------ shared-bindings/is31fl3741/IS31FL3741.h | 36 +-- shared-bindings/is31fl3741/__init__.c | 43 +-- shared-module/displayio/__init__.c | 43 ++- shared-module/displayio/__init__.h | 4 +- shared-module/is31fl3741/FrameBuffer.c | 227 +++++++++++++ .../is31fl3741/FrameBuffer.h | 31 +- shared-module/is31fl3741/IS31FL3741.c | 260 +++------------ shared-module/is31fl3741/IS31FL3741.h | 8 - shared-module/is31fl3741/__init__.c | 33 -- 13 files changed, 729 insertions(+), 571 deletions(-) create mode 100644 shared-bindings/is31fl3741/FrameBuffer.c create mode 100644 shared-bindings/is31fl3741/FrameBuffer.h create mode 100644 shared-module/is31fl3741/FrameBuffer.c rename shared-bindings/is31fl3741/__init__.h => shared-module/is31fl3741/FrameBuffer.h (64%) diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index e8834816757f..ab654aac64b8 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -555,6 +555,7 @@ SRC_SHARED_MODULE_ALL = \ ipaddress/IPv4Address.c \ ipaddress/__init__.c \ is31fl3741/IS31FL3741.c \ + is31fl3741/FrameBuffer.c \ is31fl3741/__init__.c \ keypad/__init__.c \ keypad/Event.c \ diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c new file mode 100644 index 000000000000..37372a2aeabc --- /dev/null +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -0,0 +1,303 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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 "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/objarray.h" + +#include "shared-bindings/is31fl3741/IS31FL3741.h" +#include "shared-bindings/is31fl3741/FrameBuffer.h" +#include "shared-bindings/util.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/framebufferio/__init__.h" +#include "shared-module/framebufferio/FramebufferDisplay.h" +#include "shared-bindings/busio/I2C.h" + +//| class IS31FL3741_FrameBuffer: +//| """Displays an in-memory framebuffer to a IS31FL3741 drive display.""" +//| + +//| def __init__(self, *, width: int) -> None: +//| """Create a IS31FL3741 object with the given attributes. +//| +//| The framebuffer is in "RGB888" format using 4 bytes per pixel. +//| Bits 24-31 are ignored. The format is in RGB order. +//| +//| If a framebuffer is not passed in, one is allocated and initialized +//| to all black. In any case, the framebuffer can be retrieved +//| by passing the Is31fl3741 object to memoryview(). +//| +//| A Is31fl3741 is often used in conjunction with a +//| `framebufferio.FramebufferDisplay`.""" +//| +STATIC mp_obj_t is31fl3741_FrameBuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_is31, ARG_width, ARG_height, ARG_framebuffer, ARG_mapping, ARG_scale, ARG_gamma }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_is31, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_framebuffer, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = mp_const_none } }, + { MP_QSTR_mapping, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_scale, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, + { MP_QSTR_gamma, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + is31fl3741_FrameBuffer_obj_t *self = &allocate_display_bus_or_raise()->is31fl3741; + self->base.type = &is31fl3741_FrameBuffer_type; + + if (args[ARG_width].u_int <= 0) { + mp_raise_ValueError(translate("width must be greater than zero")); + } + + self->scale = args[ARG_scale].u_bool; + if (self->scale) { + if (((args[ARG_height].u_int % 3) != 0) || ((args[ARG_width].u_int % 3) != 0)) { + mp_raise_ValueError(translate("Scale dimensions must divide by 3")); + } + + self->scale_width = args[ARG_width].u_int / 3; + self->scale_height = args[ARG_height].u_int / 3; + } else { + self->scale_width = args[ARG_width].u_int; + self->scale_height = args[ARG_height].u_int; + } + + self->auto_gamma = args[ARG_gamma].u_bool; + + mp_obj_t framebuffer = args[ARG_framebuffer].u_obj; + if (framebuffer == mp_const_none) { + int width = args[ARG_width].u_int; + int height = args[ARG_height].u_int; + int bufsize = 4 * width * height; + framebuffer = mp_obj_new_bytearray_of_zeros(bufsize); + } + + common_hal_is31fl3741_FrameBuffer_construct(self, + args[ARG_width].u_int, + args[ARG_height].u_int, + framebuffer, + args[ARG_is31].u_obj, + args[ARG_mapping].u_obj + ); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Free the resources associated with this +//| IS31FL3741 instance. After deinitialization, no further operations +//| may be performed.""" +//| ... +//| +STATIC mp_obj_t is31fl3741_FrameBuffer_deinit(mp_obj_t self_in) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + common_hal_is31fl3741_FrameBuffer_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_FrameBuffer_deinit_obj, is31fl3741_FrameBuffer_deinit); + +static void check_for_deinit(is31fl3741_FrameBuffer_obj_t *self) { + if (self->framebuffer == NULL) { + raise_deinited_error(); + } +} + +//| brightness: float +//| """In the current implementation, 0.0 turns the display off entirely +//| and any other value up to 1.0 turns the display on fully.""" +//| +STATIC mp_obj_t is31fl3741_FrameBuffer_get_brightness(mp_obj_t self_in) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + check_for_deinit(self); + uint8_t current = common_hal_is31fl3741_get_current(self->is31fl3741); + + float brightness = (float)current / (float)0xFF; + return mp_obj_new_float(brightness); +} +MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_FrameBuffer_get_brightness_obj, is31fl3741_FrameBuffer_get_brightness); + +STATIC mp_obj_t is31fl3741_FrameBuffer_set_brightness(mp_obj_t self_in, mp_obj_t value_in) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + check_for_deinit(self); + mp_float_t brightness = mp_obj_get_float(value_in); + if (brightness < 0.0f || brightness > 1.0f) { + mp_raise_ValueError(translate("Brightness must be 0-1.0")); + } + + uint8_t current = (uint8_t)(brightness * 0xFF); + common_hal_is31fl3741_set_current(self->is31fl3741, current); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_FrameBuffer_set_brightness_obj, is31fl3741_FrameBuffer_set_brightness); + +const mp_obj_property_t is31fl3741_FrameBuffer_brightness_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&is31fl3741_FrameBuffer_get_brightness_obj, + (mp_obj_t)&is31fl3741_FrameBuffer_set_brightness_obj, + MP_ROM_NONE}, +}; + +//| def refresh(self) -> None: +//| """Transmits the color data in the buffer to the pixels so that +//| they are shown.""" +//| ... +//| +STATIC mp_obj_t is31fl3741_FrameBuffer_refresh(mp_obj_t self_in) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + check_for_deinit(self); + common_hal_is31fl3741_FrameBuffer_refresh(self, 0); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_FrameBuffer_refresh_obj, is31fl3741_FrameBuffer_refresh); + +//| width: int +//| """The width of the display, in pixels""" +//| +STATIC mp_obj_t is31fl3741_FrameBuffer_get_width(mp_obj_t self_in) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_is31fl3741_FrameBuffer_get_width(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_FrameBuffer_get_width_obj, is31fl3741_FrameBuffer_get_width); +const mp_obj_property_t is31fl3741_FrameBuffer_width_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&is31fl3741_FrameBuffer_get_width_obj, + MP_ROM_NONE, + MP_ROM_NONE}, +}; + +//| height: int +//| """The height of the display, in pixels""" +//| +STATIC mp_obj_t is31fl3741_FrameBuffer_get_height(mp_obj_t self_in) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_is31fl3741_FrameBuffer_get_height(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_FrameBuffer_get_height_obj, is31fl3741_FrameBuffer_get_height); +const mp_obj_property_t is31fl3741_FrameBuffer_height_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&is31fl3741_FrameBuffer_get_height_obj, + MP_ROM_NONE, + MP_ROM_NONE}, +}; + +STATIC const mp_rom_map_elem_t is31fl3741_FrameBuffer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&is31fl3741_FrameBuffer_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&is31fl3741_FrameBuffer_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&is31fl3741_FrameBuffer_refresh_obj) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&is31fl3741_FrameBuffer_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&is31fl3741_FrameBuffer_height_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(is31fl3741_FrameBuffer_locals_dict, is31fl3741_FrameBuffer_locals_dict_table); + +STATIC void is31fl3741_FrameBuffer_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + check_for_deinit(self); + + *bufinfo = self->bufinfo; +} + +STATIC void is31fl3741_FrameBuffer_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmap) { + common_hal_is31fl3741_FrameBuffer_refresh(self_in, dirty_row_bitmap); +} + +STATIC void is31fl3741_FrameBuffer_deinit_proto(mp_obj_t self_in) { + common_hal_is31fl3741_FrameBuffer_deinit(self_in); +} + +STATIC float is31fl3741_FrameBuffer_get_brightness_proto(mp_obj_t self_in) { + return common_hal_is31fl3741_FrameBuffer_get_paused(self_in) ? 0.0f : 1.0f; +} + +STATIC bool is31fl3741_FrameBuffer_set_brightness_proto(mp_obj_t self_in, mp_float_t value) { + common_hal_is31fl3741_FrameBuffer_set_paused(self_in, value <= 0); + return true; +} + +STATIC int is31fl3741_FrameBuffer_get_width_proto(mp_obj_t self_in) { + return common_hal_is31fl3741_FrameBuffer_get_width(self_in); +} + +STATIC int is31fl3741_FrameBuffer_get_height_proto(mp_obj_t self_in) { + return common_hal_is31fl3741_FrameBuffer_get_height(self_in); +} + +STATIC int is31fl3741_FrameBuffer_get_color_depth_proto(mp_obj_t self_in) { + // The way displayio works depth is used to calculate bytes + // We use an uint32_t for color already so setting to 24 causes + // more changes required + return 32; +} + +STATIC int is31fl3741_FrameBuffer_get_bytes_per_cell_proto(mp_obj_t self_in) { + return 1; +} + +STATIC int is31fl3741_FrameBuffer_get_native_frames_per_second_proto(mp_obj_t self_in) { + return 60; // This was just chosen may vary based on LEDs used? +} + +STATIC const framebuffer_p_t is31fl3741_FrameBuffer_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer) + .get_bufinfo = is31fl3741_FrameBuffer_get_bufinfo, + .set_brightness = is31fl3741_FrameBuffer_set_brightness_proto, + .get_brightness = is31fl3741_FrameBuffer_get_brightness_proto, + .get_width = is31fl3741_FrameBuffer_get_width_proto, + .get_height = is31fl3741_FrameBuffer_get_height_proto, + .get_color_depth = is31fl3741_FrameBuffer_get_color_depth_proto, + .get_bytes_per_cell = is31fl3741_FrameBuffer_get_bytes_per_cell_proto, + .get_native_frames_per_second = is31fl3741_FrameBuffer_get_native_frames_per_second_proto, + .swapbuffers = is31fl3741_FrameBuffer_swapbuffers, + .deinit = is31fl3741_FrameBuffer_deinit_proto, +}; + +STATIC mp_int_t is31fl3741_FrameBuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + is31fl3741_FrameBuffer_obj_t *self = (is31fl3741_FrameBuffer_obj_t *)self_in; + // a readonly framebuffer would be unusual but not impossible + if ((flags & MP_BUFFER_WRITE) && !(self->bufinfo.typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) { + return 1; + } + *bufinfo = self->bufinfo; + bufinfo->typecode = 'H'; + return 0; +} + +const mp_obj_type_t is31fl3741_FrameBuffer_type = { + { &mp_type_type }, + .flags = MP_TYPE_FLAG_EXTENDED, + .name = MP_QSTR_is31fl3741, + .locals_dict = (mp_obj_dict_t *)&is31fl3741_FrameBuffer_locals_dict, + .make_new = is31fl3741_FrameBuffer_make_new, + MP_TYPE_EXTENDED_FIELDS( + .buffer_p = { .get_buffer = is31fl3741_FrameBuffer_get_buffer, }, + .protocol = &is31fl3741_FrameBuffer_proto, + ), +}; diff --git a/shared-bindings/is31fl3741/FrameBuffer.h b/shared-bindings/is31fl3741/FrameBuffer.h new file mode 100644 index 000000000000..704913b83cca --- /dev/null +++ b/shared-bindings/is31fl3741/FrameBuffer.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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. + */ + +#pragma once + +#include "shared-module/is31fl3741/FrameBuffer.h" +#include "shared-module/is31fl3741/IS31FL3741.h" + +extern const mp_obj_type_t is31fl3741_FrameBuffer_type; + +void common_hal_is31fl3741_FrameBuffer_construct(is31fl3741_FrameBuffer_obj_t *self, int width, int height, mp_obj_t framebuffer, is31fl3741_IS31FL3741_obj_t *is31, mp_obj_t mapping); + +void common_hal_is31fl3741_FrameBuffer_deinit(is31fl3741_FrameBuffer_obj_t *); + +int common_hal_is31fl3741_FrameBuffer_get_width(is31fl3741_FrameBuffer_obj_t *self); +int common_hal_is31fl3741_FrameBuffer_get_height(is31fl3741_FrameBuffer_obj_t *self); + +void common_hal_is31fl3741_FrameBuffer_set_global_current(is31fl3741_FrameBuffer_obj_t *self, uint8_t current); +uint8_t common_hal_is31fl3741_FrameBuffer_get_global_current(is31fl3741_FrameBuffer_obj_t *self); + +void common_hal_is31fl3741_FrameBuffer_set_paused(is31fl3741_FrameBuffer_obj_t *self, bool paused); +bool common_hal_is31fl3741_FrameBuffer_get_paused(is31fl3741_FrameBuffer_obj_t *self); +void common_hal_is31fl3741_FrameBuffer_refresh(is31fl3741_FrameBuffer_obj_t *self, uint8_t *dirtyrows); + +void common_hal_is31fl3741_FrameBuffer_reconstruct(is31fl3741_FrameBuffer_obj_t *self, mp_obj_t framebuffer); + +void is31fl3741_FrameBuffer_collect_ptrs(is31fl3741_FrameBuffer_obj_t *self); diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 758dd114a010..15076a97a873 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -32,82 +32,35 @@ #include "shared-bindings/is31fl3741/IS31FL3741.h" #include "shared-bindings/util.h" #include "shared-module/displayio/__init__.h" -#include "shared-module/framebufferio/__init__.h" -#include "shared-module/framebufferio/FramebufferDisplay.h" #include "shared-bindings/busio/I2C.h" //| class IS31FL3741: -//| """Displays an in-memory framebuffer to a IS31FL3741 drive display.""" +//| """Driver for a IS31FL3741 device.""" //| //| def __init__(self, *, width: int) -> None: //| """Create a IS31FL3741 object with the given attributes. //| -//| The framebuffer is in "RGB888" format using 4 bytes per pixel. -//| Bits 24-31 are ignored. The format is in RGB order. +//| Designed to work low level or passed to and object such as +//| `is31fl3741.IS31FL3741_FrameBuffer`.""" //| -//| If a framebuffer is not passed in, one is allocated and initialized -//| to all black. In any case, the framebuffer can be retrieved -//| by passing the Is31fl3741 object to memoryview(). -//| -//| A Is31fl3741 is often used in conjunction with a -//| `framebufferio.FramebufferDisplay`.""" -//| - STATIC mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_width, ARG_height, ARG_i2c, ARG_addr, ARG_framebuffer, ARG_mapping, ARG_scale, ARG_gamma }; + enum { ARG_i2c, ARG_addr }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, - { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, { MP_QSTR_i2c, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, { MP_QSTR_addr, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 0x30 } }, - { MP_QSTR_framebuffer, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = mp_const_none } }, - { MP_QSTR_mapping, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, - { MP_QSTR_scale, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, - { MP_QSTR_gamma, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); - is31fl3741_IS31FL3741_obj_t *self = &allocate_display_bus_or_raise()->is31fl3741; + is31fl3741_IS31FL3741_obj_t *self = m_new_obj(is31fl3741_IS31FL3741_obj_t); self->base.type = &is31fl3741_IS31FL3741_type; - if (args[ARG_width].u_int <= 0) { - mp_raise_ValueError(translate("width must be greater than zero")); - } - - self->scale = args[ARG_scale].u_bool; - if (self->scale) { - if (((args[ARG_height].u_int % 3) != 0) || ((args[ARG_width].u_int % 3) != 0)) { - mp_raise_ValueError(translate("Scale dimensions must divide by 3")); - } - - self->scale_width = args[ARG_width].u_int / 3; - self->scale_height = args[ARG_height].u_int / 3; - } else { - self->scale_width = args[ARG_width].u_int; - self->scale_height = args[ARG_height].u_int; - } - - self->auto_gamma = args[ARG_gamma].u_bool; - - mp_obj_t framebuffer = args[ARG_framebuffer].u_obj; - if (framebuffer == mp_const_none) { - int width = args[ARG_width].u_int; - int height = args[ARG_height].u_int; - int bufsize = 4 * width * height; - framebuffer = mp_obj_new_bytearray_of_zeros(bufsize); - } - common_hal_is31fl3741_IS31FL3741_construct(self, - args[ARG_width].u_int, - args[ARG_height].u_int, - framebuffer, MP_OBJ_TO_PTR(i2c), - args[ARG_addr].u_int, - args[ARG_mapping].u_obj + args[ARG_addr].u_int ); return MP_OBJ_FROM_PTR(self); @@ -124,185 +77,77 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_deinit(mp_obj_t self_in) { common_hal_is31fl3741_IS31FL3741_deinit(self); return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_deinit_obj, is31fl3741_IS31FL3741_deinit); -static void check_for_deinit(is31fl3741_IS31FL3741_obj_t *self) { - if (self->framebuffer == NULL) { - raise_deinited_error(); - } +STATIC mp_obj_t is31fl3741_IS31FL3741_reset(mp_obj_t self_in) { + is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_is31fl3741_send_reset(self); + return mp_const_none; } +MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_reset_obj, is31fl3741_IS31FL3741_reset); -//| brightness: float -//| """In the current implementation, 0.0 turns the display off entirely -//| and any other value up to 1.0 turns the display on fully.""" -//| -STATIC mp_obj_t is31fl3741_IS31FL3741_get_brightness(mp_obj_t self_in) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - check_for_deinit(self); - uint8_t current = common_hal_is31fl3741_IS31FL3741_get_global_current(self); - - float brightness = (float)current / (float)0xFF; - return mp_obj_new_float(brightness); +STATIC mp_obj_t is31fl3741_IS31FL3741_enable(mp_obj_t self_in) { + is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_is31fl3741_send_enable(self); + return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_get_brightness_obj, is31fl3741_IS31FL3741_get_brightness); - -STATIC mp_obj_t is31fl3741_IS31FL3741_set_brightness(mp_obj_t self_in, mp_obj_t value_in) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - check_for_deinit(self); - mp_float_t brightness = mp_obj_get_float(value_in); - if (brightness < 0.0f || brightness > 1.0f) { - mp_raise_ValueError(translate("Brightness must be 0-1.0")); - } - - uint8_t current = (uint8_t)(brightness * 0xFF); - common_hal_is31fl3741_IS31FL3741_set_global_current(self, current); +MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_enable_obj, is31fl3741_IS31FL3741_enable); +STATIC mp_obj_t is31fl3741_IS31FL3741_set_global_current(mp_obj_t self_in, mp_obj_t value) { + is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t current = mp_obj_get_int(value); + common_hal_is31fl3741_set_current(self, current); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_IS31FL3741_set_brightness_obj, is31fl3741_IS31FL3741_set_brightness); - -const mp_obj_property_t is31fl3741_IS31FL3741_brightness_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&is31fl3741_IS31FL3741_get_brightness_obj, - (mp_obj_t)&is31fl3741_IS31FL3741_set_brightness_obj, - MP_ROM_NONE}, -}; +MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_IS31FL3741_set_global_current_obj, is31fl3741_IS31FL3741_set_global_current); -//| def refresh(self) -> None: -//| """Transmits the color data in the buffer to the pixels so that -//| they are shown.""" -//| ... -//| -STATIC mp_obj_t is31fl3741_IS31FL3741_refresh(mp_obj_t self_in) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - check_for_deinit(self); - common_hal_is31fl3741_IS31FL3741_refresh(self, 0); +STATIC mp_obj_t is31fl3741_IS31FL3741_set_led(size_t n_args, const mp_obj_t *args) { + is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t led = mp_obj_get_int(args[1]); + mp_int_t value = mp_obj_get_int(args[2]); + mp_int_t page = mp_obj_get_int(args[3]); + common_hal_is31fl3741_set_led(self, led, value, page); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_refresh_obj, is31fl3741_IS31FL3741_refresh); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(is31fl3741_IS31FL3741_set_led_obj, 4, 4, is31fl3741_IS31FL3741_set_led); -//| width: int -//| """The width of the display, in pixels""" +//| def is31fl3741_write(mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: +//| """Write buf out on the I2C bus to the IS31FL3741. //| -STATIC mp_obj_t is31fl3741_IS31FL3741_get_width(mp_obj_t self_in) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_is31fl3741_IS31FL3741_get_width(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_get_width_obj, is31fl3741_IS31FL3741_get_width); -const mp_obj_property_t is31fl3741_IS31FL3741_width_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&is31fl3741_IS31FL3741_get_width_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; +//| :param ~Tuple[int, ...] mapping: map the pixels in the buffer to the order addressed by the driver chip +//| :param ~_typing.ReadableBuffer buf: The bytes to clock out. No assumption is made about color order""" +//| ... +STATIC mp_obj_t is31fl3741_IS31FL3741_write(mp_obj_t self_in, mp_obj_t mapping, mp_obj_t buffer) { + is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (!mp_obj_is_tuple_compatible(mapping)) { + mp_raise_ValueError(translate("Mapping must be a tuple")); + } -//| height: int -//| """The height of the display, in pixels""" -//| -STATIC mp_obj_t is31fl3741_IS31FL3741_get_height(mp_obj_t self_in) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_is31fl3741_IS31FL3741_get_height(self)); + mp_obj_t *map_items; + size_t map_len; + mp_obj_tuple_get(mapping, &map_len, &map_items); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); + + common_hal_is31fl3741_write(self, map_items, (uint8_t *)bufinfo.buf, bufinfo.len); + return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_get_height_obj, is31fl3741_IS31FL3741_get_height); -const mp_obj_property_t is31fl3741_IS31FL3741_height_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&is31fl3741_IS31FL3741_get_height_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; +MP_DEFINE_CONST_FUN_OBJ_3(is31fl3741_IS31FL3741_write_obj, is31fl3741_IS31FL3741_write); STATIC const mp_rom_map_elem_t is31fl3741_IS31FL3741_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&is31fl3741_IS31FL3741_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&is31fl3741_IS31FL3741_brightness_obj) }, - { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&is31fl3741_IS31FL3741_refresh_obj) }, - { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&is31fl3741_IS31FL3741_width_obj) }, - { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&is31fl3741_IS31FL3741_height_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&is31fl3741_IS31FL3741_write_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&is31fl3741_IS31FL3741_reset_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&is31fl3741_IS31FL3741_enable_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_set_global_current), (mp_obj_t)&is31fl3741_IS31FL3741_set_global_current_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_set_led), (mp_obj_t)&is31fl3741_IS31FL3741_set_led_obj }, }; STATIC MP_DEFINE_CONST_DICT(is31fl3741_IS31FL3741_locals_dict, is31fl3741_IS31FL3741_locals_dict_table); -STATIC void is31fl3741_IS31FL3741_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - check_for_deinit(self); - - *bufinfo = self->bufinfo; -} - -STATIC void is31fl3741_IS31FL3741_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmap) { - common_hal_is31fl3741_IS31FL3741_refresh(self_in, dirty_row_bitmap); -} - -STATIC void is31fl3741_IS31FL3741_deinit_proto(mp_obj_t self_in) { - common_hal_is31fl3741_IS31FL3741_deinit(self_in); -} - -STATIC float is31fl3741_IS31FL3741_get_brightness_proto(mp_obj_t self_in) { - return common_hal_is31fl3741_IS31FL3741_get_paused(self_in) ? 0.0f : 1.0f; -} - -STATIC bool is31fl3741_IS31FL3741_set_brightness_proto(mp_obj_t self_in, mp_float_t value) { - common_hal_is31fl3741_IS31FL3741_set_paused(self_in, value <= 0); - return true; -} - -STATIC int is31fl3741_IS31FL3741_get_width_proto(mp_obj_t self_in) { - return common_hal_is31fl3741_IS31FL3741_get_width(self_in); -} - -STATIC int is31fl3741_IS31FL3741_get_height_proto(mp_obj_t self_in) { - return common_hal_is31fl3741_IS31FL3741_get_height(self_in); -} - -STATIC int is31fl3741_IS31FL3741_get_color_depth_proto(mp_obj_t self_in) { - // The way displayio works depth is used to calculate bytes - // We use an uint32_t for color already so setting to 24 causes - // more changes required - return 32; -} - -STATIC int is31fl3741_IS31FL3741_get_bytes_per_cell_proto(mp_obj_t self_in) { - return 1; -} - -STATIC int is31fl3741_IS31FL3741_get_native_frames_per_second_proto(mp_obj_t self_in) { - return 60; // This was just chosen may vary based on LEDs used? -} - -STATIC const framebuffer_p_t is31fl3741_IS31FL3741_proto = { - MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer) - .get_bufinfo = is31fl3741_IS31FL3741_get_bufinfo, - .set_brightness = is31fl3741_IS31FL3741_set_brightness_proto, - .get_brightness = is31fl3741_IS31FL3741_get_brightness_proto, - .get_width = is31fl3741_IS31FL3741_get_width_proto, - .get_height = is31fl3741_IS31FL3741_get_height_proto, - .get_color_depth = is31fl3741_IS31FL3741_get_color_depth_proto, - .get_bytes_per_cell = is31fl3741_IS31FL3741_get_bytes_per_cell_proto, - .get_native_frames_per_second = is31fl3741_IS31FL3741_get_native_frames_per_second_proto, - .swapbuffers = is31fl3741_IS31FL3741_swapbuffers, - .deinit = is31fl3741_IS31FL3741_deinit_proto, -}; - -STATIC mp_int_t is31fl3741_IS31FL3741_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { - is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; - // a readonly framebuffer would be unusual but not impossible - if ((flags & MP_BUFFER_WRITE) && !(self->bufinfo.typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) { - return 1; - } - *bufinfo = self->bufinfo; - bufinfo->typecode = 'H'; - return 0; -} - const mp_obj_type_t is31fl3741_IS31FL3741_type = { { &mp_type_type }, - .flags = MP_TYPE_FLAG_EXTENDED, .name = MP_QSTR_is31fl3741, .locals_dict = (mp_obj_dict_t *)&is31fl3741_IS31FL3741_locals_dict, .make_new = is31fl3741_IS31FL3741_make_new, - MP_TYPE_EXTENDED_FIELDS( - .buffer_p = { .get_buffer = is31fl3741_IS31FL3741_get_buffer, }, - .protocol = &is31fl3741_IS31FL3741_proto, - ), }; diff --git a/shared-bindings/is31fl3741/IS31FL3741.h b/shared-bindings/is31fl3741/IS31FL3741.h index 3815f10de0e5..2b81b01617ef 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.h +++ b/shared-bindings/is31fl3741/IS31FL3741.h @@ -30,32 +30,20 @@ extern const mp_obj_type_t is31fl3741_IS31FL3741_type; -void common_hal_is31fl3741_IS31FL3741_construct(is31fl3741_IS31FL3741_obj_t *self, int width, int height, mp_obj_t framebuffer, busio_i2c_obj_t *i2c, uint8_t addr, mp_obj_t mapping); +void common_hal_is31fl3741_IS31FL3741_construct(is31fl3741_IS31FL3741_obj_t *self, busio_i2c_obj_t *i2c, uint8_t addr); void common_hal_is31fl3741_IS31FL3741_deinit(is31fl3741_IS31FL3741_obj_t *); -int common_hal_is31fl3741_IS31FL3741_get_width(is31fl3741_IS31FL3741_obj_t *self); -int common_hal_is31fl3741_IS31FL3741_get_height(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_write(is31fl3741_IS31FL3741_obj_t *is31, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes); -void common_hal_displayio_is31fl3741_begin_transaction(is31fl3741_IS31FL3741_obj_t *self); -void common_hal_displayio_is31fl3741_end_transaction(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_begin_transaction(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_end_transaction(is31fl3741_IS31FL3741_obj_t *self); -void common_hal_is31fl3741_IS31FL3741_set_global_current(is31fl3741_IS31FL3741_obj_t *self, uint8_t current); -uint8_t common_hal_is31fl3741_IS31FL3741_get_global_current(is31fl3741_IS31FL3741_obj_t *self); - -void common_hal_is31fl3741_IS31FL3741_set_paused(is31fl3741_IS31FL3741_obj_t *self, bool paused); -bool common_hal_is31fl3741_IS31FL3741_get_paused(is31fl3741_IS31FL3741_obj_t *self); -void common_hal_is31fl3741_IS31FL3741_refresh(is31fl3741_IS31FL3741_obj_t *self, uint8_t *dirtyrows); - -void common_hal_is31fl3741_IS31FL3741_reconstruct(is31fl3741_IS31FL3741_obj_t *self, mp_obj_t framebuffer); - -void is31fl3741_IS31FL3741_collect_ptrs(is31fl3741_IS31FL3741_obj_t *self); - -void is31fl3741_send_unlock(busio_i2c_obj_t *i2c, uint8_t addr); -void is31fl3741_set_page(busio_i2c_obj_t *i2c, uint8_t addr, uint8_t p); -void is31fl3741_send_enable(busio_i2c_obj_t *i2c, uint8_t addr); -void is31fl3741_send_reset(busio_i2c_obj_t *i2c, uint8_t addr); -void is31fl3741_set_current(busio_i2c_obj_t *i2c, uint8_t addr, uint8_t current); -uint8_t is31fl3741_get_current(busio_i2c_obj_t *i2c, uint8_t addr); -void is31fl3741_set_led(busio_i2c_obj_t *i2c, uint8_t addr, uint16_t led, uint8_t level, uint8_t page); -void is31fl3741_draw_pixel(busio_i2c_obj_t *i2c, uint8_t addr, int16_t x, int16_t y, uint32_t color, uint16_t *mapping); +void common_hal_is31fl3741_send_unlock(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_set_page(is31fl3741_IS31FL3741_obj_t *self, uint8_t p); +void common_hal_is31fl3741_send_enable(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_send_reset(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_set_current(is31fl3741_IS31FL3741_obj_t *self, uint8_t current); +uint8_t common_hal_is31fl3741_get_current(is31fl3741_IS31FL3741_obj_t *self); +void common_hal_is31fl3741_set_led(is31fl3741_IS31FL3741_obj_t *self, uint16_t led, uint8_t level, uint8_t page); +void common_hal_is31fl3741_draw_pixel(is31fl3741_IS31FL3741_obj_t *self, int16_t x, int16_t y, uint32_t color, uint16_t *mapping); diff --git a/shared-bindings/is31fl3741/__init__.c b/shared-bindings/is31fl3741/__init__.c index 72b8806c495c..605889700caf 100644 --- a/shared-bindings/is31fl3741/__init__.c +++ b/shared-bindings/is31fl3741/__init__.c @@ -24,8 +24,6 @@ * THE SOFTWARE. */ -#include "shared-bindings/is31fl3741/__init__.h" - #include #include @@ -34,49 +32,12 @@ #include "shared-bindings/busio/I2C.h" #include "shared-bindings/is31fl3741/IS31FL3741.h" - -//| def is31fl3741_write(i2c: busio.I2C, addr: int, mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: -//| """Write buf out on the given I2C bus. -//| -//| :param ~busio.I2C i2c: the I2C bus to output with -//| :param ~int addr: the I2C address of the IS31FL3741 device -//| :param ~Tuple[int, ...] mapping: map the pixels in the buffer to the order addressed by the driver chip -//| :param ~_typing.ReadableBuffer buf: The bytes to clock out. No assumption is made about color order""" -//| ... -STATIC mp_obj_t is31fl3741_is31fl3741_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_i2c, ARG_addr, ARG_mapping, ARG_buffer }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_i2c, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x30 } }, - { MP_QSTR_mapping, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_buffer, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); - - if (!mp_obj_is_tuple_compatible(args[ARG_mapping].u_obj)) { - mp_raise_ValueError(translate("Mapping must be a tuple")); - } - - mp_obj_t *map_items; - size_t map_len; - mp_obj_tuple_get(args[ARG_mapping].u_obj, &map_len, &map_items); - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); - - common_hal_is31fl3741_write(i2c, args[ARG_addr].u_int, map_items, (uint8_t *)bufinfo.buf, bufinfo.len); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(is31fl3741_is31fl3741_write_obj, 0, is31fl3741_is31fl3741_write); +#include "shared-bindings/is31fl3741/FrameBuffer.h" STATIC const mp_rom_map_elem_t is31fl3741_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_is31fl3741) }, { MP_ROM_QSTR(MP_QSTR_IS31FL3741), MP_ROM_PTR(&is31fl3741_IS31FL3741_type) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_is31fl3741_write), (mp_obj_t)&is31fl3741_is31fl3741_write_obj }, + { MP_ROM_QSTR(MP_QSTR_IS31FL3741_FrameBuffer), MP_ROM_PTR(&is31fl3741_FrameBuffer_type) }, }; STATIC MP_DEFINE_CONST_DICT(is31fl3741_module_globals, is31fl3741_module_globals_table); diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index ff085d45ef43..f7c35ac3bd70 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -143,8 +143,8 @@ void common_hal_displayio_release_displays(void) { common_hal_rgbmatrix_rgbmatrix_deinit(&displays[i].rgbmatrix); #endif #if CIRCUITPY_IS31FL3741 - } else if (bus_type == &is31fl3741_IS31FL3741_type) { - common_hal_is31fl3741_IS31FL3741_deinit(&displays[i].is31fl3741); + } else if (bus_type == &is31fl3741_FrameBuffer_type) { + common_hal_is31fl3741_FrameBuffer_deinit(&displays[i].is31fl3741); #endif #if CIRCUITPY_SHARPDISPLAY } else if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) { @@ -225,34 +225,33 @@ void reset_displays(void) { } #endif #if CIRCUITPY_IS31FL3741 - } else if (displays[i].is31fl3741.base.type == &is31fl3741_IS31FL3741_type) { - is31fl3741_IS31FL3741_obj_t *is31 = &displays[i].is31fl3741; - if (((uint32_t)is31->i2c) < ((uint32_t)&displays) || - ((uint32_t)is31->i2c) > ((uint32_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) { - busio_i2c_obj_t *original_i2c = is31->i2c; + } else if (displays[i].is31fl3741.base.type == &is31fl3741_FrameBuffer_type) { + is31fl3741_FrameBuffer_obj_t *is31fb = &displays[i].is31fl3741; + + if (((uint32_t)is31fb->is31fl3741->i2c) < ((uint32_t)&displays) || + ((uint32_t)is31fb->is31fl3741->i2c) > ((uint32_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) { #if BOARD_I2C // We don't need to move original_i2c if it is the board.I2C object because it is // statically allocated already. (Doing so would also make it impossible to reference in // a subsequent VM run.) - if (original_i2c == common_hal_board_get_i2c()) { + if (is31fb->is31fl3741->i2c == common_hal_board_get_i2c()) { continue; } #endif - memcpy(&is31->inline_i2c, original_i2c, sizeof(busio_i2c_obj_t)); - is31->i2c = &is31->inline_i2c; - // Check for other displays that use the same i2c bus and swap them too. - /*for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) { - if (displays[i].i2cdisplay_bus.base.type == &displayio_i2cdisplay_type && - displays[i].i2cdisplay_bus.bus == original_i2c) { - displays[i].i2cdisplay_bus.bus = &i2c->inline_bus; - } - }*/ + + is31fl3741_IS31FL3741_obj_t *original_is31 = is31fb->is31fl3741; + memcpy(&is31fb->inline_is31fl3741, original_is31, sizeof(is31fl3741_IS31FL3741_obj_t)); + is31fb->is31fl3741 = &is31fb->inline_is31fl3741; + + busio_i2c_obj_t *original_i2c = is31fb->is31fl3741->i2c; + memcpy(&is31fb->is31fl3741->inline_i2c, original_i2c, sizeof(busio_i2c_obj_t)); + is31fb->is31fl3741->i2c = &is31fb->is31fl3741->inline_i2c; } - if (!any_display_uses_this_framebuffer(&is31->base)) { - common_hal_is31fl3741_IS31FL3741_deinit(is31); + if (!any_display_uses_this_framebuffer(&is31fb->base)) { + common_hal_is31fl3741_FrameBuffer_deinit(is31fb); } else { - common_hal_is31fl3741_IS31FL3741_set_paused(is31, true); + common_hal_is31fl3741_FrameBuffer_set_paused(is31fb, true); } #endif #if CIRCUITPY_SHARPDISPLAY @@ -299,8 +298,8 @@ void displayio_gc_collect(void) { } #endif #if CIRCUITPY_IS31FL3741 - if (displays[i].is31fl3741.base.type == &is31fl3741_IS31FL3741_type) { - is31fl3741_IS31FL3741_collect_ptrs(&displays[i].is31fl3741); + if (displays[i].is31fl3741.base.type == &is31fl3741_FrameBuffer_type) { + is31fl3741_FrameBuffer_collect_ptrs(&displays[i].is31fl3741); } #endif #if CIRCUITPY_SHARPDISPLAY diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h index b4133308eb16..c1954b146cea 100644 --- a/shared-module/displayio/__init__.h +++ b/shared-module/displayio/__init__.h @@ -42,7 +42,7 @@ #include "shared-bindings/rgbmatrix/RGBMatrix.h" #endif #if CIRCUITPY_IS31FL3741 -#include "shared-bindings/is31fl3741/IS31FL3741.h" +#include "shared-bindings/is31fl3741/FrameBuffer.h" #endif #if CIRCUITPY_SHARPDISPLAY #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" @@ -63,7 +63,7 @@ typedef struct { rgbmatrix_rgbmatrix_obj_t rgbmatrix; #endif #if CIRCUITPY_IS31FL3741 - is31fl3741_IS31FL3741_obj_t is31fl3741; + is31fl3741_FrameBuffer_obj_t is31fl3741; #endif #if CIRCUITPY_SHARPDISPLAY sharpdisplay_framebuffer_obj_t sharpdisplay; diff --git a/shared-module/is31fl3741/FrameBuffer.c b/shared-module/is31fl3741/FrameBuffer.c new file mode 100644 index 000000000000..ebe630cacdfc --- /dev/null +++ b/shared-module/is31fl3741/FrameBuffer.c @@ -0,0 +1,227 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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 + +#include "py/gc.h" +#include "py/obj.h" +#include "py/objarray.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include "shared-module/is31fl3741/allocator.h" +#include "shared-bindings/is31fl3741/IS31FL3741.h" +#include "shared-bindings/is31fl3741/FrameBuffer.h" +#include "shared-bindings/util.h" +#include "shared-module/framebufferio/FramebufferDisplay.h" +#include "shared-bindings/busio/I2C.h" + +void common_hal_is31fl3741_FrameBuffer_construct(is31fl3741_FrameBuffer_obj_t *self, int width, int height, mp_obj_t framebuffer, is31fl3741_IS31FL3741_obj_t *is31, mp_obj_t mapping) { + self->width = width; + self->height = height; + + self->bufsize = sizeof(uint32_t) * width * height; + + self->is31fl3741 = is31; + + common_hal_busio_i2c_never_reset(self->is31fl3741->i2c); + // Our object is statically allocated off the heap so make sure the bus object lives to the end + // of the heap as well. + gc_never_free(self->is31fl3741->i2c); + gc_never_free(self->is31fl3741); + + mp_obj_t *items; + size_t len; + mp_obj_tuple_get(mapping, &len, &items); + + if (len != (size_t)(self->scale_width * self->scale_height * 3)) { + mp_raise_ValueError(translate("LED mappings must match display size")); + } + + self->mapping = common_hal_is31fl3741_allocator_impl(sizeof(uint16_t) * len); + for (size_t i = 0; i < len; i++) { + mp_int_t value = mp_obj_get_int(items[i]); + // We only store up to 16 bits + if (value > 0xFFFF) { + value = 0xFFFF; + } + self->mapping[i] = (uint16_t)value; + } + + common_hal_is31fl3741_FrameBuffer_reconstruct(self, framebuffer); +} + +void common_hal_is31fl3741_FrameBuffer_reconstruct(is31fl3741_FrameBuffer_obj_t *self, mp_obj_t framebuffer) { + self->paused = 1; + + if (framebuffer) { + self->framebuffer = framebuffer; + 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; + } else { + self->bufinfo.typecode = 'H'; + } + + // 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 { + common_hal_is31fl3741_free_impl(self->bufinfo.buf); + + self->framebuffer = NULL; + self->bufinfo.buf = common_hal_is31fl3741_allocator_impl(self->bufsize); + self->bufinfo.len = self->bufsize; + self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW; + } + + common_hal_is31fl3741_begin_transaction(self->is31fl3741); + common_hal_is31fl3741_send_reset(self->is31fl3741); + common_hal_is31fl3741_set_current(self->is31fl3741, 0xFE); + + // set scale (brightness) to max for all LEDs + for (int i = 0; i < 351; i++) { + common_hal_is31fl3741_set_led(self->is31fl3741, i, 0xFF, 2); + } + + common_hal_is31fl3741_send_enable(self->is31fl3741); + common_hal_is31fl3741_end_transaction(self->is31fl3741); + + self->paused = 0; +} + +void common_hal_is31fl3741_FrameBuffer_deinit(is31fl3741_FrameBuffer_obj_t *self) { + common_hal_is31fl3741_end_transaction(self->is31fl3741); // in case we still had a lock + + common_hal_is31fl3741_IS31FL3741_deinit(self->is31fl3741); + + if (self->mapping != 0) { + common_hal_is31fl3741_free_impl(self->mapping); + self->mapping = 0; + } + + self->base.type = NULL; + + // If a framebuffer was passed in to the constructor, NULL the reference + // here so that it will become GC'able + self->framebuffer = NULL; +} + +void common_hal_is31fl3741_FrameBuffer_set_paused(is31fl3741_FrameBuffer_obj_t *self, bool paused) { + self->paused = paused; +} + +bool common_hal_is31fl3741_FrameBuffer_get_paused(is31fl3741_FrameBuffer_obj_t *self) { + return self->paused; +} + +void common_hal_is31fl3741_FrameBuffer_refresh(is31fl3741_FrameBuffer_obj_t *self, uint8_t *dirtyrows) { + if (!self->paused) { + common_hal_is31fl3741_begin_transaction(self->is31fl3741); + + uint8_t dirty_row_flags = 0xFF; // only supports 8 rows gotta fix + + if (self->scale) { + // Based on the Arduino IS31FL3741 driver code + // dirtyrows flag current not implemented for scaled displays + uint32_t *buffer = self->bufinfo.buf; + + for (int x = 0; x < self->scale_width; x++) { + uint32_t *ptr = &buffer[x * 3]; // Entry along top scan line w/x offset + for (int y = 0; y < self->scale_height; y++) { + uint16_t rsum = 0, gsum = 0, bsum = 0; + // Inner x/y loops are row-major on purpose (less pointer math) + for (uint8_t yy = 0; yy < 3; yy++) { + for (uint8_t xx = 0; xx < 3; xx++) { + uint32_t rgb = ptr[xx]; + rsum += rgb >> 16 & 0xFF; + gsum += (rgb >> 8) & 0xFF; + bsum += rgb & 0xFF; + } + ptr += self->width; // Advance one scan line + } + rsum = rsum / 9; + gsum = gsum / 9; + bsum = bsum / 9; + uint32_t color = 0; + if (self->auto_gamma) { + color = (IS31GammaTable[rsum] << 16) + + (IS31GammaTable[gsum] << 8) + + IS31GammaTable[bsum]; + } else { + color = (rsum << 16) + (gsum << 8) + bsum; + } + common_hal_is31fl3741_draw_pixel(self->is31fl3741, x, y, color, self->mapping); + } + } + } else { + uint32_t *buffer = self->bufinfo.buf; + for (int y = 0; y < self->height; y++) { + if ((dirtyrows != 0) && ((y % 8) == 0)) { + dirty_row_flags = *dirtyrows++; + } + + if ((dirty_row_flags >> (y % 8)) & 0x1) { + uint32_t color = 0; + if (self->auto_gamma) { + color = IS31GammaTable[((*buffer) >> 16 & 0xFF)] + + IS31GammaTable[((*buffer) >> 8 & 0xFF)] + + IS31GammaTable[((*buffer) & 0xFF)]; + } else { + color = *buffer; + } + + for (int x = 0; x < self->width; x++) { + common_hal_is31fl3741_draw_pixel(self->is31fl3741, x, y, color, self->mapping); + buffer++; + } + } + } + } + common_hal_is31fl3741_end_transaction(self->is31fl3741); + } +} + +int common_hal_is31fl3741_FrameBuffer_get_width(is31fl3741_FrameBuffer_obj_t *self) { + return self->width; +} + +int common_hal_is31fl3741_FrameBuffer_get_height(is31fl3741_FrameBuffer_obj_t *self) { + return self->height; +} + +void *common_hal_is31fl3741_allocator_impl(size_t sz) { + supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, true); + return allocation ? allocation->ptr : NULL; +} + +void common_hal_is31fl3741_free_impl(void *ptr_in) { + free_memory(allocation_from_ptr(ptr_in)); +} + +void is31fl3741_FrameBuffer_collect_ptrs(is31fl3741_FrameBuffer_obj_t *self) { + gc_collect_ptr(self->framebuffer); + gc_collect_ptr(self->mapping); +} diff --git a/shared-bindings/is31fl3741/__init__.h b/shared-module/is31fl3741/FrameBuffer.h similarity index 64% rename from shared-bindings/is31fl3741/__init__.h rename to shared-module/is31fl3741/FrameBuffer.h index d451b3c389cf..6d0258ce400a 100644 --- a/shared-bindings/is31fl3741/__init__.h +++ b/shared-module/is31fl3741/FrameBuffer.h @@ -1,5 +1,5 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ + * This file is part of the Micro Python project, http://micropython.org/ * * The MIT License (MIT) * @@ -24,16 +24,23 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H +#pragma once -#include -#include +#include "py/obj.h" +#include "lib/protomatter/src/core.h" +#include "shared-module/is31fl3741/IS31FL3741.h" -#include "shared-bindings/busio/I2C.h" - -extern void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes); -void is31fl3741_begin_transaction(busio_i2c_obj_t *i2c); -void is31fl3741_end_transaction(busio_i2c_obj_t *i2c); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H +extern const mp_obj_type_t is31fl3741_FrameBuffer_type; +typedef struct { + mp_obj_base_t base; + is31fl3741_IS31FL3741_obj_t *is31fl3741; + is31fl3741_IS31FL3741_obj_t inline_is31fl3741; + mp_obj_t framebuffer; + mp_buffer_info_t bufinfo; + uint16_t bufsize, width, height, scale_width, scale_height; + uint16_t *mapping; + uint8_t bit_depth; + bool paused; + bool scale; + bool auto_gamma; +} is31fl3741_FrameBuffer_obj_t; diff --git a/shared-module/is31fl3741/IS31FL3741.c b/shared-module/is31fl3741/IS31FL3741.c index 8cd169f8e8a7..7efe820889d3 100644 --- a/shared-module/is31fl3741/IS31FL3741.c +++ b/shared-module/is31fl3741/IS31FL3741.c @@ -32,20 +32,11 @@ #include "py/objproperty.h" #include "py/runtime.h" -#include "shared-module/is31fl3741/allocator.h" #include "shared-bindings/is31fl3741/IS31FL3741.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/util.h" -#include "shared-module/framebufferio/FramebufferDisplay.h" #include "shared-bindings/busio/I2C.h" -void common_hal_is31fl3741_IS31FL3741_construct(is31fl3741_IS31FL3741_obj_t *self, int width, int height, mp_obj_t framebuffer, busio_i2c_obj_t *i2c, uint8_t addr, mp_obj_t mapping) { - self->width = width; - self->height = height; - - self->bufsize = sizeof(uint32_t) * width * height; - +void common_hal_is31fl3741_IS31FL3741_construct(is31fl3741_IS31FL3741_obj_t *self, busio_i2c_obj_t *i2c, uint8_t addr) { // Probe the bus to see if a device acknowledges the given address. if (!common_hal_busio_i2c_probe(i2c, addr)) { self->base.type = &mp_type_NoneType; @@ -54,193 +45,35 @@ void common_hal_is31fl3741_IS31FL3741_construct(is31fl3741_IS31FL3741_obj_t *sel self->i2c = i2c; self->device_address = addr; - common_hal_busio_i2c_never_reset(self->i2c); - // Our object is statically allocated off the heap so make sure the bus object lives to the end - // of the heap as well. - gc_never_free(self->i2c); - - mp_obj_t *items; - size_t len; - mp_obj_tuple_get(mapping, &len, &items); - - if (len != (size_t)(self->scale_width * self->scale_height * 3)) { - mp_raise_ValueError(translate("LED mappings must match display size")); - } - - self->mapping = common_hal_is31fl3741_allocator_impl(sizeof(uint16_t) * len); - for (size_t i = 0; i < len; i++) { - mp_int_t value = mp_obj_get_int(items[i]); - // We only store up to 16 bits - if (value > 0xFFFF) { - value = 0xFFFF; - } - self->mapping[i] = (uint16_t)value; - } - - common_hal_is31fl3741_IS31FL3741_reconstruct(self, framebuffer); -} - -void common_hal_is31fl3741_IS31FL3741_reconstruct(is31fl3741_IS31FL3741_obj_t *self, mp_obj_t framebuffer) { - self->paused = 1; - - if (framebuffer) { - self->framebuffer = framebuffer; - 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; - } else { - self->bufinfo.typecode = 'H'; - } - - // 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 { - common_hal_is31fl3741_free_impl(self->bufinfo.buf); - - self->framebuffer = NULL; - self->bufinfo.buf = common_hal_is31fl3741_allocator_impl(self->bufsize); - self->bufinfo.len = self->bufsize; - self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW; - } - - common_hal_displayio_is31fl3741_begin_transaction(self); - - uint8_t command = 0xFC; // device ID - common_hal_busio_i2c_write(self->i2c, self->device_address, &command, 1, false); - uint8_t data = 0; - common_hal_busio_i2c_read(self->i2c, self->device_address, &data, 1); - - is31fl3741_send_reset(self->i2c, self->device_address); - is31fl3741_send_enable(self->i2c, self->device_address); - is31fl3741_set_current(self->i2c, self->device_address, 0xFF); - - // set scale (brightness) to max for all LEDs - for (int i = 0; i < 351; i++) { - is31fl3741_set_led(self->i2c, self->device_address, i, 0xFF, 2); - } - - common_hal_displayio_is31fl3741_end_transaction(self); - - self->paused = 0; } void common_hal_is31fl3741_IS31FL3741_deinit(is31fl3741_IS31FL3741_obj_t *self) { - common_hal_displayio_is31fl3741_end_transaction(self); // in case we still had a lock + common_hal_is31fl3741_end_transaction(self); // in case we still had a lock if (self->i2c == &self->inline_i2c) { common_hal_busio_i2c_deinit(self->i2c); self->i2c = NULL; } - if (self->mapping != 0) { - common_hal_is31fl3741_free_impl(self->mapping); - self->mapping = 0; - } - self->base.type = NULL; - - // If a framebuffer was passed in to the constructor, NULL the reference - // here so that it will become GC'able - self->framebuffer = NULL; -} - -void common_hal_is31fl3741_IS31FL3741_set_paused(is31fl3741_IS31FL3741_obj_t *self, bool paused) { - self->paused = paused; -} - -bool common_hal_is31fl3741_IS31FL3741_get_paused(is31fl3741_IS31FL3741_obj_t *self) { - return self->paused; } -void common_hal_is31fl3741_IS31FL3741_set_global_current(is31fl3741_IS31FL3741_obj_t *self, uint8_t current) { - common_hal_displayio_is31fl3741_begin_transaction(self); - is31fl3741_set_current(self->i2c, self->device_address, current); - common_hal_displayio_is31fl3741_end_transaction(self); -} - -uint8_t common_hal_is31fl3741_IS31FL3741_get_global_current(is31fl3741_IS31FL3741_obj_t *self) { - common_hal_displayio_is31fl3741_begin_transaction(self); - uint8_t current = is31fl3741_get_current(self->i2c, self->device_address); - common_hal_displayio_is31fl3741_end_transaction(self); - return current; -} - -void common_hal_is31fl3741_IS31FL3741_refresh(is31fl3741_IS31FL3741_obj_t *self, uint8_t *dirtyrows) { - common_hal_displayio_is31fl3741_begin_transaction(self); - if (!self->paused) { - uint8_t dirty_row_flags = 0xFF; // only supports 8 rows gotta fix - - if (self->scale) { - // Based on the Arduino IS31FL3741 driver code - // dirtyrows flag current not implemented for scaled displays - uint32_t *buffer = self->bufinfo.buf; - - for (int x = 0; x < self->scale_width; x++) { - uint32_t *ptr = &buffer[x * 3]; // Entry along top scan line w/x offset - for (int y = 0; y < self->scale_height; y++) { - uint16_t rsum = 0, gsum = 0, bsum = 0; - // Inner x/y loops are row-major on purpose (less pointer math) - for (uint8_t yy = 0; yy < 3; yy++) { - for (uint8_t xx = 0; xx < 3; xx++) { - uint32_t rgb = ptr[xx]; - rsum += rgb >> 16 & 0xFF; - gsum += (rgb >> 8) & 0xFF; - bsum += rgb & 0xFF; - } - ptr += self->width; // Advance one scan line - } - rsum = rsum / 9; - gsum = gsum / 9; - bsum = bsum / 9; - uint32_t color = 0; - if (self->auto_gamma) { - color = (IS31GammaTable[rsum] << 16) + - (IS31GammaTable[gsum] << 8) + - IS31GammaTable[bsum]; - } else { - color = (rsum << 16) + (gsum << 8) + bsum; - } - is31fl3741_draw_pixel(self->i2c, self->device_address, x, y, color, self->mapping); - } - } - } else { - uint32_t *buffer = self->bufinfo.buf; - for (int y = 0; y < self->height; y++) { - if ((dirtyrows != 0) && ((y % 8) == 0)) { - dirty_row_flags = *dirtyrows++; - } +void common_hal_is31fl3741_write(is31fl3741_IS31FL3741_obj_t *is31, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes) { + common_hal_is31fl3741_begin_transaction(is31); - if ((dirty_row_flags >> (y % 8)) & 0x1) { - uint32_t color = 0; - if (self->auto_gamma) { - color = IS31GammaTable[((*buffer) >> 16 & 0xFF)] + - IS31GammaTable[((*buffer) >> 8 & 0xFF)] + - IS31GammaTable[((*buffer) & 0xFF)]; - } else { - color = *buffer; - } - - for (int x = 0; x < self->width; x++) { - is31fl3741_draw_pixel(self->i2c, self->device_address, x, y, color, self->mapping); - buffer++; - } - } - } + for (size_t i = 0; i < numBytes; i += 3) { + uint16_t ridx = mp_obj_get_int(mapping[i]); + if (ridx != 65535) { + common_hal_is31fl3741_set_led(is31, ridx, IS31GammaTable[pixels[i]], 0); // red + common_hal_is31fl3741_set_led(is31, mp_obj_get_int(mapping[i + 1]), IS31GammaTable[pixels[i + 1]], 0); // green + common_hal_is31fl3741_set_led(is31, mp_obj_get_int(mapping[i + 2]), IS31GammaTable[pixels[i + 2]], 0); // blue } } - common_hal_displayio_is31fl3741_end_transaction(self); -} - -int common_hal_is31fl3741_IS31FL3741_get_width(is31fl3741_IS31FL3741_obj_t *self) { - return self->width; + common_hal_is31fl3741_end_transaction(is31); } -int common_hal_is31fl3741_IS31FL3741_get_height(is31fl3741_IS31FL3741_obj_t *self) { - return self->height; -} - -void common_hal_displayio_is31fl3741_begin_transaction(is31fl3741_IS31FL3741_obj_t *self) { +void common_hal_is31fl3741_begin_transaction(is31fl3741_IS31FL3741_obj_t *self) { while (!common_hal_busio_i2c_try_lock(self->i2c)) { RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { @@ -249,91 +82,76 @@ void common_hal_displayio_is31fl3741_begin_transaction(is31fl3741_IS31FL3741_obj } } -void common_hal_displayio_is31fl3741_end_transaction(is31fl3741_IS31FL3741_obj_t *self) { +void common_hal_is31fl3741_end_transaction(is31fl3741_IS31FL3741_obj_t *self) { common_hal_busio_i2c_unlock(self->i2c); } -void *common_hal_is31fl3741_allocator_impl(size_t sz) { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, true); - return allocation ? allocation->ptr : NULL; -} - -void common_hal_is31fl3741_free_impl(void *ptr_in) { - free_memory(allocation_from_ptr(ptr_in)); -} - -void is31fl3741_IS31FL3741_collect_ptrs(is31fl3741_IS31FL3741_obj_t *self) { - gc_collect_ptr(self->framebuffer); - gc_collect_ptr(self->mapping); -} - - uint8_t is31fl3741_cur_page = 99; // set to invalid page to start -void is31fl3741_send_unlock(busio_i2c_obj_t *i2c, uint8_t addr) { +void common_hal_is31fl3741_send_unlock(is31fl3741_IS31FL3741_obj_t *self) { uint8_t unlock[2] = { 0xFE, 0xC5 }; // unlock command - common_hal_busio_i2c_write(i2c, addr, unlock, 2, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, unlock, 2, true); } -void is31fl3741_set_page(busio_i2c_obj_t *i2c, uint8_t addr, uint8_t p) { +void common_hal_is31fl3741_set_page(is31fl3741_IS31FL3741_obj_t *self, uint8_t p) { if (p == is31fl3741_cur_page) { return; } is31fl3741_cur_page = p; - is31fl3741_send_unlock(i2c, addr); + common_hal_is31fl3741_send_unlock(self); uint8_t page[2] = { 0xFD, 0x00 }; // page command page[1] = p; - common_hal_busio_i2c_write(i2c, addr, page, 2, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, page, 2, true); } -void is31fl3741_send_enable(busio_i2c_obj_t *i2c, uint8_t addr) { - is31fl3741_set_page(i2c, addr, 4); +void common_hal_is31fl3741_send_enable(is31fl3741_IS31FL3741_obj_t *self) { + common_hal_is31fl3741_set_page(self, 4); uint8_t enable[2] = { 0x00, 0x01 }; // enable command - common_hal_busio_i2c_write(i2c, addr, enable, 2, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, enable, 2, true); } -void is31fl3741_send_reset(busio_i2c_obj_t *i2c, uint8_t addr) { - is31fl3741_set_page(i2c, addr, 4); +void common_hal_is31fl3741_send_reset(is31fl3741_IS31FL3741_obj_t *self) { + common_hal_is31fl3741_set_page(self, 4); uint8_t rst[2] = { 0x3F, 0xAE }; // reset command - common_hal_busio_i2c_write(i2c, addr, rst, 2, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, rst, 2, true); } -void is31fl3741_set_current(busio_i2c_obj_t *i2c, uint8_t addr, uint8_t current) { - is31fl3741_set_page(i2c, addr, 4); +void common_hal_is31fl3741_set_current(is31fl3741_IS31FL3741_obj_t *self, uint8_t current) { + common_hal_is31fl3741_set_page(self, 4); uint8_t gcur[2] = { 0x01, 0x00 }; // global current command gcur[1] = current; - common_hal_busio_i2c_write(i2c, addr, gcur, 2, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, gcur, 2, true); } -uint8_t is31fl3741_get_current(busio_i2c_obj_t *i2c, uint8_t addr) { - is31fl3741_set_page(i2c, addr, 4); +uint8_t common_hal_is31fl3741_get_current(is31fl3741_IS31FL3741_obj_t *self) { + common_hal_is31fl3741_set_page(self, 4); uint8_t gcur = 0x01; // global current command - common_hal_busio_i2c_write(i2c, addr, &gcur, 1, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, &gcur, 1, true); uint8_t data = 0; - common_hal_busio_i2c_read(i2c, addr, &data, 1); + common_hal_busio_i2c_read(self->i2c, self->device_address, &data, 1); return data; } -void is31fl3741_set_led(busio_i2c_obj_t *i2c, uint8_t addr, uint16_t led, uint8_t level, uint8_t page) { +void common_hal_is31fl3741_set_led(is31fl3741_IS31FL3741_obj_t *self, uint16_t led, uint8_t level, uint8_t page) { uint8_t cmd[2] = { 0x00, 0x00 }; if (led < 180) { - is31fl3741_set_page(i2c, addr, page); + common_hal_is31fl3741_set_page(self, page); cmd[0] = (uint8_t)led; } else { - is31fl3741_set_page(i2c, addr, page + 1); + common_hal_is31fl3741_set_page(self, page + 1); cmd[0] = (uint8_t)(led - 180); } cmd[1] = level; - common_hal_busio_i2c_write(i2c, addr, cmd, 2, true); + common_hal_busio_i2c_write(self->i2c, self->device_address, cmd, 2, true); } -void is31fl3741_draw_pixel(busio_i2c_obj_t *i2c, uint8_t addr, int16_t x, int16_t y, uint32_t color, uint16_t *mapping) { +void common_hal_is31fl3741_draw_pixel(is31fl3741_IS31FL3741_obj_t *self, int16_t x, int16_t y, uint32_t color, uint16_t *mapping) { uint8_t r = color >> 16 & 0xFF; uint8_t g = color >> 8 & 0xFF; uint8_t b = color & 0xFF; @@ -343,8 +161,8 @@ void is31fl3741_draw_pixel(busio_i2c_obj_t *i2c, uint8_t addr, int16_t x, int16_ if (ridx != 65535) { uint16_t gidx = mapping[x1 + 1]; uint16_t bidx = mapping[x1 + 0]; - is31fl3741_set_led(i2c, addr, ridx, r, 0); - is31fl3741_set_led(i2c, addr, gidx, g, 0); - is31fl3741_set_led(i2c, addr, bidx, b, 0); + common_hal_is31fl3741_set_led(self, ridx, r, 0); + common_hal_is31fl3741_set_led(self, gidx, g, 0); + common_hal_is31fl3741_set_led(self, bidx, b, 0); } } diff --git a/shared-module/is31fl3741/IS31FL3741.h b/shared-module/is31fl3741/IS31FL3741.h index c2ccfde849bc..03f1902c4725 100644 --- a/shared-module/is31fl3741/IS31FL3741.h +++ b/shared-module/is31fl3741/IS31FL3741.h @@ -33,17 +33,9 @@ extern const mp_obj_type_t is31fl3741_is31fl3741_type; typedef struct { mp_obj_base_t base; - mp_obj_t framebuffer; - mp_buffer_info_t bufinfo; - uint16_t bufsize, width, height, scale_width, scale_height; busio_i2c_obj_t *i2c; busio_i2c_obj_t inline_i2c; uint8_t device_address; - uint16_t *mapping; - uint8_t bit_depth; - bool paused; - bool scale; - bool auto_gamma; } is31fl3741_IS31FL3741_obj_t; // Gamma correction table diff --git a/shared-module/is31fl3741/__init__.c b/shared-module/is31fl3741/__init__.c index abe03566367d..c267047eda3d 100644 --- a/shared-module/is31fl3741/__init__.c +++ b/shared-module/is31fl3741/__init__.c @@ -23,36 +23,3 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - - -#include "shared-bindings/is31fl3741/__init__.h" -#include "shared-bindings/busio/I2C.h" -#include "shared-bindings/is31fl3741/IS31FL3741.h" - -void is31fl3741_begin_transaction(busio_i2c_obj_t *i2c) { - while (!common_hal_busio_i2c_try_lock(i2c)) { - RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - break; - } - } -} - -void is31fl3741_end_transaction(busio_i2c_obj_t *i2c) { - common_hal_busio_i2c_unlock(i2c); -} - -void common_hal_is31fl3741_write(busio_i2c_obj_t *i2c, uint8_t addr, const mp_obj_t *mapping, const uint8_t *pixels, size_t numBytes) { - is31fl3741_begin_transaction(i2c); - - for (size_t i = 0; i < numBytes; i += 3) { - uint16_t ridx = mp_obj_get_int(mapping[i]); - if (ridx != 65535) { - is31fl3741_set_led(i2c, addr, ridx, IS31GammaTable[pixels[i]], 0); // red - is31fl3741_set_led(i2c, addr, mp_obj_get_int(mapping[i + 1]), IS31GammaTable[pixels[i + 1]], 0); // green - is31fl3741_set_led(i2c, addr, mp_obj_get_int(mapping[i + 2]), IS31GammaTable[pixels[i + 2]], 0); // blue - } - } - - is31fl3741_end_transaction(i2c); -} From af938175521edda79d5f760c43aca89af3de72fd Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Sun, 23 Jan 2022 14:57:06 -0600 Subject: [PATCH 07/14] Fixing bad merge --- shared-module/displayio/__init__.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 947614a27836..d026d9f7669e 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -229,11 +229,11 @@ void reset_displays(void) { if (((uint32_t)is31fb->is31fl3741->i2c) < ((uint32_t)&displays) || ((uint32_t)is31fb->is31fl3741->i2c) > ((uint32_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) { - #if BOARD_I2C + #if CIRCUITPY_BOARD_I2C // We don't need to move original_i2c if it is the board.I2C object because it is // statically allocated already. (Doing so would also make it impossible to reference in // a subsequent VM run.) - if (is31fb->is31fl3741->i2c == common_hal_board_get_i2c()) { + if (common_hal_board_is_i2c(is31fb->is31fl3741->i2c)) { continue; } #endif From dd729d8fefd423ed1c036134504ad7fbbdd05222 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Wed, 26 Jan 2022 19:42:21 -0600 Subject: [PATCH 08/14] Documentation updates --- shared-bindings/is31fl3741/FrameBuffer.c | 5 ++-- shared-bindings/is31fl3741/IS31FL3741.c | 29 +++++++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index 37372a2aeabc..1541cbe292d3 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -38,11 +38,10 @@ #include "shared-bindings/busio/I2C.h" //| class IS31FL3741_FrameBuffer: -//| """Displays an in-memory framebuffer to a IS31FL3741 drive display.""" +//| """Creates an in-memory framebuffer for a IS31FL3741 device.""" //| - //| def __init__(self, *, width: int) -> None: -//| """Create a IS31FL3741 object with the given attributes. +//| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| //| The framebuffer is in "RGB888" format using 4 bytes per pixel. //| Bits 24-31 are ignored. The format is in RGB order. diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 15076a97a873..16d46246838c 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -35,9 +35,8 @@ #include "shared-bindings/busio/I2C.h" //| class IS31FL3741: -//| """Driver for a IS31FL3741 device.""" +//| """Driver for an IS31FL3741 device.""" //| - //| def __init__(self, *, width: int) -> None: //| """Create a IS31FL3741 object with the given attributes. //| @@ -79,6 +78,10 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_deinit(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_deinit_obj, is31fl3741_IS31FL3741_deinit); +//| def reset(self) -> None: +//| """Resets the IS31FL3741 chip.""" +//| ... +//| STATIC mp_obj_t is31fl3741_IS31FL3741_reset(mp_obj_t self_in) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_is31fl3741_send_reset(self); @@ -86,6 +89,10 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_reset(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_reset_obj, is31fl3741_IS31FL3741_reset); +//| def enable(self) -> None: +//| """Enables the IS31FL3741 chip.""" +//| ... +//| STATIC mp_obj_t is31fl3741_IS31FL3741_enable(mp_obj_t self_in) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_is31fl3741_send_enable(self); @@ -93,6 +100,12 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_enable(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_enable_obj, is31fl3741_IS31FL3741_enable); +//| def set_global_current(self, current: int) -> None: +//| """Sets the global current of the IS31FL3741 chip. +//| +//| :param int current: global current value 0x00 to 0xFF""" +//| ... +//| STATIC mp_obj_t is31fl3741_IS31FL3741_set_global_current(mp_obj_t self_in, mp_obj_t value) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t current = mp_obj_get_int(value); @@ -101,6 +114,16 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_set_global_current(mp_obj_t self_in, mp_ob } MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_IS31FL3741_set_global_current_obj, is31fl3741_IS31FL3741_set_global_current); +//| def set_led(self, led: int, value: int, page: int) -> None: +//| """Resets the IS31FL3741 chip.""" +//| +//| :param int led: which LED to set +//| :param int value: value to set the LED to 0x00 to 0xFF +//| :param int page: page to write to 0 or 2. If the LED is a >= 180 +//| the routine will automatically write to page 1 or 3 (instead +//| of 0 ot 2)""" +//| ... +//| STATIC mp_obj_t is31fl3741_IS31FL3741_set_led(size_t n_args, const mp_obj_t *args) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t led = mp_obj_get_int(args[1]); @@ -111,7 +134,7 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_set_led(size_t n_args, const mp_obj_t *arg } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(is31fl3741_IS31FL3741_set_led_obj, 4, 4, is31fl3741_IS31FL3741_set_led); -//| def is31fl3741_write(mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: +//| def write(mapping: Tuple[int, ...], buf: ReadableBuffer) -> None: //| """Write buf out on the I2C bus to the IS31FL3741. //| //| :param ~Tuple[int, ...] mapping: map the pixels in the buffer to the order addressed by the driver chip From d8a7fa025de888063946bf0f07aa878fbec225a9 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Thu, 27 Jan 2022 16:49:54 -0600 Subject: [PATCH 09/14] Documentation fixes 2 --- shared-bindings/is31fl3741/FrameBuffer.c | 14 ++++++++++++-- shared-bindings/is31fl3741/IS31FL3741.c | 10 +++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index 1541cbe292d3..fe75f82c0e1d 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -40,7 +40,8 @@ //| class IS31FL3741_FrameBuffer: //| """Creates an in-memory framebuffer for a IS31FL3741 device.""" //| -//| def __init__(self, *, width: int) -> None: +//| def __init__(self, is31: ~is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], *, +//| framebuffer: Optional[WriteableBuffer] = None, scale: bool = false, gamma: bool = false) -> None: //| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| //| The framebuffer is in "RGB888" format using 4 bytes per pixel. @@ -51,7 +52,16 @@ //| by passing the Is31fl3741 object to memoryview(). //| //| A Is31fl3741 is often used in conjunction with a -//| `framebufferio.FramebufferDisplay`.""" +//| `framebufferio.FramebufferDisplay`. +//| +//| :param ~is31fl3741.IS31FL3741 is31: base IS31FL3741 instance to drive the framebuffer +//| :param int width: width of the display +//| :param int height: height of the display +//| :param Tuple[int, ...] mapping: mapping of matrix locations to LEDs +//| :param Optional[WriteableBuffer] framebuffer: Optional buffer to hold the display +//| :param bool scale: if True display is scaled down by 3 when displayed +//| :param bool gamma: if True apply gamma correction to all LEDs""" +//| ... //| STATIC mp_obj_t is31fl3741_FrameBuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_is31, ARG_width, ARG_height, ARG_framebuffer, ARG_mapping, ARG_scale, ARG_gamma }; diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 16d46246838c..1ea599739309 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -37,11 +37,15 @@ //| class IS31FL3741: //| """Driver for an IS31FL3741 device.""" //| -//| def __init__(self, *, width: int) -> None: +//| def __init__(self, i2c: busio.I2C, *, addr: int = 0x30) -> None: //| """Create a IS31FL3741 object with the given attributes. //| //| Designed to work low level or passed to and object such as -//| `is31fl3741.IS31FL3741_FrameBuffer`.""" +//| :class:`~is31fl3741.IS31FL3741_FrameBuffer`. +//| +//| :param ~busio.I2C i2c: I2C bus the IS31FL3741 is on +//| :param int addr: device address""" +//| ... //| STATIC mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_i2c, ARG_addr }; @@ -115,7 +119,7 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_set_global_current(mp_obj_t self_in, mp_ob MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_IS31FL3741_set_global_current_obj, is31fl3741_IS31FL3741_set_global_current); //| def set_led(self, led: int, value: int, page: int) -> None: -//| """Resets the IS31FL3741 chip.""" +//| """Resets the IS31FL3741 chip. //| //| :param int led: which LED to set //| :param int value: value to set the LED to 0x00 to 0xFF From 31e183ddad142ef5fb2bc2a5a2539624b0860a91 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Thu, 27 Jan 2022 18:01:27 -0600 Subject: [PATCH 10/14] Documentation fix to the fix --- shared-bindings/is31fl3741/FrameBuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index fe75f82c0e1d..ff8277687157 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -41,7 +41,7 @@ //| """Creates an in-memory framebuffer for a IS31FL3741 device.""" //| //| def __init__(self, is31: ~is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], *, -//| framebuffer: Optional[WriteableBuffer] = None, scale: bool = false, gamma: bool = false) -> None: +//| framebuffer: Optional[WriteableBuffer] = None, scale: bool = False, gamma: bool = False) -> None: //| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| //| The framebuffer is in "RGB888" format using 4 bytes per pixel. @@ -54,7 +54,7 @@ //| A Is31fl3741 is often used in conjunction with a //| `framebufferio.FramebufferDisplay`. //| -//| :param ~is31fl3741.IS31FL3741 is31: base IS31FL3741 instance to drive the framebuffer +//| :param is31fl3741.IS31FL3741 is31: base IS31FL3741 instance to drive the framebuffer //| :param int width: width of the display //| :param int height: height of the display //| :param Tuple[int, ...] mapping: mapping of matrix locations to LEDs From 6916307e765cfb1347a1de3d3c711dd550bded00 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Thu, 27 Jan 2022 18:17:38 -0600 Subject: [PATCH 11/14] Doc fix --- shared-bindings/is31fl3741/FrameBuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index ff8277687157..3afde793206b 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -40,7 +40,7 @@ //| class IS31FL3741_FrameBuffer: //| """Creates an in-memory framebuffer for a IS31FL3741 device.""" //| -//| def __init__(self, is31: ~is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], *, +//| def __init__(self, is31: is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], *, //| framebuffer: Optional[WriteableBuffer] = None, scale: bool = False, gamma: bool = False) -> None: //| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| From 19660ec66d2039a7cdfa5075636d36730f0a8305 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Fri, 28 Jan 2022 14:12:05 -0600 Subject: [PATCH 12/14] Doc and KW_REQ changes --- shared-bindings/is31fl3741/FrameBuffer.c | 12 ++++++------ shared-bindings/is31fl3741/IS31FL3741.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index 3afde793206b..398784405d80 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -40,7 +40,7 @@ //| class IS31FL3741_FrameBuffer: //| """Creates an in-memory framebuffer for a IS31FL3741 device.""" //| -//| def __init__(self, is31: is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], *, +//| def __init__(self, *, is31: is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], //| framebuffer: Optional[WriteableBuffer] = None, scale: bool = False, gamma: bool = False) -> None: //| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| @@ -64,13 +64,13 @@ //| ... //| STATIC mp_obj_t is31fl3741_FrameBuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_is31, ARG_width, ARG_height, ARG_framebuffer, ARG_mapping, ARG_scale, ARG_gamma }; + enum { ARG_is31, ARG_width, ARG_height, ARG_mapping, ARG_framebuffer, ARG_scale, ARG_gamma }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_is31, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, - { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, - { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_is31, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_mapping, MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_framebuffer, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = mp_const_none } }, - { MP_QSTR_mapping, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, { MP_QSTR_scale, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, { MP_QSTR_gamma, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, }; diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 1ea599739309..960dc3337c6d 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -125,7 +125,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_IS31FL3741_set_global_current_obj, is31fl37 //| :param int value: value to set the LED to 0x00 to 0xFF //| :param int page: page to write to 0 or 2. If the LED is a >= 180 //| the routine will automatically write to page 1 or 3 (instead -//| of 0 ot 2)""" +//| of 0 or 2)""" //| ... //| STATIC mp_obj_t is31fl3741_IS31FL3741_set_led(size_t n_args, const mp_obj_t *args) { From 02728f166890408e5e8951dab88b2e413b76b809 Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Mon, 31 Jan 2022 16:23:07 -0600 Subject: [PATCH 13/14] Doc changes --- shared-bindings/is31fl3741/FrameBuffer.c | 2 +- shared-bindings/is31fl3741/IS31FL3741.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index 398784405d80..597024500d38 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -40,7 +40,7 @@ //| class IS31FL3741_FrameBuffer: //| """Creates an in-memory framebuffer for a IS31FL3741 device.""" //| -//| def __init__(self, *, is31: is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], +//| def __init__(self, is31: is31fl3741.IS31FL3741, width: int, height: int, mapping: Tuple[int, ...], *, //| framebuffer: Optional[WriteableBuffer] = None, scale: bool = False, gamma: bool = False) -> None: //| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 960dc3337c6d..46a7f8ac8622 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -50,7 +50,7 @@ STATIC mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_i2c, ARG_addr }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_i2c, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_i2c, MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_addr, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 0x30 } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; From afb04f83788d8852daef481bb51e28716815fa4c Mon Sep 17 00:00:00 2001 From: gamblor21 Date: Tue, 1 Feb 2022 20:27:54 -0600 Subject: [PATCH 14/14] Fix to i2c code --- shared-module/is31fl3741/IS31FL3741.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/shared-module/is31fl3741/IS31FL3741.c b/shared-module/is31fl3741/IS31FL3741.c index 7efe820889d3..751ae2bc6d5b 100644 --- a/shared-module/is31fl3741/IS31FL3741.c +++ b/shared-module/is31fl3741/IS31FL3741.c @@ -128,11 +128,8 @@ void common_hal_is31fl3741_set_current(is31fl3741_IS31FL3741_obj_t *self, uint8_ uint8_t common_hal_is31fl3741_get_current(is31fl3741_IS31FL3741_obj_t *self) { common_hal_is31fl3741_set_page(self, 4); uint8_t gcur = 0x01; // global current command - common_hal_busio_i2c_write(self->i2c, self->device_address, &gcur, 1, true); - - uint8_t data = 0; - common_hal_busio_i2c_read(self->i2c, self->device_address, &data, 1); - return data; + common_hal_busio_i2c_write_read(self->i2c, self->device_address, &gcur, 1, &gcur, 1); + return gcur; } void common_hal_is31fl3741_set_led(is31fl3741_IS31FL3741_obj_t *self, uint16_t led, uint8_t level, uint8_t page) {