Badger2040: Refactor to fix MicroPython issues

Move busy wait logic into MicroPython bindings so that MICROPY_EVENT_POLL_HOOK can be called.
pull/252/head
Phil Howard 2022-02-21 15:19:47 +00:00
rodzic 5b084c1b9a
commit af230b5fd5
8 zmienionych plików z 237 dodań i 50 usunięć

Wyświetl plik

@ -115,6 +115,8 @@ namespace pimoroni {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
busy_wait();
}
void UC8151::fast_luts() {
@ -122,7 +124,7 @@ namespace pimoroni {
command(LUT_VCOM, {
0x00, 0x04, 0x04, 0x07, 0x00, 0x01,
0x00, 0x0c, 0x0c, 0x00, 0x00, 0x02,
0x00, 0x04, 0x04, 0x07, 0x00, 0x01,
0x00, 0x04, 0x04, 0x07, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -133,7 +135,7 @@ namespace pimoroni {
command(LUT_WW, {
0x54, 0x04, 0x04, 0x07, 0x00, 0x01,
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
0xa8, 0x04, 0x04, 0x07, 0x00, 0x01,
0xa8, 0x04, 0x04, 0x07, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -143,7 +145,7 @@ namespace pimoroni {
command(LUT_BW, {
0x54, 0x04, 0x04, 0x07, 0x00, 0x01,
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
0xa8, 0x04, 0x04, 0x07, 0x00, 0x01,
0xa8, 0x04, 0x04, 0x07, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -153,7 +155,7 @@ namespace pimoroni {
command(LUT_WB, {
0xa8, 0x04, 0x04, 0x07, 0x00, 0x01,
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
0x54, 0x04, 0x04, 0x07, 0x00, 0x01,
0x54, 0x04, 0x04, 0x07, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -163,12 +165,78 @@ namespace pimoroni {
command(LUT_BB, {
0xa8, 0x04, 0x04, 0x07, 0x00, 0x01,
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
0x54, 0x04, 0x04, 0x07, 0x00, 0x01,
0x54, 0x04, 0x04, 0x07, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
command(PLL, {
HZ_200
});
busy_wait();
}
void UC8151::faster_luts() {
// 0x3c, 0x00, 0x2b, 0x2b, 0x24, 0x1a, ????
command(LUT_VCOM, {
0x00, 0x01, 0x01, 0x02, 0x00, 0x01,
0x00, 0x02, 0x02, 0x00, 0x00, 0x02,
0x00, 0x02, 0x02, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
});
command(LUT_WW, {
0x54, 0x01, 0x01, 0x02, 0x00, 0x01,
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
0xa8, 0x02, 0x02, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
command(LUT_BW, {
0x54, 0x01, 0x01, 0x02, 0x00, 0x01,
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
0xa8, 0x02, 0x02, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
command(LUT_WB, {
0xa8, 0x01, 0x01, 0x02, 0x00, 0x01,
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
0x54, 0x02, 0x02, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
command(LUT_BB, {
0xa8, 0x01, 0x01, 0x02, 0x00, 0x01,
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
0x54, 0x02, 0x02, 0x03, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
command(PLL, {
HZ_200
});
busy_wait();
}
void UC8151::init() {
@ -193,13 +261,33 @@ namespace pimoroni {
gpio_set_function(SCK, GPIO_FUNC_SPI);
gpio_set_function(MOSI, GPIO_FUNC_SPI);
setup();
};
void UC8151::setup(uint8_t speed) {
reset();
command(PSR, {
RES_128x296 | LUT_REG | FORMAT_BW | SHIFT_RIGHT | BOOSTER_ON | RESET_NONE
});
default_luts();
if(speed == 0) {
command(PSR, {
RES_128x296 | LUT_OTP | FORMAT_BW | SHIFT_RIGHT | BOOSTER_ON | RESET_NONE
});
} else {
command(PSR, {
RES_128x296 | LUT_REG | FORMAT_BW | SHIFT_RIGHT | BOOSTER_ON | RESET_NONE
});
}
switch(speed) {
case 0:
break;
case 1:
fast_luts();
break;
case 2:
faster_luts();
break;
default:
break;
}
command(PWR, {
VDS_INTERNAL | VDG_INTERNAL,
@ -306,9 +394,16 @@ namespace pimoroni {
*p |= b; // set bit value
}
void UC8151::update_speed(uint8_t speed) {
setup(speed);
}
void UC8151::partial_update(int x, int y, int w, int h, bool blocking) {
// y is given in columns ("banks"), which are groups of 8 horiontal pixels
// x is given in pixels
if(blocking) {
busy_wait();
}
int cols = h / 8;
int y1 = y / 8;
@ -347,13 +442,17 @@ namespace pimoroni {
command(POF); // turn off
}
command(PTOU); // disable partial mode
}
void UC8151::update(bool blocking) {
if(blocking) {
busy_wait();
}
command(PON); // turn on
command(PTOU); // disable partial mode
command(DTM2, (width * height) / 8, frame_buffer); // transmit framebuffer
command(DSP); // data stop

Wyświetl plik

@ -181,15 +181,19 @@ namespace pimoroni {
void busy_wait();
bool is_busy();
void reset();
void setup(uint8_t speed=0);
void default_luts();
void fast_luts();
void faster_luts();
void read(uint8_t reg, size_t len, uint8_t *data);
void command(uint8_t reg, size_t len, const uint8_t *data);
void command(uint8_t reg, std::initializer_list<uint8_t> values);
void command(uint8_t reg) {command(reg, 0, nullptr);};
void data(size_t len, const uint8_t *data);
void update_speed(uint8_t speed);
void update(bool blocking = true);
void partial_update(int x, int y, int w, int h, bool blocking = true);
void off();

Wyświetl plik

@ -170,44 +170,20 @@ namespace pimoroni {
_button_states |= gpio_get_all() & mask;
}
void Badger2040::partial_update(int x, int y, int w, int h) {
// wait for display to not be busy
while(uc8151.is_busy()) {
tight_loop_contents();
}
uc8151.partial_update(x, y, w, h, true);
_button_states = 0;
// wait for display to not be busy but sample buttons in case they are
// pressed during this time
while(uc8151.is_busy()) {
update_button_states();
tight_loop_contents();
}
uc8151.off();
bool Badger2040::is_busy() {
return uc8151.is_busy();
}
void Badger2040::update() {
// wait for display to not be busy
while(uc8151.is_busy()) {
tight_loop_contents();
}
void Badger2040::update_speed(uint8_t speed) {
uc8151.update_speed(speed);
}
uc8151.update(false);
void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) {
uc8151.partial_update(x, y, w, h, blocking);
}
_button_states = 0;
// wait for display to not be busy but sample buttons in case they are
// pressed during this time
while(uc8151.is_busy()) {
update_button_states();
tight_loop_contents();
}
uc8151.off();
void Badger2040::update(bool blocking) {
uc8151.update(blocking);
}
const hershey_font_glyph_t* Badger2040::glyph_data(unsigned char c) {

Wyświetl plik

@ -27,10 +27,12 @@ namespace pimoroni {
: uc8151(296, 128, framebuffer, spi0, CS, DC, CLK, MOSI, BUSY, RESET) {
};
void init();
void update();
void partial_update(int x, int y, int w, int h);
void update(bool blocking=false);
void partial_update(int x, int y, int w, int h, bool blocking=false);
void update_speed(uint8_t speed);
void halt();
void sleep();
bool is_busy();
// state
void led(uint8_t brightness);

Wyświetl plik

@ -0,0 +1,60 @@
import badger2040
import machine
import time
display = badger2040.Badger2040()
display.update_speed(badger2040.UPDATE_TURBO)
display.pen(15)
display.clear()
display.update()
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
message = None
message_y = 60
def button(pin):
global message
if message is not None:
return
if pin == button_a:
message = "Button A"
return
if pin == button_b:
message = "Button B"
return
if pin == button_c:
message = "Button C"
return
if pin == button_up:
message = "Button U"
return
if pin == button_down:
message = "Button D"
return
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
while True:
if message is not None:
display.pen(15)
display.clear()
display.pen(0)
display.thickness(4)
display.text(message, 10, message_y, 2.0)
for _ in range(2):
display.update()
message = None
time.sleep(0.1)

Wyświetl plik

@ -4,6 +4,8 @@
/***** Methods *****/
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040___del___obj, Badger2040___del__);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_update_speed_obj, Badger2040_update_speed);
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_is_busy_obj, Badger2040_is_busy);
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_update_obj, Badger2040_update);
MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_partial_update_obj, 4, Badger2040_partial_update);
@ -13,7 +15,6 @@ MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pen_obj, Badger2040_pen);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_thickness_obj, Badger2040_thickness);
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pressed_obj, Badger2040_pressed);
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_clear_obj, Badger2040_clear);
MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_pixel_obj, Badger2040_pixel);
MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_line_obj, 4, Badger2040_line);
@ -27,6 +28,8 @@ MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_command_obj, Badger2040_command);
/***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Badger2040___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_is_busy), MP_ROM_PTR(&Badger2040_is_busy_obj) },
{ MP_ROM_QSTR(MP_QSTR_update_speed), MP_ROM_PTR(&Badger2040_update_speed_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&Badger2040_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_partial_update), MP_ROM_PTR(&Badger2040_partial_update_obj) },
@ -65,6 +68,10 @@ STATIC const mp_map_elem_t badger2040_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_badger2040) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Badger2040), (mp_obj_t)&Badger2040_type },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_NORMAL), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_FAST), MP_ROM_INT(1) },
{ MP_ROM_QSTR(MP_QSTR_UPDATE_TURBO), MP_ROM_INT(2) },
{ MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_INT(12) },
{ MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_INT(13) },
{ MP_ROM_QSTR(MP_QSTR_BUTTON_C), MP_ROM_INT(14) },

Wyświetl plik

@ -94,10 +94,33 @@ mp_obj_t Badger2040_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
return MP_OBJ_FROM_PTR(badger2040_obj);
}
mp_obj_t Badger2040_is_busy(mp_obj_t self_in) {
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t);
return self->badger2040->is_busy() ? mp_const_true : mp_const_false;
}
mp_obj_t Badger2040_update_speed(mp_obj_t self_in, mp_obj_t speed) {
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t);
self->badger2040->update_speed(mp_obj_get_int(speed));
return mp_const_none;
}
mp_obj_t Badger2040_update(mp_obj_t self_in) {
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t);
self->badger2040->update();
while(self->badger2040->is_busy()) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
}
self->badger2040->update(false);
while(self->badger2040->is_busy()) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
}
return mp_const_none;
}
@ -122,8 +145,22 @@ mp_obj_t Badger2040_partial_update(size_t n_args, const mp_obj_t *pos_args, mp_m
int h = args[ARG_h].u_int;
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Badger2040_obj_t);
while(self->badger2040->is_busy()) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
}
self->badger2040->partial_update(x, y, w, h);
while(self->badger2040->is_busy()) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
}
return mp_const_none;
}

Wyświetl plik

@ -10,6 +10,8 @@ extern void Badger2040_print(const mp_print_t *print, mp_obj_t self_in, mp_print
extern mp_obj_t Badger2040___del__(mp_obj_t self_in);
extern mp_obj_t Badger2040_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
extern mp_obj_t Badger2040_is_busy(mp_obj_t self_in);
extern mp_obj_t Badger2040_update_speed(mp_obj_t self_in, mp_obj_t speed);
extern mp_obj_t Badger2040_update(mp_obj_t self_in);
extern mp_obj_t Badger2040_partial_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);