From 02d1456639a7ada05bc7a3cdd9a6636bb0c914a8 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 24 May 2023 10:30:37 +0100 Subject: [PATCH] System Speed module for #24. --- .../PIMORONI_BADGER2040/micropython.cmake | 3 + .../PIMORONI_BADGER2040W/micropython.cmake | 3 + .../modules/system_speed/micropython.cmake | 26 ++++ firmware/modules/system_speed/system_speed.c | 26 ++++ .../modules/system_speed/system_speed.cpp | 111 ++++++++++++++++++ firmware/modules/system_speed/system_speed.h | 4 + 6 files changed, 173 insertions(+) create mode 100644 firmware/modules/system_speed/micropython.cmake create mode 100644 firmware/modules/system_speed/system_speed.c create mode 100644 firmware/modules/system_speed/system_speed.cpp create mode 100644 firmware/modules/system_speed/system_speed.h diff --git a/firmware/PIMORONI_BADGER2040/micropython.cmake b/firmware/PIMORONI_BADGER2040/micropython.cmake index b1207d4..819b5ed 100644 --- a/firmware/PIMORONI_BADGER2040/micropython.cmake +++ b/firmware/PIMORONI_BADGER2040/micropython.cmake @@ -39,6 +39,9 @@ target_compile_definitions(usermod_wakeup INTERFACE -DWAKEUP_PIN_VALUE=0b10000000000000010000000000 ) +# Use our LOCAL system_speed module from firmware/modules/system_speed +include(firmware/modules/system_speed/micropython) + # Note: cppmem is *required* for C++ code to function on MicroPython # it redirects `malloc` and `free` calls to MicroPython's heap include(cppmem/micropython) diff --git a/firmware/PIMORONI_BADGER2040W/micropython.cmake b/firmware/PIMORONI_BADGER2040W/micropython.cmake index 2901f6c..5c7c908 100644 --- a/firmware/PIMORONI_BADGER2040W/micropython.cmake +++ b/firmware/PIMORONI_BADGER2040W/micropython.cmake @@ -40,6 +40,9 @@ target_compile_definitions(usermod_wakeup INTERFACE -DWAKEUP_PIN_VALUE=0b10000000000010000000000 ) +# Use our LOCAL system_speed module from firmware/modules/system_speed +include(firmware/modules/system_speed/micropython) + # Note: cppmem is *required* for C++ code to function on MicroPython # it redirects `malloc` and `free` calls to MicroPython's heap include(cppmem/micropython) diff --git a/firmware/modules/system_speed/micropython.cmake b/firmware/modules/system_speed/micropython.cmake new file mode 100644 index 0000000..09862db --- /dev/null +++ b/firmware/modules/system_speed/micropython.cmake @@ -0,0 +1,26 @@ +add_library(usermod_system_speed INTERFACE) + +target_sources(usermod_system_speed INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/system_speed.c + ${CMAKE_CURRENT_LIST_DIR}/system_speed.cpp +) + +target_include_directories(usermod_system_speed INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +target_compile_definitions(usermod_system_speed INTERFACE + -DMODULE_SYSTEM_SPEED_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_system_speed + hardware_vreg + hardware_pll + hardware_resets +) + +set_source_files_properties( + ${CMAKE_CURRENT_LIST_DIR}/system_speed.c + PROPERTIES COMPILE_FLAGS + "-Wno-discarded-qualifiers" +) diff --git a/firmware/modules/system_speed/system_speed.c b/firmware/modules/system_speed/system_speed.c new file mode 100644 index 0000000..39157c8 --- /dev/null +++ b/firmware/modules/system_speed/system_speed.c @@ -0,0 +1,26 @@ +#include "system_speed.h" + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(system_speed_set_obj, system_speed_set); + +STATIC const mp_map_elem_t system_speed_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_system_speed) }, + { MP_ROM_QSTR(MP_QSTR_set_speed), MP_ROM_PTR(&system_speed_set_obj) }, + + { 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) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_system_speed_globals, system_speed_globals_table); + +const mp_obj_module_t system_speed_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_system_speed_globals, +}; + +#if MICROPY_VERSION <= 70144 +MP_REGISTER_MODULE(MP_QSTR_system_speed, system_speed_user_cmodule, MODULE_SYSTEM_SPEED_ENABLED); +#else +MP_REGISTER_MODULE(MP_QSTR_system_speed, system_speed_user_cmodule); +#endif \ No newline at end of file diff --git a/firmware/modules/system_speed/system_speed.cpp b/firmware/modules/system_speed/system_speed.cpp new file mode 100644 index 0000000..53b19a9 --- /dev/null +++ b/firmware/modules/system_speed/system_speed.cpp @@ -0,0 +1,111 @@ +#include "hardware/gpio.h" + + +const uint VBUS_DETECT = 24; + +extern "C" { +#include "system_speed.h" +#include "hardware/vreg.h" +#include "hardware/clocks.h" +#include "hardware/pll.h" + +if CYW43_USES_VSYS_PIN +#include "pico/cyw43_arch.h" +#endif + +#if MICROPY_HW_ENABLE_UART_REPL +#include "uart.h" +#endif + +static void _set_system_speed(uint32_t selected_speed) { + uint32_t sys_freq; + + switch (selected_speed) + { + case 4: // TURBO: 250 MHZ, 1.2V + vreg_set_voltage(VREG_VOLTAGE_1_20); + set_sys_clock_khz(250000, true); + return; + case 3: // FAST: 133 MHZ + vreg_set_voltage(VREG_VOLTAGE_1_10); + set_sys_clock_khz(133000, true); + return; + + default: + case 2: // NORMAL: 48 MHZ + vreg_set_voltage(VREG_VOLTAGE_1_10); + set_sys_clock_48mhz(); + return; + + case 1: // SLOW: 12 MHZ, 1.0V + sys_freq = 12 * MHZ; + break; + + case 0: // VERY_SLOW: 4 MHZ, 1.0V + sys_freq = 4 * 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); +} + +mp_obj_t system_speed_set(mp_obj_t speed) { + uint32_t selected_speed = mp_obj_get_int(speed); + +#if defined CYW43_WL_GPIO_VBUS_PIN + bool vbus = cyw43_arch_gpio_get(CYW43_WL_GPIO_VBUS_PIN); +#else + bool vbus = gpio_get(VBUS_DETECT); +#endif + if (vbus && selected_speed < 2) { + // If on USB never go slower than normal speed. + selected_speed = 2; + } + + _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; +} + +} \ No newline at end of file diff --git a/firmware/modules/system_speed/system_speed.h b/firmware/modules/system_speed/system_speed.h new file mode 100644 index 0000000..8a8a254 --- /dev/null +++ b/firmware/modules/system_speed/system_speed.h @@ -0,0 +1,4 @@ +#include "py/runtime.h" +#include "py/objstr.h" + +extern mp_obj_t system_speed_set(mp_obj_t speed); \ No newline at end of file