From a5ec1355d455ca4adf9b1c6c468a90c1f37ad22f Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Tue, 22 Jul 2014 21:29:00 +0100 Subject: [PATCH] CC3D - Support PPM input on IN_S1. This required timer overflow events to be used in the calculation of PPM channel data. CC3D tested, other targets may be unstable as a result. Needs further testing. --- src/main/drivers/pwm_mapping.c | 15 ++-------- src/main/drivers/pwm_rssi.c | 2 +- src/main/drivers/pwm_rx.c | 32 +++++++++++++++----- src/main/drivers/serial_softserial.c | 5 ++-- src/main/drivers/timer.c | 44 ++++++++++++++++++++++------ src/main/drivers/timer.h | 5 ++-- 6 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/main/drivers/pwm_mapping.c b/src/main/drivers/pwm_mapping.c index 42db7edb47..62d0747ff8 100755 --- a/src/main/drivers/pwm_mapping.c +++ b/src/main/drivers/pwm_mapping.c @@ -70,7 +70,7 @@ enum { TYPE_S, }; -#if USABLE_TIMER_CHANNEL_COUNT >= 14 +#if defined(NAZE) || defined(OLIMEXINO) || defined(NAZE32PRO) || defined(STM32F3DISCOVERY) static const uint16_t multiPPM[] = { PWM1 | (TYPE_IP << 8), // PPM input PWM9 | (TYPE_M << 8), // Swap to servo if needed @@ -138,17 +138,7 @@ static const uint16_t airPWM[] = { }; #endif -#if USABLE_TIMER_CHANNEL_COUNT == 12 -#ifdef CC3D // XXX HACK while PPM and MOTOR code conflicts. -static const uint16_t multiPPM[] = { - PWM6 | (TYPE_IP << 8), // PPM input - PWM7 | (TYPE_M << 8), // Swap to servo if needed - PWM8 | (TYPE_M << 8), // Swap to servo if needed - PWM9 | (TYPE_M << 8), - PWM10 | (TYPE_M << 8), - 0xFFFF -}; -#else +#ifdef CC3D static const uint16_t multiPPM[] = { PWM1 | (TYPE_IP << 8), // PPM input PWM7 | (TYPE_M << 8), // Swap to servo if needed @@ -164,7 +154,6 @@ static const uint16_t multiPPM[] = { PWM6 | (TYPE_M << 8), // Swap to servo if needed 0xFFFF }; -#endif static const uint16_t multiPWM[] = { PWM1 | (TYPE_IW << 8), // input #1 PWM2 | (TYPE_IW << 8), diff --git a/src/main/drivers/pwm_rssi.c b/src/main/drivers/pwm_rssi.c index b0cc544833..b97f74ed27 100644 --- a/src/main/drivers/pwm_rssi.c +++ b/src/main/drivers/pwm_rssi.c @@ -102,7 +102,7 @@ void pwmRSSIInConfig(uint8_t timerIndex) pwmRSSIICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, 0xFFFF, 1); - configureTimerCaptureCompareInterrupt(timerHardwarePtr, UNUSED_CALLBACK_REFERENCE, pwmRssiCallback); + configureTimerCaptureCompareInterrupt(timerHardwarePtr, UNUSED_CALLBACK_REFERENCE, pwmRssiCallback, NULL); } uint16_t pwmRSSIRead(void) diff --git a/src/main/drivers/pwm_rx.c b/src/main/drivers/pwm_rx.c index cee2248959..3802ff5578 100644 --- a/src/main/drivers/pwm_rx.c +++ b/src/main/drivers/pwm_rx.c @@ -79,18 +79,36 @@ void resetPPMDataReceivedState(void) #define MIN_CHANNELS_BEFORE_PPM_FRAME_CONSIDERED_VALID 4 -static void ppmCallback(uint8_t port, captureCompare_t capture) +uint32_t largeCounter = 0; + +static void ppmOverflowCallback(uint8_t port, captureCompare_t capture) { - uint16_t diff; // See PPM_TIMER_PERIOD - static captureCompare_t now; - static captureCompare_t last = 0; + largeCounter += capture; +} + +static void ppmEdgeCallback(uint8_t port, captureCompare_t capture) +{ + uint32_t diff; // See PPM_TIMER_PERIOD + static uint32_t now = 0; + static uint32_t last = 0; static uint8_t chan = 0; last = now; now = capture; + + now += largeCounter; + diff = now - last; +#if 0 + static uint32_t diffs[20]; + static uint8_t diffIndex = 0; + + diffIndex = (diffIndex + 1) % 20; + diffs[diffIndex] = diff; +#endif + if (diff > 2700) { // Per http://www.rcgroups.com/forums/showpost.php?p=21996147&postcount=3960 "So, if you use 2.5ms or higher as being the reset for the PPM stream start, you will be fine. I use 2.7ms just to be safe." if (chan >= MIN_CHANNELS_BEFORE_PPM_FRAME_CONSIDERED_VALID) { ppmFrameCount++; @@ -105,7 +123,7 @@ static void ppmCallback(uint8_t port, captureCompare_t capture) } -static void pwmCallback(uint8_t port, captureCompare_t capture) +static void pwmEdgeCallback(uint8_t port, captureCompare_t capture) { pwmInputPort_t *pwmInputPort = &pwmInputPorts[port]; const timerHardware_t *timerHardware = pwmInputPort->timerHardware; @@ -167,7 +185,7 @@ void pwmInConfig(uint8_t timerIndex, uint8_t channel) pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, PWM_TIMER_PERIOD, PWM_TIMER_MHZ); - configureTimerCaptureCompareInterrupt(timerHardwarePtr, channel, pwmCallback); + configureTimerCaptureCompareInterrupt(timerHardwarePtr, channel, pwmEdgeCallback, NULL); } #define UNUSED_PPM_TIMER_REFERENCE 0 @@ -186,7 +204,7 @@ void ppmInConfig(uint8_t timerIndex) pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, PPM_TIMER_PERIOD, PWM_TIMER_MHZ); - configureTimerCaptureCompareInterrupt(timerHardwarePtr, UNUSED_PPM_TIMER_REFERENCE, ppmCallback); + configureTimerCaptureCompareInterrupt(timerHardwarePtr, UNUSED_PPM_TIMER_REFERENCE, ppmEdgeCallback, ppmOverflowCallback); } uint16_t pwmRead(uint8_t channel) diff --git a/src/main/drivers/serial_softserial.c b/src/main/drivers/serial_softserial.c index 48a321e532..cdf06604c7 100644 --- a/src/main/drivers/serial_softserial.c +++ b/src/main/drivers/serial_softserial.c @@ -17,6 +17,7 @@ #include #include +#include #include "platform.h" @@ -102,7 +103,7 @@ static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t uint8_t mhz = SystemCoreClock / 1000000; timerConfigure(timerHardwarePtr, timerPeriod, mhz); - configureTimerCaptureCompareInterrupt(timerHardwarePtr, reference, onSerialTimer); + configureTimerCaptureCompareInterrupt(timerHardwarePtr, reference, onSerialTimer, NULL); } static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity) @@ -123,7 +124,7 @@ static void serialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t { // start bit is usually a FALLING signal serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, inversion == SERIAL_INVERTED ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); - configureTimerCaptureCompareInterrupt(timerHardwarePtr, reference, onSerialRxPinChange); + configureTimerCaptureCompareInterrupt(timerHardwarePtr, reference, onSerialRxPinChange, NULL); } static void serialOutputPortConfig(const timerHardware_t *timerHardwarePtr) diff --git a/src/main/drivers/timer.c b/src/main/drivers/timer.c index 3cad5ad58b..da99718e4c 100644 --- a/src/main/drivers/timer.c +++ b/src/main/drivers/timer.c @@ -229,7 +229,8 @@ static const uint16_t channels[CC_CHANNELS_PER_TIMER] = { typedef struct timerConfig_s { TIM_TypeDef *tim; uint8_t channel; - timerCCCallbackPtr *callback; + timerCCCallbackPtr *edgeCallback; + timerCCCallbackPtr *overflowCallback; uint8_t reference; } timerConfig_t; @@ -258,7 +259,12 @@ static uint8_t lookupTimerConfigIndex(TIM_TypeDef *tim, const uint16_t channel) return lookupTimerIndex(tim) + (MAX_TIMERS * lookupChannelIndex(channel)); } -void configureTimerChannelCallback(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *callback) +void configureTimerChannelCallback(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *edgeCallback) +{ + configureTimerChannelCallbacks(tim, channel, reference, edgeCallback, NULL); +} + +void configureTimerChannelCallbacks(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *edgeCallback, timerCCCallbackPtr *overflowCallback) { assert_param(IS_TIM_CHANNEL(channel)); @@ -268,7 +274,8 @@ void configureTimerChannelCallback(TIM_TypeDef *tim, uint8_t channel, uint8_t re return; } - timerConfig[timerConfigIndex].callback = callback; + timerConfig[timerConfigIndex].edgeCallback = edgeCallback; + timerConfig[timerConfigIndex].overflowCallback = overflowCallback; timerConfig[timerConfigIndex].channel = channel; timerConfig[timerConfigIndex].reference = reference; } @@ -291,10 +298,13 @@ void configureTimerInputCaptureCompareChannel(TIM_TypeDef *tim, const uint8_t ch } } -void configureTimerCaptureCompareInterrupt(const timerHardware_t *timerHardwarePtr, uint8_t reference, timerCCCallbackPtr *callback) +void configureTimerCaptureCompareInterrupt(const timerHardware_t *timerHardwarePtr, uint8_t reference, timerCCCallbackPtr *edgeCallback, timerCCCallbackPtr *overflowCallback) { - configureTimerChannelCallback(timerHardwarePtr->tim, timerHardwarePtr->channel, reference, callback); + configureTimerChannelCallbacks(timerHardwarePtr->tim, timerHardwarePtr->channel, reference, edgeCallback, overflowCallback); configureTimerInputCaptureCompareChannel(timerHardwarePtr->tim, timerHardwarePtr->channel); + if (overflowCallback) { + TIM_ITConfig(timerHardwarePtr->tim, TIM_IT_Update, ENABLE); + } } void timerNVICConfigure(uint8_t irq) @@ -342,10 +352,26 @@ static void timCCxHandler(TIM_TypeDef *tim) { captureCompare_t capture; timerConfig_t *timerConfig; + uint8_t channel; + uint8_t channelIndex; + + if (TIM_GetITStatus(tim, TIM_IT_Update) == SET) { + TIM_ClearITPendingBit(tim, TIM_IT_Update); + capture = tim->ARR; + + for (channelIndex = 0; channelIndex < CC_CHANNELS_PER_TIMER; channelIndex++) { + channel = channels[channelIndex]; + timerConfig = findTimerConfig(tim, channel); + + if (!timerConfig->overflowCallback) { + continue; + } + timerConfig->overflowCallback(timerConfig->reference, capture); + } + } - uint8_t channelIndex = 0; for (channelIndex = 0; channelIndex < CC_CHANNELS_PER_TIMER; channelIndex++) { - uint8_t channel = channels[channelIndex]; + channel = channels[channelIndex]; if (channel == TIM_Channel_1 && TIM_GetITStatus(tim, TIM_IT_CC1) == SET) { TIM_ClearITPendingBit(tim, TIM_IT_CC1); @@ -371,10 +397,10 @@ static void timCCxHandler(TIM_TypeDef *tim) continue; // avoid uninitialised variable dereference } - if (!timerConfig->callback) { + if (!timerConfig->edgeCallback) { continue; } - timerConfig->callback(timerConfig->reference, capture); + timerConfig->edgeCallback(timerConfig->reference, capture); } } diff --git a/src/main/drivers/timer.h b/src/main/drivers/timer.h index 535b272f14..94331bacac 100644 --- a/src/main/drivers/timer.h +++ b/src/main/drivers/timer.h @@ -55,5 +55,6 @@ void timerConfigure(const timerHardware_t *timerHardwarePtr, uint16_t period, ui void timerNVICConfigure(uint8_t irq); void configureTimerInputCaptureCompareChannel(TIM_TypeDef *tim, const uint8_t channel); -void configureTimerCaptureCompareInterrupt(const timerHardware_t *timerHardwarePtr, uint8_t reference, timerCCCallbackPtr *callback); -void configureTimerChannelCallback(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *callback); +void configureTimerCaptureCompareInterrupt(const timerHardware_t *timerHardwarePtr, uint8_t reference, timerCCCallbackPtr *edgeCallback, timerCCCallbackPtr *overflowCallback); +void configureTimerChannelCallback(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *edgeCallback); +void configureTimerChannelCallbacks(TIM_TypeDef *tim, uint8_t channel, uint8_t reference, timerCCCallbackPtr *edgeCallback, timerCCCallbackPtr *overflowCallback);