diff --git a/radio/src/gui/menu_general.cpp b/radio/src/gui/menu_general.cpp index 91865a966..ba0b94f12 100644 --- a/radio/src/gui/menu_general.cpp +++ b/radio/src/gui/menu_general.cpp @@ -1403,7 +1403,7 @@ void menuGeneralHardware(uint8_t event) } case ITEM_SETUP_HW_UART3_MODE: g_eeGeneral.uart3Mode = selectMenuItem(HW_SETTINGS_COLUMN, y, STR_UART3MODE, STR_UART3MODES, g_eeGeneral.uart3Mode, 0, UART_MODE_MAX, attr, event); - if (checkIncDec_Ret) { + if (attr && checkIncDec_Ret) { uart3Init(g_eeGeneral.uart3Mode, MODEL_TELEMETRY_PROTOCOL()); } break; diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index bc598a5b3..c659700e2 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -994,7 +994,7 @@ void menuModelSetup(uint8_t event) #if defined(PCBTARANIS) #define IF_INTERNAL_MODULE_ON(x) (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF ? HIDDEN_ROW : (uint8_t)(x)) #define IF_EXTERNAL_MODULE_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x)) - #define IF_TRAINER_ON(x) (g_model.trainerMode ? (uint8_t)(x) : HIDDEN_ROW) + #define IF_TRAINER_ON(x) (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)(x) : HIDDEN_ROW) #define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW) #define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) #define INTERNAL_MODULE_CHANNELS_ROWS() IF_INTERNAL_MODULE_ON(1) @@ -1467,7 +1467,7 @@ void menuModelSetup(uint8_t event) break; case ITEM_MODEL_TRAINER_MODE: - g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, 0, 1, attr, event); + g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, 0, HAS_WIRELESS_TRAINER_HARDWARE() ? TRAINER_MODE_MASTER_BATTERY_COMPARTMENT : TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, attr, event); break; #endif diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 76a081911..619bad866 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -309,6 +309,7 @@ enum uartModes { UART_MODE_TELEMETRY_MIRROR, UART_MODE_TELEMETRY, UART_MODE_SBUS_TRAINER, + // UART_MODE_CPPM_TRAINER, #if defined(DEBUG) UART_MODE_DEBUG, #endif @@ -316,6 +317,7 @@ enum uartModes { UART_MODE_MAX = UART_MODE_COUNT-1 }; +#define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.uart3Mode==UART_MODE_SBUS_TRAINER/* || g_eeGeneral.uart3Mode==UART_MODE_CPPM_TRAINER*/) #define EXTRA_GENERAL_FIELDS \ EXTRA_GENERAL_FIELDS_ARM \ uint8_t uart3Mode; \ @@ -357,6 +359,14 @@ PACK(typedef struct { EXTERNAL_MODULE, TRAINER_MODULE }; + enum TrainerMode { + TRAINER_MODE_MASTER, + TRAINER_MODE_SLAVE, + TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, + TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, + TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, + }; + #define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE) #define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; #define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t nPotsToWarn; int8_t potPosition[NUM_POTS]; uint8_t spare[2]; #define swstate_t uint16_t @@ -1759,6 +1769,8 @@ enum ModuleTypes { MODULE_TYPE_COUNT }; +#define IS_PULSES_EXTERNAL_MODULE() (g_model.externalModule != MODULE_TYPE_NONE) + enum FailsafeModes { FAILSAFE_HOLD, FAILSAFE_CUSTOM, diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 3c82bc7fc..3cef91742 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -87,6 +87,56 @@ uint8_t g_tmr1Latency_min; uint16_t lastMixerDuration; #endif +#if defined(PCBTARANIS) +uint8_t currentTrainerMode = 0xff; + +void checkTrainerSettings() +{ + uint8_t requiredTrainerMode = g_model.trainerMode; + if (requiredTrainerMode != currentTrainerMode) { + switch (currentTrainerMode) { + case TRAINER_MODE_MASTER: + stop_trainer_capture(); + break; + case TRAINER_MODE_SLAVE: + stop_trainer_ppm(); + break; + case TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE: + stop_cppm_on_heartbeat_capture() ; + break; + case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE: + stop_sbus_on_heartbeat_capture() ; + break; + case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: + uart3Stop(); + } + + currentTrainerMode = requiredTrainerMode; + switch (requiredTrainerMode) { + case TRAINER_MODE_SLAVE: + init_trainer_ppm(); + break; + case TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE: + init_cppm_on_heartbeat_capture() ; + break; + case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE: + init_sbus_on_heartbeat_capture() ; + break; + case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: + if (g_eeGeneral.uart3Mode == UART_MODE_SBUS_TRAINER) { + uart3SbusInit(); + break; + } + // no break + default: + // master is default + init_trainer_capture(); + break; + } + } +} +#endif + uint8_t unexpectedShutdown = 0; /* AVR: mixer duration in 1/16ms */ diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 620357de3..c4786ba0a 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -923,7 +923,7 @@ extern uint16_t maxLuaDuration; #endif #if defined(PCBTARANIS) - static inline uint16_t getTmr2MHz() { return TIM3->CNT; } + static inline uint16_t getTmr2MHz() { return TIM7->CNT; } #elif defined(PCBSKY9X) static inline uint16_t getTmr2MHz() { return TC1->TC_CHANNEL[0].TC_CV; } #else diff --git a/radio/src/targets/taranis/board_taranis.cpp b/radio/src/targets/taranis/board_taranis.cpp index 04ea0a4d3..57fc2dc25 100644 --- a/radio/src/targets/taranis/board_taranis.cpp +++ b/radio/src/targets/taranis/board_taranis.cpp @@ -54,6 +54,19 @@ void watchdogInit(unsigned int duration) IWDG->KR = 0xCCCC ; // start } +// Start TIMER7 at 2000000Hz +void init2MhzTimer() +{ + // Now for timer 7 + RCC->APB1ENR |= RCC_APB1ENR_TIM7EN ; // Enable clock + + TIM7->PSC = 0 ; // Max speed + TIM7->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1 ; // 0.5 uS, 2 MHz + TIM7->CR2 = 0 ; + TIM7->CR2 = 0x20 ; + TIM7->CR1 = TIM_CR1_CEN ; +} + // Starts TIMER at 200Hz, 5mS period void init5msTimer() { @@ -108,6 +121,7 @@ void boardInit() adcInit(); delaysInit(); audioInit(); + init2MhzTimer(); init5msTimer(); __enable_irq(); eepromInit(); diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 48c76479b..2c7df163e 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -108,7 +108,7 @@ void configure_pins( uint32_t pins, uint16_t config ); extern uint16_t sessionTimer; -#define SLAVE_MODE() (g_model.trainerMode == 1) +#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE) #define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(GPIOTRNDET, PIN_TRNDET) == Bit_RESET) void delaysInit(void); @@ -156,6 +156,10 @@ void init_trainer_ppm(void); void stop_trainer_ppm(void); void init_trainer_capture(void); void stop_trainer_capture(void); +void init_cppm_on_heartbeat_capture(void); +void stop_cppm_on_heartbeat_capture(void); +void init_sbus_on_heartbeat_capture(void); +void stop_sbus_on_heartbeat_capture(void); // Keys driver void keysInit(void); @@ -197,8 +201,8 @@ void pwrOff(void); #define UNEXPECTED_SHUTDOWN() (g_eeGeneral.unexpectedShutdown) #define INTERNAL_RF_ON() GPIO_SetBits(GPIO_INT_RF_PWR, PIN_INT_RF_PWR) #define INTERNAL_RF_OFF() GPIO_ResetBits(GPIO_INT_RF_PWR, PIN_INT_RF_PWR) -#define EXTERNAL_RF_ON() GPIO_SetBits(GPIO_EXT_RF_PWR, PIN_EXT_RF_PWR) -#define EXTERNAL_RF_OFF() GPIO_ResetBits(GPIO_EXT_RF_PWR, PIN_EXT_RF_PWR) +#define EXTERNAL_MODULE_ON() GPIO_SetBits(GPIO_EXT_RF_PWR, PIN_EXT_RF_PWR) +#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(GPIO_EXT_RF_PWR, PIN_EXT_RF_PWR) // Backlight driver #if defined(REVPLUS) @@ -259,7 +263,7 @@ void hapticOff(void); void uart3Init(unsigned int mode, unsigned int protocol); void uart3Putc(const char c); #define telemetrySecondPortInit(protocol) uart3Init(UART_MODE_TELEMETRY, protocol) - -extern uint8_t currentTrainerMode; +void uart3SbusInit(); +void uart3Stop(); #endif diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 6ae6c2fda..c7c1c2e47 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -193,6 +193,7 @@ #define PIN_PER_3 0x0030 #define PIN_PER_5 0x0050 #define PIN_PER_6 0x0060 +#define PIN_PER_8 0x0080 // #define PIN_OS2 0x0000 #define PIN_OS25 0x2000 #define PIN_OS50 0x4000 diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index d91da6834..b3b51d56c 100644 --- a/radio/src/targets/taranis/pulses_driver.cpp +++ b/radio/src/targets/taranis/pulses_driver.cpp @@ -172,10 +172,11 @@ static void disable_pa10_none() static void init_pa7_none() { - EXTERNAL_RF_OFF(); + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } // Timer8 - GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIO_EXTPPM, ENABLE); @@ -374,7 +375,7 @@ extern "C" void TIM1_UP_TIM10_IRQHandler() static void init_pa7_pxx() { - EXTERNAL_RF_ON(); + EXTERNAL_MODULE_ON(); // Timer8 setupPulsesPXX(EXTERNAL_MODULE); @@ -442,13 +443,15 @@ static void disable_pa7_pxx() NVIC_DisableIRQ(TIM8_CC_IRQn) ; TIM8->DIER &= ~TIM_DIER_CC2IE ; TIM8->CR1 &= ~TIM_CR1_CEN ; - EXTERNAL_RF_OFF(); + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } } #if defined(DSM2) static void init_pa7_dsm2() { - EXTERNAL_RF_ON(); + EXTERNAL_MODULE_ON(); // Timer8 setupPulsesDSM2(EXTERNAL_MODULE); @@ -516,7 +519,9 @@ static void disable_pa7_dsm2() NVIC_DisableIRQ(TIM8_CC_IRQn) ; TIM8->DIER &= ~TIM_DIER_CC2IE ; TIM8->CR1 &= ~TIM_CR1_CEN ; - EXTERNAL_RF_OFF(); + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } } #endif @@ -525,7 +530,8 @@ static void disable_pa7_dsm2() // Pin is AF1 function for timer 1 static void init_pa7_ppm() { - EXTERNAL_RF_ON(); + EXTERNAL_MODULE_ON(); + // Timer1 setupPulsesPPM(EXTERNAL_MODULE) ; ppmStreamPtr[EXTERNAL_MODULE] = ppmStream[EXTERNAL_MODULE]; @@ -573,7 +579,9 @@ static void disable_pa7_ppm() NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn) ; TIM8->DIER &= ~TIM_DIER_CC2IE & ~TIM_DIER_UIE ; TIM8->CR1 &= ~TIM_CR1_CEN ; - EXTERNAL_RF_OFF(); + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } } extern "C" void TIM8_CC_IRQHandler() diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp index 2a92fd74e..51336cf6d 100644 --- a/radio/src/targets/taranis/trainer_driver.cpp +++ b/radio/src/targets/taranis/trainer_driver.cpp @@ -36,9 +36,9 @@ #include "../../opentx.h" -uint8_t currentTrainerMode; uint16_t * TrainerPulsePtr; extern uint16_t ppmStream[NUM_MODULES+1][20]; +extern Fifo<28> sbusFifo; #define setupTrainerPulses() setupPulsesPPM(TRAINER_MODULE) @@ -79,8 +79,7 @@ void stop_trainer_ppm() { configure_pins( PIN_TR_PPM_OUT, PIN_INPUT | PIN_PORTC ) ; // Pin as input TIM3->CR1 &= ~TIM_CR1_CEN ; // Stop counter - TIM3->DIER &= ~TIM_DIER_CC2IE ; // Stop Interrupt - TIM3->DIER &= ~TIM_DIER_UIE ; // Stop Interrupt + TIM3->DIER = 0 ; // Stop Interrupt NVIC_DisableIRQ(TIM3_IRQn) ; // Stop Interrupt } @@ -99,28 +98,38 @@ void init_trainer_capture() TIM3->SR &= ~TIM_SR_CC3IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF ; // Clear flags TIM3->DIER |= TIM_DIER_CC3IE ; TIM3->CR1 = TIM_CR1_CEN ; - NVIC_EnableIRQ(TIM3_IRQn) ; NVIC_SetPriority(TIM3_IRQn, 7); + NVIC_EnableIRQ(TIM3_IRQn) ; } void stop_trainer_capture() { TIM3->CR1 &= ~TIM_CR1_CEN ; // Stop counter - TIM3->DIER &= ~TIM_DIER_CC3IE ; // Stop Interrupt + TIM3->DIER = 0; // Stop Interrupt NVIC_DisableIRQ(TIM3_IRQn) ; // Stop Interrupt } extern "C" void TIM3_IRQHandler() { - uint16_t capture ; + uint16_t capture = 0; static uint16_t lastCapt ; uint16_t val ; + bool doCapture = false ; // What mode? in or out? if ( (TIM3->DIER & TIM_DIER_CC3IE ) && ( TIM3->SR & TIM_SR_CC3IF ) ) { - // capture mode + // capture mode on trainer jack capture = TIM3->CCR3 ; + doCapture = true; + } + if ( (TIM3->DIER & TIM_DIER_CC2IE ) && ( TIM3->SR & TIM_SR_CC2IF ) ) { + // capture mode on heartbeat pin (external module) + capture = TIM3->CCR2 ; + doCapture = true ; + } + + if (doCapture) { val = (uint16_t)(capture - lastCapt) / 2 ; lastCapt = capture; @@ -168,3 +177,66 @@ extern "C" void TIM3_IRQHandler() } } +void init_cppm_on_heartbeat_capture(void) +{ + EXTERNAL_MODULE_ON(); + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN ; // Enable portC clock + configure_pins( 0x0080, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_2 ) ; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN ; // Enable clock + + TIM3->ARR = 0xFFFF ; + TIM3->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1 ; // 0.5uS + TIM3->CR2 = 0 ; + TIM3->CCMR1 = TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_CC2S_0 ; + TIM3->CCER = TIM_CCER_CC2E ; + TIM3->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM3->DIER |= TIM_DIER_CC2IE ; + TIM3->CR1 = TIM_CR1_CEN ; + NVIC_SetPriority(TIM3_IRQn, 7); + NVIC_EnableIRQ(TIM3_IRQn) ; +} + +void stop_cppm_on_heartbeat_capture(void) +{ + TIM3->DIER = 0 ; + TIM3->CR1 &= ~TIM_CR1_CEN ; // Stop counter + NVIC_DisableIRQ(TIM3_IRQn) ; // Stop Interrupt + + if (!IS_PULSES_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } +} + +void init_sbus_on_heartbeat_capture(void) +{ + EXTERNAL_MODULE_ON(); + + RCC->APB2ENR |= RCC_APB2ENR_USART6EN ; // Enable clock + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN ; // Enable portC clock + // GPIOC->MODER = (GPIOC->MODER & 0xFFFFBFFF ) | 0x00008000 ; // Alternate func. + // GPIOC->AFR[0] = (GPIOC->AFR[0] & 0x0FFFFFFF ) | 0x80000000 ; // Alternate func. + configure_pins( 0x0080, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_8 ) ; + USART6->BRR = PERI2_FREQUENCY / 100000 ; + USART6->CR1 = USART_CR1_UE | USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_M | USART_CR1_PCE ; + USART6->CR2 = 0 ; + USART6->CR3 = 0 ; + (void) USART6->DR ; + NVIC_EnableIRQ(USART6_IRQn) ; +} + +void stop_sbus_on_heartbeat_capture(void) +{ + configure_pins( 0x0080, PIN_INPUT | PIN_PORTC ) ; + NVIC_DisableIRQ(USART6_IRQn) ; + + if (!IS_PULSES_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } +} + +extern "C" void USART6_IRQHandler() +{ + uint8_t data = USART6->DR; + sbusFifo.push(data); +} diff --git a/radio/src/targets/taranis/uart3_driver.cpp b/radio/src/targets/taranis/uart3_driver.cpp index 8100672cd..2a30bd6d4 100644 --- a/radio/src/targets/taranis/uart3_driver.cpp +++ b/radio/src/targets/taranis/uart3_driver.cpp @@ -97,10 +97,6 @@ void uart3Init(unsigned int mode, unsigned int protocol) uart3Setup(FRSKY_D_BAUDRATE); } break; - case UART_MODE_SBUS_TRAINER: - uart3Setup(100000); - USART3->CR1 |= USART_CR1_M | USART_CR1_PCE ; - break; } uart3Mode = mode; @@ -121,6 +117,17 @@ void debugPutc(const char c) } #endif +void uart3SbusInit() +{ + uart3Setup(100000); + USART3->CR1 |= USART_CR1_M | USART_CR1_PCE ; +} + +void uart3Stop() +{ + USART_DeInit(USART3); +} + #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) extern "C" void USART3_IRQHandler(void) diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 2648ce22c..a3e3f0ff6 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -79,8 +79,8 @@ #define LEN_TRNCHN "\003" #define TR_TRNCHN "CH1CH2CH3CH4" -#define LEN_UART3MODES "\017" -#define TR_UART3MODES "OFF\0 ""S-Port Mirror\0 ""Telemetry\0 ""SBUS Trainer\0 ""Debug\0 " +#define LEN_UART3MODES "\015" +#define TR_UART3MODES "OFF\0 ""S-Port Mirror""Telemetry\0 ""SBUS Trainer\0""Debug\0" #define LEN_POTTYPES "\017" #define TR_POTTYPES "None\0 ""Pot with detent""Multipos Switch""Pot\0" @@ -481,8 +481,8 @@ #define LEN_VTMRMODES "\003" #define TR_VTMRMODES "OFF""ON\0""THs""TH%""THt" -#define LEN_VTRAINERMODES "\006" -#define TR_VTRAINERMODES "Master""Slave\0" +#define LEN_VTRAINERMODES "\022" +#define TR_VTRAINERMODES "Master/Jack\0 ""Slave/Jack\0 ""Master/SBUS Module""Master/CPPM Module""Master/Battery\0" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE "Hold\0 ""Custom\0 ""No pulses""Receiver\0"