Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (15.4 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 <string.h>
39

    
40

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

    
55

    
56
/* global variables */
57
uint8_t nextframe = 1; // number of next frame
58
uint8_t ack_buf[64]; // ack buffer (holds 255 packet return codes)
59
uint8_t send_buf[PACKET_BUFFER_SIZE]; // sending buffer for retries
60
uint8_t send_buf_first = 0; // first byte of data on buffer
61
uint8_t send_buf_last = 0; // next free byte on buffer
62
uint8_t send_buf_num_packets = 0; // number of packets in sending buffer
63

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

    
70
// the send functions
71

    
72
/**
73
 * @addtogroup wireless Wireless
74
 * @{
75
 **/
76

    
77

    
78
/**
79
 * The core send function. This will take all possible arguments and send all types of packets.
80
 * 
81
 * @param data pointer to the byte array of data to be included in the packet
82
 * @param length the length of the data array
83
 * @param group the packet group of the packet
84
 * @param scope flag for sending global packet or your current PAN
85
 * @param dest robot ID (for robot to robot packet)
86
 * @param mode flag for using FAST or RELIABLE sending
87
 *
88
 * @return positive packet number for tracking acks, or error code (TBD)
89
 **/
90
int16_t wl_send(uint8_t *data, uint8_t length, uint8_t group, uint8_t scope, uint16_t dest, uint8_t mode) {
91
  uint8_t packet[6];
92
  
93
  // build packet header
94
  packet[0] = nextframe;
95
  packet[1] = (dest&0xFF00)>>8;
96
  packet[2] = dest&0x00FF;  
97
  packet[3] = XBEE_OPTIONS_NONE;
98
  packet[4] = nextframe;
99
  packet[5] = group;
100
  
101
  // set scope
102
  if (scope == GLOBAL)
103
    packet[3] &= XBEE_OPTIONS_BROADCAST_ALL_PANS;
104
  else if (scope != PAN) {
105
    WL_DEBUG_PRINT("Error - bad scope in core send function\r\n");
106
    return WL_ERROR_SCOPE;
107
  }
108
    
109
  // set mode
110
  if (mode == FAST) {
111
    packet[3] &= XBEE_OPTIONS_DISABLE_RESPONSE;
112
  } else if (mode != RELIABLE) {
113
    WL_DEBUG_PRINT("Error - bad mode in core send function\r\n");
114
    return WL_ERROR_MODE;
115
  }
116
  
117
  // do checksum
118
  group = XBEE_FRAME_TX_REQUEST_16;
119
  xbee_checksum_add(packet,6,&group);
120
  xbee_checksum_add(data,length,&group); 
121
  group = 0xFF-group;
122

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

    
179
  return ret_val; // return frame number for ack tracking
180
}
181

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

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

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

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

    
236

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

    
257
  return val;
258
}
259

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

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

    
288

    
289
/**@} **/ //end defgroup
290

    
291

    
292
// Define all private functions down here
293

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

    
317

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

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