diff --git a/libraries/pico_scroll/pico_scroll.cpp b/libraries/pico_scroll/pico_scroll.cpp index 42677798..f04aabe9 100644 --- a/libraries/pico_scroll/pico_scroll.cpp +++ b/libraries/pico_scroll/pico_scroll.cpp @@ -32,13 +32,6 @@ enum reg { COLOR_OFFSET = 0x24 }; -void i2c_write(uint8_t reg, const char *data, uint8_t len) { - uint8_t buffer[256]; - buffer[0] = reg; - memcpy(&buffer[1], data, len); - i2c_write_blocking(i2c0, 0x74, buffer, len + 1, true); -} - namespace pimoroni { void PicoScroll::init() { @@ -65,17 +58,17 @@ namespace pimoroni { } void PicoScroll::set_pixel(uint8_t x, uint8_t y, uint8_t v) { - if(x < 0 || x > 16 || y < 0 || y > 6) return; + if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; - y = 6 - y; + y = (HEIGHT - 1) - y; if(x > 8) { x = x - 8; - y = 6 - (y + 8); + y = (HEIGHT - 1) - (y + 8); }else{ x = 8 - x; } - uint8_t o = x * 16 + y; + uint8_t o = x * (WIDTH - 1) + y; __fb[o] = v; } @@ -84,10 +77,17 @@ namespace pimoroni { } void PicoScroll::clear() { - memset(__fb, 0, 144); + memset(__fb, 0, BUFFER_SIZE); } void PicoScroll::update() { - i2c_write(COLOR_OFFSET, (const char *)__fb, 144); + i2c_write(COLOR_OFFSET, (const char *)__fb, BUFFER_SIZE); + } + + void PicoScroll::i2c_write(uint8_t reg, const char *data, uint8_t len) { + uint8_t buffer[256]; + buffer[0] = reg; + memcpy(&buffer[1], data, len); + i2c_write_blocking(i2c0, DEFAULT_ADDRESS, buffer, len + 1, true); } } \ No newline at end of file diff --git a/libraries/pico_scroll/pico_scroll.hpp b/libraries/pico_scroll/pico_scroll.hpp index 2563224a..d2981273 100644 --- a/libraries/pico_scroll/pico_scroll.hpp +++ b/libraries/pico_scroll/pico_scroll.hpp @@ -3,8 +3,20 @@ namespace pimoroni { class PicoScroll { - uint8_t __fb[144]; + private: + static const uint8_t DEFAULT_ADDRESS = 0x74; + static const uint BUFFER_SIZE = 144; + public: + static const int WIDTH = 17; + static const int HEIGHT = 7; + static const uint8_t A = 12; + static const uint8_t B = 13; + static const uint8_t X = 14; + static const uint8_t Y = 15; + private: + uint8_t __fb[BUFFER_SIZE]; + public: void init(); void update(); @@ -12,10 +24,8 @@ namespace pimoroni { void clear(); bool is_pressed(uint8_t button); - static const uint8_t A = 12; - static const uint8_t B = 13; - static const uint8_t X = 14; - static const uint8_t Y = 15; + private: + void i2c_write(uint8_t reg, const char *data, uint8_t len); }; } \ No newline at end of file diff --git a/micropython/modules/pico_scroll/micropython.mk b/micropython/modules/pico_scroll/micropython.mk new file mode 100755 index 00000000..65c703b4 --- /dev/null +++ b/micropython/modules/pico_scroll/micropython.mk @@ -0,0 +1,12 @@ +PICOSCROLL_MOD_DIR := $(USERMOD_DIR) + +# Add our source files to the respective variables. +SRC_USERMOD += $(PICOSCROLL_MOD_DIR)/pico_scroll.c +SRC_USERMOD_CXX += $(PICOSCROLL_MOD_DIR)/pico_scroll.cpp + +# Add our module directory to the include path. +CFLAGS_USERMOD += -I$(PICOSCROLL_MOD_DIR) +CXXFLAGS_USERMOD += -I$(PICOSCROLL_MOD_DIR) + +# We use C++ features so have to link against the standard library. +LDFLAGS_USERMOD += -lstdc++ \ No newline at end of file diff --git a/micropython/modules/pico_scroll/pico_scroll.c b/micropython/modules/pico_scroll/pico_scroll.c new file mode 100644 index 00000000..d59b7008 --- /dev/null +++ b/micropython/modules/pico_scroll/pico_scroll.c @@ -0,0 +1,52 @@ +#include "pico_scroll.h" + +/***** Constants *****/ +enum buttons +{ + BUTTON_A = 0, + BUTTON_B, + BUTTON_X, + BUTTON_Y, +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// picoscroll Module +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Module Functions *****/ +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_init_obj, picoscroll_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_get_width_obj, picoscroll_get_width); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_get_height_obj, picoscroll_get_height); +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_0(picoscroll_clear_obj, picoscroll_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_is_pressed_obj, picoscroll_is_pressed); + +/***** Globals Table *****/ +STATIC const mp_map_elem_t picoscroll_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picoscroll) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picoscroll_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picoscroll_get_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picoscroll_get_height_obj) }, + { 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_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) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_INT(BUTTON_B) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_X), MP_ROM_INT(BUTTON_X) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_Y), MP_ROM_INT(BUTTON_Y) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_picoscroll_globals, picoscroll_globals_table); + +/***** Module Definition *****/ +const mp_obj_module_t picoscroll_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_picoscroll_globals, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +MP_REGISTER_MODULE(MP_QSTR_picoscroll, picoscroll_user_cmodule, MODULE_PICOSCROLL_ENABLED); +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/micropython/modules/pico_scroll/pico_scroll.cpp b/micropython/modules/pico_scroll/pico_scroll.cpp new file mode 100644 index 00000000..0639a21b --- /dev/null +++ b/micropython/modules/pico_scroll/pico_scroll.cpp @@ -0,0 +1,85 @@ +#include "hardware/spi.h" +#include "hardware/sync.h" +#include "pico/binary_info.h" + +#include "../../../pimoroni-pico/libraries/pico_scroll/pico_scroll.hpp" + +using namespace pimoroni; + +PicoScroll scroll; + + +extern "C" { +#include "pico_scroll.h" + +mp_obj_t picoscroll_init() { + scroll.init(); + return mp_const_none; +} + +mp_obj_t picoscroll_get_width() { + return mp_obj_new_int(PicoScroll::WIDTH); +} + +mp_obj_t picoscroll_get_height() { + return mp_obj_new_int(PicoScroll::HEIGHT); +} + +mp_obj_t picoscroll_update() { + scroll.update(); + return mp_const_none; +} + +mp_obj_t picoscroll_set_pixel(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj) { + int x = mp_obj_get_int(x_obj); + int y = mp_obj_get_int(y_obj); + int val = mp_obj_get_int(v_obj); + + if(x < 0 || x >= PicoScroll::WIDTH || y < 0 || y >= PicoScroll::HEIGHT) + mp_raise_ValueError("x or y out of range."); + else + { + if(val < 0 || val > 255) + mp_raise_ValueError("val out of range. Expected 0 to 255"); + else + scroll.set_pixel(x, y, val); + } + + return mp_const_none; +} + +mp_obj_t picoscroll_clear() { + scroll.clear(); + return mp_const_none; +} + +mp_obj_t picoscroll_is_pressed(mp_obj_t button_obj) { + int buttonID = mp_obj_get_int(button_obj); + + bool buttonPressed = false; + switch(buttonID) + { + case 0: + buttonPressed = scroll.is_pressed(PicoScroll::A); + break; + + case 1: + buttonPressed = scroll.is_pressed(PicoScroll::B); + break; + + case 2: + buttonPressed = scroll.is_pressed(PicoScroll::X); + break; + + case 3: + buttonPressed = scroll.is_pressed(PicoScroll::Y); + break; + + default: + mp_raise_ValueError("button not valid. Expected 0 to 3"); + break; + } + + return buttonPressed ? mp_const_true : mp_const_false; +} +} \ No newline at end of file diff --git a/micropython/modules/pico_scroll/pico_scroll.h b/micropython/modules/pico_scroll/pico_scroll.h new file mode 100644 index 00000000..1d95d959 --- /dev/null +++ b/micropython/modules/pico_scroll/pico_scroll.h @@ -0,0 +1,11 @@ +// Include MicroPython API. +#include "py/runtime.h" + +// Declare the functions we'll make available in Python +extern mp_obj_t picoscroll_init(); +extern mp_obj_t picoscroll_get_width(); +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_clear(); +extern mp_obj_t picoscroll_is_pressed(mp_obj_t button_obj); \ No newline at end of file