Project

General

Profile

Statistics
| Revision:

root / branches / wireless / code / projects / libwireless / wireless_send.c @ 1646

History | View | Annotate | Download (15.5 KB)

1
/**
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
#include "xbee.h"
39
#include <string.h>
40

    
41

    
42
/**
43
 * Definition for wireless library send packet structure
44
 * byte 1: length of packet (from frame number to end of data)
45
 * byte 2: frame number
46
 * bytes 3-n: data (dest, options, frame number, group code, packet)
47
 * byte n+1: num retries
48
 *
49
 * Definition for ack buffer
50
 * 2 bit system: 0=still sending
51
 *               1=OK
52
 *               2=ack failure
53
 *               3=CCA failure
54
 **/
55

    
56

    
57
/* global variables */
58
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
uint8_t send_buf_num_packets = 0; // number of packets in sending buffer
64

    
65
/* private function prototypes */
66
void setack(uint8_t num,uint8_t val);
67
void ackhandle(uint8_t num,uint8_t val);
68
int8_t send_buf_add(uint8_t *ptr, uint8_t byte);
69
uint8_t send_buf_get(uint8_t *ptr);
70

    
71
// the send functions
72

    
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
 * @param scope flag for sending global packet or your current PAN
86
 * @param dest robot ID (for robot to robot packet)
87
 * @param mode flag for using FAST or RELIABLE sending
88
 *
89
 * @return positive packet number for tracking acks, or error code
90
 **/
91
int16_t wl_send(uint8_t *data, uint8_t length, uint8_t group, uint8_t scope, uint16_t dest, uint8_t mode) {
92
  uint8_t packet[6];
93
  
94
  // build packet header
95
  packet[0] = nextframe;
96
  packet[1] = (dest&0xFF00)>>8;
97
  packet[2] = dest&0x00FF;  
98
  packet[3] = XBEE_OPTIONS_NONE;
99
  packet[4] = nextframe;
100
  packet[5] = group;
101
  
102
  // set scope
103
  if (scope == GLOBAL)
104
    packet[3] &= XBEE_OPTIONS_BROADCAST_ALL_PANS;
105
  else if (scope != PAN) {
106
    WL_DEBUG_PRINT("Error - bad scope in core send function\r\n");
107
    return WL_ERROR_SCOPE;
108
  }
109
    
110
  // set mode
111
  if (mode == FAST) {
112
    packet[3] &= XBEE_OPTIONS_DISABLE_RESPONSE;
113
  } else if (mode != RELIABLE) {
114
    WL_DEBUG_PRINT("Error - bad mode in core send function\r\n");
115
    return WL_ERROR_MODE;
116
  }
117
  
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

    
124
  // send the packet
125
  if (xbee_send_header(length+7) != WL_SUCCESS) {
126
    WL_DEBUG_PRINT("1Error sending packet from core send function\r\n");
127
    return WL_ERROR_SEND;
128
  }
129
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS) {
130
    WL_DEBUG_PRINT("2Error sending packet from core send function\r\n");
131
    return WL_ERROR_SEND;
132
  }
133
  if (xbee_send(packet,6) != WL_SUCCESS) {
134
    WL_DEBUG_PRINT("3Error sending packet from core send function\r\n");
135
    return WL_ERROR_SEND;
136
  }
137
  if (xbee_send(data,length) != WL_SUCCESS) {
138
    WL_DEBUG_PRINT("4Error sending packet from core send function\r\n");
139
    return WL_ERROR_SEND;
140
  }
141
  if (xbee_putc(group) != WL_SUCCESS) {
142
    WL_DEBUG_PRINT("5Error sending packet from core send function\r\n");
143
    return WL_ERROR_SEND;
144
  }
145
  
146
  // save in ack system
147
  if (mode == FAST) {
148
    setack(nextframe,ACK_OK); // assume the send was successful
149
    nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number
150
    return WL_SUCCESS; // no frame number
151
  } else if (mode == RELIABLE) {
152
    setack(nextframe,SENDING); // set status to SENDING
153
    // 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
      WL_DEBUG_PRINT("Error: sending buffer full\r\n");
157
      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
        WL_DEBUG_PRINT("Error: sending buffer full\r\n");
162
        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
        WL_DEBUG_PRINT("Error: sending buffer full\r\n");
168
        return WL_ERROR_SENDING_BUFFER_FULL;
169
      }
170
    }
171
    if (send_buf_add(&scope,0) != WL_SUCCESS) { // add num retries=0
172
      WL_DEBUG_PRINT("Error: sending buffer full\r\n");
173
      return WL_ERROR_SENDING_BUFFER_FULL;
174
    }
175
    send_buf_last = scope;
176
    send_buf_num_packets++;
177
    
178
    nextframe = (nextframe == 0xFF)?1:nextframe+1; // increment frame number
179
    return packet[0]; // return frame number for ack tracking
180
  }
181
  return WL_ERROR_SEND;
182
}
183

    
184
/**
185
 * Wrapper for core send function that will send a global packet across the current channel.
186
 *
187
 * @param data pointer to the byte array of data to be included in the packet
188
 * @param length the length of the data array
189
 * @param group the packet group of the packet
190
 *
191
 * @return positive packet number for tracking acks, or error code
192
 **/
193
int16_t wl_send_global(uint8_t *data, uint8_t length, uint8_t group) {
194
  return wl_send(data, length, group, GLOBAL, BROADCAST, RELIABLE);
195
}
196

    
197
/**
198
 * Wrapper for core send function that will send a packet across the current channel on the current pan.
199
 *
200
 * @param data pointer to the byte array of data to be included in the packet
201
 * @param length the length of the data array
202
 * @param group the packet group of the packet
203
 *
204
 * @return positive packet number for tracking acks, or error code (TBD)
205
 **/
206
int16_t wl_send_pan(uint8_t *data, uint8_t length, uint8_t group) {
207
  return wl_send(data, length, group, PAN, BROADCAST, RELIABLE);
208
}
209

    
210
/**
211
 * Wrapper for core send function that will send a packet across the current channel to a specific robot. 
212
 *
213
 * @param data pointer to the byte array of data to be included in the packet
214
 * @param length the length of the data array
215
 * @param group the packet group of the packet 
216
 * @param dest robot ID (for robot to robot packet)
217
 * @param mode flag for using FAST or RELIABLE sending
218
 *
219
 * @return positive packet number for tracking acks, or error code (TBD)
220
 **/
221
int16_t wl_send_robot(uint8_t *data, uint8_t length, uint8_t group, uint16_t dest, uint8_t mode) {
222
  return wl_send(data, length, group, GLOBAL, dest, mode);
223
}
224

    
225
/**
226
 * Default (i.e. basic) send wrapper.
227
 *
228
 * @param data pointer to the byte array of data to be included in the packet
229
 * @param length the length of the data array
230
 *
231
 * @return positive packet number for tracking acks, or error code (TBD)
232
 **/
233
int16_t wl_send_basic(uint8_t *data, uint8_t length) {
234
/** Check if it needs to adjust according to data type. **/
235
  return wl_send(data, length, BASIC, GLOBAL, BROADCAST, RELIABLE);
236
}
237

    
238

    
239
/**
240
 * acknowledgment error
241
 * check if any of the packets you have sent have been lost.
242
 *
243
 * note that all other error checking will be handled by library, 
244
 * so your user behavior won't have to worry about it
245
 *
246
 * @return the # of packets lost (up to 255)
247
 **/
248
uint8_t wl_ack_error(void) {
249
  uint8_t val=0,i=1;
250
  
251
  while(1) {
252
    if (((ack_buf[i/4])&(0x2<<(i%4))) != 0) // if the ack is in an error state
253
      val++;
254
    if (i==255)
255
      break;
256
    i++;
257
  }
258

    
259
  return val;
260
}
261

    
262
/**
263
 * acknowledgement error check
264
 * check if a specific packet has been lost
265
 * note: buffer will overflow every 255 packets
266
 * 
267
 * @param packet packet number
268
 *
269
 * @return {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
270
 **/
271
int8_t wl_ack_check(uint8_t packet) {
272
  if (packet == 0) {
273
    // no ack information here
274
    WL_DEBUG_PRINT("packet number cannot be 0\r\n");
275
    return WL_ERROR_ARGUMENT;
276
  }
277
  
278
  // check ack
279
  return ack_buf[packet/4]&(0x3<<(packet%4));
280
}
281

    
282
/**
283
 * acknowledgement reset
284
 * reset the acknowledgement buffer
285
 **/
286
void wl_ack_reset(void) {
287
  memset(ack_buf,0,64);
288
}
289

    
290

    
291
/**@} **/ //end defgroup
292

    
293

    
294
// Define all private functions down here
295

    
296
/*
297
 * sets 2 bits in the ack_buf
298
 *
299
 * @param num the ack number
300
 * @param val {SENDING,ACK_OK,ACK_FAILURE,CCA_FAILURE}
301
 */
302
void setack(uint8_t num,uint8_t val) {
303
  switch(num%4) {
304
  case 0:
305
    ack_buf[num/4] &= (0xFC|val);
306
    break;
307
  case 1:
308
    ack_buf[num/4] &= (0xF3|(val<<2));
309
    break;
310
  case 2:
311
    ack_buf[num/4] &= (0xCF|(val<<4));
312
    break;
313
  case 3:
314
    ack_buf[num/4] &= (0x3F|(val<<6));
315
    break;
316
  }
317
}
318

    
319

    
320
/* ack handler */
321
void ackhandle(uint8_t num,uint8_t val) {
322
  uint8_t len;
323
  switch(val) {
324
  case 0:
325
    // success
326
    setack(num,ACK_OK); // set status code
327
    // remove from buffer
328
    val = send_buf_first;
329
    if (send_buf_num_packets == 0)
330
      return;
331
    while (1) {
332
      len = send_buf_get(&val);
333
      if (send_buf_get(&val) != num) {
334
        // not the correct packet, so continue
335
        val += len;
336
        if (val >= PACKET_BUFFER_SIZE)
337
          val -= PACKET_BUFFER_SIZE;
338
        if (val == send_buf_last) {
339
          // reached end of bufer, so assume not present
340
          return;
341
        }
342
      } else {
343
        // remove packet
344
        num = val+len;
345
        val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2;
346
        if (num >= PACKET_BUFFER_SIZE)
347
          num -= PACKET_BUFFER_SIZE;
348
        while(num != send_buf_last) {
349
          if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
350
            return; // error
351
        }
352
        send_buf_last = val; // set new end of buffer
353
        return;
354
      }
355
    }
356
    break;
357
  case 1:
358
    // no ack
359
    // check resend attempts
360
    val = send_buf_first;
361
    if (send_buf_num_packets == 0)
362
      return;
363
    while (1) {
364
      len = send_buf_get(&val);
365
      if (send_buf_get(&val) != num) {
366
        // not the correct packet, so continue
367
        val += len;
368
        if (val >= PACKET_BUFFER_SIZE)
369
          val -= PACKET_BUFFER_SIZE;
370
        if (val == send_buf_last) {
371
          // reached end of bufer, so assume not present
372
          setack(num,ACK_FAILURE); // mark as failed send
373
          return;
374
        }
375
      } else {
376
        // check attempts on packet
377
        num = val+len-1; // set to end of packet
378
        if (num >= PACKET_BUFFER_SIZE)
379
          num -= PACKET_BUFFER_SIZE;
380
        if (send_buf[num] < NUM_RETRIES) {
381
          val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; // set to start of this packet
382
          // retry sending
383
          send_buf[num]++; // increment retries
384
          val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // go back one byte
385
          if (xbee_send_header(len+1) != WL_SUCCESS) {
386
            WL_DEBUG_PRINT("Error sending packet from ackhandle function\r\n");
387
            return;
388
          }
389
          len = XBEE_FRAME_TX_REQUEST_16;
390
          while(val!=num) {
391
            // compute checksum
392
            len += send_buf[val];
393
            if (xbee_putc(send_buf_get(&val)) != WL_SUCCESS) { // send  byte
394
              WL_DEBUG_PRINT("Error sending packet from ackhandle function\r\n");
395
              return;
396
            }
397
          }
398
          len = 0xFF - len;
399
          if (xbee_putc(len) != WL_SUCCESS) { // send
400
            WL_DEBUG_PRINT("Error sending packet from ackhandle function\r\n");
401
            return;
402
          }
403
          return;
404
        } else {
405
          // done sending, mark as failed send
406
          val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to frame num
407
          setack(send_buf[val],ACK_FAILURE);
408
          val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet
409
          // remove packet
410
          while(num != send_buf_last) {
411
            if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
412
              return; // error
413
          }
414
          return;
415
        }
416
      }
417
    }    
418
    break; // shouldn't get here, but just in case
419
  case 2:
420
    // CCA failure
421
    // check resend attempts
422
    val = send_buf_first;
423
    if (send_buf_num_packets == 0)
424
      return;
425
    while (1) {
426
      len = send_buf_get(&val);
427
      if (send_buf_get(&val) != num) {
428
        // not the correct packet, so continue
429
        val += len;
430
        if (val >= PACKET_BUFFER_SIZE)
431
          val -= PACKET_BUFFER_SIZE;
432
        if (val == send_buf_last) {
433
          // reached end of bufer, so assume not present
434
          setack(num,CCA_FAILURE); // mark as failed send
435
          return;
436
        }
437
      } else {
438
        // check attempts on packet
439
        num = val+len-1; // set to end of packet
440
        if (num >= PACKET_BUFFER_SIZE)
441
          num -= PACKET_BUFFER_SIZE;
442
        if (send_buf[num] < NUM_RETRIES) {
443
          val = (val<2)?PACKET_BUFFER_SIZE+val-2:val-2; // set to start of this packet
444
          // retry sending
445
          send_buf[num]++; // increment retries
446
          val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // go back one byte
447
          if (xbee_send_header(len+1) != WL_SUCCESS) {
448
            WL_DEBUG_PRINT("Error sending packet from ackhandle function\r\n");
449
            return;
450
          }
451
          len = XBEE_FRAME_TX_REQUEST_16;
452
          while(val!=num) {
453
            // compute checksum
454
            len += send_buf[val];
455
            if (xbee_putc(send_buf_get(&val)) != WL_SUCCESS) { // send  byte
456
              WL_DEBUG_PRINT("Error sending packet from ackhandle function\r\n");
457
              return;
458
            }
459
          }
460
          len = 0xFF - len;
461
          if (xbee_putc(len) != WL_SUCCESS) { // send
462
            WL_DEBUG_PRINT("Error sending packet from ackhandle function\r\n");
463
            return;
464
          }
465
          return;
466
        } else {
467
          // done sending, mark as failed send
468
          val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to frame num
469
          setack(send_buf[val],CCA_FAILURE);
470
          val = (val==0)?PACKET_BUFFER_SIZE-1:val-1; // set to start of this packet
471
          // remove packet
472
          while(num != send_buf_last) {
473
            if (send_buf_add(&val,send_buf_get(&num)) != WL_SUCCESS)
474
              return; // error
475
          }
476
          return;
477
        }
478
      }
479
    }    
480
    break; // shouldn't get here, but just in case
481
  }
482
}
483

    
484
/* adds a byte to the send buffer */
485
int8_t send_buf_add(uint8_t *ptr, uint8_t byte) {
486
  if (*ptr == send_buf_first) {
487
    // buffer full
488
    WL_DEBUG_PRINT("send buffer full\r\n");
489
    return WL_ERROR_SENDING_BUFFER_FULL;
490
  }
491
  send_buf[(*ptr)++] = byte;
492
  if (*ptr == PACKET_BUFFER_SIZE)
493
    *ptr = 0;
494
  return WL_SUCCESS;
495
}
496
/* gets a byte from the send buffer */
497
uint8_t send_buf_get(uint8_t *ptr) {
498
  uint8_t byte = send_buf[(*ptr)++];
499
  if (*ptr == PACKET_BUFFER_SIZE)
500
    *ptr = 0;
501
  return byte;
502
}