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.

Dependencies:   mbed millis

Fork of QSL_SimplePublish by Jon-Håkon Bøe Røli

QSL SimplePublish

SmartMesh IP QuickStart Library

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?

UserRevisionLine numberNew 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