void processTxState(softSerial_t *softSerial) { uint8_t mask; if (!softSerial->isTransmittingData) { char byteToSend; if (isSoftSerialTransmitBufferEmpty((serialPort_t *)softSerial)) { return; } // data to send byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++]; if (softSerial->port.txBufferTail >= softSerial->port.txBufferSize) { softSerial->port.txBufferTail = 0; } // build internal buffer, MSB = Stop Bit (1) + data bits (MSB to LSB) + start bit(0) LSB softSerial->internalTxBuffer = (1 << (TX_TOTAL_BITS - 1)) | (byteToSend << 1); softSerial->bitsLeftToTransmit = TX_TOTAL_BITS; softSerial->isTransmittingData = true; return; } if (softSerial->bitsLeftToTransmit) { mask = softSerial->internalTxBuffer & 1; softSerial->internalTxBuffer >>= 1; setTxSignal(softSerial, mask); softSerial->bitsLeftToTransmit--; return; }
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr callback, uint32_t baud, 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 #ifdef USE_SOFTSERIAL2 if (portIndex == SOFTSERIAL2) { softSerial->rxTimerHardware = &(timerHardware[SOFTSERIAL_2_TIMER_RX_HARDWARE]); softSerial->txTimerHardware = &(timerHardware[SOFTSERIAL_2_TIMER_TX_HARDWARE]); } #endif softSerial->port.vTable = softSerialVTable; softSerial->port.baudRate = baud; softSerial->port.mode = MODE_RXTX; softSerial->port.options = options; softSerial->port.callback = callback; resetBuffers(softSerial); softSerial->isTransmittingData = false; softSerial->isSearchingForStartBit = true; softSerial->rxBitIndex = 0; softSerial->transmissionErrors = 0; softSerial->receiveErrors = 0; softSerial->softSerialPortIndex = portIndex; softSerial->txIO = IOGetByTag(softSerial->txTimerHardware->tag); serialOutputPortConfig(softSerial->txTimerHardware->tag, portIndex); softSerial->rxIO = IOGetByTag(softSerial->rxTimerHardware->tag); serialInputPortConfig(softSerial->rxTimerHardware->tag, portIndex); setTxSignal(softSerial, ENABLE); delay(50); serialTimerTxConfig(softSerial->txTimerHardware, portIndex, baud); serialTimerRxConfig(softSerial->rxTimerHardware, portIndex, options); return &softSerial->port; }
serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallbackPtr callback, uint32_t baud, serialInversion_e inversion) { softSerial_t *softSerial = &(softSerialPorts[portIndex]); if (portIndex == SOFTSERIAL1) { softSerial->rxTimerHardware = &(timerHardware[SOFT_SERIAL_1_TIMER_RX_HARDWARE]); softSerial->txTimerHardware = &(timerHardware[SOFT_SERIAL_1_TIMER_TX_HARDWARE]); } if (portIndex == SOFTSERIAL2) { softSerial->rxTimerHardware = &(timerHardware[SOFT_SERIAL_2_TIMER_RX_HARDWARE]); softSerial->txTimerHardware = &(timerHardware[SOFT_SERIAL_2_TIMER_TX_HARDWARE]); } softSerial->port.vTable = softSerialVTable; softSerial->port.baudRate = baud; softSerial->port.mode = MODE_RXTX; softSerial->port.inversion = inversion; softSerial->port.callback = callback; resetBuffers(softSerial); softSerial->isTransmittingData = false; softSerial->isSearchingForStartBit = true; softSerial->rxBitIndex = 0; softSerial->transmissionErrors = 0; softSerial->receiveErrors = 0; softSerial->softSerialPortIndex = portIndex; serialOutputPortConfig(softSerial->txTimerHardware); serialInputPortConfig(softSerial->rxTimerHardware); setTxSignal(softSerial, ENABLE); delay(50); serialTimerTxConfig(softSerial->txTimerHardware, portIndex, baud); serialTimerRxConfig(softSerial->rxTimerHardware, portIndex, inversion); return &softSerial->port; }
void processTxState(softSerial_t *softSerial) { uint8_t mask; if (!softSerial->isTransmittingData) { 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 uint8_t byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++]; if (softSerial->port.txBufferTail >= softSerial->port.txBufferSize) { softSerial->port.txBufferTail = 0; } // build internal buffer, MSB = Stop Bit (1) + data bits (MSB to LSB) + start bit(0) LSB softSerial->internalTxBuffer = (1 << (TX_TOTAL_BITS - 1)) | (byteToSend << 1); 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; } if (softSerial->bitsLeftToTransmit) { mask = softSerial->internalTxBuffer & 1; softSerial->internalTxBuffer >>= 1; setTxSignal(softSerial, mask); softSerial->bitsLeftToTransmit--; return; }
serialPort_t *openEscSerial(escSerialPortIndex_e portIndex, serialReceiveCallbackPtr callback, uint16_t output, uint32_t baud, portOptions_t options, uint8_t mode) { escSerial_t *escSerial = &(escSerialPorts[portIndex]); escSerial->rxTimerHardware = &(timerHardware[output]); escSerial->txTimerHardware = &(timerHardware[ESCSERIAL_TIMER_TX_HARDWARE]); escSerial->port.vTable = escSerialVTable; escSerial->port.baudRate = baud; escSerial->port.mode = MODE_RXTX; escSerial->port.options = options; escSerial->port.callback = callback; resetBuffers(escSerial); escSerial->isTransmittingData = false; escSerial->isSearchingForStartBit = true; escSerial->rxBitIndex = 0; escSerial->transmissionErrors = 0; escSerial->receiveErrors = 0; escSerial->receiveTimeout = 0; escSerial->escSerialPortIndex = portIndex; serialInputPortConfig(escSerial->rxTimerHardware); setTxSignal(escSerial, ENABLE); delay(50); if(mode==0){ serialTimerTxConfig(escSerial->txTimerHardware, portIndex); serialTimerRxConfig(escSerial->rxTimerHardware, portIndex); } if(mode==1){ serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud); serialTimerRxConfigBL(escSerial->rxTimerHardware, portIndex, options); } return &escSerial->port; }
void setupSoftSerial1(uint32_t baud, uint8_t inverted) { int portIndex = 0; softSerial_t *softSerial = &(softSerialPorts[portIndex]); softSerial->port.vTable = softSerialVTable; softSerial->port.mode = MODE_RXTX; softSerial->port.baudRate = baud; softSerial->isInverted = inverted; //softSerial->rxTimerHardware = &(timerHardware[SOFT_SERIAL_1_TIMER_RX_HARDWARE]); //softSerial->txTimerHardware = &(timerHardware[SOFT_SERIAL_1_TIMER_TX_HARDWARE]); softSerial->port.rxBufferSize = SOFT_SERIAL_BUFFER_SIZE; softSerial->port.rxBuffer = softSerial->rxBuffer; softSerial->port.rxBufferTail = 0; softSerial->port.rxBufferHead = 0; softSerial->port.txBuffer = softSerial->txBuffer; softSerial->port.txBufferSize = SOFT_SERIAL_BUFFER_SIZE, softSerial->port.txBufferTail = 0; softSerial->port.txBufferHead = 0; softSerial->isTransmittingData = false; softSerial->isSearchingForStartBit = true; softSerial->isSearchingForStopBit = false; softSerial->timerRxCounter = 1; serialInputPortConfig(softSerial->rxTimerHardware); serialOutputPortConfig(softSerial->txTimerHardware); setTxSignal(softSerial, 1); delay(50); serialTimerConfig(softSerial->rxTimerHardware, baud, portIndex, onSerialTimer); }
void processTxState(softSerial_t *softSerial) { char mask; if (!softSerial->isTransmittingData) { char byteToSend; if (isSoftSerialTransmitBufferEmpty((serialPort_t *)softSerial)) { return; } // data to send byteToSend = softSerial->port.txBuffer[softSerial->port.txBufferTail++]; if (softSerial->port.txBufferTail >= softSerial->port.txBufferSize) { softSerial->port.txBufferTail = 0; } // build internal buffer, start bit(1) + data bits + stop bit(0) softSerial->internalTxBuffer = (1 << (TX_TOTAL_BITS - 1)) | (byteToSend << 1); softSerial->bitsLeftToTransmit = TX_TOTAL_BITS; // start immediately softSerial->timerTxCounter = 1; softSerial->isTransmittingData = true; return; } if (--softSerial->timerTxCounter <= 0) { mask = softSerial->internalTxBuffer & 1; softSerial->internalTxBuffer >>= 1; setTxSignal(softSerial, mask); softSerial->timerTxCounter = TICKS_PER_BIT; if (--softSerial->bitsLeftToTransmit <= 0) { softSerial->isTransmittingData = false; } }
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; }
void processTxState(escSerial_t *escSerial) { uint8_t mask; static uint8_t bitq=0, transmitStart=0; if (escSerial->isReceivingData) { return; } if(transmitStart==0) { setTxSignal(escSerial, 1); } if (!escSerial->isTransmittingData) { char byteToSend; reload: if (isEscSerialTransmitBufferEmpty((serialPort_t *)escSerial)) { // canreceive transmitStart=0; return; } if(transmitStart<3) { if(transmitStart==0) byteToSend = 0xff; if(transmitStart==1) byteToSend = 0xff; if(transmitStart==2) byteToSend = 0x7f; transmitStart++; } else{ // data to send byteToSend = escSerial->port.txBuffer[escSerial->port.txBufferTail++]; if (escSerial->port.txBufferTail >= escSerial->port.txBufferSize) { escSerial->port.txBufferTail = 0; } } // build internal buffer, data bits (MSB to LSB) escSerial->internalTxBuffer = byteToSend; escSerial->bitsLeftToTransmit = 8; escSerial->isTransmittingData = true; //set output serialOutputPortConfig(escSerial->rxTimerHardware); return; } if (escSerial->bitsLeftToTransmit) { mask = escSerial->internalTxBuffer & 1; if(mask) { if(bitq==0 || bitq==1) { setTxSignal(escSerial, 1); } if(bitq==2 || bitq==3) { setTxSignal(escSerial, 0); } } else { if(bitq==0 || bitq==2) { setTxSignal(escSerial, 1); } if(bitq==1 ||bitq==3) { setTxSignal(escSerial, 0); } } bitq++; if(bitq>3) { escSerial->internalTxBuffer >>= 1; escSerial->bitsLeftToTransmit--; bitq=0; if(escSerial->bitsLeftToTransmit==0) { goto reload; } }