Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / libwireless / lib / wireless.c @ 343

History | View | Annotate | Download (10.2 KB)

1
/**
2
 * Copyright (c) 2007 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.c
28
 * @brief Wireless Library Implementation
29
 *
30
 * Implementation of the wireless library.
31
 *
32
 * @author Brian Coltin, Colony Project, CMU Robotics Club
33
 **/
34

    
35
#include "wireless.h"
36
#include "xbee.h"
37
#include <stdlib.h>
38
#include <stdio.h>
39

    
40
#include "wl_defs.h"
41

    
42
#ifndef ROBOT
43
#include <sys/time.h>
44
#include <signal.h>
45
#else
46
#include <time.h>
47
#ifndef FIREFLY
48
#include <bom.h>
49
#endif
50
#endif
51

    
52
/*Function Prototypes*/
53

    
54
void wl_do_timeout(void);
55

    
56
//Note: the actual frame sent has group as the first four bits and
57
//frame as the last four.
58
void wl_send_packet(char group, char type, char* data, int len,
59
                    int dest, char options, char frame);
60

    
61
/*Data Members*/
62

    
63
//used to store incoming and outgoing packets
64
unsigned char wl_buf[128];
65
//1 if we have timed out since we last checked, 0 otherwise.
66
int wl_timeout = 0;
67

    
68
PacketGroupHandler* wl_packet_groups[WL_MAX_PACKET_GROUPS];
69

    
70
#ifndef ROBOT
71

    
72
//called when we time out, or receive interrupt
73
void sig_handler(int signo) {
74
  switch (signo)        {
75
  case SIGALRM:
76
    wl_timeout = 1;
77
    break;
78
  case SIGINT:
79
    wl_terminate();
80
    exit(1);
81
    break;
82
  }
83
  return;
84
}
85
#else
86

    
87
//called when the timer ticks
88
void timer_handler(void) {
89
  wl_timeout = 1;
90
}
91

    
92
#endif
93

    
94
/**
95
 * Initializes the wireless library. Must be called before any
96
 * other function.
97
 **/
98
int wl_init() {
99
  int i;
100
  for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
101
    wl_packet_groups[i] = NULL;
102

    
103
  if (xbee_lib_init() == -1) {
104
    return -1;
105
  }
106

    
107
  //begin timeout timer
108
#ifdef ROBOT
109
#ifdef FIREFLY
110
  rtc_init(PRESCALE_DIV_256, 32, &timer_handler);
111
#else
112
  rtc_init(HALF_SECOND, &timer_handler);
113
#endif
114
#else
115

    
116
  //create our timer
117
  struct itimerval timer_val;
118
  struct timeval interval;
119
  interval.tv_sec = 0;
120
  interval.tv_usec = 500000;
121
  struct timeval first_time;
122
  first_time.tv_sec = 0;
123
  first_time.tv_usec = 500000;
124
  timer_val.it_interval = interval;
125
  timer_val.it_value = first_time;
126
  if(setitimer(ITIMER_REAL,&timer_val,NULL)==-1) {
127
    WL_DEBUG_PRINT("Error creating a timer.\r\n");
128
    perror("Failure's cause");
129
    exit(1);
130
  }
131

    
132
  //create signal handler
133
  struct sigaction wl_sig_act;
134
  wl_sig_act.sa_handler = sig_handler;
135
  wl_sig_act.sa_flags = 0;
136
  sigemptyset(&wl_sig_act.sa_mask);
137
  sigaction(SIGALRM, &wl_sig_act, 0);
138
  sigaction(SIGINT, &wl_sig_act, 0);
139
#endif
140

    
141
  return 0;
142
}
143

    
144
/**
145
 * Uninitializes the wireless library.
146
 **/
147
void wl_terminate() {
148
  int i;
149
  for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
150
    if (wl_packet_groups[i] != NULL &&
151
        wl_packet_groups[i]->unregister != NULL)
152
      wl_packet_groups[i]->unregister();
153

    
154
  xbee_terminate();
155
}
156

    
157
/**
158
 * Set the PAN for the XBee to join.
159
 *
160
 * @param pan the new PAN
161
 *
162
 * @see wl_get_pan
163
 **/
164
void wl_set_pan(int pan) {
165
  xbee_set_pan_id(pan);
166
}
167

    
168
/**
169
 * Get the PAN the XBee is currently part of.
170
 *
171
 * @return the PAN of the XBee
172
 *
173
 * @see wl_set_pan
174
 **/
175
int wl_get_pan(void) {
176
  return xbee_get_pan_id();
177
}
178

    
179
/**
180
 * Set the channel the XBee is listening to.
181
 *
182
 * @param channel the new channel to join
183
 *
184
 * @see wl_get_channel
185
 **/
186
void wl_set_channel(int channel) {
187
  xbee_set_channel(channel);
188
}
189

    
190
/**
191
 * Get the channel the XBee is part of.
192
 *
193
 * @return the channel the XBee is part of
194
 *
195
 * @see wl_set_channel
196
 **/
197
int wl_get_channel(void) {
198
  return xbee_get_channel();
199
}
200

    
201
/**
202
 * Returns the 16-bit address of the XBee module.
203
 *
204
 * @return the 16-bit address of the XBee module.
205
 **/
206
int wl_get_xbee_id() {
207
  return xbee_get_address();
208
}
209

    
210
/**
211
 * Send a packet to a specific XBee without specifying a PAN.
212
 *
213
 * @param group the packet group
214
 * @param type the packet type
215
 * @param data the packet data
216
 * @param len the packet length in bytes
217
 * @param dest the 16-bit address of the XBee to send the packet to
218
 * @param frame the frame number to see with a TX_STATUS response
219
 **/
220
void wl_send_robot_to_robot_global_packet(char group, char type,
221
                                          char* data, int len, int dest, char frame) {
222
  wl_send_packet(group, type, data, len, dest,
223
                 XBEE_OPTIONS_BROADCAST_ALL_PANS, frame);
224
}
225

    
226
/**
227
 * Send a packet to a specific XBee in the same PAN.
228
 *
229
 * @param group the packet group
230
 * @param type the packet type
231
 * @param data the packet data
232
 * @param len the packet length in bytes
233
 * @param dest the 16-bit address of the XBee to send the packet to
234
 * @param frame the frame number to see with a TX_STATUS response
235
 **/
236
void wl_send_robot_to_robot_packet(char group, char type,
237
                                   char* data, int len, int dest, char frame) {
238
  wl_send_packet(group, type, data, len, dest, XBEE_OPTIONS_NONE,
239
                 frame);
240
}
241

    
242
/**
243
 * Send a packet to all XBees in all PANs.
244
 *
245
 * @param group the packet group
246
 * @param type the packet type
247
 * @param data the packet data
248
 * @param len the packet length in bytes
249
 * @param frame the frame number to see with a TX_STATUS response
250
 **/
251
void wl_send_global_packet(char group, char type,
252
                           char* data, int len, char frame) {
253
  wl_send_packet(group, type, data, len, XBEE_BROADCAST,
254
                 XBEE_OPTIONS_BROADCAST_ALL_PANS, frame);
255
}
256

    
257
/**
258
 * Send a packet to all XBee's in the same PAN.
259
 *
260
 * @param group the packet group
261
 * @param type the packet type
262
 * @param data the packet data
263
 * @param len the packet length in bytes
264
 * @param frame the frame number to see with a TX_STATUS response
265
 **/
266
void wl_send_pan_packet(char group, char type,
267
                        char* data, int len, char frame) {
268
  wl_send_packet(group, type, data, len, XBEE_BROADCAST,
269
                 XBEE_OPTIONS_NONE, frame);
270
}
271

    
272
/**
273
 * Send a packet.
274
 *
275
 * @param group the packet group
276
 * @param type the packet type
277
 * @param data the packet data
278
 * @param len the packet length in bytes
279
 * @param dest the destination of the packet
280
 * @param options the options for sending the packet
281
 * @param frame the frame number to see with a TX_STATUS response
282
 **/
283
void wl_send_packet(char group, char type, char* data, int len,
284
                    int dest, char options, char frame) {
285
  char buf[128];
286
  int i;
287
  if (frame != 0)
288
    frame = (frame & 0x0F) | ((group & 0x0F) << 4);
289
  buf[0] = group;
290
  buf[1] = type;
291
  for (i = 0; i < len; i++)
292
    buf[2 + i] = data[i];
293
  xbee_send_packet(buf, len + 2, dest, options, frame);
294
}
295

    
296
/**
297
 * Register a packet group with the wireless library. The event
298
 * handlers in the packet group will be called whenever an
299
 * event dealing with the packet group's group code occurs.
300
 *
301
 * @param h the PacketGroupHandler to register
302
 **/
303
void wl_register_packet_group(PacketGroupHandler* h) {
304
  if (h->groupCode >= WL_MAX_PACKET_GROUPS) {
305
    WL_DEBUG_PRINT("Packet group code too large.\r\n");
306
    return;
307
  }
308
  if (wl_packet_groups[h->groupCode] != NULL) {
309
    WL_DEBUG_PRINT("Packet group code already registered.\r\n");
310
    return;
311
  }
312
  wl_packet_groups[h->groupCode] = h;
313
}
314

    
315
/**
316
 * Unregister a packet group from the wireless library.
317
 *
318
 * @param h the packet group to remove
319
 **/
320
void wl_unregister_packet_group(PacketGroupHandler* h) {
321
  unsigned int groupCode = h->groupCode;
322
  PacketGroupHandler* p = wl_packet_groups[groupCode];
323
  if (p != NULL && p->unregister != NULL)
324
    p->unregister();
325
  wl_packet_groups[groupCode] = NULL;
326
}
327

    
328
/**
329
 * Called when the timer is triggered. This calls the timeout
330
 * handlers of all the registered packet groups.
331
 **/
332
void wl_do_timeout() {
333
  int i;
334
  for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
335
    if (wl_packet_groups[i] != NULL &&
336
        wl_packet_groups[i]->timeout_handler != NULL)
337
      wl_packet_groups[i]->timeout_handler();
338
}
339

    
340
/**
341
 * Performs wireless library functionality. This function must
342
 * be called frequently for wireless to perform effectively.
343
 * This function will call timeout handlers, as well as
344
 * received packet and transmit status handlers.
345
 **/
346
void wl_do() {
347
  if (wl_timeout) {
348
    wl_do_timeout();
349
    wl_timeout = 0;
350
  }
351

    
352
  int len = xbee_get_packet(wl_buf);
353
  if (len < 0)//no packet received
354
    return;
355

    
356
  if (wl_buf[0] == XBEE_TX_STATUS) {
357
    if (len != 3) {
358
      WL_DEBUG_PRINT("Transmit Status packet should be of length 3.\r\n");
359
      return;
360
    }
361

    
362
    //the first four bits are the packet group
363
    //this only works with under 16 groups
364
    int group = (int)(wl_buf[1] >> 4);
365
    int success = 0;
366
    if (wl_buf[2] == 0)
367
      success = 1;
368
    else {
369
      WL_DEBUG_PRINT("No response received.\r\n");
370
      if (wl_buf[2] == 2) {
371
        WL_DEBUG_PRINT("CCA Failure\r\n");
372
      }
373
      if (wl_buf[2] == 3) {
374
        WL_DEBUG_PRINT("Purged\r\n");
375
      }
376
    }
377

    
378
    if (wl_packet_groups[group] != NULL &&
379
        wl_packet_groups[group]->handle_response != NULL)
380
      wl_packet_groups[group]->handle_response(
381
                                               (int)wl_buf[1] & 0x0F, success);
382
    return;
383
  }
384

    
385
  if (wl_buf[0] == XBEE_RX) {
386
    if (len < 7) {
387
      WL_DEBUG_PRINT("Packet is too small.\r\n");
388
      return;
389
    }
390

    
391
    int source = ((int)wl_buf[1] << 8) + ((int)wl_buf[2]);
392

    
393
    /*
394
    //unused for now
395
    int signalStrength = wl_buf[3];
396
    //1 for Address broadcast, 2 for PAN broadcast
397
    int options = wl_buf[4];
398
    */
399

    
400
    int group = wl_buf[5];
401
    int type = wl_buf[6];
402
    int packetLen = len - 7;
403

    
404
    if (wl_packet_groups[group] != NULL
405
        && wl_packet_groups[group]->handle_receive != NULL)
406
      wl_packet_groups[group]->handle_receive(type, source,
407
                                              wl_buf + 7, packetLen);
408
    return;
409
  }
410

    
411
  WL_DEBUG_PRINT("Unexpected packet received from XBee.\r\n");
412
  return;
413
}
414

    
415

    
416
#ifndef ROBOT
417
void wl_set_com_port(char* port) {
418
  xbee_set_com_port(port);
419
}
420
#endif
421