Project

General

Profile

Revision 1646

wireless: wireless2.c

View differences:

branches/wireless/code/projects/unit_tests/xbee.h
1
/**
2
 * Copyright (c) 2009 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.h
28
 * @brief Contains definitions for using the XBee
29
 *
30
 * Contains definitions for interfacing with the 
31
 * XBee module, from either a robot or a computer.
32
 * To use a robot, define ROBOT in wl_defs.h, and
33
 * to use a computer, don't define ROBOT.
34
 *
35
 * @author Colony Project, CMU Robotics Club
36
 **/
37

  
38
#ifndef XBEE_H
39
#define XBEE_H
40

  
41
// need this for C99 int types
42
#ifndef STDINT_H
43
#define STDINT_H
44
#include <stdint.h>
45
#endif
46

  
47

  
48
/**
49
 * @defgroup xbee XBee
50
 * @brief Interface with the XBee module
51
 *
52
 * Interface with the XBee module.
53
 *
54
 * @{
55
 **/
56
 
57
 /**@defgroup xbee_const xbee constants 
58
  * @brief These are constants used for the xbee module.
59
  * @{ **/
60
  
61
#ifndef XBEE_BAUD
62
/** @brief The XBee baud rate **/
63
#define XBEE_BAUD 9600 //115200
64
#endif
65
 
66
/**@name xbee options
67
 * @{ **/
68
 
69
/**@brief Unset PAN, uses XBee default **/
70
#define XBEE_PAN_DEFAULT 0xFFFF
71
/**@brief Unset channel, uses XBee default **/
72
#define XBEE_CHANNEL_DEFAULT 0
73
/**@brief Broadcast to all robots in the PAN **/
74
#define XBEE_BROADCAST 0xFFFF
75
/**@brief No special options **/
76
#define XBEE_OPTIONS_NONE 0x00
77
/**@brief Do not receive a TX_STATUS message from this packet **/
78
#define XBEE_OPTIONS_DISABLE_RESPONSE 0x01
79
/**@brief Send the packet to all PANS **/
80
#define XBEE_OPTIONS_BROADCAST_ALL_PANS 0x04
81
/**@brief A transmit status packet **/
82
#define XBEE_TX_STATUS 0x89
83
/**@brief A packet received from another XBee **/
84
#define XBEE_RX 0x81
85

  
86
/**@}
87
 * @name xbee frame types
88
 * @{ **/
89

  
90
// TODO: add comments for all of these definitions
91

  
92
/*Frame Types*/
93
#define XBEE_FRAME_START 0x7E
94
#define XBEE_FRAME_STATUS 0x8A
95
#define XBEE_FRAME_AT_COMMAND 0x08
96
#define XBEE_FRAME_AT_COMMAND_RESPONSE 0x88
97
#define XBEE_FRAME_TX_REQUEST_64 0x00
98
#define XBEE_FRAME_TX_REQUEST_16 0x01
99
#define XBEE_FRAME_TX_STATUS XBEE_TX_STATUS
100
#define XBEE_FRAME_RX_64 0x80
101
#define XBEE_FRAME_RX_16 XBEE_RX
102

  
103
/** @} **/
104

  
105
/**@} **/ // end const group
106
 
107
/**
108
 * @defgroup xbee_funcs Xbee Functions
109
 * @brief These are the public xbee functions.
110
 * @{
111
 **/
112
  
113
/**@brief Initialize the XBee library **/
114
int8_t xbee_init(void);
115
/**@brief Uninitialize the XBee library **/
116
int8_t xbee_terminate(void);
117
/**@brief Send a byte to the xbee **/
118
int8_t xbee_putc(uint8_t c);
119
/**@brief Read a byte form the xbee **/
120
int16_t xbee_getc(void);
121
/**@brief Read a byte from the xbee (nonblocking) **/
122
int8_t xbee_getc_nb(uint8_t *c);
123
/**@brief Send an array of bytes to the xbee **/
124
int8_t xbee_send(uint8_t* buf, uint16_t size);
125
/**@brief Add a buffer to the checksum value **/
126
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum);
127
/**@brief Send a frame header to the xbee **/
128
int8_t xbee_send_header(uint16_t len);
129
/**@brief Send a packet to the XBee **/
130
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame);
131
/**@brief Set the PAN ID for the XBee **/
132
int8_t xbee_set_pan(uint16_t id);
133
/**@brief Get the XBee's PAN ID **/
134
uint16_t xbee_get_pan(void);
135
/**@brief Set the channel the XBee is currently using **/
136
int8_t xbee_set_channel(uint8_t channel);
137
/**@brief Get the channel the XBee is currently using **/
138
int8_t xbee_get_channel(void);
139
/**@brief Get the XBee's 16-bit address **/
140
uint16_t xbee_get_address(void);
141
/**@brief Reset XBee **/
142
int8_t xbee_reset(void); // TODO: implement this function
143

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

  
146
/**@} **/ //end defgroup
147

  
148
#endif
branches/wireless/code/projects/unit_tests/wireless.h
1
/**
2
 * Copyright (c) 2009 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

  
26
/**
27
 * @file wireless.h
28
 * @brief Contains definitions for using the wireless library
29
 *
30
 * Contains definitions for interfacing with the 
31
 * wireless library.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
36
#ifndef WIRELESS_H
37
#define WIRELESS_H
38

  
39
// need this for C99 int types
40
#ifndef STDINT_H
41
#define STDINT_H
42
#include <stdint.h>
43
#endif
44

  
45

  
46
/**
47
 * @defgroup wireless Wireless
48
 * @brief Interface with the wireless library
49
 *
50
 * Interface with the wireless library.
51
 *
52
 * @{
53
 **/
54
 
55
/**@defgroup wl_defines Public Constants
56
 * @{ **/
57
 
58
/**@brief basic group code **/
59
#define BASIC UINT8_C(0)
60

  
61
/**@brief global scope **/
62
#define GLOBAL UINT8_C(0)
63

  
64
/**@brief local pan scope **/
65
#define PAN UINT8_C(1)
66

  
67
/**@brief broadcast address **/
68
#define BROADCAST UINT16_C(0xFFFF)
69

  
70
/**@brief reliable (TCP) mode **/
71
#define RELIABLE UINT8_C(0)
72

  
73
/**@brief fast (UDP) mode **/
74
#define FAST UINT8_C(1)
75

  
76
/**@brief standard priority **/
77
#define NORMAL_PRIORITY UINT8_C(0)
78

  
79
/**@brief high priority, handle immediately **/
80
#define HIGH_PRIORITY UINT8_C(1)
81

  
82
/**@brief packet still in sending phase **/
83
#define SENDING UINT8_C(0)
84

  
85
/**@brief packet was send successfully **/
86
#define ACK_OK UINT8_C(1)
87

  
88
/**@brief packet failure - no acknowledgment **/
89
#define ACK_FAILURE UINT8_C(2)
90

  
91
/**@brief packet failure - network too busy **/
92
#define CCA_FAILURE UINT8_C(3)
93

  
94
/**@brief packet handler function pointer type **/
95
#define FUNC func
96

  
97
/**@brief packet handler function pointer type **/
98
#define FNPTR void (*FUNC)(uint8_t* data,uint8_t length,uint8_t source)
99

  
100
// TODO: this max may be too big b/c the packet handler array stores 3*MAX_PACKET_GROUPS bytes 
101
/**@brief maximum number of packet groups, size of handler array **/
102
#define MAX_PACKET_GROUPS UINT8_C(16)
103

  
104
/**@brief init_flag when library has not been initialized **/
105
#define INIT_NO UINT8_C(0)
106

  
107
/**@brief init_flag when library has been initialized **/
108
#define INIT_YES UINT8_C(1)
109

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

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

  
115
/**
116
 * @struct PacketGroupHandler
117
 * A PacketGroupHandler represents a packet group, and is used to
118
 * register a packet group with the wireless library. It contains
119
 * a function pointer to the packet handler function and the priority
120
 * of the packet group.
121
 **/
122
typedef struct {
123
    
124
    // function pointer of handler for this packet group
125
    FNPTR;
126

  
127
    // priority for this packet group
128
    uint8_t priority;
129
    
130
} PacketGroupHandler;
131

  
132
static PacketGroupHandler wl_packet_handlers[MAX_PACKET_GROUPS];
133

  
134
/**@defgroup wl_functions Public API Functions 
135
 * @{ **/
136
 
137
// the init function
138

  
139
/**@brief Initialize wireless. **/
140
int8_t wl_init(void);
141

  
142
/**@brief Terminate wireless. **/
143
int8_t wl_terminate(void);
144

  
145

  
146
// the send functions
147

  
148
/**@brief The core send function. This will take all possible arguments and send all types of packets. **/
149
int16_t wl_send(uint8_t *data, uint8_t length, uint8_t group, uint8_t scope, uint16_t dest, uint8_t mode);
150

  
151
/**@brief Wrapper for core send function that will send a global packet across the current channel. **/
152
int16_t wl_send_global(uint8_t *data, uint8_t length, uint8_t group);
153

  
154
/**@brief Wrapper for core send function that will send a packet across the current channel on the current pan. **/
155
int16_t wl_send_pan(uint8_t *data, uint8_t length, uint8_t group);
156

  
157
/**@brief Wrapper for core send function that will send a packet across the current channel to a specific robot. **/
158
int16_t wl_send_robot(uint8_t *data, uint8_t length, uint8_t group, uint16_t dest, uint8_t mode);
159

  
160
/**@brief Default (i.e. basic) send wrapper. **/
161
int16_t wl_send_basic(uint8_t *data, uint8_t length);
162

  
163

  
164
// the ack function
165

  
166
/**@brief Returns the number of acknowledgment errors. **/
167
uint8_t wl_ack_error(void);
168

  
169
/**@brief Checks a specific packet for the acknowledgement status. **/
170
int8_t wl_ack_check(uint8_t packet);
171

  
172
/**@brief Resets acknowledgement statistics back to zero. **/
173
void wl_ack_reset(void);
174

  
175

  
176
// the receive functions
177

  
178
/**@brief The main receive function.  Dispatches packets for registered handlers and returns next basic packet if available. **/
179
int8_t wl_get(char *data, uint8_t length);
180

  
181
/**@brief Returns the next basic packet if available. **/
182
int8_t wl_get_basic(char *data, uint8_t length);
183

  
184
/**@brief Dispatches packets for registered handlers. **/
185
int8_t wl_dispatch(void);
186

  
187

  
188
// the group register function
189

  
190
/**@brief Function to register new packet handlers (for non-default groups only). **/
191
int8_t wl_register_handler(uint8_t group, FNPTR, uint8_t priority);
192

  
193
/**@brief Function to unregister existing packet handlers (for non-default groups only). **/
194
int8_t wl_unregister_handler(uint8_t group);
195

  
196
/**@} **/ //end functions group
197

  
198
/**@} **/ //end wireless group
199

  
200
#endif
branches/wireless/code/projects/unit_tests/wl_defs.h
1
/**
2
 * Copyright (c) 2009 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 wl_defs.h
28
 * @brief Definitions for Wireless
29
 *
30
 * Contains definitions for wireless, debugging information, etc.
31
 *
32
 * @author Colony Project, CMU Robotics Club
33
 **/
34

  
35
#ifndef WL_DEFS_H
36
#define WL_DEFS_H
37

  
38
// create main wireless page documentation
39

  
40
/** @mainpage The Wireless Library
41
 * 
42
 * This is the documentation for the Colony wireless library.\n\n
43
 * Xbee documentation can be found under @ref xbee \n
44
 * Higher level wireless documentation can be found under @ref wireless \n
45
 **/
46

  
47

  
48
// need this for C99 int types
49
#ifndef STDINT_H
50
#define STDINT_H
51
#include <stdint.h>
52
#endif
53

  
54
// ***** TODO: these next two defines should be moved to makefile options
55

  
56
//comment out this line if using a computer hooked up to an xbee
57
#define ROBOT
58

  
59
//uncomment this line for debug information
60
#define WL_DEBUG
61

  
62
/**@addtogroup wireless 
63
 * @{ **/
64
 
65
/**@defgroup wl_error Error Codes
66
 * @{ **/
67
 
68
/** @brief Success **/
69
#define WL_SUCCESS INT8_C(0)
70

  
71
/** @brief Error code for init failure **/
72
#define WL_ERROR_INIT_FAILED INT8_C(-1) 
73

  
74
/** @brief Error code for duplicate init calls **/
75
#define WL_ERROR_INIT_ALREADY_INITD INT8_C(-2) 
76

  
77
/** @brief Error code for not calling init **/
78
#define WL_ERROR_LIBRARY_NOT_INITD INT8_C(-3) 
79

  
80
/** @brief Error code for failed termination **/
81
#define WL_ERROR_TERMINATION_FAILED INT8_C(-4)
82

  
83
/** @brief Error code for failed packet group registration **/
84
#define WL_ERROR_FAILED_REGISTRATION INT8_C(-5)
85

  
86
/** @brief Error code for failed packet group registration **/
87
#define WL_ERROR_FAILED_UNREGISTRATION INT8_C(-6)
88

  
89
/** @brief Error in arguments **/
90
#define WL_ERROR_ARGUMENT INT8_C(-7)
91

  
92
/** @brief Error code for send failure **/
93
#define WL_ERROR_SEND INT8_C(-10)
94

  
95
/** @brief Error code for a bad group number **/
96
#define WL_ERROR_BAD_GROUP INT8_C(-11)
97

  
98
/** @brief Error code for a bad scope **/
99
#define WL_ERROR_SCOPE INT8_C(-12)
100

  
101
/** @brief Error code for a bad robot address **/
102
#define WL_ERROR_ADDRESS INT8_C(-13)
103

  
104
/** @brief Error code for a bad mode **/
105
#define WL_ERROR_MODE INT8_C(-14)
106

  
107
/** @brief Error code for received paacket destination too small for received packet **/
108
#define WL_ERROR_TOO_SMALL INT8_C(-15)
109

  
110
/** @brief Error code for sending buffer full (the packet was sent, but no retries will be made). **/
111
#define WL_ERROR_SENDING_BUFFER_FULL INT8_C(-16)
112

  
113
/** @brief Error code for failed xbee command **/
114
#define WL_ERROR_XBEE_COMMAND INT8_C(-17)
115

  
116
/** @brief Error code for failed 16bit xbee command **/
117
#define WL_ERROR_XBEE_COMMAND_16BIT 0xFEFE
118

  
119
/** @brief Error code for bad baud rate **/
120
#define WL_ERROR_BAUD INT8_C(-18)
121

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

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

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

  
130
#ifdef WL_DEBUG
131

  
132
#ifdef ROBOT
133
#include <serial.h>
134
#define WL_DEBUG_PRINT( s ) usb_puts( s )
135
#define WL_DEBUG_PRINT_CHAR( c ) usb_putc( c )
136
#define WL_DEBUG_PRINT_INT( i ) usb_puti(i)
137
#define WL_DEBUG_PRINT_HEX( i ) usb_puth8(i)
138
#else
139
#define WL_DEBUG_PRINT( s ) printf( s )
140
#define WL_DEBUG_PRINT_CHAR( c ) printf("%c", c)
141
#define WL_DEBUG_PRINT_INT( i ) printf("%i", i)
142
#define WL_DEBUG_PRINT_HEX( i ) printf("%x", i)
143
#endif
144

  
145
#else
146

  
147
#define WL_DEBUG_PRINT( s )
148
#define WL_DEBUG_PRINT_CHAR( c )
149
#define WL_DEBUG_PRINT_INT( i )
150
#define WL_DEBUG_PRINT_HEX( i )
151

  
152
#endif
153

  
154
#endif
branches/wireless/code/projects/unit_tests/xbee.c
1
/**
2
 * Copyright (c) 2009 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 Colony Project, CMU Robotics Club
33
 **/
34
#include <lights.h>
35

  
36
#include <string.h>
37
#include <avr/io.h>
38
#include <avr/interrupt.h>
39
#include <time.h>
40
#include <wl_defs.h>
41
#include <wireless.h>
42
#include "xbee.h"
43

  
44

  
45
/* Internal Function Prototypes */
46

  
47
/* I/O Functions */
48
static int8_t xbee_send_string(uint8_t* c);
49

  
50
/* Command Mode Functions */
51
static int8_t xbee_enter_command_mode(void);
52
static int8_t xbee_exit_command_mode(void);
53
static int8_t xbee_enter_api_mode(void);
54
static int8_t xbee_exit_api_mode(void);
55
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len);
56
static int8_t xbee_wait_for_ok(void);
57

  
58
/* API Mode Functions */
59
//TODO: does this exist?  static int8_t xbee_handle_packet(uint8_t* packet, uint16_t len);
60
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t status, uint8_t len);
61
static void xbee_handle_status(uint8_t status);
62
static int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len);
63
static uint8_t xbee_compute_checksum(uint8_t* packet, uint16_t len);
64
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len);
65
int8_t xbee_send_read_at_command(uint8_t* command);
66
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len);
67

  
68
/* Buffer Manipulation Functions */
69
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte);
70
uint8_t xbee_basic_buf_get(uint8_t *ptr);
71
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte);
72

  
73
/* private functions */
74
int8_t check_last_receive(uint16_t source,uint8_t framenum);
75
inline uint8_t getStatus(uint8_t mask);
76
inline void setStatus(uint8_t mask,uint8_t value);
77

  
78
/*Global Variables*/
79

  
80
// last few packet sources and frame nums
81
#define NUM_LAST_PACKETS 10
82
struct {
83
  uint16_t source;
84
  uint8_t framenum;
85
} lastPacket[NUM_LAST_PACKETS];
86

  
87
// array for basic packets
88
static uint8_t xbee_basic_buf[PACKET_BUFFER_SIZE];
89

  
90
// beginning of first packet in basic buffer
91
static uint8_t basic_buf_first = 0xFF;
92

  
93
// byte after end of last packet in basic buffer (only access < basic_buf_last)
94
// aka, the first free byte in basic buffer
95
static uint8_t basic_buf_last = 0;
96

  
97
// array for other packets
98
static uint8_t xbee_other_buf[PACKET_BUFFER_SIZE];
99

  
100
// beginning of first packet in other buffer
101
static uint8_t other_buf_first = 0xFF;
102

  
103
// byte after end of last packet in other buffer (only access < other_buf_last)
104
// aka, the first free byte in other buffer
105
static uint8_t other_buf_last = 0;
106

  
107
// xbee status
108
#define XBEE_API_OFF 0x00
109
#define XBEE_API_ON 0x10
110
#define XBEE_API_ESCAPE 0x20
111
#define XBEE_API_MASK 0x30
112
#define XBEE_COMMAND_WAIT 0x80
113
#define XBEE_COMMAND_RESPONSE 0xC0
114
#define XBEE_COMMAND_NONE 0x00
115
#define XBEE_COMMAND_MASK 0xC0
116
#define XBEE_NOT_INITD 0xF0
117
#define LAST_PACKET_MASK 0x0F
118
uint8_t xbee_status = XBEE_NOT_INITD;
119

  
120
// xbee command response (for PAN, channel, address, etc)
121
static uint8_t xbee_command[8];
122

  
123
// external ack handler (wireless_send.c)
124
void ackhandle(uint8_t num,uint8_t val) { return; } // disabled
125

  
126
// message buffer
127
uint8_t message[100];
128

  
129

  
130
/**@addtogroup xbee
131
 * @{ **/
132

  
133
/*Function Implementations*/
134

  
135
/**
136
 * Interrupt for the robot. Adds bytes received from the xbee
137
 * to the buffer.
138
 **/
139
 
140
 
141
#ifndef FIREFLY
142
#define PORT UDR1
143
#define FLAG (UCSR1A & (1<<RXC1))
144
ISR(USART1_RX_vect) {
145
#else
146
#define PORT UDR0
147
#define FLAG (UCSR0A & (1<<RXC0))
148
SIGNAL(SIG_USART0_RECV)
149
#endif
150
  // start of frame
151
  uint8_t apitype = PORT; // get frame start byte
152
  uint16_t i=0;
153
  uint16_t len=0;
154
  
155
  /*WL_DEBUG_PRINT("in interrupt|status=");
156
  WL_DEBUG_PRINT_HEX(xbee_status);
157
  WL_DEBUG_PRINT("|frame_start=");
158
  WL_DEBUG_PRINT_HEX(apitype);
159
  
160
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
161
    WL_DEBUG_PRINT("|API OFF");
162
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
163
    WL_DEBUG_PRINT("|API ON");
164
  } else {
165
    WL_DEBUG_PRINT("|API ERROR");
166
  }*/
167
  
168
  // check that we're in API mode
169
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF || apitype != XBEE_FRAME_START) {
170
    // not in API mode
171
    WL_DEBUG_PRINT("|api off branch");
172
    
173
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT) {
174
      // get rest of command and put in basic buf
175
      xbee_basic_buf[i] = apitype;
176
      if (xbee_basic_buf[i++] != '\r') {
177
        while(i < PACKET_BUFFER_SIZE) {
178
          if (FLAG) {
179
            xbee_basic_buf[i] = PORT;
180
            if (xbee_basic_buf[i] == '\r')
181
              break;
182
            i++;
183
          }
184
        }
185
      }
186
      WL_DEBUG_PRINT("got packet, len=");
187
      WL_DEBUG_PRINT_INT(i);
188
      WL_DEBUG_PRINT("str=");
189
      WL_DEBUG_PRINT(xbee_basic_buf);
190
      // signal handler that command response is done
191
      setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
192
    }
193
    WL_DEBUG_PRINT("return\r\n");
194
    return;
195
  }  
196
  //WL_DEBUG_PRINT("|api on branch");
197
    
198
  // get length and type
199
  char buf[100];
200
  uint8_t buf_pos = 18;
201
  while(i<3) {
202
    if (FLAG) {
203
      if (i==0) {
204
        len |= PORT<<8;
205
        buf[0] = 'l';
206
        buf[1] = 'e';
207
        buf[2] = 'n';
208
        buf[3] = '_';
209
        buf[4] = 'h';
210
        buf[5] = 'i';
211
        buf[6] = '|';
212
        //WL_DEBUG_PRINT("|len_hi");        
213
      } else if (i==1) {
214
        len |= PORT;
215
        buf[7] = 'l';
216
        buf[8] = 'e';
217
        buf[9] = 'n';
218
        buf[10] = '_';
219
        buf[11] = 'l';
220
        buf[12] = 'o';
221
        buf[13] = '|';
222
        //WL_DEBUG_PRINT("|len_lo");
223
      } else if (i==2) {      
224
        apitype = PORT;
225
        buf[14] = 'a';
226
        buf[15] = 'p';
227
        buf[16] = 'i';
228
        buf[17] = '|';
229
        //WL_DEBUG_PRINT("|GOT APITYPE");
230
      } else {
231
        buf[buf_pos++] = PORT;
232
        //WL_DEBUG_PRINT("|GOT NEXT");
233
      }
234
      i++;
235
    }
236
  }
237
  
238
  // do something based on the type
239
  i=1;
240
  switch(apitype) {
241
  case XBEE_FRAME_AT_COMMAND_RESPONSE: {
242
    // AT command response
243
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
244
      return; // we're currently processing a command, so drop the incoming one  ***** TODO: we need to read the whole length of the frame to do this right ****
245
    uint16_t atcommand=0;
246
    uint8_t ptr=basic_buf_last;
247
    while(i<len) {
248
      if (FLAG) {
249
        if (i==1)
250
          apitype = PORT; // get frame id, but ignore it
251
        else if (i==2)
252
          atcommand |= PORT<<8; // get command char1
253
        else if (i==3)
254
          atcommand |= PORT; // get command char2
255
        else if (i==4)
256
          apitype = PORT; // get status
257
        else {
258
          // put the command response on the basic buf temporarily
259
          if (xbee_basic_buf_add(&ptr,PORT) != 0)
260
            break;
261
        }
262
        i++;
263
      }
264
    }
265
    // handle AT command
266
    WL_DEBUG_PRINT("i=");
267
    WL_DEBUG_PRINT_INT(i);
268
    WL_DEBUG_PRINT("|len=");
269
    WL_DEBUG_PRINT_INT(len);
270
    WL_DEBUG_PRINT("|status:");
271
    WL_DEBUG_PRINT_INT(apitype);
272
    WL_DEBUG_PRINT("|atcommand:");
273
    WL_DEBUG_PRINT_CHAR((uint8_t)(atcommand>>8));
274
    WL_DEBUG_PRINT_CHAR((uint8_t)(atcommand&0xFF));
275
    WL_DEBUG_PRINT("|buf=");
276
    uint8_t ptr2 = basic_buf_last;
277
    for(uint8_t j=0;j<i;j++)
278
      WL_DEBUG_PRINT_HEX(xbee_basic_buf_get(&ptr2));
279
    WL_DEBUG_PRINT("|\r\n");
280
    xbee_handle_at_command_response(atcommand,apitype,len-5); // TODO: rewrite function
281
    break; }
282
  case XBEE_FRAME_TX_STATUS: {
283
    // TX status
284
    uint8_t frame_id = 0;
285
    while(i<len) {
286
      if (FLAG) {
287
        if (i==1)
288
          frame_id = PORT;
289
        else {
290
          ackhandle(frame_id,PORT); // handle the status
291
          break;
292
        }
293
        i++;
294
      }
295
    }
296
    break; }
297
  case XBEE_FRAME_RX_64: {
298
    // receive a packet with 64bit address
299
    break; } // TODO: implement this (even if we don't use it)
300
  case XBEE_FRAME_RX_16: {
301
    // receive a packet with 16bit address
302
    uint16_t source = 0;
303
    uint8_t framenum = 0;
304
    uint8_t group = 0;
305
    uint8_t ptr=basic_buf_last;
306
    while(i<len) {
307
      if (FLAG) {
308
        if (i==1)
309
          source |= PORT<<8; // get source hi byte
310
        else if (i==2)
311
          source |= PORT; // get source lo byte
312
        else if (i==3)
313
          apitype = PORT; // get RSSI, and ignore
314
        else if (i==4)
315
          apitype = PORT; // get options, and ignore
316
        else if (i==5) {
317
          framenum = PORT; // get the frame number
318
          if (check_last_receive(source,framenum) != WL_SUCCESS) {
319
            // we've already received this frame
320
            ptr = 0xFF; // signal to skip processing
321
            break;
322
          }
323
        }
324
        else if (i==6) {
325
          group = PORT; // get group number
326
          if (group == 0) {
327
            ptr = basic_buf_last+1;
328
            // add source to buffer
329
            if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
330
              break;
331
            if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
332
              break;
333
          } else {
334
            ptr = other_buf_last+1;
335
            // add source and group to buffer
336
            if (xbee_other_buf_add(&ptr,group) != 0)
337
              break;
338
            if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
339
              break;
340
            if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
341
              break;
342
          }
343
        }
344
        else { // TODO: handle escaped characters supported by APIv2
345
          // put packet data on the correct buffer
346
          if (group == 0 && xbee_basic_buf_add(&ptr,PORT) != 0)
347
            break;
348
          else if (xbee_other_buf_add(&ptr,PORT) != 0)
349
            break;
350
        }
351
        i++;
352
      }
353
    }
354
    if (ptr != 0xFF && i > 6) {
355
      if (group == 0) {
356
        xbee_basic_buf[basic_buf_last] = i-6; // set length
357
        basic_buf_last = ptr;
358
      }
359
      else {        
360
        xbee_other_buf[other_buf_last] = i-6; // set length
361
        // check if we have a high priority group
362
        for(;;)
363
          if (HIGH_PRIORITY) {
364
            // handle receive now
365
            ptr = 0xFF;
366
            break;
367
          }        
368
        if (ptr != 0xFF) {
369
          // handle receive later
370
          other_buf_last = ptr;
371
        }
372
      }
373
    }
374
    break; }
375
    default:
376
      WL_DEBUG_PRINT("|BAD APITYPE");
377
  } // end of switch statement
378
  while (1) {
379
    if (FLAG) {
380
      apitype = PORT; // get checksum, and ignore
381
      break;
382
    }
383
  }
384
  buf[buf_pos] = '\0';
385
  WL_DEBUG_PRINT("xbee_interrupt_api_mode|");
386
  WL_DEBUG_PRINT(buf);
387
  WL_DEBUG_PRINT("|len=");
388
  WL_DEBUG_PRINT_INT(len);
389
  WL_DEBUG_PRINT("|apitype=");
390
  WL_DEBUG_PRINT_HEX(apitype);
391
  WL_DEBUG_PRINT("|return\r\n");
392
} // end of interrupt 
393

  
394

  
395
/* adds a byte to the basic buffer */
396
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
397
  if (*ptr == basic_buf_first) {
398
    // buffer full
399
    WL_DEBUG_PRINT("basic buffer full\r\n");
400
    return -1;
401
  }
402
  xbee_basic_buf[(*ptr)++] = byte;
403
  if (*ptr == PACKET_BUFFER_SIZE)
404
    *ptr = 0;
405
  return 0;
406
}
407
/* gets a byte from the basic buffer */
408
uint8_t xbee_basic_buf_get(uint8_t *ptr) {
409
  uint8_t byte = xbee_basic_buf[(*ptr)++];
410
  if (*ptr == PACKET_BUFFER_SIZE)
411
    *ptr = 0;
412
  return byte;
413
}
414
/* adds a byte to the other buffer */
415
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) {
416
  if (*ptr == other_buf_first) {
417
    // buffer full
418
    WL_DEBUG_PRINT("other buffer full\r\n");
419
    return -1;
420
  }
421
  xbee_other_buf[(*ptr)++] = byte;
422
  if (*ptr == PACKET_BUFFER_SIZE)
423
    *ptr = 0;
424
  return 0;
425
}
426

  
427
/**
428
 * Checks if packet is a duplicate
429
 **/
430
int8_t check_last_receive(uint16_t source,uint8_t framenum) {
431
  uint8_t i=0;
432
  for(;i<NUM_LAST_PACKETS;i++) {
433
    if (lastPacket[i].source == source && lastPacket[i].framenum == framenum)
434
      return -1; // duplicate packet, so return error
435
  }
436
  // save packet source and framenum
437
  i=getStatus(LAST_PACKET_MASK);
438
  lastPacket[i].source = source;
439
  lastPacket[i].framenum = framenum;
440
  if (++i>=NUM_LAST_PACKETS)
441
    i = 0;
442
  setStatus(LAST_PACKET_MASK,i);
443
  return WL_SUCCESS;
444
}
445

  
446
/** status functions **/
447
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
448
void setStatus(uint8_t mask,uint8_t value) { xbee_status = ((xbee_status&(~mask))|value); }
449

  
450

  
451
// test interrupt
452
/*ISR(USART1_RX_vect) {
453
  WL_DEBUG_PRINT("in interrupt|");
454
  char c = UDR1;
455
  WL_DEBUG_PRINT_HEX(c);
456
  WL_DEBUG_PRINT("|in interrupt");
457
}*/
458

  
459

  
460

  
461
/**
462
 * Initializes the XBee library so that other functions may be used.
463
 **/
464
int8_t xbee_init()
465
{
466
  WL_DEBUG_PRINT("in xbee_init\r\n");
467
  
468
  if(getStatus(XBEE_NOT_INITD) != XBEE_NOT_INITD) {
469
    return WL_ERROR_INIT_ALREADY_INITD;
470
  }
471
  
472
  // set status
473
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
474
  
475
  // clear last packet buffer
476
  for(int i=0;i<NUM_LAST_PACKETS;i++)
477
    lastPacket[i].source = lastPacket[i].framenum = 0;
478
  
479
  // Set startup baud rate of 9600
480
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
481
  // Enable receiver and transmitter and the receiving interrupt
482
#ifdef FIREFLY
483
  UBRR0H = 0x00;
484
  UBRR0L = 103;
485
  UCSR0A |= (1<<U2X0);
486
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
487
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE); 
488
#else
489
  // Bayboard or robot  
490
  UBRR1H = 0x00; // baud rate
491
  UBRR1L = 103;  // baud rate
492
  UCSR1A |= (1<<U2X1); // double transmit speed 
493
  //Enable receiver and transmitter on USART1
494
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
495
	
496
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
497
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
498
  
499
  UCSR1B |= (1<<RXCIE1);  // enable receive, transmit (1<<RXCIE)
500
#endif
501
  sei();
502
 
503
  // enter command mode
504
  WL_DEBUG_PRINT("entering command mode\r\n");
505
  xbee_send_string((uint8_t*)"+++");
506
  xbee_wait_for_ok();
507
  WL_DEBUG_PRINT("entered command mode\r\n");
508

  
509
  
510
  // set baud on xbee
511
#if (XBEE_BAUD == 115200)
512
  xbee_send_string((uint8_t*)"ATBD7\r");
513
#elif (XBEE_BAUD == 57600)
514
  xbee_send_string((uint8_t*)"ATBD6\r");
515
#elif (XBEE_BAUD == 38400)
516
  xbee_send_string((uint8_t*)"ATBD5\r");
517
#elif (XBEE_BAUD == 19200)
518
  xbee_send_string((uint8_t*)"ATBD4\r");
519
#elif (XBEE_BAUD == 9600)
520
  // already at this baud rate
521
  xbee_send_string("ATBD3\r\n");
522
#else
523
  WL_DEBUG_PRINT("undefined baud rate\r\n");
524
  return WL_ERROR_BAUD;
525
#endif  
526
  // exit command mode
527
  xbee_wait_for_ok();
528
  WL_DEBUG_PRINT("got ok from baud reset\r\n");
529
  xbee_send_string((uint8_t*)"ATCN\r");
530
  xbee_wait_for_ok();
531
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
532
  
533
  // set UART baud
534
#ifdef FIREFLY
535
#if (XBEE_BAUD == 115200)
536
  UBRR0H = 0x00;
537
  UBRR0L = 8;
538
#elif (XBEE_BAUD == 57600)
539
  UBRR0H = 0x00;
540
  UBRR0L = 16;
541
#elif (XBEE_BAUD == 38400)
542
  UBRR0H = 0x00;
543
  UBRR0L = 25;
544
#elif (XBEE_BAUD == 19200)
545
  UBRR0H = 0x00;
546
  UBRR0L = 51;
547
#elif (XBEE_BAUD == 9600)
548
  /* this is the default baud rate, so do nothing
549
  UBRR0H = 0x00;
550
  UBRR0L = 103;*/
551
#else
552
  WL_DEBUG_PRINT("undefined baud rate\r\n");
553
  return WL_ERROR_BUAD;
554
#endif
555
#else // Bayboard or robot
556
#if (XBEE_BAUD == 115200)
557
  UBRR1H = 0x00;
558
  UBRR1L = 8;
559
#elif (XBEE_BAUD == 57600)
560
  UBRR1H = 0x00;
561
  UBRR1L = 16;
562
#elif (XBEE_BAUD == 38400)
563
  UBRR1H = 0x00;
564
  UBRR1L = 25;
565
#elif (XBEE_BAUD == 19200)
566
  UBRR1H = 0x00;
567
  UBRR1L = 51;
568
#elif (XBEE_BAUD == 9600)
569
  /* this is the default baud rate, so do nothing
570
  UBRR1H = 0x00;
571
  UBRR1L = 103;*/
572
#else
573
  WL_DEBUG_PRINT("undefined baud rate\r\n");
574
  return WL_ERROR_BUAD;
575
#endif
576
#endif
577
  // wait half second for the baud change to stabalize
578
  delay_ms(500);
579

  
580
  // enter command mode
581
  WL_DEBUG_PRINT("entering command mode 2\r\n");
582
  xbee_send_string((uint8_t*)"+++");
583
  xbee_wait_for_ok();
584
  WL_DEBUG_PRINT("entered command mode 2\r\n");
585
  
586
  if (xbee_enter_api_mode() != 0) {
587
    WL_DEBUG_PRINT("can't enter api mode\r\n");
588
    return -1;
589
  }
590
  /*xbee_send_string((uint8_t*)"ATAP 1\r");
591
  xbee_wait_for_ok();*/
592
  
593
  /*WL_DEBUG_PRINT("Entered api mode.\r\n");
594

  
595
  if (xbee_exit_command_mode() != 0) {
596
    WL_DEBUG_PRINT("can't exit command mode\r\n");
597
    return -1;
598
  }
599
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
600
  
601
  WL_DEBUG_PRINT("Left command mode.\r\n");
602
  
603
  WL_DEBUG_PRINT("before status=");
604
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
605
  WL_DEBUG_PRINT("\r\n");
606
  
607
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status to API_ON (API mode 1)*/
608
  
609
#ifdef WL_DEBUG
610
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
611
    WL_DEBUG_PRINT("|API OFF|");
612
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
613
    WL_DEBUG_PRINT("|API ON|");
614
  } else {
615
    WL_DEBUG_PRINT("|API ERROR|");
616
  }
617
#endif
618
  
619
  
620
  // TODO: we should set the MY address to the robot address from eeprom  
621
  uint16_t i=0;
622
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);  
623
  uint16_t newmy = 0x9876;
624
  if (xbee_send_modify_at_command((uint8_t*)"MY",&newmy,2) != WL_SUCCESS) {
625
    WL_DEBUG_PRINT("setting MY address failed\r\n");
626
  }
627
  // wait for up to 30 ms
628
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
629
    delay_us(1); // wait 3us
630
  }  
631
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
632
    WL_DEBUG_PRINT("setting MY address successful\r\n");
633
  } else
634
    WL_DEBUG_PRINT("setting MY address failed\r\n");
635
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
636
  
637
  
638
  uint16_t address = xbee_get_address();
639
  if (address == WL_ERROR_XBEE_COMMAND_16BIT) {
640
    WL_DEBUG_PRINT("getting MY address failed\r\n");
641
  }
642
  WL_DEBUG_PRINT("MY address:");
643
  WL_DEBUG_PRINT_HEX((uint8_t)(address>>8));
644
  WL_DEBUG_PRINT_HEX((uint8_t)(address&0xFF));
645
  WL_DEBUG_PRINT("\r\n");
646
  
647
  return WL_SUCCESS;
648
}
649

  
650
/**
651
 * Call when finished using the XBee library.
652
 **/
653
int8_t xbee_terminate()
654
{
655
  int ret=xbee_exit_api_mode();
656
  if (ret != WL_SUCCESS) {
657
    WL_DEBUG_PRINT("xbee termination failed\r\n");
658
    WL_DEBUG_PRINT_INT(ret);
659
    WL_DEBUG_PRINT("|\r\n");
660
    return WL_ERROR_TERMINATION_FAILED;
661
  }
662
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
663
  return WL_SUCCESS;
664
}
665

  
666
/**
667
 * Sends a character to the XBee.
668
 *
669
 * @param c the byte to send
670
 * @return 0 for success, nonzero for failure
671
 **/
672
int8_t xbee_putc(uint8_t c) {
673

  
674
  // Wait until buffer is clear for sending
675
  // Then load buffer with your character
676
  
677
  /*WL_DEBUG_PRINT("xbee_putc:");
678
  WL_DEBUG_PRINT_HEX(c);
679
  WL_DEBUG_PRINT("|\r\n");*/
680
  
681
#ifdef FIREFLY
682
  loop_until_bit_is_set(UCSR0A, UDRE0);  
683
  UDR0 = c;
684
#else
685
  loop_until_bit_is_set(UCSR1A, UDRE1);
686
  UDR1 = c;
687
#endif
688
  
689
  return WL_SUCCESS;
690
}
691

  
692
/**
693
 * Returns the first byte in the buffer received from xbee.
694
 * This function blocks execution until a character has been
695
 * received. xbee_init must be called before this function
696
 * may be used.
697
 * 
698
 * @return the first character in the xbee buffer, -1 on error
699
 * 
700
 * @see xbee_init, xbee_getc_nb
701
 **/
702
int16_t xbee_getc(void) {
703
    
704
  // Wait for the receive buffer to be filled
705
  // Then read the receive buffer
706
#ifdef FIREFLY
707
  loop_until_bit_is_set(UCSR0A, RXC0);  
708
  return UDR0;
709
#else
710
  loop_until_bit_is_set(UCSR1A, RXC1);
711
  return UDR1;
712
#endif
713
}
714

  
715
/**
716
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
717
 * it is returned, otherwise -1 is returned immediately. xbee_init
718
 * must be called before this function can be used.
719
 *
720
 * @param c The received byte. This will be set if a byte has been received.
721
 * 
722
 * @return -1 If no byte is available, 0 otherwise, positive for error
723
 *
724
 * @see xbee_getc
725
 **/
726
int8_t xbee_getc_nb(uint8_t *c) {
727

  
728
  // check if the receive buffer is filled
729
#ifdef FIREFLY
730
  if (UCSR0A & (1<<RXC0)) {
731
    (*c) = UDR0;
732
#else
733
  if (UCSR1A & (1<<RXC1)) {
734
    (*c) = UDR1;
735
#endif
736
    return WL_SUCCESS;
737
  }
738
  return -1; // Return empty
739
}
740

  
741
/**
742
 * Send a buffer buf of size bytes to the XBee.
743
 *
744
 * @param buf the buffer of data to send
745
 * @param size the number of bytes to send
746
 **/
747
int8_t xbee_send(uint8_t* buf, uint16_t size)
748
{
749
  uint16_t i=0; // check if we need this variable
750
  while(i<size) {
751
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
752
      return WL_ERROR_SEND;
753
  }
754

  
755
  return WL_SUCCESS;
756
}
757

  
758
/**
759
 * Sends a string to the XBee.
760
 *
761
 * @param c the string to send to the XBEE
762
 **/
763
static int8_t xbee_send_string(uint8_t* c)
764
{
765
  return xbee_send(c, strlen((char*)c));
766
}
767

  
768

  
769
/**
770
 * Enter into command mode.
771
 **/
772
static int8_t xbee_enter_command_mode(void)
773
{
774
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
775
    return WL_ERROR_XBEE_COMMAND;
776
  }
777
  WL_DEBUG_PRINT("sent command +++|");
778

  
779
  if (xbee_wait_for_ok() != WL_SUCCESS) {
780
    return WL_ERROR_XBEE_COMMAND;
781
  }
782
  WL_DEBUG_PRINT("got OK\r\n");
783
  
784
  return WL_SUCCESS;
785
}
786

  
787
/**
788
 * Exit from command mode.
789
 **/
790
static int8_t xbee_exit_command_mode()
791
{
792
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
793
    return WL_ERROR_SEND;
794
  }
795
  if (xbee_wait_for_ok() != WL_SUCCESS) {
796
    WL_DEBUG_PRINT("failed to exit command mode\r\n");
797
    return WL_ERROR_SEND;
798
  }
799

  
800
  return WL_SUCCESS;
801
}
802

  
803
/**
804
 * Enter API mode.
805
 **/
806
static int8_t xbee_enter_api_mode(void) {
807
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
808
    return WL_ERROR_SEND;
809
  }
810
  if (xbee_wait_for_ok() != WL_SUCCESS) {
811
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
812
    return WL_ERROR_SEND;
813
  }
814
  if (xbee_exit_command_mode() != WL_SUCCESS) {
815
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
816
    return WL_ERROR_SEND;
817
  }    
818
  WL_DEBUG_PRINT("got OK after entering API mode\r\n");
819
  
820
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
821
  
822
  return WL_SUCCESS;
823
}
824

  
825
/**
826
 * Enter API mode 2.
827
 **/
828
static int8_t xbee_enter_api_mode2(void) {
829
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
830
    return WL_ERROR_SEND;
831
  }
832
  if (xbee_wait_for_ok() != WL_SUCCESS) {
833
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
834
    return WL_ERROR_SEND;
835
  }
836
  if (xbee_exit_command_mode() != WL_SUCCESS) {
837
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
838
    return WL_ERROR_SEND;
839
  }    
840
  WL_DEBUG_PRINT("got OK after entering API mode2\r\n");
841
  
842
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
843
  
844
  return WL_SUCCESS;
845
}
846

  
847
/**
848
 * Exit API mode.
849
 **/
850
static int8_t xbee_exit_api_mode()
851
{
852
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
853
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
854
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
855
  WL_DEBUG_PRINT("now exiting API mode\r\n");
856
  
857
  int16_t i=0;
858
  // change status to command wait
859
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
860
  if (xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)(&i),1) != WL_SUCCESS) { // send command
861
    WL_DEBUG_PRINT("error sending AP 0 command\r\n");
862
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
863
    return WL_ERROR_XBEE_COMMAND;
864
  }
865
  // wait for up to 30 ms
866
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
867
    delay_us(1); // wait 3us
868
  }
869
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
870
    WL_DEBUG_PRINT("done exiting API mode\r\n");
871
    i = WL_SUCCESS;
872
  } else {
873
    WL_DEBUG_PRINT("failed to exit API mode\r\n");
874
    i = WL_ERROR_XBEE_COMMAND; // set error code
875
  }
876
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
877
  setStatus(XBEE_API_MASK,XBEE_API_OFF);
878
  
879
  return (int8_t)i; // return
880
}
881

  
882
/**
883
 * Wait until the string "OK\r" is received from the XBee.
884
 **/
885
static int8_t xbee_wait_for_ok()
886
{
887
  //delay_ms(1000);
888
  //return WL_SUCCESS;
889
  return xbee_wait_for_string((uint8_t*)"OK", 2);
890
}
891

  
892
/**
893
 * Delay until the specified string is received from
894
 * the XBee.
895
 *
896
 * Only works when not in API mode
897
 *
898
 * @param s the string to receive
899
 * @param len the length of the string
900
 **/
901
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
902
{
903
  uint8_t i=0;  
904
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); // set status flag
905
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
906
    // wait until the response is received (only wait 1 second)
907
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
908
      delay_us(1);
909
    }
910
    // check response
911
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
912
      // bad response
913
      WL_DEBUG_PRINT("Bad response when waiting for string ");
914
      WL_DEBUG_PRINT(s);
915
      WL_DEBUG_PRINT("\r\n");
916
      return -1;
917
    }
918
    
919
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
920
  }
921
  
922
  WL_DEBUG_PRINT("done waiting for string.\r\n");
923

  
924
  return 0;
925
}
926

  
927
/**
928
 * Delay until we receive a command response.
929
 * Then copy the response to S and set the len
930
 *
931
 * Only works when not in API mode
932
 *
933
 * @param s the string to store the response in
934
 * @param len the length of the string
935
 */
936
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
937
  uint8_t i=0;
938
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
939
    // wait until the response is received (only wait 1 second)
940
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
941
      delay_us(1);
942
    }
943
    // check response
944
    if (i >= 1000) {
945
      return -1;
946
    } else {
947
      i=strcspn((char*)xbee_basic_buf,"\r");
948
      if (i<PACKET_BUFFER_SIZE) {
949
        memcpy(s,xbee_basic_buf,i);
950
        len = i;
951
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
952
        return 0;
953
      }
954
      else
955
        return -1;      
956
    }
957
  }
958
  // TODO: do something for API mode
959
  
960
  return 0;
961
}
962

  
963
/**  TODO: since we don't use this, do we need it?
964
 *
965
 * Verifies that the packets checksum is correct.
966
 * (If the checksum is correct, the sum of the bytes
967
 * is 0xFF.)
968
 *
969
 * @param packet the packet received. This includes the first
970
 * three bytes, which are header information from the XBee.
971
 *
972
 * @param len The length of the packet received from the XBee
973
 *
974
 * @return 0 if the checksum is incorrect, nonzero
975
 * otherwise
976
 **/
977
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
978
{
979
  uint8_t sum = 0;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff