root / branches / wireless / code / projects / libwireless / wireless_send.c @ 1935
History | View | Annotate | Download (16.5 KB)
1 | 1576 | dsschult | /**
|
---|---|---|---|
2 | * Copyright (c) 2009 Colony Project
|
||
3 | *
|
||
4 | * Permission is hereby granted, free of charge, to any person
|
||
5 | * obtaining a copy of this software and associated documentation
|
||
6 | * files (the "Software"), to deal in the Software without
|
||
7 | * restriction, including without limitation the rights to use,
|
||
8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
9 | * copies of the Software, and to permit persons to whom the
|
||
10 | * Software is furnished to do so, subject to the following
|
||
11 | * conditions:
|
||
12 | *
|
||
13 | * The above copyright notice and this permission notice shall be
|
||
14 | * included in all copies or substantial portions of the Software.
|
||
15 | *
|
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||
18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||
20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
23 | * OTHER DEALINGS IN THE SOFTWARE.
|
||
24 | **/
|
||
25 | |||
26 | /**
|
||
27 | * @file wireless_send.c
|
||
28 | * @brief Wireless library send functions
|
||
29 | *
|
||
30 | * Implementation of high level wireless communication.
|
||
31 | * This is the send functions portion of the library.
|
||
32 | *
|
||
33 | * @author Colony Project, CMU Robotics Club
|
||
34 | **/
|
||
35 | |||
36 | #include "wl_defs.h" |
||
37 | #include "wireless.h" |
||
38 | 1608 | dsschult | #include "xbee.h" |
39 | 1587 | dsschult | #include <string.h> |
40 | 1576 | dsschult | |
41 | |||
42 | 1588 | dsschult | /**
|
43 | 1591 | dsschult | * Definition for wireless library send packet structure
|
44 | 1604 | dsschult | * byte 1: length of packet (from frame number to end of data)
|
45 | 1588 | dsschult | * byte 2: frame number
|
46 | 1604 | dsschult | * bytes 3-n: data (dest, options, frame number, group code, packet)
|
47 | * byte n+1: num retries
|
||
48 | 1587 | dsschult | *
|
49 | * Definition for ack buffer
|
||
50 | * 2 bit system: 0=still sending
|
||
51 | * 1=OK
|
||
52 | * 2=ack failure
|
||
53 | * 3=CCA failure
|
||
54 | 1588 | dsschult | **/
|
55 | 1587 | dsschult | |
56 | |||
57 | /* global variables */
|
||
58 | 1600 | dsschult | uint8_t nextframe = 1; // number of next frame |
59 | uint8_t ack_buf[64]; // ack buffer (holds 255 packet return codes) |
||
60 | uint8_t send_buf[PACKET_BUFFER_SIZE]; // sending buffer for retries
|
||
61 | uint8_t send_buf_first = 0; // first byte of data on buffer |
||
62 | uint8_t send_buf_last = 0; // next free byte on buffer |
||
63 | 1604 | dsschult | uint8_t send_buf_num_packets = 0; // number of packets in sending buffer |
64 | 1587 | dsschult | |
65 | /* private function prototypes */
|
||
66 | void setack(uint8_t num,uint8_t val);
|
||
67 | 1604 | dsschult | void ackhandle(uint8_t num,uint8_t val);
|
68 | 1608 | dsschult | int8_t send_buf_add(uint8_t *ptr, uint8_t byte); |
69 | 1604 | dsschult | uint8_t send_buf_get(uint8_t *ptr); |
70 | 1587 | dsschult | |
71 | 1576 | dsschult | // the send functions
|
72 | 1577 | dsschult | |
73 | /**
|
||
74 | * @addtogroup wireless Wireless
|
||
75 | * @{
|
||
76 | **/
|
||
77 | |||
78 | |||
79 | /**
|
||
80 | * The core send function. This will take all possible arguments and send all types of packets.
|
||
81 | *
|
||
82 | * @param data pointer to the byte array of data to be included in the packet
|
||
83 | * @param length the length of the data array
|
||
84 | * @param group the packet group of the packet
|
||
85 | 1581 | dsschult | * @param scope flag for sending global packet or your current PAN
|
86 | 1577 | dsschult | * @param dest robot ID (for robot to robot packet)
|
87 | 1581 | dsschult | * @param mode flag for using FAST or RELIABLE sending
|
88 | 1577 | dsschult | *
|
89 | 1620 | alevkoy | * @return positive packet number for tracking acks, or error code
|
90 | 1577 | dsschult | **/
|
91 | 1587 | dsschult | int16_t wl_send(uint8_t *data, uint8_t length, uint8_t group, uint8_t scope, uint16_t dest, uint8_t mode) { |
92 | 1604 | dsschult | uint8_t packet[6];
|
93 | 1772 | dsschult | int16_t ret = WL_SUCCESS; |
94 | 1587 | dsschult | |
95 | 1604 | dsschult | // build packet header
|
96 | 1587 | dsschult | packet[0] = nextframe;
|
97 | 1604 | dsschult | packet[1] = (dest&0xFF00)>>8; |
98 | 1688 | dsschult | packet[2] = dest&0x00FF; |
99 | 1604 | dsschult | packet[3] = XBEE_OPTIONS_NONE;
|
100 | packet[4] = nextframe;
|
||
101 | packet[5] = group;
|
||
102 | 1587 | dsschult | |
103 | 1825 | bwasserm | // set scope, defaults to send to PAN
|
104 | 1587 | dsschult | if (scope == GLOBAL)
|
105 | 1825 | bwasserm | packet[3] |= XBEE_OPTIONS_BROADCAST_ALL_PANS;
|
106 | 1604 | dsschult | else if (scope != PAN) { |
107 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error - bad scope in core send function\r\n");
|
108 | 1604 | dsschult | return WL_ERROR_SCOPE;
|
109 | } |
||
110 | 1600 | dsschult | |
111 | 1825 | bwasserm | // set mode, defaults to RELIABLE
|
112 | 1587 | dsschult | if (mode == FAST) {
|
113 | 1825 | bwasserm | packet[3] |= XBEE_OPTIONS_DISABLE_RESPONSE;
|
114 | 1600 | dsschult | } else if (mode != RELIABLE) { |
115 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error - bad mode in core send function\r\n");
|
116 | 1587 | dsschult | return WL_ERROR_MODE;
|
117 | } |
||
118 | 1604 | dsschult | |
119 | // do checksum
|
||
120 | group = XBEE_FRAME_TX_REQUEST_16; |
||
121 | xbee_checksum_add(packet,6,&group);
|
||
122 | xbee_checksum_add(data,length,&group); |
||
123 | group = 0xFF-group;
|
||
124 | 1576 | dsschult | |
125 | 1587 | dsschult | // send the packet
|
126 | 1646 | dsschult | if (xbee_send_header(length+7) != WL_SUCCESS) { |
127 | 1662 | dsschult | WL_DEBUG_PRINT_P("1Error sending packet from core send function\r\n");
|
128 | 1587 | dsschult | return WL_ERROR_SEND;
|
129 | } |
||
130 | 1679 | dsschult | if (xbee_sendc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS) {
|
131 | 1662 | dsschult | WL_DEBUG_PRINT_P("2Error sending packet from core send function\r\n");
|
132 | 1604 | dsschult | return WL_ERROR_SEND;
|
133 | } |
||
134 | if (xbee_send(packet,6) != WL_SUCCESS) { |
||
135 | 1662 | dsschult | WL_DEBUG_PRINT_P("3Error sending packet from core send function\r\n");
|
136 | 1604 | dsschult | return WL_ERROR_SEND;
|
137 | } |
||
138 | if (xbee_send(data,length) != WL_SUCCESS) {
|
||
139 | 1662 | dsschult | WL_DEBUG_PRINT_P("4Error sending packet from core send function\r\n");
|
140 | 1604 | dsschult | return WL_ERROR_SEND;
|
141 | } |
||
142 | 1679 | dsschult | if (xbee_sendc(group) != WL_SUCCESS) {
|
143 | 1662 | dsschult | WL_DEBUG_PRINT_P("5Error sending packet from core send function\r\n");
|
144 | 1604 | dsschult | return WL_ERROR_SEND;
|
145 | } |
||
146 | 1587 | dsschult | |
147 | 1600 | dsschult | // save in ack system
|
148 | 1792 | bwasserm | if (mode == FAST || dest == BROADCAST) {
|
149 | 1600 | dsschult | setack(nextframe,ACK_OK); // assume the send was successful
|
150 | 1608 | dsschult | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
151 | 1772 | dsschult | return ret; // no frame number |
152 | 1600 | dsschult | } else if (mode == RELIABLE) { |
153 | setack(nextframe,SENDING); // set status to SENDING
|
||
154 | 1825 | bwasserm | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
155 | 1604 | dsschult | // save packet on sending buffer
|
156 | scope = send_buf_last; // use as ptr to send buffer
|
||
157 | if (send_buf_add(&scope,length+6) != WL_SUCCESS) { // add length |
||
158 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding length to sending buffer\r\n");
|
159 | 1825 | bwasserm | return WL_ERROR_SENDING_BUFFER_FULL;
|
160 | 1604 | dsschult | } |
161 | 1825 | bwasserm | for(mode=0;mode<6;mode++) { // add header //mode is being used as a counter to save space |
162 | 1604 | dsschult | if (send_buf_add(&scope,packet[mode]) != WL_SUCCESS) {
|
163 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding header to sending buffer\r\n");
|
164 | 1825 | bwasserm | return WL_ERROR_SENDING_BUFFER_FULL;
|
165 | 1604 | dsschult | } |
166 | } |
||
167 | 1825 | bwasserm | for(mode=0;mode<length;mode++) { // add data //mode is being used as a counter to save space |
168 | 1604 | dsschult | if (send_buf_add(&scope,data[mode]) != WL_SUCCESS) {
|
169 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding data to sendig buffer\r\n");
|
170 | 1825 | bwasserm | return WL_ERROR_SENDING_BUFFER_FULL;
|
171 | 1604 | dsschult | } |
172 | } |
||
173 | if (send_buf_add(&scope,0) != WL_SUCCESS) { // add num retries=0 |
||
174 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding num_retries to sending buffer\r\n");
|
175 | 1825 | bwasserm | return WL_ERROR_SENDING_BUFFER_FULL;
|
176 | 1604 | dsschult | } |
177 | send_buf_last = scope; |
||
178 | send_buf_num_packets++; |
||
179 | 1770 | dsschult | WL_DEBUG_PRINT_P("send_buf_last:");
|
180 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
181 | WL_DEBUG_PRINT_P("pos:");
|
||
182 | WL_DEBUG_PRINT_INT(scope); |
||
183 | WL_DEBUG_PRINT_P("send_buf_num_packets:");
|
||
184 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
185 | 1608 | dsschult | |
186 | 1772 | dsschult | return (ret == WL_SUCCESS)?packet[0]:ret; // return frame number for ack tracking |
187 | 1600 | dsschult | } |
188 | 1772 | dsschult | return WL_ERROR_SEND; // shouldn't get here, but if it does there's a problem |
189 | 1576 | dsschult | } |
190 | |||
191 | 1577 | dsschult | /**
|
192 | * Wrapper for core send function that will send a global packet across the current channel.
|
||
193 | *
|
||
194 | * @param data pointer to the byte array of data to be included in the packet
|
||
195 | * @param length the length of the data array
|
||
196 | * @param group the packet group of the packet
|
||
197 | *
|
||
198 | 1620 | alevkoy | * @return positive packet number for tracking acks, or error code
|
199 | 1577 | dsschult | **/
|
200 | 1609 | dsschult | int16_t wl_send_global(uint8_t *data, uint8_t length, uint8_t group) { |
201 | 1608 | dsschult | return wl_send(data, length, group, GLOBAL, BROADCAST, RELIABLE);
|
202 | 1576 | dsschult | } |
203 | |||
204 | 1577 | dsschult | /**
|
205 | * Wrapper for core send function that will send a packet across the current channel on the current pan.
|
||
206 | *
|
||
207 | * @param data pointer to the byte array of data to be included in the packet
|
||
208 | * @param length the length of the data array
|
||
209 | * @param group the packet group of the packet
|
||
210 | *
|
||
211 | 1581 | dsschult | * @return positive packet number for tracking acks, or error code (TBD)
|
212 | 1577 | dsschult | **/
|
213 | 1609 | dsschult | int16_t wl_send_pan(uint8_t *data, uint8_t length, uint8_t group) { |
214 | 1608 | dsschult | return wl_send(data, length, group, PAN, BROADCAST, RELIABLE);
|
215 | 1576 | dsschult | } |
216 | |||
217 | 1577 | dsschult | /**
|
218 | * Wrapper for core send function that will send a packet across the current channel to a specific robot.
|
||
219 | *
|
||
220 | * @param data pointer to the byte array of data to be included in the packet
|
||
221 | * @param length the length of the data array
|
||
222 | * @param group the packet group of the packet
|
||
223 | * @param dest robot ID (for robot to robot packet)
|
||
224 | 1581 | dsschult | * @param mode flag for using FAST or RELIABLE sending
|
225 | 1577 | dsschult | *
|
226 | 1581 | dsschult | * @return positive packet number for tracking acks, or error code (TBD)
|
227 | 1577 | dsschult | **/
|
228 | 1609 | dsschult | int16_t wl_send_robot(uint8_t *data, uint8_t length, uint8_t group, uint16_t dest, uint8_t mode) { |
229 | 1608 | dsschult | return wl_send(data, length, group, GLOBAL, dest, mode);
|
230 | 1576 | dsschult | } |
231 | |||
232 | 1577 | dsschult | /**
|
233 | * Default (i.e. basic) send wrapper.
|
||
234 | *
|
||
235 | * @param data pointer to the byte array of data to be included in the packet
|
||
236 | * @param length the length of the data array
|
||
237 | *
|
||
238 | 1581 | dsschult | * @return positive packet number for tracking acks, or error code (TBD)
|
239 | 1577 | dsschult | **/
|
240 | 1609 | dsschult | int16_t wl_send_basic(uint8_t *data, uint8_t length) { |
241 | 1607 | bwasserm | /** Check if it needs to adjust according to data type. **/
|
242 | 1609 | dsschult | return wl_send(data, length, BASIC, GLOBAL, BROADCAST, RELIABLE);
|
243 | 1576 | dsschult | } |
244 | |||
245 | |||
246 | 1577 | dsschult | /**
|
247 | * acknowledgment error
|
||
248 | 1581 | dsschult | * check if any of the packets you have sent have been lost.
|
249 | 1577 | dsschult | *
|
250 | 1581 | dsschult | * note that all other error checking will be handled by library,
|
251 | * so your user behavior won't have to worry about it
|
||
252 | 1577 | dsschult | *
|
253 | 1581 | dsschult | * @return the # of packets lost (up to 255)
|
254 | 1577 | dsschult | **/
|
255 | 1587 | dsschult | uint8_t wl_ack_error(void) {
|
256 | 1772 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_error function");
|
257 | 1825 | bwasserm | uint8_t val=0,i=1;//i=1 because if i=0, then the xbee won't give an ack |
258 | 1587 | dsschult | |
259 | 1825 | bwasserm | for(i = 1; i < 255; i++){ |
260 | if (((ack_buf[i/4])&(0x2<<(i%4))) != 0) // if the ack is in an error state |
||
261 | 1587 | dsschult | val++; |
262 | 1825 | bwasserm | } |
263 | 1772 | dsschult | WL_DEBUG_PRINT_P("|num_errors:");
|
264 | WL_DEBUG_PRINT_INT(val); |
||
265 | WL_DEBUG_PRINT_P("\r\n");
|
||
266 | |||
267 | 1587 | dsschult | return val;
|
268 | 1576 | dsschult | } |
269 | |||
270 | 1581 | dsschult | /**
|
271 | * acknowledgement error check
|
||
272 | * check if a specific packet has been lost
|
||
273 | 1587 | dsschult | * note: buffer will overflow every 255 packets
|
274 | 1581 | dsschult | *
|
275 | 1587 | dsschult | * @param packet packet number
|
276 | 1581 | dsschult | *
|
277 | 1587 | dsschult | * @return {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
|
278 | 1581 | dsschult | **/
|
279 | int8_t wl_ack_check(uint8_t packet) { |
||
280 | 1772 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_check function|ack=");
|
281 | 1587 | dsschult | if (packet == 0) { |
282 | // no ack information here
|
||
283 | 1662 | dsschult | WL_DEBUG_PRINT_P("packet number cannot be 0\r\n");
|
284 | 1587 | dsschult | return WL_ERROR_ARGUMENT;
|
285 | } |
||
286 | |||
287 | 1772 | dsschult | WL_DEBUG_PRINT_HEX(ack_buf[packet/4]&(0x3<<(packet%4))); |
288 | WL_DEBUG_PRINT_P("\r\n");
|
||
289 | |||
290 | 1587 | dsschult | // check ack
|
291 | return ack_buf[packet/4]&(0x3<<(packet%4)); |
||
292 | 1581 | dsschult | } |
293 | |||
294 | /**
|
||
295 | * acknowledgement reset
|
||
296 | * reset the acknowledgement buffer
|
||
297 | 1825 | bwasserm | * TODO: Also needs to reset packet buffer
|
298 | 1581 | dsschult | **/
|
299 | void wl_ack_reset(void) { |
||
300 | 1662 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_reset function\r\n");
|
301 | 1587 | dsschult | memset(ack_buf,0,64); |
302 | 1581 | dsschult | } |
303 | |||
304 | |||
305 | 1577 | dsschult | /**@} **/ //end defgroup |
306 | |||
307 | |||
308 | // Define all private functions down here
|
||
309 | |||
310 | 1587 | dsschult | /*
|
311 | * sets 2 bits in the ack_buf
|
||
312 | *
|
||
313 | * @param num the ack number
|
||
314 | * @param val {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
|
||
315 | */
|
||
316 | void setack(uint8_t num,uint8_t val) {
|
||
317 | 1772 | dsschult | WL_DEBUG_PRINT_P("entering setack function|num=");
|
318 | WL_DEBUG_PRINT_INT(num); |
||
319 | WL_DEBUG_PRINT_P("|val=");
|
||
320 | WL_DEBUG_PRINT_HEX(val); |
||
321 | WL_DEBUG_PRINT_P("\r\n");
|
||
322 | 1587 | dsschult | switch(num%4) { |
323 | case 0: |
||
324 | ack_buf[num/4] &= (0xFC|val); |
||
325 | break;
|
||
326 | case 1: |
||
327 | ack_buf[num/4] &= (0xF3|(val<<2)); |
||
328 | break;
|
||
329 | case 2: |
||
330 | ack_buf[num/4] &= (0xCF|(val<<4)); |
||
331 | break;
|
||
332 | case 3: |
||
333 | ack_buf[num/4] &= (0x3F|(val<<6)); |
||
334 | break;
|
||
335 | } |
||
336 | } |
||
337 | 1577 | dsschult | |
338 | 1591 | dsschult | |
339 | 1825 | bwasserm | /* ack handler
|
340 | *
|
||
341 | * @param num the ack number
|
||
342 | * @param val {SUCCESS,ACK_FAILURE,CCA_FAILURE,PURGED}
|
||
343 | * will be either SUCCESS or FAILURE
|
||
344 | */
|
||
345 | 1591 | dsschult | void ackhandle(uint8_t num,uint8_t val) {
|
346 | 1604 | dsschult | uint8_t len; |
347 | 1769 | dsschult | uint8_t packets = 0;
|
348 | 1789 | dsschult | uint8_t num_packet = 0;
|
349 | 1780 | dsschult | WL_DEBUG_PRINT_P("entering ackhandle function: num:");
|
350 | WL_DEBUG_PRINT_HEX(num); |
||
351 | 1791 | dsschult | WL_DEBUG_PRINT_P("|num_send_packets:");
|
352 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
353 | 1780 | dsschult | WL_DEBUG_PRINT_P("\r\n");
|
354 | 1791 | dsschult | if (send_buf_num_packets == 0) |
355 | return;
|
||
356 | 1591 | dsschult | switch(val) {
|
357 | case 0: |
||
358 | 1768 | dsschult | WL_DEBUG_PRINT_P("ack success\r\n");
|
359 | 1591 | dsschult | // success
|
360 | 1600 | dsschult | setack(num,ACK_OK); // set status code
|
361 | 1604 | dsschult | // remove from buffer
|
362 | 1825 | bwasserm | val = send_buf_first; //val is no longer the send status
|
363 | |||
364 | 1604 | dsschult | while (1) { |
365 | len = send_buf_get(&val); |
||
366 | 1768 | dsschult | WL_DEBUG_PRINT_P("|send_packet_buf_pos:");
|
367 | WL_DEBUG_PRINT_INT(val); |
||
368 | WL_DEBUG_PRINT_P("|send_packet_len:");
|
||
369 | WL_DEBUG_PRINT_INT(len); |
||
370 | 1769 | dsschult | WL_DEBUG_PRINT_P("|send_packet_first:");
|
371 | WL_DEBUG_PRINT_INT(send_buf_first); |
||
372 | WL_DEBUG_PRINT_P("|send_packet_last:");
|
||
373 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
374 | 1772 | dsschult | WL_DEBUG_PRINT_P("|send_buf:");
|
375 | for(int i=send_buf_first;i<send_buf_last;i++) |
||
376 | WL_DEBUG_PRINT_HEX(send_buf[i]); |
||
377 | 1789 | dsschult | |
378 | num_packet = send_buf_get(&val); |
||
379 | if (num_packet != num) {
|
||
380 | // not the correct packet
|
||
381 | |||
382 | if ((num_packet < num && num > 9 && num_packet < num-10) |
||
383 | || (num_packet > num && num > 9)) {
|
||
384 | ackhandle(num_packet,1); // resend |
||
385 | ackhandle(num,0); // redo this packet |
||
386 | return;
|
||
387 | } |
||
388 | |||
389 | 1768 | dsschult | WL_DEBUG_PRINT_P("|not correct packet");
|
390 | 1604 | dsschult | val += len; |
391 | 1772 | dsschult | WL_DEBUG_PRINT_P("|send_packet_buf_pos:");
|
392 | WL_DEBUG_PRINT_INT(val); |
||
393 | 1604 | dsschult | if (val >= PACKET_BUFFER_SIZE)
|
394 | val -= PACKET_BUFFER_SIZE; |
||
395 | 1769 | dsschult | if (val == send_buf_last || ++packets >= send_buf_num_packets) {
|
396 | 1604 | dsschult | // reached end of bufer, so assume not present
|
397 | return;
|
||
398 | } |
||
399 | } else {
|
||
400 | // remove packet
|
||
401 | 1768 | dsschult | WL_DEBUG_PRINT_P("|remove packet");
|
402 | 1790 | dsschult | if (val+len >= PACKET_BUFFER_SIZE)
|
403 | num = val+len-PACKET_BUFFER_SIZE; |
||
404 | else
|
||
405 | num = val+len; |
||
406 | 1604 | dsschult | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; |
407 | while(num != send_buf_last) {
|
||
408 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
409 | return; // error |
||
410 | } |
||
411 | send_buf_last = val; // set new end of buffer
|
||
412 | 1782 | dsschult | send_buf_num_packets--; // remove packet from count
|
413 | 1772 | dsschult | |
414 | WL_DEBUG_PRINT_P("|send_packet_first:");
|
||
415 | WL_DEBUG_PRINT_INT(send_buf_first); |
||
416 | WL_DEBUG_PRINT_P("|send_packet_last:");
|
||
417 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
418 | 1782 | dsschult | WL_DEBUG_PRINT_P("|num_send_packets:");
|
419 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
420 | 1604 | dsschult | return;
|
421 | } |
||
422 | } |
||
423 | 1791 | dsschult | break;
|
424 | case 2: |
||
425 | WL_DEBUG_PRINT_P("CCA failure\r\n");
|
||
426 | 1591 | dsschult | case 1: |
427 | 1768 | dsschult | WL_DEBUG_PRINT_P("no ack\r\n");
|
428 | 1591 | dsschult | // no ack
|
429 | 1604 | dsschult | // check resend attempts
|
430 | val = send_buf_first; |
||
431 | if (send_buf_num_packets == 0) |
||
432 | return;
|
||
433 | while (1) { |
||
434 | len = send_buf_get(&val); |
||
435 | 1791 | dsschult | if (send_buf[val] != num) {
|
436 | 1604 | dsschult | // not the correct packet, so continue
|
437 | val += len; |
||
438 | if (val >= PACKET_BUFFER_SIZE)
|
||
439 | val -= PACKET_BUFFER_SIZE; |
||
440 | if (val == send_buf_last) {
|
||
441 | // reached end of bufer, so assume not present
|
||
442 | setack(num,ACK_FAILURE); // mark as failed send
|
||
443 | return;
|
||
444 | } |
||
445 | } else {
|
||
446 | // check attempts on packet
|
||
447 | 1791 | dsschult | if (val+len+1 >= PACKET_BUFFER_SIZE) |
448 | num = val+len-PACKET_BUFFER_SIZE; |
||
449 | 1790 | dsschult | else
|
450 | 1791 | dsschult | num = val+len; // set to end of packet
|
451 | 1604 | dsschult | if (send_buf[num] < NUM_RETRIES) {
|
452 | 1791 | dsschult | // retry sending
|
453 | 1604 | dsschult | send_buf[num]++; // increment retries
|
454 | 1791 | dsschult | |
455 | setack(send_buf[val],ACK_OK); |
||
456 | send_buf[val] = nextframe; // reset frame number
|
||
457 | setack(nextframe,SENDING); |
||
458 | 1790 | dsschult | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
459 | |||
460 | 1791 | dsschult | val = (val>0)?PACKET_BUFFER_SIZE+val-1:val-1; // set to start of this packet |
461 | 1646 | dsschult | if (xbee_send_header(len+1) != WL_SUCCESS) { |
462 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
463 | 1604 | dsschult | return;
|
464 | } |
||
465 | len = XBEE_FRAME_TX_REQUEST_16; |
||
466 | while(val!=num) {
|
||
467 | // compute checksum
|
||
468 | len += send_buf[val]; |
||
469 | 1791 | dsschult | if (xbee_sendc(send_buf_get(&val)) != WL_SUCCESS) { // send byte |
470 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
471 | 1604 | dsschult | return;
|
472 | } |
||
473 | } |
||
474 | len = 0xFF - len;
|
||
475 | 1791 | dsschult | if (xbee_sendc(len) != WL_SUCCESS) { // send |
476 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
477 | 1604 | dsschult | return;
|
478 | } |
||
479 | return;
|
||
480 | } else {
|
||
481 | // done sending, mark as failed send
|
||
482 | 1791 | dsschult | setack(send_buf[num],ACK_FAILURE); |
483 | 1604 | dsschult | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet |
484 | 1791 | dsschult | num = (num+1==PACKET_BUFFER_SIZE)?0:num+1; // set to end of this packet |
485 | 1604 | dsschult | // remove packet
|
486 | while(num != send_buf_last) {
|
||
487 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
488 | return; // error |
||
489 | } |
||
490 | return;
|
||
491 | } |
||
492 | } |
||
493 | } |
||
494 | break; // shouldn't get here, but just in case |
||
495 | } |
||
496 | 1591 | dsschult | } |
497 | |||
498 | 1604 | dsschult | /* adds a byte to the send buffer */
|
499 | int8_t send_buf_add(uint8_t *ptr, uint8_t byte) { |
||
500 | 1765 | dsschult | if (*ptr == send_buf_first && send_buf_num_packets > 0) { |
501 | 1604 | dsschult | // buffer full
|
502 | 1662 | dsschult | WL_DEBUG_PRINT_P("send buffer full\r\n");
|
503 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
504 | } |
||
505 | 1609 | dsschult | send_buf[(*ptr)++] = byte; |
506 | 1604 | dsschult | if (*ptr == PACKET_BUFFER_SIZE)
|
507 | *ptr = 0;
|
||
508 | return WL_SUCCESS;
|
||
509 | } |
||
510 | /* gets a byte from the send buffer */
|
||
511 | uint8_t send_buf_get(uint8_t *ptr) { |
||
512 | 1609 | dsschult | uint8_t byte = send_buf[(*ptr)++]; |
513 | 1604 | dsschult | if (*ptr == PACKET_BUFFER_SIZE)
|
514 | *ptr = 0;
|
||
515 | return byte;
|
||
516 | } |