summaryrefslogtreecommitdiff
path: root/shared-module
diff options
context:
space:
mode:
Diffstat (limited to 'shared-module')
-rw-r--r--shared-module/_pixelbuf/PixelBuf.c78
-rw-r--r--shared-module/_pixelbuf/PixelBuf.h3
-rw-r--r--shared-module/bitmaptools/__init__.c174
-rw-r--r--shared-module/displayio/Bitmap.c29
-rw-r--r--shared-module/displayio/Group.c235
-rw-r--r--shared-module/displayio/Group.h12
-rw-r--r--shared-module/rgbmatrix/RGBMatrix.c4
-rw-r--r--shared-module/rgbmatrix/RGBMatrix.h1
-rw-r--r--shared-module/usb_hid/Device.c6
9 files changed, 393 insertions, 149 deletions
diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c
index f3e679631..4cbf6dc21 100644
--- a/shared-module/_pixelbuf/PixelBuf.c
+++ b/shared-module/_pixelbuf/PixelBuf.c
@@ -31,6 +31,7 @@
#include "py/runtime.h"
#include "shared-bindings/_pixelbuf/PixelBuf.h"
#include <string.h>
+#include <math.h>
// Helper to ensure we have the native super class instead of a subclass.
static pixelbuf_pixelbuf_obj_t* native_pixelbuf(mp_obj_t pixelbuf_obj) {
@@ -69,6 +70,7 @@ void common_hal__pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size
}
// Call set_brightness so that it can allocate a second buffer if needed.
self->brightness = 1.0;
+ self->scaled_brightness = 0x100;
common_hal__pixelbuf_pixelbuf_set_brightness(MP_OBJ_FROM_PTR(self), brightness);
// Turn on auto_write. We don't want to do it with the above brightness call.
@@ -109,26 +111,32 @@ void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t b
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
// Skip out if the brightness is already set. The default of self->brightness is 1.0. So, this
// also prevents the pre_brightness_buffer allocation when brightness is set to 1.0 again.
- mp_float_t change = brightness - self->brightness;
- if (-0.001 < change && change < 0.001) {
+ self->brightness = brightness;
+ // Use 256 steps of brightness so that we can do integer math below.
+ uint16_t new_scaled_brightness = (uint16_t)(brightness * 256);
+ if (new_scaled_brightness == self->scaled_brightness) {
return;
}
- self->brightness = brightness;
+ self->scaled_brightness = new_scaled_brightness;
size_t pixel_len = self->pixel_count * self->bytes_per_pixel;
- if (self->pre_brightness_buffer == NULL) {
- self->pre_brightness_buffer = m_malloc(pixel_len, false);
- memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len);
- }
- for (size_t i = 0; i < pixel_len; i++) {
- // Don't adjust per-pixel luminance bytes in dotstar mode
- if (self->byteorder.is_dotstar && i % 4 == 0) {
- continue;
+ if (self->scaled_brightness == 0x100 && !self->pre_brightness_buffer) {
+ return;
+ } else {
+ if (self->pre_brightness_buffer == NULL) {
+ self->pre_brightness_buffer = m_malloc(pixel_len, false);
+ memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len);
+ }
+ for (size_t i = 0; i < pixel_len; i++) {
+ // Don't adjust per-pixel luminance bytes in dotstar mode
+ if (self->byteorder.is_dotstar && i % 4 == 0) {
+ continue;
+ }
+ self->post_brightness_buffer[i] = (self->pre_brightness_buffer[i] * self->scaled_brightness) / 256;
}
- self->post_brightness_buffer[i] = self->pre_brightness_buffer[i] * self->brightness;
- }
- if (self->auto_write) {
- common_hal__pixelbuf_pixelbuf_show(self_in);
+ if (self->auto_write) {
+ common_hal__pixelbuf_pixelbuf_show(self_in);
+ }
}
}
@@ -197,28 +205,34 @@ void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint
}
pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder;
size_t offset = index * self->bytes_per_pixel;
- if (self->pre_brightness_buffer != NULL) {
- uint8_t* pre_brightness_buffer = self->pre_brightness_buffer + offset;
- if (self->bytes_per_pixel == 4) {
- pre_brightness_buffer[rgbw_order->w] = w;
- }
-
- pre_brightness_buffer[rgbw_order->r] = r;
- pre_brightness_buffer[rgbw_order->g] = g;
- pre_brightness_buffer[rgbw_order->b] = b;
+ uint8_t *scaled_buffer, *unscaled_buffer;
+ if (self->pre_brightness_buffer) {
+ scaled_buffer = self->post_brightness_buffer + offset;
+ unscaled_buffer = self->pre_brightness_buffer + offset;
+ } else {
+ scaled_buffer = NULL;
+ unscaled_buffer = self->post_brightness_buffer + offset;
}
- uint8_t* post_brightness_buffer = self->post_brightness_buffer + offset;
if (self->bytes_per_pixel == 4) {
- // Only apply brightness if w is actually white (aka not DotStar.)
- if (!self->byteorder.is_dotstar) {
- w *= self->brightness;
+ unscaled_buffer[rgbw_order->w] = w;
+ }
+
+ unscaled_buffer[rgbw_order->r] = r;
+ unscaled_buffer[rgbw_order->g] = g;
+ unscaled_buffer[rgbw_order->b] = b;
+
+ if (scaled_buffer) {
+ if (self->bytes_per_pixel == 4) {
+ if (!self->byteorder.is_dotstar) {
+ w = (w * self->scaled_brightness) / 256;
+ }
+ scaled_buffer[rgbw_order->w] = w;
}
- post_brightness_buffer[rgbw_order->w] = w;
+ scaled_buffer[rgbw_order->r] = (r * self->scaled_brightness) / 256;
+ scaled_buffer[rgbw_order->g] = (g * self->scaled_brightness) / 256;
+ scaled_buffer[rgbw_order->b] = (b * self->scaled_brightness) / 256;
}
- post_brightness_buffer[rgbw_order->r] = r * self->brightness;
- post_brightness_buffer[rgbw_order->g] = g * self->brightness;
- post_brightness_buffer[rgbw_order->b] = b * self->brightness;
}
void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t value) {
diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h
index a9fbed366..f0c80bcad 100644
--- a/shared-module/_pixelbuf/PixelBuf.h
+++ b/shared-module/_pixelbuf/PixelBuf.h
@@ -49,7 +49,8 @@ typedef struct {
typedef struct {
mp_obj_base_t base;
size_t pixel_count;
- size_t bytes_per_pixel;
+ uint16_t bytes_per_pixel;
+ uint16_t scaled_brightness;
pixelbuf_byteorder_details_t byteorder;
mp_float_t brightness;
mp_obj_t transmit_buffer_obj;
diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c
new file mode 100644
index 000000000..7dc4024ef
--- /dev/null
+++ b/shared-module/bitmaptools/__init__.c
@@ -0,0 +1,174 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Kevin Matocha
+ *
+ * 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/Bitmap.h"
+
+#include "py/runtime.h"
+
+#include "math.h"
+
+void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy,
+ int16_t dest_clip0_x, int16_t dest_clip0_y,
+ int16_t dest_clip1_x, int16_t dest_clip1_y,
+ displayio_bitmap_t *source, int16_t px, int16_t py,
+ int16_t source_clip0_x, int16_t source_clip0_y,
+ int16_t source_clip1_x, int16_t source_clip1_y,
+ float angle,
+ float scale,
+ uint32_t skip_index, bool skip_index_none) {
+
+ // Copies region from source to the destination bitmap, including rotation,
+ // scaling and clipping of either the source or destination regions
+ //
+ // *self: destination bitmap
+ // ox: the (ox, oy) destination point where the source (px,py) point is placed
+ // oy:
+ // dest_clip0: (x,y) is the corner of the clip window on the destination bitmap
+ // dest_clip1: (x,y) is the other corner of the clip window of the destination bitmap
+ // *source: the source bitmap
+ // px: the (px, py) point of rotation of the source bitmap
+ // py:
+ // source_clip0: (x,y) is the corner of the clip window on the source bitmap
+ // source_clip1: (x,y) is the other of the clip window on the source bitmap
+ // angle: angle of rotation in radians, positive is clockwise
+ // scale: scale factor
+ // skip_index: color index that should be ignored (and not copied over)
+ // skip_index_none: if skip_index_none is True, then all color indexes should be copied
+ // (that is, no color indexes should be skipped)
+
+
+ // Copy complete "source" bitmap into "self" bitmap at location x,y in the "self"
+ // Add a boolean to determine if all values are copied, or only if non-zero
+ // If skip_value is encountered in the source bitmap, it will not be copied.
+ // If skip_value is `None`, then all pixels are copied.
+
+
+ // # Credit from https://github.com/wernsey/bitmap
+ // # MIT License from
+ // # * Copyright (c) 2017 Werner Stoop <wstoop@gmail.com>
+ // #
+ // # *
+ // # * #### `void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, int py, double angle, double scale);`
+ // # *
+ // # * Rotates a source bitmap `src` around a pivot point `px,py` and blits it onto a destination bitmap `dst`.
+ // # *
+ // # * The bitmap is positioned such that the point `px,py` on the source is at the offset `ox,oy` on the destination.
+ // # *
+ // # * The `angle` is clockwise, in radians. The bitmap is also scaled by the factor `scale`.
+ // #
+ // # void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, int py, double angle, double scale);
+
+
+ // # /*
+ // # Reference:
+ // # "Fast Bitmap Rotation and Scaling" By Steven Mortimer, Dr Dobbs' Journal, July 01, 2001
+ // # http://www.drdobbs.com/architecture-and-design/fast-bitmap-rotation-and-scaling/184416337
+ // # See also http://www.efg2.com/Lab/ImageProcessing/RotateScanline.htm
+ // # */
+
+
+ if (self->read_only) {
+ mp_raise_RuntimeError(translate("Read-only object"));
+ }
+
+ int16_t x,y;
+
+ int16_t minx = dest_clip1_x;
+ int16_t miny = dest_clip1_y;
+ int16_t maxx = dest_clip0_x;
+ int16_t maxy = dest_clip0_y;
+
+ float sinAngle = sinf(angle);
+ float cosAngle = cosf(angle);
+
+ float dx, dy;
+
+ /* Compute the position of where each corner on the source bitmap
+ will be on the destination to get a bounding box for scanning */
+ dx = -cosAngle * px * scale + sinAngle * py * scale + ox;
+ dy = -sinAngle * px * scale - cosAngle * py * scale + oy;
+ if(dx < minx) minx = (int16_t)dx;
+ if(dx > maxx) maxx = (int16_t)dx;
+ if(dy < miny) miny = (int16_t)dy;
+ if(dy > maxy) maxy = (int16_t)dy;
+
+ dx = cosAngle * (source->width - px) * scale + sinAngle * py * scale + ox;
+ dy = sinAngle * (source->width - px) * scale - cosAngle * py * scale + oy;
+ if(dx < minx) minx = (int16_t)dx;
+ if(dx > maxx) maxx = (int16_t)dx;
+ if(dy < miny) miny = (int16_t)dy;
+ if(dy > maxy) maxy = (int16_t)dy;
+
+ dx = cosAngle * (source->width - px) * scale - sinAngle * (source->height - py) * scale + ox;
+ dy = sinAngle * (source->width - px) * scale + cosAngle * (source->height - py) * scale + oy;
+ if(dx < minx) minx = (int16_t)dx;
+ if(dx > maxx) maxx = (int16_t)dx;
+ if(dy < miny) miny = (int16_t)dy;
+ if(dy > maxy) maxy = (int16_t)dy;
+
+ dx = -cosAngle * px * scale - sinAngle * (source->height - py) * scale + ox;
+ dy = -sinAngle * px * scale + cosAngle * (source->height - py) * scale + oy;
+ if(dx < minx) minx = (int16_t)dx;
+ if(dx > maxx) maxx = (int16_t)dx;
+ if(dy < miny) miny = (int16_t)dy;
+ if(dy > maxy) maxy = (int16_t)dy;
+
+ /* Clipping */
+ if(minx < dest_clip0_x) minx = dest_clip0_x;
+ if(maxx > dest_clip1_x - 1) maxx = dest_clip1_x - 1;
+ if(miny < dest_clip0_y) miny = dest_clip0_y;
+ if(maxy > dest_clip1_y - 1) maxy = dest_clip1_y - 1;
+
+ float dvCol = cosAngle / scale;
+ float duCol = sinAngle / scale;
+
+ float duRow = dvCol;
+ float dvRow = -duCol;
+
+ float startu = px - (ox * dvCol + oy * duCol);
+ float startv = py - (ox * dvRow + oy * duRow);
+
+ float rowu = startu + miny * duCol;
+ float rowv = startv + miny * dvCol;
+
+ for(y = miny; y <= maxy; y++) {
+ float u = rowu + minx * duRow;
+ float v = rowv + minx * dvRow;
+ for(x = minx; x <= maxx; x++) {
+ if(u >= source_clip0_x && u < source_clip1_x && v >= source_clip0_y && v < source_clip1_y) {
+ uint32_t c = common_hal_displayio_bitmap_get_pixel(source, u, v);
+ if( (skip_index_none) || (c != skip_index) ) {
+ common_hal_displayio_bitmap_set_pixel(self, x, y, c);
+ }
+ }
+ u += duRow;
+ v += dvRow;
+ }
+ rowu += duCol;
+ rowv += dvCol;
+ }
+}
diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c
index d1942efc7..c9ea83428 100644
--- a/shared-module/displayio/Bitmap.c
+++ b/shared-module/displayio/Bitmap.c
@@ -116,14 +116,33 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16
mp_raise_RuntimeError(translate("Read-only object"));
}
+ bool x_reverse = false;
+ bool y_reverse = false;
+
+ // Add reverse direction option to protect blitting of self bitmap back into self bitmap
+ if (x > x1) {
+ x_reverse = true;
+ }
+ if (y > y1) {
+ y_reverse = true;
+ }
+
// simplest version - use internal functions for get/set pixels
- for (int16_t i=0; i < (x2-x1) ; i++) {
- if ( (x+i >= 0) && (x+i < self->width) ) {
+ for (int16_t i=0; i < (x2-x1); i++) {
+
+ const int xs_index = x_reverse ? ( (x2) - i - 1) : x1+i; // x-index into the source bitmap
+ const int xd_index = x_reverse ? ((x + (x2-x1)) - i - 1) : x+i; // x-index into the destination bitmap
+
+ if ( (xd_index >= 0) && (xd_index < self->width) ) {
for (int16_t j=0; j < (y2-y1) ; j++){
- if ((y+j >= 0) && (y+j < self->height) ) {
- uint32_t value = common_hal_displayio_bitmap_get_pixel(source, x1+i, y1+j);
+
+ const int ys_index = y_reverse ? ( (y2 ) - j - 1) : y1+j ; // y-index into the source bitmap
+ const int yd_index = y_reverse ? ((y + (y2-y1)) - j - 1) : y+j ; // y-index into the destination bitmap
+
+ if ((yd_index >= 0) && (yd_index < self->height) ) {
+ uint32_t value = common_hal_displayio_bitmap_get_pixel(source, xs_index, ys_index);
if ( (skip_index_none) || (value != skip_index) ) { // write if skip_value_none is True
- common_hal_displayio_bitmap_set_pixel(self, x+i, y+j, value);
+ common_hal_displayio_bitmap_set_pixel(self, xd_index, yd_index, value);
}
}
}
diff --git a/shared-module/displayio/Group.c b/shared-module/displayio/Group.c
index 15cf5b8e4..42efeb18c 100644
--- a/shared-module/displayio/Group.c
+++ b/shared-module/displayio/Group.c
@@ -27,6 +27,7 @@
#include "shared-bindings/displayio/Group.h"
#include "py/runtime.h"
+#include "py/objlist.h"
#include "shared-bindings/displayio/TileGrid.h"
#if CIRCUITPY_VECTORIO
@@ -34,9 +35,9 @@
#endif
-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_construct(displayio_group_t* self, uint32_t scale, mp_int_t x, mp_int_t y) {
+ mp_obj_list_t *members = mp_obj_new_list(0, NULL);
+ displayio_group_construct(self, members, scale, x, y);
}
bool common_hal_displayio_group_get_hidden(displayio_group_t* self) {
@@ -51,12 +52,19 @@ void common_hal_displayio_group_set_hidden(displayio_group_t* self, bool hidden)
if (self->hidden_by_parent) {
return;
}
- for (size_t i = 0; i < self->size; i++) {
- mp_obj_t layer = self->children[i].native;
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ for (size_t i = 0; i < self->members->len; i++) {
+ mp_obj_t layer;
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
displayio_tilegrid_set_hidden_by_parent(layer, hidden);
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ continue;
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
displayio_group_set_hidden_by_parent(layer, hidden);
+ continue;
}
}
}
@@ -70,12 +78,19 @@ void displayio_group_set_hidden_by_parent(displayio_group_t *self, bool hidden)
if (self->hidden) {
return;
}
- for (size_t i = 0; i < self->size; i++) {
- mp_obj_t layer = self->children[i].native;
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ for (size_t i = 0; i < self->members->len; i++) {
+ mp_obj_t layer;
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
displayio_tilegrid_set_hidden_by_parent(layer, hidden);
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ continue;
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
displayio_group_set_hidden_by_parent(layer, hidden);
+ continue;
}
}
}
@@ -86,16 +101,22 @@ uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self) {
bool displayio_group_get_previous_area(displayio_group_t *self, displayio_area_t* area) {
bool first = true;
- for (size_t i = 0; i < self->size; i++) {
- mp_obj_t layer = self->children[i].native;
+ for (size_t i = 0; i < self->members->len; i++) {
+ mp_obj_t layer;
displayio_area_t layer_area;
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
if (!displayio_tilegrid_get_previous_area(layer, &layer_area)) {
continue;
}
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
- if (!displayio_group_get_previous_area(layer, &layer_area)) {
- continue;
+ } else {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
+ if (!displayio_group_get_previous_area(layer, &layer_area)) {
+ continue;
+ }
}
}
if (first) {
@@ -120,18 +141,27 @@ static void _update_child_transforms(displayio_group_t* self) {
if (!self->in_group) {
return;
}
- for (size_t i = 0; i < self->size; i++) {
- mp_obj_t layer = self->children[i].native;
+ for (size_t i = 0; i < self->members->len; i++) {
+ mp_obj_t layer;
#if CIRCUITPY_VECTORIO
- if (MP_OBJ_IS_TYPE(layer, &vectorio_vector_shape_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &vectorio_vector_shape_type);
+ if (layer != MP_OBJ_NULL) {
vectorio_vector_shape_update_transform(layer, &self->absolute_transform);
+ continue;
}
- else
#endif
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
displayio_tilegrid_update_transform(layer, &self->absolute_transform);
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ continue;
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
displayio_group_update_transform(layer, &self->absolute_transform);
+ continue;
}
}
}
@@ -210,21 +240,17 @@ void common_hal_displayio_group_set_y(displayio_group_t* self, mp_int_t y) {
_update_child_transforms(self);
}
-static mp_obj_t _add_layer(displayio_group_t* self, mp_obj_t layer) {
+static void _add_layer(displayio_group_t* self, mp_obj_t layer) {
mp_obj_t native_layer;
#if CIRCUITPY_VECTORIO
native_layer = mp_instance_cast_to_native_base(layer, &vectorio_vector_shape_type);
if (native_layer != MP_OBJ_NULL) {
vectorio_vector_shape_update_transform(native_layer, &self->absolute_transform);
- return native_layer;
+ return;
}
#endif
- 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."));
- }
+ native_layer = mp_instance_cast_to_native_base(layer, &displayio_tilegrid_type);
+ if (native_layer != MP_OBJ_NULL) {
displayio_tilegrid_t* tilegrid = native_layer;
if (tilegrid->in_group) {
mp_raise_ValueError(translate("Layer already in a group."));
@@ -232,7 +258,10 @@ static mp_obj_t _add_layer(displayio_group_t* self, mp_obj_t layer) {
tilegrid->in_group = true;
}
displayio_tilegrid_update_transform(tilegrid, &self->absolute_transform);
- } else {
+ return;
+ }
+ native_layer = mp_instance_cast_to_native_base(layer, &displayio_group_type);
+ if (native_layer != MP_OBJ_NULL) {
displayio_group_t* group = native_layer;
if (group->in_group) {
mp_raise_ValueError(translate("Layer already in a group."));
@@ -240,27 +269,34 @@ static mp_obj_t _add_layer(displayio_group_t* self, mp_obj_t layer) {
group->in_group = true;
}
displayio_group_update_transform(group, &self->absolute_transform);
+ return;
}
- return native_layer;
+ mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass."));
}
static void _remove_layer(displayio_group_t* self, size_t index) {
- mp_obj_t layer = self->children[index].native;
+ mp_obj_t layer;
displayio_area_t layer_area;
bool rendered_last_frame = false;
#if CIRCUITPY_VECTORIO
- if (MP_OBJ_IS_TYPE(layer, &vectorio_vector_shape_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[index], &vectorio_vector_shape_type);
+ if (layer != MP_OBJ_NULL) {
bool has_dirty_area = vectorio_vector_shape_get_dirty_area(layer, &layer_area);
rendered_last_frame = has_dirty_area;
vectorio_vector_shape_update_transform(layer, NULL);
}
- else
#endif
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[index], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
displayio_tilegrid_t* tilegrid = layer;
rendered_last_frame = displayio_tilegrid_get_previous_area(tilegrid, &layer_area);
displayio_tilegrid_update_transform(tilegrid, NULL);
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[index], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
displayio_group_t* group = layer;
rendered_last_frame = displayio_group_get_previous_area(group, &layer_area);
displayio_group_update_transform(group, NULL);
@@ -277,62 +313,40 @@ static void _remove_layer(displayio_group_t* self, size_t index) {
}
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"));
- }
- mp_obj_t native_layer = _add_layer(self, layer);
- // Shift everything right.
- for (size_t i = self->size; i > index; i--) {
- self->children[i] = self->children[i - 1];
- }
- self->children[index].native = native_layer;
- self->children[index].original = layer;
- self->size++;
+ _add_layer(self, layer);
+ mp_obj_list_insert(self->members, index, layer);
}
mp_obj_t common_hal_displayio_group_pop(displayio_group_t* self, size_t index) {
- self->size--;
- mp_obj_t item = self->children[index].original;
_remove_layer(self, index);
-
- // 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;
- return item;
+ return mp_obj_list_pop(self->members, index);
}
mp_int_t common_hal_displayio_group_index(displayio_group_t* self, mp_obj_t layer) {
- for (size_t i = 0; i < self->size; i++) {
- if (self->children[i].original == layer) {
- return i;
- }
- }
- return -1;
+ mp_obj_t args[] = {self->members, layer};
+ mp_obj_t *index = mp_seq_index_obj(
+ self->members->items, self->members->len, 2, args);
+ return MP_OBJ_SMALL_INT_VALUE(index);
}
size_t common_hal_displayio_group_get_len(displayio_group_t* self) {
- return self->size;
+ return self->members->len;
}
mp_obj_t common_hal_displayio_group_get(displayio_group_t* self, size_t index) {
- return self->children[index].original;
+ return self->members->items[index];
}
void common_hal_displayio_group_set(displayio_group_t* self, size_t index, mp_obj_t layer) {
- mp_obj_t native_layer = _add_layer(self, layer);
+ _add_layer(self, layer);
_remove_layer(self, index);
- self->children[index].native = native_layer;
- self->children[index].original = layer;
+ mp_obj_list_store(self, MP_OBJ_NEW_SMALL_INT(index), layer);
}
-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) {
+void displayio_group_construct(displayio_group_t* self, mp_obj_list_t* members, 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->members = members;
self->item_removed = false;
self->scale = scale;
self->in_group = false;
@@ -341,47 +355,61 @@ void displayio_group_construct(displayio_group_t* self, displayio_group_child_t*
bool displayio_group_fill_area(displayio_group_t *self, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t* buffer) {
// Track if any of the layers finishes filling in the given area. We can ignore any remaining
// layers at that point.
- bool full_coverage = false;
- for (int32_t i = self->size - 1; i >= 0 ; i--) {
- mp_obj_t layer = self->children[i].native;
+ for (int32_t i = self->members->len - 1; i >= 0 ; i--) {
+ mp_obj_t layer;
#if CIRCUITPY_VECTORIO
- if (MP_OBJ_IS_TYPE(layer, &vectorio_vector_shape_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &vectorio_vector_shape_type);
+ if (layer != MP_OBJ_NULL) {
if (vectorio_vector_shape_fill_area(layer, colorspace, area, mask, buffer)) {
- full_coverage = true;
- break;
+ return true;
}
+ continue;
}
- else
#endif
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
if (displayio_tilegrid_fill_area(layer, colorspace, area, mask, buffer)) {
- full_coverage = true;
- break;
+ return true;
}
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ continue;
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
if (displayio_group_fill_area(layer, colorspace, area, mask, buffer)) {
- full_coverage = true;
- break;
+ return true;
}
+ continue;
}
}
- return full_coverage;
+ return false;
}
void displayio_group_finish_refresh(displayio_group_t *self) {
self->item_removed = false;
- for (int32_t i = self->size - 1; i >= 0 ; i--) {
- mp_obj_t layer = self->children[i].native;
+ for (int32_t i = self->members->len - 1; i >= 0 ; i--) {
+ mp_obj_t layer;
#if CIRCUITPY_VECTORIO
- if (MP_OBJ_IS_TYPE(layer, &vectorio_vector_shape_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &vectorio_vector_shape_type);
+ if (layer != MP_OBJ_NULL) {
vectorio_vector_shape_finish_refresh(layer);
+ continue;
}
- else
#endif
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
displayio_tilegrid_finish_refresh(layer);
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ continue;
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
displayio_group_finish_refresh(layer);
+ continue;
}
}
}
@@ -392,18 +420,27 @@ displayio_area_t* displayio_group_get_refresh_areas(displayio_group_t *self, dis
tail = &self->dirty_area;
}
- for (int32_t i = self->size - 1; i >= 0 ; i--) {
- mp_obj_t layer = self->children[i].native;
+ for (int32_t i = self->members->len - 1; i >= 0 ; i--) {
+ mp_obj_t layer;
#if CIRCUITPY_VECTORIO
- if (MP_OBJ_IS_TYPE(layer, &vectorio_vector_shape_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &vectorio_vector_shape_type);
+ if (layer != MP_OBJ_NULL) {
tail = vectorio_vector_shape_get_refresh_areas(layer, tail);
+ continue;
}
- else
#endif
- if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_tilegrid_type);
+ if (layer != MP_OBJ_NULL) {
tail = displayio_tilegrid_get_refresh_areas(layer, tail);
- } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ continue;
+ }
+ layer = mp_instance_cast_to_native_base(
+ self->members->items[i], &displayio_group_type);
+ if (layer != MP_OBJ_NULL) {
tail = displayio_group_get_refresh_areas(layer, tail);
+ continue;
}
}
diff --git a/shared-module/displayio/Group.h b/shared-module/displayio/Group.h
index 5afaac1ba..0964e0a0b 100644
--- a/shared-module/displayio/Group.h
+++ b/shared-module/displayio/Group.h
@@ -31,24 +31,18 @@
#include <stdint.h>
#include "py/obj.h"
+#include "py/objlist.h"
#include "shared-module/displayio/area.h"
#include "shared-module/displayio/Palette.h"
typedef struct {
- mp_obj_t native;
- mp_obj_t original;
-} displayio_group_child_t;
-
-typedef struct {
mp_obj_base_t base;
- displayio_group_child_t* children;
+ mp_obj_list_t *members;
displayio_buffer_transform_t absolute_transform;
displayio_area_t dirty_area; // Catch all for changed area
int16_t x;
int16_t y;
uint16_t scale;
- uint16_t size;
- uint16_t max_size;
bool item_removed :1;
bool in_group :1;
bool hidden :1;
@@ -56,7 +50,7 @@ typedef struct {
uint8_t padding :4;
} displayio_group_t;
-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);
+void displayio_group_construct(displayio_group_t* self, mp_obj_list_t* members, uint32_t scale, mp_int_t x, mp_int_t y);
void displayio_group_set_hidden_by_parent(displayio_group_t *self, bool hidden);
bool displayio_group_get_previous_area(displayio_group_t *group, displayio_area_t* area);
bool displayio_group_fill_area(displayio_group_t *group, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
diff --git a/shared-module/rgbmatrix/RGBMatrix.c b/shared-module/rgbmatrix/RGBMatrix.c
index b8db0d893..a688d7fd6 100644
--- a/shared-module/rgbmatrix/RGBMatrix.c
+++ b/shared-module/rgbmatrix/RGBMatrix.c
@@ -56,7 +56,7 @@ void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t *self, i
self->tile = tile;
self->serpentine = serpentine;
- self->timer = timer ? timer : common_hal_rgbmatrix_timer_allocate();
+ self->timer = timer ? timer : common_hal_rgbmatrix_timer_allocate(self);
if (self->timer == NULL) {
mp_raise_ValueError(translate("No timer available"));
}
@@ -68,6 +68,8 @@ void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t *self, i
}
void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, mp_obj_t framebuffer) {
+ self->paused = 1;
+
common_hal_rgbmatrix_timer_disable(self->timer);
if (framebuffer) {
self->framebuffer = framebuffer;
diff --git a/shared-module/rgbmatrix/RGBMatrix.h b/shared-module/rgbmatrix/RGBMatrix.h
index 4a0e9235e..65bfc9799 100644
--- a/shared-module/rgbmatrix/RGBMatrix.h
+++ b/shared-module/rgbmatrix/RGBMatrix.h
@@ -26,6 +26,7 @@
#pragma once
+#include "py/obj.h"
#include "lib/protomatter/src/core.h"
extern const mp_obj_type_t rgbmatrix_RGBMatrix_type;
diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c
index 943c9bfed..2b560c328 100644
--- a/shared-module/usb_hid/Device.c
+++ b/shared-module/usb_hid/Device.c
@@ -73,7 +73,8 @@ static usb_hid_device_obj_t* get_hid_device(uint8_t report_id) {
}
// Callbacks invoked when receive Get_Report request through control endpoint
-uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
+uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
+ (void) itf;
// only support Input Report
if ( report_type != HID_REPORT_TYPE_INPUT ) return 0;
@@ -83,7 +84,8 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type,
}
// Callbacks invoked when receive Set_Report request through control endpoint
-void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
+void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
+ (void) itf;
if (report_type == HID_REPORT_TYPE_INVALID) {
report_id = buffer[0];
buffer++;