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 serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference) { uint32_t timerPeriod=34; TIM_DeInit(timerHardwarePtr->tim); timerConfigure(timerHardwarePtr, timerPeriod, 1); timerChCCHandlerInit(&escSerialPorts[reference].timerCb, onSerialTimer); timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].timerCb, NULL); }
static void serialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference) { // start bit is usually a FALLING signal TIM_DeInit(timerHardwarePtr->tim); timerConfigure(timerHardwarePtr, 0xFFFF, 1); serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Falling); timerChCCHandlerInit(&escSerialPorts[reference].edgeCb, onSerialRxPinChange); timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].edgeCb, NULL); }
static void serialTimerRxConfigBL(const timerHardware_t *timerHardwarePtr, uint8_t reference, portOptions_t options) { // start bit is usually a FALLING signal uint8_t mhz = SystemCoreClock / 2000000; TIM_DeInit(timerHardwarePtr->tim); timerConfigure(timerHardwarePtr, 0xFFFF, mhz); serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); timerChCCHandlerInit(&escSerialPorts[reference].edgeCb, onSerialRxPinChangeBL); timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].edgeCb, NULL); }
void ppmInConfig(const timerHardware_t *timerHardwarePtr) { ppmInit(); pwmInputPort_t *self = &pwmInputPorts[FIRST_PWM_PORT]; self->mode = INPUT_MODE_PPM; self->timerHardware = timerHardwarePtr; pwmGPIOConfig(timerHardwarePtr->gpio, timerHardwarePtr->pin, timerHardwarePtr->gpioInputMode); pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, (uint16_t)PPM_TIMER_PERIOD, PWM_TIMER_MHZ); timerChCCHandlerInit(&self->edgeCb, ppmEdgeCallback); timerChOvrHandlerInit(&self->overflowCb, ppmOverflowCallback); timerChConfigCallbacks(timerHardwarePtr, &self->edgeCb, &self->overflowCb); }
void pwmInConfig(const timerHardware_t *timerHardwarePtr, uint8_t channel) { pwmInputPort_t *self = &pwmInputPorts[channel]; self->state = 0; self->missedEvents = 0; self->channel = channel; self->mode = INPUT_MODE_PWM; self->timerHardware = timerHardwarePtr; pwmGPIOConfig(timerHardwarePtr->gpio, timerHardwarePtr->pin, timerHardwarePtr->gpioInputMode); pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, (uint16_t)PWM_TIMER_PERIOD, PWM_TIMER_MHZ); timerChCCHandlerInit(&self->edgeCb, pwmEdgeCallback); timerChOvrHandlerInit(&self->overflowCb, pwmOverflowCallback); timerChConfigCallbacks(timerHardwarePtr, &self->edgeCb, &self->overflowCb); }
void pwmRxInit(const pwmConfig_t *pwmConfig) { inputFilteringMode = pwmConfig->inputFilteringMode; for (int channel = 0; channel < PWM_INPUT_PORT_COUNT; channel++) { pwmInputPort_t *port = &pwmInputPorts[channel]; const timerHardware_t *timer = timerGetByTag(pwmConfig->ioTags[channel], TIM_USE_ANY); if (!timer) { /* TODO: maybe fail here if not enough channels? */ continue; } port->state = 0; port->missedEvents = 0; port->channel = channel; port->mode = INPUT_MODE_PWM; port->timerHardware = timer; IO_t io = IOGetByTag(pwmConfig->ioTags[channel]); IOInit(io, OWNER_PWMINPUT, RESOURCE_INDEX(channel)); #ifdef STM32F1 IOConfigGPIO(io, IOCFG_IPD); #else IOConfigGPIOAF(io, IOCFG_AF_PP, timer->alternateFunction); #endif timerConfigure(timer, (uint16_t)PWM_TIMER_PERIOD, PWM_TIMER_1MHZ); timerChCCHandlerInit(&port->edgeCb, pwmEdgeCallback); timerChOvrHandlerInit(&port->overflowCb, pwmOverflowCallback); timerChConfigCallbacks(timer, &port->edgeCb, &port->overflowCb); #if defined(USE_HAL_DRIVER) pwmICConfig(timer->tim, timer->channel, TIM_ICPOLARITY_RISING); #else pwmICConfig(timer->tim, timer->channel, TIM_ICPolarity_Rising); #endif } }
static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference, uint32_t baud) { uint32_t clock = SystemCoreClock; uint32_t timerPeriod; do { timerPeriod = clock / baud; if (isTimerPeriodTooLarge(timerPeriod)) { if (clock > 1) { clock = clock / 2; // this is wrong - mhz stays the same ... This will double baudrate until ok (but minimum baudrate is < 1200) } else { // TODO unable to continue, unable to determine clock and timerPeriods for the given baud } } } while (isTimerPeriodTooLarge(timerPeriod)); uint8_t mhz = SystemCoreClock / 1000000; timerConfigure(timerHardwarePtr, timerPeriod, mhz); timerChCCHandlerInit(&softSerialPorts[reference].timerCb, onSerialTimer); timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].timerCb, NULL); }
void ppmInConfig(const timerHardware_t *timerHardwarePtr) { ppmInit(); pwmInputPort_t *self = &pwmInputPorts[FIRST_PWM_PORT]; self->mode = INPUT_MODE_PPM; self->timerHardware = timerHardwarePtr; IO_t io = IOGetByTag(timerHardwarePtr->tag); IOInit(io, OWNER_PPMINPUT, RESOURCE_INPUT, 0); IOConfigGPIO(io, timerHardwarePtr->ioMode); pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, (uint16_t)PPM_TIMER_PERIOD, PWM_TIMER_MHZ); timerChCCHandlerInit(&self->edgeCb, ppmEdgeCallback); timerChOvrHandlerInit(&self->overflowCb, ppmOverflowCallback); timerChConfigCallbacks(timerHardwarePtr, &self->edgeCb, &self->overflowCb); }
void pwmInConfig(const timerHardware_t *timerHardwarePtr, uint8_t channel) { pwmInputPort_t *self = &pwmInputPorts[channel]; self->state = 0; self->missedEvents = 0; self->channel = channel; self->mode = INPUT_MODE_PWM; self->timerHardware = timerHardwarePtr; IO_t io = IOGetByTag(timerHardwarePtr->tag); IOInit(io, OWNER_PWMINPUT, RESOURCE_INPUT, RESOURCE_INDEX(channel)); IOConfigGPIO(io, timerHardwarePtr->ioMode); pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); timerConfigure(timerHardwarePtr, (uint16_t)PWM_TIMER_PERIOD, PWM_TIMER_MHZ); timerChCCHandlerInit(&self->edgeCb, pwmEdgeCallback); timerChOvrHandlerInit(&self->overflowCb, pwmOverflowCallback); timerChConfigCallbacks(timerHardwarePtr, &self->edgeCb, &self->overflowCb); }
void ppmRxInit(const ppmConfig_t *ppmConfig) { ppmResetDevice(); pwmInputPort_t *port = &pwmInputPorts[FIRST_PWM_PORT]; const timerHardware_t *timer = timerGetByTag(ppmConfig->ioTag, TIM_USE_ANY); if (!timer) { /* TODO: fail here? */ return; } ppmAvoidPWMTimerClash(timer->tim); port->mode = INPUT_MODE_PPM; port->timerHardware = timer; IO_t io = IOGetByTag(ppmConfig->ioTag); IOInit(io, OWNER_PPMINPUT, 0); #ifdef STM32F1 IOConfigGPIO(io, IOCFG_IPD); #else IOConfigGPIOAF(io, IOCFG_AF_PP, timer->alternateFunction); #endif timerConfigure(timer, (uint16_t)PPM_TIMER_PERIOD, PWM_TIMER_1MHZ); timerChCCHandlerInit(&port->edgeCb, ppmEdgeCallback); timerChOvrHandlerInit(&port->overflowCb, ppmOverflowCallback); timerChConfigCallbacks(timer, &port->edgeCb, &port->overflowCb); #if defined(USE_HAL_DRIVER) pwmICConfig(timer->tim, timer->channel, TIM_ICPOLARITY_RISING); #else pwmICConfig(timer->tim, timer->channel, TIM_ICPolarity_Rising); #endif }
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr rxCallback, uint32_t baud, portMode_t mode, portOptions_t options) { softSerial_t *softSerial = &(softSerialPorts[portIndex]); int pinCfgIndex = portIndex + RESOURCE_SOFT_OFFSET; ioTag_t tagRx = serialPinConfig()->ioTagRx[pinCfgIndex]; ioTag_t tagTx = serialPinConfig()->ioTagTx[pinCfgIndex]; 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; if (!(mode & MODE_RX)) { // TX Simplex, must have a timer if (!timerTx) return NULL; softSerial->timerHardware = timerTx; } else { // Duplex softSerial->exTimerHardware = timerTx; } IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(portIndex) + RESOURCE_SOFT_OFFSET); } } softSerial->port.vTable = &softSerialVTable; softSerial->port.baudRate = baud; softSerial->port.mode = mode; softSerial->port.options = options; softSerial->port.rxCallback = rxCallback; resetBuffers(softSerial); softSerial->softSerialPortIndex = portIndex; softSerial->transmissionErrors = 0; softSerial->receiveErrors = 0; softSerial->rxActive = false; softSerial->isTransmittingData = false; // Configure master timer (on RX); time base and input capture serialTimerConfigureTimebase(softSerial->timerHardware, baud); timerChConfigIC(softSerial->timerHardware, (options & SERIAL_INVERTED) ? ICPOLARITY_RISING : ICPOLARITY_FALLING, 0); // Initialize callbacks timerChCCHandlerInit(&softSerial->edgeCb, onSerialRxPinChange); timerChOvrHandlerInit(&softSerial->overCb, onSerialTimerOverflow); // 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); } #ifdef USE_HAL_DRIVER softSerial->timerHandle = timerFindTimerHandle(softSerial->timerHardware->tim); #endif if (!(options & SERIAL_BIDIR)) { serialOutputPortActivate(softSerial); setTxSignal(softSerial, ENABLE); } serialInputPortActivate(softSerial); return &softSerial->port; }