Skip to content

Commit 037b356

Browse files
committedFeb 3, 2014
sm_clib 1.0.0.2
1 parent e5d2c1d commit 037b356

27 files changed

+19421
-0
lines changed
 

‎DN_LICENSE.txt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Copyright (c) 2012, Dust Networks
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
* Redistributions of source code must retain the above copyright
7+
notice, this list of conditions and the following disclaimer.
8+
* Redistributions in binary form must reproduce the above copyright
9+
notice, this list of conditions and the following disclaimer in the
10+
documentation and/or other materials provided with the distribution.
11+
* Neither the name of Dust Networks nor the
12+
names of its contributors may be used to endorse or promote products
13+
derived from this software without specific prior written permission.
14+
15+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
DISCLAIMED. IN NO EVENT SHALL DUST NETWORKS BE LIABLE FOR ANY
19+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

‎examples/arduino/Libraries/IpMgWrapper/IpMgWrapper.cpp

+625
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Arduino library to connect to a SmartMesh IP mote and periodically send data.
5+
6+
This library is an Arduino "wrapper" around the generic SmartMesh C library.
7+
8+
This library will:
9+
- Connect to the SmartMesh IP mote over its serial port.
10+
- Have the SmartMesh IP mote connect to a SmartMesh IP network, open and bind a
11+
UDP socket
12+
- Periodically, invoke a data generation function and send the generated
13+
payload to the specified IPv6 address and UDP port.
14+
15+
\license See attached DN_LICENSE.txt.
16+
*/
17+
18+
#ifndef IPMGWRAPPER_H
19+
#define IPMGWRAPPER_H
20+
21+
#include <Arduino.h>
22+
#include "dn_ipmt.h"
23+
24+
//=========================== defines =========================================
25+
26+
#define TIME_T unsigned long
27+
28+
#define BAUDRATE_CLI 9600
29+
#define BAUDRATE_API 115200
30+
31+
#define TRUE 0x01
32+
#define FALSE 0x00
33+
34+
// mote state
35+
#define MOTE_STATE_LOST 0x00
36+
#define MOTE_STATE_NEGOTIATING 0x01
37+
#define MOTE_STATE_OPERATIONAL 0x04
38+
39+
// service types
40+
#define SERVICE_TYPE_BW 0x00
41+
42+
#define IPv6ADDR_LEN 16
43+
#define DEFAULT_SOCKETID 22
44+
45+
// subscription
46+
#define SUBSC_FILTER_EVENT 0x02
47+
#define SUBSC_FILTER_LOG 0x02
48+
#define SUBSC_FILTER_DATA 0x10
49+
#define SUBSC_FILTER_IPDATA 0x20
50+
#define SUBSC_FILTER_HR 0x40
51+
52+
#define DN_UDP_PORT_OAP 0xf0b9
53+
54+
//===== fsm
55+
56+
#define CMD_PERIOD 0 // number of ms between two commands being sent
57+
#define INTER_FRAME_PERIOD 1 // min number of ms between two TX frames over serial port
58+
#define SERIAL_RESPONSE_TIMEOUT 100 // max number of ms to wait for serial response
59+
#define BACKOFF_AFTER_TIMEOUT 1000 // number of ms to back off after a timeout occurs
60+
#define OAP_RESPONSE_TIMEOUT 10000 // max number of ms to wait for OAP response
61+
62+
//=========================== typedef =========================================
63+
64+
class IpMgWrapper; // forward declaration needed here
65+
66+
typedef void (IpMgWrapper::*fsm_timer_callback)(void);
67+
typedef void (IpMgWrapper::*fsm_reply_callback)(void);
68+
typedef void (*data_generator)(uint16_t* returnVal);
69+
70+
//=========================== IpMgWrapper object ==============================
71+
72+
class IpMgWrapper {
73+
public:
74+
//===== methods
75+
IpMgWrapper();
76+
void setup();
77+
void loop();
78+
//===== attributes
79+
//===== methods
80+
//=== fsm
81+
void fsm_scheduleEvent(
82+
uint16_t delay,
83+
fsm_timer_callback cb
84+
);
85+
void fsm_setCallback(fsm_reply_callback cb);
86+
//=== api
87+
void api_response_timeout();
88+
void oap_response_timeout();
89+
void api_initiateConnect();
90+
void api_subscribe();
91+
void api_subscribe_reply();
92+
void api_getNextMoteConfig();
93+
void api_getNextMoteConfig_reply();
94+
void api_toggleLed();
95+
void api_toggleLed_reply();
96+
//=== helpers
97+
void printState(uint8_t state);
98+
void printByteArray(uint8_t* payload, uint8_t length);
99+
private:
100+
//===== attributes
101+
102+
};
103+
104+
#endif

‎examples/arduino/Libraries/IpMtWrapper/IpMtWrapper.cpp

+698
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Arduino library to connect to a SmartMesh IP mote and periodically send data.
5+
6+
This library is an Arduino "wrapper" around the generic SmartMesh C library.
7+
8+
This library will:
9+
- Connect to the SmartMesh IP mote over its serial port.
10+
- Have the SmartMesh IP mote connect to a SmartMesh IP network, open and bind a
11+
UDP socket
12+
- Periodically, invoke a data generation function and send the generated
13+
payload to the specified IPv6 address and UDP port.
14+
15+
\license See attached DN_LICENSE.txt.
16+
*/
17+
18+
#ifndef IPMTWRAPPER_H
19+
#define IPMTWRAPPER_H
20+
21+
#include <Arduino.h>
22+
#include "dn_ipmt.h"
23+
24+
//=========================== defines =========================================
25+
26+
#define TIME_T unsigned long
27+
28+
#define BAUDRATE_CLI 9600
29+
#define BAUDRATE_API 115200
30+
31+
#define TRUE 0x01
32+
#define FALSE 0x00
33+
34+
// mote state
35+
#define MOTE_STATE_IDLE 0x01
36+
#define MOTE_STATE_SEARCHING 0x02
37+
#define MOTE_STATE_NEGOCIATING 0x03
38+
#define MOTE_STATE_CONNECTED 0x04
39+
#define MOTE_STATE_OPERATIONAL 0x05
40+
41+
// service types
42+
#define SERVICE_TYPE_BW 0x00
43+
44+
#define IPv6ADDR_LEN 16
45+
#define DEFAULT_SOCKETID 22
46+
47+
//===== fsm
48+
49+
#define CMD_PERIOD 1000 // number of ms between two commands being sent
50+
#define SERIAL_RESPONSE_TIMEOUT 500 // max number of ms to wait for response
51+
52+
//=========================== typedef =========================================
53+
54+
class IpMtWrapper; // forward declaration needed here
55+
56+
typedef void (IpMtWrapper::*fsm_timer_callback)(void);
57+
typedef void (IpMtWrapper::*fsm_reply_callback)(void);
58+
typedef void (*data_generator)(uint16_t* returnVal);
59+
60+
//=========================== IpMtWrapper object ==============================
61+
62+
class IpMtWrapper {
63+
public:
64+
//===== methods
65+
IpMtWrapper();
66+
void setup(
67+
uint16_t srcPort,
68+
uint8_t* destAddr,
69+
uint16_t destPort,
70+
TIME_T dataPeriod,
71+
data_generator dataGenerator
72+
);
73+
void loop();
74+
//===== attributes
75+
//===== methods
76+
//=== fsm
77+
void fsm_scheduleEvent(uint16_t delay, fsm_timer_callback cb);
78+
void fsm_cancelEvent();
79+
void fsm_setCallback(fsm_reply_callback cb);
80+
//=== api
81+
void api_response_timeout();
82+
void api_getMoteStatus();
83+
void api_getMoteStatus_reply();
84+
void api_openSocket();
85+
void api_openSocket_reply();
86+
void api_bindSocket();
87+
void api_bindSocket_reply();
88+
void api_join();
89+
void api_join_reply();
90+
void api_getServiceInfo();
91+
void api_getServiceInfo_reply();
92+
void api_requestService();
93+
void api_requestService_reply();
94+
void api_sendTo();
95+
void api_sendTo_reply();
96+
//=== helpers
97+
void printState(uint8_t state);
98+
void printByteArray(uint8_t* payload, uint8_t length);
99+
private:
100+
//===== attributes
101+
102+
};
103+
104+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Arduino library which generates a "triangle" signal.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#include "Arduino.h"
10+
#include "TriangleGenerator.h"
11+
12+
//########################### public ##########################################
13+
14+
/**
15+
\brief Constructor.
16+
*/
17+
TriangleGenerator::TriangleGenerator() {
18+
}
19+
20+
/**
21+
\brief Get the next value.
22+
*/
23+
void TriangleGenerator::nextValue(uint16_t* returnVal) {
24+
uint16_t newValue;
25+
26+
// decide whether to go up or down
27+
if (counter==0) {
28+
direction = DIRECTION_UP;
29+
}
30+
if (counter==NUM_STEPS-1) {
31+
direction = DIRECTION_DOWN;
32+
}
33+
34+
// calculate new value
35+
if (direction==DIRECTION_UP) {
36+
counter++;
37+
} else {
38+
counter--;
39+
}
40+
*returnVal = 0x10000/NUM_STEPS;
41+
*returnVal *= counter;
42+
}
43+
44+
//########################### private #########################################
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Arduino library which generates a "triangle" signal.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#ifndef TriangleGenerator_h
10+
#define TriangleGenerator_h
11+
12+
#include <Arduino.h>
13+
14+
//=========================== defines =========================================
15+
16+
#define NUM_STEPS 8
17+
#define DIRECTION_UP 1
18+
#define DIRECTION_DOWN 0
19+
20+
//=========================== TriangleGenerator object ========================
21+
22+
class TriangleGenerator {
23+
public:
24+
//===== methods
25+
TriangleGenerator();
26+
void nextValue(uint16_t* returnVal);
27+
//===== attributes
28+
private:
29+
//===== methods
30+
//===== attributes
31+
uint8_t counter;
32+
uint8_t direction;
33+
};
34+
35+
#endif SmartMesh_h
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Arduino sketch which connects to a SmartMesh IP manager, retrieves the list of
5+
motes connected to it, and sets/clears the motes in a round-robin fashion.
6+
7+
Note: before you can run this sketch, you need import the sm_clib
8+
library. To do so:
9+
- double click on this file to open the Arduino IDE
10+
- In Sketch > Import Library... > Add Library..., select navigate to the
11+
sm_clib folder and click open.
12+
13+
Note: before running this sketch:
14+
- configure your SmartMesh IP motes to run in master mode
15+
- Configure the same network ID on all your motes and manager.
16+
- remove the battery from your SmartMesh IP manager, it will be powered by the
17+
Arduino Due.
18+
- Connect your Arduino Due board to your SmartMesh IP manager as detailed in
19+
the documentation.
20+
- make sure the power switch of the SmartMesh IP manager is in the ON position.
21+
- plug the Arduino Due in your computer, using a USB cable connected to the
22+
"programming" USB port.
23+
- Switch on all your motes.
24+
25+
To run this sketch, connect your Arduino Due board to your computer over the
26+
programming USB port, and Select File > Upload.
27+
28+
\license See attached DN_LICENSE.txt.
29+
*/
30+
31+
#include <IpMgWrapper.h>
32+
#include <dn_ipmg.h>
33+
34+
IpMgWrapper ipmgwrapper;
35+
36+
//=========================== "main" ==========================================
37+
38+
void setup() {
39+
ipmgwrapper.setup();
40+
}
41+
42+
void loop() {
43+
ipmgwrapper.loop();
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Arduino sketch which connects to a SmartMesh IP mote and periodically sends a
5+
2-byte value to the manager. You can use the SensorDataReceiver application of
6+
the SmartMesh SDK to see that data arrive.
7+
8+
Note: before you can run this sketch, you need import the sm_clib
9+
library. To do so:
10+
- double click on this file to open the Arduino IDE
11+
- In Sketch > Import Library... > Add Library..., select navigate to the
12+
sm_clib folder and click open.
13+
14+
Note: before running this sketch:
15+
- configure your SmartMesh IP mote to run in slave mode
16+
- on your SmartMesh IP mote, configure the network ID you the mote to connect
17+
to.
18+
- remove the battery from your SmartMesh IP mote, it will be powered by the
19+
Arduino Due
20+
- connect your Arduino Due board to your DC9003 SmartMesh IP mote as detailed
21+
in the documentation.
22+
- make sure the power switch of the DC9003 SmartMesh IP mote is in the ON
23+
position.
24+
25+
To run this sketch, connect your Arduino Due board to your computer, and Select
26+
File > Upload.
27+
28+
\license See attached DN_LICENSE.txt.
29+
*/
30+
31+
#include <IpMtWrapper.h>
32+
#include <TriangleGenerator.h>
33+
#include <dn_ipmt.h>
34+
35+
IpMtWrapper ipmtwrapper;
36+
TriangleGenerator generator;
37+
38+
//=========================== data generator ==================================
39+
40+
void generateData(uint16_t* returnVal) {
41+
generator.nextValue(returnVal);
42+
}
43+
44+
//=========================== "main" ==========================================
45+
46+
void setup() {
47+
ipmtwrapper.setup(
48+
60000, // srcPort
49+
(uint8_t*)ipv6Addr_manager, // destAddr
50+
61000, // destPort
51+
10000, // dataPeriod (ms)
52+
generateData // dataGenerator
53+
);
54+
}
55+
56+
void loop() {
57+
ipmtwrapper.loop();
58+
}

‎sm_clib/dn_clib_build.h

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
* DO NOT EDIT! Automatically generated by SCons.
3+
*/
4+
5+
enum {
6+
// This is the build number used on the next release.
7+
VER_BUILD = 2
8+
};

‎sm_clib/dn_clib_version.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef DN_CLIB_VERSION_H
2+
#define DN_CLIB_VERSION_H
3+
4+
#include "dn_clib_build.h"
5+
6+
enum {
7+
VER_MAJOR = 1,
8+
VER_MINOR = 0,
9+
VER_PATCH = 0,
10+
};
11+
12+
#endif

‎sm_clib/dn_common.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Commmon definitions.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#ifndef DN_COMMON_H
10+
#define DN_COMMON_H
11+
12+
#include "inttypes.h"
13+
#include <stdbool.h>
14+
#include <string.h>
15+
16+
//=========================== defines =========================================
17+
18+
#ifndef TRUE
19+
#define TRUE 1
20+
#endif
21+
22+
#ifndef FALSE
23+
#define FALSE 0
24+
#endif
25+
26+
// error codes
27+
typedef enum {
28+
DN_ERR_NONE = 0,
29+
DN_ERR_BUSY,
30+
DN_ERR_NOT_CONNECTED, // only used in SmartMesh IP Manager
31+
DN_ERR_ALREADY,
32+
DN_ERR_MALFORMED
33+
} dn_err_t;
34+
35+
//=== API return type
36+
37+
//=========================== typedef =========================================
38+
39+
#endif

‎sm_clib/dn_endianness.h

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
\license See attached DN_LICENSE.txt.
5+
*/
6+
7+
#ifndef DN_ENDIANNESS_H
8+
#define DN_ENDIANNESS_H
9+
10+
#include "dn_common.h"
11+
12+
//=========================== defined =========================================
13+
14+
//=========================== typedef =========================================
15+
16+
//=========================== variables =======================================
17+
18+
//=========================== prototypes ======================================
19+
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
void dn_write_uint16_t(uint8_t* ptr, uint16_t val);
25+
void dn_write_uint32_t(uint8_t* ptr, uint32_t val);
26+
void dn_read_uint16_t(uint16_t* to, uint8_t* from);
27+
void dn_read_uint32_t(uint32_t* to, uint8_t* from);
28+
29+
#ifdef __cplusplus
30+
}
31+
#endif
32+
33+
#endif

‎sm_clib/dn_hdlc.c

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

‎sm_clib/dn_hdlc.h

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
HDLC library.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#ifndef DN_HDLC_H
10+
#define DN_HDLC_H
11+
12+
#include "dn_common.h"
13+
14+
//=========================== defines =========================================
15+
16+
// this table is used to expedite execution (at the expense of memory usage)
17+
static const uint16_t dn_hdlc_fcstab[256] = {
18+
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
19+
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
20+
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
21+
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
22+
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
23+
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
24+
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
25+
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
26+
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
27+
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
28+
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
29+
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
30+
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
31+
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
32+
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
33+
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
34+
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
35+
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
36+
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
37+
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
38+
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
39+
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
40+
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
41+
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
42+
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
43+
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
44+
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
45+
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
46+
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
47+
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
48+
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
49+
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
50+
};
51+
52+
#define DN_HDLC_FLAG 0x7e
53+
#define DN_HDLC_ESCAPE 0x7d
54+
#define DN_HDLC_ESCAPE_MASK 0x20
55+
#define DN_HDLC_CRCINIT 0xffff
56+
#define DN_HDLC_CRCGOOD 0xf0b8
57+
58+
#define DN_HDLC_MAX_FRAME_LENGTH 128
59+
#define DN_HDLC_INPUT_BUFFER_SIZE DN_HDLC_MAX_FRAME_LENGTH
60+
61+
//=========================== typedef =========================================
62+
63+
typedef void (*dn_hdlc_rxFrame_cbt)(uint8_t* rxFrame, uint8_t rxFrameLen);
64+
65+
//=========================== variables =======================================
66+
67+
//=========================== prototypes ======================================
68+
69+
#ifdef __cplusplus
70+
extern "C" {
71+
#endif
72+
73+
void dn_hdlc_init(dn_hdlc_rxFrame_cbt rxFrame_cb);
74+
// output
75+
inline void dn_hdlc_outputOpen();
76+
inline void dn_hdlc_outputWrite(uint8_t b);
77+
inline void dn_hdlc_outputClose();
78+
79+
#ifdef __cplusplus
80+
}
81+
#endif
82+
83+
#endif

‎sm_clib/dn_ipmg.c

+4,095
Large diffs are not rendered by default.

‎sm_clib/dn_ipmg.h

+1,179
Large diffs are not rendered by default.

‎sm_clib/dn_ipmt.c

+4,205
Large diffs are not rendered by default.

‎sm_clib/dn_ipmt.h

+823
Large diffs are not rendered by default.

‎sm_clib/dn_lock.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
\license See attached DN_LICENSE.txt.
5+
*/
6+
7+
#ifndef DN_LOCK_H
8+
#define DN_LOCK_H
9+
10+
#include "dn_common.h"
11+
12+
//=========================== defined =========================================
13+
14+
//=========================== typedef =========================================
15+
16+
//=========================== variables =======================================
17+
18+
//=========================== prototypes ======================================
19+
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
void dn_lock();
25+
void dn_unlock();
26+
27+
#ifdef __cplusplus
28+
}
29+
#endif
30+
31+
#endif

‎sm_clib/dn_serial_mg.c

+256
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
HDLC library.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#include "dn_serial_mg.h"
10+
#include "dn_hdlc.h"
11+
12+
//=========================== variables =======================================
13+
14+
typedef struct {
15+
// admin
16+
uint8_t status;
17+
// packet IDs
18+
uint8_t txPacketId;
19+
bool rxPacketIdInit;
20+
uint8_t rxPacketId;
21+
// reply callback
22+
uint8_t replyCmdId;
23+
dn_serial_reply_cbt replyCb;
24+
// callbacks
25+
dn_serial_request_cbt requestCb;
26+
dn_status_change_cbt statusChangeCb;
27+
} dn_serial_mg_vars_t;
28+
29+
dn_serial_mg_vars_t dn_serial_mg_vars;
30+
31+
//=========================== prototype =======================================
32+
33+
dn_err_t dn_serial_sendRequestNoCheck(
34+
uint8_t cmdId,
35+
bool isAck,
36+
bool shouldBeAcked,
37+
uint8_t* payload,
38+
uint8_t length,
39+
dn_serial_reply_cbt replyCb
40+
);
41+
void dn_serial_mg_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen);
42+
void dn_serial_mg_dispatch_response(uint8_t cmdId, uint8_t *payload, uint8_t length);
43+
44+
//=========================== public ==========================================
45+
46+
/**
47+
\brief Setting up the instance.
48+
*/
49+
void dn_serial_mg_init(dn_serial_request_cbt requestCb, dn_status_change_cbt statusChangeCb) {
50+
// reset local variables
51+
memset(&dn_serial_mg_vars, 0, sizeof(dn_serial_mg_vars));
52+
53+
// initialize variables
54+
dn_serial_mg_vars.txPacketId = 0x00;
55+
dn_serial_mg_vars.rxPacketIdInit = FALSE;
56+
dn_serial_mg_vars.rxPacketId = 0x00;
57+
58+
dn_serial_mg_vars.requestCb = requestCb;
59+
dn_serial_mg_vars.statusChangeCb = statusChangeCb;
60+
61+
// initialize the HDLC module
62+
dn_hdlc_init(dn_serial_mg_rxHdlcFrame);
63+
}
64+
65+
dn_err_t dn_serial_mg_initiateConnect() {
66+
uint8_t payload[3];
67+
68+
// prepare hello packet
69+
payload[0] = DN_API_VERSION; // version
70+
payload[1] = dn_serial_mg_vars.txPacketId; // cliSeqNo
71+
payload[2] = 0; // mode
72+
73+
// send hello packet
74+
dn_serial_sendRequestNoCheck(
75+
SERIAL_CMID_HELLO, // cmdId
76+
FALSE, // isAck
77+
FALSE, // shouldBeAcked
78+
payload, // payload
79+
sizeof(payload), // length
80+
NULL // replyCb
81+
);
82+
83+
// remember state
84+
dn_serial_mg_vars.status = DN_SERIAL_ST_HELLO_SENT;
85+
86+
return DN_ERR_NONE;
87+
}
88+
89+
dn_err_t dn_serial_mg_sendRequest(uint8_t cmdId, bool isAck, uint8_t* payload, uint8_t length, dn_serial_reply_cbt replyCb) {
90+
// abort if not connected
91+
if (dn_serial_mg_vars.status!=DN_SERIAL_ST_CONNECTED) {
92+
return DN_ERR_NOT_CONNECTED;
93+
}
94+
95+
// send the request
96+
return dn_serial_sendRequestNoCheck(
97+
cmdId, // cmdId
98+
isAck, // isAck
99+
!isAck, // shouldBeAcked
100+
payload, // payload
101+
length, // length
102+
replyCb // replyCb
103+
);
104+
}
105+
106+
//=========================== private =========================================
107+
108+
dn_err_t dn_serial_sendRequestNoCheck(uint8_t cmdId, bool isAck, bool shouldBeAcked, uint8_t* payload, uint8_t length, dn_serial_reply_cbt replyCb) {
109+
uint8_t i;
110+
uint8_t control;
111+
112+
// register reply callback
113+
dn_serial_mg_vars.replyCmdId = cmdId;
114+
dn_serial_mg_vars.replyCb = replyCb;
115+
116+
// create the control byte
117+
control = 0;
118+
if (isAck==1) {
119+
control |= DN_SERIAL_FLAG_ACK;
120+
} else {
121+
control |= DN_SERIAL_FLAG_DATA;
122+
}
123+
if (shouldBeAcked==1) {
124+
control |= DN_SERIAL_FLAG_ACKNOWLEDGED;
125+
} else {
126+
control |= DN_SERIAL_FLAG_UNACKNOWLEDGED;
127+
}
128+
129+
// send the frame over serial
130+
dn_hdlc_outputOpen();
131+
dn_hdlc_outputWrite(control); // Control
132+
dn_hdlc_outputWrite(cmdId); // Packet Type
133+
dn_hdlc_outputWrite(dn_serial_mg_vars.txPacketId); // Seq. Number
134+
dn_hdlc_outputWrite(length); // Payload Length
135+
for (i=0; i<length; i++) { // Payload
136+
dn_hdlc_outputWrite(payload[i]);
137+
}
138+
dn_hdlc_outputClose();
139+
140+
// increment the txPacketId
141+
dn_serial_mg_vars.txPacketId++;
142+
143+
return DN_ERR_NONE;
144+
}
145+
146+
void dn_serial_mg_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen) {
147+
// fields in the serial API header
148+
uint8_t control;
149+
uint8_t cmdId;
150+
uint8_t seqNum;
151+
uint8_t length;
152+
uint8_t* payload;
153+
// misc
154+
uint8_t isAck;
155+
uint8_t shouldAck;
156+
uint8_t isRepeatId;
157+
158+
// assert length is OK
159+
if (rxFrameLen<4) {
160+
return;
161+
}
162+
163+
// parse header
164+
control = rxFrame[0];
165+
cmdId = rxFrame[1];
166+
seqNum = rxFrame[2];
167+
length = rxFrame[3];
168+
payload = &rxFrame[4];
169+
isAck = ((control & DN_SERIAL_FLAG_ACK)!=0);
170+
shouldAck = ((control & DN_SERIAL_FLAG_ACKNOWLEDGED)!=0);
171+
172+
// check if valid packet ID
173+
if (isAck) {
174+
// ACK, dispatch
175+
176+
if (length>0) {
177+
dn_serial_mg_dispatch_response(cmdId,payload,length);
178+
}
179+
} else {
180+
// DATA
181+
182+
if (dn_serial_mg_vars.rxPacketIdInit==TRUE && seqNum==dn_serial_mg_vars.rxPacketId) {
183+
isRepeatId = TRUE;
184+
} else {
185+
isRepeatId = FALSE;
186+
dn_serial_mg_vars.rxPacketIdInit = TRUE;
187+
dn_serial_mg_vars.rxPacketId = seqNum;
188+
}
189+
190+
// ACK
191+
if (shouldAck) {
192+
dn_hdlc_outputOpen();
193+
dn_hdlc_outputWrite(DN_SERIAL_FLAG_ACK | DN_SERIAL_FLAG_UNACKNOWLEDGED); // Control
194+
dn_hdlc_outputWrite(cmdId); // Packet Type
195+
dn_hdlc_outputWrite(dn_serial_mg_vars.rxPacketId); // Seq. Number
196+
dn_hdlc_outputWrite(1); // Payload Length
197+
dn_hdlc_outputWrite(0); // Payload (RC==0x00)
198+
dn_hdlc_outputClose();
199+
}
200+
201+
switch (cmdId) {
202+
case SERIAL_CMID_HELLO_RESPONSE:
203+
if (
204+
length>=5 &&
205+
payload[HELLO_RESP_OFFS_RC] == 0 &&
206+
payload[HELLO_RESP_OFFS_VERSION] == DN_API_VERSION
207+
) {
208+
// change state
209+
dn_serial_mg_vars.status = DN_SERIAL_ST_CONNECTED;
210+
// record manager sequence number
211+
dn_serial_mg_vars.rxPacketIdInit = TRUE;
212+
dn_serial_mg_vars.rxPacketId = payload[HELLO_RESP_OFFS_MGRSEQNO];
213+
// indicate state change
214+
if (dn_serial_mg_vars.statusChangeCb) {
215+
dn_serial_mg_vars.statusChangeCb(dn_serial_mg_vars.status);
216+
}
217+
};
218+
break;
219+
case SERIAL_CMID_MGR_HELLO:
220+
if (
221+
length>=2
222+
) {
223+
// change state
224+
dn_serial_mg_vars.status = DN_SERIAL_ST_DISCONNECTED;
225+
// indicate state change
226+
if (dn_serial_mg_vars.statusChangeCb) {
227+
dn_serial_mg_vars.statusChangeCb(dn_serial_mg_vars.status);
228+
}
229+
}
230+
break;
231+
default:
232+
// dispatch
233+
if (length>0 && dn_serial_mg_vars.requestCb!=NULL && isRepeatId==FALSE) {
234+
dn_serial_mg_vars.requestCb(cmdId,control,payload,length);
235+
}
236+
break;
237+
}
238+
}
239+
}
240+
241+
void dn_serial_mg_dispatch_response(uint8_t cmdId, uint8_t* payload, uint8_t length) {
242+
uint8_t rc;
243+
244+
rc = payload[0];
245+
if (cmdId==dn_serial_mg_vars.replyCmdId && dn_serial_mg_vars.replyCb!=NULL) {
246+
247+
// call the callback
248+
(dn_serial_mg_vars.replyCb)(cmdId,rc,&payload[1],length-1);
249+
250+
// reset
251+
dn_serial_mg_vars.replyCmdId = 0x00;
252+
dn_serial_mg_vars.replyCb = NULL;
253+
}
254+
}
255+
256+
//=========================== helpers =========================================

‎sm_clib/dn_serial_mg.h

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Serial connector.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#ifndef DN_SERIAL_H
10+
#define DN_SERIAL_H
11+
12+
#include "dn_common.h"
13+
14+
//=========================== defines =========================================
15+
16+
#define DN_SERIAL_API_MASK_RESPONSE 0x01
17+
#define DN_SERIAL_API_MASK_PACKETID 0x02
18+
#define DN_SERIAL_API_MASK_SYNC 0x08
19+
20+
#define DN_SERIAL_FLAG_DATA (0<<0)
21+
#define DN_SERIAL_FLAG_ACK (1<<0)
22+
23+
#define DN_SERIAL_FLAG_UNACKNOWLEDGED (0<<1)
24+
#define DN_SERIAL_FLAG_ACKNOWLEDGED (1<<1)
25+
26+
// return code
27+
#define DN_SERIAL_RC_OK 0x00
28+
29+
// connection states
30+
#define DN_SERIAL_ST_DISCONNECTED 0x00
31+
#define DN_SERIAL_ST_HELLO_SENT 0x01
32+
#define DN_SERIAL_ST_CONNECTED 0x02
33+
34+
#define DN_API_VERSION 4
35+
36+
#define SERIAL_CMID_HELLO 1
37+
#define SERIAL_CMID_HELLO_RESPONSE 2
38+
#define SERIAL_CMID_MGR_HELLO 3
39+
40+
#define HELLO_RESP_OFFS_RC 0
41+
#define HELLO_RESP_OFFS_VERSION 1
42+
#define HELLO_RESP_OFFS_MGRSEQNO 2
43+
#define HELLO_RESP_OFFS_CLISEQNO 3
44+
#define HELLO_RESP_OFFS_MODE 4
45+
46+
//=========================== typedef =========================================
47+
48+
typedef void (*dn_status_change_cbt)(uint8_t newStatus);
49+
typedef void (*dn_serial_request_cbt)(uint8_t cmdId, uint8_t flags, uint8_t* payload, uint8_t len);
50+
typedef void (*dn_serial_reply_cbt)(uint8_t cmdId, uint8_t rc, uint8_t* payload, uint8_t len);
51+
52+
//=========================== variables =======================================
53+
54+
//=========================== prototypes ======================================
55+
56+
void dn_serial_mg_init(dn_serial_request_cbt requestCb, dn_status_change_cbt statusChangeCb);
57+
dn_err_t dn_serial_mg_initiateConnect();
58+
dn_err_t dn_serial_mg_sendRequest(
59+
uint8_t cmdId,
60+
bool isAck,
61+
uint8_t* payload,
62+
uint8_t length,
63+
dn_serial_reply_cbt replyCb
64+
);
65+
66+
#endif

‎sm_clib/dn_serial_mt.c

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
HDLC library.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#include "dn_serial_mt.h"
10+
#include "dn_hdlc.h"
11+
12+
//=========================== variables =======================================
13+
14+
typedef struct {
15+
// packet IDs
16+
uint8_t txPacketId;
17+
uint8_t rxPacketId;
18+
// reply callback
19+
uint8_t replyCmdId;
20+
dn_serial_reply_cbt replyCb;
21+
// request callback
22+
dn_serial_request_cbt requestCb;
23+
} dn_serial_mt_vars_t;
24+
25+
dn_serial_mt_vars_t dn_serial_mt_vars;
26+
27+
//=========================== prototype =======================================
28+
29+
void dn_serial_mt_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen);
30+
void dn_serial_mt_dispatch_response(uint8_t cmdId, uint8_t *payload, uint8_t length);
31+
void dn_serial_sendReply(uint8_t cmdId, uint8_t rc, uint8_t *payload, uint8_t length);
32+
33+
//=========================== public ==========================================
34+
35+
/**
36+
\brief Setting up the instance.
37+
*/
38+
void dn_serial_mt_init(dn_serial_request_cbt requestCb) {
39+
// reset local variables
40+
memset(&dn_serial_mt_vars, 0, sizeof(dn_serial_mt_vars));
41+
42+
// initialize variables
43+
dn_serial_mt_vars.txPacketId = DN_SERIAL_PACKETID_NOTSET;
44+
dn_serial_mt_vars.rxPacketId = DN_SERIAL_PACKETID_NOTSET;
45+
dn_serial_mt_vars.requestCb = requestCb;
46+
47+
// initialize the HDLC module
48+
dn_hdlc_init(dn_serial_mt_rxHdlcFrame);
49+
}
50+
51+
dn_err_t dn_serial_mt_sendRequest(uint8_t cmdId, uint8_t extraFlags, uint8_t* payload, uint8_t length, dn_serial_reply_cbt replyCb) {
52+
uint8_t i;
53+
uint8_t flags;
54+
55+
// register reply callback
56+
dn_serial_mt_vars.replyCmdId = cmdId;
57+
dn_serial_mt_vars.replyCb = replyCb;
58+
59+
// calculate the flags
60+
flags = 0;
61+
if (dn_serial_mt_vars.txPacketId==DN_SERIAL_PACKETID_NOTSET) {
62+
dn_serial_mt_vars.txPacketId = 0x00;
63+
flags |= 0x01<<3; // sync bit
64+
flags |= dn_serial_mt_vars.txPacketId<<1; // txPacketId
65+
} else {
66+
flags |= dn_serial_mt_vars.txPacketId<<1; // txPacketId
67+
}
68+
flags |= extraFlags;
69+
70+
// send the frame over serial
71+
dn_hdlc_outputOpen();
72+
dn_hdlc_outputWrite(cmdId); // cmdId
73+
dn_hdlc_outputWrite(length); // length
74+
dn_hdlc_outputWrite(flags); // flags
75+
for (i=0; i<length; i++) { // payload
76+
dn_hdlc_outputWrite(payload[i]);
77+
}
78+
dn_hdlc_outputClose();
79+
80+
// toggle the txPacketId
81+
if (dn_serial_mt_vars.txPacketId==0x00) {
82+
dn_serial_mt_vars.txPacketId = 0x01;
83+
} else {
84+
dn_serial_mt_vars.txPacketId = 0x00;
85+
}
86+
87+
return DN_ERR_NONE;
88+
}
89+
90+
//=========================== private =========================================
91+
92+
void dn_serial_mt_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen) {
93+
// fields in the serial API header
94+
uint8_t cmdId;
95+
uint8_t length;
96+
uint8_t flags;
97+
uint8_t isResponse;
98+
uint8_t packetId;
99+
// misc
100+
uint8_t isRepeatId;
101+
uint8_t updateRxPacketId;
102+
uint8_t i;
103+
104+
// assert length is OK
105+
if (rxFrameLen<3) {
106+
return;
107+
}
108+
109+
// parse header
110+
cmdId = rxFrame[0];
111+
length = rxFrame[1];
112+
flags = rxFrame[2];
113+
isResponse = ((flags & DN_SERIAL_API_MASK_RESPONSE)!=0);
114+
packetId = ((flags & DN_SERIAL_API_MASK_PACKETID)!=0);
115+
116+
// check if valid packet ID
117+
if (isResponse) {
118+
// dispatch
119+
120+
dn_serial_mt_dispatch_response(cmdId,&rxFrame[3],length);
121+
} else {
122+
if (packetId==dn_serial_mt_vars.rxPacketId) {
123+
isRepeatId = TRUE;
124+
} else {
125+
isRepeatId = FALSE;
126+
dn_serial_mt_vars.rxPacketId = packetId;
127+
}
128+
129+
// ACK
130+
dn_serial_sendReply(cmdId,DN_SERIAL_RC_OK,NULL,0);
131+
132+
// dispatch
133+
if (length>0 && dn_serial_mt_vars.requestCb!=NULL) {
134+
dn_serial_mt_vars.requestCb(cmdId,flags,&rxFrame[3],length);
135+
}
136+
}
137+
}
138+
139+
/**
140+
\note Not public, only used for sending ACK.
141+
*/
142+
void dn_serial_sendReply(uint8_t cmdId, uint8_t rc, uint8_t *payload, uint8_t length) {
143+
uint8_t i;
144+
145+
dn_hdlc_outputOpen();
146+
dn_hdlc_outputWrite(cmdId); // cmdId
147+
dn_hdlc_outputWrite(length); // length
148+
dn_hdlc_outputWrite(DN_SERIAL_API_MASK_RESPONSE | (dn_serial_mt_vars.rxPacketId<<1)); // flags
149+
dn_hdlc_outputWrite(rc); // rc
150+
for (i=0; i<length; i++) { // payload
151+
dn_hdlc_outputWrite(payload[i]);
152+
}
153+
dn_hdlc_outputClose();
154+
}
155+
156+
void dn_serial_mt_dispatch_response(uint8_t cmdId, uint8_t* payload, uint8_t length) {
157+
uint8_t rc;
158+
159+
rc = payload[0];
160+
if (cmdId==dn_serial_mt_vars.replyCmdId && dn_serial_mt_vars.replyCb!=NULL) {
161+
162+
// call the callback
163+
(dn_serial_mt_vars.replyCb)(cmdId,rc,&payload[1],length);
164+
165+
// reset
166+
dn_serial_mt_vars.replyCmdId = 0x00;
167+
dn_serial_mt_vars.replyCb = NULL;
168+
}
169+
}
170+
171+
//=========================== helpers =========================================

‎sm_clib/dn_serial_mt.h

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
Serial connector.
5+
6+
\license See attached DN_LICENSE.txt.
7+
*/
8+
9+
#ifndef DN_SERIAL_H
10+
#define DN_SERIAL_H
11+
12+
#include "dn_common.h"
13+
14+
//=========================== defines =========================================
15+
16+
#define DN_SERIAL_API_MASK_RESPONSE 0x01
17+
#define DN_SERIAL_API_MASK_PACKETID 0x02
18+
#define DN_SERIAL_API_MASK_SYNC 0x08
19+
20+
#define DN_SERIAL_PACKETID_NOTSET 0x02
21+
22+
// return code
23+
#define DN_SERIAL_RC_OK 0x00
24+
25+
//=========================== typedef =========================================
26+
27+
typedef void (*dn_serial_request_cbt)(uint8_t cmdId, uint8_t flags, uint8_t* payload, uint8_t len);
28+
typedef void (*dn_serial_reply_cbt)(uint8_t cmdId, uint8_t rc, uint8_t* payload, uint8_t len);
29+
30+
//=========================== variables =======================================
31+
32+
//=========================== prototypes ======================================
33+
34+
void dn_serial_mt_init(dn_serial_request_cbt requestCb);
35+
dn_err_t dn_serial_mt_sendRequest(
36+
uint8_t cmdId,
37+
uint8_t extraFlags,
38+
uint8_t* payload,
39+
uint8_t length,
40+
dn_serial_reply_cbt replyCb
41+
);
42+
43+
#endif

‎sm_clib/dn_uart.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
Copyright (c) 2014, Dust Networks. All rights reserved.
3+
4+
\license See attached DN_LICENSE.txt.
5+
*/
6+
7+
#ifndef DN_UART_H
8+
#define DN_UART_H
9+
10+
#include "dn_common.h"
11+
12+
//=========================== defined =========================================
13+
14+
//=========================== typedef =========================================
15+
16+
typedef void (*dn_uart_rxByte_cbt)(uint8_t byte);
17+
18+
//=========================== variables =======================================
19+
20+
//=========================== prototypes ======================================
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
void dn_uart_init(dn_uart_rxByte_cbt rxByte_cb);
27+
void dn_uart_txByte(uint8_t byte);
28+
void dn_uart_txFlush();
29+
30+
#ifdef __cplusplus
31+
}
32+
#endif
33+
34+
#endif

‎sm_clib/dn_whmt.c

+5,399
Large diffs are not rendered by default.

‎sm_clib/dn_whmt.h

+956
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.