diff --git a/radio/src/audio.h b/radio/src/audio.h index 3dbfc5911..ac356863a 100644 --- a/radio/src/audio.h +++ b/radio/src/audio.h @@ -588,8 +588,6 @@ void audioTimerCountdown(uint8_t timer, int value); #define AUDIO_TRAINER_LOST() audioEvent(AU_TRAINER_LOST) #define AUDIO_TRAINER_BACK() audioEvent(AU_TRAINER_BACK) -#define AUDIO_HEARTBEAT() - enum AutomaticPromptsCategories { SYSTEM_AUDIO_CATEGORY, MODEL_AUDIO_CATEGORY, diff --git a/radio/src/debounce.h b/radio/src/debounce.h new file mode 100644 index 000000000..f7b1559bc --- /dev/null +++ b/radio/src/debounce.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DEBOUNCE_H_ +#define _DEBOUNCE_H_ + +#include "board.h" + +template +class Debounce +{ + public: + T debounce(T state) + { + if (state == lastState) + debouncedState = state; + else + lastState = state; + return debouncedState; + } + + private: + T lastState; + T debouncedState; +}; + +#if defined(STM32) +class PinDebounce: public Debounce +{ + public: + uint8_t debounce(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) + { + return Debounce::debounce(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin)); + } +}; +#endif + +#endif // _DEBOUNCE_H_ diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 6ca4173cc..918cb6822 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -28,6 +28,7 @@ #include #include "definitions.h" #include "opentx_types.h" +#include "debounce.h" #if defined(STM32) #include "usbd_conf.h" @@ -542,8 +543,6 @@ bool setTrimValue(uint8_t phase, uint8_t idx, int trim); #if defined(PCBSKY9X) #define ROTARY_ENCODER_GRANULARITY (2 << g_eeGeneral.rotarySteps) -#elif defined(PCBHORUS) - #define ROTARY_ENCODER_GRANULARITY (1) #else #define ROTARY_ENCODER_GRANULARITY (2) #endif diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index 0663ef223..f1421abef 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -201,7 +201,7 @@ int main() AUX_SERIAL_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | + RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph | LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_xMS_RCC_APB1Periph | I2C_RCC_APB1Periph | AUX_SERIAL_RCC_APB1Periph | SD_RCC_APB1Periph, ENABLE); diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp index ea94cdaaf..b8d06a03a 100644 --- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp +++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp @@ -20,7 +20,7 @@ #include "opentx.h" -uint32_t rotencPosition; +uint8_t rotencPosition; void rotaryEncoderInit() { @@ -56,19 +56,29 @@ void rotaryEncoderInit() #endif rotencPosition = ROTARY_ENCODER_POSITION(); + + ROTARY_ENCODER_TIMER->ARR = 99; // 100uS + ROTARY_ENCODER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS + ROTARY_ENCODER_TIMER->CCER = 0; + ROTARY_ENCODER_TIMER->CCMR1 = 0; + ROTARY_ENCODER_TIMER->EGR = 0; + ROTARY_ENCODER_TIMER->CR1 = 0; + ROTARY_ENCODER_TIMER->DIER |= TIM_DIER_UIE; + NVIC_EnableIRQ(ROTARY_ENCODER_TIMER_IRQn); + NVIC_SetPriority(ROTARY_ENCODER_TIMER_IRQn, 7); } void rotaryEncoderCheck() { - uint32_t newpos = ROTARY_ENCODER_POSITION(); - if (newpos != rotencPosition && !keyState(KEY_ENTER)) { - if ((rotencPosition & 0x01) ^ ((newpos & 0x02) >> 1)) { + uint8_t newPosition = ROTARY_ENCODER_POSITION(); + if (newPosition != rotencPosition && !keyState(KEY_ENTER)) { + if ((rotencPosition & 0x01) ^ ((newPosition & 0x02) >> 1)) { --rotencValue; } else { ++rotencValue; } - rotencPosition = newpos; + rotencPosition = newPosition; #if !defined(BOOT) if (g_eeGeneral.backlightMode & e_backlight_mode_keys) { backlightOn(); @@ -77,16 +87,21 @@ void rotaryEncoderCheck() } } +void rotaryEncoderStartDelay() +{ + ROTARY_ENCODER_TIMER->CR1 = TIM_CR1_CEN | TIM_CR1_URS; +} + extern "C" void ROTARY_ENCODER_EXTI_IRQHandler1(void) { if (EXTI_GetITStatus(ROTARY_ENCODER_EXTI_LINE1) != RESET) { - rotaryEncoderCheck(); + rotaryEncoderStartDelay(); EXTI_ClearITPendingBit(ROTARY_ENCODER_EXTI_LINE1); } #if !defined(ROTARY_ENCODER_EXTI_IRQn2) if (EXTI_GetITStatus(ROTARY_ENCODER_EXTI_LINE2) != RESET) { - rotaryEncoderCheck(); + rotaryEncoderStartDelay(); EXTI_ClearITPendingBit(ROTARY_ENCODER_EXTI_LINE2); } #endif @@ -100,8 +115,15 @@ extern "C" void ROTARY_ENCODER_EXTI_IRQHandler1(void) extern "C" void ROTARY_ENCODER_EXTI_IRQHandler2(void) { if (EXTI_GetITStatus(ROTARY_ENCODER_EXTI_LINE2) != RESET) { - rotaryEncoderCheck(); + rotaryEncoderStartDelay(); EXTI_ClearITPendingBit(ROTARY_ENCODER_EXTI_LINE2); } } #endif + +extern "C" void ROTARY_ENCODER_TIMER_IRQHandler(void) +{ + ROTARY_ENCODER_TIMER->SR &= ~TIM_SR_UIF; + ROTARY_ENCODER_TIMER->CR1 = 0; + rotaryEncoderCheck(); +} \ No newline at end of file diff --git a/radio/src/targets/common/arm/stm32/timers_driver.cpp b/radio/src/targets/common/arm/stm32/timers_driver.cpp new file mode 100644 index 000000000..f25cf483b --- /dev/null +++ b/radio/src/targets/common/arm/stm32/timers_driver.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" + +// Start TIMER at 2000000Hz +void init2MhzTimer() +{ + TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5 uS, 2 MHz + TIMER_2MHz_TIMER->ARR = 65535; + TIMER_2MHz_TIMER->CR2 = 0; + TIMER_2MHz_TIMER->CR1 = TIM_CR1_CEN; +} + +// Start TIMER at 200Hz +void init5msTimer() +{ + INTERRUPT_xMS_TIMER->ARR = 4999; // 5mS in uS + INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS + INTERRUPT_xMS_TIMER->CCER = 0; + INTERRUPT_xMS_TIMER->CCMR1 = 0; + INTERRUPT_xMS_TIMER->EGR = 0; + INTERRUPT_xMS_TIMER->CR1 = TIM_CR1_CEN | TIM_CR1_URS; + INTERRUPT_xMS_TIMER->DIER |= TIM_DIER_UIE; + NVIC_EnableIRQ(INTERRUPT_xMS_IRQn); + NVIC_SetPriority(INTERRUPT_xMS_IRQn, 7); +} + +void stop5msTimer() +{ + INTERRUPT_xMS_TIMER->CR1 = 0 ; // stop timer + NVIC_DisableIRQ(INTERRUPT_xMS_IRQn) ; +} + +// TODO use the same than board_sky9x.cpp +void interrupt5ms() +{ + static uint8_t pre_scale; // Used to get 10 Hz counter + + ++pre_scale; + +#if defined(HAPTIC) + DEBUG_TIMER_START(debugTimerHaptic); + HAPTIC_HEARTBEAT(); + DEBUG_TIMER_STOP(debugTimerHaptic); +#endif + + if (pre_scale == 2) { + pre_scale = 0; + DEBUG_TIMER_START(debugTimerPer10ms); + DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod); + per10ms(); + DEBUG_TIMER_STOP(debugTimerPer10ms); + } +} + +extern "C" void INTERRUPT_xMS_IRQHandler() +{ + INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF; + interrupt5ms(); + DEBUG_INTERRUPT(INT_1MS); +} diff --git a/radio/src/targets/common/arm/stm32/usb_driver.cpp b/radio/src/targets/common/arm/stm32/usb_driver.cpp index e47774623..7e2c5abf1 100644 --- a/radio/src/targets/common/arm/stm32/usb_driver.cpp +++ b/radio/src/targets/common/arm/stm32/usb_driver.cpp @@ -49,23 +49,8 @@ void setSelectedUsbMode(int mode) int usbPlugged() { - // debounce - static uint8_t debounced_state = 0; - static uint8_t last_state = 0; - - if (GPIO_ReadInputDataBit(USB_GPIO, USB_GPIO_PIN_VBUS)) { - if (last_state) { - debounced_state = 1; - } - last_state = 1; - } - else { - if (!last_state) { - debounced_state = 0; - } - last_state = 0; - } - return debounced_state; + static PinDebounce debounce; + return debounce.debounce(USB_GPIO, USB_GPIO_PIN_VBUS); } USB_OTG_CORE_HANDLE USB_OTG_dev; diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 14fd9c4e9..e94df176b 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -128,6 +128,7 @@ set(TARGET_SRC led_driver.cpp extmodule_driver.cpp trainer_driver.cpp + ../common/arm/stm32/timers_driver.cpp ../common/arm/stm32/intmodule_serial_driver.cpp ../common/arm/stm32/bluetooth_driver.cpp ../common/arm/stm32/rotary_encoder_driver.cpp diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index c30c9b8ff..51b22889a 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -41,60 +41,6 @@ void watchdogInit(unsigned int duration) IWDG->KR = 0xCCCC; // start } -// Start TIMER7 at 2000000Hz -void init2MhzTimer() -{ - TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5 uS, 2 MHz - TIMER_2MHz_TIMER->ARR = 65535; - TIMER_2MHz_TIMER->CR2 = 0; - TIMER_2MHz_TIMER->CR1 = TIM_CR1_CEN; -} - -// Starts TIMER at 1000Hz -void init1msTimer() -{ - INTERRUPT_xMS_TIMER->ARR = 999; // 1mS in uS - INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS - INTERRUPT_xMS_TIMER->CCER = 0; - INTERRUPT_xMS_TIMER->CCMR1 = 0; - INTERRUPT_xMS_TIMER->EGR = 0; - INTERRUPT_xMS_TIMER->CR1 = 5; - INTERRUPT_xMS_TIMER->DIER |= 1; - NVIC_EnableIRQ(INTERRUPT_xMS_IRQn); - NVIC_SetPriority(INTERRUPT_xMS_IRQn, 7); -} - -// TODO use the same than board_sky9x.cpp -void interrupt1ms() -{ - static uint8_t pre_scale; // Used to get 10 Hz counter - - ++pre_scale; - -#if defined(HAPTIC) - if (pre_scale == 5 || pre_scale == 10) { - DEBUG_TIMER_START(debugTimerHaptic); - HAPTIC_HEARTBEAT(); - DEBUG_TIMER_STOP(debugTimerHaptic); - } -#endif - - if (pre_scale == 10) { - pre_scale = 0; - DEBUG_TIMER_START(debugTimerPer10ms); - DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod); - per10ms(); - DEBUG_TIMER_STOP(debugTimerPer10ms); - } -} - -extern "C" void INTERRUPT_xMS_IRQHandler() -{ - INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF; - interrupt1ms(); - DEBUG_INTERRUPT(INT_1MS); -} - #if defined(SEMIHOSTING) extern "C" void initialise_monitor_handles(); #endif @@ -150,7 +96,8 @@ void boardInit() SPORT_UPDATE_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(INTERRUPT_xMS_RCC_APB1Periph | + RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph | + INTERRUPT_xMS_RCC_APB1Periph | ADC_RCC_APB1Periph | TIMER_2MHz_RCC_APB1Periph | AUDIO_RCC_APB1Periph | @@ -208,7 +155,7 @@ void boardInit() backlightInit(); init2MhzTimer(); - init1msTimer(); + init5msTimer(); usbInit(); hapticInit(); diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index ea4d2604e..8eceb5587 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -112,6 +112,10 @@ void boardPreInit(void); void boardInit(void); void boardOff(void); +// Timers driver +void init2MhzTimer(); +void init5msTimer(); + // Delays driver #ifdef __cplusplus extern "C" { diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index b94470799..007fefec7 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -54,6 +54,7 @@ #endif // Rotary Encoder +#define ROTARY_ENCODER_RCC_APB1Periph RCC_APB1Periph_TIM4 #define ROTARY_ENCODER_GPIO GPIOH #define ROTARY_ENCODER_GPIO_PIN_A GPIO_Pin_11 // PH.11 #define ROTARY_ENCODER_GPIO_PIN_B GPIO_Pin_10 // PH.10 @@ -65,6 +66,9 @@ #define ROTARY_ENCODER_EXTI_PortSource EXTI_PortSourceGPIOH #define ROTARY_ENCODER_EXTI_PinSource1 EXTI_PinSource11 #define ROTARY_ENCODER_EXTI_PinSource2 EXTI_PinSource10 +#define ROTARY_ENCODER_TIMER TIM4 +#define ROTARY_ENCODER_TIMER_IRQn TIM4_IRQn +#define ROTARY_ENCODER_TIMER_IRQHandler TIM4_IRQHandler // Switches #define STORAGE_SWITCH_A diff --git a/radio/src/targets/sky9x/board.cpp b/radio/src/targets/sky9x/board.cpp index 515dc7708..93f96e491 100644 --- a/radio/src/targets/sky9x/board.cpp +++ b/radio/src/targets/sky9x/board.cpp @@ -148,7 +148,6 @@ void interrupt5ms() static uint32_t pre_scale ; // Used to get 10 Hz counter HAPTIC_HEARTBEAT(); - AUDIO_HEARTBEAT(); if ( ++pre_scale >= 2 ) { BUZZER_HEARTBEAT(); diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index aca21c142..1d2ccc7c5 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -253,6 +253,7 @@ set(TARGET_SRC backlight_driver.cpp extmodule_driver.cpp trainer_driver.cpp + ../common/arm/stm32/timers_driver.cpp ../common/arm/stm32/audio_dac_driver.cpp ../common/arm/stm32/adc_driver.cpp ../common/arm/stm32/heartbeat_driver.cpp diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index f5704f08b..5bc5def1d 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -41,64 +41,6 @@ void watchdogInit(unsigned int duration) IWDG->KR = 0xCCCC; // start } -// Starts TIMER at 2MHz -void init2MhzTimer() -{ - TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1 ; // 0.5 uS, 2 MHz - TIMER_2MHz_TIMER->ARR = 65535; - TIMER_2MHz_TIMER->CR2 = 0; - TIMER_2MHz_TIMER->CR1 = TIM_CR1_CEN; -} - -// Starts TIMER at 200Hz (5ms) -void init5msTimer() -{ - INTERRUPT_xMS_TIMER->ARR = 4999 ; // 5mS in uS - INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1 ; // 1uS - INTERRUPT_xMS_TIMER->CCER = 0 ; - INTERRUPT_xMS_TIMER->CCMR1 = 0 ; - INTERRUPT_xMS_TIMER->EGR = 0 ; - INTERRUPT_xMS_TIMER->CR1 = 5 ; - INTERRUPT_xMS_TIMER->DIER |= 1 ; - NVIC_EnableIRQ(INTERRUPT_xMS_IRQn) ; - NVIC_SetPriority(INTERRUPT_xMS_IRQn, 7); -} - -void stop5msTimer( void ) -{ - INTERRUPT_xMS_TIMER->CR1 = 0 ; // stop timer - NVIC_DisableIRQ(INTERRUPT_xMS_IRQn) ; -} - -// TODO use the same than board_sky9x.cpp -void interrupt5ms() -{ - static uint32_t pre_scale ; // Used to get 10 Hz counter - - AUDIO_HEARTBEAT(); - -#if defined(HAPTIC) - HAPTIC_HEARTBEAT(); -#endif - - if (++pre_scale >= 2) { - pre_scale = 0 ; - DEBUG_TIMER_START(debugTimerPer10ms); - DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod); - per10ms(); - DEBUG_TIMER_STOP(debugTimerPer10ms); - } -} - -#if !defined(SIMU) -extern "C" void INTERRUPT_xMS_IRQHandler() -{ - INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF ; - interrupt5ms() ; - DEBUG_INTERRUPT(INT_5MS); -} -#endif - #if defined(PWR_BUTTON_PRESS) #define PWR_PRESS_DURATION_MIN 100 // 1s #define PWR_PRESS_DURATION_MAX 500 // 5s @@ -160,7 +102,8 @@ void boardInit() GYRO_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | + RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph | + LCD_RCC_APB1Periph | AUDIO_RCC_APB1Periph | ADC_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index aca1b8f67..f1a152e2b 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -124,6 +124,10 @@ void boardPreInit(void); void boardInit(void); void boardOff(void); +// Timers driver +void init2MhzTimer(); +void init5msTimer(); + // Delays driver #ifdef __cplusplus extern "C" { diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 8c0175408..c9d8c15ef 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -135,6 +135,14 @@ #define ROTARY_ENCODER_EXTI_PinSource1 EXTI_PinSource10 #define ROTARY_ENCODER_EXTI_PinSource2 EXTI_PinSource12 #endif +#if defined(ROTARY_ENCODER_NAVIGATION) + #define ROTARY_ENCODER_RCC_APB1Periph RCC_APB1Periph_TIM5 + #define ROTARY_ENCODER_TIMER TIM5 + #define ROTARY_ENCODER_TIMER_IRQn TIM5_IRQn + #define ROTARY_ENCODER_TIMER_IRQHandler TIM5_IRQHandler +#else + #define ROTARY_ENCODER_RCC_APB1Periph 0 +#endif // Trims #if defined(PCBX9E)