summaryrefslogtreecommitdiff
path: root/shared-module
diff options
context:
space:
mode:
Diffstat (limited to 'shared-module')
-rw-r--r--shared-module/_pew/PewPew.c125
-rw-r--r--shared-module/_pew/PewPew.h48
-rw-r--r--shared-module/_pew/__init__.c87
-rw-r--r--shared-module/_pew/__init__.h32
-rw-r--r--shared-module/_pixelbuf/PixelBuf.c120
-rw-r--r--shared-module/_pixelbuf/PixelBuf.h50
-rw-r--r--shared-module/_pixelbuf/__init__.c0
-rw-r--r--shared-module/bleio/Characteristic.h19
-rw-r--r--shared-module/bleio/Service.h4
-rw-r--r--shared-module/bleio/__init__.h38
-rw-r--r--shared-module/displayio/Bitmap.c33
-rw-r--r--shared-module/displayio/Bitmap.h1
-rw-r--r--shared-module/displayio/ColorConverter.c8
-rw-r--r--shared-module/displayio/ColorConverter.h3
-rw-r--r--shared-module/displayio/Display.c269
-rw-r--r--shared-module/displayio/Display.h70
-rw-r--r--shared-module/displayio/FourWire.c89
-rw-r--r--shared-module/displayio/FourWire.h43
-rw-r--r--shared-module/displayio/Group.c126
-rw-r--r--shared-module/displayio/Group.h14
-rw-r--r--shared-module/displayio/OnDiskBitmap.c135
-rw-r--r--shared-module/displayio/OnDiskBitmap.h7
-rw-r--r--shared-module/displayio/Palette.c4
-rw-r--r--shared-module/displayio/Palette.h2
-rw-r--r--shared-module/displayio/Shape.c90
-rw-r--r--shared-module/displayio/Shape.h46
-rw-r--r--shared-module/displayio/Sprite.c99
-rw-r--r--shared-module/displayio/TileGrid.c193
-rw-r--r--shared-module/displayio/TileGrid.h59
-rw-r--r--shared-module/displayio/__init__.c258
-rw-r--r--shared-module/displayio/__init__.h20
-rw-r--r--shared-module/fontio/BuiltinFont.c79
-rw-r--r--shared-module/fontio/BuiltinFont.h (renamed from shared-module/displayio/Sprite.h)25
-rw-r--r--shared-module/fontio/__init__.c27
-rw-r--r--shared-module/storage/__init__.c5
-rw-r--r--shared-module/struct/__init__.c113
-rw-r--r--shared-module/terminalio/Terminal.c122
-rw-r--r--shared-module/terminalio/Terminal.h46
-rw-r--r--shared-module/terminalio/__init__.c27
-rw-r--r--shared-module/terminalio/__init__.h30
-rw-r--r--shared-module/usb_midi/PortIn.c37
-rw-r--r--shared-module/usb_midi/PortIn.h39
-rw-r--r--shared-module/usb_midi/PortOut.c37
-rw-r--r--shared-module/usb_midi/PortOut.h39
-rw-r--r--shared-module/usb_midi/__init__.c63
-rw-r--r--shared-module/usb_midi/__init__.h32
46 files changed, 2513 insertions, 300 deletions
diff --git a/shared-module/_pew/PewPew.c b/shared-module/_pew/PewPew.c
new file mode 100644
index 000000000..568dc6425
--- /dev/null
+++ b/shared-module/_pew/PewPew.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+
+#include "py/mpstate.h"
+#include "py/runtime.h"
+#include "__init__.h"
+#include "PewPew.h"
+
+#include "shared-bindings/digitalio/Pull.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/util.h"
+#include "samd/timers.h"
+#include "supervisor/shared/translate.h"
+#include "timer_handler.h"
+
+
+static uint8_t pewpew_tc_index = 0xff;
+
+
+void pewpew_interrupt_handler(uint8_t index) {
+ if (index != pewpew_tc_index) {
+ return;
+ }
+ Tc* tc = tc_insts[index];
+ if (!tc->COUNT16.INTFLAG.bit.MC0) {
+ return;
+ }
+
+ pew_tick();
+
+ // Clear the interrupt bit.
+ tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
+}
+
+void pew_init() {
+ pew_obj_t* pew = MP_STATE_VM(pew_singleton);
+
+ common_hal_digitalio_digitalinout_switch_to_input(pew->buttons, PULL_UP);
+
+ for (size_t i = 0; i < pew->rows_size; ++i) {
+ digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pew->rows[i]);
+ common_hal_digitalio_digitalinout_switch_to_output(pin, false,
+ DRIVE_MODE_PUSH_PULL);
+ }
+ for (size_t i = 0; i < pew->cols_size; ++i) {
+ digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pew->cols[i]);
+ common_hal_digitalio_digitalinout_switch_to_output(pin, true,
+ DRIVE_MODE_OPEN_DRAIN);
+ }
+ if (pewpew_tc_index == 0xff) {
+ // Find a spare timer.
+ uint8_t index = find_free_timer();
+ if (index == 0xff) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+ Tc *tc = tc_insts[index];
+
+ pewpew_tc_index = index;
+ set_timer_handler(true, index, TC_HANDLER_PEW);
+
+ // We use GCLK0 for SAMD21 and GCLK1 for SAMD51 because they both run
+ // at 48mhz making our math the same across the boards.
+ #ifdef SAMD21
+ turn_on_clocks(true, index, 0);
+ #endif
+ #ifdef SAMD51
+ turn_on_clocks(true, index, 1);
+ #endif
+
+
+ #ifdef SAMD21
+ tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
+ TC_CTRLA_PRESCALER_DIV64 |
+ TC_CTRLA_WAVEGEN_MFRQ;
+ #endif
+ #ifdef SAMD51
+ tc_reset(tc);
+ tc_set_enable(tc, false);
+ tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16
+ | TC_CTRLA_PRESCALER_DIV64;
+ tc->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
+ #endif
+
+ tc_set_enable(tc, true);
+ tc->COUNT16.CC[0].reg = 64;
+
+ // Clear our interrupt in case it was set earlier
+ tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
+ tc->COUNT16.INTENSET.reg = TC_INTENSET_MC0;
+ tc_enable_interrupts(pewpew_tc_index);
+ }
+}
+
+void pew_reset(void) {
+ if (pewpew_tc_index != 0xff) {
+ tc_reset(tc_insts[pewpew_tc_index]);
+ pewpew_tc_index = 0xff;
+ }
+ MP_STATE_VM(pew_singleton) = NULL;
+}
diff --git a/shared-module/_pew/PewPew.h b/shared-module/_pew/PewPew.h
new file mode 100644
index 000000000..da1cae0a2
--- /dev/null
+++ b/shared-module/_pew/PewPew.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_PEW_PEWPEW_H
+#define MICROPY_INCLUDED_PEW_PEWPEW_H
+
+#include <stdint.h>
+#include "shared-bindings/digitalio/DigitalInOut.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t* buffer;
+ mp_obj_t* rows;
+ mp_obj_t* cols;
+ digitalio_digitalinout_obj_t *buttons;
+ uint8_t rows_size;
+ uint8_t cols_size;
+ uint8_t pressed;
+} pew_obj_t;
+
+void pew_init(void);
+void pewpew_interrupt_handler(uint8_t index);
+void pew_reset(void);
+
+#endif // MICROPY_INCLUDED_PEW_PEWPEW_H
diff --git a/shared-module/_pew/__init__.c b/shared-module/_pew/__init__.c
new file mode 100644
index 000000000..f3b23c606
--- /dev/null
+++ b/shared-module/_pew/__init__.c
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+
+#include "py/mpstate.h"
+#include "__init__.h"
+#include "PewPew.h"
+
+#include "shared-bindings/digitalio/DigitalInOut.h"
+
+
+void pew_tick(void) {
+ static uint8_t col = 0;
+ static uint8_t turn = 0;
+ static uint8_t pressed = 0;
+ static uint8_t last_pressed = 0;
+ digitalio_digitalinout_obj_t *pin;
+
+ pew_obj_t* pew = MP_STATE_VM(pew_singleton);
+ if (!pew) { return; }
+
+ pin = MP_OBJ_TO_PTR(pew->cols[col]);
+ ++col;
+ if (col >= pew->cols_size) {
+ pew->pressed |= last_pressed & pressed;
+ last_pressed = pressed;
+ pressed = 0;
+ col = 0;
+ ++turn;
+ if (turn > 11) {
+ turn = 0;
+ }
+ }
+ if (!common_hal_digitalio_digitalinout_get_value(pew->buttons)) {
+ pressed |= 1 << col;
+ }
+ common_hal_digitalio_digitalinout_set_value(pin, true);
+ for (size_t x = 0; x < pew->rows_size; ++x) {
+ pin = MP_OBJ_TO_PTR(pew->rows[x]);
+ uint8_t color = pew->buffer[col * (pew->rows_size) + x];
+ bool value = false;
+ switch (color & 0x03) {
+ case 3:
+ value = true;
+ break;
+ case 2:
+ if (turn == 2 || turn == 5 || turn == 8 || turn == 11) {
+ value = true;
+ }
+ break;
+ case 1:
+ if (turn == 0) {
+ value = true;
+ }
+ break;
+ case 0:
+ break;
+ }
+ common_hal_digitalio_digitalinout_set_value(pin, value);
+ }
+ pin = MP_OBJ_TO_PTR(pew->cols[col]);
+ common_hal_digitalio_digitalinout_set_value(pin, false);
+}
diff --git a/shared-module/_pew/__init__.h b/shared-module/_pew/__init__.h
new file mode 100644
index 000000000..4f953c610
--- /dev/null
+++ b/shared-module/_pew/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Radomir Dopieralski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_PEW_H
+#define MICROPY_INCLUDED_PEW_H
+
+void pew_tick(void);
+
+#endif // MICROPY_INCLUDED_PEW_H
diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c
new file mode 100644
index 000000000..d32697239
--- /dev/null
+++ b/shared-module/_pixelbuf/PixelBuf.c
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Roy Hooper
+ *
+ * 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/objarray.h"
+#include "py/runtime.h"
+#include "PixelBuf.h"
+#include <string.h>
+
+void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder) {
+ buf[byteorder->byteorder.r] = value >> 16 & 0xff;
+ buf[byteorder->byteorder.g] = (value >> 8) & 0xff;
+ buf[byteorder->byteorder.b] = value & 0xff;
+ if (byteorder->bpp == 4 && byteorder->has_white &&
+ (buf[byteorder->byteorder.r] == buf[byteorder->byteorder.g] &&
+ buf[byteorder->byteorder.r] == buf[byteorder->byteorder.b])) {
+ buf[byteorder->byteorder.w] = buf[byteorder->byteorder.r];
+ buf[byteorder->byteorder.r] = buf[byteorder->byteorder.g] = buf[byteorder->byteorder.b] = 0;
+ }
+}
+
+void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) {
+ if (MP_OBJ_IS_INT(item)) {
+ uint8_t *target = rawbuf ? rawbuf : buf;
+ pixelbuf_set_pixel_int(target, mp_obj_get_int_truncated(item), byteorder);
+ if (dotstar) {
+ buf[0] = DOTSTAR_LED_START_FULL_BRIGHT;
+ if (rawbuf)
+ rawbuf[0] = DOTSTAR_LED_START_FULL_BRIGHT;
+ }
+ if (rawbuf) {
+ buf[byteorder->byteorder.r] = rawbuf[byteorder->byteorder.r] * brightness;
+ buf[byteorder->byteorder.g] = rawbuf[byteorder->byteorder.g] * brightness;
+ buf[byteorder->byteorder.b] = rawbuf[byteorder->byteorder.b] * brightness;
+ } else {
+ buf[byteorder->byteorder.r] *= brightness;
+ buf[byteorder->byteorder.g] *= brightness;
+ buf[byteorder->byteorder.b] *= brightness;
+ }
+ } else {
+ mp_obj_t *items;
+ size_t len;
+ mp_obj_get_array(item, &len, &items);
+ if (len != byteorder->bpp && !dotstar)
+ mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len);
+
+ buf[byteorder->byteorder.r] = mp_obj_get_int_truncated(items[PIXEL_R]) * brightness;
+ buf[byteorder->byteorder.g] = mp_obj_get_int_truncated(items[PIXEL_G]) * brightness;
+ buf[byteorder->byteorder.b] = mp_obj_get_int_truncated(items[PIXEL_B]) * brightness;
+ if (rawbuf) {
+ rawbuf[byteorder->byteorder.r] = mp_obj_get_int_truncated(items[PIXEL_R]);
+ rawbuf[byteorder->byteorder.g] = mp_obj_get_int_truncated(items[PIXEL_G]);
+ rawbuf[byteorder->byteorder.b] = mp_obj_get_int_truncated(items[PIXEL_B]);
+ }
+ if (len > 3) {
+ if (dotstar) {
+ buf[byteorder->byteorder.w] = DOTSTAR_LED_START | DOTSTAR_BRIGHTNESS(mp_obj_get_float(items[PIXEL_W]));
+ if (rawbuf)
+ rawbuf[byteorder->byteorder.w] = buf[byteorder->byteorder.w];
+ } else {
+ buf[byteorder->byteorder.w] = mp_obj_get_int_truncated(items[PIXEL_W]) * brightness;
+ if (rawbuf)
+ rawbuf[byteorder->byteorder.w] = mp_obj_get_int_truncated(items[PIXEL_W]);
+ }
+ } else if (dotstar) {
+ buf[byteorder->byteorder.w] = DOTSTAR_LED_START_FULL_BRIGHT;
+ if (rawbuf)
+ rawbuf[byteorder->byteorder.w] = DOTSTAR_LED_START_FULL_BRIGHT;
+ }
+ }
+}
+
+mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar) {
+ mp_obj_t elems[len];
+ for (uint i = 0; i < len; i++) {
+ elems[i] = pixelbuf_get_pixel(buf + (i * step), byteorder, dotstar);
+ }
+ return mp_obj_new_tuple(len, elems);
+}
+
+mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) {
+ mp_obj_t elems[byteorder->bpp];
+
+ elems[0] = mp_obj_new_int(buf[byteorder->byteorder.r]);
+ elems[1] = mp_obj_new_int(buf[byteorder->byteorder.g]);
+ elems[2] = mp_obj_new_int(buf[byteorder->byteorder.b]);
+ if (byteorder->bpp > 3)
+ {
+ if (dotstar)
+ elems[3] = mp_obj_new_float(DOTSTAR_GET_BRIGHTNESS(buf[byteorder->byteorder.w]));
+ else
+ elems[3] = mp_obj_new_int(buf[byteorder->byteorder.w]);
+ }
+
+ return mp_obj_new_tuple(byteorder->bpp, elems);
+}
diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h
new file mode 100644
index 000000000..9e115fe0c
--- /dev/null
+++ b/shared-module/_pixelbuf/PixelBuf.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Roy Hooper
+ *
+ * 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/objarray.h"
+#include "../../shared-bindings/_pixelbuf/types.h"
+
+#ifndef PIXELBUF_SHARED_MODULE_H
+#define PIXELBUF_SHARED_MODULE_H
+
+#define PIXEL_R 0
+#define PIXEL_G 1
+#define PIXEL_B 2
+#define PIXEL_W 3
+
+#define DOTSTAR_LED_START 0b11100000
+#define DOTSTAR_BRIGHTNESS(brightness) ((32 - (uint8_t)(32 - brightness * 31)) & 0b00011111)
+#define DOTSTAR_GET_BRIGHTNESS(value) ((value & 0b00011111) / 31.0)
+#define DOTSTAR_LED_START_FULL_BRIGHT 0xFF
+
+void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar);
+mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar);
+mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar);
+void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder);
+
+#endif
diff --git a/shared-module/_pixelbuf/__init__.c b/shared-module/_pixelbuf/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/_pixelbuf/__init__.c
diff --git a/shared-module/bleio/Characteristic.h b/shared-module/bleio/Characteristic.h
index 94c43f81e..958837e64 100644
--- a/shared-module/bleio/Characteristic.h
+++ b/shared-module/bleio/Characteristic.h
@@ -27,26 +27,15 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
-#include "shared-module/bleio/Service.h"
-#include "common-hal/bleio/UUID.h"
-
+// Flags for each characteristic property. Common across ports.
typedef struct {
- mp_obj_base_t base;
- bleio_service_obj_t *service;
- bleio_uuid_obj_t *uuid;
- mp_obj_t value_data;
- uint16_t handle;
- struct {
bool broadcast : 1;
bool read : 1;
- bool write_wo_resp : 1;
+ bool write_no_response : 1;
bool write : 1;
bool notify : 1;
bool indicate : 1;
- } props;
- uint16_t user_desc_handle;
- uint16_t cccd_handle;
- uint16_t sccd_handle;
-} bleio_characteristic_obj_t;
+} bleio_characteristic_properties_t;
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
diff --git a/shared-module/bleio/Service.h b/shared-module/bleio/Service.h
index ff506d3f3..828d4cdc8 100644
--- a/shared-module/bleio/Service.h
+++ b/shared-module/bleio/Service.h
@@ -28,14 +28,14 @@
#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H
#include "common-hal/bleio/UUID.h"
-#include "shared-module/bleio/Device.h"
typedef struct {
mp_obj_base_t base;
uint16_t handle;
bool is_secondary;
bleio_uuid_obj_t *uuid;
- bleio_device_obj_t *device;
+ // May be a Peripheral, Central, etc.
+ mp_obj_t *device;
mp_obj_t char_list;
uint16_t start_handle;
uint16_t end_handle;
diff --git a/shared-module/bleio/__init__.h b/shared-module/bleio/__init__.h
new file mode 100644
index 000000000..07d148594
--- /dev/null
+++ b/shared-module/bleio/__init__.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
+
+typedef enum {
+ GATT_ROLE_NONE,
+ GATT_ROLE_SERVER,
+ GATT_ROLE_CLIENT,
+} gatt_role_t;
+
+extern void bleio_reset(void);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c
index addc341a7..2b2c70ab6 100644
--- a/shared-module/displayio/Bitmap.c
+++ b/shared-module/displayio/Bitmap.c
@@ -42,7 +42,7 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi
self->width = width;
self->height = height;
self->data = m_malloc(self->stride * height * sizeof(uint32_t), false);
-
+ self->read_only = false;
self->bits_per_value = bits_per_value;
if (bits_per_value > 8) {
@@ -64,6 +64,18 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi
self->bitmask = (1 << bits_per_value) - 1;
}
+uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self) {
+ return self->height;
+}
+
+uint16_t common_hal_displayio_bitmap_get_width(displayio_bitmap_t *self) {
+ return self->width;
+}
+
+uint32_t common_hal_displayio_bitmap_get_bits_per_value(displayio_bitmap_t *self) {
+ return self->bits_per_value;
+}
+
void common_hal_displayio_bitmap_load_row(displayio_bitmap_t *self, uint16_t y, uint8_t* data, uint16_t len) {
if (len != self->stride * sizeof(uint32_t)) {
mp_raise_ValueError(translate("row must be packed and word aligned"));
@@ -85,6 +97,7 @@ void common_hal_displayio_bitmap_load_row(displayio_bitmap_t *self, uint16_t y,
row_value++;
}
}
+
uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t x, int16_t y) {
if (x >= self->width || x < 0 || y >= self->height || y < 0) {
return 0;
@@ -99,3 +112,21 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
return self->data[row_start + x * bytes_per_value];
}
}
+
+void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
+ if (self->read_only) {
+ mp_raise_RuntimeError(translate("Read-only object"));
+ }
+ int32_t row_start = y * self->stride;
+ if (self->bits_per_value < 8) {
+ uint32_t bit_position = (32 - ((x & self->x_mask) + 1) * self->bits_per_value);
+ uint32_t index = row_start + (x >> self->x_shift);
+ uint32_t word = self->data[index];
+ word &= ~(self->bitmask << bit_position);
+ word |= (value & self->bitmask) << bit_position;
+ self->data[index] = word;
+ } else {
+ uint32_t bytes_per_value = self->bits_per_value / 8;
+ self->data[row_start + x * bytes_per_value] = value;
+ }
+}
diff --git a/shared-module/displayio/Bitmap.h b/shared-module/displayio/Bitmap.h
index 781a4d12a..485b57daf 100644
--- a/shared-module/displayio/Bitmap.h
+++ b/shared-module/displayio/Bitmap.h
@@ -42,6 +42,7 @@ typedef struct {
uint8_t x_shift;
uint8_t x_mask;
uint16_t bitmask;
+ bool read_only;
} displayio_bitmap_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H
diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c
index d20b24c01..3928e115a 100644
--- a/shared-module/displayio/ColorConverter.c
+++ b/shared-module/displayio/ColorConverter.c
@@ -39,3 +39,11 @@ bool common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *sel
*output_color = __builtin_bswap16(packed);
return true;
}
+
+// Currently no refresh logic is needed for a ColorConverter.
+bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self) {
+ return false;
+}
+
+void displayio_colorconverter_finish_refresh(displayio_colorconverter_t *self) {
+}
diff --git a/shared-module/displayio/ColorConverter.h b/shared-module/displayio/ColorConverter.h
index 62ef2eaab..7f3c1a0a0 100644
--- a/shared-module/displayio/ColorConverter.h
+++ b/shared-module/displayio/ColorConverter.h
@@ -36,4 +36,7 @@ typedef struct {
mp_obj_base_t base;
} displayio_colorconverter_t;
+bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self);
+void displayio_colorconverter_finish_refresh(displayio_colorconverter_t *self);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_COLORCONVERTER_H
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
new file mode 100644
index 000000000..0e76a868f
--- /dev/null
+++ b/shared-module/displayio/Display.c
@@ -0,0 +1,269 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/Display.h"
+
+#include "py/runtime.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-bindings/displayio/ParallelBus.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-module/displayio/__init__.h"
+#include "supervisor/shared/display.h"
+
+#include <stdint.h>
+
+#include "tick.h"
+
+#define DELAY 0x80
+
+void common_hal_displayio_display_construct(displayio_display_obj_t* self,
+ mp_obj_t bus, uint16_t width, uint16_t height, int16_t colstart, int16_t rowstart, uint16_t rotation,
+ uint16_t color_depth, uint8_t set_column_command, uint8_t set_row_command,
+ uint8_t write_ram_command, uint8_t set_vertical_scroll, uint8_t* init_sequence, uint16_t init_sequence_len,
+ const mcu_pin_obj_t* backlight_pin) {
+ self->color_depth = color_depth;
+ self->set_column_command = set_column_command;
+ self->set_row_command = set_row_command;
+ self->write_ram_command = write_ram_command;
+ self->refresh = false;
+ self->current_group = NULL;
+ self->colstart = colstart;
+ self->rowstart = rowstart;
+ self->auto_brightness = false;
+
+ if (MP_OBJ_IS_TYPE(bus, &displayio_parallelbus_type)) {
+ self->begin_transaction = common_hal_displayio_parallelbus_begin_transaction;
+ self->send = common_hal_displayio_parallelbus_send;
+ self->end_transaction = common_hal_displayio_parallelbus_end_transaction;
+ } else if (MP_OBJ_IS_TYPE(bus, &displayio_fourwire_type)) {
+ self->begin_transaction = common_hal_displayio_fourwire_begin_transaction;
+ self->send = common_hal_displayio_fourwire_send;
+ self->end_transaction = common_hal_displayio_fourwire_end_transaction;
+ } else {
+ mp_raise_ValueError(translate("Unsupported display bus type"));
+ }
+ self->bus = bus;
+
+ uint32_t i = 0;
+ while (!self->begin_transaction(self->bus)) {
+#ifdef MICROPY_VM_HOOK_LOOP
+ MICROPY_VM_HOOK_LOOP ;
+#endif
+ }
+ while (i < init_sequence_len) {
+ uint8_t *cmd = init_sequence + i;
+ uint8_t data_size = *(cmd + 1);
+ bool delay = (data_size & DELAY) != 0;
+ data_size &= ~DELAY;
+ uint8_t *data = cmd + 2;
+ self->send(self->bus, true, cmd, 1);
+ self->send(self->bus, false, data, data_size);
+ uint16_t delay_length_ms = 10;
+ if (delay) {
+ data_size++;
+ delay_length_ms = *(cmd + 1 + data_size);
+ if (delay_length_ms == 255) {
+ delay_length_ms = 500;
+ }
+ }
+ common_hal_time_delay_ms(delay_length_ms);
+ i += 2 + data_size;
+ }
+ self->end_transaction(self->bus);
+
+ supervisor_start_terminal(width, height);
+
+ // Set the group after initialization otherwise we may send pixels while we delay in
+ // initialization.
+ self->refresh = true;
+ self->current_group = &circuitpython_splash;
+
+ self->width = width;
+ self->height = height;
+ rotation = rotation % 360;
+ self->mirror_x = false;
+ self->mirror_y = false;
+ self->transpose_xy = false;
+ if (rotation == 0 || rotation == 180) {
+ if (rotation == 180) {
+ self->mirror_x = true;
+ self->mirror_y = true;
+ }
+ } else {
+ self->transpose_xy = true;
+ if (rotation == 90) {
+ self->mirror_y = true;
+ } else {
+ self->mirror_x = true;
+ }
+ }
+
+ // Always set the backlight type in case we're reusing memory.
+ self->backlight_inout.base.type = &mp_type_NoneType;
+ if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) {
+ pwmout_result_t result = common_hal_pulseio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 50000, false);
+ if (result != PWMOUT_OK) {
+ self->backlight_inout.base.type = &digitalio_digitalinout_type;
+ common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin);
+ never_reset_pin_number(backlight_pin->number);
+ } else {
+ self->backlight_pwm.base.type = &pulseio_pwmout_type;
+ common_hal_pulseio_pwmout_never_reset(&self->backlight_pwm);
+ }
+ }
+}
+
+void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
+ if (root_group == NULL) {
+ root_group = &circuitpython_splash;
+ }
+ self->current_group = root_group;
+ common_hal_displayio_display_refresh_soon(self);
+}
+
+void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self) {
+ self->refresh = true;
+}
+
+int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self) {
+ uint64_t last_refresh = self->last_refresh;
+ // Don't try to refresh if we got an exception.
+ while (last_refresh == self->last_refresh && MP_STATE_VM(mp_pending_exception) == NULL) {
+ MICROPY_VM_HOOK_LOOP
+ }
+ return 0;
+}
+
+bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self) {
+ return self->auto_brightness;
+}
+
+uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self){
+ return self->width;
+}
+
+uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self){
+ return self->height;
+}
+
+void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness) {
+ self->auto_brightness = auto_brightness;
+}
+
+mp_float_t common_hal_displayio_display_get_brightness(displayio_display_obj_t* self) {
+ if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
+ uint16_t duty_cycle = common_hal_pulseio_pwmout_get_duty_cycle(&self->backlight_pwm);
+ return duty_cycle / ((mp_float_t) 0xffff);
+ } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
+ if (common_hal_digitalio_digitalinout_get_value(&self->backlight_inout)) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ return -1.0;
+}
+
+bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self, mp_float_t brightness) {
+ self->updating_backlight = true;
+ bool ok = false;
+ if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
+ common_hal_pulseio_pwmout_set_duty_cycle(&self->backlight_pwm, (uint16_t) (0xffff * brightness));
+ ok = true;
+ } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
+ common_hal_digitalio_digitalinout_set_value(&self->backlight_inout, brightness > 0.99);
+ ok = true;
+ }
+ self->updating_backlight = false;
+ return ok;
+}
+
+bool displayio_display_begin_transaction(displayio_display_obj_t* self) {
+ return self->begin_transaction(self->bus);
+}
+
+void displayio_display_end_transaction(displayio_display_obj_t* self) {
+ self->end_transaction(self->bus);
+}
+
+void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
+ // TODO(tannewt): Handle displays with single byte bounds.
+ uint16_t data[2];
+ self->send(self->bus, true, &self->set_column_command, 1);
+ data[0] = __builtin_bswap16(x0 + self->colstart);
+ data[1] = __builtin_bswap16(x1 - 1 + self->colstart);
+ self->send(self->bus, false, (uint8_t*) data, 4);
+ self->send(self->bus, true, &self->set_row_command, 1);
+ data[0] = __builtin_bswap16(y0 + self->rowstart);
+ data[1] = __builtin_bswap16(y1 - 1 + self->rowstart);
+ self->send(self->bus, false, (uint8_t*) data, 4);
+ self->send(self->bus, true, &self->write_ram_command, 1);
+}
+
+bool displayio_display_frame_queued(displayio_display_obj_t* self) {
+ // Refresh at ~30 fps.
+ return (ticks_ms - self->last_refresh) > 32;
+}
+
+bool displayio_display_refresh_queued(displayio_display_obj_t* self) {
+ return self->refresh || (self->current_group != NULL && displayio_group_needs_refresh(self->current_group));
+}
+
+void displayio_display_finish_refresh(displayio_display_obj_t* self) {
+ if (self->current_group != NULL) {
+ displayio_group_finish_refresh(self->current_group);
+ }
+ self->refresh = false;
+ self->last_refresh = ticks_ms;
+}
+
+void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
+ self->send(self->bus, false, (uint8_t*) pixels, length * 4);
+}
+
+void displayio_display_update_backlight(displayio_display_obj_t* self) {
+ if (!self->auto_brightness || self->updating_backlight) {
+ return;
+ }
+ if (ticks_ms - self->last_backlight_refresh < 100) {
+ return;
+ }
+ // TODO(tannewt): Fade the backlight based on it's existing value and a target value. The target
+ // should account for ambient light when possible.
+ common_hal_displayio_display_set_brightness(self, 1.0);
+
+ self->last_backlight_refresh = ticks_ms;
+}
+
+void release_display(displayio_display_obj_t* self) {
+ if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
+ common_hal_pulseio_pwmout_reset_ok(&self->backlight_pwm);
+ common_hal_pulseio_pwmout_deinit(&self->backlight_pwm);
+ } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
+ common_hal_digitalio_digitalinout_deinit(&self->backlight_inout);
+ }
+}
diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h
new file mode 100644
index 000000000..04da68b63
--- /dev/null
+++ b/shared-module/displayio/Display.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
+
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/pulseio/PWMOut.h"
+
+typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
+typedef void (*display_bus_send)(mp_obj_t bus, bool command, uint8_t *data, uint32_t data_length);
+typedef void (*display_bus_end_transaction)(mp_obj_t bus);
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t bus;
+ uint16_t width;
+ uint16_t height;
+ uint16_t color_depth;
+ uint8_t set_column_command;
+ uint8_t set_row_command;
+ uint8_t write_ram_command;
+ displayio_group_t *current_group;
+ bool refresh;
+ uint64_t last_refresh;
+ int16_t colstart;
+ int16_t rowstart;
+ display_bus_begin_transaction begin_transaction;
+ display_bus_send send;
+ display_bus_end_transaction end_transaction;
+ union {
+ digitalio_digitalinout_obj_t backlight_inout;
+ pulseio_pwmout_obj_t backlight_pwm;
+ };
+ uint64_t last_backlight_refresh;
+ bool auto_brightness:1;
+ bool updating_backlight:1;
+ bool mirror_x;
+ bool mirror_y;
+ bool transpose_xy;
+} displayio_display_obj_t;
+
+void displayio_display_update_backlight(displayio_display_obj_t* self);
+void release_display(displayio_display_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c
new file mode 100644
index 000000000..9da5c0701
--- /dev/null
+++ b/shared-module/displayio/FourWire.c
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/FourWire.h"
+
+#include <stdint.h>
+
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+
+#include "tick.h"
+
+void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self,
+ busio_spi_obj_t* spi, const mcu_pin_obj_t* command,
+ const mcu_pin_obj_t* chip_select, const mcu_pin_obj_t* reset) {
+
+ self->bus = spi;
+ common_hal_busio_spi_never_reset(self->bus);
+
+ common_hal_digitalio_digitalinout_construct(&self->command, command);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL);
+ common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
+
+ if (reset != NULL) {
+ common_hal_digitalio_digitalinout_construct(&self->reset, reset);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
+ never_reset_pin_number(reset->number);
+ }
+
+ never_reset_pin_number(command->number);
+ never_reset_pin_number(chip_select->number);
+}
+
+void common_hal_displayio_fourwire_deinit(displayio_fourwire_obj_t* self) {
+ if (self->bus == &self->inline_bus) {
+ common_hal_busio_spi_deinit(self->bus);
+ }
+
+ reset_pin_number(self->command.pin->number);
+ reset_pin_number(self->chip_select.pin->number);
+ reset_pin_number(self->reset.pin->number);
+}
+
+bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) {
+ displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (!common_hal_busio_spi_try_lock(self->bus)) {
+ return false;
+ }
+ // TODO(tannewt): Stop hardcoding SPI frequency, polarity and phase.
+ common_hal_busio_spi_configure(self->bus, 12000000, 0, 0, 8);
+ common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
+ return true;
+}
+
+void common_hal_displayio_fourwire_send(mp_obj_t obj, bool command, uint8_t *data, uint32_t data_length) {
+ displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
+ common_hal_digitalio_digitalinout_set_value(&self->command, !command);
+ common_hal_busio_spi_write(self->bus, data, data_length);
+}
+
+void common_hal_displayio_fourwire_end_transaction(mp_obj_t obj) {
+ displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
+ common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
+ common_hal_busio_spi_unlock(self->bus);
+}
diff --git a/shared-module/displayio/FourWire.h b/shared-module/displayio/FourWire.h
new file mode 100644
index 000000000..234bcf794
--- /dev/null
+++ b/shared-module/displayio/FourWire.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H
+
+#include "common-hal/busio/SPI.h"
+#include "common-hal/digitalio/DigitalInOut.h"
+#include "shared-module/displayio/Group.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ busio_spi_obj_t* bus;
+ busio_spi_obj_t inline_bus;
+ digitalio_digitalinout_obj_t command;
+ digitalio_digitalinout_obj_t chip_select;
+ digitalio_digitalinout_obj_t reset;
+} displayio_fourwire_obj_t;
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H
diff --git a/shared-module/displayio/Group.c b/shared-module/displayio/Group.c
index 655376da0..20182863e 100644
--- a/shared-module/displayio/Group.c
+++ b/shared-module/displayio/Group.c
@@ -27,52 +27,120 @@
#include "shared-bindings/displayio/Group.h"
#include "py/runtime.h"
-#include "shared-bindings/displayio/Sprite.h"
+#include "shared-bindings/displayio/TileGrid.h"
-void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size) {
- mp_obj_t* children = m_new(mp_obj_t, max_size);
- displayio_group_construct(self, children, max_size);
+void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y) {
+ displayio_group_child_t* children = m_new(displayio_group_child_t, max_size);
+ displayio_group_construct(self, children, max_size, scale, x, y);
}
-void common_hal_displayio_group_append(displayio_group_t* self, mp_obj_t layer) {
+uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self) {
+ return self->scale;
+}
+
+void common_hal_displayio_group_set_scale(displayio_group_t* self, uint32_t scale) {
+ self->needs_refresh = self->scale != scale;
+ self->scale = scale;
+}
+
+mp_int_t common_hal_displayio_group_get_x(displayio_group_t* self) {
+ return self->x;
+}
+
+void common_hal_displayio_group_set_x(displayio_group_t* self, mp_int_t x) {
+ self->needs_refresh = self->x != x;
+ self->x = x;
+}
+
+mp_int_t common_hal_displayio_group_get_y(displayio_group_t* self) {
+ return self->y;
+}
+
+void common_hal_displayio_group_set_y(displayio_group_t* self, mp_int_t y) {
+ self->needs_refresh = self->y != y;
+ self->y = y;
+}
+
+void common_hal_displayio_group_insert(displayio_group_t* self, size_t index, mp_obj_t layer) {
if (self->size == self->max_size) {
mp_raise_RuntimeError(translate("Group full"));
}
- self->children[self->size] = layer;
+ mp_obj_t native_layer = mp_instance_cast_to_native_base(layer, &displayio_group_type);
+ if (native_layer == MP_OBJ_NULL) {
+ native_layer = mp_instance_cast_to_native_base(layer, &displayio_tilegrid_type);
+ }
+ if (native_layer == MP_OBJ_NULL) {
+ mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass."));
+ }
+ // Shift everything right.
+ for (size_t i = index; i < self->size; i++) {
+ self->children[i + 1] = self->children[i];
+ }
+ self->children[index].native = native_layer;
+ self->children[index].original = layer;
self->size++;
self->needs_refresh = true;
}
-mp_obj_t common_hal_displayio_group_pop(displayio_group_t* self) {
- if (self->size == 0) {
- mp_raise_IndexError(translate("Group empty"));
- }
+mp_obj_t common_hal_displayio_group_pop(displayio_group_t* self, size_t index) {
self->size--;
- mp_obj_t item = self->children[self->size];
- self->children[self->size] = NULL;
+ mp_obj_t item = self->children[index].original;
+ // Shift everything left.
+ for (size_t i = index; i < self->size; i++) {
+ self->children[i] = self->children[i + 1];
+ }
+ self->children[self->size].native = NULL;
+ self->children[self->size].original = NULL;
self->needs_refresh = true;
return item;
}
-void displayio_group_construct(displayio_group_t* self, mp_obj_t* child_array, uint32_t max_size) {
- self->x = 0;
- self->y = 0;
+size_t common_hal_displayio_group_get_len(displayio_group_t* self) {
+ return self->size;
+}
+
+mp_obj_t common_hal_displayio_group_get(displayio_group_t* self, size_t index) {
+ return self->children[index].original;
+}
+
+void common_hal_displayio_group_set(displayio_group_t* self, size_t index, mp_obj_t layer) {
+ mp_obj_t native_layer = mp_instance_cast_to_native_base(layer, &displayio_group_type);
+ if (native_layer == MP_OBJ_NULL) {
+ native_layer = mp_instance_cast_to_native_base(layer, &displayio_tilegrid_type);
+ }
+ if (native_layer == MP_OBJ_NULL) {
+ mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass."));
+ }
+ self->children[index].native = native_layer;
+ self->children[index].original = layer;
+ self->needs_refresh = true;
+}
+
+void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y) {
+ self->x = x;
+ self->y = y;
self->children = child_array;
self->max_size = max_size;
self->needs_refresh = false;
+ self->scale = scale;
}
bool displayio_group_get_pixel(displayio_group_t *self, int16_t x, int16_t y, uint16_t* pixel) {
x -= self->x;
y -= self->y;
+ x /= self->scale;
+ y /= self->scale;
for (int32_t i = self->size - 1; i >= 0 ; i--) {
- mp_obj_t layer = self->children[i];
- if (MP_OBJ_IS_TYPE(layer, &displayio_sprite_type)) {
- if (displayio_sprite_get_pixel(layer, x, y, pixel)) {
+ mp_obj_t layer = self->children[i].native;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ if (displayio_tilegrid_get_pixel(layer, x, y, pixel)) {
+ return true;
+ }
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ if (displayio_group_get_pixel(layer, x, y, pixel)) {
return true;
}
}
- // TODO: Tiled layer
}
return false;
}
@@ -82,13 +150,16 @@ bool displayio_group_needs_refresh(displayio_group_t *self) {
return true;
}
for (int32_t i = self->size - 1; i >= 0 ; i--) {
- mp_obj_t layer = self->children[i];
- if (MP_OBJ_IS_TYPE(layer, &displayio_sprite_type)) {
- if (displayio_sprite_needs_refresh(layer)) {
+ mp_obj_t layer = self->children[i].native;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ if (displayio_tilegrid_needs_refresh(layer)) {
+ return true;
+ }
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ if (displayio_group_needs_refresh(layer)) {
return true;
}
}
- // TODO: Tiled layer
}
return false;
}
@@ -96,10 +167,11 @@ bool displayio_group_needs_refresh(displayio_group_t *self) {
void displayio_group_finish_refresh(displayio_group_t *self) {
self->needs_refresh = false;
for (int32_t i = self->size - 1; i >= 0 ; i--) {
- mp_obj_t layer = self->children[i];
- if (MP_OBJ_IS_TYPE(layer, &displayio_sprite_type)) {
- displayio_sprite_finish_refresh(layer);
+ mp_obj_t layer = self->children[i].native;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ displayio_tilegrid_finish_refresh(layer);
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ displayio_group_finish_refresh(layer);
}
- // TODO: Tiled layer
}
}
diff --git a/shared-module/displayio/Group.h b/shared-module/displayio/Group.h
index 272f3114c..7826b9e66 100644
--- a/shared-module/displayio/Group.h
+++ b/shared-module/displayio/Group.h
@@ -33,20 +33,22 @@
#include "py/obj.h"
typedef struct {
+ mp_obj_t native;
+ mp_obj_t original;
+} displayio_group_child_t;
+
+typedef struct {
mp_obj_base_t base;
int16_t x;
int16_t y;
+ uint16_t scale;
uint16_t size;
uint16_t max_size;
- mp_obj_t* children;
+ displayio_group_child_t* children;
bool needs_refresh;
} displayio_group_t;
-
-void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size);
-void common_hal_displayio_group_append(displayio_group_t* self, mp_obj_t layer);
-
-void displayio_group_construct(displayio_group_t* self, mp_obj_t* child_array, uint32_t max_size);
+void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y);
bool displayio_group_get_pixel(displayio_group_t *group, int16_t x, int16_t y, uint16_t *pixel);
bool displayio_group_needs_refresh(displayio_group_t *self);
void displayio_group_finish_refresh(displayio_group_t *self);
diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c
index 6e4a4c6f0..d710bdae0 100644
--- a/shared-module/displayio/OnDiskBitmap.c
+++ b/shared-module/displayio/OnDiskBitmap.c
@@ -38,13 +38,13 @@ static uint32_t read_word(uint16_t* bmp_header, uint16_t index) {
void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, pyb_file_obj_t* file) {
// Load the wave
self->file = file;
- uint16_t bmp_header[24];
+ uint16_t bmp_header[69];
f_rewind(&self->file->fp);
UINT bytes_read;
- if (f_read(&self->file->fp, bmp_header, 48, &bytes_read) != FR_OK) {
+ if (f_read(&self->file->fp, bmp_header, 138, &bytes_read) != FR_OK) {
mp_raise_OSError(MP_EIO);
}
- if (bytes_read != 48 ||
+ if (bytes_read != 138 ||
memcmp(bmp_header, "BM", 2) != 0) {
mp_raise_ValueError(translate("Invalid BMP file"));
}
@@ -53,25 +53,68 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
self->data_offset = read_word(bmp_header, 5);
uint32_t header_size = read_word(bmp_header, 7);
- uint32_t compression = read_word(bmp_header, 15);
- if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124) ||
- !(compression == 0)) {
- mp_raise_ValueError_varg(translate("Only Windows format, uncompressed BMP supported %d"), header_size);
- }
- // TODO(tannewt): Support bitfield compressed colors since RGB565 can be produced by the GIMP.
uint16_t bits_per_pixel = bmp_header[14];
- if (bits_per_pixel < 24) {
- mp_raise_ValueError_varg(translate("Only true color (24 bpp or higher) BMP supported %x"), bits_per_pixel);
- }
- self->bytes_per_pixel = bits_per_pixel / 8;
+ uint32_t compression = read_word(bmp_header, 15);
+ uint32_t number_of_colors = read_word(bmp_header, 23);
+
+ bool indexed = ((bits_per_pixel <= 8) && (number_of_colors != 0));
+ self->bitfield_compressed = (compression == 3);
+ self->bits_per_pixel = bits_per_pixel;
self->width = read_word(bmp_header, 9);
self->height = read_word(bmp_header, 11);
- uint32_t byte_width = self->width * self->bytes_per_pixel;
- self->stride = byte_width;
- // Rows are word aligned.
- if (self->stride % 4 != 0) {
- self->stride += 4 - self->stride % 4;
+
+ if (bits_per_pixel == 16){
+ if (((header_size >= 56)) || (self->bitfield_compressed)) {
+ self->r_bitmask = read_word(bmp_header, 27);
+ self->g_bitmask = read_word(bmp_header, 29);
+ self->b_bitmask = read_word(bmp_header, 31);
+
+ } else { // no compression or short header means 5:5:5
+ self->r_bitmask = 0x7c00;
+ self->g_bitmask = 0x3e0;
+ self->b_bitmask = 0x1f;
+ }
+ } else if ((indexed) && (self->bits_per_pixel != 1)) {
+ uint16_t palette_size = number_of_colors * sizeof(uint32_t);
+ uint16_t palette_offset = 0xe + header_size;
+
+ self->palette_data = m_malloc(palette_size, false);
+
+ f_rewind(&self->file->fp);
+ f_lseek(&self->file->fp, palette_offset);
+
+ UINT palette_bytes_read;
+ if (f_read(&self->file->fp, self->palette_data, palette_size, &palette_bytes_read) != FR_OK) {
+ mp_raise_OSError(MP_EIO);
+ }
+ if (palette_bytes_read != palette_size) {
+ mp_raise_ValueError(translate("Unable to read color palette data"));
+ }
+
+
+ } else if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124)) {
+ mp_raise_ValueError_varg(translate("Only Windows format, uncompressed BMP supported: given header size is %d"), header_size);
}
+
+ if ((bits_per_pixel == 4 ) || (( bits_per_pixel == 8) && (number_of_colors == 0))) {
+ mp_raise_ValueError_varg(translate("Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp given"), bits_per_pixel);
+ }
+
+ if (self->bits_per_pixel >=8){
+ self->stride = (self->width * (bits_per_pixel / 8));
+ // Rows are word aligned.
+ if (self->stride % 4 != 0) {
+ self->stride += 4 - self->stride % 4;
+ }
+
+ } else {
+ uint32_t bit_stride = self->width;
+ if (bit_stride % 32 != 0) {
+ bit_stride += 32 - bit_stride % 32;
+ }
+ self->stride = (bit_stride / 8);
+ }
+
}
@@ -80,14 +123,62 @@ uint32_t common_hal_displayio_ondiskbitmap_get_pixel(displayio_ondiskbitmap_t *s
if (x < 0 || x >= self->width || y < 0 || y >= self->height) {
return 0;
}
- uint32_t location = self->data_offset + (self->height - y) * self->stride + x * self->bytes_per_pixel;
+ uint32_t location;
+ uint8_t bytes_per_pixel = (self->bits_per_pixel / 8) ? (self->bits_per_pixel /8) : 1;
+ if (self->bits_per_pixel >= 8){
+ location = self->data_offset + (self->height - y) * self->stride + x * bytes_per_pixel;
+ } else {
+ location = self->data_offset + (self->height - y) * self->stride + x / 8;
+ }
// We don't cache here because the underlying FS caches sectors.
f_lseek(&self->file->fp, location);
UINT bytes_read;
- uint32_t pixel = 0;
- uint32_t result = f_read(&self->file->fp, &pixel, self->bytes_per_pixel, &bytes_read);
+ uint32_t pixel_data = 0;
+ uint32_t result = f_read(&self->file->fp, &pixel_data, bytes_per_pixel, &bytes_read);
if (result == FR_OK) {
- return pixel;
+ uint32_t tmp = 0;
+ uint8_t red;
+ uint8_t green;
+ uint8_t blue;
+ if (self->bits_per_pixel == 1){
+ uint8_t bit_offset = x%8;
+ tmp = ( pixel_data & (0x80 >> (bit_offset))) >> (7 - bit_offset);
+ if (tmp == 1) {
+ return 0x00FFFFFF;
+ } else {
+ return 0x00000000;
+ }
+ } else if (bytes_per_pixel == 1){
+ blue = ((self->palette_data[pixel_data] & 0xFF) >> 0);
+ red = ((self->palette_data[pixel_data] & 0xFF0000) >> 16);
+ green = ((self->palette_data[pixel_data] & 0xFF00) >> 8);
+ tmp = (red << 16 | green << 8 | blue );
+ return tmp;
+ } else if (bytes_per_pixel == 2) {
+ if (self->g_bitmask == 0x07e0) { // 565
+ red =((pixel_data & self->r_bitmask) >>11);
+ green = ((pixel_data & self->g_bitmask) >>5);
+ blue = ((pixel_data & self->b_bitmask) >> 0);
+ } else { // 555
+ red =((pixel_data & self->r_bitmask) >>10);
+ green = ((pixel_data & self->g_bitmask) >>4);
+ blue = ((pixel_data & self->b_bitmask) >> 0);
+ }
+ tmp = (red << 19 | green << 10 | blue << 3);
+ return tmp;
+ } else if ((bytes_per_pixel == 4) && (self->bitfield_compressed)) {
+ return pixel_data & 0x00FFFFFF;
+ } else {
+ return pixel_data;
+ }
}
return 0;
}
+
+uint16_t common_hal_displayio_ondiskbitmap_get_height(displayio_ondiskbitmap_t *self) {
+ return self->height;
+}
+
+uint16_t common_hal_displayio_ondiskbitmap_get_width(displayio_ondiskbitmap_t *self) {
+ return self->width;
+}
diff --git a/shared-module/displayio/OnDiskBitmap.h b/shared-module/displayio/OnDiskBitmap.h
index 31d6c9550..28426f11b 100644
--- a/shared-module/displayio/OnDiskBitmap.h
+++ b/shared-module/displayio/OnDiskBitmap.h
@@ -40,8 +40,13 @@ typedef struct {
uint16_t height;
uint16_t data_offset;
uint16_t stride;
+ uint32_t r_bitmask;
+ uint32_t g_bitmask;
+ uint32_t b_bitmask;
+ bool bitfield_compressed;
pyb_file_obj_t* file;
- uint8_t bytes_per_pixel;
+ uint8_t bits_per_pixel;
+ uint32_t* palette_data;
} displayio_ondiskbitmap_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_ONDISKBITMAP_H
diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c
index 5f410d786..e810be875 100644
--- a/shared-module/displayio/Palette.c
+++ b/shared-module/displayio/Palette.c
@@ -47,9 +47,9 @@ void common_hal_displayio_palette_make_transparent(displayio_palette_t* self, ui
void common_hal_displayio_palette_set_color(displayio_palette_t* self, uint32_t palette_index, uint32_t color) {
uint32_t shift = (palette_index % 2) * 16;
uint32_t masked = self->colors[palette_index / 2] & ~(0xffff << shift);
- uint32_t b5 = (color >> 19);
+ uint32_t r5 = (color >> 19);
uint32_t g6 = (color >> 10) & 0x3f;
- uint32_t r5 = (color >> 3) & 0x1f;
+ uint32_t b5 = (color >> 3) & 0x1f;
uint32_t packed = r5 << 11 | g6 << 5 | b5;
// swap bytes
packed = __builtin_bswap16(packed);
diff --git a/shared-module/displayio/Palette.h b/shared-module/displayio/Palette.h
index 5a5f1d287..3813e8bdd 100644
--- a/shared-module/displayio/Palette.h
+++ b/shared-module/displayio/Palette.h
@@ -36,7 +36,7 @@ typedef struct {
mp_obj_base_t base;
uint32_t* opaque;
uint32_t* colors;
- uint8_t color_count;
+ uint32_t color_count;
bool needs_refresh;
} displayio_palette_t;
diff --git a/shared-module/displayio/Shape.c b/shared-module/displayio/Shape.c
new file mode 100644
index 000000000..ab9ca735b
--- /dev/null
+++ b/shared-module/displayio/Shape.c
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/Shape.h"
+
+#include <string.h>
+
+#include "py/runtime.h"
+
+void common_hal_displayio_shape_construct(displayio_shape_t *self, uint32_t width,
+ uint32_t height, bool mirror_x, bool mirror_y) {
+ self->mirror_x = mirror_x;
+ self->mirror_y = mirror_y;
+ self->width = width;
+ if (self->mirror_x) {
+ width /= 2;
+ width += self->width % 2 - 1;
+ }
+ self->half_width = width;
+
+ self->height = height;
+ if (self->mirror_y) {
+ height /= 2;
+ height += self->height % 2 - 1;
+ }
+ self->half_height = height;
+
+ self->data = m_malloc(height * sizeof(uint32_t), false);
+ for (uint16_t i = 0; i <= height; i++) {
+ self->data[2 * i] = 0;
+ self->data[2 * i + 1] = width;
+ }
+}
+
+void common_hal_displayio_shape_set_boundary(displayio_shape_t *self, uint16_t y, uint16_t start_x, uint16_t end_x) {
+ if (y < 0 || y >= self->height || (self->mirror_y && y > self->half_height)) {
+ mp_raise_ValueError(translate("y value out of bounds"));
+ }
+ if (start_x < 0 || start_x > self->width || end_x < 0 || end_x > self->width) {
+ mp_raise_ValueError(translate("x value out of bounds"));
+ }
+ uint16_t half_width = self->width / 2 - 1 + self->width % 2;
+ if (self->mirror_x && (start_x > half_width || end_x > half_width)) {
+ mp_raise_ValueError_varg(translate("Maximum x value when mirrored is %d"), half_width);
+ }
+ self->data[2 * y] = start_x;
+ self->data[2 * y + 1] = end_x;
+}
+
+uint32_t common_hal_displayio_shape_get_pixel(void *obj, int16_t x, int16_t y) {
+ displayio_shape_t *self = obj;
+ if (x >= self->width || x < 0 || y >= self->height || y < 0) {
+ return 0;
+ }
+ if (self->mirror_x && x > self->half_width) {
+ x = self->width - 1 - x;
+ }
+ if (self->mirror_y && y > self->half_height) {
+ y = self->height - y - 1;
+ }
+ uint16_t start_x = self->data[2 * y];
+ uint16_t end_x = self->data[2 * y + 1];
+ if (x < start_x || x > end_x) {
+ return 0;
+ }
+ return 1;
+}
diff --git a/shared-module/displayio/Shape.h b/shared-module/displayio/Shape.h
new file mode 100644
index 000000000..ca054fe00
--- /dev/null
+++ b/shared-module/displayio/Shape.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SHAPE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SHAPE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint16_t width;
+ uint16_t height;
+ uint16_t half_width;
+ uint16_t half_height;
+ uint16_t* data;
+ bool mirror_x;
+ bool mirror_y;
+} displayio_shape_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SHAPE_H
diff --git a/shared-module/displayio/Sprite.c b/shared-module/displayio/Sprite.c
deleted file mode 100644
index 87600f721..000000000
--- a/shared-module/displayio/Sprite.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * This file is part of the Micro Python project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "shared-bindings/displayio/Sprite.h"
-
-#include "shared-bindings/displayio/Bitmap.h"
-#include "shared-bindings/displayio/ColorConverter.h"
-#include "shared-bindings/displayio/OnDiskBitmap.h"
-#include "shared-bindings/displayio/Palette.h"
-
-void common_hal_displayio_sprite_construct(displayio_sprite_t *self, mp_obj_t bitmap,
- mp_obj_t pixel_shader, uint16_t width, uint16_t height, uint16_t x, uint16_t y) {
- self->width = width;
- self->height = height;
- self->bitmap = bitmap;
- self->pixel_shader = pixel_shader;
- self->x = x;
- self->y = y;
-}
-
-void common_hal_displayio_sprite_get_position(displayio_sprite_t *self, int16_t* x, int16_t* y) {
- *x = self->x;
- *y = self->y;
-}
-
-void common_hal_displayio_sprite_set_position(displayio_sprite_t *self, int16_t x, int16_t y) {
- self->x = x;
- self->y = y;
- self->needs_refresh = true;
-}
-
-
-mp_obj_t common_hal_displayio_sprite_get_pixel_shader(displayio_sprite_t *self) {
- return self->pixel_shader;
-}
-
-void common_hal_displayio_sprite_set_pixel_shader(displayio_sprite_t *self, mp_obj_t pixel_shader) {
- self->pixel_shader = pixel_shader;
- self->needs_refresh = true;
-}
-
-bool displayio_sprite_get_pixel(displayio_sprite_t *self, int16_t x, int16_t y, uint16_t* pixel) {
- x -= self->x;
- y -= self->y;
- if (y < 0 || y >= self->height || x >= self->width || x < 0) {
- return false;
- }
- uint32_t value = 0;
- if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
- value = common_hal_displayio_bitmap_get_pixel(self->bitmap, x, y);
- } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
- value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, x, y);
- }
-
- if (self->pixel_shader == mp_const_none) {
- *pixel = value;
- return true;
- } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) && displayio_palette_get_color(self->pixel_shader, value, pixel)) {
- return true;
- } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type) && common_hal_displayio_colorconverter_convert(self->pixel_shader, value, pixel)) {
- return true;
- }
-
- return false;
-}
-
-bool displayio_sprite_needs_refresh(displayio_sprite_t *self) {
- return self->needs_refresh || displayio_palette_needs_refresh(self->pixel_shader);
-}
-
-void displayio_sprite_finish_refresh(displayio_sprite_t *self) {
- self->needs_refresh = false;
- displayio_palette_finish_refresh(self->pixel_shader);
- // TODO(tannewt): We could double buffer changes to position and move them over here.
- // That way they won't change during a refresh and tear.
-}
diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c
new file mode 100644
index 000000000..3212dfe8b
--- /dev/null
+++ b/shared-module/displayio/TileGrid.c
@@ -0,0 +1,193 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/TileGrid.h"
+
+#include "shared-bindings/displayio/Bitmap.h"
+#include "shared-bindings/displayio/ColorConverter.h"
+#include "shared-bindings/displayio/OnDiskBitmap.h"
+#include "shared-bindings/displayio/Palette.h"
+#include "shared-bindings/displayio/Shape.h"
+
+void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap,
+ uint16_t bitmap_width_in_tiles,
+ mp_obj_t pixel_shader, uint16_t width, uint16_t height,
+ uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) {
+ uint32_t total_tiles = width * height;
+ // Sprites will only have one tile so save a little memory by inlining values in the pointer.
+ uint8_t inline_tiles = sizeof(uint8_t*);
+ if (total_tiles <= inline_tiles) {
+ self->tiles = 0;
+ // Pack values into the pointer since there are only a few.
+ for (uint32_t i = 0; i < inline_tiles; i++) {
+ ((uint8_t*) &self->tiles)[i] = default_tile;
+ }
+ self->inline_tiles = true;
+ } else {
+ self->tiles = (uint8_t*) m_malloc(total_tiles, false);
+ for (uint32_t i = 0; i < total_tiles; i++) {
+ self->tiles[i] = default_tile;
+ }
+ self->inline_tiles = false;
+ }
+ self->bitmap_width_in_tiles = bitmap_width_in_tiles;
+ self->width_in_tiles = width;
+ self->height_in_tiles = height;
+ self->total_width = width * tile_width;
+ self->total_height = height * tile_height;
+ self->tile_width = tile_width;
+ self->tile_height = tile_height;
+ self->bitmap = bitmap;
+ self->pixel_shader = pixel_shader;
+ self->x = x;
+ self->y = y;
+}
+
+
+mp_int_t common_hal_displayio_tilegrid_get_x(displayio_tilegrid_t *self) {
+ return self->x;
+}
+void common_hal_displayio_tilegrid_set_x(displayio_tilegrid_t *self, mp_int_t x) {
+ self->needs_refresh = self->x != x;
+ self->x = x;
+}
+mp_int_t common_hal_displayio_tilegrid_get_y(displayio_tilegrid_t *self) {
+ return self->y;
+}
+
+void common_hal_displayio_tilegrid_set_y(displayio_tilegrid_t *self, mp_int_t y) {
+ self->needs_refresh = self->y != y;
+ self->y = y;
+}
+
+mp_obj_t common_hal_displayio_tilegrid_get_pixel_shader(displayio_tilegrid_t *self) {
+ return self->pixel_shader;
+}
+
+void common_hal_displayio_tilegrid_set_pixel_shader(displayio_tilegrid_t *self, mp_obj_t pixel_shader) {
+ self->pixel_shader = pixel_shader;
+ self->needs_refresh = true;
+}
+
+
+uint16_t common_hal_displayio_tilegrid_get_width(displayio_tilegrid_t *self) {
+ return self->width_in_tiles;
+}
+
+uint16_t common_hal_displayio_tilegrid_get_height(displayio_tilegrid_t *self) {
+ return self->height_in_tiles;
+}
+
+uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y) {
+ uint8_t* tiles = self->tiles;
+ if (self->inline_tiles) {
+ tiles = (uint8_t*) &self->tiles;
+ }
+ if (tiles == NULL) {
+ return 0;
+ }
+ return tiles[y * self->width_in_tiles + x];
+}
+
+void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index) {
+ uint8_t* tiles = self->tiles;
+ if (self->inline_tiles) {
+ tiles = (uint8_t*) &self->tiles;
+ }
+ if (tiles == NULL) {
+ return;
+ }
+ tiles[y * self->width_in_tiles + x] = tile_index;
+ self->needs_refresh = true;
+}
+
+
+void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y) {
+ self->top_left_x = x;
+ self->top_left_y = y;
+}
+bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t y, uint16_t* pixel) {
+ x -= self->x;
+ y -= self->y;
+ if (y < 0 || y >= self->total_height || x >= self->total_width || x < 0) {
+ return false;
+ }
+
+ uint8_t* tiles = self->tiles;
+ if (self->inline_tiles) {
+ tiles = (uint8_t*) &self->tiles;
+ }
+ if (tiles == NULL) {
+ return false;
+ }
+ uint16_t tile_location = ((y / self->tile_height + self->top_left_y) % self->height_in_tiles) * self->width_in_tiles + (x / self->tile_width + self->top_left_x) % self->width_in_tiles;
+ uint8_t tile = tiles[tile_location];
+ uint16_t tile_x = tile_x = (tile % self->bitmap_width_in_tiles) * self->tile_width + x % self->tile_width;
+ uint16_t tile_y = tile_y = (tile / self->bitmap_width_in_tiles) * self->tile_height + y % self->tile_height;
+
+ uint32_t value = 0;
+ if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
+ value = common_hal_displayio_bitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
+ value = common_hal_displayio_shape_get_pixel(self->bitmap, tile_x, tile_y);
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
+ value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ }
+
+ if (self->pixel_shader == mp_const_none) {
+ *pixel = value;
+ return true;
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) && displayio_palette_get_color(self->pixel_shader, value, pixel)) {
+ return true;
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type) && common_hal_displayio_colorconverter_convert(self->pixel_shader, value, pixel)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool displayio_tilegrid_needs_refresh(displayio_tilegrid_t *self) {
+ if (self->needs_refresh) {
+ return true;
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
+ return displayio_palette_needs_refresh(self->pixel_shader);
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
+ return displayio_colorconverter_needs_refresh(self->pixel_shader);
+ }
+
+ return false;
+}
+
+void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
+ self->needs_refresh = false;
+ if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
+ displayio_palette_finish_refresh(self->pixel_shader);
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
+ displayio_colorconverter_finish_refresh(self->pixel_shader);
+ }
+ // TODO(tannewt): We could double buffer changes to position and move them over here.
+ // That way they won't change during a refresh and tear.
+}
diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h
new file mode 100644
index 000000000..59645553d
--- /dev/null
+++ b/shared-module/displayio/TileGrid.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t bitmap;
+ mp_obj_t pixel_shader;
+ uint16_t x;
+ uint16_t y;
+ uint16_t bitmap_width_in_tiles;
+ uint16_t width_in_tiles;
+ uint16_t height_in_tiles;
+ uint16_t total_width;
+ uint16_t total_height;
+ uint16_t tile_width;
+ uint16_t tile_height;
+ uint16_t top_left_x;
+ uint16_t top_left_y;
+ uint8_t* tiles;
+ bool needs_refresh;
+ bool inline_tiles;
+} displayio_tilegrid_t;
+
+bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t y, uint16_t *pixel);
+bool displayio_tilegrid_needs_refresh(displayio_tilegrid_t *self);
+void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index df9c2963a..ced5b0fef 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -1,80 +1,216 @@
-#include "shared-bindings/displayio/FourWire.h"
-extern displayio_fourwire_obj_t board_display_obj;
+#include <string.h>
+#include "shared-module/displayio/__init__.h"
-void start_region_update(displayio_fourwire_obj_t* display, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
- // TODO delegate between different display types
- displayio_fourwire_start_region_update(display, x0, y0, x1, y1);
-}
-
-void finish_region_update(displayio_fourwire_obj_t* display) {
- // TODO delegate between different display types
- displayio_fourwire_finish_region_update(display);
-}
+#include "lib/utils/interrupt_char.h"
+#include "py/reload.h"
+#include "py/runtime.h"
+#include "shared-bindings/displayio/Bitmap.h"
+#include "shared-bindings/displayio/Display.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/displayio/Palette.h"
+#include "supervisor/shared/autoreload.h"
+#include "supervisor/shared/display.h"
+#include "supervisor/memory.h"
+#include "supervisor/usb.h"
-void finish_refresh(displayio_fourwire_obj_t* display) {
- // TODO delegate between different display types
- displayio_fourwire_finish_refresh(display);
-}
+primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
-bool frame_queued(displayio_fourwire_obj_t* display) {
- // TODO delegate between different display types
- return displayio_fourwire_frame_queued(display);
+static inline void swap(uint16_t* a, uint16_t* b) {
+ uint16_t temp = *a;
+ *a = *b;
+ *b = temp;
}
-bool refresh_queued(displayio_fourwire_obj_t* display) {
- // TODO delegate between different display types
- return displayio_fourwire_refresh_queued(display);
-}
-
-bool send_pixels(displayio_fourwire_obj_t* display, uint32_t* pixels, uint32_t length) {
- // TODO delegate between different display types
- return displayio_fourwire_send_pixels(display, pixels, length);
-}
+// Check for recursive calls to displayio_refresh_displays.
+bool refresh_displays_in_progress = false;
-void displayio_refresh_display(void) {
- displayio_fourwire_obj_t* display = &board_display_obj;
+void displayio_refresh_displays(void) {
+ if (mp_hal_is_interrupted()) {
+ return;
+ }
+ if (reload_requested) {
+ // Reload is about to happen, so don't redisplay.
+ return;
+ }
- if (!frame_queued(display)) {
+ if (refresh_displays_in_progress) {
+ // Don't allow recursive calls to this routine.
return;
}
- if (refresh_queued(display)) {
- // We compute the pixels
- uint16_t x0 = 0;
- uint16_t y0 = 0;
- uint16_t x1 = display->width;
- uint16_t y1 = display->height;
- size_t index = 0;
- //size_t row_size = (x1 - x0);
- uint16_t buffer_size = 256;
- uint32_t buffer[buffer_size / 2];
- start_region_update(display, x0, y0, x1, y1);
- for (uint16_t y = y0; y < y1; ++y) {
- for (uint16_t x = x0; x < x1; ++x) {
- uint16_t* pixel = &(((uint16_t*)buffer)[index]);
- *pixel = 0;
- if (display->current_group != NULL) {
- displayio_group_get_pixel(display->current_group, x, y, pixel);
- }
+ refresh_displays_in_progress = true;
+
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) {
+ // Skip null display.
+ continue;
+ }
+ displayio_display_obj_t* display = &displays[i].display;
+ displayio_display_update_backlight(display);
+
+ // Time to refresh at specified frame rate?
+ if (!displayio_display_frame_queued(display)) {
+ // Too soon. Try next display.
+ continue;
+ }
+ if (displayio_display_refresh_queued(display)) {
+ // We compute the pixels. r and c are row and column to match the display memory
+ // structure. x and y match location within the groups.
+ uint16_t c0 = 0;
+ uint16_t r0 = 0;
+ uint16_t c1 = display->width;
+ uint16_t r1 = display->height;
+ if (display->transpose_xy) {
+ swap(&c1, &r1);
+ }
+
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't acquire display bus; skip updating this display. Try next display.
+ continue;
+ }
+ displayio_display_set_region_to_update(display, c0, r0, c1, r1);
+ displayio_display_end_transaction(display);
+
+ uint16_t x0 = 0;
+ uint16_t x1 = display->width - 1;
+ uint16_t startx = 0;
+ int8_t dx = 1;
+ if (display->mirror_x) {
+ dx = -1;
+ startx = x1;
+ }
+ uint16_t y0 = 0;
+ uint16_t y1 = display->height - 1;
+ uint16_t starty = 0;
+ int8_t dy = 1;
+ if (display->mirror_y) {
+ dy = -1;
+ starty = y1;
+ }
+
+ bool transpose = false;
+ if (display->transpose_xy) {
+ transpose = true;
+ int8_t temp_dx = dx;
+ dx = dy;
+ dy = temp_dx;
+
+ swap(&starty, &startx);
+ swap(&x0, &y0);
+ swap(&x1, &y1);
+ }
+
+ size_t index = 0;
+ uint16_t buffer_size = 256;
+ uint32_t buffer[buffer_size / 2];
+ bool skip_this_display = false;
+
+ for (uint16_t y = starty; y0 <= y && y <= y1; y += dy) {
+ for (uint16_t x = startx; x0 <= x && x <= x1; x += dx) {
+ uint16_t* pixel = &(((uint16_t*)buffer)[index]);
+ *pixel = 0;
+
+ if (display->current_group != NULL) {
+ if (transpose) {
+ displayio_group_get_pixel(display->current_group, y, x, pixel);
+ } else {
+ displayio_group_get_pixel(display->current_group, x, y, pixel);
+ }
+ }
- index += 1;
- // The buffer is full, send it.
- if (index >= buffer_size) {
- if (!send_pixels(display, buffer, buffer_size / 2)) {
- finish_region_update(display);
- return;
+ index += 1;
+ // The buffer is full, send it.
+ if (index >= buffer_size) {
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't acquire display bus; skip the rest of the data. Try next display.
+ index = 0;
+ skip_this_display = true;
+ break;
+ }
+ displayio_display_send_pixels(display, buffer, buffer_size / 2);
+ displayio_display_end_transaction(display);
+ // TODO(tannewt): Make refresh displays faster so we don't starve other
+ // background tasks.
+ usb_background();
+ index = 0;
}
- index = 0;
}
}
+
+ if (skip_this_display) {
+ // Go on to next display.
+ continue;
+ }
+ // Send the remaining data.
+ if (index) {
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't get display bus. Skip the rest of the data. Try next display.
+ continue;
+ }
+ displayio_display_send_pixels(display, buffer, index * 2);
+ }
+ displayio_display_end_transaction(display);
+ }
+ displayio_display_finish_refresh(display);
+ }
+
+ // All done.
+ refresh_displays_in_progress = false;
+}
+
+void common_hal_displayio_release_displays(void) {
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ mp_const_obj_t bus_type = displays[i].fourwire_bus.base.type;
+ if (bus_type == NULL) {
+ continue;
+ } else if (bus_type == &displayio_fourwire_type) {
+ common_hal_displayio_fourwire_deinit(&displays[i].fourwire_bus);
+ } else if (bus_type == &displayio_parallelbus_type) {
+ common_hal_displayio_parallelbus_deinit(&displays[i].parallel_bus);
}
- // Send the remaining data.
- if (index && !send_pixels(display, buffer, index * 2)) {
- finish_region_update(display);
- return;
+ displays[i].fourwire_bus.base.type = &mp_type_NoneType;
+ }
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ release_display(&displays[i].display);
+ displays[i].display.base.type = &mp_type_NoneType;
+ }
+
+ supervisor_stop_terminal();
+}
+
+void reset_displays(void) {
+ #if CIRCUITPY_DISPLAYIO
+ // The SPI buses used by FourWires may be allocated on the heap so we need to move them inline.
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].fourwire_bus.base.type != &displayio_fourwire_type) {
+ continue;
+ }
+ displayio_fourwire_obj_t* fourwire = &displays[i].fourwire_bus;
+ if (((uint32_t) fourwire->bus) < ((uint32_t) &displays) ||
+ ((uint32_t) fourwire->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
+ busio_spi_obj_t* original_spi = fourwire->bus;
+ if (original_spi == board_spi()) {
+ continue;
+ }
+ memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t));
+ fourwire->bus = &fourwire->inline_bus;
+ // Check for other displays that use the same spi bus and swap them too.
+ for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
+ if (displays[i].fourwire_bus.bus == original_spi) {
+ displays[i].fourwire_bus.bus = &fourwire->inline_bus;
+ }
+ }
+ }
+ }
+
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].display.base.type == NULL) {
+ continue;
}
- finish_region_update(display);
+ displayio_display_obj_t* display = &displays[i].display;
+ display->auto_brightness = true;
+ common_hal_displayio_display_show(display, &circuitpython_splash);
}
- finish_refresh(display);
+ #endif
}
diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h
index 556af430d..5b56ed55c 100644
--- a/shared-module/displayio/__init__.h
+++ b/shared-module/displayio/__init__.h
@@ -27,6 +27,24 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
-void displayio_refresh_display(void);
+#include "shared-bindings/displayio/Display.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/displayio/ParallelBus.h"
+
+typedef struct {
+ union {
+ displayio_fourwire_obj_t fourwire_bus;
+ displayio_parallelbus_obj_t parallel_bus;
+ };
+ displayio_display_obj_t display;
+} primary_display_t;
+
+extern primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
+
+extern displayio_group_t circuitpython_splash;
+
+void displayio_refresh_displays(void);
+void reset_displays(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
diff --git a/shared-module/fontio/BuiltinFont.c b/shared-module/fontio/BuiltinFont.c
new file mode 100644
index 000000000..58820d524
--- /dev/null
+++ b/shared-module/fontio/BuiltinFont.c
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/fontio/BuiltinFont.h"
+
+
+#include "shared-bindings/fontio/Glyph.h"
+
+#include "py/objnamedtuple.h"
+
+mp_obj_t common_hal_fontio_builtinfont_get_bitmap(const fontio_builtinfont_t *self) {
+ return MP_OBJ_FROM_PTR(self->bitmap);
+}
+
+mp_obj_t common_hal_fontio_builtinfont_get_bounding_box(const fontio_builtinfont_t *self) {
+ mp_obj_t *items = m_new(mp_obj_t, 2);
+ items[0] = MP_OBJ_NEW_SMALL_INT(self->width);
+ items[1] = MP_OBJ_NEW_SMALL_INT(self->height);
+ return mp_obj_new_tuple(2, items);
+}
+
+uint8_t fontio_builtinfont_get_glyph_index(const fontio_builtinfont_t *self, mp_uint_t codepoint) {
+ if (codepoint >= 0x20 && codepoint <= 0x7e) {
+ return codepoint - 0x20;
+ }
+ // Do a linear search of the mapping for unicode.
+ const byte* j = self->unicode_characters;
+ uint8_t k = 0;
+ while (j < self->unicode_characters + self->unicode_characters_len) {
+ unichar potential_c = utf8_get_char(j);
+ j = utf8_next_char(j);
+ if (codepoint == potential_c) {
+ return 0x7f - 0x20 + k;
+ }
+ k++;
+ }
+ return 0xff;
+}
+
+mp_obj_t common_hal_fontio_builtinfont_get_glyph(const fontio_builtinfont_t *self, mp_uint_t codepoint) {
+ uint8_t glyph_index = fontio_builtinfont_get_glyph_index(self, codepoint);
+ if (glyph_index == 0xff) {
+ return mp_const_none;
+ }
+ mp_obj_t field_values[8] = {
+ MP_OBJ_FROM_PTR(self->bitmap),
+ MP_OBJ_NEW_SMALL_INT(glyph_index),
+ MP_OBJ_NEW_SMALL_INT(self->width),
+ MP_OBJ_NEW_SMALL_INT(self->height),
+ MP_OBJ_NEW_SMALL_INT(0),
+ MP_OBJ_NEW_SMALL_INT(0),
+ MP_OBJ_NEW_SMALL_INT(self->width),
+ MP_OBJ_NEW_SMALL_INT(0)
+ };
+ return namedtuple_make_new((const mp_obj_type_t*) &fontio_glyph_type, 8, field_values, NULL);
+}
diff --git a/shared-module/displayio/Sprite.h b/shared-module/fontio/BuiltinFont.h
index dc368c4b7..30b4ade8c 100644
--- a/shared-module/displayio/Sprite.h
+++ b/shared-module/fontio/BuiltinFont.h
@@ -24,27 +24,24 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SPRITE_H
-#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SPRITE_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_FONTIO_BUILTINFONT_H
+#define MICROPY_INCLUDED_SHARED_MODULE_FONTIO_BUILTINFONT_H
#include <stdbool.h>
#include <stdint.h>
#include "py/obj.h"
+#include "shared-bindings/displayio/Bitmap.h"
typedef struct {
mp_obj_base_t base;
- mp_obj_t bitmap;
- mp_obj_t pixel_shader;
- uint16_t x;
- uint16_t y;
- uint16_t width;
- uint16_t height;
- bool needs_refresh;
-} displayio_sprite_t;
+ const displayio_bitmap_t* bitmap;
+ uint8_t width;
+ uint8_t height;
+ const byte* unicode_characters;
+ uint16_t unicode_characters_len;
+} fontio_builtinfont_t;
-bool displayio_sprite_get_pixel(displayio_sprite_t *sprite, int16_t x, int16_t y, uint16_t *pixel);
-bool displayio_sprite_needs_refresh(displayio_sprite_t *self);
-void displayio_sprite_finish_refresh(displayio_sprite_t *self);
+uint8_t fontio_builtinfont_get_glyph_index(const fontio_builtinfont_t *self, mp_uint_t codepoint);
-#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SPRITE_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_FONTIO_BUILTINFONT_H
diff --git a/shared-module/fontio/__init__.c b/shared-module/fontio/__init__.c
new file mode 100644
index 000000000..674343c53
--- /dev/null
+++ b/shared-module/fontio/__init__.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// Nothing now.
diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c
index f09edd785..215e1356a 100644
--- a/shared-module/storage/__init__.c
+++ b/shared-module/storage/__init__.c
@@ -143,7 +143,7 @@ mp_obj_t common_hal_storage_getmount(const char *mount_path) {
return storage_object_from_path(mount_path);
}
-void common_hal_storage_remount(const char *mount_path, bool readonly) {
+void common_hal_storage_remount(const char *mount_path, bool readonly, bool disable_concurrent_write_protection) {
if (strcmp(mount_path, "/") != 0) {
mp_raise_OSError(MP_EINVAL);
}
@@ -156,7 +156,8 @@ void common_hal_storage_remount(const char *mount_path, bool readonly) {
}
#endif
- supervisor_flash_set_usb_writable(readonly);
+ filesystem_set_internal_writable_by_usb(readonly);
+ filesystem_set_internal_concurrent_write_protection(!disable_concurrent_write_protection);
}
void common_hal_storage_erase_filesystem(void) {
diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c
index 78c04f07b..245dbbda9 100644
--- a/shared-module/struct/__init__.c
+++ b/shared-module/struct/__init__.c
@@ -71,45 +71,6 @@ mp_uint_t get_fmt_num(const char **p) {
return val;
}
-void shared_modules_struct_pack_into(mp_obj_t fmt_in, byte *p, byte* end_p, size_t n_args, const mp_obj_t *args) {
- const char *fmt = mp_obj_str_get_str(fmt_in);
- char fmt_type = get_fmt_type(&fmt);
-
- size_t i;
- for (i = 0; i < n_args;) {
- mp_uint_t sz = 1;
- if (*fmt == '\0') {
- // more arguments given than used by format string; CPython raises struct.error here
- mp_raise_RuntimeError(translate("too many arguments provided with the given format"));
- }
- struct_validate_format(*fmt);
-
- if (unichar_isdigit(*fmt)) {
- sz = get_fmt_num(&fmt);
- }
- if (p + sz > end_p) {
- mp_raise_RuntimeError(translate("buffer too small"));
- }
-
- if (*fmt == 's') {
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ);
- mp_uint_t to_copy = sz;
- if (bufinfo.len < to_copy) {
- to_copy = bufinfo.len;
- }
- memcpy(p, bufinfo.buf, to_copy);
- memset(p + to_copy, 0, sz - to_copy);
- p += sz;
- } else {
- while (sz--) {
- mp_binary_set_val(fmt_type, *fmt, args[i++], &p);
- }
- }
- fmt++;
- }
-}
-
mp_uint_t calcsize_items(const char *fmt) {
mp_uint_t cnt = 0;
while (*fmt) {
@@ -120,7 +81,10 @@ mp_uint_t calcsize_items(const char *fmt) {
num = 1;
}
}
- cnt += num;
+ // Pad bytes are skipped and don't get included in the item count.
+ if (*fmt != 'x') {
+ cnt += num;
+ }
fmt++;
}
return cnt;
@@ -155,14 +119,71 @@ mp_uint_t shared_modules_struct_calcsize(mp_obj_t fmt_in) {
return size;
}
+void shared_modules_struct_pack_into(mp_obj_t fmt_in, byte *p, byte* end_p, size_t n_args, const mp_obj_t *args) {
+ const char *fmt = mp_obj_str_get_str(fmt_in);
+ char fmt_type = get_fmt_type(&fmt);
+ const mp_uint_t total_sz = shared_modules_struct_calcsize(fmt_in);
+
+ if (p + total_sz > end_p) {
+ mp_raise_RuntimeError(translate("buffer too small"));
+ }
+
+ size_t i;
+ for (i = 0; i < n_args;) {
+ mp_uint_t sz = 1;
+ if (*fmt == '\0') {
+ // more arguments given than used by format string; CPython raises struct.error here
+ mp_raise_RuntimeError(translate("too many arguments provided with the given format"));
+ }
+ struct_validate_format(*fmt);
+
+ if (unichar_isdigit(*fmt)) {
+ sz = get_fmt_num(&fmt);
+ }
+
+ if (*fmt == 's') {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ);
+ mp_uint_t to_copy = sz;
+ if (bufinfo.len < to_copy) {
+ to_copy = bufinfo.len;
+ }
+ memcpy(p, bufinfo.buf, to_copy);
+ memset(p + to_copy, 0, sz - to_copy);
+ p += sz;
+ } else {
+ while (sz--) {
+ mp_binary_set_val(fmt_type, *fmt, args[i], &p);
+ // Pad bytes don't have a corresponding argument.
+ if (*fmt != 'x') {
+ i++;
+ }
+ }
+ }
+ fmt++;
+ }
+}
-mp_obj_tuple_t * shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byte *end_p) {
+mp_obj_tuple_t * shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byte *end_p, bool exact_size) {
const char *fmt = mp_obj_str_get_str(fmt_in);
char fmt_type = get_fmt_type(&fmt);
- mp_uint_t num_items = calcsize_items(fmt);
+ const mp_uint_t num_items = calcsize_items(fmt);
+ const mp_uint_t total_sz = shared_modules_struct_calcsize(fmt_in);
mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_items, NULL));
+ // If exact_size, make sure the buffer is exactly the right size.
+ // Otherwise just make sure it's big enough.
+ if (exact_size) {
+ if (p + total_sz != end_p) {
+ mp_raise_RuntimeError(translate("buffer size must match format"));
+ }
+ } else {
+ if (p + total_sz > end_p) {
+ mp_raise_RuntimeError(translate("buffer too small"));
+ }
+ }
+
for (uint i = 0; i < num_items;) {
mp_uint_t sz = 1;
@@ -171,9 +192,6 @@ mp_obj_tuple_t * shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byt
if (unichar_isdigit(*fmt)) {
sz = get_fmt_num(&fmt);
}
- if (p + sz > end_p) {
- mp_raise_RuntimeError(translate("buffer too small"));
- }
mp_obj_t item;
if (*fmt == 's') {
item = mp_obj_new_bytes(p, sz);
@@ -182,7 +200,10 @@ mp_obj_tuple_t * shared_modules_struct_unpack_from(mp_obj_t fmt_in, byte *p, byt
} else {
while (sz--) {
item = mp_binary_get_val(fmt_type, *fmt, &p);
- res->items[i++] = item;
+ // Pad bytes are not stored.
+ if (*fmt != 'x') {
+ res->items[i++] = item;
+ }
}
}
fmt++;
diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c
new file mode 100644
index 000000000..7adf9d032
--- /dev/null
+++ b/shared-module/terminalio/Terminal.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/terminalio/Terminal.h"
+
+#include "shared-module/fontio/BuiltinFont.h"
+#include "shared-bindings/displayio/TileGrid.h"
+
+void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, displayio_tilegrid_t* tilegrid, const fontio_builtinfont_t* font) {
+ self->cursor_x = 0;
+ self->cursor_y = 0;
+ self->font = font;
+ self->tilegrid = tilegrid;
+ self->first_row = 0;
+}
+
+size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) {
+ const byte* i = data;
+ uint16_t start_y = self->cursor_y;
+ while (i < data + len) {
+ unichar c = utf8_get_char(i);
+ i = utf8_next_char(i);
+ // Always handle ASCII.
+ if (c < 128) {
+ if (c >= 0x20 && c <= 0x7e) {
+ uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c);
+ common_hal_displayio_tilegrid_set_tile(self->tilegrid, self->cursor_x, self->cursor_y, tile_index);
+ self->cursor_x++;
+ } else if (c == '\r') {
+ self->cursor_x = 0;
+ } else if (c == '\n') {
+ self->cursor_y++;
+ // Commands below are used by MicroPython in the REPL
+ } else if (c == '\b') {
+ if (self->cursor_x > 0) {
+ self->cursor_x--;
+ }
+ } else if (c == 0x1b) {
+ if (i[0] == '[') {
+ if (i[1] == 'K') {
+ // Clear the rest of the line.
+ for (uint16_t j = self->cursor_x; j < self->tilegrid->width_in_tiles; j++) {
+ common_hal_displayio_tilegrid_set_tile(self->tilegrid, j, self->cursor_y, 0);
+ }
+ i += 2;
+ } else {
+ // Handle commands of the form \x1b[####D
+ uint16_t n = 0;
+ uint8_t j = 1;
+ for (; j < 6; j++) {
+ if ('0' <= i[j] && i[j] <= '9') {
+ n = n * 10 + (i[j] - '0');
+ } else {
+ c = i[j];
+ break;
+ }
+ }
+ if (c == 'D') {
+ if (n > self->cursor_x) {
+ self->cursor_x = 0;
+ } else {
+ self->cursor_x -= n;
+ }
+ }
+ i += j + 1;
+ continue;
+ }
+ }
+ }
+ } else {
+ uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c);
+ if (tile_index != 0xff) {
+ common_hal_displayio_tilegrid_set_tile(self->tilegrid, self->cursor_x, self->cursor_y, tile_index);
+ self->cursor_x++;
+
+ }
+ }
+ if (self->cursor_x >= self->tilegrid->width_in_tiles) {
+ self->cursor_y++;
+ self->cursor_x %= self->tilegrid->width_in_tiles;
+ }
+ if (self->cursor_y >= self->tilegrid->height_in_tiles) {
+ self->cursor_y %= self->tilegrid->height_in_tiles;
+ }
+ if (self->cursor_y != start_y) {
+ // clear the new row
+ for (uint16_t j = 0; j < self->tilegrid->width_in_tiles; j++) {
+ common_hal_displayio_tilegrid_set_tile(self->tilegrid, j, self->cursor_y, 0);
+ start_y = self->cursor_y;
+ }
+ common_hal_displayio_tilegrid_set_top_left(self->tilegrid, 0, (start_y + self->tilegrid->height_in_tiles + 1) % self->tilegrid->height_in_tiles);
+ }
+ }
+ return i - data;
+}
+
+bool common_hal_terminalio_terminal_ready_to_tx(terminalio_terminal_obj_t *self) {
+ return true;
+}
diff --git a/shared-module/terminalio/Terminal.h b/shared-module/terminalio/Terminal.h
new file mode 100644
index 000000000..c31392cc4
--- /dev/null
+++ b/shared-module/terminalio/Terminal.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_TERMINALIO_TERMINAL_H
+#define SHARED_MODULE_TERMINALIO_TERMINAL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+#include "shared-module/fontio/BuiltinFont.h"
+#include "shared-module/displayio/TileGrid.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ const fontio_builtinfont_t* font;
+ uint16_t cursor_x;
+ uint16_t cursor_y;
+ displayio_tilegrid_t* tilegrid;
+ uint16_t first_row;
+} terminalio_terminal_obj_t;
+
+#endif /* SHARED_MODULE_TERMINALIO_TERMINAL_H */
diff --git a/shared-module/terminalio/__init__.c b/shared-module/terminalio/__init__.c
new file mode 100644
index 000000000..3f61f4823
--- /dev/null
+++ b/shared-module/terminalio/__init__.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/terminalio/__init__.h"
diff --git a/shared-module/terminalio/__init__.h b/shared-module/terminalio/__init__.h
new file mode 100644
index 000000000..e925dd429
--- /dev/null
+++ b/shared-module/terminalio/__init__.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_TERMINALIO___INIT___H
+#define SHARED_MODULE_TERMINALIO___INIT___H
+
+#endif /* SHARED_MODULE_TERMINALIO___INIT___H */
diff --git a/shared-module/usb_midi/PortIn.c b/shared-module/usb_midi/PortIn.c
new file mode 100644
index 000000000..31e320baa
--- /dev/null
+++ b/shared-module/usb_midi/PortIn.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/usb_midi/PortIn.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+size_t common_hal_usb_midi_portin_read(usb_midi_portin_obj_t *self, uint8_t *data, size_t len, int *errcode) {
+ return tud_midi_read(data, len);
+}
+
+uint32_t common_hal_usb_midi_portin_bytes_available(usb_midi_portin_obj_t *self) {
+ return tud_midi_available();
+}
diff --git a/shared-module/usb_midi/PortIn.h b/shared-module/usb_midi/PortIn.h
new file mode 100644
index 000000000..2f72aa4c2
--- /dev/null
+++ b/shared-module/usb_midi/PortIn.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_USB_MIDI_PORTIN_H
+#define SHARED_MODULE_USB_MIDI_PORTIN_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} usb_midi_portin_obj_t;
+
+#endif /* SHARED_MODULE_USB_MIDI_PORTIN_H */
diff --git a/shared-module/usb_midi/PortOut.c b/shared-module/usb_midi/PortOut.c
new file mode 100644
index 000000000..99a4fad43
--- /dev/null
+++ b/shared-module/usb_midi/PortOut.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-module/usb_midi/PortOut.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+size_t common_hal_usb_midi_portout_write(usb_midi_portout_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
+ return tud_midi_write(0, data, len);
+}
+
+bool common_hal_usb_midi_portout_ready_to_tx(usb_midi_portout_obj_t *self) {
+ return tud_midi_connected();
+}
diff --git a/shared-module/usb_midi/PortOut.h b/shared-module/usb_midi/PortOut.h
new file mode 100644
index 000000000..6b1b88464
--- /dev/null
+++ b/shared-module/usb_midi/PortOut.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_USB_MIDI_PORTOUT_H
+#define SHARED_MODULE_USB_MIDI_PORTOUT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} usb_midi_portout_obj_t;
+
+#endif /* SHARED_MODULE_USB_MIDI_PORTOUT_H */
diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c
new file mode 100644
index 000000000..73a314b99
--- /dev/null
+++ b/shared-module/usb_midi/__init__.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/usb_midi/__init__.h"
+
+#include "genhdr/autogen_usb_descriptor.h"
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "py/runtime.h"
+#include "py/objtuple.h"
+#include "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/usb_midi/PortOut.h"
+#include "supervisor/memory.h"
+#include "tusb.h"
+
+supervisor_allocation* usb_midi_allocation;
+
+void usb_midi_init(void) {
+ // TODO(tannewt): Make this dynamic.
+ uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
+ uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
+ uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
+
+ // For each embedded MIDI Jack in the descriptor we create a Port
+ usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false);
+
+ mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr;
+ ports->base.type = &mp_type_tuple;
+ ports->len = 2;
+
+ usb_midi_portin_obj_t* in = (usb_midi_portin_obj_t *) (usb_midi_allocation->ptr + tuple_size / 4);
+ in->base.type = &usb_midi_portin_type;
+ ports->items[0] = MP_OBJ_FROM_PTR(in);
+
+ usb_midi_portout_obj_t* out = (usb_midi_portout_obj_t *) (usb_midi_allocation->ptr + tuple_size / 4 + portin_size / 4);
+ out->base.type = &usb_midi_portout_type;
+ ports->items[1] = MP_OBJ_FROM_PTR(out);
+
+ mp_map_lookup(&usb_midi_module_globals.map, MP_ROM_QSTR(MP_QSTR_ports), MP_MAP_LOOKUP)->value = MP_OBJ_FROM_PTR(ports);
+}
diff --git a/shared-module/usb_midi/__init__.h b/shared-module/usb_midi/__init__.h
new file mode 100644
index 000000000..e1ad1fbaf
--- /dev/null
+++ b/shared-module/usb_midi/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef SHARED_MODULE_USB_MIDI___INIT___H
+#define SHARED_MODULE_USB_MIDI___INIT___H
+
+void usb_midi_init(void);
+
+#endif /* SHARED_MODULE_USB_MIDI___INIT___H */