Cremulus

Soft emulated UARTs first attempt.

Nov 2nd, 2021 (edited)
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.23 KB | None | 0 0
  1. // 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
  2. // correctly the very first time I ran it.
  3.  
  4. // 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.
  5.  
  6. typedef enum TSU_RX_STATES
  7.   {
  8.   surxIdle = 0,
  9.   surxPossStart1,surxPossStart2,surxPossStart3,surxPossStart4,surxSetupByteRx,
  10.   surxWaitForBit,
  11.   surxSampleBit1,surxSampleBit2,surxSampleBit3,
  12.   surxAverageBit,surxItIsZero,surxItIsOne,
  13.   surxCheckStopBit1,
  14.   surxError
  15.   }TSU_RX_STATES;
  16.  
  17. typedef struct TSOFT_UART
  18.   {
  19.   u8 u8ID;
  20.   // Rx
  21.   TSU_RX_STATES sRxState;
  22.   u8 u8SampleCnt;
  23.   u8 u8ActiveCnt;
  24.   u8 u8BitCnt;
  25.   u16 u16RxData;
  26.   u16 u16RxMask;
  27.   // The Rx buffer
  28.   u16 u16Rx_pIn;
  29.   u16 u16Rx_pOut;
  30.   u8 u8RxData[SU_BYTE_BUFFER_CNT];
  31.   // Tx
  32.   TSU_TX_STATES sTxState;
  33.   u16 u16TxData;
  34.   // The Tx buffer
  35.   u16 u16Tx_pIn;
  36.   u16 u16Tx_pOut;
  37.   u8 u8TxData[SU_BYTE_BUFFER_CNT];
  38.   } TSOFT_UART;
  39.  
  40. volatile TSOFT_UART sSoftUARTs[SOFT_UART_CNT];
  41.  
  42. // The fast RX buffer - filled at 460KHz.
  43. #define FAST_RXBUFFER_SIZE (0x1000) // 4K samples
  44.  
  45. // Handle a UART/Sample
  46. static void vHandleSU_Sample(volatile TSOFT_UART *psSU, bool bRxBit)
  47.   {
  48.   int u16Ptr;
  49.  
  50.   // Handle the Receive process
  51.   switch(psSU->sRxState)
  52.     {
  53.     case surxError:
  54.       psSU->sRxState=surxIdle;
  55.       break;
  56.     case surxIdle:
  57.       if (bRxBit==0)
  58.         psSU->sRxState=surxPossStart1;
  59.       break;
  60.     case surxPossStart1:
  61.       if (bRxBit==0)
  62.         psSU->sRxState=surxPossStart2;
  63.       else
  64.         psSU->sRxState=surxIdle;
  65.       break;
  66.     case surxPossStart2:
  67.       if (bRxBit==0)
  68.         psSU->sRxState=surxPossStart3;
  69.       else
  70.         psSU->sRxState=surxIdle;
  71.       break;
  72.     case surxPossStart3:
  73.       if (bRxBit==0)
  74.         {
  75.         psSU->u8SampleCnt=3;
  76.         psSU->sRxState=surxSetupByteRx;
  77.         }
  78.       else
  79.         psSU->sRxState=surxIdle;
  80.       break;
  81.     case surxSetupByteRx:
  82.       psSU->u8BitCnt=9; // 8 data plus one stop
  83.       psSU->u16RxData=0; // Accumulator
  84.       psSU->u16RxMask=0x0001; // Mask
  85.       psSU->u8SampleCnt=3;
  86.       psSU->sRxState=surxWaitForBit;
  87.       break;
  88.  
  89.     case surxWaitForBit:
  90.       if (--psSU->u8SampleCnt == 0)
  91.         psSU->sRxState=surxSampleBit1;
  92.       break;
  93.     case surxSampleBit1:
  94.       if (bRxBit!=0)
  95.         psSU->u8ActiveCnt=1;
  96.       else
  97.         psSU->u8ActiveCnt=0;
  98.       psSU->sRxState=surxSampleBit2;
  99.       break;
  100.     case surxSampleBit2:
  101.       if (bRxBit!=0)
  102.         psSU->u8ActiveCnt++;
  103.       psSU->sRxState=surxSampleBit3;
  104.       break;
  105.     case surxSampleBit3:
  106.       if (bRxBit!=0)
  107.         psSU->u8ActiveCnt++;
  108.       psSU->sRxState=surxAverageBit;
  109.       break;
  110.     case surxAverageBit:
  111.       // Calc the state of this bit 0 -> "0", 1-> error, 2-> "1"
  112.       if (psSU->u8ActiveCnt==0)
  113.         psSU->sRxState=surxItIsZero;
  114.       else if (psSU->u8ActiveCnt==3)
  115.         psSU->sRxState=surxItIsOne;
  116.       else
  117.         psSU->sRxState=surxError;
  118.       break;
  119.     case surxItIsZero:
  120.       // Shift the mask
  121.       psSU->u16RxMask<<=1;
  122.       // Are we done?
  123.       if (--psSU->u8BitCnt == 0)
  124.         psSU->sRxState=surxCheckStopBit1;
  125.       else
  126.         {
  127.         psSU->u8SampleCnt=3;
  128.         psSU->sRxState=surxWaitForBit;
  129.         }
  130.       break;
  131.     case surxItIsOne:
  132.       // Set the bit
  133.       psSU->u16RxData|=psSU->u16RxMask;
  134.       // Shift the mask
  135.       psSU->u16RxMask<<=1;
  136.       // Are we done?
  137.       if (--psSU->u8BitCnt == 0)
  138.         psSU->sRxState=surxCheckStopBit1;
  139.       else
  140.         {
  141.         psSU->u8SampleCnt=3;
  142.         psSU->sRxState=surxWaitForBit;
  143.         }
  144.       break;
  145.  
  146.     case surxCheckStopBit1:
  147.       // Is it high?
  148.       if (psSU->u16RxData & 0x0100)
  149.         {
  150.         // This data-byte is valid, stuff it in the buffer
  151.         // Calculate the next place in the buffer
  152.         u16Ptr = psSU->u16Rx_pIn;
  153.         if (++u16Ptr >= SU_BYTE_BUFFER_CNT)
  154.           u16Ptr = 0;
  155.         // Is there any room ? i.e. is this the same as the output pointer ?
  156.         if (u16Ptr != psSU->u16Rx_pOut)
  157.           {
  158.           // There's room. Put the char in the buffer
  159.           psSU->u8RxData[psSU->u16Rx_pIn] = psSU->u16RxData;
  160.           // Move the input pointer
  161.           psSU->u16Rx_pIn = u16Ptr;
  162.           }
  163.         // Go back to looking for the next start-bit
  164.         psSU->sRxState=surxIdle;
  165.         }
  166.       else
  167.         psSU->sRxState=surxError;
  168.       break;
  169.  
  170.     default:
  171.       psSU->sRxState=surxIdle;
  172.       break;
  173.     }
  174.   }
  175.  
  176. // Handle the RX process...
  177. static void vProcessRx_SU(int iMaxCycles)
  178.   {
  179.   u16 u16RawInputs;
  180.   volatile TSOFT_UART *psSU;
  181.   int iIndex;
  182.   u16 u16iMask;
  183.  
  184.   // Show the Active time
  185.   SET_PORT(GPIOI,B9);
  186.   do {
  187.     // Anything lurking?
  188.     if (u16RxFast_pIn == u16RxFast_pOut)
  189.       break; // No, bugger off
  190.     // Yes, get and process it
  191.     u16RawInputs = u16RxFastBuff[u16RxFast_pOut++];
  192.     // Clip the pointer
  193.     if (u16RxFast_pOut>=FAST_RXBUFFER_SIZE)
  194.       u16RxFast_pOut=0;
  195.     // Now, handle the Rx process for these 13 inputs
  196.     u16iMask=0x0001;
  197.     psSU=sSoftUARTs;
  198.     for(iIndex=0;iIndex<SOFT_UART_RX_CNT;iIndex++)
  199.       {
  200.       vHandleSU_Sample(psSU++,(u16RawInputs & u16iMask)!=0);
  201.       u16iMask<<=1;
  202.       }
  203.     // And we're done
  204.     } while(iMaxCycles--);
  205.   // Show the Active time
  206.   CLR_PORT(GPIOI,B9);
  207.   }
  208.  
  209. // Receive a char from a soft UART, else result = -1 if there isn't one in the buffer
  210. s32 s32Read_SU(int iIndex)
  211.   {
  212.   volatile TSOFT_UART *psSU;
  213.   u8 u8C;
  214.  
  215.   if (iIndex>=SOFT_UART_CNT)
  216.     return (-1);
  217.  
  218.   // Point at the damned thing
  219.   psSU=&sSoftUARTs[iIndex];
  220.  
  221.   // Anything waiting in the buffer?
  222.   if (psSU->u16Rx_pIn != psSU->u16Rx_pOut)
  223.     {
  224.     // Read it
  225.     u8C = psSU->u8RxData[psSU->u16Rx_pOut++];
  226.     // Wrap the pointer
  227.     if (psSU->u16Rx_pOut >= SU_BYTE_BUFFER_CNT)
  228.       psSU->u16Rx_pOut = 0;
  229.     return (u8C);
  230.     }
  231.   else
  232.     return (-1);
  233.   }
  234.  
  235. // Anything waiting in the receive buffer?
  236. bool bRxWaiting_SU(int iIndex)
  237.   {
  238.   volatile TSOFT_UART *psSU;
  239.  
  240.   if (iIndex>=SOFT_UART_CNT)
  241.     return true;
  242.  
  243.   // Point at the damned thing
  244.   psSU=&sSoftUARTs[iIndex];
  245.   return (psSU->u16Rx_pIn != psSU->u16Rx_pOut);
  246.   }
  247.  
  248.  
Add Comment
Please, Sign In to add comment