SmartMesh QSL for STM32F4 version

Fork of COG-AD4050_QSL by APS Lab

Committer:
APS_Lab
Date:
Thu Jul 12 09:19:12 2018 +0000
Revision:
1:b909b8399252
Parent:
0:8ca1e814a851
SmartMesh for STM32F4 version

Who changed what in which revision?

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