Project

General

Profile

Statistics
| Revision:

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
}