| 157 |
Kevin |
1 |
#include <xc.h>
|
|
|
2 |
#include <stdio.h>
|
|
|
3 |
#include <string.h>
|
| 155 |
Kevin |
4 |
#include "defines.h"
|
| 158 |
Kevin |
5 |
#include "comm_xbee.h"
|
|
|
6 |
#include "base_UART.h"
|
| 155 |
Kevin |
7 |
|
| 157 |
Kevin |
8 |
static XBEE_DATA *xbee_data_p;
|
| 155 |
Kevin |
9 |
static void *xbee_data_frame;
|
| 158 |
Kevin |
10 |
//static void *xbee_frame;
|
| 155 |
Kevin |
11 |
|
|
|
12 |
/* Initialize variables used by this library */
|
| 157 |
Kevin |
13 |
void XBee_Init(XBEE_DATA *data) {
|
|
|
14 |
xbee_data_p = data;
|
| 155 |
Kevin |
15 |
XBEE_CTS_TRIS = 1; // RB0 is CTS, set by XBee chip
|
|
|
16 |
XBEE_RTS_TRIS = 0; // RB1 is RTS, set by PIC
|
|
|
17 |
|
|
|
18 |
XBEE_CTS_LAT = 0; // Pin set high to signal stop sending data to XBee
|
|
|
19 |
XBEE_RTS_LAT = 0; // Pin set high to indicate stop sending data to PIC
|
|
|
20 |
|
|
|
21 |
xbee_data_p->dataind = 0;
|
|
|
22 |
xbee_data_p->checksum_sum = 0;
|
|
|
23 |
xbee_data_p->frame_rdy = 0;
|
|
|
24 |
xbee_data_p->escape_flag = 0;
|
|
|
25 |
xbee_data_p->read_state = XBEE_STATE_READ_START;
|
|
|
26 |
|
|
|
27 |
// memset(&xbee_data, 0, 32);
|
|
|
28 |
|
|
|
29 |
// Grab a pointer to where the unique frame array starts
|
|
|
30 |
xbee_data_frame = &(xbee_data_p->rcv_frame.FRAME);
|
| 158 |
Kevin |
31 |
// xbee_frame = &(xbee_data_p->rcv_frame);
|
| 155 |
Kevin |
32 |
}
|
|
|
33 |
|
|
|
34 |
/* Here we handle the serial input from the UART interrupt */
|
| 157 |
Kevin |
35 |
void XBee_Serial_In(char c) {
|
| 155 |
Kevin |
36 |
// For some reason writing the length straight to xbee_data doesnt seem to work
|
|
|
37 |
// so we work around it by pointing to the length bytes directly
|
| 158 |
Kevin |
38 |
// XBEE_ADDRESS_16 *length = xbee_frame + 1;
|
| 155 |
Kevin |
39 |
|
|
|
40 |
#ifdef XBEE_USE_ESCAPE_CHAR
|
|
|
41 |
if (c == XBEE_ESCAPE_CHAR) {
|
|
|
42 |
// Next byte needs is an escaped char
|
|
|
43 |
xbee_data_p->escape_flag = 1;
|
|
|
44 |
return;
|
|
|
45 |
}
|
|
|
46 |
|
|
|
47 |
if (xbee_data_p->escape_flag) {
|
|
|
48 |
// XOR byte with 0x20 to get escaped char
|
|
|
49 |
c ^= XBEE_ESCAPE_VAL;
|
|
|
50 |
xbee_data_p->escape_flag = 0;
|
|
|
51 |
}
|
|
|
52 |
#endif
|
|
|
53 |
// Reset on start bit and start saving data
|
|
|
54 |
if (c == XBEE_START_DELIMITER) {
|
|
|
55 |
// On detect start delimiter, clear out initial array
|
|
|
56 |
xbee_data_p->dataind = 0;
|
|
|
57 |
xbee_data_p->checksum_sum = 0;
|
|
|
58 |
xbee_data_p->frame_rdy = 0;
|
|
|
59 |
xbee_data_p->read_state = XBEE_STATE_READ_LENGTH_HIGH;
|
| 158 |
Kevin |
60 |
// *((char *)xbee_frame) = XBEE_START_DELIMITER;
|
|
|
61 |
xbee_data_p->rcv_frame.start_delimiter = XBEE_START_DELIMITER;
|
|
|
62 |
|
| 155 |
Kevin |
63 |
} else {
|
|
|
64 |
switch (xbee_data_p->read_state) {
|
|
|
65 |
case XBEE_STATE_READ_START:
|
|
|
66 |
// Do nothing and wait till start bit is read
|
|
|
67 |
break;
|
|
|
68 |
case XBEE_STATE_READ_LENGTH_HIGH:
|
|
|
69 |
// Read length (MSB)
|
| 158 |
Kevin |
70 |
// length->INT_16.char_value[1] = c;
|
|
|
71 |
xbee_data_p->rcv_frame.length.INT_16.char_value[1] = c;
|
| 155 |
Kevin |
72 |
xbee_data_p->read_state = XBEE_STATE_READ_LENGTH_LOW;
|
|
|
73 |
break;
|
|
|
74 |
case XBEE_STATE_READ_LENGTH_LOW:
|
|
|
75 |
// Read length (LSB)
|
| 158 |
Kevin |
76 |
// length->INT_16.char_value[0] = c;
|
|
|
77 |
xbee_data_p->rcv_frame.length.INT_16.char_value[0] = c;
|
| 155 |
Kevin |
78 |
xbee_data_p->read_state = XBEE_STATE_READ_FRAME_DATA;
|
|
|
79 |
break;
|
|
|
80 |
case XBEE_STATE_READ_FRAME_DATA:
|
|
|
81 |
// Read unique frame data
|
|
|
82 |
if (xbee_data_p->dataind < xbee_data_p->rcv_frame.length.INT_16.int_value) {
|
|
|
83 |
*((char*) xbee_data_frame + xbee_data_p->dataind) = c;
|
|
|
84 |
xbee_data_p->checksum_sum += c;
|
|
|
85 |
xbee_data_p->dataind++;
|
|
|
86 |
}
|
|
|
87 |
// If total length is read, the next byte is the expected checksum
|
|
|
88 |
if (xbee_data_p->dataind == xbee_data_p->rcv_frame.length.INT_16.int_value) {
|
|
|
89 |
xbee_data_p->read_state = XBEE_STATE_READ_CHECKSUM;
|
|
|
90 |
}
|
|
|
91 |
break;
|
|
|
92 |
case XBEE_STATE_READ_CHECKSUM:
|
|
|
93 |
// Calculate and compare checksum
|
|
|
94 |
if (0xFF - xbee_data_p->checksum_sum == c) {
|
|
|
95 |
// Frame was recieved successfully
|
|
|
96 |
xbee_data_p->frame_rdy = 1;
|
|
|
97 |
// XBee_Process_Received_Frame();
|
|
|
98 |
} else {
|
|
|
99 |
// If checksum does not match, drop frame
|
| 157 |
Kevin |
100 |
char output[32];
|
|
|
101 |
sprintf(output, "XBEE: checksum mismatch\r\n");
|
|
|
102 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
103 |
}
|
|
|
104 |
xbee_data_p->read_state = XBEE_STATE_READ_START;
|
|
|
105 |
break;
|
|
|
106 |
}
|
|
|
107 |
}
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
/* This processes the frame data within the interrupt. Dont use this. */
|
|
|
111 |
void XBee_Process_Received_Frame() {
|
|
|
112 |
// DBG_PRINT_XBEE("Length: %d\r\n", xbee_data_p->rcv_frame.length.INT_16.int_value);
|
|
|
113 |
// Here we process the received frame depending on the frame type
|
| 157 |
Kevin |
114 |
char output[64];
|
|
|
115 |
switch (*((char *) xbee_data_frame)) {
|
| 155 |
Kevin |
116 |
case XBEE_RX_AT_COMMAND_RESPONSE:
|
| 157 |
Kevin |
117 |
sprintf(output, "XBEE: parsing recieved AT command response frame\r\n");
|
|
|
118 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
119 |
break;
|
|
|
120 |
case XBEE_RX_DATA_PACKET:
|
| 157 |
Kevin |
121 |
sprintf(output, "XBEE: parsing recieved data frame\r\n");
|
|
|
122 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
123 |
break;
|
|
|
124 |
case XBEE_RX_DATA_TX_STATUS:
|
| 157 |
Kevin |
125 |
sprintf(output, "XBEE: parsing recieved TX status frame\r\n");
|
|
|
126 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
127 |
break;
|
|
|
128 |
case XBEE_RX_IO_DATA_SAMPLE:
|
| 157 |
Kevin |
129 |
sprintf(output, "XBEE: parsing recieved IO data sample frame\r\n");
|
|
|
130 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
131 |
break;
|
|
|
132 |
case XBEE_RX_EXPLICIT_COMMAND:
|
| 157 |
Kevin |
133 |
sprintf(output, "XBEE: parsing recieved explicit command frame\r\n");
|
|
|
134 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
135 |
break;
|
|
|
136 |
case XBEE_RX_REMOTE_AT_COMMAND_RESPONSE:
|
| 157 |
Kevin |
137 |
sprintf(output, "XBEE: parsing recieved remote AT command frame\r\n");
|
|
|
138 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
139 |
break;
|
|
|
140 |
case XBEE_RX_ROUTE_RECORD:
|
| 157 |
Kevin |
141 |
sprintf(output, "XBEE: parsing recieved route record frame\r\n");
|
|
|
142 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
143 |
break;
|
|
|
144 |
case XBEE_RX_NODE_IDENTIFICATION:
|
| 157 |
Kevin |
145 |
sprintf(output, "XBEE: parsing recieved node identification frame\r\n");
|
|
|
146 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
147 |
break;
|
|
|
148 |
case XBEE_RX_FRAME_MODEM_STATUS:
|
| 157 |
Kevin |
149 |
sprintf(output, "XBEE: parsing recieved modem status frame\r\n");
|
|
|
150 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
151 |
break;
|
|
|
152 |
default:
|
| 157 |
Kevin |
153 |
sprintf(output, "XBEE: (ERROR) unrecognized frame type\r\n");
|
|
|
154 |
DBG_PRINT_XBEE(output, strlen(output));
|
| 155 |
Kevin |
155 |
}
|
|
|
156 |
}
|
|
|
157 |
|
| 157 |
Kevin |
158 |
unsigned int XBee_Get_Received_Frame(char *frame) {
|
| 155 |
Kevin |
159 |
if (!xbee_data_p->frame_rdy) {
|
|
|
160 |
return 0;
|
|
|
161 |
} else {
|
|
|
162 |
memcpy(frame, xbee_data_frame, xbee_data_p->rcv_frame.length.INT_16.int_value);
|
|
|
163 |
xbee_data_p->frame_rdy = 0; // Reset frame ready status
|
|
|
164 |
return xbee_data_p->rcv_frame.length.INT_16.int_value;
|
|
|
165 |
}
|
|
|
166 |
}
|
|
|
167 |
|
| 157 |
Kevin |
168 |
void XBee_Process_Transmit_Frame(char *data, char length) {
|
| 155 |
Kevin |
169 |
#ifdef XBEE_USE_ESCAPE_CHAR
|
|
|
170 |
unsigned int i = 0;
|
| 157 |
Kevin |
171 |
char chksum = 0;
|
| 155 |
Kevin |
172 |
|
|
|
173 |
// Write the start bit and length
|
|
|
174 |
UART1_WriteC(XBEE_START_DELIMITER);
|
|
|
175 |
UART1_WriteC(0);
|
|
|
176 |
UART1_WriteC(length);
|
|
|
177 |
|
|
|
178 |
// Write the frame data
|
|
|
179 |
for (i = 0; i < length; i++) {
|
|
|
180 |
chksum += data[i];
|
|
|
181 |
if (data[i] == XBEE_START_DELIMITER || \
|
|
|
182 |
data[i] == XBEE_ESCAPE_CHAR || \
|
|
|
183 |
data[i] == XBEE_XON || \
|
|
|
184 |
data[i] == XBEE_XOFF) {
|
|
|
185 |
UART1_WriteC(XBEE_ESCAPE_CHAR);
|
|
|
186 |
UART1_WriteC(data[i] ^ XBEE_ESCAPE_VAL);
|
|
|
187 |
} else {
|
|
|
188 |
UART1_WriteC(data[i]);
|
|
|
189 |
}
|
|
|
190 |
}
|
|
|
191 |
// Write the checksum
|
|
|
192 |
if (chksum == XBEE_START_DELIMITER || \
|
|
|
193 |
chksum == XBEE_ESCAPE_CHAR || \
|
|
|
194 |
chksum == XBEE_XON || \
|
|
|
195 |
chksum == XBEE_XOFF) {
|
|
|
196 |
UART1_WriteC(XBEE_ESCAPE_CHAR);
|
|
|
197 |
UART1_WriteC(chksum ^ XBEE_ESCAPE_VAL);
|
|
|
198 |
} else {
|
|
|
199 |
UART1_WriteC(0xFF - chksum);
|
|
|
200 |
}
|
|
|
201 |
#else
|
|
|
202 |
unsigned int i = 0;
|
| 157 |
Kevin |
203 |
char chksum = 0;
|
| 155 |
Kevin |
204 |
|
|
|
205 |
UART1_WriteC(XBEE_START_DELIMITER);
|
|
|
206 |
UART1_WriteC(0);
|
|
|
207 |
UART1_WriteC(length);
|
|
|
208 |
for (i = 0; i < length; i++) {
|
|
|
209 |
chksum += data[i];
|
|
|
210 |
UART1_WriteC(data[i]);
|
|
|
211 |
}
|
|
|
212 |
UART1_WriteC(0xFF - chksum);
|
|
|
213 |
#endif
|
|
|
214 |
}
|
|
|
215 |
|
| 157 |
Kevin |
216 |
void XBee_Set_RTS(char c) {
|
| 155 |
Kevin |
217 |
if (c) {
|
|
|
218 |
XBEE_RTS_LAT = 1; // Set high to stop receiving data
|
|
|
219 |
} else {
|
|
|
220 |
XBEE_RTS_LAT = 0; // Set low to resume receiving data
|
|
|
221 |
}
|
|
|
222 |
}
|
|
|
223 |
|
| 157 |
Kevin |
224 |
char XBee_Read_CTS() {
|
|
|
225 |
char c = XBEE_CTS_PORT;
|
| 155 |
Kevin |
226 |
if (c) {
|
|
|
227 |
return 0x1; // High indicates stop sending data
|
|
|
228 |
} else {
|
|
|
229 |
return 0x0; // Low indicates ok to send data
|
|
|
230 |
}
|
|
|
231 |
}
|
|
|
232 |
|
|
|
233 |
void XBee_Convert_Endian_64(XBEE_ADDRESS_64 *src) {
|
|
|
234 |
char tmp[2];
|
|
|
235 |
tmp[0] = src->UPPER_32.char_value[3];
|
|
|
236 |
tmp[1] = src->UPPER_32.char_value[2];
|
|
|
237 |
src->UPPER_32.char_value[3] = src->UPPER_32.char_value[0];
|
|
|
238 |
src->UPPER_32.char_value[2] = src->UPPER_32.char_value[1];
|
|
|
239 |
src->UPPER_32.char_value[1] = tmp[1];
|
|
|
240 |
src->UPPER_32.char_value[0] = tmp[0];
|
|
|
241 |
|
|
|
242 |
tmp[0] = src->LOWER_32.char_value[3];
|
|
|
243 |
tmp[1] = src->LOWER_32.char_value[2];
|
|
|
244 |
src->LOWER_32.char_value[3] = src->LOWER_32.char_value[0];
|
|
|
245 |
src->LOWER_32.char_value[2] = src->LOWER_32.char_value[1];
|
|
|
246 |
src->LOWER_32.char_value[1] = tmp[1];
|
|
|
247 |
src->LOWER_32.char_value[0] = tmp[0];
|
|
|
248 |
}
|
|
|
249 |
|
|
|
250 |
void XBee_Convert_Endian_16(XBEE_ADDRESS_16 *src) {
|
|
|
251 |
char tmp;
|
|
|
252 |
tmp = src->INT_16.char_value[0];
|
|
|
253 |
src->INT_16.char_value[0] = src->INT_16.char_value[1];
|
|
|
254 |
src->INT_16.char_value[1] = tmp;
|
|
|
255 |
}
|