diff --git a/src/pulses_arm.cpp b/src/pulses_arm.cpp index 4994c4f10..8ad539b0d 100644 --- a/src/pulses_arm.cpp +++ b/src/pulses_arm.cpp @@ -51,8 +51,14 @@ uint8_t Bit_pulses[64] ; // Likely more than we need uint8_t *Pulses2MHzptr ; #else uint16_t pxxStream[400] ; // Transisitions + #if defined(PCBTARANIS) +uint16_t pxx2Stream[400] ; // Transisitions +uint16_t *pxxStreamPtr[NUM_MODULES] ; +uint16_t PxxValue[NUM_MODULES] ; + #else uint16_t *pxxStreamPtr ; uint16_t PxxValue ; + #endif #endif // DSM2 control bits @@ -67,7 +73,14 @@ uint8_t Serial_byte ; uint8_t Serial_bit_count; uint8_t Serial_byte_count ; -void setupPulses(); +#if defined(PCBTARANIS) +#define MODULE_INDEX_PARAM uint32_t module_index +#else +#define MODULE_INDEX_PARAM +#endif + +void setupPulses( MODULE_INDEX_PARAM ) ; + void setupPulsesDsm2(uint8_t chns); void setupPulsesPXX(); @@ -77,7 +90,11 @@ void startPulses() #if defined(PCBSKY9X) init_main_ppm(3000, 1) ; // Default for now, initial period 1.5 mS, output on #else + #if defined(PCBTARANIS) + init_ppm( 0 ) ; + #else init_main_ppm(); + #endif #endif } @@ -141,8 +158,13 @@ void setupPulsesPPM(PPM_PORT_PARAM) // Don't enable interrupts *(ptr + 1) = 0; #if defined(PCBTARANIS) - TIM1->CCR2 = rest - 1000 ; // Update time - TIM1->CCR1 = (g_model.ppmDelay*50+300)*2 ; +// THIS IS SPECIFIC TO EITHER THE INTERNAL OR EXTERNAL MODULE +// OTHER IS COMMENTED OUT. IF PPM IS NEEDED ON INTERNAL AS WELL AS EXTARNAL +// setupPulsesPPM() WILL NEED A "MODULE" PARAMETER + TIM8->CCR2 = rest - 1000 ; // Update time + TIM8->CCR1 = (g_model.ppmDelay*50+300)*2 ; +// TIM1->CCR2 = rest - 1000 ; // Update time +// TIM1->CCR3 = (g_model.ppmDelay*50+300)*2 ; #endif } @@ -182,9 +204,80 @@ const uint16_t CRCTable[]= 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; +#if defined(PCBTARANIS) +uint16_t PcmCrc[2] ; +uint8_t PcmOnesCount[2] ; + +void crc( uint8_t data, uint32_t module_index ) +{ + // uint8_t i ; + + PcmCrc[module_index]=(PcmCrc[module_index]<<8)^(CRCTable[((PcmCrc[module_index]>>8)^data) & 0xFF]); +} + +void putPcmPart( uint8_t value, uint32_t module_index ) +{ + PxxValue[module_index] += 18 ; // Output 1 for this time + *pxxStreamPtr[module_index]++ = PxxValue[module_index] ; + PxxValue[module_index] += 14 ; + if ( value ) { + PxxValue[module_index] += 16 ; + } + *pxxStreamPtr[module_index]++ = PxxValue[module_index] ; // Output 0 for this time +} + +void putPcmFlush( uint32_t module_index ) +{ + *pxxStreamPtr[module_index]++ = 18010 ; // Past the 18000 of the ARR +} + +void putPcmBit( uint8_t bit, uint32_t module_index ) +{ + if ( bit ) + { + PcmOnesCount[module_index] += 1 ; + putPcmPart( 1, module_index ) ; + } + else + { + PcmOnesCount[module_index] = 0 ; + putPcmPart( 0, module_index ) ; + } + if ( PcmOnesCount[module_index] >= 5 ) + { + putPcmBit( 0, module_index ) ; // Stuff a 0 bit in + } +} + +void putPcmByte( uint8_t byte, uint32_t module_index ) +{ + crc(byte, module_index); + + for (uint8_t i=0; i<8; i++) { + putPcmBit(byte & 0x80, module_index); + byte <<= 1; + } +} + +void putPcmHead( uint32_t module_index ) +{ + // send 7E, do not CRC + // 01111110 + putPcmPart( 0, module_index ) ; + putPcmPart( 1, module_index ) ; + putPcmPart( 1, module_index ) ; + putPcmPart( 1, module_index ) ; + putPcmPart( 1, module_index ) ; + putPcmPart( 1, module_index ) ; + putPcmPart( 1, module_index ) ; + putPcmPart( 0, module_index ) ; +} + +#else // Not Taranis uint16_t PcmCrc ; uint8_t PcmOnesCount ; + void crc( uint8_t data ) { // uint8_t i ; @@ -285,8 +378,9 @@ void putPcmHead() putPcmPart( 1 ) ; putPcmPart( 0 ) ; } +#endif // Taranis -void setupPulsesPXX() +void setupPulsesPXX(MODULE_INDEX_PARAM) { uint16_t chan=0, chan_low=0; @@ -296,10 +390,25 @@ void setupPulsesPXX() Serial_byte_count = 0 ; Pulses2MHzptr = Bit_pulses ; #else + #if defined(PCBTARANIS) + pxxStreamPtr[module_index] = module_index ? pxx2Stream : pxxStream ; + PxxValue[module_index] = 0 ; + #else pxxStreamPtr = pxxStream ; PxxValue = 0 ; + #endif #endif +#if defined(PCBTARANIS) + PcmCrc[module_index] = 0; + PcmOnesCount[module_index] = 0; + + /* Sync */ + putPcmHead(module_index); + + /* Rx Number */ + putPcmByte(g_model.modelId, module_index); +#else PcmCrc = 0; PcmOnesCount = 0; @@ -308,41 +417,53 @@ void setupPulsesPXX() /* Rx Number */ putPcmByte(g_model.modelId); +#endif /* FLAG1 */ uint8_t flag1; if (pxxFlag[0] & PXX_SEND_RXNUM) { - flag1 = (g_model.moduleData[0].rfProtocol << 6) | (g_eeGeneral.countryCode << 1) | pxxFlag[0]; + flag1 = (g_model.moduleData[module_index].rfProtocol << 6) | (g_eeGeneral.countryCode << 1) | pxxFlag[module_index]; } else { - flag1 = (g_model.moduleData[0].rfProtocol << 6) | pxxFlag[0]; + flag1 = (g_model.moduleData[module_index].rfProtocol << 6) | pxxFlag[0]; #if defined(PCBTARANIS) - if (g_model.moduleData[0].failsafeMode != FAILSAFE_HOLD) { + if (g_model.moduleData[module_index].failsafeMode != FAILSAFE_HOLD) { if (failsafeCounter-- == 0) { failsafeCounter = 1000; flag1 |= PXX_SEND_FAILSAFE; } - if (failsafeCounter == 0 && g_model.moduleData[0].channelsCount > 0) { + if (failsafeCounter == 0 && g_model.moduleData[module_index].channelsCount > 0) { flag1 |= PXX_SEND_FAILSAFE; } } #endif } +#if defined(PCBTARANIS) + putPcmByte(flag1, module_index); + + /* FLAG2 */ + putPcmByte(0, module_index); +#else putPcmByte(flag1); /* FLAG2 */ putPcmByte(0); +#endif /* PPM */ static uint32_t pass = 0; uint32_t sendUpperChannels = 0; if (pass++ & 0x01) { +#if defined(PCBTARANIS) + sendUpperChannels = g_model.moduleData[module_index].channelsCount; +#else sendUpperChannels = g_model.moduleData[0].channelsCount; +#endif } for (uint32_t i=0; i<8; i++) { #if defined(PCBTARANIS) if (flag1 & PXX_SEND_FAILSAFE) { - if (g_model.moduleData[0].failsafeMode == FAILSAFE_NOPULSES) { + if (g_model.moduleData[module_index].failsafeMode == FAILSAFE_NOPULSES) { if (i < sendUpperChannels) chan = 3072; else @@ -350,11 +471,11 @@ void setupPulsesPXX() } else { if (i < sendUpperChannels) { - chan = limit(2048, PPM_CH_CENTER(8+g_model.moduleData[0].channelsStart+i) - PPM_CENTER + (g_model.moduleData[0].failsafeChannels[8+g_model.moduleData[0].channelsStart+i] * 512 / 682) + 3072, 4095); + chan = limit(2048, PPM_CH_CENTER(8+g_model.moduleData[module_index].channelsStart+i) - PPM_CENTER + (g_model.moduleData[module_index].failsafeChannels[8+g_model.moduleData[0].channelsStart+i] * 512 / 682) + 3072, 4095); if (chan == 3072) chan = 3073; } else { - chan = limit(0, PPM_CH_CENTER(g_model.moduleData[0].channelsStart+i) - PPM_CENTER + (g_model.moduleData[0].failsafeChannels[g_model.moduleData[0].channelsStart+i] * 512 / 682) + 1024, 2047); + chan = limit(0, PPM_CH_CENTER(g_model.moduleData[module_index].channelsStart+i) - PPM_CENTER + (g_model.moduleData[module_index].failsafeChannels[g_model.moduleData[0].channelsStart+i] * 512 / 682) + 1024, 2047); if (chan == 1024) chan = 1025; } } @@ -369,9 +490,15 @@ void setupPulsesPXX() } if (i & 1) { +#if defined(PCBTARANIS) + putPcmByte(chan_low, module_index); // Low byte of channel + putPcmByte( ( ( chan_low >> 8 ) & 0x0F ) | ( chan << 4), module_index ) ; // 4 bits each from 2 channels + putPcmByte(chan >> 4, module_index); // High byte of channel +#else putPcmByte(chan_low); // Low byte of channel putPcmByte( ( ( chan_low >> 8 ) & 0x0F ) | ( chan << 4) ) ; // 4 bits each from 2 channels putPcmByte(chan >> 4); // High byte of channel +#endif } else { chan_low = chan; @@ -379,6 +506,17 @@ void setupPulsesPXX() } /* CRC16 */ +#if defined(PCBTARANIS) + putPcmByte(0, module_index); + chan = PcmCrc[module_index]; + putPcmByte(chan>>8, module_index); + putPcmByte(chan, module_index); + + /* Sync */ + putPcmHead(module_index); + + putPcmFlush(module_index); +#else putPcmByte(0); chan = PcmCrc; putPcmByte(chan>>8); @@ -388,6 +526,7 @@ void setupPulsesPXX() putPcmHead(); putPcmFlush(); +#endif } #if defined(DSM2) @@ -542,12 +681,16 @@ extern "C" void PWM_IRQHandler(void) } #endif -void setupPulses() +void setupPulses(MODULE_INDEX_PARAM) { heartbeat |= HEART_TIMER_PULSES; #if defined(PCBTARANIS) - uint8_t required_protocol = (g_model.moduleData[0].rfProtocol == RF_PROTO_OFF ? PROTO_NONE : PROTO_PXX); + if ( module_index ) + { + module_index = 1 ; // Ensure is 0 or 1 only + } + uint8_t required_protocol = (g_model.moduleData[module_index].rfProtocol == RF_PROTO_OFF ? PROTO_NONE : PROTO_PXX); #else uint8_t required_protocol = g_model.protocol; #endif @@ -559,7 +702,11 @@ void setupPulses() switch (s_current_protocol) { // stop existing protocol hardware case PROTO_PXX: +#if defined(PCBTARANIS) + disable_pxx(module_index); +#else disable_pxx(); +#endif break; #if defined(DSM2) case PROTO_DSM2_LP45: @@ -569,7 +716,11 @@ void setupPulses() break; #endif default: - disable_main_ppm(); +#if defined(PCBTARANIS) + disable_ppm(module_index); +#else + disable_ppm(); +#endif break; } @@ -578,10 +729,12 @@ void setupPulses() #if defined(PCBTARANIS) switch (required_protocol) { case PROTO_PXX: - init_pxx(); + init_pxx(0); +// init_pxx(module_index); break; default: - init_main_ppm(); + init_ppm(0); +// init_ppm(module_index); break; } #elif defined(PCBSKY9X) @@ -609,7 +762,11 @@ void setupPulses() // Set up output data here switch (required_protocol) { case PROTO_PXX: +#if defined(PCBTARANIS) + setupPulsesPXX(module_index); +#else setupPulsesPXX(); +#endif break; #if defined(DSM2) case PROTO_DSM2_LP45: diff --git a/src/taranis/board_taranis.cpp b/src/taranis/board_taranis.cpp index d56c808e1..962b821c0 100644 --- a/src/taranis/board_taranis.cpp +++ b/src/taranis/board_taranis.cpp @@ -221,14 +221,14 @@ void boardInit() usbInit(); //Temporary: Configure second PPM pin as input (done after USB init in case the lib already initialises USB_ID) - GPIO_InitTypeDef GPIO_InitStructure; - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIO_EXTPPM, ENABLE); - GPIO_InitStructure.GPIO_Pin = PIN_EXTPPM_OUT; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(GPIO_EXTPPM, &GPIO_InitStructure); +// GPIO_InitTypeDef GPIO_InitStructure; +// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIO_EXTPPM, ENABLE); +// GPIO_InitStructure.GPIO_Pin = PIN_EXTPPM_OUT; +// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; +// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; +// GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; +// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; +// GPIO_Init(GPIO_EXTPPM, &GPIO_InitStructure); } #endif diff --git a/src/taranis/board_taranis.h b/src/taranis/board_taranis.h index e5d945ab6..173b582ff 100644 --- a/src/taranis/board_taranis.h +++ b/src/taranis/board_taranis.h @@ -114,10 +114,10 @@ uint32_t sdMounted(); #endif // Pulses driver -void init_main_ppm(); -void disable_main_ppm(); -void init_pxx(); -void disable_pxx(); +void init_ppm( uint32_t module_index ); +void disable_ppm( uint32_t module_index ); +void init_pxx( uint32_t module_index ); +void disable_pxx( uint32_t module_index ); // Trainer driver void init_trainer_ppm(); diff --git a/src/taranis/pulses_driver.cpp b/src/taranis/pulses_driver.cpp index 36c84d98e..7cdbaf903 100644 --- a/src/taranis/pulses_driver.cpp +++ b/src/taranis/pulses_driver.cpp @@ -36,72 +36,136 @@ #include "../opentx.h" +#define EXTERNAL_TEST 0 + +// CURRENTLY EXPECTS ONLY PXX ON THE INTERNAL SIGNAL, PPM ALLOWED ON THE EXTERNAL SIGNAL + // TODO not here! -void setupPulses(); -void setupPulsesPPM(); -void setupPulsesPXX(); +void setupPulses( uint32_t module ); +void setupPulsesPPM() ; +void setupPulsesPXX( uint32_t module ); uint16_t *ppmStreamPtr; +uint16_t *ppm2StreamPtr; extern uint16_t ppmStream[20]; +extern uint16_t ppm2Stream[20]; extern uint16_t pxxStream[400] ; +extern uint16_t pxx2Stream[400] ; -void init_pxx() +#define INT_MODULE 0 +#define EXT_MODULE 0 + +static void init_pa10_pxx( void ) ; +static void disable_pa10_pxx( void ) ; +static void init_pa10_ppm( void ) ; +static void disable_pa10_ppm( void ) ; +static void init_pa7_pxx( void ) ; +static void disable_pa7_pxx( void ) ; +static void init_pa7_ppm( void ) ; +static void disable_pa7_ppm( void ) ; + +void init_pxx( uint32_t module_index ) { - INTERNAL_RF_ON(); + if ( module_index ) + { + init_pa10_pxx() ; + } + else + { + init_pa7_pxx() ; + } +} - // Timer1 - setupPulsesPXX() ; // TODO not here! +void disable_pxx( uint32_t module_index ) +{ + if ( module_index ) + { + disable_pa10_pxx() ; + } + else + { + disable_pa7_pxx() ; + } +} + +void init_ppm( uint32_t module_index ) +{ + if ( module_index ) + { + init_pa10_ppm() ; + } + else + { + init_pa7_ppm() ; + } +} + +void disable_ppm( uint32_t module_index ) +{ + if ( module_index ) + { + disable_pa10_ppm() ; + } + else + { + disable_pa7_ppm() ; + } +} + + +static void init_pa10_pxx() +{ + EXTERNAL_RF_ON(); + + // Timer1, channel 3 + setupPulsesPXX(EXT_MODULE) ; // TODO not here! RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock -#if defined(REV3) - configure_pins( 0x0100, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; -#else GPIO_InitTypeDef GPIO_InitStructure; - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOCPPM, ENABLE); - GPIO_PinAFConfig(GPIOCPPM, GPIO_PinSource_CPPM, GPIO_AF_TIM1); - GPIO_InitStructure.GPIO_Pin = PIN_CPPM_OUT; +// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOCPPM, ENABLE); + + GPIO_PinAFConfig(GPIO_EXTPPM, GPIO_PinSource_EXTPPM, GPIO_AF_TIM1); + GPIO_InitStructure.GPIO_Pin = PIN_EXTPPM_OUT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOCPPM, &GPIO_InitStructure); -#endif - RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // Enable clock - RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN ; // Enable DMA1 clock + + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // Enable clock + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN ; // Enable DMA2 clock TIM1->CR1 &= ~TIM_CR1_CEN ; TIM1->ARR = 18000 ; // 9mS TIM1->CCR2 = 15000 ; // Update time TIM1->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz -#if defined(REV3) - TIM1->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P ; -#else - TIM1->CCER = TIM_CCER_CC1NE ; -#endif - TIM1->CR2 = TIM_CR2_OIS1 ; // O/P idle high + + TIM1->CCER = TIM_CCER_CC3E ; + + TIM1->CR2 = TIM_CR2_OIS3 ; // O/P idle high TIM1->BDTR = TIM_BDTR_MOE ; // Enable outputs - TIM1->CCR1 = pxxStream[0] ; - TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0 ; // Force O/P high + TIM1->CCR3 = pxxStream[0] ; + TIM1->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0 ; // Force O/P high TIM1->EGR = 1 ; // Restart -// TIM1->SR &= ~TIM_SR_UIF ; // Clear flag -// TIM1->SR &= ~TIM_SR_CC2IF ; // Clear flag - TIM1->DIER |= TIM_DIER_CC1DE ; // Enable DMA on CC1 match - TIM1->DCR = 13 ; // DMA to CC1 +// TIM1->SR &= ~TIM_SR_UIF ; // Clear flag +// TIM1->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM1->DIER |= TIM_DIER_CC3DE ; // Enable DMA on CC3 match + TIM1->DCR = 15 ; // DMA to CC1 // TIM1->CR1 = TIM_CR1_OPM ; // Just run once - // Enable the DMA channel here, DMA2 stream 1, channel 6 - DMA2_Stream1->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA2->LIFCR = DMA_LIFCR_CTCIF1 | DMA_LIFCR_CHTIF1 | DMA_LIFCR_CTEIF1 | DMA_LIFCR_CDMEIF1 | DMA_LIFCR_CFEIF1 ; // Write ones to clear bits - DMA2_Stream1->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 - | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL ; - DMA2_Stream1->PAR = CONVERT_PTR(&TIM1->DMAR); - DMA2_Stream1->M0AR = CONVERT_PTR(&pxxStream[1]); -// DMA2_Stream1->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; -// DMA2_Stream1->NDTR = 100 ; - DMA2_Stream1->CR |= DMA_SxCR_EN ; // Enable DMA + // Enable the DMA channel here, DMA2 stream 6, channel 6 + DMA2_Stream6->CR &= ~DMA_SxCR_EN ; // Disable DMA + DMA2->HIFCR = DMA_HIFCR_CTCIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 | DMA_HIFCR_CFEIF6 ; // Write ones to clear bits + DMA2_Stream6->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 + | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL ; + DMA2_Stream6->PAR = CONVERT_PTR(&TIM1->DMAR); + DMA2_Stream6->M0AR = CONVERT_PTR(&pxxStream[1]); +// DMA2_Stream2->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; +// DMA2_Stream2->NDTR = 100 ; + DMA2_Stream6->CR |= DMA_SxCR_EN ; // Enable DMA - TIM1->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 ; // Toggle CC1 o/p + TIM1->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 ; // Toggle CC1 o/p TIM1->SR &= ~TIM_SR_CC2IF ; // Clear flag TIM1->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt TIM1->CR1 |= TIM_CR1_CEN ; @@ -109,18 +173,19 @@ void init_pxx() NVIC_EnableIRQ(TIM1_CC_IRQn) ; } -void disable_pxx() +static void disable_pa10_pxx() { + DMA2_Stream6->CR &= ~DMA_SxCR_EN ; // Disable DMA NVIC_DisableIRQ(TIM1_CC_IRQn) ; TIM1->DIER &= ~TIM_DIER_CC2IE ; TIM1->CR1 &= ~TIM_CR1_CEN ; - INTERNAL_RF_OFF(); + EXTERNAL_RF_OFF(); } // PPM output // Timer 1, channel 1 on PA8 for prototype // Pin is AF1 function for timer 1 -void init_main_ppm() +static void init_pa10_ppm() { EXTERNAL_RF_ON(); // Timer1 @@ -128,22 +193,20 @@ void init_main_ppm() ppmStreamPtr = ppmStream ; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock -#if defined(REV3) - configure_pins( 0x0100, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; -#else - configure_pins( 0x0080, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; -#endif - RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // Enable clock + configure_pins( PIN_EXTPPM_OUT, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; + + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // Enable clock + + TIM1->CR1 &= ~TIM_CR1_CEN ; TIM1->ARR = *ppmStreamPtr++ ; TIM1->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz -#if defined(REV3) - TIM1->CCER = TIM_CCER_CC1E ; -#else - TIM1->CCER = TIM_CCER_CC1NE | TIM_CCER_CC1NP ; -#endif - TIM1->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE ; // PWM mode 1 - TIM1->CCR1 = 600 ; // 300 uS pulse + + TIM1->CCER = TIM_CCER_CC3E ; + + TIM1->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 ; // PWM mode 1 + TIM1->CCMR1 = TIM_CCMR1_OC2PE ; // PWM mode 1 + TIM1->CCR3 = 600 ; // 300 uS pulse ?? (g_model.ppmDelay*50+300)*2 ?? TIM1->BDTR = TIM_BDTR_MOE ; TIM1->EGR = 1 ; TIM1->DIER = TIM_DIER_UDE ; @@ -158,12 +221,23 @@ void init_main_ppm() NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn) ; } -void disable_main_ppm() +static void disable_pa10_ppm() { NVIC_DisableIRQ(TIM1_CC_IRQn) ; NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn) ; TIM1->DIER &= ~TIM_DIER_CC2IE & ~TIM_DIER_UIE ; TIM1->CR1 &= ~TIM_CR1_CEN ; + + // Make pin an input + GPIO_InitTypeDef GPIO_InitStructure; + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIO_EXTPPM, ENABLE); + GPIO_InitStructure.GPIO_Pin = PIN_EXTPPM_OUT; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Init(GPIO_EXTPPM, &GPIO_InitStructure); + EXTERNAL_RF_OFF(); } @@ -172,14 +246,14 @@ extern "C" void TIM1_CC_IRQHandler() TIM1->DIER &= ~TIM_DIER_CC2IE ; // stop this interrupt TIM1->SR &= ~TIM_SR_CC2IF ; // Clear flag - setupPulses() ; + setupPulses(1) ; if (s_current_protocol == PROTO_PXX) { - DMA2_Stream1->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA2->LIFCR = DMA_LIFCR_CTCIF1 | DMA_LIFCR_CHTIF1 | DMA_LIFCR_CTEIF1 | DMA_LIFCR_CDMEIF1 | DMA_LIFCR_CFEIF1 ; // Write ones to clear bits - DMA2_Stream1->M0AR = CONVERT_PTR(&pxxStream[1]); - DMA2_Stream1->CR |= DMA_SxCR_EN ; // Enable DMA - TIM1->CCR1 = pxxStream[0] ; + DMA2_Stream6->CR &= ~DMA_SxCR_EN ; // Disable DMA + DMA2->HIFCR = DMA_HIFCR_CTCIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 | DMA_HIFCR_CFEIF6 ; // Write ones to clear bits + DMA2_Stream6->M0AR = CONVERT_PTR(&pxxStream[1]); + DMA2_Stream6->CR |= DMA_SxCR_EN ; // Enable DMA + TIM1->CCR3 = pxxStream[0] ; TIM1->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt } else { @@ -202,3 +276,183 @@ extern "C" void TIM1_UP_TIM10_IRQHandler() TIM1->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt } } + + + +static void init_pa7_pxx() +{ +#if EXTERNAL_TEST + init_pa10_pxx() ; + return ; +#endif + INTERNAL_RF_ON(); + + // Timer8 + setupPulsesPXX(INT_MODULE) ; // TODO not here! + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock +#if defined(REV3) + configure_pins( PIN_CPPM_OUT, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; +#else + GPIO_InitTypeDef GPIO_InitStructure; + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOCPPM, ENABLE); + GPIO_PinAFConfig(GPIOCPPM, GPIO_PinSource_CPPM, GPIO_AF_TIM8); + GPIO_InitStructure.GPIO_Pin = PIN_CPPM_OUT; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOCPPM, &GPIO_InitStructure); +#endif + RCC->APB2ENR |= RCC_APB2ENR_TIM8EN ; // Enable clock + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN ; // Enable DMA2 clock + + TIM8->CR1 &= ~TIM_CR1_CEN ; + TIM8->ARR = 18000 ; // 9mS + TIM8->CCR2 = 15000 ; // Update time + TIM8->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz +#if defined(REV3) + TIM8->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P ; +#else + TIM8->CCER = TIM_CCER_CC1NE ; +#endif + TIM8->CR2 = TIM_CR2_OIS1 ; // O/P idle high + TIM8->BDTR = TIM_BDTR_MOE ; // Enable outputs + TIM8->CCR1 = pxxStream[0] ; + TIM8->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0 ; // Force O/P high + TIM8->EGR = 1 ; // Restart + +// TIM8->SR &= ~TIM_SR_UIF ; // Clear flag +// TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM8->DIER |= TIM_DIER_CC1DE ; // Enable DMA on CC1 match + TIM8->DCR = 13 ; // DMA to CC1 + +// TIM8->CR1 = TIM_CR1_OPM ; // Just run once + // Enable the DMA channel here, DMA2 stream 2, channel 7 + DMA2_Stream2->CR &= ~DMA_SxCR_EN ; // Disable DMA + DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2 ; // Write ones to clear bits + DMA2_Stream2->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 + | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL ; + DMA2_Stream2->PAR = CONVERT_PTR(&TIM8->DMAR); + DMA2_Stream2->M0AR = CONVERT_PTR(&pxxStream[1]); +// DMA2_Stream2->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; +// DMA2_Stream2->NDTR = 100 ; + DMA2_Stream2->CR |= DMA_SxCR_EN ; // Enable DMA + + TIM8->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 ; // Toggle CC1 o/p + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM8->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt + TIM8->CR1 |= TIM_CR1_CEN ; +// NVIC_SetPriority(TIM8_CC_IRQn, 1); // Debug - high priority, doesn't help + NVIC_EnableIRQ(TIM8_CC_IRQn) ; +} + +static void disable_pa7_pxx() +{ +#if EXTERNAL_TEST + disable_pa10_pxx() ; + return ; +#endif + DMA2_Stream2->CR &= ~DMA_SxCR_EN ; // Disable DMA + NVIC_DisableIRQ(TIM8_CC_IRQn) ; + TIM8->DIER &= ~TIM_DIER_CC2IE ; + TIM8->CR1 &= ~TIM_CR1_CEN ; + INTERNAL_RF_OFF(); +} + +// PPM output +// Timer 1, channel 1 on PA8 for prototype +// Pin is AF1 function for timer 1 +static void init_pa7_ppm() +{ +#if EXTERNAL_TEST + init_pa10_ppm() ; + return ; +#endif + INTERNAL_RF_ON(); + // Timer1 + setupPulsesPPM() ; + ppmStreamPtr = ppmStream ; + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock +#if defined(REV3) + configure_pins( 0x0100, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; +#else + configure_pins( 0x0080, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_3 | PIN_OS25 | PIN_PUSHPULL ) ; +#endif + RCC->APB2ENR |= RCC_APB2ENR_TIM8EN ; // Enable clock + + TIM8->CR1 &= ~TIM_CR1_CEN ; + + TIM8->ARR = *ppmStreamPtr++ ; + TIM8->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz +#if defined(REV3) + TIM8->CCER = TIM_CCER_CC1E ; +#else + TIM8->CCER = TIM_CCER_CC1NE | TIM_CCER_CC1NP ; +#endif + TIM8->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE ; // PWM mode 1 + TIM8->CCR1 = 600 ; // 300 uS pulse ?? (g_model.ppmDelay*50+300)*2 ?? + TIM8->BDTR = TIM_BDTR_MOE ; + TIM8->EGR = 1 ; + TIM8->DIER = TIM_DIER_UDE ; + + TIM8->SR &= ~TIM_SR_UIF ; // Clear flag + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM8->DIER |= TIM_DIER_CC2IE ; + TIM8->DIER |= TIM_DIER_UIE ; + + TIM8->CR1 = TIM_CR1_CEN ; + NVIC_EnableIRQ(TIM8_CC_IRQn) ; + NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn) ; +} + +static void disable_pa7_ppm() +{ +#if EXTERNAL_TEST + disable_pa10_ppm() ; + return ; +#endif + NVIC_DisableIRQ(TIM8_CC_IRQn) ; + NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn) ; + TIM8->DIER &= ~TIM_DIER_CC2IE & ~TIM_DIER_UIE ; + TIM8->CR1 &= ~TIM_CR1_CEN ; + INTERNAL_RF_OFF(); +} + +extern "C" void TIM8_CC_IRQHandler() +{ + TIM8->DIER &= ~TIM_DIER_CC2IE ; // stop this interrupt + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag + + setupPulses(INT_MODULE) ; + + if (s_current_protocol == PROTO_PXX) { + DMA2_Stream2->CR &= ~DMA_SxCR_EN ; // Disable DMA + DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2 ; // Write ones to clear bits + DMA2_Stream2->M0AR = CONVERT_PTR(&pxxStream[1]); + DMA2_Stream2->CR |= DMA_SxCR_EN ; // Enable DMA + TIM8->CCR1 = pxxStream[0] ; + TIM8->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt + } + else { + ppmStreamPtr = ppmStream ; + + TIM8->DIER |= TIM_DIER_UDE ; + TIM8->SR &= ~TIM_SR_UIF ; // Clear this flag + TIM8->DIER |= TIM_DIER_UIE ; // Enable this interrupt + } +} + +extern "C" void TIM8_UP_TIM13_IRQHandler() +{ + TIM8->SR &= ~TIM_SR_UIF ; // Clear flag + + TIM8->ARR = *ppmStreamPtr++ ; + if ( *ppmStreamPtr == 0 ) + { + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear this flag + TIM8->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt + } +} + diff --git a/src/taranis/trainer_driver.cpp b/src/taranis/trainer_driver.cpp index 8838b86ff..adc8c451c 100644 --- a/src/taranis/trainer_driver.cpp +++ b/src/taranis/trainer_driver.cpp @@ -72,72 +72,46 @@ void setupTrainerPulses() *ptr++ = rest ; *ptr = 0 ; - TIM8->CCR2 = rest - 1000 ; // Update time - TIM8->CCR4 = (g_model.ppmDelay*50+300)*2 ; + TIM3->CCR2 = rest - 1000 ; // Update time + TIM3->CCR4 = (g_model.ppmDelay*50+300)*2 ; } -// Trainer PPM oputput PC9, Timer 8 channel 4 +// Trainer PPM oputput PC9, Timer 3 channel 4, (Alternate Function 2) void init_trainer_ppm() { setupTrainerPulses() ; TrainerPulsePtr = TrainerPpmStream ; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN ; // Enable portC clock - configure_pins( 0x0200, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_3 | PIN_OS25 | PIN_PUSHPULL ) ; - RCC->APB2ENR |= RCC_APB2ENR_TIM8EN ; // Enable clock + configure_pins( PIN_TR_PPM_OUT, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_3 | PIN_OS25 | PIN_PUSHPULL ) ; + configure_pins( PIN_TR_PPM_IN, PIN_PORTA | PIN_INPUT ) ; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN ; // Enable clock - TIM8->ARR = *TrainerPulsePtr++ ; - TIM8->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz - TIM8->CCER = TIM_CCER_CC4E ; - TIM8->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE ; // PWM mode 1 - TIM8->CCR4 = 600 ; // 300 uS pulse - TIM8->BDTR = TIM_BDTR_MOE ; - TIM8->EGR = 1 ; - // TIM8->DIER = TIM_DIER_UDE ; + TIM3->ARR = *TrainerPulsePtr++ ; + TIM3->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1 ; // 0.5uS + TIM3->CCER = TIM_CCER_CC4E ; + TIM3->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE ; // PWM mode 1 + TIM3->CCR4 = 600 ; // 300 uS pulse + TIM3->BDTR = TIM_BDTR_MOE ; + TIM3->EGR = 1 ; + // TIM3->DIER = TIM_DIER_UDE ; - TIM8->SR &= ~TIM_SR_UIF ; // Clear flag - TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag - TIM8->DIER |= TIM_DIER_CC2IE ; - TIM8->DIER |= TIM_DIER_UIE ; + TIM3->SR &= ~TIM_SR_UIF ; // Clear flag + TIM3->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM3->DIER |= TIM_DIER_CC2IE ; + TIM3->DIER |= TIM_DIER_UIE ; - TIM8->CR1 = TIM_CR1_CEN ; - NVIC_EnableIRQ(TIM8_CC_IRQn) ; - NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn) ; + TIM3->CR1 = TIM_CR1_CEN ; + NVIC_EnableIRQ(TIM3_IRQn) ; +// NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn) ; } // TODO - testing void stop_trainer_ppm() { - configure_pins( 0x0200, PIN_INPUT | PIN_PORTC ) ; - TIM8->CR1 &= ~TIM_CR1_CEN ; // Stop counter - NVIC_DisableIRQ(TIM8_CC_IRQn) ; // Stop Interrupt - NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn) ; // Stop Interrupt -} - -extern "C" void TIM8_CC_IRQHandler() -{ - TIM8->DIER &= ~TIM_DIER_CC2IE ; // stop this interrupt - TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag - - setupTrainerPulses() ; - - TrainerPulsePtr = TrainerPpmStream ; - TIM8->DIER |= TIM_DIER_UDE ; - - TIM8->SR &= ~TIM_SR_UIF ; // Clear this flag - TIM8->DIER |= TIM_DIER_UIE ; // Enable this interrupt -} - -extern "C" void TIM8_UP_TIM13_IRQHandler() -{ - TIM8->SR &= ~TIM_SR_UIF ; // Clear flag - - TIM8->ARR = *TrainerPulsePtr++ ; - if ( *TrainerPulsePtr == 0 ) - { - TIM8->SR &= ~TIM_SR_CC2IF ; // Clear this flag - TIM8->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt - } + configure_pins( PIN_TR_PPM_OUT, PIN_INPUT | PIN_PORTC ) ; + TIM3->CR1 &= ~TIM_CR1_CEN ; // Stop counter + NVIC_DisableIRQ(TIM3_IRQn) ; // Stop Interrupt } // Trainer capture, PC8, Timer 3 channel 3 @@ -152,7 +126,7 @@ void init_trainer_capture() TIM3->CR2 = 0 ; TIM3->CCMR2 = TIM_CCMR2_IC3F_0 | TIM_CCMR2_IC3F_1 | TIM_CCMR2_CC3S_0 ; TIM3->CCER = TIM_CCER_CC3E ; - TIM3->SR &= ~TIM_SR_CC3IF ; // Clear flag + 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) ; @@ -165,25 +139,58 @@ extern "C" void TIM3_IRQHandler() static uint16_t lastCapt ; uint16_t val ; - capture = TIM3->CCR3 ; + // What mode? in or out? + if ( (TIM3->DIER & TIM_DIER_CC3IE ) && ( TIM3->SR & TIM_SR_CC3IF ) ) + { + // capture mode + capture = TIM3->CCR3 ; - val = (uint16_t)(capture - lastCapt) / 2 ; - lastCapt = capture; + val = (uint16_t)(capture - lastCapt) / 2 ; + lastCapt = capture; - // We prcoess g_ppmInsright here to make servo movement as smooth as possible - // while under trainee control - if ((val>4000) && (val < 19000)) { // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses) - ppmInState = 1; // triggered - } - else { - if(ppmInState && (ppmInState<=8)) { - if ((val>800) && (val<2200)) { - g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough. - } - else { - ppmInState = 0; // not triggered - } - } - } + // We prcoess g_ppmInsright here to make servo movement as smooth as possible + // while under trainee control + if ((val>4000) && (val < 19000)) { // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses) + ppmInState = 1; // triggered + } + else { + if(ppmInState && (ppmInState<=8)) { + if ((val>800) && (val<2200)) { + g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough. + } + else { + ppmInState = 0; // not triggered + } + } + } + } + // PPM out compare interrupt + if ( ( TIM3->DIER & TIM_DIER_CC2IE ) && ( TIM3->SR & TIM_SR_CC2IF ) ) + { // compare interrupt + TIM3->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM3->DIER &= ~TIM_DIER_CC2IE ; // stop this interrupt + TIM3->SR &= ~TIM_SR_CC2IF ; // Clear flag + + setupTrainerPulses() ; + + TrainerPulsePtr = TrainerPpmStream ; + TIM3->DIER |= TIM_DIER_UDE ; + + TIM3->SR &= ~TIM_SR_UIF ; // Clear this flag + TIM3->DIER |= TIM_DIER_UIE ; // Enable this interrupt + } + + // PPM out update interrupt + if ( (TIM3->DIER & TIM_DIER_UIE) && ( TIM3->SR & TIM_SR_UIF ) ) + { + TIM3->SR &= ~TIM_SR_UIF ; // Clear flag + + TIM3->ARR = *TrainerPulsePtr++ ; + if ( *TrainerPulsePtr == 0 ) + { + TIM3->SR &= ~TIM_SR_CC2IF ; // Clear this flag + TIM3->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt + } + } }