From 4b30a6673572de17733201e9bc966a59ae8552b3 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Sun, 11 Apr 2021 12:38:20 +0200 Subject: [PATCH] Added 'platform_pwrButtonStatus' API function, which returns the current status of the power button/knob. Implemented power on/off mechanism on MD-9600 --- openrtx/include/interfaces/platform.h | 7 +++ openrtx/src/main.c | 13 +++++ openrtx/src/ui/ui.c | 7 ++- platform/targets/DM-1801/platform.c | 8 +++ platform/targets/GD-77/platform.c | 8 +++ platform/targets/MD-3x0/platform.c | 8 +++ platform/targets/MD-9600/platform.c | 71 +++++++++++++++++++++++++-- platform/targets/MD-UV3x0/platform.c | 8 +++ 8 files changed, 121 insertions(+), 9 deletions(-) diff --git a/openrtx/include/interfaces/platform.h b/openrtx/include/interfaces/platform.h index 7df55a4f..863c451d 100644 --- a/openrtx/include/interfaces/platform.h +++ b/openrtx/include/interfaces/platform.h @@ -108,6 +108,13 @@ int8_t platform_getChSelector(); */ bool platform_getPttStatus(); +/** + * This function reads and returns the current status of the power on/power off + * button or switch. + * @return true if power is enabled, false otherwise. + */ +bool platform_pwrButtonStatus(); + /** * This function turns on the selected led. * @param led: which led to control diff --git a/openrtx/src/main.c b/openrtx/src/main.c index a3fc785f..0a9a3838 100644 --- a/openrtx/src/main.c +++ b/openrtx/src/main.c @@ -32,6 +32,19 @@ extern void *ui_task(void *arg); int main(void) { + // MD-9600 does not have a proper power on/off mechanism and the MCU is + // always powered on. We thus need to place a busy wait on the power on + // button to manage the on/off mechanism. + // A do-while block is used to avoid re-powering on after a power off due to + // MCU rebooting before user stops pressing the power button. + #ifdef PLATFORM_MD9600 + do + { + sleepFor(1, 0); + } + while(!platform_pwrButtonStatus()); + #endif + // Initialize platform drivers platform_init(); diff --git a/openrtx/src/ui/ui.c b/openrtx/src/ui/ui.c index 11d070af..0f3695f0 100644 --- a/openrtx/src/ui/ui.c +++ b/openrtx/src/ui/ui.c @@ -695,15 +695,14 @@ void ui_saveState() void ui_updateFSM(event_t event, bool *sync_rtx) { -#ifndef BAT_NONE - // The volume knob has been set to OFF, shutdown the radio - if(state.v_bat <= 0) + // User wants to power off the radio, so shutdown. + if(!platform_pwrButtonStatus()) { state_terminate(); platform_terminate(); return; } -#endif + // Check if battery has enough charge to operate. // Check is skipped if there is an ongoing transmission, since the voltage // drop caused by the RF PA power absorption causes spurious triggers of diff --git a/platform/targets/DM-1801/platform.c b/platform/targets/DM-1801/platform.c index 5c6ac2ae..cd39b258 100644 --- a/platform/targets/DM-1801/platform.c +++ b/platform/targets/DM-1801/platform.c @@ -140,6 +140,14 @@ bool platform_getPttStatus() return (gpio_readPin(PTT_SW) == 0) ? true : false; } +bool platform_pwrButtonStatus() +{ + /* + * When power knob is set to off, battery voltage measurement returns 0V. + */ + return (platform_getVbat() > 0.0f) ? true : false: +} + void platform_ledOn(led_t led) { switch(led) diff --git a/platform/targets/GD-77/platform.c b/platform/targets/GD-77/platform.c index f0d6ae67..56cc2cd9 100644 --- a/platform/targets/GD-77/platform.c +++ b/platform/targets/GD-77/platform.c @@ -139,6 +139,14 @@ bool platform_getPttStatus() return (gpio_readPin(PTT_SW) == 0) ? true : false; } +bool platform_pwrButtonStatus() +{ + /* + * When power knob is set to off, battery voltage measurement returns 0V. + */ + return (platform_getVbat() > 0.0f) ? true : false: +} + void platform_ledOn(led_t led) { switch(led) diff --git a/platform/targets/MD-3x0/platform.c b/platform/targets/MD-3x0/platform.c index cb952bf1..4c4739a4 100644 --- a/platform/targets/MD-3x0/platform.c +++ b/platform/targets/MD-3x0/platform.c @@ -122,6 +122,14 @@ bool platform_getPttStatus() return (gpio_readPin(PTT_SW) == 0) ? true : false; } +bool platform_pwrButtonStatus() +{ + /* + * When power knob is set to off, battery voltage measurement returns 0V. + */ + return (adc1_getMeasurement(ADC_VBAT_CH) > 0.0f) ? true : false; +} + void platform_ledOn(led_t led) { switch(led) diff --git a/platform/targets/MD-9600/platform.c b/platform/targets/MD-9600/platform.c index 0ac0fdf7..2a9624ec 100644 --- a/platform/targets/MD-9600/platform.c +++ b/platform/targets/MD-9600/platform.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -34,14 +35,12 @@ hwInfo_t hwInfo; void platform_init() { - gpio_setMode(CH_SELECTOR_0, INPUT_PULL_UP); - gpio_setMode(CH_SELECTOR_1, INPUT_PULL_UP); - - gpio_setMode(PTT_SW, INPUT); - + /* Enable 8V power supply rail */ gpio_setMode(PWR_SW, OUTPUT); gpio_setPin(PWR_SW); + gpio_setMode(PTT_SW, INPUT); + /* * Initialise ADC1, for vbat, RSSI, ... * Configuration of corresponding GPIOs in analog input mode is done inside @@ -93,6 +92,13 @@ void platform_terminate() /* Finally, remove power supply */ gpio_clearPin(PWR_SW); + + /* + * MD-9600 does not have a proper power on/off mechanism and the MCU is + * always powered. Thus, for turn off, perform a system reset. + */ + NVIC_SystemReset(); + while(1) ; } float platform_getVbat() @@ -121,6 +127,61 @@ bool platform_getPttStatus() return (gpio_readPin(PTT_SW) == 0) ? true : false; } +bool platform_pwrButtonStatus() +{ + /* + * The power on/off button, when pressed, connects keyboard coloumn 3 to + * row 3. Here we set coloumn to input with pull up mode and row to output + * mode, consistently with keyboard driver. + */ + + gpio_setMode(KB_COL3, INPUT_PULL_UP); + gpio_setMode(KB_ROW3, OUTPUT); + + /* + * Critical section to avoid stomping the keyboard driver. + * Also, working at register level to keep it as short as possible + */ + __disable_irq(); + uint32_t prevRowState = GPIOD->ODR & (1 << 4); /* Row 3 is PD4 */ + GPIOD->BSRRH = 1 << 4; /* PD4 low */ + delayUs(10); + uint32_t btnStatus = GPIOE->IDR & 0x01; /* Col 3 is PE0 */ + GPIOD->ODR |= prevRowState; /* Restore PD4 */ + __enable_irq(); + + /* + * Power button API requires this function to return true if power is + * enabled. To comply to the requirement this function behaves in this way: + * - if button is not pressed, return current status of PWR_SW. + * - if button is pressed and PWR_SW is low, return true as user wants to + * turn the radio on. + * - if button is pressed and PWR_SW is high, return false as user wants to + * turn the radio off. + */ + + /* + * Power button follows an active-low logic: btnStatus is low when button + * is pressed + */ + if(btnStatus == 0) + { + if(gpio_readPin(PWR_SW)) + { + /* Power switch high and button pressed: request to turn off */ + return false; + } + else + { + /* Power switch low and button pressed: request to turn on */ + return true; + } + } + + /* We get here if power button is not pressed, just return PWR_SW status */ + return gpio_readPin(PWR_SW) ? true : false; +} + void platform_ledOn(led_t led) { /* No LEDs on this platform */ diff --git a/platform/targets/MD-UV3x0/platform.c b/platform/targets/MD-UV3x0/platform.c index 216a4dd7..836d6fbb 100644 --- a/platform/targets/MD-UV3x0/platform.c +++ b/platform/targets/MD-UV3x0/platform.c @@ -116,6 +116,14 @@ bool platform_getPttStatus() return (gpio_readPin(PTT_SW) == 0) ? true : false; } +bool platform_pwrButtonStatus() +{ + /* + * When power knob is set to off, battery voltage measurement returns 0V. + */ + return (adc1_getMeasurement(ADC_VBAT_CH) > 0.0f) ? true : false; +} + void platform_ledOn(led_t led) { switch(led)