Skip to content

Commit 7881ed5

Browse files
committed
Pixelbuf: Support 565-format
This is needed for the Protomatter LED matrix
1 parent 070b0dc commit 7881ed5

File tree

2 files changed

+60
-21
lines changed

2 files changed

+60
-21
lines changed

shared-bindings/_pixelbuf/PixelBuf.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t
136136
}
137137
parsed->order_string = byteorder_obj;
138138

139+
if (bo_len == 3 && !strcmp(byteorder, "565")) {
140+
parsed->is_dotstar = false;
141+
parsed->has_white = false;
142+
parsed->bpp = 2;
143+
parsed->byteorder.r = 0;
144+
parsed->byteorder.g = 1;
145+
parsed->byteorder.b = 2;
146+
parsed->byteorder.w = 0;
147+
return;
148+
}
149+
139150
parsed->bpp = bo_len;
140151
char *dotstar = strchr(byteorder, 'P');
141152
char *r = strchr(byteorder, 'R');

shared-module/_pixelbuf/PixelBuf.c

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_
169169
mp_obj_t *items;
170170
size_t len;
171171
mp_obj_get_array(color, &len, &items);
172-
if (len != byteorder->bpp && !byteorder->is_dotstar) {
172+
size_t n_elems = self->byteorder.bpp == 2 ? 3 : self->byteorder.bpp;
173+
if (len != n_elems && !byteorder->is_dotstar) {
173174
mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len);
174175
}
175176

@@ -187,8 +188,6 @@ void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_
187188
}
188189

189190
void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
190-
// DotStars don't have white, instead they have 5 bit brightness so pack it into w. Shift right
191-
// by three to leave the top five bits.
192191
if (self->bytes_per_pixel == 4 && self->byteorder.is_dotstar) {
193192
w = DOTSTAR_LED_START | w >> 3;
194193
}
@@ -200,9 +199,15 @@ void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint
200199
pre_brightness_buffer[rgbw_order->w] = w;
201200
}
202201

203-
pre_brightness_buffer[rgbw_order->r] = r;
204-
pre_brightness_buffer[rgbw_order->g] = g;
205-
pre_brightness_buffer[rgbw_order->b] = b;
202+
if (self->bytes_per_pixel == 2) {
203+
uint16_t rgb565 = ((r << 8) & 0xf800) | ((g <<3) & 0xfc0) | (b >> 3);
204+
pre_brightness_buffer[0] = rgb565 & 0xff;
205+
pre_brightness_buffer[1] = rgb565 >> 8;
206+
} else {
207+
pre_brightness_buffer[rgbw_order->r] = r;
208+
pre_brightness_buffer[rgbw_order->g] = g;
209+
pre_brightness_buffer[rgbw_order->b] = b;
210+
}
206211
}
207212

208213
uint8_t* post_brightness_buffer = self->post_brightness_buffer + offset;
@@ -213,9 +218,18 @@ void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint
213218
}
214219
post_brightness_buffer[rgbw_order->w] = w;
215220
}
216-
post_brightness_buffer[rgbw_order->r] = r * self->brightness;
217-
post_brightness_buffer[rgbw_order->g] = g * self->brightness;
218-
post_brightness_buffer[rgbw_order->b] = b * self->brightness;
221+
if (self->bytes_per_pixel == 2) {
222+
r *= self->brightness;
223+
g *= self->brightness;
224+
b *= self->brightness;
225+
uint16_t rgb565 = ((r << 8) & 0xf800) | ((g <<3) & 0x0fc0) | (b >> 3);
226+
post_brightness_buffer[0] = rgb565 & 0xff;
227+
post_brightness_buffer[1] = rgb565 >> 8;
228+
} else {
229+
post_brightness_buffer[rgbw_order->r] = r * self->brightness;
230+
post_brightness_buffer[rgbw_order->g] = g * self->brightness;
231+
post_brightness_buffer[rgbw_order->b] = b * self->brightness;
232+
}
219233
}
220234

221235
void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t value) {
@@ -249,27 +263,41 @@ void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self_in, size_t index, mp_
249263

250264
mp_obj_t common_hal__pixelbuf_pixelbuf_get_pixel(mp_obj_t self_in, size_t index) {
251265
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
252-
mp_obj_t elems[self->byteorder.bpp];
266+
size_t n_elems = self->byteorder.bpp == 2 ? 3 : self->byteorder.bpp;
267+
mp_obj_t elems[n_elems];
253268
uint8_t* pixel_buffer = self->post_brightness_buffer;
254269
if (self->pre_brightness_buffer != NULL) {
255270
pixel_buffer = self->pre_brightness_buffer;
256271
}
257272
pixel_buffer += self->byteorder.bpp * index;
258273

259-
pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder;
260-
elems[0] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->r]);
261-
elems[1] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->g]);
262-
elems[2] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->b]);
263-
if (self->byteorder.bpp > 3) {
264-
uint8_t w = pixel_buffer[rgbw_order->w];
265-
if (self->byteorder.is_dotstar) {
266-
elems[3] = mp_obj_new_float((w & 0b00011111) / 31.0);
267-
} else {
268-
elems[3] = MP_OBJ_NEW_SMALL_INT(w);
274+
if (self->byteorder.bpp == 2) {
275+
uint16_t rgb565 = pixel_buffer[0] + (pixel_buffer[1] << 8);
276+
uint8_t r = rgb565 >> 11;
277+
uint8_t g = (rgb565 >> 5) & 0x3f;
278+
uint8_t b = rgb565 >> 5 & 0x1f;
279+
r |= r >> 3;
280+
g |= g >> 2;
281+
b |= b >> 3;
282+
elems[0] = MP_OBJ_NEW_SMALL_INT(r);
283+
elems[1] = MP_OBJ_NEW_SMALL_INT(g);
284+
elems[2] = MP_OBJ_NEW_SMALL_INT(b);
285+
} else {
286+
pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder;
287+
elems[0] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->r]);
288+
elems[1] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->g]);
289+
elems[2] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->b]);
290+
if (self->byteorder.bpp > 3) {
291+
uint8_t w = pixel_buffer[rgbw_order->w];
292+
if (self->byteorder.is_dotstar) {
293+
elems[3] = mp_obj_new_float((w & 0b00011111) / 31.0);
294+
} else {
295+
elems[3] = MP_OBJ_NEW_SMALL_INT(w);
296+
}
269297
}
270298
}
271299

272-
return mp_obj_new_tuple(self->byteorder.bpp, elems);
300+
return mp_obj_new_tuple(n_elems, elems);
273301
}
274302

275303
void common_hal__pixelbuf_pixelbuf_show(mp_obj_t self_in) {

0 commit comments

Comments
 (0)