diff --git a/src/main/config/config_master.h b/src/main/config/config_master.h index e7ae046c1e..fffa42e358 100644 --- a/src/main/config/config_master.h +++ b/src/main/config/config_master.h @@ -34,6 +34,7 @@ #include "drivers/light_led.h" #include "drivers/flash.h" #include "drivers/display.h" +#include "drivers/serial.h" #include "fc/rc_controls.h" @@ -86,6 +87,7 @@ #define mixerConfig(x) (&masterConfig.mixerConfig) #define airplaneConfig(x) (&masterConfig.airplaneConfig) #define failsafeConfig(x) (&masterConfig.failsafeConfig) +#define serialPinConfig(x) (&masterConfig.serialPinConfig) #define serialConfig(x) (&masterConfig.serialConfig) #define telemetryConfig(x) (&masterConfig.telemetryConfig) #define ibusTelemetryConfig(x) (&masterConfig.telemetryConfig) @@ -173,6 +175,7 @@ typedef struct master_s { airplaneConfig_t airplaneConfig; failsafeConfig_t failsafeConfig; + serialPinConfig_t serialPinConfig; serialConfig_t serialConfig; telemetryConfig_t telemetryConfig; diff --git a/src/main/drivers/serial.h b/src/main/drivers/serial.h index bfad7e2aad..6b72040627 100644 --- a/src/main/drivers/serial.h +++ b/src/main/drivers/serial.h @@ -17,6 +17,8 @@ #pragma once +#include "drivers/io.h" + typedef enum portMode_t { MODE_RX = 1 << 0, MODE_TX = 1 << 1, @@ -68,6 +70,21 @@ typedef struct serialPort_s { serialReceiveCallbackPtr rxCallback; } serialPort_t; +#if defined(USE_SOFTSERIAL1) || defined(USE_SOFTSERIAL2) +# ifdef USE_SOFTSERIAL2 +# define SERIAL_PORT_MAX_INDEX (RESOURCE_SOFT_OFFSET + 2) +# else +# define SERIAL_PORT_MAX_INDEX (RESOURCE_SOFT_OFFSET + 1) +# endif +#else +# define SERIAL_PORT_MAX_INDEX RESOURCE_SOFT_OFFSET +#endif + +typedef struct serialPinConfig_s { + ioTag_t ioTagTx[SERIAL_PORT_MAX_INDEX]; + ioTag_t ioTagRx[SERIAL_PORT_MAX_INDEX]; +} serialPinConfig_t; + struct serialPortVTable { void (*serialWrite)(serialPort_t *instance, uint8_t ch); diff --git a/src/main/drivers/serial_softserial.c b/src/main/drivers/serial_softserial.c index 0b599e09c6..55b30dcbde 100644 --- a/src/main/drivers/serial_softserial.c +++ b/src/main/drivers/serial_softserial.c @@ -25,8 +25,12 @@ #include "build/build_config.h" #include "build/atomic.h" +#include "build/debug.h" + #include "common/utils.h" +#include "config/config_master.h" + #include "nvic.h" #include "system.h" #include "io.h" @@ -44,21 +48,29 @@ #define MAX_SOFTSERIAL_PORTS 1 #endif +typedef enum { + TIMER_MODE_SINGLE, + TIMER_MODE_DUAL, +} timerMode_e; + typedef struct softSerial_s { serialPort_t port; IO_t rxIO; IO_t txIO; - const timerHardware_t *rxTimerHardware; - volatile uint8_t rxBuffer[SOFTSERIAL_BUFFER_SIZE]; - const timerHardware_t *txTimerHardware; + const timerHardware_t *timerHardware; + const timerHardware_t *exTimerHardware; + uint32_t ccEnableBit; + + volatile uint8_t rxBuffer[SOFTSERIAL_BUFFER_SIZE]; volatile uint8_t txBuffer[SOFTSERIAL_BUFFER_SIZE]; uint8_t isSearchingForStartBit; uint8_t rxBitIndex; uint8_t rxLastLeadingEdgeAtBitIndex; uint8_t rxEdge; + uint8_t rxActive; uint8_t isTransmittingData; int8_t bitsLeftToTransmit; @@ -70,23 +82,20 @@ typedef struct softSerial_s { uint16_t receiveErrors; uint8_t softSerialPortIndex; + timerMode_e timerMode; - timerCCHandlerRec_t timerCb; + timerOvrHandlerRec_t overCb; timerCCHandlerRec_t edgeCb; } softSerial_t; -extern timerHardware_t* serialTimerHardware; -extern softSerial_t softSerialPorts[]; +static const struct serialPortVTable softSerialVTable; // Forward -extern const struct serialPortVTable softSerialVTable[]; +static softSerial_t softSerialPorts[MAX_SOFTSERIAL_PORTS]; - -softSerial_t softSerialPorts[MAX_SOFTSERIAL_PORTS]; - -void onSerialTimer(timerCCHandlerRec_t *cbRec, captureCompare_t capture); +void onSerialTimerOverflow(timerOvrHandlerRec_t *cbRec, captureCompare_t capture); void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture); -void setTxSignal(softSerial_t *softSerial, uint8_t state) +static void setTxSignal(softSerial_t *softSerial, uint8_t state) { if (softSerial->port.options & SERIAL_INVERTED) { state = !state; @@ -99,20 +108,83 @@ void setTxSignal(softSerial_t *softSerial, uint8_t state) } } -void serialInputPortConfig(ioTag_t pin, uint8_t portIndex) +// XXX CCEnableBit: Compute CCxE bit. +// XXX (Note: timer.c:timerChICPolarity() uses "TIM_CCER_CC1P << timHw->channel".) + +static uint32_t CCEnableBit(int channel) { - IOInit(IOGetByTag(pin), OWNER_SERIAL_RX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET); -#ifdef STM32F1 - IOConfigGPIO(IOGetByTag(pin), IOCFG_IPU); + uint32_t bit; + +#if defined(STM32F7) + switch (channel) { + case TIM_CHANNEL_1: + bit = TIM_CCER_CC1E; + break; + case TIM_CHANNEL_2: + bit = TIM_CCER_CC2E; + break; + case TIM_CHANNEL_3: + bit = TIM_CCER_CC3E; + break; + case TIM_CHANNEL_4: + bit = TIM_CCER_CC4E; + break; + } #else - IOConfigGPIO(IOGetByTag(pin), IOCFG_AF_PP_UP); + switch (channel) { + case TIM_Channel_1: + bit = TIM_CCER_CC1E; + break; + case TIM_Channel_2: + bit = TIM_CCER_CC2E; + break; + case TIM_Channel_3: + bit = TIM_CCER_CC3E; + break; + case TIM_Channel_4: + bit = TIM_CCER_CC4E; + break; + } #endif + + return bit; } -static void serialOutputPortConfig(ioTag_t pin, uint8_t portIndex) +static void serialInputPortActivate(softSerial_t *softSerial) { - IOInit(IOGetByTag(pin), OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET); - IOConfigGPIO(IOGetByTag(pin), IOCFG_OUT_PP); + softSerial->rxActive = true; +#ifdef STM32F1 + IOConfigGPIO(softSerial->rxIO, IOCFG_IPU); +#else + IOConfigGPIO(softSerial->rxIO, IOCFG_AF_PP_UP); +#endif + + softSerial->isSearchingForStartBit = true; + softSerial->rxBitIndex = 0; + + // Enable input capture + + softSerial->timerHardware->tim->CCER |= softSerial->ccEnableBit; +} + +static void serialInputPortDeActivate(softSerial_t *softSerial) +{ + // Disable input capture + + softSerial->timerHardware->tim->CCER &= ~softSerial->ccEnableBit; + + IOConfigGPIO(softSerial->rxIO, IOCFG_IN_FLOATING); + softSerial->rxActive = false; +} + +static void serialOutputPortActivate(softSerial_t *softSerial) +{ + IOConfigGPIO(softSerial->txIO, IOCFG_OUT_PP); +} + +static void serialOutputPortDeActivate(softSerial_t *softSerial) +{ + IOConfigGPIO(softSerial->txIO, IOCFG_IN_FLOATING); } static bool isTimerPeriodTooLarge(uint32_t timerPeriod) @@ -120,10 +192,12 @@ static bool isTimerPeriodTooLarge(uint32_t timerPeriod) return timerPeriod > 0xFFFF; } -static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference, uint32_t baud) +static void serialTimerConfigureTimebase(const timerHardware_t *timerHardwarePtr, uint32_t baud) { - uint32_t clock = SystemCoreClock; + uint32_t baseClock = SystemCoreClock / timerClockDivisor(timerHardwarePtr->tim); + uint32_t clock = baseClock; uint32_t timerPeriod; + do { timerPeriod = clock / baud; if (isTimerPeriodTooLarge(timerPeriod)) { @@ -136,10 +210,9 @@ static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t } } while (isTimerPeriodTooLarge(timerPeriod)); - uint8_t mhz = SystemCoreClock / 1000000; + uint8_t mhz = baseClock / 1000000; + timerConfigure(timerHardwarePtr, timerPeriod, mhz); - timerChCCHandlerInit(&softSerialPorts[reference].timerCb, onSerialTimer); - timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].timerCb, NULL); } static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity) @@ -156,14 +229,6 @@ static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity) TIM_ICInit(tim, &TIM_ICInitStructure); } -static void serialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference, portOptions_t options) -{ - // start bit is usually a FALLING signal - serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); - timerChCCHandlerInit(&softSerialPorts[reference].edgeCb, onSerialRxPinChange); - timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].edgeCb, NULL); -} - static void resetBuffers(softSerial_t *softSerial) { softSerial->port.rxBufferSize = SOFTSERIAL_BUFFER_SIZE; @@ -177,71 +242,131 @@ static void resetBuffers(softSerial_t *softSerial) softSerial->port.txBufferHead = 0; } -serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portOptions_t options) +serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portMode_t mode, portOptions_t options) { softSerial_t *softSerial = &(softSerialPorts[portIndex]); -#ifdef USE_SOFTSERIAL1 - if (portIndex == SOFTSERIAL1) { - softSerial->rxTimerHardware = &(timerHardware[SOFTSERIAL_1_TIMER_RX_HARDWARE]); - softSerial->txTimerHardware = &(timerHardware[SOFTSERIAL_1_TIMER_TX_HARDWARE]); - } -#endif + int pinCfgIndex = portIndex + RESOURCE_SOFT_OFFSET; -#ifdef USE_SOFTSERIAL2 - if (portIndex == SOFTSERIAL2) { - softSerial->rxTimerHardware = &(timerHardware[SOFTSERIAL_2_TIMER_RX_HARDWARE]); - softSerial->txTimerHardware = &(timerHardware[SOFTSERIAL_2_TIMER_TX_HARDWARE]); - } -#endif + ioTag_t tagRx = serialPinConfig()->ioTagRx[pinCfgIndex]; + ioTag_t tagTx = serialPinConfig()->ioTagTx[pinCfgIndex]; - softSerial->port.vTable = softSerialVTable; + const timerHardware_t *timerRx = timerGetByTag(tagRx, TIM_USE_ANY); + const timerHardware_t *timerTx = timerGetByTag(tagTx, TIM_USE_ANY); + + IO_t rxIO = IOGetByTag(tagRx); + IO_t txIO = IOGetByTag(tagTx); + + if (options & SERIAL_BIDIR) { + // If RX and TX pins are both assigned, we CAN use either with a timer. + // However, for consistency with hardware UARTs, we only use TX pin, + // and this pin must have a timer. + if (!timerTx) + return NULL; + + softSerial->timerHardware = timerTx; + softSerial->txIO = txIO; + softSerial->rxIO = txIO; + IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET); + } else { + if (mode & MODE_RX) { + // Need a pin & a timer on RX + if (!(tagRx && timerRx)) + return NULL; + + softSerial->rxIO = rxIO; + softSerial->timerHardware = timerRx; + IOInit(rxIO, OWNER_SERIAL_RX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET); + } + + if (mode & MODE_TX) { + // Need a pin on TX + if (!tagTx) + return NULL; + + softSerial->txIO = txIO; + softSerial->exTimerHardware = timerTx; + IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET); + } + } + + softSerial->ccEnableBit = CCEnableBit(softSerial->timerHardware->channel); + + //debug[2] = softSerial->ccEnableBit; + + softSerial->port.vTable = &softSerialVTable; softSerial->port.baudRate = baud; - softSerial->port.mode = MODE_RXTX; + softSerial->port.mode = mode; softSerial->port.options = options; softSerial->port.rxCallback = rxCallback; resetBuffers(softSerial); - softSerial->isTransmittingData = false; - - softSerial->isSearchingForStartBit = true; - softSerial->rxBitIndex = 0; + softSerial->softSerialPortIndex = portIndex; softSerial->transmissionErrors = 0; softSerial->receiveErrors = 0; - softSerial->softSerialPortIndex = portIndex; + softSerial->rxActive = false; + softSerial->isTransmittingData = false; - softSerial->txIO = IOGetByTag(softSerial->txTimerHardware->tag); - serialOutputPortConfig(softSerial->txTimerHardware->tag, portIndex); + // Configure master timer (on RX); time base and input capture - softSerial->rxIO = IOGetByTag(softSerial->rxTimerHardware->tag); - serialInputPortConfig(softSerial->rxTimerHardware->tag, portIndex); + serialTimerConfigureTimebase(softSerial->timerHardware, baud); + serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); - setTxSignal(softSerial, ENABLE); - delay(50); + // Initialize callbacks + timerChCCHandlerInit(&softSerial->edgeCb, onSerialRxPinChange); + timerChOvrHandlerInit(&softSerial->overCb, onSerialTimerOverflow); - serialTimerTxConfig(softSerial->txTimerHardware, portIndex, baud); - serialTimerRxConfig(softSerial->rxTimerHardware, portIndex, options); + // Configure bit clock interrupt & handler. + // If we have an extra timer (on TX), it is initialized and configured + // for overflow interrupt. + // Receiver input capture is configured when input is activated. + + if ((mode & MODE_TX) && softSerial->exTimerHardware && softSerial->exTimerHardware->tim != softSerial->timerHardware->tim) { + softSerial->timerMode = TIMER_MODE_DUAL; + serialTimerConfigureTimebase(softSerial->exTimerHardware, baud); + timerChConfigCallbacks(softSerial->exTimerHardware, NULL, &softSerial->overCb); + timerChConfigCallbacks(softSerial->timerHardware, &softSerial->edgeCb, NULL); + } else { + softSerial->timerMode = TIMER_MODE_SINGLE; + timerChConfigCallbacks(softSerial->timerHardware, &softSerial->edgeCb, &softSerial->overCb); + } + + if (!(options & SERIAL_BIDIR)) { + serialOutputPortActivate(softSerial); + setTxSignal(softSerial, ENABLE); + } + + serialInputPortActivate(softSerial); return &softSerial->port; } /*********************************************/ +// +// Serial engines +// + void processTxState(softSerial_t *softSerial) { uint8_t mask; if (!softSerial->isTransmittingData) { - char byteToSend; if (isSoftSerialTransmitBufferEmpty((serialPort_t *)softSerial)) { + // Transmit buffer empty. + // Start listening if not already in if half-duplex + if (!softSerial->rxActive && softSerial->port.options & SERIAL_BIDIR) { + serialOutputPortDeActivate(softSerial); + serialInputPortActivate(softSerial); + } return; } // data to send - byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++]; + char byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++]; if (softSerial->port.txBufferTail >= softSerial->port.txBufferSize) { softSerial->port.txBufferTail = 0; } @@ -251,6 +376,12 @@ void processTxState(softSerial_t *softSerial) softSerial->bitsLeftToTransmit = TX_TOTAL_BITS; softSerial->isTransmittingData = true; + if (softSerial->rxActive && (softSerial->port.options & SERIAL_BIDIR)) { + // Half-duplex: Deactivate receiver, activate transmitter + serialInputPortDeActivate(softSerial); + serialOutputPortActivate(softSerial); + } + return; } @@ -288,9 +419,7 @@ void prepareForNextRxByte(softSerial_t *softSerial) softSerial->isSearchingForStartBit = true; if (softSerial->rxEdge == LEADING) { softSerial->rxEdge = TRAILING; - serialICConfig( - softSerial->rxTimerHardware->tim, - softSerial->rxTimerHardware->channel, + serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, (softSerial->port.options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling ); } @@ -347,18 +476,24 @@ void processRxState(softSerial_t *softSerial) } } -void onSerialTimer(timerCCHandlerRec_t *cbRec, captureCompare_t capture) +void onSerialTimerOverflow(timerOvrHandlerRec_t *cbRec, captureCompare_t capture) { UNUSED(capture); - softSerial_t *softSerial = container_of(cbRec, softSerial_t, timerCb); + //debug[0]++; - processTxState(softSerial); - processRxState(softSerial); + softSerial_t *softSerial = container_of(cbRec, softSerial_t, overCb); + + if (softSerial->port.mode & MODE_TX) + processTxState(softSerial); + + if (softSerial->port.mode & MODE_RX) + processRxState(softSerial); } void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture) { UNUSED(capture); + //debug[1]++; softSerial_t *softSerial = container_of(cbRec, softSerial_t, edgeCb); bool inverted = softSerial->port.options & SERIAL_INVERTED; @@ -371,12 +506,12 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture) // synchronise bit counter // FIXME this reduces functionality somewhat as receiving breaks concurrent transmission on all ports because // the next callback to the onSerialTimer will happen too early causing transmission errors. - TIM_SetCounter(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->tim->ARR / 2); - if (softSerial->isTransmittingData) { + TIM_SetCounter(softSerial->timerHardware->tim, softSerial->timerHardware->tim->ARR / 2); + if ((softSerial->timerMode != TIMER_MODE_DUAL) && softSerial->isTransmittingData) { softSerial->transmissionErrors++; } - serialICConfig(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising); + serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising); softSerial->rxEdge = LEADING; softSerial->rxBitIndex = 0; @@ -394,13 +529,17 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture) if (softSerial->rxEdge == TRAILING) { softSerial->rxEdge = LEADING; - serialICConfig(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising); + serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising); } else { softSerial->rxEdge = TRAILING; - serialICConfig(softSerial->rxTimerHardware->tim, softSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); + serialICConfig(softSerial->timerHardware->tim, softSerial->timerHardware->channel, inverted ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); } } +// +// Standard serial driver API +// + uint32_t softSerialRxBytesWaiting(const serialPort_t *instance) { if ((instance->mode & MODE_RX) == 0) { @@ -455,7 +594,10 @@ void softSerialWriteByte(serialPort_t *s, uint8_t ch) void softSerialSetBaudRate(serialPort_t *s, uint32_t baudRate) { softSerial_t *softSerial = (softSerial_t *)s; - openSoftSerial(softSerial->softSerialPortIndex, s->rxCallback, baudRate, softSerial->port.options); + + softSerial->port.baudRate = baudRate; + + serialTimerConfigureTimebase(softSerial->timerHardware, baudRate); } void softSerialSetMode(serialPort_t *instance, portMode_t mode) @@ -468,19 +610,17 @@ bool isSoftSerialTransmitBufferEmpty(const serialPort_t *instance) return instance->txBufferHead == instance->txBufferTail; } -const struct serialPortVTable softSerialVTable[] = { - { - .serialWrite = softSerialWriteByte, - .serialTotalRxWaiting = softSerialRxBytesWaiting, - .serialTotalTxFree = softSerialTxBytesFree, - .serialRead = softSerialReadByte, - .serialSetBaudRate = softSerialSetBaudRate, - .isSerialTransmitBufferEmpty = isSoftSerialTransmitBufferEmpty, - .setMode = softSerialSetMode, - .writeBuf = NULL, - .beginWrite = NULL, - .endWrite = NULL - } +static const struct serialPortVTable softSerialVTable = { + .serialWrite = softSerialWriteByte, + .serialTotalRxWaiting = softSerialRxBytesWaiting, + .serialTotalTxFree = softSerialTxBytesFree, + .serialRead = softSerialReadByte, + .serialSetBaudRate = softSerialSetBaudRate, + .isSerialTransmitBufferEmpty = isSoftSerialTransmitBufferEmpty, + .setMode = softSerialSetMode, + .writeBuf = NULL, + .beginWrite = NULL, + .endWrite = NULL }; #endif diff --git a/src/main/drivers/serial_softserial.h b/src/main/drivers/serial_softserial.h index 42c8bcbf09..032368b2b5 100644 --- a/src/main/drivers/serial_softserial.h +++ b/src/main/drivers/serial_softserial.h @@ -24,7 +24,7 @@ typedef enum { SOFTSERIAL2 } softSerialPortIndex_e; -serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portOptions_t options); +serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portMode_t mode, portOptions_t options); // serialPort API void softSerialWriteByte(serialPort_t *instance, uint8_t ch); diff --git a/src/main/fc/cli.c b/src/main/fc/cli.c index 0f952bb64b..da3753fa28 100755 --- a/src/main/fc/cli.c +++ b/src/main/fc/cli.c @@ -3342,6 +3342,8 @@ const cliResourceValue_t resourceTable[] = { #ifdef LED_STRIP { OWNER_LED_STRIP, &ledStripConfig()->ioTag, 0 }, #endif + { OWNER_SERIAL_TX, &serialPinConfig()->ioTagTx[0], SERIAL_PORT_MAX_INDEX }, + { OWNER_SERIAL_RX, &serialPinConfig()->ioTagRx[0], SERIAL_PORT_MAX_INDEX }, }; static void printResource(uint8_t dumpMask, const master_t *defaultConfig) diff --git a/src/main/fc/config.c b/src/main/fc/config.c index d9b6245c8c..1be550c2fe 100755 --- a/src/main/fc/config.c +++ b/src/main/fc/config.c @@ -428,6 +428,175 @@ void resetBatteryConfig(batteryConfig_t *batteryConfig) batteryConfig->consumptionWarningPercentage = 10; } +// Default pin (NONE). +// XXX Does this mess belong here??? +#ifdef USE_UART1 +# if !defined(UART1_RX_PIN) +# define UART1_RX_PIN NONE +# endif +# if !defined(UART1_TX_PIN) +# define UART1_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART2 +# if !defined(UART2_RX_PIN) +# define UART2_RX_PIN NONE +# endif +# if !defined(UART2_TX_PIN) +# define UART2_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART3 +# if !defined(UART3_RX_PIN) +# define UART3_RX_PIN NONE +# endif +# if !defined(UART3_TX_PIN) +# define UART3_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART4 +# if !defined(UART4_RX_PIN) +# define UART4_RX_PIN NONE +# endif +# if !defined(UART4_TX_PIN) +# define UART4_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART5 +# if !defined(UART5_RX_PIN) +# define UART5_RX_PIN NONE +# endif +# if !defined(UART5_TX_PIN) +# define UART5_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART6 +# if !defined(UART6_RX_PIN) +# define UART6_RX_PIN NONE +# endif +# if !defined(UART6_TX_PIN) +# define UART6_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART7 +# if !defined(UART7_RX_PIN) +# define UART7_RX_PIN NONE +# endif +# if !defined(UART7_TX_PIN) +# define UART7_TX_PIN NONE +# endif +#endif + +#ifdef USE_UART8 +# if !defined(UART8_RX_PIN) +# define UART8_RX_PIN NONE +# endif +# if !defined(UART8_TX_PIN) +# define UART8_TX_PIN NONE +# endif +#endif + +#ifdef USE_SOFTSERIAL1 +# if !defined(SOFTSERIAL1_RX_PIN) +# define SOFTSERIAL1_RX_PIN NONE +# endif +# if !defined(SOFTSERIAL1_TX_PIN) +# define SOFTSERIAL1_TX_PIN NONE +# endif +#endif + +#ifdef USE_SOFTSERIAL2 +# if !defined(SOFTSERIAL2_RX_PIN) +# define SOFTSERIAL2_RX_PIN NONE +# endif +# if !defined(SOFTSERIAL2_TX_PIN) +# define SOFTSERIAL2_TX_PIN NONE +# endif +#endif + +void resetSerialPinConfig(serialPinConfig_t *pSerialPinConfig) +{ + for (int port = 0 ; port < SERIAL_PORT_MAX_INDEX ; port++) { + pSerialPinConfig->ioTagRx[port] = IO_TAG(NONE); + pSerialPinConfig->ioTagTx[port] = IO_TAG(NONE); + } + + for (int index = 0 ; index < SERIAL_PORT_COUNT ; index++) { + switch (serialPortIdentifiers[index]) { + case SERIAL_PORT_USART1: +#ifdef USE_UART1 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART1)] = IO_TAG(UART1_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART1)] = IO_TAG(UART1_TX_PIN); +#endif + break; + case SERIAL_PORT_USART2: +#ifdef USE_UART2 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART2)] = IO_TAG(UART2_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART2)] = IO_TAG(UART2_TX_PIN); +#endif + break; + case SERIAL_PORT_USART3: +#ifdef USE_UART3 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART3)] = IO_TAG(UART3_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART3)] = IO_TAG(UART3_TX_PIN); +#endif + break; + case SERIAL_PORT_USART4: +#ifdef USE_UART4 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART4)] = IO_TAG(UART4_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART4)] = IO_TAG(UART4_TX_PIN); +#endif + break; + case SERIAL_PORT_USART5: +#ifdef USE_UART5 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART5)] = IO_TAG(UART5_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART5)] = IO_TAG(UART5_TX_PIN); +#endif + break; + case SERIAL_PORT_USART6: +#ifdef USE_UART6 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART6)] = IO_TAG(UART6_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART6)] = IO_TAG(UART6_TX_PIN); +#endif + break; + case SERIAL_PORT_USART7: +#ifdef USE_UART7 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART7)] = IO_TAG(UART7_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART7)] = IO_TAG(UART7_TX_PIN); +#endif + break; + case SERIAL_PORT_USART8: +#ifdef USE_UART8 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART8)] = IO_TAG(UART8_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_USART8)] = IO_TAG(UART8_TX_PIN); +#endif + break; + case SERIAL_PORT_SOFTSERIAL1: +#ifdef USE_SOFTSERIAL1 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL1)] = IO_TAG(SOFTSERIAL1_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL1)] = IO_TAG(SOFTSERIAL1_TX_PIN); +#endif + break; + case SERIAL_PORT_SOFTSERIAL2: +#ifdef USE_SOFTSERIAL2 + pSerialPinConfig->ioTagRx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL2)] = IO_TAG(SOFTSERIAL2_RX_PIN); + pSerialPinConfig->ioTagTx[SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(SERIAL_PORT_SOFTSERIAL2)] = IO_TAG(SOFTSERIAL2_TX_PIN); +#endif + break; + case SERIAL_PORT_USB_VCP: + break; + case SERIAL_PORT_NONE: + break; + } + } +} + #ifdef SWAP_SERIAL_PORT_0_AND_1_DEFAULTS #define FIRST_PORT_INDEX 1 #define SECOND_PORT_INDEX 0 @@ -747,6 +916,8 @@ void createDefaultConfig(master_t *config) config->gpsConfig.autoBaud = GPS_AUTOBAUD_OFF; #endif + resetSerialPinConfig(&config->serialPinConfig); + resetSerialConfig(&config->serialConfig); resetProfile(&config->profile[0]); diff --git a/src/main/io/serial.c b/src/main/io/serial.c index 6c96238aae..1d3982154f 100644 --- a/src/main/io/serial.c +++ b/src/main/io/serial.c @@ -352,14 +352,12 @@ serialPort_t *openSerialPort( #endif #ifdef USE_SOFTSERIAL1 case SERIAL_PORT_SOFTSERIAL1: - serialPort = openSoftSerial(SOFTSERIAL1, rxCallback, baudRate, options); - serialSetMode(serialPort, mode); + serialPort = openSoftSerial(SOFTSERIAL1, rxCallback, baudRate, mode, options); break; #endif #ifdef USE_SOFTSERIAL2 case SERIAL_PORT_SOFTSERIAL2: - serialPort = openSoftSerial(SOFTSERIAL2, rxCallback, baudRate, options); - serialSetMode(serialPort, mode); + serialPort = openSoftSerial(SOFTSERIAL2, rxCallback, baudRate, mode, options); break; #endif default: diff --git a/src/main/io/serial.h b/src/main/io/serial.h index 5a68a18041..3522e2d37c 100644 --- a/src/main/io/serial.h +++ b/src/main/io/serial.h @@ -81,6 +81,8 @@ typedef enum { extern const serialPortIdentifier_e serialPortIdentifiers[SERIAL_PORT_COUNT]; +#define SERIAL_PORT_IDENTIFIER_TO_RESOURCE_INDEX(x) (((x) <= SERIAL_PORT_USART8) ? (x) : (RESOURCE_SOFT_OFFSET + ((x) - SERIAL_PORT_SOFTSERIAL1))) + // // runtime // diff --git a/src/main/target/OMNIBUS/target.h b/src/main/target/OMNIBUS/target.h index bde8cd793c..bc56b8c318 100644 --- a/src/main/target/OMNIBUS/target.h +++ b/src/main/target/OMNIBUS/target.h @@ -68,7 +68,8 @@ #define USE_UART1 #define USE_UART2 #define USE_UART3 -#define SERIAL_PORT_COUNT 4 +#define USE_SOFTSERIAL1 +#define SERIAL_PORT_COUNT 5 #define UART1_TX_PIN PA9 #define UART1_RX_PIN PA10 @@ -79,8 +80,9 @@ #define UART3_TX_PIN PB10 // PB10 (AF7) #define UART3_RX_PIN PB11 // PB11 (AF7) -#define USE_I2C -#define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA +#undef USE_I2C +//#define USE_I2C +//#define I2C_DEVICE (I2CDEV_1) // PB6/SCL, PB7/SDA #define USE_ESCSERIAL #define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1 diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index 6d4289da5a..3d6e36c268 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -125,11 +125,23 @@ #define UART6_RX_PIN PC7 #define UART6_TX_PIN PC6 +#define USE_SOFTSERIAL1 +//#define SOFTSERIAL1_RX_PIN PC8 // S5_IN (TIM8 CH3) +//#define SOFTSERIAL1_TX_PIN PC9 // S6_IN (TIM8 CH4) + +#define USE_SOFTSERIAL2 +// Special case of using different timers for RX and TX +//#define SOFTSERIAL2_RX_PIN PA1 // PWM5, LED_STRIP +//#define SOFTSERIAL2_TX_PIN PA8 // PWM6 +// Experimental (untested) +//#define SOFTSERIAL2_RX_PIN PA8 // PWM6 +//#define SOFTSERIAL2_TX_PIN PB15 // S2_IN + +#define SERIAL_PORT_COUNT 6 //VCP, USART1, USART3, USART6, SOFTSERIALx2 + #define USE_ESCSERIAL #define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1 -#define SERIAL_PORT_COUNT 4 //VCP, USART1, USART3, USART6 - #define USE_SPI #define USE_SPI_DEVICE_1 diff --git a/src/main/target/REVO/target.h b/src/main/target/REVO/target.h index a93fdc3813..a257860c9b 100644 --- a/src/main/target/REVO/target.h +++ b/src/main/target/REVO/target.h @@ -157,7 +157,10 @@ #define UART6_RX_PIN PC7 #define UART6_TX_PIN PC6 -#define SERIAL_PORT_COUNT 4 //VCP, USART1, USART3, USART6 +#define USE_SOFTSERIAL1 +#define USE_SOFTSERIAL2 + +#define SERIAL_PORT_COUNT 6 //VCP, USART1, USART3, USART6, SOFTSERIALx2 #define USE_ESCSERIAL #define ESCSERIAL_TIMER_TX_HARDWARE 0 // PWM 1