root / branches / wireless / code / projects / libwireless / wireless_send.c @ 1770
History | View | Annotate | Download (16.8 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 | 1587 | dsschult | |
94 | 1604 | dsschult | // build packet header
|
95 | 1587 | dsschult | packet[0] = nextframe;
|
96 | 1604 | dsschult | packet[1] = (dest&0xFF00)>>8; |
97 | 1688 | dsschult | packet[2] = dest&0x00FF; |
98 | 1604 | dsschult | packet[3] = XBEE_OPTIONS_NONE;
|
99 | packet[4] = nextframe;
|
||
100 | packet[5] = group;
|
||
101 | 1587 | dsschult | |
102 | 1600 | dsschult | // set scope
|
103 | 1587 | dsschult | if (scope == GLOBAL)
|
104 | 1604 | dsschult | packet[3] &= XBEE_OPTIONS_BROADCAST_ALL_PANS;
|
105 | else if (scope != PAN) { |
||
106 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error - bad scope in core send function\r\n");
|
107 | 1604 | dsschult | return WL_ERROR_SCOPE;
|
108 | } |
||
109 | 1600 | dsschult | |
110 | // set mode
|
||
111 | 1587 | dsschult | if (mode == FAST) {
|
112 | 1604 | dsschult | packet[3] &= XBEE_OPTIONS_DISABLE_RESPONSE;
|
113 | 1600 | dsschult | } else if (mode != RELIABLE) { |
114 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error - bad mode in core send function\r\n");
|
115 | 1587 | dsschult | return WL_ERROR_MODE;
|
116 | } |
||
117 | 1604 | dsschult | |
118 | // do checksum
|
||
119 | group = XBEE_FRAME_TX_REQUEST_16; |
||
120 | xbee_checksum_add(packet,6,&group);
|
||
121 | xbee_checksum_add(data,length,&group); |
||
122 | group = 0xFF-group;
|
||
123 | 1576 | dsschult | |
124 | 1587 | dsschult | // send the packet
|
125 | 1646 | dsschult | if (xbee_send_header(length+7) != WL_SUCCESS) { |
126 | 1662 | dsschult | WL_DEBUG_PRINT_P("1Error sending packet from core send function\r\n");
|
127 | 1587 | dsschult | return WL_ERROR_SEND;
|
128 | } |
||
129 | 1679 | dsschult | if (xbee_sendc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS) {
|
130 | 1662 | dsschult | WL_DEBUG_PRINT_P("2Error sending packet from core send function\r\n");
|
131 | 1604 | dsschult | return WL_ERROR_SEND;
|
132 | } |
||
133 | if (xbee_send(packet,6) != WL_SUCCESS) { |
||
134 | 1662 | dsschult | WL_DEBUG_PRINT_P("3Error sending packet from core send function\r\n");
|
135 | 1604 | dsschult | return WL_ERROR_SEND;
|
136 | } |
||
137 | if (xbee_send(data,length) != WL_SUCCESS) {
|
||
138 | 1662 | dsschult | WL_DEBUG_PRINT_P("4Error sending packet from core send function\r\n");
|
139 | 1604 | dsschult | return WL_ERROR_SEND;
|
140 | } |
||
141 | 1679 | dsschult | if (xbee_sendc(group) != WL_SUCCESS) {
|
142 | 1662 | dsschult | WL_DEBUG_PRINT_P("5Error sending packet from core send function\r\n");
|
143 | 1604 | dsschult | return WL_ERROR_SEND;
|
144 | } |
||
145 | 1587 | dsschult | |
146 | 1600 | dsschult | // save in ack system
|
147 | if (mode == FAST) {
|
||
148 | setack(nextframe,ACK_OK); // assume the send was successful
|
||
149 | 1608 | dsschult | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
150 | return WL_SUCCESS; // no frame number |
||
151 | 1600 | dsschult | } else if (mode == RELIABLE) { |
152 | setack(nextframe,SENDING); // set status to SENDING
|
||
153 | 1604 | dsschult | // save packet on sending buffer
|
154 | scope = send_buf_last; // use as ptr to send buffer
|
||
155 | if (send_buf_add(&scope,length+6) != WL_SUCCESS) { // add length |
||
156 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error: sending buffer full\r\n");
|
157 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
158 | } |
||
159 | for(mode=0;mode<6;mode++) { // add header |
||
160 | if (send_buf_add(&scope,packet[mode]) != WL_SUCCESS) {
|
||
161 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error: sending buffer full\r\n");
|
162 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
163 | } |
||
164 | } |
||
165 | for(mode=0;mode<length;mode++) { // add data |
||
166 | if (send_buf_add(&scope,data[mode]) != WL_SUCCESS) {
|
||
167 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error: sending buffer full\r\n");
|
168 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
169 | } |
||
170 | } |
||
171 | if (send_buf_add(&scope,0) != WL_SUCCESS) { // add num retries=0 |
||
172 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error: sending buffer full\r\n");
|
173 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
174 | } |
||
175 | send_buf_last = scope; |
||
176 | send_buf_num_packets++; |
||
177 | 1770 | dsschult | WL_DEBUG_PRINT_P("send_buf_last:");
|
178 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
179 | WL_DEBUG_PRINT_P("pos:");
|
||
180 | WL_DEBUG_PRINT_INT(scope); |
||
181 | WL_DEBUG_PRINT_P("send_buf_num_packets:");
|
||
182 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
183 | 1608 | dsschult | |
184 | 1770 | dsschult | |
185 | 1608 | dsschult | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
186 | return packet[0]; // return frame number for ack tracking |
||
187 | 1600 | dsschult | } |
188 | 1609 | dsschult | return WL_ERROR_SEND;
|
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 | 1662 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_error function\r\n");
|
257 | 1609 | dsschult | uint8_t val=0,i=1; |
258 | 1587 | dsschult | |
259 | while(1) { |
||
260 | 1609 | dsschult | if (((ack_buf[i/4])&(0x2<<(i%4))) != 0) // if the ack is in an error state |
261 | 1587 | dsschult | val++; |
262 | if (i==255) |
||
263 | break;
|
||
264 | i++; |
||
265 | } |
||
266 | 1576 | dsschult | |
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 | 1662 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_check function\r\n");
|
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 | // check ack
|
||
288 | return ack_buf[packet/4]&(0x3<<(packet%4)); |
||
289 | 1581 | dsschult | } |
290 | |||
291 | /**
|
||
292 | * acknowledgement reset
|
||
293 | * reset the acknowledgement buffer
|
||
294 | **/
|
||
295 | void wl_ack_reset(void) { |
||
296 | 1662 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_reset function\r\n");
|
297 | 1587 | dsschult | memset(ack_buf,0,64); |
298 | 1581 | dsschult | } |
299 | |||
300 | |||
301 | 1577 | dsschult | /**@} **/ //end defgroup |
302 | |||
303 | |||
304 | // Define all private functions down here
|
||
305 | |||
306 | 1587 | dsschult | /*
|
307 | * sets 2 bits in the ack_buf
|
||
308 | *
|
||
309 | * @param num the ack number
|
||
310 | * @param val {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
|
||
311 | */
|
||
312 | void setack(uint8_t num,uint8_t val) {
|
||
313 | 1662 | dsschult | WL_DEBUG_PRINT_P("entering setack function\r\n");
|
314 | 1587 | dsschult | switch(num%4) { |
315 | case 0: |
||
316 | ack_buf[num/4] &= (0xFC|val); |
||
317 | break;
|
||
318 | case 1: |
||
319 | ack_buf[num/4] &= (0xF3|(val<<2)); |
||
320 | break;
|
||
321 | case 2: |
||
322 | ack_buf[num/4] &= (0xCF|(val<<4)); |
||
323 | break;
|
||
324 | case 3: |
||
325 | ack_buf[num/4] &= (0x3F|(val<<6)); |
||
326 | break;
|
||
327 | } |
||
328 | } |
||
329 | 1577 | dsschult | |
330 | 1591 | dsschult | |
331 | /* ack handler */
|
||
332 | void ackhandle(uint8_t num,uint8_t val) {
|
||
333 | 1604 | dsschult | uint8_t len; |
334 | 1769 | dsschult | uint8_t packets = 0;
|
335 | 1768 | dsschult | WL_DEBUG_PRINT_P("entering ackhandle function:\r\n");
|
336 | 1591 | dsschult | switch(val) {
|
337 | case 0: |
||
338 | 1768 | dsschult | WL_DEBUG_PRINT_P("ack success\r\n");
|
339 | 1591 | dsschult | // success
|
340 | 1600 | dsschult | setack(num,ACK_OK); // set status code
|
341 | 1604 | dsschult | // remove from buffer
|
342 | val = send_buf_first; |
||
343 | if (send_buf_num_packets == 0) |
||
344 | return;
|
||
345 | 1768 | dsschult | WL_DEBUG_PRINT_P("|num_send_packets:");
|
346 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
347 | 1604 | dsschult | while (1) { |
348 | len = send_buf_get(&val); |
||
349 | 1768 | dsschult | WL_DEBUG_PRINT_P("|send_packet_buf_pos:");
|
350 | WL_DEBUG_PRINT_INT(val); |
||
351 | WL_DEBUG_PRINT_P("|send_packet_len:");
|
||
352 | WL_DEBUG_PRINT_INT(len); |
||
353 | 1769 | dsschult | WL_DEBUG_PRINT_P("|send_packet_first:");
|
354 | WL_DEBUG_PRINT_INT(send_buf_first); |
||
355 | WL_DEBUG_PRINT_P("|send_packet_last:");
|
||
356 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
357 | 1604 | dsschult | if (send_buf_get(&val) != num) {
|
358 | // not the correct packet, so continue
|
||
359 | 1768 | dsschult | WL_DEBUG_PRINT_P("|not correct packet");
|
360 | 1604 | dsschult | val += len; |
361 | if (val >= PACKET_BUFFER_SIZE)
|
||
362 | val -= PACKET_BUFFER_SIZE; |
||
363 | 1769 | dsschult | if (val == send_buf_last || ++packets >= send_buf_num_packets) {
|
364 | 1604 | dsschult | // reached end of bufer, so assume not present
|
365 | return;
|
||
366 | } |
||
367 | } else {
|
||
368 | // remove packet
|
||
369 | 1768 | dsschult | WL_DEBUG_PRINT_P("|remove packet");
|
370 | 1604 | dsschult | num = val+len; |
371 | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; |
||
372 | if (num >= PACKET_BUFFER_SIZE)
|
||
373 | num -= PACKET_BUFFER_SIZE; |
||
374 | while(num != send_buf_last) {
|
||
375 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
376 | return; // error |
||
377 | } |
||
378 | send_buf_last = val; // set new end of buffer
|
||
379 | return;
|
||
380 | } |
||
381 | } |
||
382 | 1591 | dsschult | break;
|
383 | case 1: |
||
384 | 1768 | dsschult | WL_DEBUG_PRINT_P("no ack\r\n");
|
385 | 1591 | dsschult | // no ack
|
386 | 1604 | dsschult | // check resend attempts
|
387 | val = send_buf_first; |
||
388 | if (send_buf_num_packets == 0) |
||
389 | return;
|
||
390 | while (1) { |
||
391 | len = send_buf_get(&val); |
||
392 | if (send_buf_get(&val) != num) {
|
||
393 | // not the correct packet, so continue
|
||
394 | val += len; |
||
395 | if (val >= PACKET_BUFFER_SIZE)
|
||
396 | val -= PACKET_BUFFER_SIZE; |
||
397 | if (val == send_buf_last) {
|
||
398 | // reached end of bufer, so assume not present
|
||
399 | setack(num,ACK_FAILURE); // mark as failed send
|
||
400 | return;
|
||
401 | } |
||
402 | } else {
|
||
403 | // check attempts on packet
|
||
404 | num = val+len-1; // set to end of packet |
||
405 | if (num >= PACKET_BUFFER_SIZE)
|
||
406 | num -= PACKET_BUFFER_SIZE; |
||
407 | if (send_buf[num] < NUM_RETRIES) {
|
||
408 | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; // set to start of this packet |
||
409 | // retry sending
|
||
410 | send_buf[num]++; // increment retries
|
||
411 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // go back one byte |
||
412 | 1646 | dsschult | if (xbee_send_header(len+1) != WL_SUCCESS) { |
413 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
414 | 1604 | dsschult | return;
|
415 | } |
||
416 | len = XBEE_FRAME_TX_REQUEST_16; |
||
417 | while(val!=num) {
|
||
418 | // compute checksum
|
||
419 | len += send_buf[val]; |
||
420 | if (xbee_putc(send_buf_get(&val)) != WL_SUCCESS) { // send byte |
||
421 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
422 | 1604 | dsschult | return;
|
423 | } |
||
424 | } |
||
425 | len = 0xFF - len;
|
||
426 | if (xbee_putc(len) != WL_SUCCESS) { // send |
||
427 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
428 | 1604 | dsschult | return;
|
429 | } |
||
430 | return;
|
||
431 | } else {
|
||
432 | // done sending, mark as failed send
|
||
433 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to frame num |
||
434 | setack(send_buf[val],ACK_FAILURE); |
||
435 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet |
||
436 | // remove packet
|
||
437 | while(num != send_buf_last) {
|
||
438 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
439 | return; // error |
||
440 | } |
||
441 | return;
|
||
442 | } |
||
443 | } |
||
444 | } |
||
445 | break; // shouldn't get here, but just in case |
||
446 | 1591 | dsschult | case 2: |
447 | 1768 | dsschult | WL_DEBUG_PRINT_P("CCA failure\r\n");
|
448 | 1591 | dsschult | // CCA failure
|
449 | 1604 | dsschult | // check resend attempts
|
450 | val = send_buf_first; |
||
451 | if (send_buf_num_packets == 0) |
||
452 | return;
|
||
453 | while (1) { |
||
454 | len = send_buf_get(&val); |
||
455 | if (send_buf_get(&val) != num) {
|
||
456 | // not the correct packet, so continue
|
||
457 | val += len; |
||
458 | if (val >= PACKET_BUFFER_SIZE)
|
||
459 | val -= PACKET_BUFFER_SIZE; |
||
460 | if (val == send_buf_last) {
|
||
461 | // reached end of bufer, so assume not present
|
||
462 | setack(num,CCA_FAILURE); // mark as failed send
|
||
463 | return;
|
||
464 | } |
||
465 | } else {
|
||
466 | // check attempts on packet
|
||
467 | num = val+len-1; // set to end of packet |
||
468 | if (num >= PACKET_BUFFER_SIZE)
|
||
469 | num -= PACKET_BUFFER_SIZE; |
||
470 | if (send_buf[num] < NUM_RETRIES) {
|
||
471 | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; // set to start of this packet |
||
472 | // retry sending
|
||
473 | send_buf[num]++; // increment retries
|
||
474 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // go back one byte |
||
475 | 1646 | dsschult | if (xbee_send_header(len+1) != WL_SUCCESS) { |
476 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
477 | 1604 | dsschult | return;
|
478 | } |
||
479 | len = XBEE_FRAME_TX_REQUEST_16; |
||
480 | while(val!=num) {
|
||
481 | // compute checksum
|
||
482 | len += send_buf[val]; |
||
483 | if (xbee_putc(send_buf_get(&val)) != WL_SUCCESS) { // send byte |
||
484 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
485 | 1604 | dsschult | return;
|
486 | } |
||
487 | } |
||
488 | len = 0xFF - len;
|
||
489 | if (xbee_putc(len) != WL_SUCCESS) { // send |
||
490 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
491 | 1604 | dsschult | return;
|
492 | } |
||
493 | return;
|
||
494 | } else {
|
||
495 | // done sending, mark as failed send
|
||
496 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to frame num |
||
497 | setack(send_buf[val],CCA_FAILURE); |
||
498 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet |
||
499 | // remove packet
|
||
500 | while(num != send_buf_last) {
|
||
501 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
502 | return; // error |
||
503 | } |
||
504 | return;
|
||
505 | } |
||
506 | } |
||
507 | } |
||
508 | break; // shouldn't get here, but just in case |
||
509 | } |
||
510 | 1591 | dsschult | } |
511 | |||
512 | 1604 | dsschult | /* adds a byte to the send buffer */
|
513 | int8_t send_buf_add(uint8_t *ptr, uint8_t byte) { |
||
514 | 1765 | dsschult | if (*ptr == send_buf_first && send_buf_num_packets > 0) { |
515 | 1604 | dsschult | // buffer full
|
516 | 1662 | dsschult | WL_DEBUG_PRINT_P("send buffer full\r\n");
|
517 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
518 | } |
||
519 | 1609 | dsschult | send_buf[(*ptr)++] = byte; |
520 | 1604 | dsschult | if (*ptr == PACKET_BUFFER_SIZE)
|
521 | *ptr = 0;
|
||
522 | return WL_SUCCESS;
|
||
523 | } |
||
524 | /* gets a byte from the send buffer */
|
||
525 | uint8_t send_buf_get(uint8_t *ptr) { |
||
526 | 1609 | dsschult | uint8_t byte = send_buf[(*ptr)++]; |
527 | 1604 | dsschult | if (*ptr == PACKET_BUFFER_SIZE)
|
528 | *ptr = 0;
|
||
529 | return byte;
|
||
530 | } |