diff --git a/micropython/modules/pico_scroll/README.md b/micropython/modules/pico_scroll/README.md index 54d681c2..d4629dc7 100644 --- a/micropython/modules/pico_scroll/README.md +++ b/micropython/modules/pico_scroll/README.md @@ -85,6 +85,24 @@ image = bytearray(0 for j in range(width * height)) picoscroll.set_pixels(image) ``` +### show_bitmap_1d + +Show a view of a bitmap stored as the 7 least significant bits of +bytes in a `bytearray`, top-down. Individual pixels are set to +`brightness` based on individual bit values, with the view defined by +the offset and the width of the scroll (i.e. 17 columns). Changes will +not be visible until `update()` is called. + +```python +bitmap = bytearray(j for j in range 127) +for offset in range(-17, 127): + picoscroll.show_bitmap_1d(bitmap, 16, offset) + picoscroll.update() +``` + +will scroll a binary counter across the display (i.e. show `0x00` to +`0x7f` in binary). + ### update Pushes pixel data from the Pico to the Scroll Pack. Until this function is called any `set_pixel` or `clear` calls won't have any visible effect. diff --git a/micropython/modules/pico_scroll/pico_scroll.c b/micropython/modules/pico_scroll/pico_scroll.c index b1968268..d406ba1e 100644 --- a/micropython/modules/pico_scroll/pico_scroll.c +++ b/micropython/modules/pico_scroll/pico_scroll.c @@ -21,6 +21,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_get_height_obj, picoscroll_get_heigh STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_update_obj, picoscroll_update); STATIC MP_DEFINE_CONST_FUN_OBJ_3(picoscroll_set_pixel_obj, picoscroll_set_pixel); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_set_pixels_obj, picoscroll_set_pixels); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picoscroll_show_bitmap_1d_obj, picoscroll_show_bitmap_1d); STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_clear_obj, picoscroll_clear); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_is_pressed_obj, picoscroll_is_pressed); @@ -33,6 +34,7 @@ STATIC const mp_map_elem_t picoscroll_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picoscroll_update_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&picoscroll_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixels), MP_ROM_PTR(&picoscroll_set_pixels_obj) }, + { MP_ROM_QSTR(MP_QSTR_show_bitmap_1d), MP_ROM_PTR(&picoscroll_show_bitmap_1d_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picoscroll_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picoscroll_is_pressed_obj) }, { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_INT(BUTTON_A) }, diff --git a/micropython/modules/pico_scroll/pico_scroll.cpp b/micropython/modules/pico_scroll/pico_scroll.cpp index a048e987..5112b15a 100644 --- a/micropython/modules/pico_scroll/pico_scroll.cpp +++ b/micropython/modules/pico_scroll/pico_scroll.cpp @@ -13,8 +13,8 @@ extern "C" { #include "pico_scroll.h" #define NOT_INITIALISED_MSG "Cannot call this function, as picoscroll is not initialised. Call picoscroll.init() first." - #define BUFFER_TOO_SMALL_MSG "bytearray too small: len(image) < width * height." +#define INCORRECT_SIZE_MSG "Scroll height wrong: > 8 pixels." mp_obj_t picoscroll_init() { if(scroll == nullptr) @@ -84,6 +84,47 @@ mp_obj_t picoscroll_set_pixels(mp_obj_t image_obj) { return mp_const_none; } +mp_obj_t picoscroll_show_bitmap_1d(mp_obj_t bitmap_obj, mp_obj_t brightness_obj, mp_obj_t offset_obj) { + if(scroll != nullptr) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(bitmap_obj, &bufinfo, MP_BUFFER_RW); + int offset = mp_obj_get_int(offset_obj); + int brightness = mp_obj_get_int(brightness_obj); + int length = bufinfo.len; + int width = PicoScroll::WIDTH; + int height = PicoScroll::HEIGHT; + + // this obviously shouldn't happen as the scroll is 17x7 pixels + if (height > (int) sizeof(unsigned char)) { + mp_raise_msg(&mp_type_RuntimeError, INCORRECT_SIZE_MSG); + } + + unsigned char * values = (unsigned char *) bufinfo.buf; + + // clear the scroll, so only need to write visible bytes + scroll->clear(); + + if ((offset < -width) || (offset > length)) { + return mp_const_none; + } + + for (int x = 0; x < width; x++) { + int k = offset + x; + if ((k >= 0) && (k <= length)) { + unsigned char col = values[k]; + for (int y = 0; y < height; y++) { + int val = brightness * ((col >> y) & 1); + scroll->set_pixel(x, height - 1 - y, val); + } + } + } + } else { + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + } + + return mp_const_none; +} + mp_obj_t picoscroll_clear() { if(scroll != nullptr) scroll->clear(); diff --git a/micropython/modules/pico_scroll/pico_scroll.h b/micropython/modules/pico_scroll/pico_scroll.h index 166792b1..9ab507bd 100644 --- a/micropython/modules/pico_scroll/pico_scroll.h +++ b/micropython/modules/pico_scroll/pico_scroll.h @@ -8,5 +8,6 @@ extern mp_obj_t picoscroll_get_height(); extern mp_obj_t picoscroll_update(); extern mp_obj_t picoscroll_set_pixel(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj); extern mp_obj_t picoscroll_set_pixels(mp_obj_t image_obj); +extern mp_obj_t picoscroll_show_bitmap_1d(mp_obj_t bitmap_obj, mp_obj_t brightness, mp_obj_t offset); extern mp_obj_t picoscroll_clear(); extern mp_obj_t picoscroll_is_pressed(mp_obj_t button_obj);