Added mpy wrapper for pico_unicorn

pull/1/head
ZodiusInfuser 2021-01-19 18:46:53 +00:00
rodzic 60c69c2a1f
commit a90edb8041
6 zmienionych plików z 205 dodań i 11 usunięć

Wyświetl plik

@ -143,7 +143,7 @@ namespace pimoroni {
}
// initialise the bcd timing values and row selects in the bitstream
for(uint8_t row = 0; row < 7; row++) {
for(uint8_t row = 0; row < HEIGHT; row++) {
for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) {
// determine offset in the buffer for this row/frame
uint16_t offset = (row * ROW_BYTES * BCD_FRAMES) + (ROW_BYTES * frame);
@ -198,18 +198,18 @@ namespace pimoroni {
}
void PicoUnicorn::clear() {
for(uint8_t y = 0; y < 7; y++) {
for(uint8_t x = 0; x < 16; x++) {
for(uint8_t y = 0; y < HEIGHT; y++) {
for(uint8_t x = 0; x < WIDTH; x++) {
set_pixel(x, y, 0);
}
}
}
void PicoUnicorn::set_pixel(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b) {
if(x < 0 || x > 15 || y < 0 || y > 6) return;
if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return;
// make those coordinates sane
x = 15 - x;
x = (WIDTH - 1) - x;
// work out the byte offset of this pixel
uint8_t byte_offset = x / 2;

Wyświetl plik

@ -5,7 +5,15 @@
namespace pimoroni {
class PicoUnicorn {
uint32_t __fb[16 * 7];
public:
static const int WIDTH = 16;
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:
uint32_t __fb[WIDTH * HEIGHT];
PIO bitstream_pio = pio0;
uint bitstream_sm = 0;
@ -17,11 +25,6 @@ namespace pimoroni {
void set_pixel(uint8_t x, uint8_t y, uint8_t v);
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;
};
}

Wyświetl plik

@ -0,0 +1,12 @@
PICOUNICORN_MOD_DIR := $(USERMOD_DIR)
# Add our source files to the respective variables.
SRC_USERMOD += $(PICOUNICORN_MOD_DIR)/pico_unicorn.c
SRC_USERMOD_CXX += $(PICOUNICORN_MOD_DIR)/pico_unicorn.cpp
# Add our module directory to the include path.
CFLAGS_USERMOD += -I$(PICOUNICORN_MOD_DIR)
CXXFLAGS_USERMOD += -I$(PICOUNICORN_MOD_DIR)
# We use C++ features so have to link against the standard library.
LDFLAGS_USERMOD += -lstdc++

Wyświetl plik

@ -0,0 +1,55 @@
#include "pico_unicorn.h"
/***** Constants *****/
enum buttons
{
BUTTON_A = 0,
BUTTON_B,
BUTTON_X,
BUTTON_Y,
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// picounicorn Module
////////////////////////////////////////////////////////////////////////////////////////////////////
/***** Module Functions *****/
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_init_obj, picounicorn_init);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_get_width_obj, picounicorn_get_width);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_get_height_obj, picounicorn_get_height);
//STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_update_obj, picounicorn_update);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picounicorn_set_pixel_obj, 5, 5, picounicorn_set_pixel);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(picounicorn_set_pixel_value_obj, picounicorn_set_pixel_value);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_clear_obj, picounicorn_init);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_is_pressed_obj, picounicorn_is_pressed);
/***** Globals Table *****/
STATIC const mp_rom_map_elem_t picounicorn_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picounicorn) },
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picounicorn_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picounicorn_get_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picounicorn_get_height_obj) },
//{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picounicorn_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&picounicorn_set_pixel_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_pixel_value), MP_ROM_PTR(&picounicorn_set_pixel_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picounicorn_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picounicorn_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_picounicorn_globals, picounicorn_globals_table);
/***** Module Definition *****/
const mp_obj_module_t picounicorn_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_picounicorn_globals,
};
////////////////////////////////////////////////////////////////////////////////////////////////////
MP_REGISTER_MODULE(MP_QSTR_picounicorn, picounicorn_user_cmodule, MODULE_PICOUNICORN_ENABLED);
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

Wyświetl plik

@ -0,0 +1,111 @@
#include "hardware/spi.h"
#include "hardware/sync.h"
#include "pico/binary_info.h"
#include "../../../pimoroni-pico/libraries/pico_unicorn/pico_unicorn.hpp"
using namespace pimoroni;
PicoUnicorn unicorn;
extern "C" {
#include "pico_unicorn.h"
mp_obj_t picounicorn_init() {
unicorn.init();
return mp_const_none;
}
mp_obj_t picounicorn_get_width() {
return mp_obj_new_int(PicoUnicorn::WIDTH);
}
mp_obj_t picounicorn_get_height() {
return mp_obj_new_int(PicoUnicorn::HEIGHT);
}
// mp_obj_t picounicorn_update() {
// unicorn.update();
// return mp_const_none;
// }
mp_obj_t picounicorn_set_pixel(mp_uint_t n_args, const mp_obj_t *args) {
(void)n_args; //Unused input parameter, we know it's 5
int x = mp_obj_get_int(args[0]);
int y = mp_obj_get_int(args[1]);
int r = mp_obj_get_int(args[2]);
int g = mp_obj_get_int(args[3]);
int b = mp_obj_get_int(args[4]);
if(x < 0 || x >= PicoUnicorn::WIDTH || y < 0 || y >= PicoUnicorn::HEIGHT)
mp_raise_ValueError("x or y out of range.");
else
{
if(r < 0 || r > 255)
mp_raise_ValueError("r out of range. Expected 0 to 255");
else if(g < 0 || g > 255)
mp_raise_ValueError("g out of range. Expected 0 to 255");
else if(b < 0 || b > 255)
mp_raise_ValueError("b out of range. Expected 0 to 255");
else
unicorn.set_pixel(x, y, r, g, b);
}
return mp_const_none;
}
mp_obj_t picounicorn_set_pixel_value(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 >= PicoUnicorn::WIDTH || y < 0 || y >= PicoUnicorn::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
unicorn.set_pixel(x, y, val);
}
return mp_const_none;
}
mp_obj_t picounicorn_clear() {
unicorn.clear();
return mp_const_none;
}
mp_obj_t picounicorn_is_pressed(mp_obj_t button_obj) {
int buttonID = mp_obj_get_int(button_obj);
bool buttonPressed = false;
switch(buttonID)
{
case 0:
buttonPressed = unicorn.is_pressed(PicoUnicorn::A);
break;
case 1:
buttonPressed = unicorn.is_pressed(PicoUnicorn::B);
break;
case 2:
buttonPressed = unicorn.is_pressed(PicoUnicorn::X);
break;
case 3:
buttonPressed = unicorn.is_pressed(PicoUnicorn::Y);
break;
default:
mp_raise_ValueError("button not valid. Expected 0 to 3");
break;
}
return buttonPressed ? mp_const_true : mp_const_false;
}
}

Wyświetl plik

@ -0,0 +1,13 @@
// Include MicroPython API.
//#include "py/obj.h"
#include "py/runtime.h"
// Declare the functions we'll make available in Python
extern mp_obj_t picounicorn_init();
extern mp_obj_t picounicorn_get_width();
extern mp_obj_t picounicorn_get_height();
//extern mp_obj_t picounicorn_update();
extern mp_obj_t picounicorn_set_pixel(mp_uint_t n_args, const mp_obj_t *args);
extern mp_obj_t picounicorn_set_pixel_value(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj);
extern mp_obj_t picounicorn_clear();
extern mp_obj_t picounicorn_is_pressed(mp_obj_t button_obj);