Project

General

Profile

Statistics
| Revision:

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

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
static 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
static int wl_send_packet(char group, char type, char* data, int len, int dest, char options, char frame);
59

    
60
/*Data Members*/
61

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

    
67
static PacketGroupHandler* wl_packet_groups[WL_MAX_PACKET_GROUPS];
68

    
69
#ifndef ROBOT
70

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

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

    
94
#endif
95

    
96
/**
97
 * Initializes the wireless library. Must be called before any
98
 * other function.
99
 *
100
 * @param wl_port File descriptor for wireless port, or NULL for default.
101
 **/
102
int wl_init()
103
{
104
        int i;
105
        for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
106
                wl_packet_groups[i] = NULL;
107

    
108
        if (xbee_lib_init() == -1) {
109
                return -1;
110
        }
111

    
112
        //begin timeout timer
113
#ifdef ROBOT
114
#ifdef FIREFLY
115
        rtc_init(PRESCALE_DIV_256, 32, &timer_handler);
116
#else
117
        rtc_init(HALF_SECOND, &timer_handler);
118
#endif
119
#else
120

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

    
138
        //create signal handler
139
        struct sigaction wl_sig_act;
140
        wl_sig_act.sa_handler = sig_handler;
141
        wl_sig_act.sa_flags = 0;
142
        sigemptyset(&wl_sig_act.sa_mask);
143
        sigaction(SIGALRM, &wl_sig_act, 0);
144
        sigaction(SIGINT, &wl_sig_act, 0);
145
#endif
146

    
147
        return 0;
148
}
149

    
150
/**
151
 * Uninitializes the wireless library.
152
 **/
153
void wl_terminate()
154
{
155
        int i;
156
        for (i = 0; i < WL_MAX_PACKET_GROUPS; i++) {
157
                if (wl_packet_groups[i] != NULL &&
158
                        wl_packet_groups[i]->unregister != NULL) {
159
                        wl_packet_groups[i]->unregister();
160
                }
161
        }
162

    
163
        xbee_terminate();
164
}
165

    
166
/**
167
 * Set the PAN for the XBee to join.
168
 *
169
 * @param pan the new PAN
170
 *
171
 * @see wl_get_pan
172
 **/
173
int wl_set_pan(int pan)
174
{
175
        return xbee_set_pan_id(pan);
176
}
177

    
178
/**
179
 * Get the PAN the XBee is currently part of.
180
 *
181
 * @return the PAN of the XBee
182
 *
183
 * @see wl_set_pan
184
 **/
185
int wl_get_pan(void)
186
{
187
        return xbee_get_pan_id();
188
}
189

    
190
/**
191
 * Set the channel the XBee is listening to.
192
 *
193
 * @param channel the new channel to join
194
 *
195
 * @see wl_get_channel
196
 **/
197
int wl_set_channel(int channel)
198
{
199
        return xbee_set_channel(channel);
200
}
201

    
202
/**
203
 * Get the channel the XBee is part of.
204
 *
205
 * @return the channel the XBee is part of
206
 *
207
 * @see wl_set_channel
208
 **/
209
int wl_get_channel(void)
210
{
211
        return xbee_get_channel();
212
}
213

    
214
/**
215
 * Returns the 16-bit address of the XBee module.
216
 *
217
 * @return the 16-bit address of the XBee module.
218
 **/
219
int wl_get_xbee_id()
220
{
221
        return xbee_get_address();
222
}
223

    
224
/**
225
 * Send a packet to a specific XBee without specifying a PAN.
226
 *
227
 * @param group the packet group
228
 * @param type the packet type
229
 * @param data the packet data
230
 * @param len the packet length in bytes
231
 * @param dest the 16-bit address of the XBee to send the packet to
232
 * @param frame the frame number to see with a TX_STATUS response
233
 **/
234
int wl_send_robot_to_robot_global_packet(char group, char type, char* data, int len, int dest, char frame)
235
{
236
        return wl_send_packet(group, type, data, len, dest, XBEE_OPTIONS_BROADCAST_ALL_PANS, frame);
237
}
238

    
239
/**
240
 * Send a packet to a specific XBee in the same PAN.
241
 *
242
 * @param group the packet group
243
 * @param type the packet type
244
 * @param data the packet data
245
 * @param len the packet length in bytes
246
 * @param dest the 16-bit address of the XBee to send the packet to
247
 * @param frame the frame number to see with a TX_STATUS response
248
 **/
249
int wl_send_robot_to_robot_packet(char group, char type, char* data, int len, int dest, char frame)
250
{
251
        return wl_send_packet(group, type, data, len, dest, XBEE_OPTIONS_NONE, frame);
252
}
253

    
254
/**
255
 * Send a packet to all XBees in all PANs.
256
 *
257
 * @param group the packet group
258
 * @param type the packet type
259
 * @param data the packet data
260
 * @param len the packet length in bytes
261
 * @param frame the frame number to see with a TX_STATUS response
262
 **/
263
int wl_send_global_packet(char group, char type, char* data, int len, char frame)
264
{
265
        return wl_send_packet(group, type, data, len, XBEE_BROADCAST, XBEE_OPTIONS_BROADCAST_ALL_PANS, frame);
266
}
267

    
268
/**
269
 * Send a packet to all XBee's in the same PAN.
270
 *
271
 * @param group the packet group
272
 * @param type the packet type
273
 * @param data the packet data
274
 * @param len the packet length in bytes
275
 * @param frame the frame number to see with a TX_STATUS response
276
 **/
277
void wl_send_pan_packet(char group, char type, char* data, int len, char frame)
278
{
279
        wl_send_packet(group, type, data, len, XBEE_BROADCAST,
280
                        XBEE_OPTIONS_NONE, frame);
281
}
282

    
283
/**
284
 * Send a packet.
285
 *
286
 * @param group the packet group
287
 * @param type the packet type
288
 * @param data the packet data
289
 * @param len the packet length in bytes
290
 * @param dest the destination of the packet
291
 * @param options the options for sending the packet
292
 * @param frame the frame number to see with a TX_STATUS response
293
 **/
294
int wl_send_packet(char group, char type, char* data, int len, int dest, char options, char frame)
295
{
296
        char buf[128];
297
        int i;
298
        if (frame != 0)
299
                frame = (frame & 0x0F) | ((group & 0x0F) << 4);
300

    
301
        buf[0] = group;
302
        buf[1] = type;
303
        for (i = 0; i < len; i++)
304
                buf[2 + i] = data[i];
305

    
306
        return xbee_send_packet(buf, len + 2, dest, options, frame);
307
}
308

    
309
/**
310
 * Register a packet group with the wireless library. The event
311
 * handlers in the packet group will be called whenever an
312
 * event dealing with the packet group's group code occurs.
313
 *
314
 * @param h the PacketGroupHandler to register
315
 **/
316
void wl_register_packet_group(PacketGroupHandler* h)
317
{
318
        if (h->groupCode >= WL_MAX_PACKET_GROUPS)
319
        {
320
                WL_DEBUG_PRINT("Packet group code too large.\r\n");
321
                return;
322
        }
323
        if (wl_packet_groups[h->groupCode] != NULL)
324
        {
325
                WL_DEBUG_PRINT("Packet group code already registered.\r\n");
326
                return;
327
        }
328
        wl_packet_groups[h->groupCode] = h;
329
}
330

    
331
/**
332
 * Unregister a packet group from the wireless library.
333
 *
334
 * @param h the packet group to remove
335
 **/
336
void wl_unregister_packet_group(PacketGroupHandler* h)
337
{
338
        unsigned int groupCode = h->groupCode;
339
        PacketGroupHandler* p = wl_packet_groups[groupCode];
340
        if (p != NULL && p->unregister != NULL)
341
                p->unregister();
342
        wl_packet_groups[groupCode] = NULL;
343
}
344

    
345
/**
346
 * Called when the timer is triggered. This calls the timeout
347
 * handlers of all the registered packet groups.
348
 **/
349
void wl_do_timeout()
350
{
351
        int i;
352
        for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
353
                if (wl_packet_groups[i] != NULL &&
354
                        wl_packet_groups[i]->timeout_handler != NULL)
355
                        wl_packet_groups[i]->timeout_handler();
356
}
357

    
358
/**
359
 * Performs wireless library functionality. This function must
360
 * be called frequently for wireless to perform effectively.
361
 * This function will call timeout handlers, as well as
362
 * received packet and transmit status handlers.
363
 **/
364
void wl_do()
365
{
366
        if (wl_timeout)
367
        {
368
                wl_do_timeout();
369
                wl_timeout = 0;
370
        }
371

    
372
        int len = xbee_get_packet(wl_buf);
373
        if (len < 0)//no packet received
374
                return;
375

    
376
        if (wl_buf[0] == XBEE_TX_STATUS)
377
        {
378
                if (len != 3)
379
                {
380
                        WL_DEBUG_PRINT("Transmit Status packet should be of length 3.\r\n");
381
                        return;
382
                }
383

    
384
                //the first four bits are the packet group
385
                //this only works with under 16 groups
386
                int group = (int)(wl_buf[1] >> 4);
387
                int success = 0;
388
                if (wl_buf[2] == 0) {
389
                        success = 1;
390
                }
391
                else
392
                {
393
                        WL_DEBUG_PRINT("No response received.\r\n");
394
                        if (wl_buf[2] == 2)
395
                        {
396
                                WL_DEBUG_PRINT("CCA Failure\r\n");
397
                        }
398
                        if (wl_buf[2] == 3)
399
                        {
400
                                WL_DEBUG_PRINT("Purged\r\n");
401
                        }
402
                }
403

    
404
                if (wl_packet_groups[group] != NULL && wl_packet_groups[group]->handle_response != NULL)
405
                        wl_packet_groups[group]->handle_response((int)wl_buf[1] & 0x0F, success);
406
                return;
407
        }
408

    
409
        if (wl_buf[0] == XBEE_RX)
410
        {
411
                if (len < 7)
412
                {
413
                        WL_DEBUG_PRINT("Packet is too small.\r\n");
414
                        return;
415
                }
416

    
417
                int source = ((int)wl_buf[1] << 8) + ((int)wl_buf[2]);
418

    
419
                /*
420
                //unused for now
421
                int signalStrength = wl_buf[3];
422
                //1 for Address broadcast, 2 for PAN broadcast
423
                int options = wl_buf[4];
424
                */
425

    
426
                int group = wl_buf[5];
427
                int type = wl_buf[6];
428
                int packetLen = len - 7;
429

    
430
                if (wl_packet_groups[group] != NULL && wl_packet_groups[group]->handle_receive != NULL)
431
                        wl_packet_groups[group]->handle_receive(type, source, wl_buf + 7, packetLen);
432
                return;
433
        }
434

    
435
        WL_DEBUG_PRINT("Unexpected packet received from XBee.\r\n");
436
        return;
437
}
438

    
439

    
440
#ifndef ROBOT
441
void wl_set_com_port(char* port)
442
{
443
        xbee_set_com_port(port);
444
}
445
#endif
446