Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (15.2 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

    
193
  return 0;
194
}
195

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

    
207
  return 0;
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(char *data, uint8_t length, uint8_t group, uint16_t dest, uint8_t mode) {
222

    
223
  return 0;
224
}
225

    
226
/**
227
 * Default (i.e. basic) send wrapper.
228
 *
229
 * @param data pointer to the byte array of data to be included in the packet
230
 * @param length the length of the data array
231
 *
232
 * @return positive packet number for tracking acks, or error code (TBD)
233
 **/
234
int16_t wl_send_basic(char *data, uint8_t length) {
235

    
236
  return 0;
237
}
238

    
239

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

    
260
  return val;
261
}
262

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

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

    
291

    
292
/**@} **/ //end defgroup
293

    
294

    
295
// Define all private functions down here
296

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

    
320

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

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