Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This is about as much C as I can write in an hour. A software emulation of a UART, notable only for the fact it received data
- // correctly the very first time I ran it.
- // Don't expect this to compile, or be useful, I just cut the bits I'd written in the last hour out of a larger source as an example.
- typedef enum TSU_RX_STATES
- {
- surxIdle = 0,
- surxPossStart1,surxPossStart2,surxPossStart3,surxPossStart4,surxSetupByteRx,
- surxWaitForBit,
- surxSampleBit1,surxSampleBit2,surxSampleBit3,
- surxAverageBit,surxItIsZero,surxItIsOne,
- surxCheckStopBit1,
- surxError
- }TSU_RX_STATES;
- typedef struct TSOFT_UART
- {
- u8 u8ID;
- // Rx
- TSU_RX_STATES sRxState;
- u8 u8SampleCnt;
- u8 u8ActiveCnt;
- u8 u8BitCnt;
- u16 u16RxData;
- u16 u16RxMask;
- // The Rx buffer
- u16 u16Rx_pIn;
- u16 u16Rx_pOut;
- u8 u8RxData[SU_BYTE_BUFFER_CNT];
- // Tx
- TSU_TX_STATES sTxState;
- u16 u16TxData;
- // The Tx buffer
- u16 u16Tx_pIn;
- u16 u16Tx_pOut;
- u8 u8TxData[SU_BYTE_BUFFER_CNT];
- } TSOFT_UART;
- volatile TSOFT_UART sSoftUARTs[SOFT_UART_CNT];
- // The fast RX buffer - filled at 460KHz.
- #define FAST_RXBUFFER_SIZE (0x1000) // 4K samples
- // Handle a UART/Sample
- static void vHandleSU_Sample(volatile TSOFT_UART *psSU, bool bRxBit)
- {
- int u16Ptr;
- // Handle the Receive process
- switch(psSU->sRxState)
- {
- case surxError:
- psSU->sRxState=surxIdle;
- break;
- case surxIdle:
- if (bRxBit==0)
- psSU->sRxState=surxPossStart1;
- break;
- case surxPossStart1:
- if (bRxBit==0)
- psSU->sRxState=surxPossStart2;
- else
- psSU->sRxState=surxIdle;
- break;
- case surxPossStart2:
- if (bRxBit==0)
- psSU->sRxState=surxPossStart3;
- else
- psSU->sRxState=surxIdle;
- break;
- case surxPossStart3:
- if (bRxBit==0)
- {
- psSU->u8SampleCnt=3;
- psSU->sRxState=surxSetupByteRx;
- }
- else
- psSU->sRxState=surxIdle;
- break;
- case surxSetupByteRx:
- psSU->u8BitCnt=9; // 8 data plus one stop
- psSU->u16RxData=0; // Accumulator
- psSU->u16RxMask=0x0001; // Mask
- psSU->u8SampleCnt=3;
- psSU->sRxState=surxWaitForBit;
- break;
- case surxWaitForBit:
- if (--psSU->u8SampleCnt == 0)
- psSU->sRxState=surxSampleBit1;
- break;
- case surxSampleBit1:
- if (bRxBit!=0)
- psSU->u8ActiveCnt=1;
- else
- psSU->u8ActiveCnt=0;
- psSU->sRxState=surxSampleBit2;
- break;
- case surxSampleBit2:
- if (bRxBit!=0)
- psSU->u8ActiveCnt++;
- psSU->sRxState=surxSampleBit3;
- break;
- case surxSampleBit3:
- if (bRxBit!=0)
- psSU->u8ActiveCnt++;
- psSU->sRxState=surxAverageBit;
- break;
- case surxAverageBit:
- // Calc the state of this bit 0 -> "0", 1-> error, 2-> "1"
- if (psSU->u8ActiveCnt==0)
- psSU->sRxState=surxItIsZero;
- else if (psSU->u8ActiveCnt==3)
- psSU->sRxState=surxItIsOne;
- else
- psSU->sRxState=surxError;
- break;
- case surxItIsZero:
- // Shift the mask
- psSU->u16RxMask<<=1;
- // Are we done?
- if (--psSU->u8BitCnt == 0)
- psSU->sRxState=surxCheckStopBit1;
- else
- {
- psSU->u8SampleCnt=3;
- psSU->sRxState=surxWaitForBit;
- }
- break;
- case surxItIsOne:
- // Set the bit
- psSU->u16RxData|=psSU->u16RxMask;
- // Shift the mask
- psSU->u16RxMask<<=1;
- // Are we done?
- if (--psSU->u8BitCnt == 0)
- psSU->sRxState=surxCheckStopBit1;
- else
- {
- psSU->u8SampleCnt=3;
- psSU->sRxState=surxWaitForBit;
- }
- break;
- case surxCheckStopBit1:
- // Is it high?
- if (psSU->u16RxData & 0x0100)
- {
- // This data-byte is valid, stuff it in the buffer
- // Calculate the next place in the buffer
- u16Ptr = psSU->u16Rx_pIn;
- if (++u16Ptr >= SU_BYTE_BUFFER_CNT)
- u16Ptr = 0;
- // Is there any room ? i.e. is this the same as the output pointer ?
- if (u16Ptr != psSU->u16Rx_pOut)
- {
- // There's room. Put the char in the buffer
- psSU->u8RxData[psSU->u16Rx_pIn] = psSU->u16RxData;
- // Move the input pointer
- psSU->u16Rx_pIn = u16Ptr;
- }
- // Go back to looking for the next start-bit
- psSU->sRxState=surxIdle;
- }
- else
- psSU->sRxState=surxError;
- break;
- default:
- psSU->sRxState=surxIdle;
- break;
- }
- }
- // Handle the RX process...
- static void vProcessRx_SU(int iMaxCycles)
- {
- u16 u16RawInputs;
- volatile TSOFT_UART *psSU;
- int iIndex;
- u16 u16iMask;
- // Show the Active time
- SET_PORT(GPIOI,B9);
- do {
- // Anything lurking?
- if (u16RxFast_pIn == u16RxFast_pOut)
- break; // No, bugger off
- // Yes, get and process it
- u16RawInputs = u16RxFastBuff[u16RxFast_pOut++];
- // Clip the pointer
- if (u16RxFast_pOut>=FAST_RXBUFFER_SIZE)
- u16RxFast_pOut=0;
- // Now, handle the Rx process for these 13 inputs
- u16iMask=0x0001;
- psSU=sSoftUARTs;
- for(iIndex=0;iIndex<SOFT_UART_RX_CNT;iIndex++)
- {
- vHandleSU_Sample(psSU++,(u16RawInputs & u16iMask)!=0);
- u16iMask<<=1;
- }
- // And we're done
- } while(iMaxCycles--);
- // Show the Active time
- CLR_PORT(GPIOI,B9);
- }
- // Receive a char from a soft UART, else result = -1 if there isn't one in the buffer
- s32 s32Read_SU(int iIndex)
- {
- volatile TSOFT_UART *psSU;
- u8 u8C;
- if (iIndex>=SOFT_UART_CNT)
- return (-1);
- // Point at the damned thing
- psSU=&sSoftUARTs[iIndex];
- // Anything waiting in the buffer?
- if (psSU->u16Rx_pIn != psSU->u16Rx_pOut)
- {
- // Read it
- u8C = psSU->u8RxData[psSU->u16Rx_pOut++];
- // Wrap the pointer
- if (psSU->u16Rx_pOut >= SU_BYTE_BUFFER_CNT)
- psSU->u16Rx_pOut = 0;
- return (u8C);
- }
- else
- return (-1);
- }
- // Anything waiting in the receive buffer?
- bool bRxWaiting_SU(int iIndex)
- {
- volatile TSOFT_UART *psSU;
- if (iIndex>=SOFT_UART_CNT)
- return true;
- // Point at the damned thing
- psSU=&sSoftUARTs[iIndex];
- return (psSU->u16Rx_pIn != psSU->u16Rx_pOut);
- }
Add Comment
Please, Sign In to add comment