Project

General

Profile

Revision 207

Updated the library

View differences:

branches/slam/code/projects/libwireless/lib/wireless.h
1
/**
2
 * @file wireless.h
3
 * @brief Contains definitions for the wireless library.
4
 *
5
 * Contains functions for the wireless library.
6
 *
7
 * @author Brian Coltin, Colony Project, CMU Robotics Club
8
 **/
9

  
10
#ifndef WIRELESS_H
11
#define WIRELESS_H
12
 
13
//Note: If this is raised above 16, we will need to do
14
//something about frame numbers for TX Status packets.
15
/**
16
 * The maximum number of packet groups.
17
 **/
18
#define WL_MAX_PACKET_GROUPS 16
19

  
20
/**
21
 * @defgroup wireless Wireless
22
 * @brief Wireless definitions.
23
 *
24
 * Contains functions and definitions for dealing with wireless functionality.<br><br>
25
 *
26
 * The wireless library provides a modular method for dealing with 
27
 * wireless packets, by allowing packet groups to be registered.
28
 * A packet group is a collection of packets which share a packet
29
 * group code. Each packet in the group also has a type. A packet 
30
 * group code and type are sent with each packet. When a packet
31
 * with a group code registered in the wireless library is 
32
 * received, the corresponding event handler is called. The
33
 * event handler uses the packet type and other information
34
 * stored in the packet to respond.<br><br>
35
 *
36
 * This architecture allows different wireless functionality to be
37
 * defined and handled separately, making it simpler and more
38
 * efficient to take advantage of the XBee's wireless functionality.
39
 *
40
 * @{
41
 **/
42

  
43
/**
44
 * @struct PacketGroupHandler
45
 * A PacketGroupHandler represents a packet group, and is used to 
46
 * register a packet group with the wireless library. It contains
47
 * handlers for various events which can occur related to a packet
48
 * group.
49
 **/
50
typedef struct
51
{
52
	/**
53
	 * The group code for this packet group. This number
54
	 * must be unique. The maximum number of packet groups
55
	 * is defined by WL_MAX_PACKET_GROUPS.
56
	 **/
57
	unsigned int groupCode;
58

  
59
	/**
60
	 * Called every half second (not in interrupt,
61
	 * but in wl_do).
62
	 **/
63
	void (*timeout_handler) (void);
64
	
65
	/**
66
	 * Called when a transmit status packet is received
67
	 * from the XBee where the first four bits of the frame
68
	 * are  the group code.
69
	 *
70
	 * @param frame the last four bits of the frame
71
	 * @param received is true if we received an ack, 0 if
72
	 * we did not.
73
	 **/
74
	void (*handle_response) (int frame, int received);
75
	
76
	/**
77
	 * Called when we receive a packet from this group.
78
	 *
79
	 * @param type the packet type
80
	 * @param source the 16-bit address of the XBee this
81
	 * packet was sent from
82
	 * @param packet the packet received
83
	 * @param length the length of the packet
84
	 **/
85
	void (*handle_receive) (char type, int source, unsigned char* packet,
86
							int length);
87
	
88
	/**
89
	 * Called for any cleanup when the network is turned off.
90
	 **/
91
	void (*unregister) (void);
92
	
93
} PacketGroupHandler;
94

  
95
/**@brief Initialize the wireless library **/
96
void wl_init(void);
97
/**@brief Uninitialize the wireless library **/
98
void wl_terminate(void);
99
/**@brief Perform wireless library functionality **/
100
void wl_do(void);
101
/**@brief Register a packet group with the wireless library **/
102
void wl_register_packet_group(PacketGroupHandler* h);
103
/**@brief Unregister a packet group with the wireless library **/
104
void wl_unregister_packet_group(PacketGroupHandler* h);
105

  
106
/**@brief Send a packet to a specific robot in any PAN **/
107
void wl_send_robot_to_robot_global_packet(char group, char type,
108
		char* data, int len, int dest, char frame);
109
/**@brief Send a packet to a specific robot in our PAN **/
110
void wl_send_robot_to_robot_packet(char group, char type,
111
		char* data, int len, int dest, char frame);
112
/**@brief Send a packet to all robots **/
113
void wl_send_global_packet(char group, char type,
114
		char* data, int len, char frame);
115
/**@brief Send a packet to all robots in our PAN **/
116
void wl_send_pan_packet(char group, char type,
117
		char* data, int len, char frame);
118

  
119
/**@brief Set the PAN we are using **/
120
void wl_set_pan(int pan);
121
/**@brief Get the PAN we are using **/
122
int wl_get_pan(void);
123
/**@brief Set the channel we are using **/
124
void wl_set_channel(int channel);
125
/**@brief Get the channel we are using **/
126
int wl_get_channel(void);
127
/**@brief Get the 16-bit address of the XBee module **/
128
unsigned int wl_get_xbee_id(void);
129
/**@brief Set the com port on a computer, undefined on the robot.**/
130
void wl_set_com_port(char* port);
131

  
132
/** @} **/ // end defgroup
133

  
134
#endif
135

  
branches/slam/code/projects/libwireless/lib/xbee.c
1
#include "xbee.h"
2
#include "wl_defs.h"
3

  
4
#ifndef ROBOT
5

  
6
#include <fcntl.h>
7
#include <unistd.h>
8
#include <pthread.h>
9
#include <errno.h>
10

  
11
#else
12

  
13
#include <serial.h>
14
#include <avr/interrupt.h>
15

  
16
#endif
17

  
18
#include <stdio.h>
19
#include <stdlib.h>
20
#include <string.h>
21

  
22
#include <queue.h>
23

  
24
#define XBEE_FRAME_START 0x7E
25

  
26
/*Frame Types*/
27
#define XBEE_FRAME_STATUS 0x8A
28
#define XBEE_FRAME_AT_COMMAND 0x08
29
#define XBEE_FRAME_AT_COMMAND_RESPONSE 0x88
30
#define XBEE_FRAME_TX_REQUEST_64 0x00
31
#define XBEE_FRAME_TX_REQUEST_16 0x01
32
#define XBEE_FRAME_TX_STATUS XBEE_TX_STATUS
33
#define XBEE_FRAME_RX_64 0x80
34
#define XBEE_FRAME_RX_16 XBEE_RX
35

  
36
/*Internal Function Prototypes*/
37

  
38
/*I/O Functions*/
39
void xbee_send(char* buf, int size);
40
void xbee_send_string(char* c);
41

  
42
#ifndef ROBOT
43
void xbee_read(char* buf, int size);
44
#endif
45

  
46
/*Command Mode Functions
47
 * Called during initialization.
48
 */
49
void xbee_enter_command_mode(void);
50
void xbee_exit_command_mode(void);
51
void xbee_enter_api_mode(void);
52
void xbee_wait_for_string(char* s, int len);
53
void xbee_wait_for_ok(void);
54

  
55
/*API Mode Functions*/
56

  
57
int xbee_handle_packet(char* packet, int len);
58
void xbee_handle_at_command_response(char* command, char result,
59
	char* extra, int extraLen);
60
void xbee_handle_status(char status);
61
int xbee_verify_checksum(char* packet, int len);
62
char xbee_compute_checksum(char* packet, int len);
63
void xbee_send_frame(char* buf, int len);
64
void xbee_send_read_at_command(char* command);
65
void xbee_send_modify_at_command(char* command, char* value);
66

  
67
/*Global Variables*/
68

  
69
#ifndef ROBOT
70
char* xbee_com_port;
71
int xbee_stream;
72
pthread_t* xbee_listen_thread;
73
#endif
74

  
75
Queue* xbee_queue;
76

  
77
//used to store packets as they are read
78
char xbee_buf[128];
79
int currentBufPos = 0;
80

  
81
//XBee status
82
unsigned int xbee_panID = XBEE_PAN_DEFAULT;
83
unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
84
int xbee_channel = XBEE_CHANNEL_DEFAULT;
85
int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
86
unsigned int xbee_address = 0;
87

  
88
/*Function Implementations*/
89

  
90
#ifdef ROBOT
91

  
92
/**
93
 * Interrupt for the robot. Adds bytes received from the xbee
94
 * to the queue.
95
 **/
96
#ifndef FIREFLY
97
ISR(USART1_RX_vect)
98
{
99
	char c = UDR1;
100
	queue_add(xbee_queue, (void*)(int)c);
101
}
102
#else
103
SIGNAL(SIG_USART0_RECV)
104
{
105
	char c = UDR0;
106
	queue_add(xbee_queue, (void*)(int)c);
107
}
108
#endif
109

  
110
#else
111

  
112
/**
113
 * Thread that listens to the xbee.
114
 **/
115
void* listen_to_xbee(void* x)
116
{
117
	char c;
118
	while (1)
119
	{
120
		xbee_read(&c, 1);
121
		queue_add(xbee_queue, (void*)(int)c);
122
	}
123
	return 0;
124
}
125

  
126
#endif
127

  
128
/**
129
 * Initializes the XBee library so that other functions may be used.
130
 *
131
 * @param pan_id the PAN to join initially. Use XBEE_PAN_DEFAULT
132
 * to leave the PAN as it is initially.
133
 **/
134
void xbee_lib_init(void)
135
{
136
	xbee_queue = queue_create();
137
	
138
	#ifdef ROBOT
139

  
140
	//enable the receiving interrupt
141
	#ifdef FIREFLY
142
	UCSR0B |= _BV(RXCIE) | _BV(RXEN);
143
	#else
144
	UCSR1B |= _BV(RXCIE);
145
	#endif
146
	sei();
147
	#else
148
	xbee_stream = open(xbee_com_port, O_RDWR);
149
	if (xbee_stream == -1 || lockf(xbee_stream, F_TEST, 0) != 0)
150
		xbee_stream = open(XBEE_PORT2, O_RDWR);
151
	if (xbee_stream == -1 || lockf(xbee_stream, F_TEST, 0) != 0)
152
	{
153
		printf("Failed to open connection to XBee on port %s\r\n",xbee_com_port);
154
		exit(0);
155
	}
156
	lockf(xbee_stream, F_LOCK, 0);
157
	
158
	xbee_listen_thread =
159
		(pthread_t*)malloc(sizeof(pthread_t));
160
	
161
	int ret = pthread_create(xbee_listen_thread, NULL, 
162
		listen_to_xbee, NULL);
163
	if (ret)
164
	{
165
		printf("Failed to create listener thread.\r\n");
166
		exit(0);
167
	}
168
	#endif
169
	xbee_enter_command_mode();
170
	xbee_enter_api_mode();
171
	xbee_exit_command_mode();
172
	xbee_send_read_at_command("MY");
173
	
174
	//wait to return until the address is set
175
	while (xbee_address == 0) xbee_get_packet(NULL);
176
}
177

  
178
/**
179
 * Call when finished using the XBee library. This releases
180
 * all sued resources.
181
 **/
182
void xbee_terminate()
183
{
184
	#ifndef ROBOT
185
	pthread_cancel(*xbee_listen_thread);
186
	free(xbee_listen_thread);
187
	lockf(xbee_stream, F_ULOCK, 0);
188
	close(xbee_stream);
189
	#endif
190
	queue_destroy(xbee_queue);
191
}
192

  
193
/**
194
 * Send a buffer buf of size bytes to the XBee.
195
 * 
196
 * @param buf the buffer of data to send
197
 * @param size the number of bytes to send
198
 **/
199
void xbee_send(char* buf, int size)
200
{
201
	#ifdef ROBOT
202
	int i;
203
	for (i = 0; i < size; i++)
204
		xbee_putc(buf[i]);
205
	#else
206
	int ret = write(xbee_stream, buf, size);
207
	//success
208
	if (ret == size)
209
		return;
210
	if (ret == -1)
211
	{
212
		//interrupted by system signal, probably timer interrupt.
213
		//just try again
214
		if (errno == 4)
215
		{
216
			xbee_send(buf, size);
217
			return;
218
		}
219
		printf("Failed to write to xbee, error %i.\r\n", errno);
220
		return;
221
	}
222

  
223
	//write was interrupted after writing ret bytes
224
	xbee_send(buf + ret, size - ret);
225
	#endif
226
}
227

  
228
/**
229
 * Sends a string to the XBee.
230
 *
231
 * @param c the string to send to the XBEE
232
 **/
233
void xbee_send_string(char* c)
234
{
235
	xbee_send(c, strlen(c));
236
}
237

  
238
#ifndef ROBOT
239
void xbee_read(char* buf, int size)
240
{
241
	if (read(xbee_stream, buf, size) == -1)
242
		printf("Failed to read from xbee.\r\n");
243
}
244
#endif
245

  
246
/**
247
 * Enter into command mode.
248
 **/
249
void xbee_enter_command_mode()
250
{
251
	xbee_send_string("+++");
252
	xbee_wait_for_ok();
253
}
254

  
255
/**
256
 * Exit from command mode.
257
 **/
258
void xbee_exit_command_mode()
259
{
260
	xbee_send_string("ATCN\r");
261
	xbee_wait_for_ok();
262
}
263

  
264
/**
265
 * Enter API mode.
266
 **/
267
void xbee_enter_api_mode()
268
{
269
	xbee_send_string("ATAP 1\r");
270
	xbee_wait_for_ok();
271
}
272

  
273
/**
274
 * Wait until the string "OK\r" is received from the XBee.
275
 **/
276
void xbee_wait_for_ok()
277
{
278
	xbee_wait_for_string("OK\r", 3);
279
}
280

  
281
/**
282
 * Delay until the specified string is received from
283
 * the XBee. Discards all other XBee data.
284
 *
285
 * @param s the string to receive
286
 * @param len the length of the string
287
 **/
288
void xbee_wait_for_string(char* s, int len)
289
{
290
	char* curr = s;
291
	while (curr - s < len)
292
	{
293
		if (queue_is_empty(xbee_queue))
294
			continue;
295
		char c = (char)(int)queue_remove(xbee_queue);
296
		if (c == *curr)
297
			curr++;
298
		else
299
			curr = s;
300
	}
301
}
302

  
303
/**
304
 * Verifies that the packets checksum is correct.
305
 * (If the checksum is correct, the sum of the bytes
306
 * is 0xFF.)
307
 *
308
 * @param packet the packet received. This includes the first
309
 * three bytes, which are header information from the XBee.
310
 *
311
 * @param len The length of the packet received from the XBee
312
 *
313
 * @return 0 if the checksum is incorrect, nonzero
314
 * otherwise
315
 **/
316
int xbee_verify_checksum(char* packet, int len)
317
{
318
	unsigned char sum = 0;
319
	int i;
320
	for (i = 3; i < len; i++)
321
		sum += (unsigned char)packet[i];
322
	return sum == 0xFF;
323
}
324

  
325
/**
326
 * Returns the checksum of the given packet.
327
 *
328
 * @param buf the data for the packet to send
329
 * @param len the length of the packet in bytes
330
 *
331
 * @return the checksum of the packet, which will
332
 * become the last byte sent in the packet
333
 **/
334
char xbee_compute_checksum(char* buf, int len)
335
{
336
	int i;
337
	unsigned char sum = 0;
338
	for (i = 0; i < len; i++)
339
		sum += (unsigned char)buf[i];
340
	return 0xFF - sum;
341
}
342

  
343
/**
344
 * Adds header information and checksum to the given
345
 * packet and sends it. Header information includes
346
 * XBEE_FRAME_START and the packet length, as two bytes.
347
 *
348
 * @param buf the packet data
349
 * @param len the size in bytes of the packet data
350
 *
351
 **/
352
void xbee_send_frame(char* buf, int len)
353
{
354
	char prefix[3];
355
	prefix[0] = XBEE_FRAME_START;
356
	prefix[1] = (len & 0xFF00) >> 8;
357
	prefix[2] = len & 0xFF;
358
	char checksum = xbee_compute_checksum(buf, len);
359
	xbee_send(prefix, 3);
360
	xbee_send(buf, len);
361
	xbee_send(&checksum, 1);
362
}
363

  
364
/**
365
 * Sends an AT command to read a parameter.
366
 *
367
 * @param command the AT command to send. For exmaple,
368
 * use ID to read the PAN ID and MY to return the XBee ID.
369
 * See the XBee reference guide for a complete listing.
370
 **/
371
void xbee_send_read_at_command(char* command)
372
{
373
	xbee_send_modify_at_command(command, NULL);
374
}
375

  
376
/**
377
 * Sends the given AT command.
378
 *
379
 * @param command the AT command to send (e.g., MY, ID)
380
 * @param value the value to pass as a parameter
381
 * (or NULL if there is no parameter)
382
 **/
383
void xbee_send_modify_at_command(char* command, char* value)
384
{
385
	char buf[16];
386
	int i;
387
	
388
	buf[0] = XBEE_FRAME_AT_COMMAND;
389
	buf[1] = 1;
390
	buf[2] = command[0];
391
	buf[3] = command[1];
392
	int valueLen = 0;
393
	if (value != NULL)
394
	{
395
		valueLen = strlen(value);
396
		if (valueLen > 8)
397
		{
398
			WL_DEBUG_PRINT("AT Command too large.\r\n");
399
			return;
400
		}
401
		for (i = 0; i < valueLen; i++)
402
			buf[4 + i] = value[i];
403
	}
404
	xbee_send_frame(buf, 4 + valueLen);
405
}
406

  
407
/**
408
 * Send the specified packet.
409
 * 
410
 * @param packet the packet data to send
411
 * @param len the number of bytes in the packet
412
 * 
413
 * @param dest the ID of the XBee to send the packet to,
414
 * or XBEE_BROADCAST to send the message to all robots
415
 * in the PAN.
416
 * 
417
 * @param options a combination of the flags
418
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and 
419
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
420
 *
421
 * @param frame the frame number to associate this packet
422
 * with. This will be used to identify the response when
423
 * the XBee alerts us as to whether or not our message
424
 * was received.
425
 **/
426
void xbee_send_packet(char* packet, int len, int dest,
427
	char options, char frame)
428
{
429
	char buf[5];
430
	char prefix[3];
431
	int i;
432
	unsigned char checksum = 0;
433

  
434
	if (len > 100)
435
	{
436
		WL_DEBUG_PRINT("Packet is too large.\r\n");
437
		return;
438
	}
439

  
440
	//data for sending request
441
	buf[0] = XBEE_FRAME_TX_REQUEST_16;
442
	buf[1] = frame;
443
	buf[2] = (dest >> 8) & 0xFF;
444
	buf[3] = dest & 0xFF;
445
	buf[4] = options;
446

  
447
	//packet prefix, do this here so we don't need an extra buffer
448
	prefix[0] = XBEE_FRAME_START;
449
	prefix[1] = ((5 + len) & 0xFF00) >> 8;
450
	prefix[2] = (5 + len) & 0xFF;
451

  
452
	for (i = 0; i < 5; i++)
453
		checksum += (unsigned char)buf[i];
454
	for (i = 0; i < len; i++)
455
		checksum += (unsigned char)packet[i];
456
	checksum = 0xFF - checksum;
457
	xbee_send(prefix, 3);
458
	xbee_send(buf, 5);
459
	xbee_send(packet, len);
460
	xbee_send((char*)&checksum, 1);
461
}
462

  
463
/**
464
 * Reads a packet received from the XBee. This function
465
 * is non-blocking. The resulting packet is stored in dest.
466
 * Only returns transmission response packets and
467
 * received packets. The returned packet does not include
468
 * header information or the checksum. This method also
469
 * handles special packets dealt with by the XBee library,
470
 * and so should be called frequently while the XBee is in
471
 * use.<br><br>
472
 *
473
 * The first byte of the packet will be either
474
 * XBEE_TX_STATUS or XBEE_RX to indicated
475
 * a response to a sent message or a received message, 
476
 * respectively.<br><br>
477
 *
478
 * For a status response packet:<br>
479
 * The first byte will be XBEE_TX_STATUS.<br>
480
 * The second byte will be the frame number.<br>
481
 * The third byte will be the result. 0 indicates success,
482
 * and nonzero indicates that an error ocurred in 
483
 * transmitting the packet.<br><br>
484
 *
485
 * For a received packet:<br>
486
 * The first byte will be XBEE_RX.<br>
487
 * The second and third bytes will be the 16-bit
488
 * address of the packet's sender.<br>
489
 * The fourth byte is the signal strength.<br>
490
 * The fifth byte is 1 if the packet were sent to
491
 * a specific address, and 2 if it is a broadcast packet.<br><br>
492
 * 
493
 * @param dest set to the packet data
494
 * @return the length of the packet, or -1 if no packet
495
 * is available
496
 **/
497
int xbee_get_packet(unsigned char* dest)
498
{
499
	//start reading a packet with XBEE_FRAME_START
500
	if (currentBufPos == 0)
501
	{
502
		do
503
			if (queue_is_empty(xbee_queue))
504
				return -1;
505
		while ((char)(int)queue_remove(xbee_queue) != XBEE_FRAME_START);
506
		xbee_buf[0] = XBEE_FRAME_START;
507
		currentBufPos++;
508
	}
509

  
510
	int len = -1;
511
	if (currentBufPos >= 3)
512
		len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
513
		
514
	while (len == -1 //packet length has not been read yet
515
			|| currentBufPos < len + 4)
516
	{
517
		if (currentBufPos == 3)
518
		{
519
			len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
520
			if (len > 120)
521
			{
522
				WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
523
				currentBufPos = 0;
524
				return -1;
525
			}
526
		}
527
		if (queue_is_empty(xbee_queue))
528
			return -1;
529
		xbee_buf[currentBufPos++] = (char)(int)queue_remove(xbee_queue);
530
	}
531
	
532
	currentBufPos = 0;
533
	
534
	if (!xbee_verify_checksum(xbee_buf, len + 4))
535
	{
536
		WL_DEBUG_PRINT("XBee checksum failed.\r\n");
537
		return -1;
538
	}
539

  
540
	//we will take care of the packet
541
	if (xbee_handle_packet(xbee_buf + 3, len))
542
		return -1;
543
	
544
	if (dest == NULL)
545
		return -1;
546
	
547
	int i;
548
	for (i = 3; i < len + 3; i++)
549
		dest[i - 3] = xbee_buf[i];
550
	return len;
551
}
552

  
553
/**
554
 * Handles modem status packets.
555
 *
556
 * @param status the type of status packet received.
557
 **/
558
void xbee_handle_status(char status)
559
{
560
	switch (status)
561
	{
562
		case 0:
563
			WL_DEBUG_PRINT("XBee hardware reset.\r\n");
564
			break;
565
		case 1:
566
			WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
567
			break;
568
		case 2:
569
			WL_DEBUG_PRINT("Associated.\r\n");
570
			break;
571
		case 3:
572
			WL_DEBUG_PRINT("Disassociated.\r\n");
573
			break;
574
		case 4:
575
			WL_DEBUG_PRINT("Synchronization lost.\r\n");
576
			break;
577
		case 5:
578
			WL_DEBUG_PRINT("Coordinator realignment.\r\n");
579
			break;
580
		case 6:
581
			WL_DEBUG_PRINT("Coordinator started.\r\n");
582
			break;
583
	}
584
}
585

  
586
/**
587
 * Handles AT command response packets.
588
 * @param command the two character AT command, e.g. MY or ID
589
 * @param result 0 for success, 1 for an error
590
 * @param extra the hex value of the requested register
591
 * @param extraLen the length in bytes of extra
592
 **/
593
void xbee_handle_at_command_response(char* command, char result,
594
	char* extra, int extraLen)
595
{
596
	if (result == 1)
597
	{
598
		WL_DEBUG_PRINT("Error with AT");
599
		WL_DEBUG_PRINT(command);
600
		WL_DEBUG_PRINT(" packet.\r\n");
601
	}
602
	WL_DEBUG_PRINT("AT");
603
	WL_DEBUG_PRINT(command);
604
	WL_DEBUG_PRINT(" command was successful.\r\n");
605
		
606
	if (command[0] == 'I' && command[1] == 'D')
607
	{
608
		xbee_panID = xbee_pending_panID;
609
		WL_DEBUG_PRINT("PAN ID set to ");
610
		WL_DEBUG_PRINT_INT(xbee_panID);
611
		WL_DEBUG_PRINT(".\r\n");
612
		return;
613
	}
614

  
615
	if (command[0] == 'C' && command[1] == 'H')
616
	{
617
		xbee_channel = xbee_pending_channel;
618
		WL_DEBUG_PRINT("Channel set to ");
619
		WL_DEBUG_PRINT_INT(xbee_channel);
620
		WL_DEBUG_PRINT(".\r\n");
621
		return;
622
	}
623
	
624
	if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
625
	{
626
		xbee_address = 0;
627
		int i;
628
		for (i = 0; i < extraLen; i++)
629
			xbee_address = (xbee_address << 8) + extra[i];
630

  
631
		WL_DEBUG_PRINT("XBee address is ");
632
		WL_DEBUG_PRINT_INT(xbee_address);
633
		WL_DEBUG_PRINT(".\r\n");
634

  
635
		if (xbee_address == 0)
636
		{
637
			WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
638
			exit(0);
639
		}
640
	}
641
}
642

  
643
/**
644
 * Attempts to handle the packet if it is dealt with
645
 * by the library.
646
 * We will handle the following packet types:
647
 *    Modem Status
648
 *    AT Command Response
649
 *
650
 * @param packet the packet to handle
651
 * @param len the length of the packet
652
 * 
653
 * @return 1 if we have handled the packet, 0 otherwise
654
 */
655
int xbee_handle_packet(char* packet, int len)
656
{
657
	char command[3] = {1, 2, 3};
658
	if (len <= 0) //this should not happend
659
	{
660
		WL_DEBUG_PRINT("Non-positive packet length.\r\n");
661
		return 0;
662
	}
663
	
664
	switch ((unsigned char)packet[0]) //packet type
665
	{
666
		case XBEE_FRAME_STATUS:
667
			xbee_handle_status(packet[1]);
668
			return 1;
669
		case XBEE_FRAME_AT_COMMAND_RESPONSE:
670
			command[0] = packet[2];
671
			command[1] = packet[3];
672
			command[2] = 0;
673
			xbee_handle_at_command_response(command,
674
				packet[4], packet + 5, len - 5);
675
			return 1;
676
	}
677
	return 0;
678
}
679

  
680
/**
681
 * Sets the personal area network id.
682
 *
683
 * @param id the new personal area network (PAN) id
684
 **/
685
void xbee_set_pan_id(int id)
686
{
687
	char s[3];
688
	s[0] = (id >> 8) & 0xFF;
689
	s[1] = id & 0xFF;
690
	s[2] = 0;
691
	xbee_pending_panID = id;
692
	xbee_send_modify_at_command("ID", s);
693
}
694

  
695
/**
696
 * Get the PAN ID for the XBee.
697
 * 
698
 * @return the personal area network id, or
699
 * XBEE_PAN_DEFAULT if it has not yet been set.
700
 **/
701
unsigned int xbee_get_pan_id()
702
{
703
	return xbee_panID;
704
}
705

  
706
/**
707
 * Set the channel the XBee is using.
708
 *
709
 * @param channel the channel the XBee will not use, 
710
 * between 0x0B and 0x1A
711
 *
712
 * @see xbee_get_channel
713
 **/
714
void xbee_set_channel(int channel)
715
{
716
	if (channel < 0x0B || channel > 0x1A)
717
	{
718
		WL_DEBUG_PRINT("Channel out of range.\r\n");
719
		return;
720
	}
721
	char s[3];
722
	s[0] = channel & 0xFF;
723
	s[1] = 0;
724
	xbee_pending_channel = channel;
725
	xbee_send_modify_at_command("CH", s);
726
}
727

  
728
/**
729
 * Returns the channel which the XBee is currently using.
730
 *
731
 * @return the channel the XBee is using
732
 *
733
 * @see xbee_set_channel
734
 **/
735
int xbee_get_channel(void)
736
{
737
	return xbee_channel;
738
}
739

  
740
/**
741
 * Get the 16-bit address of the XBee.
742
 * This is used to specify who to send messages to
743
 * and who messages are from.
744
 *
745
 * @return the 16-bit address of the XBee.
746
 **/
747
unsigned int xbee_get_address()
748
{
749
	return xbee_address;
750
}
751

  
752
#ifndef ROBOT
753
void xbee_set_com_port(char* port){
754
  //printf("Port being passed is %s\n",port);
755
  xbee_com_port = malloc(strlen(port));
756
  strcpy(xbee_com_port,port); 
757
}
758
#endif
759

  
branches/slam/code/projects/libwireless/lib/xbee.h
1
/**
2
 * @file xbee.h
3
 * @brief Contains definitions for using the XBee
4
 *
5
 * Contains definitions for interfacing with the 
6
 * XBee module, from either a robot or a computer.
7
 * To use a robot, define ROBOT in wl_defs.h, and
8
 * to use a computer, don't define ROBOT.
9
 *
10
 * @author Brian Coltin, Colony Project, CMU Robotics Club
11
 **/
12

  
13
#ifndef XBEE_H
14
#define XBEE_H
15

  
16
/**
17
 * The port to use the XBee from on the computer.
18
 * Also, a backup port if the other is used.
19
 **/
20
#ifndef ROBOT
21
#ifndef XBEE_PORT
22
#define XBEE_PORT "/dev/ttyUSB1"
23
#endif
24
#define XBEE_PORT2 "/dev/ttyUSB0"
25
#endif
26

  
27
/**
28
 * @defgroup xbee XBee
29
 * @brief Interface with the XBee module
30
 *
31
 * Interface with the XBee module.
32
 *
33
 * @{
34
 **/
35

  
36
/*Definitions*/
37
/**@brief Unset PAN, uses XBee default **/
38
#define XBEE_PAN_DEFAULT 0xFFFF
39
/**@brief Unset channel, uses XBee default **/
40
#define XBEE_CHANNEL_DEFAULT 0
41
/**@brief Broadcast to all robots in the PAN **/
42
#define XBEE_BROADCAST 0xFFFF
43
/**@brief No special options **/
44
#define XBEE_OPTIONS_NONE 0x00
45
/**@brief Do not receive a TX_STATUS message from this packet **/
46
#define XBEE_OPTIONS_DISABLE_RESPONSE 0x01
47
/**@brief Send the packet to all PANS **/
48
#define XBEE_OPTIONS_BROADCAST_ALL_PANS 0x04
49
/**@brief A transmit status packet **/
50
#define XBEE_TX_STATUS 0x89
51
/**@brief A packet received from another XBee **/
52
#define XBEE_RX 0x81
53

  
54
/**@brief Initialize the XBee library **/
55
void xbee_lib_init(void);
56
/**@brief Uninitialize the XBee library **/
57
void xbee_terminate(void);
58
/**@brief Get a packet from the XBee **/
59
int xbee_get_packet(unsigned char* packet);
60
/**@brief Send a packet to the XBee **/
61
void xbee_send_packet(char* packet, int len, int dest,
62
	char options, char frame);
63
/**@brief Set the PAN ID for the XBee **/
64
void xbee_set_pan_id(int id);
65
/**@brief Get the XBee's PAN ID **/
66
unsigned int xbee_get_pan_id(void);
67
/**@brief Set the channel the XBee is currently using **/
68
void xbee_set_channel(int channel);
69
/**@brief Get the channel the XBee is currently using **/
70
int xbee_get_channel(void);
71
/**@brief Get the XBee's 16-bit address **/
72
unsigned int xbee_get_address(void);
73
/**@brief Set the com port on a computer, undefined on the robot**/
74
void xbee_set_com_port(char* port);
75

  
76
/**@}**/ //end defgroup
77

  
78
#endif
branches/slam/code/projects/libwireless/lib/wireless.c
1
#include "wireless.h"
2
#include "xbee.h"
3
#include <stdlib.h>
4
#include <stdio.h>
5

  
6
#include "wl_defs.h"
7

  
8
#ifndef ROBOT
9
#include <sys/time.h>
10
#include <signal.h>
11
#else
12
#include <time.h>
13
#ifndef FIREFLY
14
#include <bom.h>
15
#endif
16
#endif
17

  
18
/*Function Prototypes*/
19

  
20
void wl_do_timeout(void);
21

  
22
//Note: the actual frame sent has group as the first four bits and
23
//frame as the last four.
24
void wl_send_packet(char group, char type, char* data, int len,
25
					int dest, char options, char frame);
26

  
27
/*Data Members*/
28

  
29
//used to store incoming and outgoing packets
30
unsigned char wl_buf[128];
31
//1 if we have timed out since we last checked, 0 otherwise.
32
int wl_timeout = 0;
33

  
34
PacketGroupHandler* wl_packet_groups[WL_MAX_PACKET_GROUPS];
35

  
36
#ifndef ROBOT
37

  
38
//called when we time out, or receive interrupt
39
void sig_handler(int signo)
40
{
41
	switch (signo)
42
	{
43
		case SIGALRM:
44
			wl_timeout = 1;
45
			break;
46
		case SIGINT:
47
			wl_terminate();
48
			exit(1);
49
			break;
50
	}
51
	return;
52
}
53
#else
54

  
55
//called when the timer ticks
56
void timer_handler(void)
57
{
58
	wl_timeout = 1;
59
}
60

  
61
#endif
62

  
63
/**
64
 * Initializes the wireless library. Must be called before any
65
 * other function.
66
 **/
67
void wl_init()
68
{
69
	int i;
70
	for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
71
		wl_packet_groups[i] = NULL;
72

  
73
	xbee_lib_init();
74
	
75
	//begin timeout timer
76
	#ifdef ROBOT
77
	#ifdef FIREFLY
78
	rtc_init(PRESCALE_DIV_256, 32, &timer_handler);
79
	#else
80
	rtc_init(HALF_SECOND, &timer_handler); 
81
	#endif
82
	#else
83
  
84
	//create our timer
85
	struct itimerval timer_val;
86
	struct timeval interval;
87
	interval.tv_sec = 0;
88
	interval.tv_usec = 500000;
89
	struct timeval first_time;
90
	first_time.tv_sec = 0;
91
	first_time.tv_usec = 500000;
92
	timer_val.it_interval = interval;
93
	timer_val.it_value = first_time;
94
	if(setitimer(ITIMER_REAL,&timer_val,NULL)==-1)
95
	{
96
		WL_DEBUG_PRINT("Error creating a timer.\r\n"); 
97
		perror("Failure's cause");
98
		exit(1); 
99
	}
100

  
101
	//create signal handler
102
	struct sigaction wl_sig_act;
103
	wl_sig_act.sa_handler = sig_handler;
104
	wl_sig_act.sa_flags = 0;
105
	sigemptyset(&wl_sig_act.sa_mask);
106
	sigaction(SIGALRM, &wl_sig_act, 0);
107
	sigaction(SIGINT, &wl_sig_act, 0);
108
	#endif
109
}
110

  
111
/**
112
 * Uninitializes the wireless library.
113
 **/
114
void wl_terminate()
115
{
116
	int i;
117
	for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
118
		if (wl_packet_groups[i] != NULL &&
119
			wl_packet_groups[i]->unregister != NULL)
120
			wl_packet_groups[i]->unregister();
121
	
122
	xbee_terminate();
123
}
124

  
125
/**
126
 * Set the PAN for the XBee to join.
127
 *
128
 * @param pan the new PAN
129
 *
130
 * @see wl_get_pan
131
 **/
132
void wl_set_pan(int pan)
133
{
134
	xbee_set_pan_id(pan);
135
}
136

  
137
/**
138
 * Get the PAN the XBee is currently part of.
139
 *
140
 * @return the PAN of the XBee
141
 *
142
 * @see wl_set_pan
143
 **/
144
int wl_get_pan(void)
145
{
146
	return xbee_get_pan_id();
147
}
148

  
149
/**
150
 * Set the channel the XBee is listening to.
151
 *
152
 * @param channel the new channel to join
153
 *
154
 * @see wl_get_channel
155
 **/
156
void wl_set_channel(int channel)
157
{
158
	xbee_set_channel(channel);
159
}
160

  
161
/**
162
 * Get the channel the XBee is part of.
163
 *
164
 * @return the channel the XBee is part of
165
 *
166
 * @see wl_set_channel
167
 **/
168
int wl_get_channel(void)
169
{
170
	return xbee_get_channel();
171
}
172

  
173
/**
174
 * Returns the 16-bit address of the XBee module.
175
 *
176
 * @return the 16-bit address of the XBee module.
177
 **/
178
unsigned int wl_get_xbee_id()
179
{
180
	return xbee_get_address();
181
}
182

  
183
/**
184
 * Send a packet to a specific XBee without specifying a PAN.
185
 *
186
 * @param group the packet group
187
 * @param type the packet type
188
 * @param data the packet data
189
 * @param len the packet length in bytes
190
 * @param dest the 16-bit address of the XBee to send the packet to
191
 * @param frame the frame number to see with a TX_STATUS response
192
 **/
193
void wl_send_robot_to_robot_global_packet(char group, char type,
194
		char* data, int len, int dest, char frame)
195
{
196
	wl_send_packet(group, type, data, len, dest,
197
			XBEE_OPTIONS_BROADCAST_ALL_PANS, frame);
198
}
199

  
200
/**
201
 * Send a packet to a specific XBee in the same PAN.
202
 *
203
 * @param group the packet group
204
 * @param type the packet type
205
 * @param data the packet data
206
 * @param len the packet length in bytes
207
 * @param dest the 16-bit address of the XBee to send the packet to
208
 * @param frame the frame number to see with a TX_STATUS response
209
 **/
210
void wl_send_robot_to_robot_packet(char group, char type,
211
		char* data, int len, int dest, char frame)
212
{
213
	wl_send_packet(group, type, data, len, dest, XBEE_OPTIONS_NONE,
214
			frame);
215
}
216

  
217
/**
218
 * Send a packet to all XBees in all PANs.
219
 *
220
 * @param group the packet group
221
 * @param type the packet type
222
 * @param data the packet data
223
 * @param len the packet length in bytes
224
 * @param frame the frame number to see with a TX_STATUS response
225
 **/
226
void wl_send_global_packet(char group, char type,
227
		char* data, int len, char frame)
228
{
229
	wl_send_packet(group, type, data, len, XBEE_BROADCAST,
230
			XBEE_OPTIONS_BROADCAST_ALL_PANS, frame);
231
}
232

  
233
/**
234
 * Send a packet to all XBee's in the same PAN.
235
 *
236
 * @param group the packet group
237
 * @param type the packet type
238
 * @param data the packet data
239
 * @param len the packet length in bytes
240
 * @param frame the frame number to see with a TX_STATUS response
241
 **/
242
void wl_send_pan_packet(char group, char type,
243
		char* data, int len, char frame)
244
{
245
	wl_send_packet(group, type, data, len, XBEE_BROADCAST, 
246
			XBEE_OPTIONS_NONE, frame);
247
}
248

  
249
/**
250
 * Send a packet.
251
 *
252
 * @param group the packet group
253
 * @param type the packet type
254
 * @param data the packet data
255
 * @param len the packet length in bytes
256
 * @param dest the destination of the packet
257
 * @param options the options for sending the packet
258
 * @param frame the frame number to see with a TX_STATUS response
259
 **/
260
void wl_send_packet(char group, char type, char* data, int len,
261
					int dest, char options, char frame)
262
{
263
	char buf[128];
264
	int i;
265
	if (frame != 0)
266
		frame = (frame & 0x0F) | ((group & 0x0F) << 4);
267
	buf[0] = group;
268
	buf[1] = type;
269
	for (i = 0; i < len; i++)
270
		buf[2 + i] = data[i];
271
	xbee_send_packet(buf, len + 2, dest, options, frame);
272
}
273

  
274
/**
275
 * Register a packet group with the wireless library. The event
276
 * handlers in the packet group will be called whenever an
277
 * event dealing with the packet group's group code occurs.
278
 *
279
 * @param h the PacketGroupHandler to register
280
 **/
281
void wl_register_packet_group(PacketGroupHandler* h)
282
{
283
	if (h->groupCode >= WL_MAX_PACKET_GROUPS)
284
	{
285
		WL_DEBUG_PRINT("Packet group code too large.\r\n");
286
		return;
287
	}
288
	if (wl_packet_groups[h->groupCode] != NULL)
289
	{
290
		WL_DEBUG_PRINT("Packet group code already registered.\r\n");
291
		return;
292
	}
293
	wl_packet_groups[h->groupCode] = h;
294
}
295

  
296
/**
297
 * Unregister a packet group from the wireless library.
298
 * 
299
 * @param h the packet group to remove
300
 **/
301
void wl_unregister_packet_group(PacketGroupHandler* h)
302
{
303
	unsigned int groupCode = h->groupCode;
304
	PacketGroupHandler* p = wl_packet_groups[groupCode];
305
	if (p != NULL && p->unregister != NULL)
306
		p->unregister();
307
	wl_packet_groups[groupCode] = NULL;
308
}
309

  
310
/**
311
 * Called when the timer is triggered. This calls the timeout
312
 * handlers of all the registered packet groups.
313
 **/
314
void wl_do_timeout()
315
{
316
	int i;
317
	for (i = 0; i < WL_MAX_PACKET_GROUPS; i++)
318
		if (wl_packet_groups[i] != NULL &&
319
			wl_packet_groups[i]->timeout_handler != NULL)
320
			wl_packet_groups[i]->timeout_handler();
321
}
322

  
323
/**
324
 * Performs wireless library functionality. This function must
325
 * be called frequently for wireless to perform effectively.
326
 * This function will call timeout handlers, as well as
327
 * received packet and transmit status handlers.
328
 **/
329
void wl_do()
330
{
331
	if (wl_timeout)
332
	{
333
		wl_do_timeout();
334
		wl_timeout = 0;
335
	}
336
	
337
	int len = xbee_get_packet(wl_buf);
338
	if (len < 0)//no packet received
339
		return;
340
	
341
	if (wl_buf[0] == XBEE_TX_STATUS)
342
	{
343
		if (len != 3)
344
		{
345
			WL_DEBUG_PRINT("Transmit Status packet should be of length 3.\r\n");
346
			return;
347
		}
348
		
349
		//the first four bits are the packet group
350
		//this only works with under 16 groups
351
		int group = (int)(wl_buf[1] >> 4);
352
		int success = 0;
353
		if (wl_buf[2] == 0)
354
			success = 1;
355
		else
356
		{
357
			WL_DEBUG_PRINT("No response received.\r\n");
358
			if (wl_buf[2] == 2)
359
			{
360
				WL_DEBUG_PRINT("CCA Failure\r\n");
361
			}
362
			if (wl_buf[2] == 3)
363
			{
364
				WL_DEBUG_PRINT("Purged\r\n");
365
			}
366
		}
367
		
368
		if (wl_packet_groups[group] != NULL &&
369
					wl_packet_groups[group]->handle_response != NULL)
370
			wl_packet_groups[group]->handle_response(
371
					(int)wl_buf[1] & 0x0F, success);
372
		return;
373
	}
374
	
375
	if (wl_buf[0] == XBEE_RX)
376
	{
377
		if (len < 7)
378
		{
379
			WL_DEBUG_PRINT("Packet is too small.\r\n");
380
			return;
381
		}
382
		
383
		int source = ((int)wl_buf[1] << 8) + ((int)wl_buf[2]);
384
		
385
		/*
386
		//unused for now
387
		int signalStrength = wl_buf[3];
388
		//1 for Address broadcast, 2 for PAN broadcast
389
		int options = wl_buf[4];
390
		*/
391
		
392
		int group = wl_buf[5];
393
		int type = wl_buf[6];
394
		int packetLen = len - 7;
395
		
396
		if (wl_packet_groups[group] != NULL
397
				&& wl_packet_groups[group]->handle_receive != NULL)
398
			wl_packet_groups[group]->handle_receive(type, source, 
399
				wl_buf + 7, packetLen);
400
		return;
401
	}
402
	
403
	WL_DEBUG_PRINT("Unexpected packet received from XBee.\r\n");
404
	return;
405
}
406

  
407

  
408
#ifndef ROBOT
409
void wl_set_com_port(char* port){
410
  xbee_set_com_port(port);
411
}
412
#endif
413

  
414

  
branches/slam/code/projects/libwireless/lib/wl_token_ring.c
1
#include <wl_token_ring.h>
2

  
3
#include <stdlib.h>
4
#include <stdio.h>
5

  
6
#include <wl_defs.h>
7
#include <wireless.h>
8
#include <sensor_matrix.h>
9

  
10
#ifdef ROBOT
11
#ifndef FIREFLY
12
#include <bom.h>
13
#endif
14
#include <time.h>
15
#endif
16

  
17
#define DEFAULT_SENSOR_MATRIX_SIZE 20
18

  
19
/*Ring States*/
20

  
21
#define NONMEMBER 0
22
#define MEMBER 1
23
#define JOINING 2
24
#define ACCEPTED 3
25
#define LEAVING 4
26

  
27
/*Frame Types*/
28
#define TOKEN_JOIN_ACCEPT_FRAME 1
29

  
30
/*Function Prototypes*/
31

  
32
/*Wireless Library Prototypes*/
33
void wl_token_ring_timeout_handler(void);
34
void wl_token_ring_response_handler(int frame, int received);
35
void wl_token_ring_receive_handler(char type, int source, unsigned char* packet,
36
							int length);
37
void wl_token_ring_cleanup(void);
38

  
39
/*Helper Functions*/
40
void wl_token_pass_token(void);
41
int get_token_distance(int robot1, int robot2);
42
void wl_token_get_token(void);
43

  
44
/*Packet Handling Routines*/
45
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength);
46
void wl_token_bom_on_receive(int source);
47
void wl_token_join_receive(int source);
48
void wl_token_join_accept_receive(int source);
49

  
50
/*Global Variables*/
51

  
52
//the sensor matrix
53
SensorMatrix* sensorMatrix;
54

  
55
//the robot we are waiting to say it has received the token. -1 if unspecified
56
int wl_token_next_robot = -1;
57

  
58
//true if the robot should be in the token ring, 0 otherwise
59
int ringState = NONMEMBER;
60
//the id of the robot who accepted us into the token ring, only used in ACCEPTED state
61
int acceptor = -1;
62
//id of the robot we are accepting
63
int accepted = -1;
64

  
65
//the counter for when we assume a robot is dead
66
int deathDelay = -1;
67
//the counter for joining, before we form our own token ring
68
int joinDelay = -1;
69

  
70
//current robot to check in the iterator
71
int iteratorCount = 0;
72

  
73
// the amount of time a robot has had its BOM on for
74
int bom_on_count = 0;
75

  
76
void do_nothing(void) {}
77
int get_nothing(void) {return -1;}
78

  
79
#ifdef ROBOT
80
#ifndef FIREFLY
81
void (*bom_on_function) (void) = bom_on;
82
void (*bom_off_function) (void) = bom_off;
83
int (*get_max_bom_function) (void) = get_max_bom;
84
#else
85
void (*bom_on_function) (void) = do_nothing;
86
void (*bom_off_function) (void) = do_nothing;
87
int (*get_max_bom_function) (void) = get_nothing;
88
#endif
89
#else
90
void (*bom_on_function) (void) = do_nothing;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff