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_BADGER2040/mpconfigboard.h b/firmware/PIMORONI_BADGER2040/mpconfigboard.h index 8eacab1..89555eb 100644 --- a/firmware/PIMORONI_BADGER2040/mpconfigboard.h +++ b/firmware/PIMORONI_BADGER2040/mpconfigboard.h @@ -1,3 +1,4 @@ // This is a hack! Need to replace with upstream board definition. #define MICROPY_HW_BOARD_NAME "Pimoroni Badger2040 2MB" #define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024) +#define PICO_VBUS_PIN 24 \ No newline at end of file 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/PIMORONI_BADGER2040W/mpconfigboard.h b/firmware/PIMORONI_BADGER2040W/mpconfigboard.h index 1c39710..889f7cd 100644 --- a/firmware/PIMORONI_BADGER2040W/mpconfigboard.h +++ b/firmware/PIMORONI_BADGER2040W/mpconfigboard.h @@ -11,6 +11,7 @@ #define CYW43_LWIP (1) #define CYW43_GPIO (1) #define CYW43_SPI_PIO (1) +#define CYW43_WL_GPIO_VBUS_PIN (2) // For debugging mbedtls - also set // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose 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..9226eeb --- /dev/null +++ b/firmware/modules/system_speed/system_speed.cpp @@ -0,0 +1,111 @@ +#include "hardware/gpio.h" + +extern "C" { +#include "system_speed.h" +#include "pico/stdlib.h" +#include "hardware/vreg.h" +#include "hardware/clocks.h" +#include "hardware/pll.h" + +#if defined CYW43_WL_GPIO_VBUS_PIN +#include "lib/cyw43-driver/src/cyw43.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); + bool vbus = false; +#if defined CYW43_WL_GPIO_VBUS_PIN + cyw43_gpio_get(&cyw43_state, CYW43_WL_GPIO_VBUS_PIN, &vbus); +#else + gpio_set_function(PICO_VBUS_PIN, GPIO_FUNC_SIO); + vbus = gpio_get(PICO_VBUS_PIN); +#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 + + // TODO Make this work... + /*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