APS Lab
/
STM32F4_SmartMesh_QSL
SmartMesh QSL for STM32F4 version
Fork of COG-AD4050_QSL by
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 21:33:36 by 1.7.2