1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 20:35:33 +03:00

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.
This commit is contained in:
Dominic Clifton 2014-07-22 21:29:00 +01:00
parent 440e942af4
commit a5ec1355d4
6 changed files with 69 additions and 34 deletions

View file

@ -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),

View file

@ -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)

View file

@ -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)

View file

@ -17,6 +17,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#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)

View file

@ -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);
}
}

View file

@ -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);