root / branches / wireless / code / projects / libwireless / wireless_send.c @ 1790
History | View | Annotate | Download (18.3 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 | 1600 | dsschult | // set scope
|
104 | 1587 | dsschult | if (scope == GLOBAL)
|
105 | 1604 | dsschult | packet[3] &= XBEE_OPTIONS_BROADCAST_ALL_PANS;
|
106 | 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 | // set mode
|
||
112 | 1587 | dsschult | if (mode == FAST) {
|
113 | 1604 | dsschult | 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 | if (mode == FAST) {
|
||
149 | 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 | 1604 | dsschult | // save packet on sending buffer
|
155 | scope = send_buf_last; // use as ptr to send buffer
|
||
156 | if (send_buf_add(&scope,length+6) != WL_SUCCESS) { // add length |
||
157 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding length to sending buffer\r\n");
|
158 | ret = WL_ERROR_SENDING_BUFFER_FULL; |
||
159 | 1604 | dsschult | } |
160 | for(mode=0;mode<6;mode++) { // add header |
||
161 | if (send_buf_add(&scope,packet[mode]) != WL_SUCCESS) {
|
||
162 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding header to sending buffer\r\n");
|
163 | ret = WL_ERROR_SENDING_BUFFER_FULL; |
||
164 | 1604 | dsschult | } |
165 | } |
||
166 | for(mode=0;mode<length;mode++) { // add data |
||
167 | if (send_buf_add(&scope,data[mode]) != WL_SUCCESS) {
|
||
168 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding data to sendig buffer\r\n");
|
169 | ret = WL_ERROR_SENDING_BUFFER_FULL; |
||
170 | 1604 | dsschult | } |
171 | } |
||
172 | if (send_buf_add(&scope,0) != WL_SUCCESS) { // add num retries=0 |
||
173 | 1772 | dsschult | WL_DEBUG_PRINT_P("Error adding num_retries to sending buffer\r\n");
|
174 | ret = WL_ERROR_SENDING_BUFFER_FULL; |
||
175 | 1604 | dsschult | } |
176 | send_buf_last = scope; |
||
177 | send_buf_num_packets++; |
||
178 | 1770 | dsschult | WL_DEBUG_PRINT_P("send_buf_last:");
|
179 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
180 | WL_DEBUG_PRINT_P("pos:");
|
||
181 | WL_DEBUG_PRINT_INT(scope); |
||
182 | WL_DEBUG_PRINT_P("send_buf_num_packets:");
|
||
183 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
184 | 1608 | dsschult | |
185 | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
||
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 | 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 | 1772 | dsschult | } |
266 | WL_DEBUG_PRINT_P("|num_errors:");
|
||
267 | WL_DEBUG_PRINT_INT(val); |
||
268 | WL_DEBUG_PRINT_P("\r\n");
|
||
269 | |||
270 | 1587 | dsschult | return val;
|
271 | 1576 | dsschult | } |
272 | |||
273 | 1581 | dsschult | /**
|
274 | * acknowledgement error check
|
||
275 | * check if a specific packet has been lost
|
||
276 | 1587 | dsschult | * note: buffer will overflow every 255 packets
|
277 | 1581 | dsschult | *
|
278 | 1587 | dsschult | * @param packet packet number
|
279 | 1581 | dsschult | *
|
280 | 1587 | dsschult | * @return {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
|
281 | 1581 | dsschult | **/
|
282 | int8_t wl_ack_check(uint8_t packet) { |
||
283 | 1772 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_check function|ack=");
|
284 | 1587 | dsschult | if (packet == 0) { |
285 | // no ack information here
|
||
286 | 1662 | dsschult | WL_DEBUG_PRINT_P("packet number cannot be 0\r\n");
|
287 | 1587 | dsschult | return WL_ERROR_ARGUMENT;
|
288 | } |
||
289 | |||
290 | 1772 | dsschult | WL_DEBUG_PRINT_HEX(ack_buf[packet/4]&(0x3<<(packet%4))); |
291 | WL_DEBUG_PRINT_P("\r\n");
|
||
292 | |||
293 | 1587 | dsschult | // check ack
|
294 | return ack_buf[packet/4]&(0x3<<(packet%4)); |
||
295 | 1581 | dsschult | } |
296 | |||
297 | /**
|
||
298 | * acknowledgement reset
|
||
299 | * reset the acknowledgement buffer
|
||
300 | **/
|
||
301 | void wl_ack_reset(void) { |
||
302 | 1662 | dsschult | WL_DEBUG_PRINT_P("entering wl_ack_reset function\r\n");
|
303 | 1587 | dsschult | memset(ack_buf,0,64); |
304 | 1581 | dsschult | } |
305 | |||
306 | |||
307 | 1577 | dsschult | /**@} **/ //end defgroup |
308 | |||
309 | |||
310 | // Define all private functions down here
|
||
311 | |||
312 | 1587 | dsschult | /*
|
313 | * sets 2 bits in the ack_buf
|
||
314 | *
|
||
315 | * @param num the ack number
|
||
316 | * @param val {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
|
||
317 | */
|
||
318 | void setack(uint8_t num,uint8_t val) {
|
||
319 | 1772 | dsschult | WL_DEBUG_PRINT_P("entering setack function|num=");
|
320 | WL_DEBUG_PRINT_INT(num); |
||
321 | WL_DEBUG_PRINT_P("|val=");
|
||
322 | WL_DEBUG_PRINT_HEX(val); |
||
323 | WL_DEBUG_PRINT_P("\r\n");
|
||
324 | 1587 | dsschult | switch(num%4) { |
325 | case 0: |
||
326 | ack_buf[num/4] &= (0xFC|val); |
||
327 | break;
|
||
328 | case 1: |
||
329 | ack_buf[num/4] &= (0xF3|(val<<2)); |
||
330 | break;
|
||
331 | case 2: |
||
332 | ack_buf[num/4] &= (0xCF|(val<<4)); |
||
333 | break;
|
||
334 | case 3: |
||
335 | ack_buf[num/4] &= (0x3F|(val<<6)); |
||
336 | break;
|
||
337 | } |
||
338 | } |
||
339 | 1577 | dsschult | |
340 | 1591 | dsschult | |
341 | /* ack handler */
|
||
342 | void ackhandle(uint8_t num,uint8_t val) {
|
||
343 | 1604 | dsschult | uint8_t len; |
344 | 1769 | dsschult | uint8_t packets = 0;
|
345 | 1789 | dsschult | uint8_t num_packet = 0;
|
346 | 1780 | dsschult | WL_DEBUG_PRINT_P("entering ackhandle function: num:");
|
347 | WL_DEBUG_PRINT_HEX(num); |
||
348 | WL_DEBUG_PRINT_P("\r\n");
|
||
349 | 1591 | dsschult | switch(val) {
|
350 | case 0: |
||
351 | 1768 | dsschult | WL_DEBUG_PRINT_P("ack success\r\n");
|
352 | 1591 | dsschult | // success
|
353 | 1600 | dsschult | setack(num,ACK_OK); // set status code
|
354 | 1604 | dsschult | // remove from buffer
|
355 | val = send_buf_first; |
||
356 | if (send_buf_num_packets == 0) |
||
357 | return;
|
||
358 | 1768 | dsschult | WL_DEBUG_PRINT_P("|num_send_packets:");
|
359 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
360 | 1604 | dsschult | while (1) { |
361 | len = send_buf_get(&val); |
||
362 | 1768 | dsschult | WL_DEBUG_PRINT_P("|send_packet_buf_pos:");
|
363 | WL_DEBUG_PRINT_INT(val); |
||
364 | WL_DEBUG_PRINT_P("|send_packet_len:");
|
||
365 | WL_DEBUG_PRINT_INT(len); |
||
366 | 1769 | dsschult | WL_DEBUG_PRINT_P("|send_packet_first:");
|
367 | WL_DEBUG_PRINT_INT(send_buf_first); |
||
368 | WL_DEBUG_PRINT_P("|send_packet_last:");
|
||
369 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
370 | 1772 | dsschult | WL_DEBUG_PRINT_P("|send_buf:");
|
371 | for(int i=send_buf_first;i<send_buf_last;i++) |
||
372 | WL_DEBUG_PRINT_HEX(send_buf[i]); |
||
373 | 1789 | dsschult | |
374 | num_packet = send_buf_get(&val); |
||
375 | if (num_packet != num) {
|
||
376 | // not the correct packet
|
||
377 | |||
378 | if ((num_packet < num && num > 9 && num_packet < num-10) |
||
379 | || (num_packet > num && num > 9)) {
|
||
380 | ackhandle(num_packet,1); // resend |
||
381 | ackhandle(num,0); // redo this packet |
||
382 | return;
|
||
383 | } |
||
384 | |||
385 | 1768 | dsschult | WL_DEBUG_PRINT_P("|not correct packet");
|
386 | 1604 | dsschult | val += len; |
387 | 1772 | dsschult | WL_DEBUG_PRINT_P("|send_packet_buf_pos:");
|
388 | WL_DEBUG_PRINT_INT(val); |
||
389 | 1604 | dsschult | if (val >= PACKET_BUFFER_SIZE)
|
390 | val -= PACKET_BUFFER_SIZE; |
||
391 | 1769 | dsschult | if (val == send_buf_last || ++packets >= send_buf_num_packets) {
|
392 | 1604 | dsschult | // reached end of bufer, so assume not present
|
393 | return;
|
||
394 | } |
||
395 | } else {
|
||
396 | // remove packet
|
||
397 | 1768 | dsschult | WL_DEBUG_PRINT_P("|remove packet");
|
398 | 1790 | dsschult | if (val+len >= PACKET_BUFFER_SIZE)
|
399 | num = val+len-PACKET_BUFFER_SIZE; |
||
400 | else
|
||
401 | num = val+len; |
||
402 | 1604 | dsschult | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; |
403 | while(num != send_buf_last) {
|
||
404 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
405 | return; // error |
||
406 | } |
||
407 | send_buf_last = val; // set new end of buffer
|
||
408 | 1782 | dsschult | send_buf_num_packets--; // remove packet from count
|
409 | 1772 | dsschult | |
410 | WL_DEBUG_PRINT_P("|send_packet_first:");
|
||
411 | WL_DEBUG_PRINT_INT(send_buf_first); |
||
412 | WL_DEBUG_PRINT_P("|send_packet_last:");
|
||
413 | WL_DEBUG_PRINT_INT(send_buf_last); |
||
414 | 1782 | dsschult | WL_DEBUG_PRINT_P("|num_send_packets:");
|
415 | WL_DEBUG_PRINT_INT(send_buf_num_packets); |
||
416 | 1604 | dsschult | return;
|
417 | } |
||
418 | } |
||
419 | 1591 | dsschult | break;
|
420 | case 1: |
||
421 | 1768 | dsschult | WL_DEBUG_PRINT_P("no ack\r\n");
|
422 | 1591 | dsschult | // no ack
|
423 | 1604 | dsschult | // check resend attempts
|
424 | val = send_buf_first; |
||
425 | if (send_buf_num_packets == 0) |
||
426 | return;
|
||
427 | while (1) { |
||
428 | len = send_buf_get(&val); |
||
429 | if (send_buf_get(&val) != num) {
|
||
430 | // not the correct packet, so continue
|
||
431 | val += len; |
||
432 | if (val >= PACKET_BUFFER_SIZE)
|
||
433 | val -= PACKET_BUFFER_SIZE; |
||
434 | if (val == send_buf_last) {
|
||
435 | // reached end of bufer, so assume not present
|
||
436 | setack(num,ACK_FAILURE); // mark as failed send
|
||
437 | return;
|
||
438 | } |
||
439 | } else {
|
||
440 | // check attempts on packet
|
||
441 | 1790 | dsschult | if (val+len-1 >= PACKET_BUFFER_SIZE) |
442 | num = val+len-1-PACKET_BUFFER_SIZE;
|
||
443 | else
|
||
444 | num = val+len-1; // set to end of packet |
||
445 | 1604 | dsschult | if (send_buf[num] < NUM_RETRIES) {
|
446 | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; // set to start of this packet |
||
447 | // retry sending
|
||
448 | send_buf[num]++; // increment retries
|
||
449 | 1790 | dsschult | send_buf[val+1] = nextframe; // reset frame number |
450 | nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number |
||
451 | |||
452 | 1604 | dsschult | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // go back one byte |
453 | 1646 | dsschult | if (xbee_send_header(len+1) != WL_SUCCESS) { |
454 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
455 | 1604 | dsschult | return;
|
456 | } |
||
457 | len = XBEE_FRAME_TX_REQUEST_16; |
||
458 | while(val!=num) {
|
||
459 | // compute checksum
|
||
460 | len += send_buf[val]; |
||
461 | if (xbee_putc(send_buf_get(&val)) != WL_SUCCESS) { // send byte |
||
462 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
463 | 1604 | dsschult | return;
|
464 | } |
||
465 | } |
||
466 | len = 0xFF - len;
|
||
467 | if (xbee_putc(len) != WL_SUCCESS) { // send |
||
468 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
469 | 1604 | dsschult | return;
|
470 | } |
||
471 | return;
|
||
472 | } else {
|
||
473 | // done sending, mark as failed send
|
||
474 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to frame num |
||
475 | setack(send_buf[val],ACK_FAILURE); |
||
476 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet |
||
477 | // remove packet
|
||
478 | while(num != send_buf_last) {
|
||
479 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
480 | return; // error |
||
481 | } |
||
482 | return;
|
||
483 | } |
||
484 | } |
||
485 | } |
||
486 | break; // shouldn't get here, but just in case |
||
487 | 1591 | dsschult | case 2: |
488 | 1768 | dsschult | WL_DEBUG_PRINT_P("CCA failure\r\n");
|
489 | 1591 | dsschult | // CCA failure
|
490 | 1604 | dsschult | // check resend attempts
|
491 | val = send_buf_first; |
||
492 | if (send_buf_num_packets == 0) |
||
493 | return;
|
||
494 | while (1) { |
||
495 | len = send_buf_get(&val); |
||
496 | if (send_buf_get(&val) != num) {
|
||
497 | // not the correct packet, so continue
|
||
498 | val += len; |
||
499 | if (val >= PACKET_BUFFER_SIZE)
|
||
500 | val -= PACKET_BUFFER_SIZE; |
||
501 | if (val == send_buf_last) {
|
||
502 | // reached end of bufer, so assume not present
|
||
503 | setack(num,CCA_FAILURE); // mark as failed send
|
||
504 | return;
|
||
505 | } |
||
506 | } else {
|
||
507 | // check attempts on packet
|
||
508 | num = val+len-1; // set to end of packet |
||
509 | if (num >= PACKET_BUFFER_SIZE)
|
||
510 | num -= PACKET_BUFFER_SIZE; |
||
511 | if (send_buf[num] < NUM_RETRIES) {
|
||
512 | val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; // set to start of this packet |
||
513 | // retry sending
|
||
514 | send_buf[num]++; // increment retries
|
||
515 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // go back one byte |
||
516 | 1646 | dsschult | if (xbee_send_header(len+1) != WL_SUCCESS) { |
517 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
518 | 1604 | dsschult | return;
|
519 | } |
||
520 | len = XBEE_FRAME_TX_REQUEST_16; |
||
521 | while(val!=num) {
|
||
522 | // compute checksum
|
||
523 | len += send_buf[val]; |
||
524 | if (xbee_putc(send_buf_get(&val)) != WL_SUCCESS) { // send byte |
||
525 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
526 | 1604 | dsschult | return;
|
527 | } |
||
528 | } |
||
529 | len = 0xFF - len;
|
||
530 | if (xbee_putc(len) != WL_SUCCESS) { // send |
||
531 | 1662 | dsschult | WL_DEBUG_PRINT_P("Error sending packet from ackhandle function\r\n");
|
532 | 1604 | dsschult | return;
|
533 | } |
||
534 | return;
|
||
535 | } else {
|
||
536 | // done sending, mark as failed send
|
||
537 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to frame num |
||
538 | setack(send_buf[val],CCA_FAILURE); |
||
539 | val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet |
||
540 | // remove packet
|
||
541 | while(num != send_buf_last) {
|
||
542 | if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
|
||
543 | return; // error |
||
544 | } |
||
545 | return;
|
||
546 | } |
||
547 | } |
||
548 | } |
||
549 | break; // shouldn't get here, but just in case |
||
550 | } |
||
551 | 1591 | dsschult | } |
552 | |||
553 | 1604 | dsschult | /* adds a byte to the send buffer */
|
554 | int8_t send_buf_add(uint8_t *ptr, uint8_t byte) { |
||
555 | 1765 | dsschult | if (*ptr == send_buf_first && send_buf_num_packets > 0) { |
556 | 1604 | dsschult | // buffer full
|
557 | 1662 | dsschult | WL_DEBUG_PRINT_P("send buffer full\r\n");
|
558 | 1604 | dsschult | return WL_ERROR_SENDING_BUFFER_FULL;
|
559 | } |
||
560 | 1609 | dsschult | send_buf[(*ptr)++] = byte; |
561 | 1604 | dsschult | if (*ptr == PACKET_BUFFER_SIZE)
|
562 | *ptr = 0;
|
||
563 | return WL_SUCCESS;
|
||
564 | } |
||
565 | /* gets a byte from the send buffer */
|
||
566 | uint8_t send_buf_get(uint8_t *ptr) { |
||
567 | 1609 | dsschult | uint8_t byte = send_buf[(*ptr)++]; |
568 | 1604 | dsschult | if (*ptr == PACKET_BUFFER_SIZE)
|
569 | *ptr = 0;
|
||
570 | return byte;
|
||
571 | } |