diff --git a/micropython/modules/badger2040/badger2040.c b/micropython/modules/badger2040/badger2040.c index aa81c828..9c1df9e4 100644 --- a/micropython/modules/badger2040/badger2040.c +++ b/micropython/modules/badger2040/badger2040.c @@ -35,6 +35,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_command_obj, Badger2040_command); MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_pressed_to_wake_obj, Badger2040_pressed_to_wake); MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_halt_obj, Badger2040_halt); MP_DEFINE_CONST_FUN_OBJ_0(Badger2040_woken_by_button_obj, Badger2040_woken_by_button); +MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_system_speed_obj, Badger2040_system_speed); /***** Binding of Methods *****/ STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = { @@ -90,6 +91,7 @@ STATIC const mp_rom_map_elem_t badger2040_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_pressed_to_wake), MP_ROM_PTR(&Badger2040_pressed_to_wake_obj) }, { MP_ROM_QSTR(MP_QSTR_woken_by_button), MP_ROM_PTR(&Badger2040_woken_by_button_obj) }, + { MP_ROM_QSTR(MP_QSTR_system_speed), MP_ROM_PTR(&Badger2040_system_speed_obj) }, { MP_ROM_QSTR(MP_QSTR_UPDATE_NORMAL), MP_ROM_INT(0) }, { MP_ROM_QSTR(MP_QSTR_UPDATE_MEDIUM), MP_ROM_INT(1) }, @@ -97,6 +99,12 @@ STATIC const mp_rom_map_elem_t badger2040_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_UPDATE_TURBO), MP_ROM_INT(3) }, { MP_ROM_QSTR(MP_QSTR_UPDATE_SUPER_EXTRA_TURBO), MP_ROM_INT(3) }, // ho ho placebo! + { MP_ROM_QSTR(MP_QSTR_SYSTEM_VERY_SLOW), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_SYSTEM_SLOW), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_SYSTEM_NORMAL), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_SYSTEM_FAST), MP_ROM_INT(3) }, + { MP_ROM_QSTR(MP_QSTR_SYSTEM_TURBO), MP_ROM_INT(4) }, + { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(296) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(128) }, diff --git a/micropython/modules/badger2040/badger2040.cpp b/micropython/modules/badger2040/badger2040.cpp index d928b193..9616545f 100644 --- a/micropython/modules/badger2040/badger2040.cpp +++ b/micropython/modules/badger2040/badger2040.cpp @@ -139,7 +139,7 @@ MICROPY_EVENT_POLL_HOOK // Ensure blocking for the minimum amount of time // in cases where "is_busy" is unreliable. - while(self->badger2040->is_busy() || absolute_time_diff_us(t_end, get_absolute_time()) > 0) { + while(self->badger2040->is_busy() || absolute_time_diff_us(get_absolute_time(), t_end) > 0) { #ifdef MICROPY_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK #endif @@ -517,4 +517,75 @@ mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_ma return mp_obj_new_int(self->badger2040->measure_glyph(c, scale)); } +#include "hardware/vreg.h" +#include "hardware/clocks.h" +#include "hardware/pll.h" + +mp_obj_t Badger2040_system_speed(mp_obj_t 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; + case 3: // FAST: 133 MHZ + vreg_set_voltage(VREG_VOLTAGE_1_10); + set_sys_clock_khz(133000, true); + return mp_const_none; + + default: + case 2: // NORMAL: 48 MHZ + vreg_set_voltage(VREG_VOLTAGE_1_10); + set_sys_clock_48mhz(); + return mp_const_none; + + case 1: // SLOW: 12 MHZ, 1.0V + sys_freq = 12 * MHZ; + break; + + case 0: // VERY_SLOW: 3 MHZ, 1.0V + sys_freq = 3 * MHZ; + 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, + CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, + 48 * MHZ, + sys_freq); + + clock_configure(clk_peri, + 0, + CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, + sys_freq, + sys_freq); + + clock_configure(clk_adc, + 0, + CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, + 48 * MHZ, + sys_freq); + + // No longer using the SYS PLL so disable it + pll_deinit(pll_sys); + + // Not using USB so stop the clock + clock_stop(clk_usb); + + // Drop the core voltage + vreg_set_voltage(VREG_VOLTAGE_1_00); + + return mp_const_none; +} + } diff --git a/micropython/modules/badger2040/badger2040.h b/micropython/modules/badger2040/badger2040.h index 0b6fac44..58ebc851 100644 --- a/micropython/modules/badger2040/badger2040.h +++ b/micropython/modules/badger2040/badger2040.h @@ -43,3 +43,5 @@ extern mp_obj_t Badger2040_command(mp_obj_t self_in, mp_obj_t reg, mp_obj_t data extern mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button); extern mp_obj_t Badger2040_woken_by_button(); + +extern mp_obj_t Badger2040_system_speed(mp_obj_t speed); diff --git a/micropython/modules/badger2040/micropython.cmake b/micropython/modules/badger2040/micropython.cmake index 4ae063de..770e4660 100644 --- a/micropython/modules/badger2040/micropython.cmake +++ b/micropython/modules/badger2040/micropython.cmake @@ -20,4 +20,7 @@ target_compile_definitions(usermod_${MOD_NAME} INTERFACE MODULE_BADGER2040_ENABLED=1 ) -target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME} + hardware_vreg + hardware_pll + hardware_resets)