SmartMesh QSL for STM32F4 version

Fork of COG-AD4050_QSL by APS Lab

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dn_hdlc.c Source File

dn_hdlc.c

00001 /*
00002 Copyright (c) 2014, Dust Networks. All rights reserved.
00003 
00004 HDLC library.
00005 
00006 \license See attached DN_LICENSE.txt.
00007 */
00008 
00009 #include "dn_hdlc.h"
00010 #include "dn_uart.h"
00011 #include "dn_lock.h"
00012 
00013 //=========================== variables =======================================
00014 
00015 typedef struct {
00016    // admin
00017    dn_hdlc_rxFrame_cbt  rxFrame_cb;
00018    // input
00019    uint8_t              lastRxByte;
00020    bool                 busyReceiving;
00021    bool                 inputEscaping;
00022    uint16_t             inputCrc;
00023    uint8_t              inputBufFill;
00024    uint8_t              inputBuf[DN_HDLC_INPUT_BUFFER_SIZE];
00025    // output
00026    uint16_t             outputCrc;
00027 } dn_hdlc_vars_t;
00028 
00029 dn_hdlc_vars_t dn_hdlc_vars;
00030 
00031 //=========================== prototypes ======================================
00032 
00033 // callback handlers
00034 void dn_hdlc_rxByte(uint8_t rxbyte);
00035 // input
00036 void dn_hdlc_inputOpen();
00037 void dn_hdlc_inputWrite(uint8_t b);
00038 void dn_hdlc_inputClose();
00039 // helpers
00040 uint16_t dn_hdlc_crcIteration(uint16_t crc, uint8_t data_byte);
00041 
00042 //=========================== public ==========================================
00043 
00044 /**
00045 \brief Setting up the instance.
00046 */
00047 void dn_hdlc_init(dn_hdlc_rxFrame_cbt rxFrame_cb) {
00048    // reset local variables
00049    memset(&dn_hdlc_vars,   0, sizeof(dn_hdlc_vars));
00050    
00051    // store params
00052    dn_hdlc_vars.rxFrame_cb = rxFrame_cb;
00053    
00054    // initialize UART
00055    dn_uart_init(dn_hdlc_rxByte);
00056 }
00057 
00058 //=========================== private =========================================
00059 
00060 //===== callback_handler
00061 
00062 /**
00063 \brief Function which getted called each time a byte is received over UART.
00064 
00065 \param[in] rxbyte The received byte.
00066 */
00067 void dn_hdlc_rxByte(uint8_t rxbyte) {
00068    
00069    // lock the module
00070    dn_lock();
00071    
00072    if        (
00073          dn_hdlc_vars.busyReceiving==FALSE  &&
00074          dn_hdlc_vars.lastRxByte==DN_HDLC_FLAG &&
00075          rxbyte!=DN_HDLC_FLAG
00076       ) {
00077       // start of frame
00078       
00079       // I'm now receiving
00080       dn_hdlc_vars.busyReceiving       = TRUE;
00081       
00082       // create the HDLC frame
00083       dn_hdlc_inputOpen();
00084       
00085       // add the byte just received
00086       dn_hdlc_inputWrite(rxbyte);
00087    } else if (
00088          dn_hdlc_vars.busyReceiving==TRUE   &&
00089          rxbyte!=DN_HDLC_FLAG
00090       ){
00091       // middle of frame
00092       
00093       // add the byte just received
00094       dn_hdlc_inputWrite(rxbyte);
00095       
00096       if (dn_hdlc_vars.inputBufFill+1>DN_HDLC_INPUT_BUFFER_SIZE) {
00097          // input buffer overflow
00098          dn_hdlc_vars.inputBufFill       = 0;
00099          dn_hdlc_vars.busyReceiving      = FALSE;
00100       }
00101    } else if (
00102          dn_hdlc_vars.busyReceiving==TRUE   &&
00103          rxbyte==DN_HDLC_FLAG
00104       ) {
00105       // end of frame
00106       
00107       // finalize the HDLC frame
00108       dn_hdlc_inputClose();
00109       
00110       if (dn_hdlc_vars.inputBufFill==0) {
00111          // invalid HDLC frame
00112       } else {
00113          // hand over frame to upper layer
00114          dn_hdlc_vars.rxFrame_cb(&dn_hdlc_vars.inputBuf[0],dn_hdlc_vars.inputBufFill);
00115          
00116          // clear inputBuffer
00117          dn_hdlc_vars.inputBufFill=0;
00118       }
00119       
00120       dn_hdlc_vars.busyReceiving = FALSE;
00121    }
00122    
00123    dn_hdlc_vars.lastRxByte = rxbyte;
00124    
00125    // unlock the module
00126    dn_unlock();
00127 }
00128 
00129 //===== output
00130 
00131 /**
00132 \brief Start an HDLC frame in the output buffer.
00133 */
00134 void dn_hdlc_outputOpen() {
00135    // initialize the value of the CRC
00136    dn_hdlc_vars.outputCrc = DN_HDLC_CRCINIT;
00137    
00138    // send opening HDLC flag
00139    dn_uart_txByte(DN_HDLC_FLAG);
00140 }
00141 
00142 /**
00143 \brief Add a byte to the outgoing HDLC frame being built.
00144 
00145 \param[in] b The byte to add.
00146 */
00147 void dn_hdlc_outputWrite(uint8_t b) {
00148    
00149    // iterate through CRC calculator
00150    dn_hdlc_vars.outputCrc = dn_hdlc_crcIteration(dn_hdlc_vars.outputCrc,b);
00151    
00152    // write optional escape byte
00153    if (b==DN_HDLC_FLAG || b==DN_HDLC_ESCAPE) {
00154       dn_uart_txByte(DN_HDLC_ESCAPE);
00155       b = b^DN_HDLC_ESCAPE_MASK;
00156    }
00157    
00158    // data byte
00159    dn_uart_txByte(b);
00160 }
00161 
00162 /**
00163 \brief Finalize the outgoing HDLC frame.
00164 */
00165 void dn_hdlc_outputClose() {
00166    uint16_t   finalCrc;
00167    
00168    // finalize the calculation of the CRC
00169    finalCrc   = ~dn_hdlc_vars.outputCrc;
00170    
00171    // write the CRC value
00172    dn_hdlc_outputWrite((finalCrc>>0)&0xff);
00173    dn_hdlc_outputWrite((finalCrc>>8)&0xff);
00174    
00175    // write closing HDLC flag
00176    dn_uart_txByte(DN_HDLC_FLAG);
00177    
00178    // flush the UART
00179    dn_uart_txFlush();
00180 }
00181 
00182 //===== input
00183 
00184 /**
00185 \brief Start an HDLC frame in the input buffer.
00186 */
00187 void dn_hdlc_inputOpen() {
00188    // reset the input buffer index
00189    dn_hdlc_vars.inputBufFill = 0;
00190    
00191    // initialize the value of the CRC
00192    dn_hdlc_vars.inputCrc = DN_HDLC_CRCINIT;
00193 }
00194 
00195 /**
00196 \brief Add a byte to the incoming HDLC frame.
00197 
00198 \param[in] b The byte to add.
00199 */
00200 void dn_hdlc_inputWrite(uint8_t b) {
00201    if (b==DN_HDLC_ESCAPE) {
00202       dn_hdlc_vars.inputEscaping = TRUE;
00203    } else {
00204       if (dn_hdlc_vars.inputEscaping==TRUE) {
00205          b = b^DN_HDLC_ESCAPE_MASK;
00206          dn_hdlc_vars.inputEscaping = FALSE;
00207       }
00208       
00209       // add byte to input buffer
00210       dn_hdlc_vars.inputBuf[dn_hdlc_vars.inputBufFill] = b;
00211       dn_hdlc_vars.inputBufFill++;
00212       
00213       // iterate through CRC calculator
00214       dn_hdlc_vars.inputCrc = dn_hdlc_crcIteration(dn_hdlc_vars.inputCrc,b);
00215    }
00216 }
00217 
00218 /**
00219 \brief Finalize the incoming HDLC frame.
00220 */
00221 void dn_hdlc_inputClose() {
00222    
00223    // verify the validity of the frame
00224    if (dn_hdlc_vars.inputCrc==DN_HDLC_CRCGOOD) {
00225       // the CRC is correct
00226       
00227       // remove the CRC from the input buffer
00228       dn_hdlc_vars.inputBufFill    -= 2;
00229    } else {
00230       // the CRC is incorrect
00231       
00232       // drop the incoming fram
00233       dn_hdlc_vars.inputBufFill     = 0;
00234    }
00235    
00236    // reset escaping
00237    dn_hdlc_vars.inputEscaping = FALSE;
00238 }
00239 
00240 //=========================== helpers =========================================
00241 
00242 /**
00243 \brief Perform a single CRC iteration.
00244 
00245 \param[in] crc The current running CRC value.
00246 \param[in] b   The new byte.
00247 
00248 \return The updated CRC running value.
00249 */
00250 uint16_t dn_hdlc_crcIteration(uint16_t crc, uint8_t b) {
00251    return (crc >> 8) ^ dn_hdlc_fcstab[(crc ^ b) & 0xff];
00252 }
00253