Program that uses the QuickStart Library to interface a SmartMesh IP mote: Connects to the default network and starts publishing a random walk value every 5 seconds.
Fork of QSL_SimplePublish by
QSL SimplePublish
SmartMesh IP QuickStart Library
- GitHub repository
- Current release used: REL-1.0.2.2
- Documentation
- Discussion
sm_clib/dn_hdlc.c@9:f723949a18b7, 2016-11-04 (annotated)
- Committer:
- jhbr
- Date:
- Fri Nov 04 14:19:34 2016 +0000
- Revision:
- 9:f723949a18b7
- Parent:
- 1:89766ea2e99d
Deactivated DEBUG prints and updated mbed library to v128
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jhbr | 0:d3f5fdf2e6da | 1 | /* |
jhbr | 0:d3f5fdf2e6da | 2 | Copyright (c) 2014, Dust Networks. All rights reserved. |
jhbr | 0:d3f5fdf2e6da | 3 | |
jhbr | 0:d3f5fdf2e6da | 4 | HDLC library. |
jhbr | 0:d3f5fdf2e6da | 5 | |
jhbr | 0:d3f5fdf2e6da | 6 | \license See attached DN_LICENSE.txt. |
jhbr | 0:d3f5fdf2e6da | 7 | */ |
jhbr | 0:d3f5fdf2e6da | 8 | |
jhbr | 0:d3f5fdf2e6da | 9 | #include "dn_hdlc.h" |
jhbr | 0:d3f5fdf2e6da | 10 | #include "dn_uart.h" |
jhbr | 0:d3f5fdf2e6da | 11 | #include "dn_lock.h" |
jhbr | 0:d3f5fdf2e6da | 12 | |
jhbr | 0:d3f5fdf2e6da | 13 | //=========================== variables ======================================= |
jhbr | 0:d3f5fdf2e6da | 14 | |
jhbr | 0:d3f5fdf2e6da | 15 | typedef struct { |
jhbr | 0:d3f5fdf2e6da | 16 | // admin |
jhbr | 0:d3f5fdf2e6da | 17 | dn_hdlc_rxFrame_cbt rxFrame_cb; |
jhbr | 0:d3f5fdf2e6da | 18 | // input |
jhbr | 0:d3f5fdf2e6da | 19 | uint8_t lastRxByte; |
jhbr | 0:d3f5fdf2e6da | 20 | bool busyReceiving; |
jhbr | 0:d3f5fdf2e6da | 21 | bool inputEscaping; |
jhbr | 0:d3f5fdf2e6da | 22 | uint16_t inputCrc; |
jhbr | 0:d3f5fdf2e6da | 23 | uint8_t inputBufFill; |
jhbr | 0:d3f5fdf2e6da | 24 | uint8_t inputBuf[DN_HDLC_INPUT_BUFFER_SIZE]; |
jhbr | 0:d3f5fdf2e6da | 25 | // output |
jhbr | 0:d3f5fdf2e6da | 26 | uint16_t outputCrc; |
jhbr | 0:d3f5fdf2e6da | 27 | } dn_hdlc_vars_t; |
jhbr | 0:d3f5fdf2e6da | 28 | |
jhbr | 0:d3f5fdf2e6da | 29 | dn_hdlc_vars_t dn_hdlc_vars; |
jhbr | 0:d3f5fdf2e6da | 30 | |
jhbr | 0:d3f5fdf2e6da | 31 | //=========================== prototypes ====================================== |
jhbr | 0:d3f5fdf2e6da | 32 | |
jhbr | 0:d3f5fdf2e6da | 33 | // callback handlers |
jhbr | 0:d3f5fdf2e6da | 34 | void dn_hdlc_rxByte(uint8_t rxbyte); |
jhbr | 0:d3f5fdf2e6da | 35 | // input |
jhbr | 0:d3f5fdf2e6da | 36 | void dn_hdlc_inputOpen(); |
jhbr | 0:d3f5fdf2e6da | 37 | void dn_hdlc_inputWrite(uint8_t b); |
jhbr | 0:d3f5fdf2e6da | 38 | void dn_hdlc_inputClose(); |
jhbr | 0:d3f5fdf2e6da | 39 | // helpers |
jhbr | 0:d3f5fdf2e6da | 40 | uint16_t dn_hdlc_crcIteration(uint16_t crc, uint8_t data_byte); |
jhbr | 0:d3f5fdf2e6da | 41 | |
jhbr | 0:d3f5fdf2e6da | 42 | //=========================== public ========================================== |
jhbr | 0:d3f5fdf2e6da | 43 | |
jhbr | 0:d3f5fdf2e6da | 44 | /** |
jhbr | 0:d3f5fdf2e6da | 45 | \brief Setting up the instance. |
jhbr | 0:d3f5fdf2e6da | 46 | */ |
jhbr | 0:d3f5fdf2e6da | 47 | void dn_hdlc_init(dn_hdlc_rxFrame_cbt rxFrame_cb) { |
jhbr | 0:d3f5fdf2e6da | 48 | // reset local variables |
jhbr | 0:d3f5fdf2e6da | 49 | memset(&dn_hdlc_vars, 0, sizeof(dn_hdlc_vars)); |
jhbr | 0:d3f5fdf2e6da | 50 | |
jhbr | 0:d3f5fdf2e6da | 51 | // store params |
jhbr | 0:d3f5fdf2e6da | 52 | dn_hdlc_vars.rxFrame_cb = rxFrame_cb; |
jhbr | 0:d3f5fdf2e6da | 53 | |
jhbr | 0:d3f5fdf2e6da | 54 | // initialize UART |
jhbr | 0:d3f5fdf2e6da | 55 | dn_uart_init(dn_hdlc_rxByte); |
jhbr | 0:d3f5fdf2e6da | 56 | } |
jhbr | 0:d3f5fdf2e6da | 57 | |
jhbr | 0:d3f5fdf2e6da | 58 | //=========================== private ========================================= |
jhbr | 0:d3f5fdf2e6da | 59 | |
jhbr | 0:d3f5fdf2e6da | 60 | //===== callback_handler |
jhbr | 0:d3f5fdf2e6da | 61 | |
jhbr | 0:d3f5fdf2e6da | 62 | /** |
jhbr | 0:d3f5fdf2e6da | 63 | \brief Function which getted called each time a byte is received over UART. |
jhbr | 0:d3f5fdf2e6da | 64 | |
jhbr | 0:d3f5fdf2e6da | 65 | \param[in] rxbyte The received byte. |
jhbr | 0:d3f5fdf2e6da | 66 | */ |
jhbr | 0:d3f5fdf2e6da | 67 | void dn_hdlc_rxByte(uint8_t rxbyte) { |
jhbr | 0:d3f5fdf2e6da | 68 | |
jhbr | 0:d3f5fdf2e6da | 69 | // lock the module |
jhbr | 0:d3f5fdf2e6da | 70 | dn_lock(); |
jhbr | 0:d3f5fdf2e6da | 71 | |
jhbr | 0:d3f5fdf2e6da | 72 | if ( |
jhbr | 0:d3f5fdf2e6da | 73 | dn_hdlc_vars.busyReceiving==FALSE && |
jhbr | 0:d3f5fdf2e6da | 74 | dn_hdlc_vars.lastRxByte==DN_HDLC_FLAG && |
jhbr | 0:d3f5fdf2e6da | 75 | rxbyte!=DN_HDLC_FLAG |
jhbr | 0:d3f5fdf2e6da | 76 | ) { |
jhbr | 0:d3f5fdf2e6da | 77 | // start of frame |
jhbr | 0:d3f5fdf2e6da | 78 | |
jhbr | 0:d3f5fdf2e6da | 79 | // I'm now receiving |
jhbr | 0:d3f5fdf2e6da | 80 | dn_hdlc_vars.busyReceiving = TRUE; |
jhbr | 0:d3f5fdf2e6da | 81 | |
jhbr | 0:d3f5fdf2e6da | 82 | // create the HDLC frame |
jhbr | 0:d3f5fdf2e6da | 83 | dn_hdlc_inputOpen(); |
jhbr | 0:d3f5fdf2e6da | 84 | |
jhbr | 0:d3f5fdf2e6da | 85 | // add the byte just received |
jhbr | 0:d3f5fdf2e6da | 86 | dn_hdlc_inputWrite(rxbyte); |
jhbr | 0:d3f5fdf2e6da | 87 | } else if ( |
jhbr | 0:d3f5fdf2e6da | 88 | dn_hdlc_vars.busyReceiving==TRUE && |
jhbr | 0:d3f5fdf2e6da | 89 | rxbyte!=DN_HDLC_FLAG |
jhbr | 0:d3f5fdf2e6da | 90 | ){ |
jhbr | 0:d3f5fdf2e6da | 91 | // middle of frame |
jhbr | 0:d3f5fdf2e6da | 92 | |
jhbr | 0:d3f5fdf2e6da | 93 | // add the byte just received |
jhbr | 0:d3f5fdf2e6da | 94 | dn_hdlc_inputWrite(rxbyte); |
jhbr | 0:d3f5fdf2e6da | 95 | |
jhbr | 0:d3f5fdf2e6da | 96 | if (dn_hdlc_vars.inputBufFill+1>DN_HDLC_INPUT_BUFFER_SIZE) { |
jhbr | 0:d3f5fdf2e6da | 97 | // input buffer overflow |
jhbr | 0:d3f5fdf2e6da | 98 | dn_hdlc_vars.inputBufFill = 0; |
jhbr | 0:d3f5fdf2e6da | 99 | dn_hdlc_vars.busyReceiving = FALSE; |
jhbr | 0:d3f5fdf2e6da | 100 | } |
jhbr | 0:d3f5fdf2e6da | 101 | } else if ( |
jhbr | 0:d3f5fdf2e6da | 102 | dn_hdlc_vars.busyReceiving==TRUE && |
jhbr | 0:d3f5fdf2e6da | 103 | rxbyte==DN_HDLC_FLAG |
jhbr | 0:d3f5fdf2e6da | 104 | ) { |
jhbr | 0:d3f5fdf2e6da | 105 | // end of frame |
jhbr | 0:d3f5fdf2e6da | 106 | |
jhbr | 0:d3f5fdf2e6da | 107 | // finalize the HDLC frame |
jhbr | 0:d3f5fdf2e6da | 108 | dn_hdlc_inputClose(); |
jhbr | 0:d3f5fdf2e6da | 109 | |
jhbr | 0:d3f5fdf2e6da | 110 | if (dn_hdlc_vars.inputBufFill==0) { |
jhbr | 0:d3f5fdf2e6da | 111 | // invalid HDLC frame |
jhbr | 0:d3f5fdf2e6da | 112 | } else { |
jhbr | 0:d3f5fdf2e6da | 113 | // hand over frame to upper layer |
jhbr | 0:d3f5fdf2e6da | 114 | dn_hdlc_vars.rxFrame_cb(&dn_hdlc_vars.inputBuf[0],dn_hdlc_vars.inputBufFill); |
jhbr | 0:d3f5fdf2e6da | 115 | |
jhbr | 0:d3f5fdf2e6da | 116 | // clear inputBuffer |
jhbr | 0:d3f5fdf2e6da | 117 | dn_hdlc_vars.inputBufFill=0; |
jhbr | 0:d3f5fdf2e6da | 118 | } |
jhbr | 0:d3f5fdf2e6da | 119 | |
jhbr | 0:d3f5fdf2e6da | 120 | dn_hdlc_vars.busyReceiving = FALSE; |
jhbr | 0:d3f5fdf2e6da | 121 | } |
jhbr | 0:d3f5fdf2e6da | 122 | |
jhbr | 0:d3f5fdf2e6da | 123 | dn_hdlc_vars.lastRxByte = rxbyte; |
jhbr | 0:d3f5fdf2e6da | 124 | |
jhbr | 0:d3f5fdf2e6da | 125 | // unlock the module |
jhbr | 0:d3f5fdf2e6da | 126 | dn_unlock(); |
jhbr | 0:d3f5fdf2e6da | 127 | } |
jhbr | 0:d3f5fdf2e6da | 128 | |
jhbr | 0:d3f5fdf2e6da | 129 | //===== output |
jhbr | 0:d3f5fdf2e6da | 130 | |
jhbr | 0:d3f5fdf2e6da | 131 | /** |
jhbr | 0:d3f5fdf2e6da | 132 | \brief Start an HDLC frame in the output buffer. |
jhbr | 0:d3f5fdf2e6da | 133 | */ |
jhbr | 0:d3f5fdf2e6da | 134 | void dn_hdlc_outputOpen() { |
jhbr | 0:d3f5fdf2e6da | 135 | // initialize the value of the CRC |
jhbr | 0:d3f5fdf2e6da | 136 | dn_hdlc_vars.outputCrc = DN_HDLC_CRCINIT; |
jhbr | 0:d3f5fdf2e6da | 137 | |
jhbr | 0:d3f5fdf2e6da | 138 | // send opening HDLC flag |
jhbr | 0:d3f5fdf2e6da | 139 | dn_uart_txByte(DN_HDLC_FLAG); |
jhbr | 0:d3f5fdf2e6da | 140 | } |
jhbr | 0:d3f5fdf2e6da | 141 | |
jhbr | 0:d3f5fdf2e6da | 142 | /** |
jhbr | 0:d3f5fdf2e6da | 143 | \brief Add a byte to the outgoing HDLC frame being built. |
jhbr | 0:d3f5fdf2e6da | 144 | |
jhbr | 0:d3f5fdf2e6da | 145 | \param[in] b The byte to add. |
jhbr | 0:d3f5fdf2e6da | 146 | */ |
jhbr | 0:d3f5fdf2e6da | 147 | void dn_hdlc_outputWrite(uint8_t b) { |
jhbr | 0:d3f5fdf2e6da | 148 | |
jhbr | 0:d3f5fdf2e6da | 149 | // iterate through CRC calculator |
jhbr | 0:d3f5fdf2e6da | 150 | dn_hdlc_vars.outputCrc = dn_hdlc_crcIteration(dn_hdlc_vars.outputCrc,b); |
jhbr | 0:d3f5fdf2e6da | 151 | |
jhbr | 0:d3f5fdf2e6da | 152 | // write optional escape byte |
jhbr | 0:d3f5fdf2e6da | 153 | if (b==DN_HDLC_FLAG || b==DN_HDLC_ESCAPE) { |
jhbr | 0:d3f5fdf2e6da | 154 | dn_uart_txByte(DN_HDLC_ESCAPE); |
jhbr | 0:d3f5fdf2e6da | 155 | b = b^DN_HDLC_ESCAPE_MASK; |
jhbr | 0:d3f5fdf2e6da | 156 | } |
jhbr | 0:d3f5fdf2e6da | 157 | |
jhbr | 0:d3f5fdf2e6da | 158 | // data byte |
jhbr | 0:d3f5fdf2e6da | 159 | dn_uart_txByte(b); |
jhbr | 0:d3f5fdf2e6da | 160 | } |
jhbr | 0:d3f5fdf2e6da | 161 | |
jhbr | 0:d3f5fdf2e6da | 162 | /** |
jhbr | 0:d3f5fdf2e6da | 163 | \brief Finalize the outgoing HDLC frame. |
jhbr | 0:d3f5fdf2e6da | 164 | */ |
jhbr | 0:d3f5fdf2e6da | 165 | void dn_hdlc_outputClose() { |
jhbr | 0:d3f5fdf2e6da | 166 | uint16_t finalCrc; |
jhbr | 0:d3f5fdf2e6da | 167 | |
jhbr | 0:d3f5fdf2e6da | 168 | // finalize the calculation of the CRC |
jhbr | 0:d3f5fdf2e6da | 169 | finalCrc = ~dn_hdlc_vars.outputCrc; |
jhbr | 0:d3f5fdf2e6da | 170 | |
jhbr | 0:d3f5fdf2e6da | 171 | // write the CRC value |
jhbr | 0:d3f5fdf2e6da | 172 | dn_hdlc_outputWrite((finalCrc>>0)&0xff); |
jhbr | 0:d3f5fdf2e6da | 173 | dn_hdlc_outputWrite((finalCrc>>8)&0xff); |
jhbr | 0:d3f5fdf2e6da | 174 | |
jhbr | 0:d3f5fdf2e6da | 175 | // write closing HDLC flag |
jhbr | 0:d3f5fdf2e6da | 176 | dn_uart_txByte(DN_HDLC_FLAG); |
jhbr | 0:d3f5fdf2e6da | 177 | |
jhbr | 0:d3f5fdf2e6da | 178 | // flush the UART |
jhbr | 0:d3f5fdf2e6da | 179 | dn_uart_txFlush(); |
jhbr | 0:d3f5fdf2e6da | 180 | } |
jhbr | 0:d3f5fdf2e6da | 181 | |
jhbr | 0:d3f5fdf2e6da | 182 | //===== input |
jhbr | 0:d3f5fdf2e6da | 183 | |
jhbr | 0:d3f5fdf2e6da | 184 | /** |
jhbr | 0:d3f5fdf2e6da | 185 | \brief Start an HDLC frame in the input buffer. |
jhbr | 0:d3f5fdf2e6da | 186 | */ |
jhbr | 0:d3f5fdf2e6da | 187 | void dn_hdlc_inputOpen() { |
jhbr | 0:d3f5fdf2e6da | 188 | // reset the input buffer index |
jhbr | 0:d3f5fdf2e6da | 189 | dn_hdlc_vars.inputBufFill = 0; |
jhbr | 0:d3f5fdf2e6da | 190 | |
jhbr | 0:d3f5fdf2e6da | 191 | // initialize the value of the CRC |
jhbr | 0:d3f5fdf2e6da | 192 | dn_hdlc_vars.inputCrc = DN_HDLC_CRCINIT; |
jhbr | 0:d3f5fdf2e6da | 193 | } |
jhbr | 0:d3f5fdf2e6da | 194 | |
jhbr | 0:d3f5fdf2e6da | 195 | /** |
jhbr | 0:d3f5fdf2e6da | 196 | \brief Add a byte to the incoming HDLC frame. |
jhbr | 0:d3f5fdf2e6da | 197 | |
jhbr | 0:d3f5fdf2e6da | 198 | \param[in] b The byte to add. |
jhbr | 0:d3f5fdf2e6da | 199 | */ |
jhbr | 0:d3f5fdf2e6da | 200 | void dn_hdlc_inputWrite(uint8_t b) { |
jhbr | 0:d3f5fdf2e6da | 201 | if (b==DN_HDLC_ESCAPE) { |
jhbr | 0:d3f5fdf2e6da | 202 | dn_hdlc_vars.inputEscaping = TRUE; |
jhbr | 0:d3f5fdf2e6da | 203 | } else { |
jhbr | 0:d3f5fdf2e6da | 204 | if (dn_hdlc_vars.inputEscaping==TRUE) { |
jhbr | 0:d3f5fdf2e6da | 205 | b = b^DN_HDLC_ESCAPE_MASK; |
jhbr | 0:d3f5fdf2e6da | 206 | dn_hdlc_vars.inputEscaping = FALSE; |
jhbr | 0:d3f5fdf2e6da | 207 | } |
jhbr | 0:d3f5fdf2e6da | 208 | |
jhbr | 0:d3f5fdf2e6da | 209 | // add byte to input buffer |
jhbr | 0:d3f5fdf2e6da | 210 | dn_hdlc_vars.inputBuf[dn_hdlc_vars.inputBufFill] = b; |
jhbr | 0:d3f5fdf2e6da | 211 | dn_hdlc_vars.inputBufFill++; |
jhbr | 0:d3f5fdf2e6da | 212 | |
jhbr | 0:d3f5fdf2e6da | 213 | // iterate through CRC calculator |
jhbr | 0:d3f5fdf2e6da | 214 | dn_hdlc_vars.inputCrc = dn_hdlc_crcIteration(dn_hdlc_vars.inputCrc,b); |
jhbr | 0:d3f5fdf2e6da | 215 | } |
jhbr | 0:d3f5fdf2e6da | 216 | } |
jhbr | 0:d3f5fdf2e6da | 217 | |
jhbr | 0:d3f5fdf2e6da | 218 | /** |
jhbr | 0:d3f5fdf2e6da | 219 | \brief Finalize the incoming HDLC frame. |
jhbr | 0:d3f5fdf2e6da | 220 | */ |
jhbr | 0:d3f5fdf2e6da | 221 | void dn_hdlc_inputClose() { |
jhbr | 0:d3f5fdf2e6da | 222 | |
jhbr | 0:d3f5fdf2e6da | 223 | // verify the validity of the frame |
jhbr | 0:d3f5fdf2e6da | 224 | if (dn_hdlc_vars.inputCrc==DN_HDLC_CRCGOOD) { |
jhbr | 0:d3f5fdf2e6da | 225 | // the CRC is correct |
jhbr | 0:d3f5fdf2e6da | 226 | |
jhbr | 0:d3f5fdf2e6da | 227 | // remove the CRC from the input buffer |
jhbr | 0:d3f5fdf2e6da | 228 | dn_hdlc_vars.inputBufFill -= 2; |
jhbr | 0:d3f5fdf2e6da | 229 | } else { |
jhbr | 0:d3f5fdf2e6da | 230 | // the CRC is incorrect |
jhbr | 0:d3f5fdf2e6da | 231 | |
jhbr | 0:d3f5fdf2e6da | 232 | // drop the incoming fram |
jhbr | 0:d3f5fdf2e6da | 233 | dn_hdlc_vars.inputBufFill = 0; |
jhbr | 0:d3f5fdf2e6da | 234 | } |
jhbr | 0:d3f5fdf2e6da | 235 | |
jhbr | 0:d3f5fdf2e6da | 236 | // reset escaping |
jhbr | 0:d3f5fdf2e6da | 237 | dn_hdlc_vars.inputEscaping = FALSE; |
jhbr | 0:d3f5fdf2e6da | 238 | } |
jhbr | 0:d3f5fdf2e6da | 239 | |
jhbr | 0:d3f5fdf2e6da | 240 | //=========================== helpers ========================================= |
jhbr | 0:d3f5fdf2e6da | 241 | |
jhbr | 0:d3f5fdf2e6da | 242 | /** |
jhbr | 0:d3f5fdf2e6da | 243 | \brief Perform a single CRC iteration. |
jhbr | 0:d3f5fdf2e6da | 244 | |
jhbr | 0:d3f5fdf2e6da | 245 | \param[in] crc The current running CRC value. |
jhbr | 0:d3f5fdf2e6da | 246 | \param[in] b The new byte. |
jhbr | 0:d3f5fdf2e6da | 247 | |
jhbr | 0:d3f5fdf2e6da | 248 | \return The updated CRC running value. |
jhbr | 0:d3f5fdf2e6da | 249 | */ |
jhbr | 0:d3f5fdf2e6da | 250 | uint16_t dn_hdlc_crcIteration(uint16_t crc, uint8_t b) { |
jhbr | 0:d3f5fdf2e6da | 251 | return (crc >> 8) ^ dn_hdlc_fcstab[(crc ^ b) & 0xff]; |
jhbr | 0:d3f5fdf2e6da | 252 | } |
jhbr | 0:d3f5fdf2e6da | 253 |