From b0fda0a459e26d133044ed02e8d7e0a32a15d77d Mon Sep 17 00:00:00 2001 From: enriquezgarc Date: Mon, 21 Oct 2024 12:09:48 +0200 Subject: [PATCH] ports/psoc6: WIP reproduce MTB example within MPY environment. Signed-off-by: enriquezgarc --- ports/psoc6/main.c | 589 ++++++++++++++++++++++++++++++++++++++- ports/psoc6/modmachine.c | 282 ++++++++++++++++++- 2 files changed, 861 insertions(+), 10 deletions(-) diff --git a/ports/psoc6/main.c b/ports/psoc6/main.c index 8c9d3c8c16c67..9b8811597ec59 100644 --- a/ports/psoc6/main.c +++ b/ports/psoc6/main.c @@ -67,8 +67,431 @@ // port-specific includes #include "mplogger.h" -#define MPY_TASK_STACK_SIZE (4096u) -#define MPY_TASK_PRIORITY (3u) +/////////////////////////////////////////////////////////////// +///// Inserting code used by switching power modes //////////// + +/* Constants to define LONG and SHORT presses on User Button (x10 = ms) */ +#define QUICK_PRESS_COUNT 2u /* 20 ms < press < 200 ms */ +#define SHORT_PRESS_COUNT 20u /* 200 ms < press < 2 sec */ +#define LONG_PRESS_COUNT 200u /* press > 2 sec */ + +/* PWM LED frequency constants (in Hz) */ +#define PWM_FAST_FREQ_HZ 10 +#define PWM_SLOW_FREQ_HZ 3 +#define PWM_DIM_FREQ_HZ 100 + +/* PWM Duty cycles (Active Low, in %) */ +#define PWM_50P_DUTY_CYCLE 50.0f +#define PWM_10P_DUTY_CYCLE 90.0f +#define PWM_100P_DUTY_CYCLE 0.0f + +/* Clock frequency constants (in Hz) */ +#define CLOCK_50_MHZ 50000000u +#define CLOCK_100_MHZ 100000000u + +/* Glitch delays */ +#define SHORT_GLITCH_DELAY_MS 10u /* in ms */ +#define LONG_GLITCH_DELAY_MS 100u /* in ms */ + +/* User button press delay*/ +#define USER_BTN_PRESS_DELAY 10u /* in ms */ + +#define led_conf_on_bright() cyhal_pwm_set_duty_cycle(&pwm, PWM_100P_DUTY_CYCLE, PWM_DIM_FREQ_HZ) +#define led_conf_on_dimmed() cyhal_pwm_set_duty_cycle(&pwm, PWM_10P_DUTY_CYCLE, PWM_DIM_FREQ_HZ) +#define led_conf_off() +#define led_conf_blink_fast() cyhal_pwm_set_duty_cycle(&pwm, PWM_50P_DUTY_CYCLE, PWM_FAST_FREQ_HZ) +#define led_conf_blink_slow() cyhal_pwm_set_duty_cycle(&pwm, PWM_50P_DUTY_CYCLE, PWM_SLOW_FREQ_HZ) + +typedef enum +{ + SWITCH_NO_EVENT = 0u, + SWITCH_QUICK_PRESS = 1u, + SWITCH_SHORT_PRESS = 2u, + SWITCH_LONG_PRESS = 3u, +} en_switch_event_t; + +extern uint8_t selected_event; + +/***************************************************************************** +* Function Prototypes +********************************************************************************/ +en_switch_event_t get_switch_event(void); + +/* Power callbacks */ +bool pwm_power_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *arg); +bool clk_power_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *arg); + + +/******************************************************************************* +* Global Variables +********************************************************************************/ +/* HAL Objects */ +// cyhal_pwm_t pwm; +// cyhal_clock_t system_clock; + +// #define BUTLEDPWMODE_TASK_STACK_SIZE_BYTES (4096) +// #define BUTLEDPWMODE_TASK_PRIORITY (3U) + +// TaskHandle_t button_led_pwm_mode_task_handle; + +// void button_led_pwm_mode_task() +// { +// cy_rslt_t result; + +// /* Initialize the User Button */ +// cyhal_gpio_init(CYBSP_USER_BTN, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF); +// /* Enable the GPIO interrupt to wake-up the device */ +// cyhal_gpio_enable_event(CYBSP_USER_BTN, CYHAL_GPIO_IRQ_FALL, CYHAL_ISR_PRIORITY_DEFAULT, true); + +// /* Initialize the PWM to control LED brightness */ +// cyhal_pwm_init(&pwm, CYBSP_USER_LED, NULL); +// cyhal_pwm_set_duty_cycle(&pwm, PWM_50P_DUTY_CYCLE, PWM_FAST_FREQ_HZ); +// cyhal_pwm_start(&pwm); + +// /* Reserve, take ownership of, the specified clock instance*/ +// result = cyhal_clock_reserve(&system_clock, &CYHAL_CLOCK_FLL); + +// // If the clock is not already enabled, enable it +// if (!cyhal_clock_is_enabled(&system_clock)) +// { +// result = cyhal_clock_set_enabled(&system_clock, true, true); +// } + +// (void)result; + +// /* Callback declaration for Power Modes */ +// cyhal_syspm_callback_data_t pwm_callback = {pwm_power_callback, /* Callback function */ +// (cyhal_syspm_callback_state_t) +// (CYHAL_SYSPM_CB_CPU_SLEEP | +// CYHAL_SYSPM_CB_CPU_DEEPSLEEP | +// CYHAL_SYSPM_CB_SYSTEM_NORMAL | +// CYHAL_SYSPM_CB_SYSTEM_LOW), /* Power States supported */ +// (cyhal_syspm_callback_mode_t) +// (CYHAL_SYSPM_CHECK_FAIL), /* Modes to ignore */ +// NULL, /* Callback Argument */ +// NULL}; /* For internal use */ + +// cyhal_syspm_callback_data_t clk_callback = {clk_power_callback, /* Callback function */ +// (cyhal_syspm_callback_state_t) +// (CYHAL_SYSPM_CB_CPU_SLEEP | +// CYHAL_SYSPM_CB_CPU_DEEPSLEEP | +// CYHAL_SYSPM_CB_SYSTEM_NORMAL | +// CYHAL_SYSPM_CB_SYSTEM_LOW), /* Power States supported */ +// (cyhal_syspm_callback_mode_t) +// (CYHAL_SYSPM_CHECK_READY | +// CYHAL_SYSPM_CHECK_FAIL), /* Modes to ignore */ +// NULL, /* Callback Argument */ +// NULL}; /* For internal use */ + +// /* Initialize the System Power Management */ +// cyhal_syspm_init(); + +// /* Power Management Callback registration */ +// cyhal_syspm_register_callback(&pwm_callback); +// cyhal_syspm_register_callback(&clk_callback); + + +// // button_led_pwm_task_init(); +// // const TickType_t xDelay = 100 / portTICK_PERIOD_MS; + +// for(;;) +// { +// switch (get_switch_event()) +// { +// case SWITCH_QUICK_PRESS: +// /* Check if the device is in System Low Power state */ +// if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) +// { +// /* Switch to System Normal Power state */ +// cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_NORMAL); +// } +// else +// { +// /* Switch to System Low Power state */ +// cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW); +// } +// break; + +// case SWITCH_SHORT_PRESS: +// /* Go to sleep */ +// cyhal_syspm_sleep(); + +// /* Wait a bit to avoid glitches from the button press */ +// cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); +// vTaskSuspend(NULL); +// break; + +// case SWITCH_LONG_PRESS: +// /* Go to deep sleep */ +// cyhal_syspm_deepsleep(); + +// /* Wait a bit to avoid glitches from the button press */ +// cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); +// break; + +// default: +// break; +// } +// // taskYIELD(); +// // vTaskSuspend(NULL); +// // vTaskDelay(xDelay); +// } + +// } + +extern en_switch_event_t get_switch_event(void); +// en_switch_event_t get_switch_event(void) +// { +// en_switch_event_t event = SWITCH_NO_EVENT; +// uint32_t pressCount = 0; + +// /* Check if User button is pressed */ +// while (cyhal_gpio_read(CYBSP_USER_BTN) == CYBSP_BTN_PRESSED) +// { +// /* Wait for 10 ms */ +// cyhal_system_delay_ms(USER_BTN_PRESS_DELAY); + +// /* Increment counter. Each count represents 10 ms */ +// pressCount++; +// } + +// /* Check for how long the button was pressed */ +// if (pressCount > LONG_PRESS_COUNT) +// { +// event = SWITCH_LONG_PRESS; +// } +// else if (pressCount > SHORT_PRESS_COUNT) +// { +// event = SWITCH_SHORT_PRESS; +// } +// else if (pressCount > QUICK_PRESS_COUNT) +// { +// event = SWITCH_QUICK_PRESS; +// } + +// /* Add a delay to avoid glitches */ +// cyhal_system_delay_ms(SHORT_GLITCH_DELAY_MS); + +// return event; +// } + +TaskHandle_t mpy_task_handle; + +// bool pwm_power_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *arg) +// { +// (void) arg; + +// /* Stop the PWM before applying any changes */ +// cyhal_pwm_stop(&pwm); + +// if (mode == CYHAL_SYSPM_BEFORE_TRANSITION) +// { +// if (state == CYHAL_SYSPM_CB_CPU_SLEEP) +// { +// /* Check if the device is in Low Power Mode */ +// if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) +// { +// /* Before going to Low Power Sleep Mode, set LED brightness to 10% */ +// led_conf_on_dimmed(); +// } +// else +// { +// /* Before going to Normal Power Sleep Mode, set LED brightness to 100% */ +// led_conf_on_bright(); +// } + +// /* Restart the PWM */ +// cyhal_pwm_start(&pwm); + +// } +// } +// else if (mode == CYHAL_SYSPM_AFTER_TRANSITION) +// { +// switch (state) +// { +// // case CYHAL_SYSPM_CB_CPU_SLEEP: +// // /* Check if the device is in Low Power Mode */ +// // if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) +// // { +// // /* Before going to Low Power Sleep Mode, set LED brightness to 10% */ +// //// cyhal_pwm_set_duty_cycle(&pwm, PWM_100P_DUTY_CYCLE, PWM_DIM_FREQ_HZ); +// // led_conf_on_dimmed(); +// // } +// // else +// // { +// // /* Before going to Normal Power Sleep Mode, set LED brightness to 100% */ +// //// cyhal_pwm_set_duty_cycle(&pwm, PWM_10P_DUTY_CYCLE, PWM_DIM_FREQ_HZ); +// // led_conf_on_bright(); +// // } +// // break; + +// case CYHAL_SYSPM_CB_CPU_SLEEP: +// // { +// // BaseType_t xYieldRequired = pdFALSE; +// // xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); +// // portYIELD_FROM_ISR( xYieldRequired ); +// // } +// case CYHAL_SYSPM_CB_CPU_DEEPSLEEP: +// /* Check if the device is in Low Power Mode */ +// if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) +// { +// /* After waking up, set the slow blink pattern */ +// led_conf_blink_slow(); +// } +// else +// { +// /* After waking up, set the fast blink pattern */ +// led_conf_blink_fast(); +// } +// break; + +// case CYHAL_SYSPM_CB_SYSTEM_NORMAL: +// /* Set fast blinking rate when in Normal Power state*/ +// led_conf_blink_fast(); +// break; + +// case CYHAL_SYSPM_CB_SYSTEM_LOW: +// /* Set slow blinking rate when in Low Power state */ +// led_conf_blink_slow(); +// break; + +// default: +// break; +// } + +// /* Restart the PWM */ +// cyhal_pwm_start(&pwm); +// } + +// return true; +// } + + +// void switch_power_modes_loop() { +// switch (get_switch_event()) +// { +// case SWITCH_QUICK_PRESS: +// /* Check if the device is in System Low Power state */ +// if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) +// { +// /* Switch to System Normal Power state */ +// cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_NORMAL); +// } +// else +// { +// /* Switch to System Low Power state */ +// cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW); +// } +// break; + +// case SWITCH_SHORT_PRESS: +// /* Go to sleep */ +// cyhal_syspm_sleep(); + +// /* Wait a bit to avoid glitches from the button press */ +// cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); +// vTaskSuspend(NULL); +// break; + +// case SWITCH_LONG_PRESS: +// /* Go to deep sleep */ +// cyhal_syspm_deepsleep(); + +// /* Wait a bit to avoid glitches from the button press */ +// cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); +// break; + +// default: +// break; +// } +// } + +// bool clk_power_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *arg) +// { +// (void) arg; + +// if (mode == CYHAL_SYSPM_AFTER_TRANSITION) +// { +// switch (state) +// { +// case CYHAL_SYSPM_CB_SYSTEM_NORMAL: +// /* Set the system clock to 100 MHz */ +// // cyhal_clock_set_frequency(&system_clock, CLOCK_100_MHZ, NULL); +// break; + +// case CYHAL_SYSPM_CB_CPU_SLEEP: +// { +// BaseType_t xYieldRequired = pdFALSE; +// xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); +// portYIELD_FROM_ISR( xYieldRequired ); +// } +// break; + +// case CYHAL_SYSPM_CB_CPU_DEEPSLEEP: +// { +// BaseType_t xYieldRequired = pdFALSE; +// xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); +// portYIELD_FROM_ISR( xYieldRequired ); +// } +// break; + +// case CYHAL_SYSPM_CB_SYSTEM_LOW: +// // /* Set the System Clock to 50 MHz */ +// // cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); +// break; + +// default: +// break; +// } +// // if (state == CYHAL_SYSPM_CB_SYSTEM_NORMAL) +// // { +// // /* Set the system clock to 100 MHz */ +// // cyhal_clock_set_frequency(&system_clock, CLOCK_100_MHZ, NULL); +// // } +// // else if (state == CYHAL_SYSPM_CB_CPU_SLEEP) +// // { +// // BaseType_t xYieldRequired = pdFALSE; +// // xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); +// // portYIELD_FROM_ISR( xYieldRequired ); +// // } else if (state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP) { +// // BaseType_t xYieldRequired = pdFALSE; +// // xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); +// // portYIELD_FROM_ISR( xYieldRequired ); +// // } +// } +// else if (mode == CYHAL_SYSPM_BEFORE_TRANSITION) +// { +// switch (state) +// { +// case CYHAL_SYSPM_CB_SYSTEM_LOW: +// /* Set the System Clock to 50 MHz */ +// // mp_printf(&mp_plat_print, "bef low\n"); +// // cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); +// break; + +// case CYHAL_SYSPM_CB_CPU_DEEPSLEEP: +// vTaskSuspend(mpy_task_handle); +// default: +// break; +// } +// if (state == CYHAL_SYSPM_CB_SYSTEM_LOW) +// { +// /* Set the System Clock to 50 MHz */ +// // cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); +// } +// } + +// return true; +// } + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// + +#define MPY_TASK_STACK_SIZE (4096) +#define MPY_TASK_PRIORITY (3U) + +void mpy_task(); typedef enum { BOOT_MODE_NORMAL, @@ -86,10 +509,6 @@ extern void os_init(void); extern void network_init(void); extern void network_deinit(void); -void mpy_task(void *arg); - -TaskHandle_t mpy_task_handle; - boot_mode_t check_boot_mode(void) { boot_mode_t boot_mode; @@ -126,6 +545,7 @@ boot_mode_t check_boot_mode(void) { int main(int argc, char **argv) { // Initialize the device and board peripherals cy_rslt_t result = cybsp_init(); + // TODO: the printing is not ready yet. if (result != CY_RSLT_SUCCESS) { mp_raise_ValueError(MP_ERROR_TEXT("cybsp_init failed !\n")); } @@ -133,10 +553,18 @@ int main(int argc, char **argv) { // Initialize retarget-io to use the debug UART port result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE); if (result != CY_RSLT_SUCCESS) { + // TODO: the printing is not guaranteed to be ready yet.`?? mp_raise_ValueError(MP_ERROR_TEXT("cy_retarget_io_init failed !\n")); } + ///////// + // __enable_irq(); + //////// + xTaskCreate(mpy_task, "MicroPython task", MPY_TASK_STACK_SIZE, NULL, MPY_TASK_PRIORITY, &mpy_task_handle); + // xTaskCreate(button_led_pwm_mode_task, "Butt LED PWM Task", BUTLEDPWMODE_TASK_STACK_SIZE_BYTES, + // NULL, BUTLEDPWMODE_TASK_PRIORITY, &button_led_pwm_mode_task_handle); + vTaskStartScheduler(); // Should never get here @@ -144,7 +572,7 @@ int main(int argc, char **argv) { return 0; } -void mpy_task(void *arg) { +void mpy_task() { #if MICROPY_ENABLE_GC mp_stack_set_top(&__StackTop); // mp_stack_set_limit((mp_uint_t)&__StackTop - (mp_uint_t)&__StackLimit); @@ -154,7 +582,7 @@ void mpy_task(void *arg) { // Initialize modules. Or to be redone after a reset and therefore to be placed next to machine_init below ? os_init(); - time_init(); + // time_init(); // TODO: This does not allow to enter deep sleep mode soft_reset: mod_rtc_init(); @@ -204,6 +632,109 @@ void mpy_task(void *arg) { __enable_irq(); +// cy_rslt_t result; + + /* Initialize the User Button */ + cyhal_gpio_init(CYBSP_USER_BTN, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF); + /* Enable the GPIO interrupt to wake-up the device */ + cyhal_gpio_enable_event(CYBSP_USER_BTN, CYHAL_GPIO_IRQ_FALL, CYHAL_ISR_PRIORITY_DEFAULT, true); + + /* Initialize the PWM to control LED brightness */ + // cyhal_pwm_init(&pwm, CYBSP_USER_LED, NULL); + // cyhal_pwm_set_duty_cycle(&pwm, PWM_50P_DUTY_CYCLE, PWM_FAST_FREQ_HZ); + // cyhal_pwm_start(&pwm); + + /* Reserve, take ownership of, the specified clock instance*/ + // result = +// cyhal_clock_reserve(&system_clock, &CYHAL_CLOCK_FLL); + +// // If the clock is not already enabled, enable it +// if (!cyhal_clock_is_enabled(&system_clock)) +// { +// // result = +// cyhal_clock_set_enabled(&system_clock, true, true); +// } + + // (void)result; + + // /* Callback declaration for Power Modes */ + // cyhal_syspm_callback_data_t pwm_callback = {pwm_power_callback, /* Callback function */ + // (cyhal_syspm_callback_state_t) + // (CYHAL_SYSPM_CB_CPU_SLEEP | + // CYHAL_SYSPM_CB_CPU_DEEPSLEEP | + // CYHAL_SYSPM_CB_SYSTEM_NORMAL | + // CYHAL_SYSPM_CB_SYSTEM_LOW), /* Power States supported */ + // (cyhal_syspm_callback_mode_t) + // (CYHAL_SYSPM_CHECK_FAIL), /* Modes to ignore */ + // NULL, /* Callback Argument */ + // NULL}; /* For internal use */ + + // cyhal_syspm_callback_data_t clk_callback = {clk_power_callback, /* Callback function */ + // (cyhal_syspm_callback_state_t) + // (CYHAL_SYSPM_CB_CPU_SLEEP | + // CYHAL_SYSPM_CB_CPU_DEEPSLEEP | + // CYHAL_SYSPM_CB_SYSTEM_NORMAL | + // CYHAL_SYSPM_CB_SYSTEM_LOW), /* Power States supported */ + // (cyhal_syspm_callback_mode_t) + // (CYHAL_SYSPM_CHECK_READY | + // CYHAL_SYSPM_CHECK_FAIL), /* Modes to ignore */ + // NULL, /* Callback Argument */ + // NULL}; /* For internal use */ + + /* Initialize the System Power Management */ + // cyhal_syspm_init(); + + /* Power Management Callback registration */ + // cyhal_syspm_register_callback(&pwm_callback); + // cyhal_syspm_register_callback(&clk_callback); + + +// button_led_pwm_task_init(); + // const TickType_t xDelay = 100 / portTICK_PERIOD_MS; + +// for(;;) +// { +// switch (get_switch_event()) +// { +// case SWITCH_QUICK_PRESS: +// /* Check if the device is in System Low Power state */ +// if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) +// { +// /* Switch to System Normal Power state */ +// cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_NORMAL); +// } +// else +// { +// /* Switch to System Low Power state */ +// cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW); +// } +// break; + +// case SWITCH_SHORT_PRESS: +// /* Go to sleep */ +// cyhal_syspm_sleep(); + +// /* Wait a bit to avoid glitches from the button press */ +// cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); +// vTaskSuspend(NULL); +// break; + +// case SWITCH_LONG_PRESS: +// /* Go to deep sleep */ +// cyhal_syspm_deepsleep(); + +// /* Wait a bit to avoid glitches from the button press */ +// cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); +// break; + +// default: +// break; +// } +// // taskYIELD(); +// // vTaskSuspend(NULL); +// // vTaskDelay(xDelay); + // } + for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { @@ -214,6 +745,48 @@ void mpy_task(void *arg) { break; } } + + //////// + + // switch_power_modes_loop(); + + // switch (get_switch_event()) + // { + // case SWITCH_QUICK_PRESS: + // /* Check if the device is in System Low Power state */ + // if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) + // { + // /* Switch to System Normal Power state */ + // cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_NORMAL); + // } + // else + // { + // /* Switch to System Low Power state */ + // cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW); + // } + // break; + + // case SWITCH_SHORT_PRESS: + // /* Go to sleep */ + // cyhal_syspm_sleep(); + + // /* Wait a bit to avoid glitches from the button press */ + // cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); + // vTaskSuspend(NULL); + // break; + + // case SWITCH_LONG_PRESS: + // /* Go to deep sleep */ + // cyhal_syspm_deepsleep(); + + // /* Wait a bit to avoid glitches from the button press */ + // cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); + // break; + + // default: + // break; + // } + //////// } mp_printf(&mp_plat_print, "MPY: soft reboot\n"); diff --git a/ports/psoc6/modmachine.c b/ports/psoc6/modmachine.c index a5d7f33bacbf0..6ca10f5840f9f 100644 --- a/ports/psoc6/modmachine.c +++ b/ports/psoc6/modmachine.c @@ -39,12 +39,19 @@ // MTB includes #include "cybsp.h" #include "cyhal.h" +#include "cy_retarget_io.h" #include "cy_pdl.h" // port-specific includes #include "modmachine.h" #include "mplogger.h" #include "modpsoc6.h" + +// FreeRTOS header file +#include +#include +#include + #if MICROPY_PY_MACHINE // enums to hold the MPY constants as given in guidelines @@ -217,8 +224,279 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) { mp_raise_NotImplementedError(MP_ERROR_TEXT("Not implemented!!!\n")); } + + +///////////////////////////////// + + +/* Constants to define LONG and SHORT presses on User Button (x10 = ms) */ +#define QUICK_PRESS_COUNT 2u /* 20 ms < press < 200 ms */ +#define SHORT_PRESS_COUNT 20u /* 200 ms < press < 2 sec */ +#define LONG_PRESS_COUNT 200u /* press > 2 sec */ + +#define CLOCK_50_MHZ 50000000u +#define CLOCK_100_MHZ 100000000u + +/* Glitch delays */ +#define SHORT_GLITCH_DELAY_MS 10u /* in ms */ +#define LONG_GLITCH_DELAY_MS 100u /* in ms */ + +/* User button press delay*/ +#define USER_BTN_PRESS_DELAY 10u /* in ms */ + +uint8_t selected_event; + +typedef enum +{ + SWITCH_NO_EVENT = 0u, + SWITCH_QUICK_PRESS = 1u, + SWITCH_SHORT_PRESS = 2u, + SWITCH_LONG_PRESS = 3u, +} en_switch_event_t; + +en_switch_event_t get_switch_event(void) { + en_switch_event_t event = SWITCH_NO_EVENT; + uint32_t pressCount = 0; + + /* Check if User button is pressed */ + while (cyhal_gpio_read(CYBSP_USER_BTN) == CYBSP_BTN_PRESSED) { + /* Wait for 10 ms */ + cyhal_system_delay_ms(USER_BTN_PRESS_DELAY); + + /* Increment counter. Each count represents 10 ms */ + pressCount++; + } + + /* Check for how long the button was pressed */ + if (pressCount > LONG_PRESS_COUNT) { + event = SWITCH_LONG_PRESS; + } else if (pressCount > SHORT_PRESS_COUNT) { + event = SWITCH_SHORT_PRESS; + } else if (pressCount > QUICK_PRESS_COUNT) { + event = SWITCH_QUICK_PRESS; + } + + /* Add a delay to avoid glitches */ + cyhal_system_delay_ms(SHORT_GLITCH_DELAY_MS); + + return event; +} + +extern TaskHandle_t mpy_task_handle; +cyhal_clock_t system_clock; + + +bool clk_power_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *arg) { + (void)arg; + + if (mode == CYHAL_SYSPM_AFTER_TRANSITION) { + switch (state) + { + case CYHAL_SYSPM_CB_SYSTEM_NORMAL: + /* Set the system clock to 100 MHz */ + // cyhal_clock_set_frequency(&system_clock, CLOCK_100_MHZ, NULL); + break; + + case CYHAL_SYSPM_CB_CPU_SLEEP: { + BaseType_t xYieldRequired = pdFALSE; + + cyhal_syspm_unlock_deepsleep(); + + xYieldRequired = xTaskResumeFromISR(mpy_task_handle); + + portYIELD_FROM_ISR(xYieldRequired); + } + break; + + case CYHAL_SYSPM_CB_CPU_DEEPSLEEP: { + BaseType_t xYieldRequired = pdFALSE; + xYieldRequired = xTaskResumeFromISR(mpy_task_handle); + portYIELD_FROM_ISR(xYieldRequired); + } + break; + + case CYHAL_SYSPM_CB_SYSTEM_LOW: + // /* Set the System Clock to 50 MHz */ + // cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); + break; + + default: + break; + } + // if (state == CYHAL_SYSPM_CB_SYSTEM_NORMAL) + // { + // /* Set the system clock to 100 MHz */ + // cyhal_clock_set_frequency(&system_clock, CLOCK_100_MHZ, NULL); + // } + // else if (state == CYHAL_SYSPM_CB_CPU_SLEEP) + // { + // BaseType_t xYieldRequired = pdFALSE; + // xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); + // portYIELD_FROM_ISR( xYieldRequired ); + // } else if (state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP) { + // BaseType_t xYieldRequired = pdFALSE; + // xYieldRequired = xTaskResumeFromISR( mpy_task_handle ); + // portYIELD_FROM_ISR( xYieldRequired ); + // } + } else if (mode == CYHAL_SYSPM_BEFORE_TRANSITION) { + switch (state) + { + case CYHAL_SYSPM_CB_SYSTEM_LOW: + /* Set the System Clock to 50 MHz */ + // mp_printf(&mp_plat_print, "bef low\n"); + // cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); + break; + + + case CYHAL_SYSPM_CB_CPU_SLEEP: + cyhal_syspm_lock_deepsleep(); + break; + + case CYHAL_SYSPM_CB_CPU_DEEPSLEEP: + // cyhal_syspm_unlock_deepsleep(); + // vTaskSuspend(mpy_task_handle); + default: + break; + } + // if (state == CYHAL_SYSPM_CB_SYSTEM_LOW) + // { + // /* Set the System Clock to 50 MHz */ + // cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); + // } + } + + return true; +} +// CYHAL_SYSPM_CB_SYSTEM_NORMAL | +// CYHAL_SYSPM_CB_SYSTEM_LOW), /* Power States supported */ + +cyhal_syspm_callback_data_t clk_callback = {clk_power_callback, /* Callback function */ + (cyhal_syspm_callback_state_t) + (CYHAL_SYSPM_CB_CPU_SLEEP | + CYHAL_SYSPM_CB_CPU_DEEPSLEEP), + (cyhal_syspm_callback_mode_t) + (CYHAL_SYSPM_CHECK_READY | + CYHAL_SYSPM_CHECK_FAIL), /* Modes to ignore */ + NULL, /* Callback Argument */ + NULL}; + +////////////////////////////////// // Sleep Modes Not working. Might be because of the REPL always running in background. Need to evaluate static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) { + // cyhal_clock_t system_clock; + + cyhal_clock_reserve(&system_clock, &CYHAL_CLOCK_FLL); + +// If the clock is not already enabled, enable it + if (!cyhal_clock_is_enabled(&system_clock)) { + // result = + cyhal_clock_set_enabled(&system_clock, true, true); + } + + cyhal_syspm_register_callback(&clk_callback); + + if (n_args != 0) { + selected_event = mp_obj_get_int(args[0]); + mp_printf(&mp_plat_print, "Selected event %lx !\n", selected_event); + + __disable_irq(); + // switch (get_switch_event()) + switch (selected_event) + { + // NORMAL POWER MODE + case 1: + /* Switch to System Normal Power state */ + mp_printf(&mp_plat_print, "n\n"); + cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_NORMAL); + cyhal_system_delay_ms(200); + cyhal_clock_set_frequency(&system_clock, CLOCK_100_MHZ, NULL); + break; + + // LOW POWER MODE + case 2: + + // cy_retarget_io_deinit(); + // cyhal_system_delay_ms(200); + /* Switch to System Low Power state */ + cyhal_clock_set_frequency(&system_clock, CLOCK_50_MHZ, NULL); + + cyhal_system_delay_ms(300); + // mp_printf(&mp_plat_print, "l\n"); + // uint32_t freq = cyhal_clock_get_frequency(&system_clock); + // mp_printf(&mp_plat_print, "Freq: %lx\n", freq); + // cyhal_system_delay_ms(1000); + // cyhal_syspm_lock_deepsleep(); + cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW); + // cyhal_syspm_deepsleep(); + // vTaskSuspend(NULL); + break; + + // SLEEP MODE + case 3: + // mp_printf(&mp_plat_print, "b\n"); + /* Go to sleep */ + cyhal_syspm_lock_deepsleep(); + // cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW); + cyhal_syspm_sleep(); + + /* Wait a bit to avoid glitches from the button press */ + // cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); + vTaskSuspend(mpy_task_handle); + + break; + + // DEEPSLEEP MODE + case 4: + // mp_printf(&mp_plat_print, "c\n"); + /* Go to deep sleep */ + // cyhal_syspm_unlock_deepsleep(); + cyhal_syspm_deepsleep(); + + /* Wait a bit to avoid glitches from the button press */ + // cyhal_system_delay_ms(LONG_GLITCH_DELAY_MS); + vTaskSuspend(mpy_task_handle); + + break; + + default: { + cyhal_lptimer_t obj; + uint32_t actual_ms; + cyhal_syspm_tickless_sleep(&obj, selected_event, &actual_ms); + } + break; + + // case SWITCH_QUICK_PRESS: + + // /* Check if the device is in System Low Power state */ + // if (cyhal_syspm_get_system_state() == CYHAL_SYSPM_SYSTEM_LOW) + // { + + // } + // else + // { + + // } + // break; + + // case SWITCH_SHORT_PRESS: + + // break; + + // case SWITCH_LONG_PRESS: + + // break; + + // default: + // break; + } + __enable_irq(); + + cyhal_clock_free(&system_clock); + } + + + + // cy_rslt_t result; // if (n_args != 0) { // uint32_t expiry = mp_obj_get_int(args[0]); @@ -234,7 +512,7 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) { // mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Light sleeep failed %lx !"), result); // } // } - mp_raise_NotImplementedError(MP_ERROR_TEXT("Not implemented!!!\n")); + // mp_raise_NotImplementedError(MP_ERROR_TEXT("Not implemented!!!\n")); } NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args) { @@ -343,7 +621,7 @@ static mp_obj_t machine_rng(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_rng_obj, machine_rng); -#ifdef MICROPY_PY_SD_CARD +#if MICROPY_PY_SD_CARD #define MICROPY_PY_MACHINE_SD_CARD_ENTRY { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&machine_sdcard_type) }, #else #define MICROPY_PY_MACHINE_SD_CARD_ENTRY