Project

General

Profile

Revision 1432

test_xbee - checks address of xbee

View differences:

trunk/code/projects/test/test_xbee.c
1
#include <dragonfly_lib.h>
2
#include <xbee.h>
3

  
4
#define ROBOT
5
#define WL_DEBUG
6
#define WL_DEBUG_PRINT( s ) usb_puts( S )
7

  
8
extern int xbee_send_read_at_command(char* command);
9
extern int xbee_get_packet(unsigned char* dest);
10

  
11
/*
12
 * This function tests the xbee, returning the results to teraterm
13
 *
14
 * 
15
 */
16
 
17
static init = 0;
18

  
19
int testxbee(void) {
20

  
21
  unsigned char buf[100];
22
  int i=0;
23
	
24
	usb_init();
25
	usb_puts("usb turned on, test starting:\r\n");
26
  
27
  if(!init) {
28
    // initialize xbee only once
29
    if (xbee_lib_init() != 0) {
30
      usb_puts("xbee_lib_init() failed\r\n");
31
      return -1;
32
    } else {
33
      usb_puts("xbee_lib__init successful\r\n");
34
      init = 1;
35
    }
36
  }
37
  
38
	usb_puts("\r\n\n");
39
	delay_ms(1000);
40
	
41
	// try getting xbee address
42
  xbee_send_read_at_command("MY");
43
  while(i++ < 10000) {
44
    if(xbee_get_packet(buf) == 3) {
45
      usb_puts("got response from xbee\r\n");
46
      //usb_puts("packet:");
47
      //usb_puts(buf);
48
      //usb_puts("|end\r\n");
49
      break; // got a response
50
    }
51
  }
52
  usb_puts("testxbee done\r\n\r\n");
53
  
54
	return 0;
55
}
trunk/code/projects/test/xbee.c
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 xbee.c
28
 * @brief XBee Interface
29
 *
30
 * Implementation of low level communication with the XBee in API mode.
31
 *
32
 * @author Brian Coltin, Colony Project, CMU Robotics Club
33
 **/
34

  
35
#include <xbee.h>
36
#include <wl_defs.h>
37

  
38
#define ROBOT
39
#define WL_DEBUG
40
#define WL_DEBUG_PRINT( s ) usb_puts( s )
41
#define WL_DEBUG_PRINT_INT( i ) usb_puti(i)
42

  
43
#ifndef ROBOT
44

  
45
#include <fcntl.h>
46
#include <unistd.h>
47
#include <pthread.h>
48
#include <errno.h>
49
#include <termios.h>
50

  
51
#else
52

  
53
#include <serial.h>
54
#include <avr/interrupt.h>
55

  
56
#endif
57

  
58
#include <stdio.h>
59
#include <stdlib.h>
60
#include <string.h>
61

  
62
#define XBEE_FRAME_START 0x7E
63
#define XBEE_GET_PACKET_TIMEOUT 1000
64

  
65
/*Frame Types*/
66
#define XBEE_FRAME_STATUS 0x8A
67
#define XBEE_FRAME_AT_COMMAND 0x08
68
#define XBEE_FRAME_AT_COMMAND_RESPONSE 0x88
69
#define XBEE_FRAME_TX_REQUEST_64 0x00
70
#define XBEE_FRAME_TX_REQUEST_16 0x01
71
#define XBEE_FRAME_TX_STATUS XBEE_TX_STATUS
72
#define XBEE_FRAME_RX_64 0x80
73
#define XBEE_FRAME_RX_16 XBEE_RX
74

  
75
/*Internal Function Prototypes*/
76

  
77
/*I/O Functions*/
78
static int xbee_send(char* buf, int size);
79
static int xbee_send_string(char* c);
80

  
81
#ifndef ROBOT
82
static int xbee_read(char* buf, int size);
83
#endif
84

  
85
/*Command Mode Functions
86
 * Called during initialization.
87
 */
88
static int xbee_enter_command_mode(void);
89
static int xbee_exit_command_mode(void);
90
static int xbee_enter_api_mode(void);
91
static int xbee_wait_for_string(char* s, int len);
92
static int xbee_wait_for_ok(void);
93

  
94
/*API Mode Functions*/
95

  
96
static int xbee_handle_packet(char* packet, int len);
97
static void xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen);
98
static void xbee_handle_status(char status);
99
static int xbee_verify_checksum(char* packet, int len);
100
static char xbee_compute_checksum(char* packet, int len);
101
static int xbee_send_frame(char* buf, int len);
102
int xbee_send_read_at_command(char* command);
103
static int xbee_send_modify_at_command(char* command, char* value);
104

  
105
/*Global Variables*/
106

  
107
#ifndef ROBOT
108
static char* xbee_com_port = XBEE_PORT_DEFAULT;
109
static int xbee_stream;
110
static pthread_t* xbee_listen_thread;
111
#endif
112

  
113
// TODO: is this a good size?
114
#define XBEE_BUFFER_SIZE	128
115
#define PACKET_BUFFER_SIZE	108
116
// a buffer for data received from the XBee
117
char arrival_buf[XBEE_BUFFER_SIZE];
118
// location of last unread byte in buffer
119
volatile int buffer_last = 0;
120
// first unread byte in buffer
121
volatile int buffer_first = 0;
122

  
123

  
124
//used to store packets as they are read
125
static char xbee_buf[PACKET_BUFFER_SIZE];
126
static int currentBufPos = 0;
127

  
128
//XBee status
129
static unsigned int xbee_panID = XBEE_PAN_DEFAULT;
130
static unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
131
static int xbee_channel = XBEE_CHANNEL_DEFAULT;
132
static int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
133
static volatile unsigned int xbee_address = 0;
134

  
135
/*Function Implementations*/
136

  
137
#ifdef ROBOT
138

  
139
/**
140
 * Interrupt for the robot. Adds bytes received from the xbee
141
 * to the buffer.
142
 **/
143
#ifndef FIREFLY
144
ISR(USART1_RX_vect)
145
{
146
	char c = UDR1;
147
	arrival_buf[buffer_last] = c;
148
	int t = buffer_last + 1;
149
	if (t == XBEE_BUFFER_SIZE)
150
		t = 0;
151
	if (t == buffer_first)
152
	{
153
		WL_DEBUG_PRINT("\nOut of space in buffer.\n");
154
	}
155
	buffer_last = t;
156
}
157
#else
158
SIGNAL(SIG_USART0_RECV)
159
{
160
	char c = UDR0;
161
	arrival_buf[buffer_last] = c;
162
	int t = buffer_last + 1;
163
	if (t == XBEE_BUFFER_SIZE)
164
		t = 0;
165
	if (t == buffer_first)
166
	{
167
		WL_DEBUG_PRINT("Out of space in buffer.\n");
168
	}
169
	buffer_last = t;
170
}
171
#endif
172

  
173
#else
174

  
175
// Computer code
176

  
177
/**
178
 * Thread that listens to the xbee.
179
 **/
180
static void* listen_to_xbee(void* x)
181
{
182
	char c;
183
	while (1)
184
	{
185
		if (xbee_read(&c, 1) != 0) {
186
			WL_DEBUG_PRINT("xbee_read failed.\n");
187
			return NULL;
188
		}
189

  
190
		arrival_buf[buffer_last] = c;
191
		int t = buffer_last + 1;
192
		if (t == XBEE_BUFFER_SIZE)
193
			t = 0;
194
		if (t == buffer_first)
195
		{
196
			WL_DEBUG_PRINT("Out of space in buffer.\n");
197
		}
198
		buffer_last = t;
199

  
200
		usleep(1000);
201
	}
202

  
203
	return NULL;
204
}
205

  
206
#endif
207

  
208
/**
209
 * Initializes the XBee library so that other functions may be used.
210
 **/
211
int xbee_lib_init()
212
{
213
	WL_DEBUG_PRINT("in xbee_init\n");
214
#ifdef ROBOT
215

  
216
	//enable the receiving interrupt
217
#ifdef FIREFLY
218
	UCSR0B |= _BV(RXCIE) | _BV(RXEN);
219
#else
220
#ifdef BAYBOARD
221
	UCSR1B |= _BV(RXCIE1);
222
#else
223
	UCSR1B |= _BV(RXCIE);
224
#endif
225
#endif
226
	sei();
227
#else
228
	xbee_stream = open(xbee_com_port, O_RDWR);
229
	if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/)
230
	{
231
		WL_DEBUG_PRINT("Failed to open connection to XBee on port ");
232
		WL_DEBUG_PRINT_INT(xbee_com_port);
233
		WL_DEBUG_PRINT(".\n");
234
		return -1;
235
	} else {
236
	  WL_DEBUG_PRINT("Successfully opened connection to XBee on port ");
237
		WL_DEBUG_PRINT_INT(xbee_com_port);
238
		WL_DEBUG_PRINT(".\n");
239
	}
240

  
241
	// set baud rate, etc. correctly
242
	struct termios options;
243

  
244
	tcgetattr(xbee_stream, &options);
245
	cfsetispeed(&options, B9600);
246
	cfsetospeed(&options, B9600);
247
	options.c_iflag &= ~ICRNL;
248
	options.c_oflag &= ~OCRNL;
249
	options.c_cflag |= (CLOCAL | CREAD);
250
	options.c_cflag &= ~PARENB;
251
	options.c_cflag &= ~CSTOPB;
252
	options.c_cflag &= ~CSIZE;
253
	options.c_cflag |= CS8;
254
	options.c_lflag &= ~ICANON;
255
	options.c_cc[VMIN] = 1;
256
	options.c_cc[VTIME] = 50;
257

  
258
	if (tcsetattr(xbee_stream, TCSANOW, &options))
259
	{
260
		WL_DEBUG_PRINT("Error setting attributes.\n");
261
		return -1;
262
	}
263

  
264
	xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t));
265
	if (xbee_listen_thread == NULL)
266
	{
267
		WL_DEBUG_PRINT("Malloc failed.\n");
268
		return -1;
269
	}
270

  
271
	int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL);
272
	if (ret)
273
	{
274
		WL_DEBUG_PRINT("Failed to create listener thread.\n");
275
		return -1;
276
	}
277
#endif
278

  
279
	WL_DEBUG_PRINT("Entering command mode.\n");
280

  
281
	if (xbee_enter_command_mode() != 0) {
282
		return -1;
283
	}
284

  
285
	WL_DEBUG_PRINT("Entered command mode.\n");
286

  
287
	if (xbee_enter_api_mode() != 0) {
288
		return -1;
289
	}
290

  
291
	WL_DEBUG_PRINT("Entered api mode.\n");
292

  
293
	if (xbee_exit_command_mode() != 0) {
294
	     return -1;
295
	}
296
	
297
	WL_DEBUG_PRINT("Left command mode.\n");
298

  
299
	if (xbee_send_read_at_command("MY")) {
300
		return -1;
301
	}
302
	WL_DEBUG_PRINT("Getting ATMY address.\n");
303

  
304
#ifndef ROBOT
305
	int i;
306
	for (i = 0; xbee_address == 0 && i < XBEE_GET_PACKET_TIMEOUT; i++) {
307
	  ret = xbee_get_packet(NULL);
308

  
309
	  usleep(1000);
310
	  
311
/* 	  if (ret == -1) { */
312
/* 	    WL_DEBUG_PRINT("xbee_get_packet(NULL) failed.\n"); */
313
/* 	    return -1; */
314
/* 	  } */
315
	}
316
#else
317
	//wait to return until the address is set
318
  //TODO: this shouldn't wait indefinitely.  There should be some sort of reasonable timeout
319
  // so if the address is never set right, an error can be returned instead of having the
320
  // robot hang forever
321
	while (xbee_address == 0) {
322
	  xbee_get_packet(NULL);
323
	}
324
#endif
325
	WL_DEBUG_PRINT("Got ATMY address.\n");
326

  
327
#ifndef ROBOT
328
	if (i == XBEE_GET_PACKET_TIMEOUT) { // We timed-out.
329

  
330
	  WL_DEBUG_PRINT("xbee_get_packet timed out.\n");
331
	  return -1;
332
	} else {
333
	  return 0;
334
	}
335
#else
336
	return 0;
337
#endif
338
}
339

  
340
/**
341
 * Call when finished using the XBee library. This releases
342
 * all sued resources.
343
 **/
344
void xbee_terminate()
345
{
346
	#ifndef ROBOT
347
	pthread_cancel(*xbee_listen_thread);
348
    pthread_join(*xbee_listen_thread, NULL);
349
	free(xbee_listen_thread);
350
	lockf(xbee_stream, F_ULOCK, 0);
351
	close(xbee_stream);
352
	#endif
353
}
354

  
355
/**
356
 * Send a buffer buf of size bytes to the XBee.
357
 *
358
 * @param buf the buffer of data to send
359
 * @param size the number of bytes to send
360
 **/
361
static int xbee_send(char* buf, int size)
362
{
363
#ifdef ROBOT
364
	int i;
365
	for (i = 0; i < size; i++) {
366
		xbee_putc(buf[i]);
367
	}
368

  
369
	return 0;
370

  
371
#else
372

  
373
	int ret = write(xbee_stream, buf, size);
374
	//success
375
	if (ret == size)
376
		return 0;
377
	if (ret == -1)
378
	{
379
		//interrupted by system signal, probably timer interrupt.
380
		//just try again
381
		if (errno == 4)
382
		{
383
			return xbee_send(buf, size);
384
		}
385
		WL_DEBUG_PRINT("Failed to write to xbee\r\n");
386
		return -1;
387
	}
388

  
389
	//write was interrupted after writing ret bytes
390
	return xbee_send(buf + ret, size - ret);
391
#endif
392
}
393

  
394
/**
395
 * Sends a string to the XBee.
396
 *
397
 * @param c the string to send to the XBEE
398
 **/
399
static int xbee_send_string(char* c)
400
{
401
	return xbee_send(c, strlen(c));
402
}
403

  
404
#ifndef ROBOT
405
static int xbee_read(char* buf, int size)
406
{
407
	if (read(xbee_stream, buf, size) == -1) {
408
		WL_DEBUG_PRINT("Failed to read from xbee.\r\n");
409
		return -1;
410
	}
411

  
412
	return 0;
413
}
414
#endif
415

  
416
/**
417
 * Enter into command mode.
418
 **/
419
static int xbee_enter_command_mode()
420
{
421
	if (xbee_send_string("+++") != 0) {
422
		return -1;
423
	}
424

  
425
	if (xbee_wait_for_ok() != 0) {
426
	  return -1;
427
	}
428
	  return 0;
429
}
430

  
431
/**
432
 * Exit from command mode.
433
 **/
434
static int xbee_exit_command_mode()
435
{
436
	if (xbee_send_string("ATCN\r") != 0) {
437
		return -1;
438
	}
439

  
440
	xbee_wait_for_ok();
441

  
442
	return 0;
443
}
444

  
445
/**
446
 * Enter API mode.
447
 **/
448
static int xbee_enter_api_mode()
449
{
450
	if (xbee_send_string("ATAP 1\r") != 0) {
451
		return -1;
452
	}
453
	xbee_wait_for_ok();
454

  
455
	return 0;
456
}
457

  
458
/**
459
 * Wait until the string "OK\r" is received from the XBee.
460
 **/
461
static int xbee_wait_for_ok()
462
{
463
	return xbee_wait_for_string("OK\r", 3);
464
}
465

  
466
/**
467
 * Delay until the specified string is received from
468
 * the XBee. Discards all other XBee data.
469
 *
470
 * ********* Robot often hangs here ****************
471
 *
472
 * @param s the string to receive
473
 * @param len the length of the string
474
 **/
475
static int xbee_wait_for_string(char* s, int len)
476
{
477
	char* curr = s;
478
	while (curr - s < len) {
479
    WL_DEBUG_PRINT("waiting for string\r\n");
480
		// check if buffer is empty
481
		if (buffer_last != buffer_first) {
482
			char c = arrival_buf[buffer_first++];
483
			if (buffer_first == XBEE_BUFFER_SIZE) {
484
				buffer_first = 0;
485
			}
486

  
487
			if (c == *curr) {
488
				curr++;
489
			} else {
490
#ifndef ROBOT
491
			  //return -1; // Computer is less forgiving.
492
			  curr = s;
493
#else
494
			  curr = s;
495
#endif
496
			}
497
		} // else buffer is empty.
498

  
499
#ifndef ROBOT
500
		usleep(100);
501
#endif
502
	}
503

  
504
	return 0;
505
}
506

  
507
/**
508
 * Verifies that the packets checksum is correct.
509
 * (If the checksum is correct, the sum of the bytes
510
 * is 0xFF.)
511
 *
512
 * @param packet the packet received. This includes the first
513
 * three bytes, which are header information from the XBee.
514
 *
515
 * @param len The length of the packet received from the XBee
516
 *
517
 * @return 0 if the checksum is incorrect, nonzero
518
 * otherwise
519
 **/
520
int xbee_verify_checksum(char* packet, int len)
521
{
522
	unsigned char sum = 0;
523
	int i;
524
	for (i = 3; i < len; i++)
525
		sum += (unsigned char)packet[i];
526
	return sum == 0xFF;
527
}
528

  
529
/**
530
 * Returns the checksum of the given packet.
531
 *
532
 * @param buf the data for the packet to send
533
 * @param len the length of the packet in bytes
534
 *
535
 * @return the checksum of the packet, which will
536
 * become the last byte sent in the packet
537
 **/
538
char xbee_compute_checksum(char* buf, int len)
539
{
540
	int i;
541
	unsigned char sum = 0;
542
	for (i = 0; i < len; i++)
543
		sum += (unsigned char)buf[i];
544
	return 0xFF - sum;
545
}
546

  
547
/**
548
 * Adds header information and checksum to the given
549
 * packet and sends it. Header information includes
550
 * XBEE_FRAME_START and the packet length, as two bytes.
551
 *
552
 * @param buf the packet data
553
 * @param len the size in bytes of the packet data
554
 *
555
 **/
556
static int xbee_send_frame(char* buf, int len)
557
{
558
	char prefix[3];
559
	prefix[0] = XBEE_FRAME_START;
560
	prefix[1] = (len & 0xFF00) >> 8;
561
	prefix[2] = len & 0xFF;
562
	char checksum = xbee_compute_checksum(buf, len);
563

  
564
	if (xbee_send(prefix, 3) != 0) {
565
		return -1;
566
	}
567

  
568
	if (xbee_send(buf, len) != 0) {
569
		return -1;
570
	}
571

  
572
	if (xbee_send(&checksum, 1) != 0) {
573
		return -1;
574
	}
575

  
576
	return 0;
577
}
578

  
579
/**
580
 * Sends an AT command to read a parameter.
581
 *
582
 * @param command the AT command to send. For exmaple,
583
 * use ID to read the PAN ID and MY to return the XBee ID.
584
 * See the XBee reference guide for a complete listing.
585
 **/
586
int xbee_send_read_at_command(char* command)
587
{
588
	return xbee_send_modify_at_command(command, NULL);
589
}
590

  
591
/**
592
 * Sends the given AT command.
593
 *
594
 * @param command the AT command to send (e.g., MY, ID)
595
 * @param value the value to pass as a parameter
596
 * (or NULL if there is no parameter)
597
 **/
598
static int xbee_send_modify_at_command(char* command, char* value)
599
{
600
	char buf[16];
601
	int i;
602

  
603
	buf[0] = XBEE_FRAME_AT_COMMAND;
604
	buf[1] = 1;
605
	buf[2] = command[0];
606
	buf[3] = command[1];
607
	int valueLen = 0;
608
	if (value != NULL)
609
	{
610
		valueLen = strlen(value);
611
		if (valueLen > 8)
612
		{
613
			WL_DEBUG_PRINT("AT Command too large.\r\n");
614
			return -1;
615
		}
616

  
617
		for (i = 0; i < valueLen; i++) {
618
			buf[4 + i] = value[i];
619
		}
620
	}
621

  
622
	return xbee_send_frame(buf, 4 + valueLen);
623
}
624

  
625
/**
626
 * Send the specified packet.
627
 *
628
 * @param packet the packet data to send
629
 * @param len the number of bytes in the packet
630
 *
631
 * @param dest the ID of the XBee to send the packet to,
632
 * or XBEE_BROADCAST to send the message to all robots
633
 * in the PAN.
634
 *
635
 * @param options a combination of the flags
636
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
637
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
638
 *
639
 * @param frame the frame number to associate this packet
640
 * with. This will be used to identify the response when
641
 * the XBee alerts us as to whether or not our message
642
 * was received.
643
 **/
644
int xbee_send_packet(char* packet, int len, int dest, char options, char frame)
645
{
646
	char buf[5];
647
	char prefix[3];
648
	int i;
649
	unsigned char checksum = 0;
650

  
651
	if (len > 100)
652
	{
653
		WL_DEBUG_PRINT("Packet is too large.\r\n");
654
		return -1;
655
	}
656

  
657
	//data for sending request
658
	buf[0] = XBEE_FRAME_TX_REQUEST_16;
659
	buf[1] = frame;
660
	buf[2] = (dest >> 8) & 0xFF;
661
	buf[3] = dest & 0xFF;
662
	buf[4] = options;
663

  
664
	//packet prefix, do this here so we don't need an extra buffer
665
	prefix[0] = XBEE_FRAME_START;
666
	prefix[1] = ((5 + len) & 0xFF00) >> 8;
667
	prefix[2] = (5 + len) & 0xFF;
668

  
669
	for (i = 0; i < 5; i++)
670
		checksum += (unsigned char)buf[i];
671
	for (i = 0; i < len; i++)
672
		checksum += (unsigned char)packet[i];
673
	checksum = 0xFF - checksum;
674

  
675
	if (xbee_send(prefix, 3) != 0) {
676
		return -1;
677
	}
678

  
679
	if (xbee_send(buf, 5) != 0) {
680
		return -1;
681
	}
682

  
683
	if (xbee_send(packet, len) != 0) {
684
		return -1;
685
	}
686

  
687
	if (xbee_send((char*)&checksum, 1) != 0) {
688
		return -1;
689
	}
690

  
691
	return 0;
692
}
693

  
694
/**
695
 * Reads a packet received from the XBee. This function
696
 * is non-blocking. The resulting packet is stored in dest.
697
 * Only returns transmission response packets and
698
 * received packets. The returned packet does not include
699
 * header information or the checksum. This method also
700
 * handles special packets dealt with by the XBee library,
701
 * and so should be called frequently while the XBee is in
702
 * use.<br><br>
703
 *
704
 * The first byte of the packet will be either
705
 * XBEE_TX_STATUS or XBEE_RX to indicated
706
 * a response to a sent message or a received message,
707
 * respectively.<br><br>
708
 *
709
 * For a status response packet:<br>
710
 * The first byte will be XBEE_TX_STATUS.<br>
711
 * The second byte will be the frame number.<br>
712
 * The third byte will be the result. 0 indicates success,
713
 * and nonzero indicates that an error ocurred in
714
 * transmitting the packet.<br><br>
715
 *
716
 * For a received packet:<br>
717
 * The first byte will be XBEE_RX.<br>
718
 * The second and third bytes will be the 16-bit
719
 * address of the packet's sender.<br>
720
 * The fourth byte is the signal strength.<br>
721
 * The fifth byte is 1 if the packet were sent to
722
 * a specific address, and 2 if it is a broadcast packet.<br><br>
723
 *
724
 * @param dest set to the packet data
725
 * @return the length of the packet, or -1 if no packet
726
 * is available
727
 **/
728
int xbee_get_packet(unsigned char* dest)
729
{
730
     int ret;
731
	//start reading a packet with XBEE_FRAME_START
732
	if (currentBufPos == 0)
733
	{
734
		do
735
		{
736
			if (buffer_first == XBEE_BUFFER_SIZE)
737
				buffer_first = 0;
738
			// check if buffer is empty
739
			if (buffer_first == buffer_last) {
740
				return -1;
741
			}
742
		} while (arrival_buf[buffer_first++] != XBEE_FRAME_START);
743

  
744
		if (buffer_first == XBEE_BUFFER_SIZE) {
745
			buffer_first = 0;
746
		}
747
		xbee_buf[0] = XBEE_FRAME_START;
748
		currentBufPos++;
749
	}
750

  
751
	int len = -1;
752
	if (currentBufPos >= 3) {
753
		len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
754
	}
755

  
756
	while (len == -1 //packet length has not been read yet
757
		|| currentBufPos < len + 4)
758
	{
759
		if (currentBufPos == 3)
760
		{
761
			len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
762
			if (len > 120)
763
			{
764
				WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
765
				currentBufPos = 0;
766
				return -1;
767
			}
768
		}
769

  
770
		// check if buffer is empty
771
		if (buffer_first == buffer_last) {
772
			return -1;
773
		}
774
		xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
775
		if (buffer_first == XBEE_BUFFER_SIZE) {
776
			buffer_first = 0;
777
		}
778
	}
779

  
780
	currentBufPos = 0;
781

  
782
	if (!xbee_verify_checksum(xbee_buf, len + 4))
783
	{
784
		WL_DEBUG_PRINT("XBee checksum failed.\r\n");
785
		return -1;
786
	}
787

  
788
	//we will take care of the packet
789
	
790
	ret = xbee_handle_packet(xbee_buf+3, len);
791
	if (ret == 1) {
792
		return 3;
793
	}
794
	
795
	if (dest == NULL) {
796
		return -1;
797
	}
798

  
799
	int i;
800
	for (i = 3; i < len + 3; i++) {
801
		dest[i - 3] = xbee_buf[i];
802
	}
803
	return len;
804
}
805

  
806
/**
807
 * Handles modem status packets.
808
 *
809
 * @param status the type of status packet received.
810
 **/
811
void xbee_handle_status(char status)
812
{
813
	switch (status)
814
	{
815
		case 0:
816
			WL_DEBUG_PRINT("XBee hardware reset.\r\n");
817
			break;
818
		case 1:
819
			WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
820
			break;
821
		case 2:
822
			WL_DEBUG_PRINT("Associated.\r\n");
823
			break;
824
		case 3:
825
			WL_DEBUG_PRINT("Disassociated.\r\n");
826
			break;
827
		case 4:
828
			WL_DEBUG_PRINT("Synchronization lost.\r\n");
829
			break;
830
		case 5:
831
			WL_DEBUG_PRINT("Coordinator realignment.\r\n");
832
			break;
833
		case 6:
834
			WL_DEBUG_PRINT("Coordinator started.\r\n");
835
			break;
836
	}
837
}
838

  
839
/**
840
 * Handles AT command response packets.
841
 * @param command the two character AT command, e.g. MY or ID
842
 * @param result 0 for success, 1 for an error
843
 * @param extra the hex value of the requested register
844
 * @param extraLen the length in bytes of extra
845
 **/
846
static void xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen)
847
{
848
	if (result == 1)
849
	{
850
		WL_DEBUG_PRINT("Error with AT");
851
		WL_DEBUG_PRINT(command);
852
		WL_DEBUG_PRINT(" packet.\r\n");
853
	}
854
	WL_DEBUG_PRINT("AT");
855
	WL_DEBUG_PRINT(command);
856
	WL_DEBUG_PRINT(" command was successful.\r\n");
857

  
858
	if (command[0] == 'I' && command[1] == 'D')
859
	{
860
		xbee_panID = xbee_pending_panID;
861
		WL_DEBUG_PRINT("PAN ID set to ");
862
		WL_DEBUG_PRINT_INT(xbee_panID);
863
		WL_DEBUG_PRINT(".\r\n");
864
		return;
865
	}
866

  
867
	if (command[0] == 'C' && command[1] == 'H')
868
	{
869
		xbee_channel = xbee_pending_channel;
870
		WL_DEBUG_PRINT("Channel set to ");
871
		WL_DEBUG_PRINT_INT(xbee_channel);
872
		WL_DEBUG_PRINT(".\r\n");
873
		return;
874
	}
875

  
876
	if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
877
	{
878
		xbee_address = 0;
879
		int i;
880
		for (i = 0; i < extraLen; i++) {
881
			xbee_address = (xbee_address << 8) + extra[i];
882
		}
883

  
884
		WL_DEBUG_PRINT("XBee address is ");
885
		WL_DEBUG_PRINT_INT(xbee_address);
886
		WL_DEBUG_PRINT(".\r\n");
887

  
888
		if (xbee_address == 0)
889
		{
890
			WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
891
			#ifndef ROBOT
892
			exit(0);
893
			#endif
894
		}
895
	}
896
}
897

  
898
/**
899
 * Attempts to handle the packet if it is dealt with
900
 * by the library.
901
 * We will handle the following packet types:
902
 *    Modem Status
903
 *    AT Command Response
904
 *
905
 * @param packet the packet to handle
906
 * @param len the length of the packet
907
 *
908
 * @return 1 if we have handled the packet, 0 otherwise
909
 */
910
static int xbee_handle_packet(char* packet, int len)
911
{
912

  
913
	char command[3] = {1, 2, 3};
914
	if (len <= 0) //this should not happend
915
	{
916
		WL_DEBUG_PRINT("Non-positive packet length.\r\n");
917
		return 0;
918
	}
919

  
920
	switch ((unsigned char)packet[0]) //packet type
921
	{
922
		case XBEE_FRAME_STATUS:
923
			xbee_handle_status(packet[1]);
924
			return 1;
925
		case XBEE_FRAME_AT_COMMAND_RESPONSE:
926
			command[0] = packet[2];
927
			command[1] = packet[3];
928
			command[2] = 0;
929
			xbee_handle_at_command_response(command, packet[4], packet + 5, len - 5);
930
			return 1;
931
	}
932
	return 0;
933
}
934

  
935
/**
936
 * Sets the personal area network id.
937
 *
938
 * @param id the new personal area network (PAN) id
939
 **/
940
int xbee_set_pan_id(int id)
941
{
942
	char s[3];
943
	s[0] = (id >> 8) & 0xFF;
944
	s[1] = id & 0xFF;
945
	s[2] = 0;
946
	xbee_pending_panID = id;
947
	return xbee_send_modify_at_command("ID", s);
948
}
949

  
950
/**
951
 * Get the PAN ID for the XBee.
952
 *
953
 * @return the personal area network id, or
954
 * XBEE_PAN_DEFAULT if it has not yet been set.
955
 **/
956
unsigned int xbee_get_pan_id()
957
{
958
	return xbee_panID;
959
}
960

  
961
/**
962
 * Set the channel the XBee is using.
963
 *
964
 * @param channel the channel the XBee will not use,
965
 * between 0x0B and 0x1A
966
 *
967
 * @see xbee_get_channel
968
 **/
969
int xbee_set_channel(int channel)
970
{
971
	if (channel < 0x0B || channel > 0x1A)
972
	{
973
		WL_DEBUG_PRINT("Channel out of range.\r\n");
974
		return -1;
975
	}
976

  
977
	char s[3];
978
	s[0] = channel & 0xFF;
979
	s[1] = 0;
980
	xbee_pending_channel = channel;
981

  
982
	return xbee_send_modify_at_command("CH", s);
983
}
984

  
985
/**
986
 * Returns the channel which the XBee is currently using.
987
 *
988
 * @return the channel the XBee is using
989
 *
990
 * @see xbee_set_channel
991
 **/
992
int xbee_get_channel(void)
993
{
994
	return xbee_channel;
995
}
996

  
997
/**
998
 * Get the 16-bit address of the XBee.
999
 * This is used to specify who to send messages to
1000
 * and who messages are from.
1001
 *
1002
 * @return the 16-bit address of the XBee.
1003
 **/
1004
unsigned int xbee_get_address()
1005
{
1006
	return xbee_address;
1007
}
1008

  
1009
#ifndef ROBOT
1010
void xbee_set_com_port(char* port)
1011
{
1012
	xbee_com_port = port;
1013
}
1014
#endif
trunk/code/projects/test/main.c
15 15
    // RUN_TEST(testmotors);
16 16
    // RUN_TEST(testrangefinder);
17 17
    // RUN_TEST(testtokenring);
18
    RUN_TEST(testwireless);
18
    // RUN_TEST(testwireless);
19
    RUN_TEST(testxbee);
19 20
  }
20 21

  
21 22
  return 0;
trunk/code/projects/test/test_usb.c
40 40
  usb_putc('\n');
41 41
  usb_puts("enter an 'a':");  
42 42

  
43
  /* TODO: add test for getting values from usb */
43
  // test getting a value from usb
44 44
  if (usb_getc() == 'a')
45 45
    usb_puts("\r\ngetc() works\r\n");
46 46
  else

Also available in: Unified diff