Project

General

Profile

Revision 1604

wireless: software retransmit done. serial functions moved to xbee.c

View differences:

branches/wireless/code/projects/libwireless/xbee_computer.c
13 13

  
14 14
#endif
15 15

  
16
#ifdef USE_STDIO
16 17

  
18
#include <stdio.h>
19

  
20
/**
21
 * For use with fprintf() and related stdio functions
22
 **/
23
FILE *xbee_fd;
24

  
25
#endif
26

  
27
uint8_t xbee_initd=0;
28

  
29
/**
30
 * Initializes communication over the XBee.
31
 * This must be called before any other xbee function
32
 * may be used.
33
 **/
34
int xbee_init() {
35

  
36
  if(xbee_initd) {
37
    return ERROR_INIT_ALREADY_INITD;
38
  }
39

  
40
  //Set baud rate
41
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
42
  // - 9600 is U2X =1, UBRR = 107.
43
#if (XBEE_BAUD == 115200)
44
  UBRR1H = 0x00;
45
  UBRR1L = 8;
46
  UCSR1A |= _BV(U2X1);
47
#elif (XBEE_BAUD == 9600)
48
  UBRR1H = 0x00;
49
  UBRR1L = 103;
50
  UCSR1A |= _BV(U2X1);
51
#else //Baud rate is defined in the header file, we should not get here
52
  return 0;
53
#endif
54

  
55
  //Enable receiver and transmitter
56
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
57
	
58
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
59
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
60
  
61
  // if we have enabled the stdio stuff, then we init it here
62
#ifdef USE_STDIO
63
  /* Open the stdio stream corresponding to this port */
64
  xbee_fd = fdevopen(xbee_putc, xbee_getc);
65
#endif
66

  
67
  xbee_initd = 1;
68
  return 0;
69

  
70
}
71

  
72

  
73
/**@brief The port to use the XBee from on the computer. **/
74
#ifndef ROBOT
75
#define XBEE_PORT_DEFAULT "/dev/ttyUSB1"
76
#endif
77

  
78

  
79
/**@brief Set the com port on a computer, undefined on the robot**/
80
void xbee_set_com_port(char* port);
81

  
17 82
#define XBEE_GET_PACKET_TIMEOUT 1000
18 83

  
19 84
#ifndef ROBOT
branches/wireless/code/projects/libwireless/wireless.h
107 107
/**@brief init_flag when library has been initialized **/
108 108
#define INIT_YES UINT8_C(1)
109 109

  
110
/**@brief numer of reliable sending retries **/
111
#define NUM_RETRIES UINT8_C(3)
112

  
110 113
/**@} **/ // end defines group
111 114

  
112 115
/**
branches/wireless/code/projects/libwireless/xbee.c
95 95
// aka, the first free byte in other buffer
96 96
static uint8_t other_buf_last = 0;
97 97

  
98

  
99 98
// xbee status
100 99
#define XBEE_API_OFF 0x0
101 100
#define XBEE_API_ON 0x1
......
103 102
#define XBEE_NORMAL 0x00
104 103
#define XBEE_COMMAND_WAIT 0x80
105 104
#define XBEE_COMMAND_RESPONSE 0xC0
105
#define XBEE_INITD 0x08
106 106
static uint8_t xbee_status = XBEE_API_OFF|XBEE_NORMAL;
107 107

  
108 108
// xbee command response (for PAN, channel, address, etc)
......
303 303
} // end of interrupt
304 304

  
305 305

  
306

  
307 306
/* adds a byte to the basic buffer */
308 307
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
309 308
  if (*ptr == basic_buf_first) {
......
340 339
/**
341 340
 * Initializes the XBee library so that other functions may be used.
342 341
 **/
343
int8_t xbee_lib_init()
342
int8_t xbee_init()
344 343
{
345
  // do serial.c xbee init     TODO: merge this into xbee.c
346
  if (xbee_init() != 0) {
347
    usb_puts("xbee_init error");
348
    return WL_ERROR_INIT_FAILED;
344
	WL_DEBUG_PRINT("in xbee_init\n");
345
  
346
  if(xbee_status&0x08 == XBEE_INITD) {
347
    return WL_ERROR_INIT_ALREADY_INITD;
349 348
  }
350

  
351
	WL_DEBUG_PRINT("in xbee_init\n");
352

  
353
	//enable the receiving interrupt
349
  
350
  // Set startup baud rate of 9600
351
	// Set frame format: 8data, 1stop bit, asynchronous normal mode
352
  // Enable receiver and transmitter and the receiving interrupt
354 353
#ifdef FIREFLY
355
	UCSR0B |= _BV(RXCIE) | _BV(RXEN);
354
  UCSR0A |= (1<<U2X0);
355
  UBRR0H = 0x00;
356
  UBRR0L = 103;
357
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
358
	UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); 
356 359
#else
357
#ifdef BAYBOARD
358
	UCSR1B |= _BV(RXCIE1);
359
#else
360
	UCSR1B |= _BV(RXCIE);
360
  // Bayboard or robot
361
  UCSR1A |= (1<<U2X1);
362
  UBRR1H = 0x00;
363
  UBRR1L = 103;
364
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
365
	UCSR1B |= (1<<RXEN1) | (1<<TXEN1) | (1<<RXCIE1);
361 366
#endif
362
#endif
363 367
	sei();
364 368

  
365 369
	WL_DEBUG_PRINT("Entering command mode.\r\n");
......
398 402
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
399 403
  
400 404
  // set UART baud
405
#ifdef FIREFLY
401 406
#if (XBEE_BAUD == 115200)
407
  UBRR0H = 0x00;
408
  UBRR0L = 8;
409
#elif (XBEE_BAUD == 57600)
410
  UBRR0H = 0x00;
411
  UBRR0L = 16;
412
#elif (XBEE_BAUD == 38400)
413
  UBRR0H = 0x00;
414
  UBRR0L = 25;
415
#elif (XBEE_BAUD == 19200)
416
  UBRR0H = 0x00;
417
  UBRR0L = 51;
418
#elif (XBEE_BAUD == 9600)
419
  /* this is the default baud rate, so do nothing
420
  UBRR0H = 0x00;
421
  UBRR0L = 103;*/
422
#else
423
  WL_DEBUG_PRINT("undefined baud rate\r\n");
424
  return WL_ERROR_BUAD;
425
#endif
426
#else // Bayboard or robot
427
#if (XBEE_BAUD == 115200)
402 428
  UBRR1H = 0x00;
403 429
  UBRR1L = 8;
404
  UCSR1A |= _BV(U2X1);
405 430
#elif (XBEE_BAUD == 57600)
406 431
  UBRR1H = 0x00;
407 432
  UBRR1L = 16;
408
  UCSR1A |= _BV(U2X1);
409 433
#elif (XBEE_BAUD == 38400)
410 434
  UBRR1H = 0x00;
411 435
  UBRR1L = 25;
412
  UCSR1A |= _BV(U2X1);
413 436
#elif (XBEE_BAUD == 19200)
414 437
  UBRR1H = 0x00;
415 438
  UBRR1L = 51;
416
  UCSR1A |= _BV(U2X1);
417 439
#elif (XBEE_BAUD == 9600)
418 440
  /* this is the default baud rate, so do nothing
419 441
  UBRR1H = 0x00;
420
  UBRR1L = 103;
421
  UCSR1A |= _BV(U2X1);*/
442
  UBRR1L = 103;*/
422 443
#else
423 444
  WL_DEBUG_PRINT("undefined baud rate\r\n");
424 445
  return WL_ERROR_BUAD;
425 446
#endif
447
#endif
426 448
  delay_ms(50);
427 449

  
428 450
  // enter command mode
......
447 469
  
448 470
  // TODO: we should set the MY address to the robot address from eeprom
449 471
  
472
  
473
  // set status
474
  xbee_status |= XBEE_INITD;
475
  
450 476
	return WL_SUCCESS;
451 477
}
452 478

  
453 479
/**
454 480
 * Call when finished using the XBee library.
455 481
 **/
456
void xbee_terminate()
482
int8_t xbee_terminate()
457 483
{
458
  xbee_exit_api_mode();
484
  if (xbee_exit_api_mode() != WL_SUCCESS) {
485
    WL_DEBUG_PRINT("xbee termination failed\r\n");
486
    return WL_ERROR_TERMINATION_FAILED;
487
  }
488
  xbee_status = xbee_status&0xF7; // clean initd status
489
  return WL_SUCCESS;
459 490
}
460 491

  
461 492
/**
493
 * Sends a character to the XBee.
494
 *
495
 * @param c the byte to send
496
 * @return 0 for success, nonzero for failure
497
 **/
498
int xbee_putc(char c) {
499
  if(!(xbee_status&XBEE_INITD))
500
    return WL_ERROR_LIBRARY_NOT_INITD;
501

  
502
  // Wait until buffer is clear for sending
503
  // Then load buffer with your character
504
#ifdef FIREFLY
505
  loop_until_bit_is_set(UCSR0A, UDRE0);  
506
  UDR0 = c;
507
#else
508
  loop_until_bit_is_set(UCSR1A, UDRE1);
509
  UDR1 = c;
510
#endif
511
	
512
  return WL_SUCCESS;
513
}
514

  
515
/**
516
 * Returns the first byte in the buffer received from xbee.
517
 * This function blocks execution until a character has been
518
 * received. xbee_init must be called before this function
519
 * may be used.
520
 * 
521
 * @return the first character in the xbee buffer, -1 on error
522
 * 
523
 * @see xbee_init, xbee_getc_nb
524
 **/
525
int16_t xbee_getc(void) {
526
  if(!(xbee_status&XBEE_INITD))
527
    return WL_ERROR_LIBRARY_NOT_INITD;
528

  
529
  // Wait for the receive buffer to be filled
530
  // Then read the receive buffer
531
#ifdef FIREFLY
532
  loop_until_bit_is_set(UCSR0A, RXC0);  
533
  return UDR0;
534
#else
535
  loop_until_bit_is_set(UCSR1A, RXC1);
536
  return UDR1;
537
#endif
538
}
539

  
540
/**
541
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
542
 * it is returned, otherwise -1 is returned immediately. xbee_init
543
 * must be called before this function can be used.
544
 *
545
 * @param c The received byte. This will be set if a byte has been received.
546
 * 
547
 * @return -1 If no byte is available, 0 otherwise, positive for error
548
 *
549
 * @see xbee_getc
550
 **/
551
int8_t xbee_getc_nb(uint8_t *c) {
552
  if(!(xbee_status&XBEE_INITD))
553
    return WL_ERROR_LIBRARY_NOT_INITD;
554

  
555
  // check if the receive buffer is filled
556
#ifdef FIREFLY
557
  if (UCSR0A & (1<<RXC0)) {
558
    (*c) = UDR0;
559
#else
560
  if (UCSR1A & (1<<RXC1)) {
561
    (*c) = UDR1;
562
#endif
563
    return WL_SUCCESS;
564
  }
565
  return -1; // Return empty
566
}
567

  
568
/**
462 569
 * Send a buffer buf of size bytes to the XBee.
463 570
 *
464 571
 * @param buf the buffer of data to send
......
509 616
static int8_t xbee_exit_command_mode()
510 617
{
511 618
	if (xbee_send_string("ATCN\r") != 0) {
512
		return -1;
619
		return WL_ERROR_SEND;
513 620
	}
514

  
515 621
	xbee_wait_for_ok();
516 622

  
517
	return 0;
623
	return WL_SUCCESS;
518 624
}
519 625

  
520 626
/**
521 627
 * Enter API mode.
522 628
 **/
523
static int xbee_enter_api_mode()
629
static int8_t xbee_enter_api_mode()
524 630
{
525 631
	if (xbee_send_string("ATAP 1\r") != 0) {
526
		return -1;
632
		return WL_ERROR_SEND;
527 633
	}
528 634
	xbee_wait_for_ok();
529 635
  
530 636
  xbee_status = (xbee_status&0xFC)|XBEE_API_ON;
531 637

  
532
	return 0;
638
	return WL_SUCCESS;
533 639
}
534 640

  
535 641
/**
536 642
 * Enter API mode 2.
537 643
 **/
538
static int xbee_enter_api_mode2()
644
static int8_t xbee_enter_api_mode2()
539 645
{
540 646
	if (xbee_send_string("ATAP 2\r") != 0) {
541
		return -1;
647
		return WL_ERROR_SEND;
542 648
	}
543 649
	xbee_wait_for_ok();
544 650
  
545 651
  xbee_status = (xbee_status&0xFC)|XBEE_API_ESCAPE;
546 652
  
547
	return 0;
653
	return WL_SUCCESS;
548 654
}
549 655

  
550 656
/**
551 657
 * Exit API mode.
552 658
 **/
553
static int xbee_exit_api_mode()
659
static int8_t xbee_exit_api_mode()
554 660
{
555
	if (xbee_send_modify_at_command("AP","0") != 0) {
556
		return -1;
557
	}
661
	if (xbee_status&0xC0 == XBEE_COMMAND_WAIT
662
    || xbee_status&0xC0 == XBEE_COMMAND_RESPONSE)
663
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
558 664
  
559
  xbee_status = (xbee_status&0xFC)|XBEE_API_OFF;
560

  
561
	return 0;
665
  int16_t i=0;
666
  // change status to command wait
667
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
668
  xbee_send_modify_at_command("AP","0",1); // send command
669
  // wait for up to 30 ms
670
  while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) {
671
    delay_us(1); // wait 3us
672
  }
673
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
674
    i = WL_SUCCESS;
675
  else
676
    i = WL_ERROR_XBEE_COMMAND; // set error code
677
  xbee_status = (xbee_status&0x3C)|XBEE_API_OFF; // reset status
678
	return (int8_t)i; // return
562 679
}
563 680

  
564 681
/**
......
571 688

  
572 689
/**
573 690
 * Delay until the specified string is received from
574
 * the XBee. Discards all other XBee data.
691
 * the XBee.
575 692
 *
576
 * ********* Robot often hangs here ****************
693
 * Only works when not in API mode
577 694
 *
578 695
 * @param s the string to receive
579 696
 * @param len the length of the string
......
670 787
 * @return the checksum of the packet, which will
671 788
 * become the last byte sent in the packet
672 789
 **/
673
char xbee_compute_checksum(uint8_t* buf, uint16_t len)
790
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
674 791
{
675 792
	uint8_t sum = 0;
676 793
	while(--len > 0) {
......
681 798
}
682 799

  
683 800
/**
801
 * Adds buf to the previous checksum total
802
 *
803
 * @param buf a byte buffer to add to the checksum
804
 * @param len the length of the buffer
805
 * @param sum the previous sum
806
 *
807
 * @return error code
808
 **/
809
static int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
810
  if (buf == NULL || sum == NULL)
811
    return WL_ERROR_ARGUMENT;
812
  while(--len > 0) {
813
		*sum += buf[len];
814
  }
815
  *sum += buf[0];
816
}
817

  
818

  
819
/**
820
 * Sends header information. Header information includes
821
 * XBEE_FRAME_START and the packet length, as two bytes.
822
 *
823
 * @param type the packet type
824
 * @param len the size in bytes of the packet data
825
 *
826
 **/
827
static int8_t xbee_send_header(uint8_t type, uint16_t len)
828
{  
829
  //packet prefix
830
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
831
    return WL_ERROR_SEND;
832
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
833
    return WL_ERROR_SEND;
834
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
835
    return WL_ERROR_SEND;
836

  
837
	if (xbee_send(buf, len) != WL_SUCCESS)
838
		return WL_ERROR_SEND;
839
	
840
	if (xbee_putc(checksum) != WL_SUCCESS)
841
		return WL_ERROR_SEND;
842
	
843
	return WL_SUCCESS;
844
}
845

  
846
/**
684 847
 * Adds header information and checksum to the given
685 848
 * packet and sends it. Header information includes
686 849
 * XBEE_FRAME_START and the packet length, as two bytes.
......
691 854
 **/
692 855
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
693 856
{
694
	uint8_t prefix[3];
695
	prefix[0] = XBEE_FRAME_START;
696
	prefix[1] = (len & 0xFF00) >> 8;
697
	prefix[2] = len & 0x00FF;
698 857
	uint8_t checksum = xbee_compute_checksum(buf, len);
858
  
859
  //packet prefix
860
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
861
    return WL_ERROR_SEND;
862
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
863
    return WL_ERROR_SEND;
864
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
865
    return WL_ERROR_SEND;
699 866

  
700
	if (xbee_send(prefix, 3) != 0) {
867
	if (xbee_send(buf, len) != WL_SUCCESS)
701 868
		return WL_ERROR_SEND;
702
	}
703

  
704
	if (xbee_send(buf, len) != 0) {
869
	
870
	if (xbee_putc(checksum) != WL_SUCCESS)
705 871
		return WL_ERROR_SEND;
706
	}
707

  
708
	if (xbee_send(&checksum, 1) != 0) {
709
		return WL_ERROR_SEND;
710
	}
711

  
872
	
712 873
	return WL_SUCCESS;
713 874
}
714 875

  
......
771 932
 * the XBee alerts us as to whether or not our message
772 933
 * was received.
773 934
 **/
774
int xbee_send_packet(char* packet, int len, int dest, char options, char frame)
935
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
775 936
{
776
	char buf[5];
777
	char prefix[3];
778
	int i;
779
	unsigned char checksum = 0;
937
	uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
938
  uint8_t i = 0;
780 939

  
781 940
	if (len > 100)
782 941
	{
783 942
		WL_DEBUG_PRINT("Packet is too large.\r\n");
784
		return -1;
943
		return WL_ERROR_ARGUMENT;
785 944
	}
945
  
946
  // calculate checksum
947
	for(;i<len;i++)
948
		sum += packet[len];
949
  sum += frame;
950
  sum += (dest&0xFF00) >> 8;
951
  sum += dest&0x00FF;
952
  sum += options;
953
	sum = 0xFF - sum;
786 954

  
787
	//data for sending request
788
	buf[0] = XBEE_FRAME_TX_REQUEST_16;
789
	buf[1] = frame;
790
	buf[2] = (dest >> 8) & 0xFF;
791
	buf[3] = dest & 0xFF;
792
	buf[4] = options;
955
	//packet prefix
956
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
957
    return WL_ERROR_SEND;
958
  if (xbee_putc(0x00) != WL_SUCCESS)
959
    return WL_ERROR_SEND;
960
  if (xbee_putc(len+5) != WL_SUCCESS)
961
    return WL_ERROR_SEND;
962
    
963
	//send header for TX request
964
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
965
    return WL_ERROR_SEND;
966
  if (xbee_putc(frame) != WL_SUCCESS)
967
    return WL_ERROR_SEND;
968
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
969
    return WL_ERROR_SEND;
970
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
971
    return WL_ERROR_SEND;
972
  if (xbee_putc(options) != WL_SUCCESS)
973
    return WL_ERROR_SEND;
793 974

  
794
	//packet prefix, do this here so we don't need an extra buffer
795
	prefix[0] = XBEE_FRAME_START;
796
	prefix[1] = ((5 + len) & 0xFF00) >> 8;
797
	prefix[2] = (5 + len) & 0xFF;
975
  // send packet
976
	if (xbee_send(packet, len) != WL_SUCCESS)
977
		return WL_ERROR_SEND;
798 978

  
799
	for (i = 0; i < 5; i++)
800
		checksum += (unsigned char)buf[i];
801
	for (i = 0; i < len; i++)
802
		checksum += (unsigned char)packet[i];
803
	checksum = 0xFF - checksum;
979
  // send checksum
980
	if (xbee_putc(sum) != WL_SUCCESS)
981
		return WL_ERROR_SEND;
804 982

  
805
	if (xbee_send(prefix, 3) != 0) {
806
		return -1;
807
	}
808

  
809
	if (xbee_send(buf, 5) != 0) {
810
		return -1;
811
	}
812

  
813
	if (xbee_send(packet, len) != 0) {
814
		return -1;
815
	}
816

  
817
	if (xbee_send((char*)&checksum, 1) != 0) {
818
		return -1;
819
	}
820

  
821
	return 0;
983
	return WL_SUCCESS;
822 984
}
823 985

  
824 986
/**
branches/wireless/code/projects/libwireless/wireless_send.c
40 40

  
41 41
/**
42 42
 * Definition for wireless library send packet structure
43
 * byte 1: length of packet
43
 * byte 1: length of packet (from frame number to end of data)
44 44
 * byte 2: frame number
45
 * byte 3: group code 
46
 * bytes 4-n: data
47
 * (byte n+1: num retries - only saved locally in sending buffer)
45
 * bytes 3-n: data (dest, options, frame number, group code, packet)
46
 * byte n+1: num retries
48 47
 *
49 48
 * Definition for ack buffer
50 49
 * 2 bit system: 0=still sending
......
60 59
uint8_t send_buf[PACKET_BUFFER_SIZE]; // sending buffer for retries
61 60
uint8_t send_buf_first = 0; // first byte of data on buffer
62 61
uint8_t send_buf_last = 0; // next free byte on buffer
62
uint8_t send_buf_num_packets = 0; // number of packets in sending buffer
63 63

  
64 64
/* private function prototypes */
65 65
void setack(uint8_t num,uint8_t val);
66
void ackhandle(uint8_t num,uint8_t val);
67
int8_t send_buf_add(uint8_t *ptr, uint8_t byte)
68
uint8_t send_buf_get(uint8_t *ptr);
66 69

  
67

  
68 70
// the send functions
69 71

  
70 72
/**
......
86 88
 * @return positive packet number for tracking acks, or error code (TBD)
87 89
 **/
88 90
int16_t wl_send(uint8_t *data, uint8_t length, uint8_t group, uint8_t scope, uint16_t dest, uint8_t mode) {
89
  uint8_t packet[length+2];
90
  uint8_t options = XBEE_OPTIONS_NONE;
91
  int16_t ret_val = (int16_t)nextframe;
91
  uint8_t packet[6];
92 92
  
93
  // build packet
93
  // build packet header
94 94
  packet[0] = nextframe;
95
  packet[1] = group;
96
  memcpy(packet+2,data,length);
95
  packet[1] = (dest&0xFF00)>>8;
96
  packet[2] = dest&0x00FF;  
97
  packet[3] = XBEE_OPTIONS_NONE;
98
  packet[4] = nextframe;
99
  packet[5] = group;
97 100
  
98 101
  // set scope
99 102
  if (scope == GLOBAL)
100
    options &= XBEE_OPTIONS_BROADCAST_ALL_PANS;
103
    packet[3] &= XBEE_OPTIONS_BROADCAST_ALL_PANS;
104
  else if (scope != PAN) {
105
    WL_DEBUG_PRINT("Error - bad scope in core send function\r\n");
106
    return WL_ERROR_SCOPE;
107
  }
101 108
    
102 109
  // set mode
103 110
  if (mode == FAST) {
104
    options &= XBEE_OPTIONS_DISABLE_RESPONSE;
105
    ret_val = 0;
111
    packet[3] &= XBEE_OPTIONS_DISABLE_RESPONSE;
106 112
  } else if (mode != RELIABLE) {
107 113
    WL_DEBUG_PRINT("Error - bad mode in core send function\r\n");
108 114
    return WL_ERROR_MODE;
109 115
  }
116
  
117
  // do checksum
118
  group = XBEE_FRAME_TX_REQUEST_16;
119
  xbee_checksum_add(packet,6,&group);
120
  xbee_checksum_add(data,length,&group); 
121
  group = 0xFF-group;
110 122

  
111 123
  // send the packet
112
  if (xbee_send_packet(packet,length,dest,options,(uint_8)ret_val) != 0) {
113
    WL_DEBUG_PRINT("Error sending packet from core send function\r\n");
124
  if (xbee_send_header(XBEE_FRAME_TX_REQUEST_16,length+7) != WL_SUCCESS) {
125
    WL_DEBUG_PRINT("1Error sending packet from core send function\r\n");
114 126
    return WL_ERROR_SEND;
115 127
  }
128
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS) {
129
    WL_DEBUG_PRINT("2Error sending packet from core send function\r\n");
130
    return WL_ERROR_SEND;
131
  }
132
  if (xbee_send(packet,6) != WL_SUCCESS) {
133
    WL_DEBUG_PRINT("3Error sending packet from core send function\r\n");
134
    return WL_ERROR_SEND;
135
  }
136
  if (xbee_send(data,length) != WL_SUCCESS) {
137
    WL_DEBUG_PRINT("4Error sending packet from core send function\r\n");
138
    return WL_ERROR_SEND;
139
  }
140
  if (xbee_putc(group) != WL_SUCCESS) {
141
    WL_DEBUG_PRINT("5Error sending packet from core send function\r\n");
142
    return WL_ERROR_SEND;
143
  }
116 144
  
117 145
  // save in ack system
118 146
  if (mode == FAST) {
119 147
    setack(nextframe,ACK_OK); // assume the send was successful
120 148
  } else if (mode == RELIABLE) {
121 149
    setack(nextframe,SENDING); // set status to SENDING
122
    // TODO: save packet on sending buffer
123
    /* if (buffer full) {
150
    // save packet on sending buffer
151
    scope = send_buf_last; // use as ptr to send buffer    
152
    if (send_buf_add(&scope,length+6) != WL_SUCCESS) { // add length
124 153
      WL_DEBUG_PRINT("Error: sending buffer full\r\n");
125
      return WL_ERROR_SENDING_BUFFER_FULL
126
    } */
154
      return WL_ERROR_SENDING_BUFFER_FULL;
155
    }    
156
    for(mode=0;mode<6;mode++) { // add header
157
      if (send_buf_add(&scope,packet[mode]) != WL_SUCCESS) {
158
        WL_DEBUG_PRINT("Error: sending buffer full\r\n");
159
        return WL_ERROR_SENDING_BUFFER_FULL;
160
      }
161
    }
162
    for(mode=0;mode<length;mode++) { // add data
163
      if (send_buf_add(&scope,data[mode]) != WL_SUCCESS) {
164
        WL_DEBUG_PRINT("Error: sending buffer full\r\n");
165
        return WL_ERROR_SENDING_BUFFER_FULL;
166
      }
167
    }
168
    if (send_buf_add(&scope,0) != WL_SUCCESS) { // add num retries=0
169
      WL_DEBUG_PRINT("Error: sending buffer full\r\n");
170
      return WL_ERROR_SENDING_BUFFER_FULL;
171
    }
172
    send_buf_last = scope;
173
    send_buf_num_packets++;
127 174
  }
128 175
  
129 176
  // increment frame number
......
273 320

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

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

  
122 122
/**@} */ // end error group
123 123

  
124
// TODO: is this a good size?
125
/*Buffer sizes*/
126
#define PACKET_BUFFER_SIZE	128
127

  
124 128
/**@} */ // end wireless group
125 129

  
126 130
#ifdef WL_DEBUG
branches/wireless/code/projects/libwireless/xbee.h
57 57
 /**@defgroup xbee_const xbee constants 
58 58
  * @brief These are constants used for the xbee module.
59 59
  * @{ **/
60
 
61
// TODO: move constants to xbee.h so they can be used publicly
62

  
63
/**@brief The port to use the XBee from on the computer. **/
64
#ifndef ROBOT
65
#define XBEE_PORT_DEFAULT "/dev/ttyUSB1"
60
  
61
#ifndef XBEE_BAUD
62
/** @brief The XBee baud rate **/
63
#define XBEE_BAUD 115200
66 64
#endif
67 65
 
68 66
/**@name xbee options
......
104 102

  
105 103
/** @} **/
106 104

  
107

  
108
// TODO: is this a good size?
109
/*Buffer sizes*/
110
#define XBEE_BUFFER_SIZE	128
111
#define PACKET_BUFFER_SIZE	108
112

  
113 105
/**@} **/ // end const group
114 106
 
115 107
/**
......
121 113
// TODO: convert all int references to int16_t syntax (see stdint.h)
122 114

  
123 115
/**@brief Initialize the XBee library **/
124
int xbee_lib_init(void);
116
int8_t xbee_init(void);
125 117
/**@brief Uninitialize the XBee library **/
126
void xbee_terminate(void);
118
int8_t xbee_terminate(void);
119
/**@brief Send a byte to the xbee **/
120
int8_t xbee_putc(uint8_t c);
121
/**@brief Read a byte form the xbee **/
122
int16_t xbee_getc(void);
123
/**@brief Read a byte from the xbee (nonblocking) **/
124
int8_t xbee_getc_nb(uint8_t *c);
125
/**@brief Send an array of bytes to the xbee **/
126
int8_t xbee_send(uint8_t* buf, uint16_t size);
127
/**@brief Add a buffer to the checksum value **/
128
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum);
129
/**@brief Send a frame header to the xbee **/
130
int8_t xbee_send_header(uint8_t type, uint16_t len);
127 131
/**@brief Send a packet to the XBee **/
128
int xbee_send_packet(char* packet, int len, int dest, char options, char frame);
132
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame);
129 133
/**@brief Set the PAN ID for the XBee **/
130
int xbee_set_pan_id(int id);
134
int16_t xbee_set_pan_id(int id);
131 135
/**@brief Get the XBee's PAN ID **/
132
unsigned int xbee_get_pan_id(void);
136
uint16_t xbee_get_pan_id(void);
133 137
/**@brief Set the channel the XBee is currently using **/
134
int xbee_set_channel(int channel);
138
int8_t xbee_set_channel(int channel);
135 139
/**@brief Get the channel the XBee is currently using **/
136
int xbee_get_channel(void);
140
int8_t xbee_get_channel(void);
137 141
/**@brief Get the XBee's 16-bit address **/
138
unsigned int xbee_get_address(void);
139
/**@brief Set the com port on a computer, undefined on the robot**/
140
void xbee_set_com_port(char* port);
142
uint16_t xbee_get_address(void);
141 143
/**@brief Reset XBee **/
142
int xbee_reset(void);
144
int8_t xbee_reset(void); // TODO: implement this function
143 145

  
144 146
/**@} **/ //end xbee_funcs group
145 147

  
branches/wireless/code/projects/libwireless/wireless.c
93 93
    // reset packet handler array
94 94
    memset(wl_packet_handlers, sizeof(PacketGroupHandler)*MAX_PACKET_GROUPS, 0);
95 95

  
96
    // TODO need pass termination error from lower level functions
97
    xbee_terminate();
98
    // if(TERMINATE FAILS) {
99
    //     return WL_ERROR_TERMINATION_FAILED
100
    // }
96
    if(xbee_terminate() != WL_SUCCESS) {
97
        return WL_ERROR_TERMINATION_FAILED
98
    }
101 99

  
102 100
    return WL_SUCCESS;
103 101
}
......
118 116
        return WL_ERROR_LIBRARY_NOT_INITD;
119 117
    }
120 118

  
121
    // packet group number exceeds available packets groups
122
    if(group >= MAX_PACKET_GROUPS) {
119
    // packet group number exceeds available packets groups   
120
    // or packet group handler already exists
121
    if(group >= MAX_PACKET_GROUPS || group == 0
122
        || wl_packet_handlers[group].FUNC != NULL) {
123 123
        return WL_ERROR_FAILED_REGISTRATION;
124 124
    }
125

  
126
    // packet group handler already exists, user needs to unregister first
127
    if(wl_packet_handlers[group].FUNC != NULL) {
128
        return WL_ERROR_FAILED_REGISTRATION;
129
    }
130 125
    
131 126
    // save packet handler function pointer and priority
132 127
    wl_packet_handlers[group].FUNC = FUNC;
branches/wireless/code/projects/libdragonfly/serial.c
39 39
#include "serial.h"
40 40

  
41 41
unsigned char usb_initd=0;
42
unsigned char xbee_initd=0;
43 42

  
44 43
#ifdef USE_STDIO
45 44

  
......
50 49
 **/
51 50
FILE *usb_fd;
52 51

  
53
/**
54
 * For use with fprintf() and related stdio functions
55
 **/
56
FILE *xbee_fd;
57

  
58 52
#endif
59 53

  
60 54
/**
......
100 94

  
101 95
}
102 96

  
103
/**
104
 * Initializes communication over the XBee.
105
 * This must be called before any other xbee function
106
 * may be used.
107
 **/
108
int xbee_init() {
109 97

  
110
  if(xbee_initd) {
111
    return ERROR_INIT_ALREADY_INITD;
112
  }
113

  
114
  //Set baud rate
115
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
116
  // - 9600 is U2X =1, UBRR = 107.
117
#if (XBEE_BAUD == 115200)
118
  UBRR1H = 0x00;
119
  UBRR1L = 8;
120
  UCSR1A |= _BV(U2X1);
121
#elif (XBEE_BAUD == 9600)
122
  UBRR1H = 0x00;
123
  UBRR1L = 103;
124
  UCSR1A |= _BV(U2X1);
125
#else //Baud rate is defined in the header file, we should not get here
126
  return 0;
127
#endif
128

  
129
  //Enable receiver and transmitter
130
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
131
	
132
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
133
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
134
  
135
  // if we have enabled the stdio stuff, then we init it here
136
#ifdef USE_STDIO
137
  /* Open the stdio stream corresponding to this port */
138
  xbee_fd = fdevopen(xbee_putc, xbee_getc);
139
#endif
140

  
141
  xbee_initd = 1;
142
  return 0;
143

  
144
}
145

  
146 98
/**
147 99
 * Sends a character over USB.
148 100
 *
......
163 115
}
164 116

  
165 117
/**
166
 * Sends a character to the XBee.
167
 *
168
 * @param c the character to send
169
 * @return 0 for success, nonzero for failure
170
 **/
171
int xbee_putc(char c) {
172

  
173
  if(!xbee_initd)
174
    return ERROR_LIBRARY_NOT_INITD;
175

  
176
  // Wait until buffer is clear for sending
177
  loop_until_bit_is_set(UCSR1A, UDRE1);
178
	
179
  // Load buffer with your character
180
  UDR1 = c;
181
  return 0;
182
}
183

  
184
/**
185 118
 * Sends a sequence of characters over USB.
186 119
 *
187 120
 * @param s the string to send
......
245 178
}
246 179

  
247 180
/**
248
 * Returns the first character in the buffer received from USB.
249
 * This function blocks execution until a character has been
250
 * received. xbee_init must be called before this function
251
 * may be used.
252
 * 
253
 * @return the first character in the xbee buffer, -1 on error
254
 * 
255
 * @see xbee_init, xbee_getc_nb
256
 **/
257
int xbee_getc(void) {
258

  
259
  if(!usb_initd)
260
    return -1;
261

  
262
  // Wait for the receive buffer to be filled
263
  loop_until_bit_is_set(UCSR1A, RXC1);
264
	
265
  // Read the receive buffer
266
  return UDR1;
267
}
268

  
269
/**
270 181
 * Non blocking version of usb_getc. If a character is present in the buffer,
271 182
 * it is returned, otherwise -1 is returned immediately. usb_init must be
272 183
 * called before this function can be used.
......
294 205
  }
295 206
}
296 207

  
297
/**
298
 * Non blocking version of xbee_getc. If a character is present in the buffer,
299
 * it is returned, otherwise -1 is returned immediately. xbee_init
300
 * must be called before this function can be used.
301
 *
302
 * @param c the received character. This will be set if a character has
303
 * been received.
304
 * 
305
 * @return -1 if no character is available, 0 otherwise, positive for error
306
 *
307
 * @see xbee_init, xbee_getc
308
 **/
309
int xbee_getc_nb(char *c) {
310
  if(!xbee_initd)
311
    return ERROR_LIBRARY_NOT_INITD;
312

  
313
  // check if the receive buffer is filled
314
  if (UCSR1A & _BV(RXC1)) {
315
    // Read the receive buffer
316
    (*c) = UDR1;
317
    return 0;
318
  } else {
319
    // Return empty
320
    return -1;
321
  }
322
}
323

  
324

  
325 208
/*
326 209
  prints an int to serial
327 210

  
branches/wireless/code/projects/libdragonfly/serial.h
107 107
/** @brief Print a fixed width hexadecimal representation to USB **/
108 108
int usb_puth8(uint8_t value);
109 109
/** @brief Alias for usb_puth16 **/
110
static inline void usb_puth (uint16_t value) { usb_puth16 (value); };
110
static inline void usb_puth(uint16_t value) { usb_puth16 (value); };
111 111

  
112

  
113 112
/** @} **/ //end addtogroup
114 113

  
115
/**
116
 * @defgroup xbee XBee Input / Output
117
 * @brief Functions for XBee input / output
118
 *
119
 * Low level functions for XBee input and output.
120
 *
121
 * @{
122
 **/
123

  
124
// if no baud rate is defined for usb, default is set here
125

  
126
// if no baud rate is defined for xbee, default is set here
127
#ifndef XBEE_BAUD
128
/** @brief the XBee baud rate **/
129
#define XBEE_BAUD 9600
130 114
#endif
131 115

  
132
/** @brief Initialize the XBee **/
133
int xbee_init(void);
134
/** @brief Print a character to the XBee **/
135
int xbee_putc(char c);
136
/** @brief Read a character from the XBee **/
137
int xbee_getc(void);
138
/** @brief Read a character from the XBee without blocking **/
139
int xbee_getc_nb(char *c);
140

  
141

  
142

  
143
/** @} **/ //end addtogroup
144

  
145
#endif
146

  

Also available in: Unified diff