From 16bfa467ce585d6a3351a119c44210a764f674ed Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Wed, 30 Mar 2022 21:07:40 +0100 Subject: [PATCH 1/3] Reinitialize hardware after system clock change --- micropython/modules/badger2040/README.md | 3 ++ micropython/modules/badger2040/badger2040.cpp | 54 +++++++++++++------ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/micropython/modules/badger2040/README.md b/micropython/modules/badger2040/README.md index c082f015..56cbd886 100644 --- a/micropython/modules/badger2040/README.md +++ b/micropython/modules/badger2040/README.md @@ -6,6 +6,7 @@ Badger 2040 is an RP2040 powered E Ink badge. - [Getting Started](#getting-started) - [Update Speed](#update-speed) - [Buttons](#buttons) + - [System Speed](#system-speed) - [Other Functions](#other-functions) - [Other Constants](#other-constants) - [Screen Size](#screen-size) @@ -79,6 +80,8 @@ The system clock speed of the RP2040 can be controlled, allowing power to be sav On USB, the system will not run slower than 48MHz, as that is the minimum clock speed required to keep the USB connection stable. +It is best to set the clock speed as the first thing in your program, and you must not change it after initializing any drivers for any I2C hardware connected to the qwiic port. To allow you to set the speed at the top of your program, this method is on the `badger2040` module, rather than the `badger` instance, although we have made sure that it is safe to call it after creating a `badger` instance. + Note that `SYSTEM_TURBO` overclocks the RP2040 to 250MHz, and applies a small over voltage to ensure this is stable. We've found that every RP2040 we've tested is happy to run at this speed without any issues. ## Other Functions diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index 1f444b6e..5d74a76a 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -11,15 +11,15 @@ extern "C" { extern uint32_t badger_buttons_on_wake; -static bool Badger2040_wake_state_any() { +static bool _Badger2040_wake_state_any() { return badger_buttons_on_wake > 0; } -static bool Badger2040_wake_state_get(uint32_t pin) { +static bool _Badger2040_wake_state_get(uint32_t pin) { return badger_buttons_on_wake & (0b1 << pin); } -static bool Badger2040_wake_state_get_once(uint32_t pin) { +static bool _Badger2040_wake_state_get_once(uint32_t pin) { uint32_t mask = 0b1 << pin; bool value = badger_buttons_on_wake & mask; badger_buttons_on_wake &= ~mask; @@ -195,7 +195,7 @@ MICROPY_EVENT_POLL_HOOK } mp_obj_t Badger2040_woken_by_button() { - return Badger2040_wake_state_any() ? mp_const_true : mp_const_false; + return _Badger2040_wake_state_any() ? mp_const_true : mp_const_false; } mp_obj_t Badger2040_halt(mp_obj_t self_in) { @@ -250,13 +250,13 @@ mp_obj_t Badger2040_thickness(mp_obj_t self_in, mp_obj_t thickness) { mp_obj_t Badger2040_pressed(mp_obj_t self_in, mp_obj_t button) { _Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t); self->badger2040->update_button_states(); - bool wake_state = Badger2040_wake_state_get_once(mp_obj_get_int(button)); + bool wake_state = _Badger2040_wake_state_get_once(mp_obj_get_int(button)); bool state = self->badger2040->pressed(mp_obj_get_int(button)); return (state || wake_state) ? mp_const_true : mp_const_false; } mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button) { - bool state = Badger2040_wake_state_get(mp_obj_get_int(button)); + bool state = _Badger2040_wake_state_get(mp_obj_get_int(button)); return state ? mp_const_true : mp_const_false; } @@ -520,32 +520,27 @@ mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_ma #include "hardware/vreg.h" #include "hardware/clocks.h" #include "hardware/pll.h" +// #include "uart.h" -mp_obj_t Badger2040_system_speed(mp_obj_t speed) { +static void _Badger2040_set_system_speed(uint32_t selected_speed) { uint32_t sys_freq; - uint32_t selected_speed = mp_obj_get_int(speed); - - if (gpio_get(pimoroni::Badger2040::VBUS_DETECT) && selected_speed < 2) { - // If on USB never go slower than normal speed. - selected_speed = 2; - } switch (selected_speed) { case 4: // TURBO: 250 MHZ, 1.2V vreg_set_voltage(VREG_VOLTAGE_1_20); set_sys_clock_khz(250000, true); - return mp_const_none; + return; case 3: // FAST: 133 MHZ vreg_set_voltage(VREG_VOLTAGE_1_10); set_sys_clock_khz(133000, true); - return mp_const_none; + return; default: case 2: // NORMAL: 48 MHZ vreg_set_voltage(VREG_VOLTAGE_1_10); set_sys_clock_48mhz(); - return mp_const_none; + return; case 1: // SLOW: 12 MHZ, 1.0V sys_freq = 12 * MHZ; @@ -556,7 +551,6 @@ mp_obj_t Badger2040_system_speed(mp_obj_t speed) { break; } - // Set the configured clock speed, by dividing the USB PLL clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, @@ -584,6 +578,32 @@ mp_obj_t Badger2040_system_speed(mp_obj_t speed) { // Drop the core voltage vreg_set_voltage(VREG_VOLTAGE_1_00); +} + +mp_obj_t Badger2040_system_speed(mp_obj_t speed) { + uint32_t selected_speed = mp_obj_get_int(speed); + + if (gpio_get(pimoroni::Badger2040::VBUS_DETECT) && selected_speed < 2) { + // If on USB never go slower than normal speed. + selected_speed = 2; + } + + _Badger2040_set_system_speed(selected_speed); + +#if MICROPY_HW_ENABLE_UART_REPL + setup_default_uart(); + mp_uart_init(); +#endif + + if (selected_speed >= 2) { + spi_set_baudrate(PIMORONI_SPI_DEFAULT_INSTANCE, 12 * MHZ); + } + else { + // Set the SPI baud rate for communicating with the display to + // go as fast as possible (which is now 6 or 2 MHz) + spi_get_hw(PIMORONI_SPI_DEFAULT_INSTANCE)->cpsr = 2; + hw_write_masked(&spi_get_hw(PIMORONI_SPI_DEFAULT_INSTANCE)->cr0, 0, SPI_SSPCR0_SCR_BITS); + } return mp_const_none; } From a4acf4b94ee30777aba47910cb5bdd8003060d75 Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Wed, 30 Mar 2022 22:23:09 +0100 Subject: [PATCH 2/3] Fix buffer overrun on out of bounds rectangle height/width --- libraries/badger2040/badger2040.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/badger2040/badger2040.cpp b/libraries/badger2040/badger2040.cpp index ba51a2d9..c3644787 100644 --- a/libraries/badger2040/badger2040.cpp +++ b/libraries/badger2040/badger2040.cpp @@ -225,6 +225,12 @@ namespace pimoroni { } w += _thickness - 1; h += _thickness - 1; + if (x + w > 296) { + w = 296 - x; + } + if (y + h > 128) { + h = 128 - y; + } if (h >= 8) { // Directly write to the frame buffer when clearing a large area From 4d67e35137ccf919d87f002f49c949647747b8b2 Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Wed, 30 Mar 2022 22:23:24 +0100 Subject: [PATCH 3/3] Badger2040: UART enabled build works --- micropython/modules/badger2040/badger2040.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index 5d74a76a..104f5dc3 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -520,7 +520,10 @@ mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_ma #include "hardware/vreg.h" #include "hardware/clocks.h" #include "hardware/pll.h" -// #include "uart.h" + +#if MICROPY_HW_ENABLE_UART_REPL +#include "uart.h" +#endif static void _Badger2040_set_system_speed(uint32_t selected_speed) { uint32_t sys_freq;