Project

General

Profile

Revision 18

Added wireless library to lib directory.

View differences:

trunk/code/lib/include/libwireless/sensor_matrix.h
1
/**
2
 * @file sensor_matrix.h
3
 * @brief Definitions for sensor matrices
4
 *
5
 * Contains functions and declarations for using sensor matrices.
6
 *
7
 * @author Brian Coltin, Colony Project, CMU Robotics Club
8
 **/
9

  
10
/**
11
 * @defgroup sensormatrix Sensor Matrix
12
 * @brief the robot sensor matrix
13
 *
14
 * These functions and structures are used for localization
15
 * to determine the relative directions of robots.
16
 *
17
 * @{
18
 **/
19

  
20
/**
21
 * @struct SensorMatrix
22
 *
23
 * A sensor matrix.
24
 **/
25
typedef struct
26
{
27
	/**
28
	 * The size of the sensor matrix.
29
	**/
30
	unsigned int size;
31
	/**
32
	 * The matrix. Each row represents the readings of one
33
	 * robot.
34
	 **/
35
	int** matrix;
36
	/**
37
	 * The element representing a robot is true if that robot
38
	 * is in the token ring and false otherwise.
39
	 **/
40
	int* joined;
41
	/**
42
	 * The number of robots in the token ring.
43
	 **/
44
	int numJoined;
45
} SensorMatrix;
46

  
47
/**@brief Create a sensor matrix **/
48
SensorMatrix* sensor_matrix_create(void);
49
/**@brief Destroy a sensor matrix **/
50
void sensor_matrix_destroy(SensorMatrix* m);
51
/**@brief Add a robot to a sensor matrix **/
52
void sensor_matrix_add_robot(SensorMatrix* m, unsigned int id);
53
/**@brief Remove a robot from a sensor matrix **/
54
void sensor_matrix_remove_robot(SensorMatrix* m, unsigned int id);
55
/**@brief Set a reading in a sensor matrix **/
56
void sensor_matrix_set_reading(SensorMatrix* m, int observer, int robot, int reading);
57
/**@brief Get a reading in a sensor matrix **/
58
int sensor_matrix_get_reading(SensorMatrix* m, int observer, int robot);
59
/**@brief Set whether the robot is in the token ring **/
60
void sensor_matrix_set_in_ring(SensorMatrix* m, int robot, int in);
61
/**@brief Get whether the robot is in the sensor ring **/
62
int sensor_matrix_get_in_ring(SensorMatrix* m, int robot);
63
/**@brief Get the size of the sensor matrix **/
64
int sensor_matrix_get_size(SensorMatrix* m);
65
/**@brief Get the number of robots which have joined the token ring **/
66
int sensor_matrix_get_joined(SensorMatrix* m);
67

  
68
/** @} **/ //end defgroup
69

  
trunk/code/lib/include/libwireless/wireless.h
1
/**
2
 * @file wireless.h
3
 * @brief Contains definitions for the wireless library.
4
 *
5
 * Contains functions for the wireless library.
6
 *
7
 * @author Brian Coltin, Colony Project, CMU Robotics Club
8
 **/
9
 
10
//Note: If this is raised above 16, we will need to do
11
//something about frame numbers for TX Status packets.
12
/**
13
 * The maximum number of packet groups.
14
 **/
15
#define WL_MAX_PACKET_GROUPS 16
16
/**
17
 * The default PAN.
18
 **/
19
#define WL_DEFAULT_PAN 0x3331
20

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

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

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

  
96
/**@brief Initialize the wireless library **/
97
void wl_init(void);
98
/**@brief Uninitialize the wireless library **/
99
void wl_terminate(void);
100
/**@brief Perform wireless library functionality **/
101
void wl_do(void);
102
/**@brief Register a packet group with the wireless library **/
103
void wl_register_packet_group(PacketGroupHandler* h);
104
/**@brief Unregister a packet group with the wireless library **/
105
void wl_unregister_packet_group(PacketGroupHandler* h);
106
/**@brief Send a packet to a specific robot in any PAN **/
107
void wl_send_robot_to_robot_global_packet(char group, char type,
108
		char* data, int len, int dest, char frame);
109
/**@brief Send a packet to a specific robot in our PAN **/
110
void wl_send_robot_to_robot_packet(char group, char type,
111
		char* data, int len, int dest, char frame);
112
/**@brief Send a packet to all robots **/
113
void wl_send_global_packet(char group, char type,
114
		char* data, int len, char frame);
115
/**@brief Send a packet to all robots in our PAN **/
116
void wl_send_pan_packet(char group, char type,
117
		char* data, int len, char frame);
118
/**@brief Get the 16-bit address of the XBee module **/
119
unsigned int wl_get_xbee_id(void);
120

  
121
/** @} **/ // end defgroup
122

  
trunk/code/lib/include/libwireless/wl_token_ring.h
1
/**
2
 * @file wl_token_ring.h
3
 * @brief Declarations for the token ring packet group
4
 * 
5
 * Contains declarations for the token ring packet group.
6
 *
7
 * @author Brian Coltin, Colony Project, CMU Robotics Club
8
 **/
9

  
10
/**
11
 * @defgroup tokenring Token Ring
12
 * @brief Wireless library token ring implementation
13
 *
14
 * This packet group is used to form a token ring, which
15
 * keeps track of the relative directions of the robots
16
 * from one another.
17
 *
18
 * @{
19
 **/
20

  
21
/**@brief Register the token ring group with the wireless library.**/
22
void wl_token_ring_register(void);
23
/**@brief Unregister the token ring group with the wirelss library.**/
24
void wl_token_ring_unregister(void);
25
/**@brief Set the functions called to turn the bom on and off.**/
26
void wl_token_ring_set_bom_functions(void (*on_function) (void), 
27
		void (*off_function) (void), int (*max_bom_function) (void));
28
/**@brief Join the token ring **/
29
void wl_token_ring_join(void);
30
/**@brief Leave the token ring **/
31
void wl_token_ring_leave(void);
32
/**@brief Request a BOM flash from the specified robot **/
33
void wl_token_request(int robot);
34
/**@brief Return the latest BOM reading between two robots **/
35
int wl_token_get_sensor_reading(int source, int dest);
36
/**@brief Return the latest BOM reading between us and another robot **/
37
int wl_token_get_my_sensor_reading(int dest);
38

  
39
/** @} **/ //end token ring group
40

  
trunk/code/lib/include/libwireless/wl_defs.h
1
//comment out this line if using a computer hooked up to an xbee
2
//#define ROBOT
3

  
4
//uncomment this line for debug information
5
#define WL_DEBUG
6

  
7
// Packet Groups and Types
8

  
9
// Error group
10
#define WL_ERROR_GROUP 1
11

  
12
#define WL_ERROR_STRING_TYPE 1
13

  
14
// Token Ring group
15
#define WL_TOKEN_RING_GROUP 2
16

  
17
#define WL_TOKEN_PASS 1
18
#define WL_TOKEN_BOM_ON 2
19
#define WL_TOKEN_INTERRUPT_REQUEST 3
20
#define WL_TOKEN_INTERRUPT_PASS 4
21
#define WL_TOKEN_JOIN 5
22
#define WL_TOKEN_JOIN_ACCEPT 6
23

  
24
// timing constants
25
#define BOM_DELAY 100
26
#define DEATH_DELAY 3
27
#define JOIN_DELAY 8
28

  
29
// Recharging group
30
#define WL_RECHARGE_GROUP 3
31

  
32
#define WL_RECHARGE_POLL_STATIONS 1
33
#define WL_RECHARGE_STATION_AVAILABLE 2
34
#define WL_RECHARGE_REQUEST 3
35
#define WL_RECHARGE_REQUEST_ACCEPT 4
36
#define WL_RECHARGE_VERIFY 5
37
#define WL_RECHARGE_CANCEL 6
38
#define WL_RECHARGE_SEEKING 7
39
#define WL_RECHARGE_DOCKED 8
40

  
41
#ifdef WL_DEBUG
42

  
43
#ifdef ROBOT
44
#include <serial.h>
45
#endif
46

  
47
#ifdef ROBOT
48
#define WL_DEBUG_PRINT( s ) usb_puts( s )
49
#else
50
#define WL_DEBUG_PRINT( s ) printf( s )
51
#endif
52

  
53
#ifdef ROBOT
54
#define WL_DEBUG_PRINT_INT( i ) usb_puti(i)
55
#else
56
#define WL_DEBUG_PRINT_INT( i ) printf("%i", i)
57
#endif
58

  
59
#else
60

  
61
#define WL_DEBUG_PRINT( s )
62
#define WL_DEBUG_PRINT_INT( i )
63

  
64
#endif
65

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

  
13
/**
14
 * @defgroup xbee XBee
15
 * @brief Interface with the XBee module
16
 *
17
 * Interface with the XBee module.
18
 *
19
 * @{
20
 **/
21

  
22
/*Definitions*/
23
/**@brief Do not change the PAN **/
24
#define XBEE_PAN_DEFAULT 0xFFFF
25
/**@brief Broadcast to all robots in the PAN **/
26
#define XBEE_BROADCAST 0xFFFF
27
/**@brief No special options **/
28
#define XBEE_OPTIONS_NONE 0x00
29
/**@brief Do not receive a TX_STATUS message from this packet **/
30
#define XBEE_OPTIONS_DISABLE_RESPONSE 0x01
31
/**@brief Send the packet to all PANS **/
32
#define XBEE_OPTIONS_BROADCAST_ALL_PANS 0x04
33
/**@brief A transmit status packet **/
34
#define XBEE_TX_STATUS 0x89
35
/**@brief A packet received from another XBee **/
36
#define XBEE_RX 0x81
37

  
38
/**@brief Initialize the XBee library **/
39
void xbee_lib_init(int pan_id);
40
/**@brief Uninitialize the XBee library **/
41
void xbee_terminate(void);
42
/**@brief Get a packet from the XBee **/
43
int xbee_get_packet(unsigned char* packet);
44
/**@brief Send a packet to the XBee **/
45
void xbee_send_packet(char* packet, int len, int dest,
46
	char options, char frame);
47
/**@brief Set the PAN ID for the XBee **/
48
void xbee_set_pan_id(int id);
49
/**@brief Get the XBee's PAN ID **/
50
unsigned int xbee_get_pan_id(void);
51
/**@brief Get the XBee's 16-bit address **/
52
unsigned int xbee_get_address(void);
53

  
54
/**@}**/ //end defgroup
55

  
trunk/code/lib/include/libwireless/queue.h
1
/**
2
 * @file queue.h
3
 * @brief A queue implementation
4
 * 
5
 * Implements a queue, a first in, first out data structure.
6
 *
7
 * @author Brian Coltin, Colony Project
8
 **/
9

  
10
struct node_def;
11

  
12
/**
13
 * @defgroup queue Queue
14
 * @brief A queue implementation
15
 * 
16
 * A queue implementation.
17
 *
18
 * @{
19
 **/
20

  
21
/**
22
 * @struct Queue
23
 * Represents a queue, a first in, first out data structure.
24
 **/
25
typedef struct
26
{
27
	/**
28
	 * The head of the queue, the next item to be removed.
29
	 **/
30
	struct node_def* head;
31
	/**
32
	 * The tail of the queue, the last item added.
33
	 **/
34
	struct node_def* tail;
35
	/**
36
	 * The number of elements in the queue.
37
	 **/
38
	int size;
39
} Queue;
40

  
41
/** @brief Create a new queue **/
42
Queue* queue_create(void);
43
/** @brief Destroy a queue **/
44
void queue_destroy(Queue* q);
45
/** @brief Add an element to a queue **/
46
void queue_add(Queue* q, void* item);
47
/** @brief Remove an element from a queue **/
48
void* queue_remove(Queue* q);
49
/** @brief Remove all instances of a given element from a queue **/
50
void queue_remove_all(Queue* q, void* item);
51
/** @brief Get the size of a queue **/
52
int queue_size(Queue* q);
53
/** @brief Check if the queue is empty **/
54
int queue_is_empty(Queue* q);
55

  
56
/** @} **/
57

  
trunk/code/lib/include/libwireless/wl_error_group.h
1
/**
2
 * @file wl_error_group.h
3
 * @brief A packet group for error messages.
4
 *
5
 * A packet group for sending and receiving error
6
 * messages.
7
 *
8
 * @author Brian Coltin, Colony Project, CMU Robotics Club
9
 **/
10

  
11
/**
12
 * @defgroup wlerror Error Packets
13
 * @brief Functions for sending and receiving error packets
14
 * 
15
 * Functions for sending and receiving error packets.
16
 * 
17
 * @{
18
 **/
19

  
20
/**@brief Register this packet group with the wireless library **/
21
void wl_error_register(void);
22
/**@brief Unregister this packet group with the wireless library **/
23
void wl_error_unregister(void);
24
/**@brief Send a string in an error packet **/
25
void wl_error_send_string(char* str);
26

  
27
/** @} **/ // end defgroup
28

  
trunk/code/lib/src/libwireless/wl_token_ring.c
1
#include <wl_token_ring.h>
2

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

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

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

  
16
#define DEFAULT_SENSOR_MATRIX_SIZE 20
17

  
18
//TODO: idea: if the xbee can handle many packets at once, we could have everyone
19
//send their BOM reading for a particular robot right after getting it.
20

  
21
/*Ring States*/
22

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

  
29
/*Frame Types*/
30
#define TOKEN_JOIN_ACCEPT_FRAME 1
31

  
32
/*Function Prototypes*/
33

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

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

  
46
/*Packet Handling Routines*/
47
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength);
48
void wl_token_interrupt_request_receive(int source, int robot);
49
void wl_token_interrupt_pass_receive(int source, int robot);
50
void wl_token_bom_on_receive(int source);
51
void wl_token_join_receive(int source);
52
void wl_token_join_accept_receive(int source);
53

  
54
/*Global Variables*/
55

  
56
//the sensor matrix
57
SensorMatrix* sensorMatrix;
58

  
59
//the robot we are waiting to say it has received the token. -1 if unspecified
60
int wl_token_next_robot = -1;
61

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

  
69
//the counter for when we assume a robot is dead
70
int deathDelay = -1;
71
//the counter for joining, before we form our own token ring
72
int joinDelay = -1;
73
//queue containing ids of interruption requests
74
Queue* interrupting = NULL;
75

  
76
#ifdef ROBOT
77
void (*bom_on_function) (void) = bom_on;
78
void (*bom_off_function) (void) = bom_off;
79
int (*get_max_bom_function) (void) = get_max_bom;
80
#else
81
void do_nothing(void) {}
82
int get_nothing(void) {return -1;}
83
void (*bom_on_function) (void) = do_nothing;
84
void (*bom_off_function) (void) = do_nothing;
85
int (*get_max_bom_function) (void) = get_nothing;
86
#endif
87

  
88
PacketGroupHandler wl_token_ring_handler =
89
		{WL_TOKEN_RING_GROUP, wl_token_ring_timeout_handler,
90
		wl_token_ring_response_handler, wl_token_ring_receive_handler,
91
		wl_token_ring_cleanup};
92

  
93
/**
94
 * Initialize the token ring packet group and register it with the
95
 * wireless library. The robot will not join a token ring.
96
 **/
97
void wl_token_ring_register()
98
{
99
	if (wl_get_xbee_id() > 0xFF)
100
	{
101
		//Note: if this becomes an issue (unlikely), we could limit sensor information
102
		//to half a byte and use 12 bits for the id
103
		WL_DEBUG_PRINT("XBee ID must be single byte for token ring, is ");
104
		WL_DEBUG_PRINT_INT(wl_get_xbee_id());
105
		WL_DEBUG_PRINT(".\r\n");
106
		return;
107
	}
108
	
109
	sensorMatrix = sensor_matrix_create();
110
	interrupting = queue_create();
111
	//add ourselves to the sensor matrix
112
	sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
113

  
114
	wl_register_packet_group(&wl_token_ring_handler);
115
}
116

  
117
/**
118
 * Removes the packet group from the wireless library.
119
 **/
120
void wl_token_ring_unregister()
121
{
122
	wl_unregister_packet_group(&wl_token_ring_handler);
123
}
124

  
125
/**
126
 * Sets the functions that are called when the BOM ought to be
127
 * turned on or off. This could be used for things such as 
128
 * charging stations, which have multiple BOMs.
129
 *
130
 * @param on_function the function to be called when the BOM
131
 * should be turned on
132
 * @param off_function the function to be called when the BOM
133
 * should be turned off
134
 * @param max_bom_function the function to be called when a
135
 * measurement of the maximum BOM reading is needed.
136
 **/
137
void wl_token_ring_set_bom_functions(void (*on_function) (void),
138
	void (*off_function) (void), int (*max_bom_function) (void))
139
{
140
	bom_on_function = on_function;
141
	bom_off_function = off_function;
142
	get_max_bom_function = max_bom_function;
143
}
144

  
145
/**
146
 * Called to cleanup the token ring packet group.
147
 **/
148
void wl_token_ring_cleanup()
149
{
150
	sensor_matrix_destroy(sensorMatrix);
151
	queue_destroy(interrupting);
152
}
153

  
154
/**
155
 * Called approximately every quarter second by the wireless library.
156
 **/
157
void wl_token_ring_timeout_handler()
158
{
159
	//someone is not responding, assume they are dead
160
	if (deathDelay == 0)
161
	{
162
		//pass the token to the next robot if we think someone has died
163
		//also, declare that person dead, as long as it isn't us
164
		if (wl_token_next_robot != wl_get_xbee_id())
165
		{
166
			sensor_matrix_set_in_ring(sensorMatrix, wl_token_next_robot, 0);
167
			WL_DEBUG_PRINT("Robot ");
168
			WL_DEBUG_PRINT_INT(wl_token_next_robot);
169
			WL_DEBUG_PRINT(" has died.\r\n");
170
		}
171
		wl_token_pass_token();
172
	}
173

  
174
	//we must start our own token ring, no one is responding to us
175
	if (joinDelay == 0)
176
	{
177
		if (sensor_matrix_get_joined(sensorMatrix) == 0)
178
		{
179
			WL_DEBUG_PRINT("Creating our own token ring, no robots seem to exist.\r\n");
180
			sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
181
			ringState = MEMBER;
182
			//this will make us pass the token to ourself
183
			//repeatedly, and other robots when they join
184
			deathDelay = DEATH_DELAY;
185
			wl_token_next_robot = wl_get_xbee_id();
186
		}
187
		else
188
		{
189
			WL_DEBUG_PRINT("Attempting to join the token ring again.\r\n");
190
			//attempt to rejoin with a random delay
191
			wl_token_ring_join();
192
			joinDelay = rand() / (RAND_MAX / JOIN_DELAY) + 1;
193
		}
194
	}
195

  
196
	if (deathDelay >= 0)
197
		deathDelay--;
198
	if (joinDelay >= 0)
199
		joinDelay--;
200
}
201

  
202
/**
203
 * Called when the XBee tells us if a packet we sent has been received.
204
 * 
205
 * @param frame the frame number assigned when the packet was sent
206
 * @param received 1 if the packet was received, 0 otherwise
207
 **/
208
void wl_token_ring_response_handler(int frame, int received)
209
{
210
	if (!received)
211
	{
212
		WL_DEBUG_PRINT("FAILED.\r\n");
213
	}
214
}
215

  
216
/**
217
 * Called when we recieve a token ring packet.
218
 * @param type the type of the packet
219
 * @param source the id of the robot who sent the packet
220
 * @param packet the data in the packet
221
 * @param length the length of the packet in bytes
222
 **/
223
void wl_token_ring_receive_handler(char type, int source, unsigned char* packet,
224
							int length)
225
{
226
	switch (type)
227
	{
228
		case WL_TOKEN_PASS:
229
			if (length < 1)
230
			{
231
				WL_DEBUG_PRINT("Malformed Token Pass packet received.\r\n");
232
				return;
233
			}
234
			wl_token_pass_receive(source, packet[0], packet + 1, length - 1);
235
			break;
236
		case WL_TOKEN_BOM_ON:
237
			//add the robot to the sensor matrix if it is not already there
238
			wl_token_bom_on_receive(source);
239
			break;
240
		case WL_TOKEN_INTERRUPT_REQUEST:
241
			wl_token_interrupt_request_receive(source, packet[0]);
242
			break;
243
		case WL_TOKEN_INTERRUPT_PASS:
244
			wl_token_interrupt_pass_receive(source, packet[0]);
245
			break;
246
		case WL_TOKEN_JOIN:
247
			wl_token_join_receive(source);
248
			break;
249
		case WL_TOKEN_JOIN_ACCEPT:
250
			wl_token_join_accept_receive(source);
251
			break;
252
		default:
253
			WL_DEBUG_PRINT("Unimplemented token ring packet received.\r\n");
254
			break;
255
	}
256
}
257

  
258
/**
259
 * Causes the robot to join an existing token ring, or create one
260
 * if no token ring exists. The token ring uses global and robot to robot
261
 * packets, and does not rely on any PAN.
262
 **/
263
void wl_token_ring_join()
264
{
265
	WL_DEBUG_PRINT("Joining the token ring.\r\n");
266
	ringState = JOINING;
267
	joinDelay = JOIN_DELAY;
268
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN,
269
		NULL, 0, 0);
270
}
271

  
272
/**
273
 * Causes the robot to leave the token ring. The robot stops
274
 * alerting others of its location, but continues storing the
275
 * locations of other robots.
276
 **/
277
void wl_token_ring_leave()
278
{
279
	ringState = LEAVING;
280
}
281

  
282
/**
283
 * Requests that the specified robot be given the token and
284
 * allowed to flash its BOM. After its BOM is flashed, the
285
 * token will return to the robot who sent it.
286
 *
287
 * @param robot the ID of the robot which should flash its BOM
288
 **/
289
void wl_token_request(int robot)
290
{
291
	char buf[1];
292
	buf[0] = robot;
293
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_INTERRUPT_REQUEST,
294
		buf, 1, 0);
295
}
296

  
297
/**
298
 * Returns the BOM reading robot source has for robot dest.
299
 *
300
 * @param source the robot that made the BOM reading
301
 * @param dest the robot whose relative location is returned
302
 *
303
 * @return a BOM reading from robot source to robot dest,
304
 * in the range 0-15, or -1 if it is unknown
305
 **/
306
int wl_token_get_sensor_reading(int source, int dest)
307
{
308
	return sensor_matrix_get_reading(sensorMatrix, source, dest);
309
}
310

  
311
/**
312
 * Returns the BOM reading we have for robot dest.
313
 * 
314
 * @param dest the robot whose relative location is returned
315
 *
316
 * @return a BOM reading from us to robot dest, in the range
317
 * 0-15, or -1 if it is unkown
318
 **/
319
int wl_token_get_my_sensor_reading(int dest)
320
{
321
	return wl_token_get_sensor_reading(wl_get_xbee_id(), dest);
322
}
323

  
324
/**
325
 * This method is called when we receive a token pass packet.
326
 * @param source is the robot it came from
327
 * @param nextRobot is the robot the token was passed to
328
 * @param sensorData a char with an id followed by a char with the sensor
329
 *		reading for that robot, repeated for sensorDataLength bytes
330
 * @param sensorDataLength the length in bytes of sensorData
331
 */
332
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength)
333
{
334
	int i, j;
335
	deathDelay = -1;
336

  
337
	WL_DEBUG_PRINT("Received the token, next robot is ");
338
	WL_DEBUG_PRINT_INT((int)nextRobot);
339
	WL_DEBUG_PRINT(" \r\n");
340
	sensor_matrix_set_in_ring(sensorMatrix, source, 1);
341

  
342
	//with this packet, we are passed the id of the next robot in the ring
343
	//and the sensor matrix, a list of id and sensor reading pairs (two bytes for both)
344
	j = 0;
345
	for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
346
	{
347
		if (i == source)
348
			continue;
349
		
350
		//set the sensor information we receive
351
		if (j < sensorDataLength / 2 && sensorData[2 * j] == i)
352
		{
353
			//the robot we were going to accept has already been accepted
354
			if (accepted == i)
355
			{
356
				accepted = -1;
357
				WL_DEBUG_PRINT("Someone accepted the robot we did.\r\n");
358
			}
359
			sensor_matrix_set_reading(sensorMatrix, source, i,
360
						sensorData[2 * j + 1]);
361
			sensor_matrix_set_in_ring(sensorMatrix, i, 1);
362
			j++;
363
		}
364
		else
365
		{
366
			if (sensor_matrix_get_in_ring(sensorMatrix, i))
367
			{
368
				WL_DEBUG_PRINT("Robot ");
369
				WL_DEBUG_PRINT_INT(i);
370
				WL_DEBUG_PRINT(" has been removed from the sensor matrix of robot ");
371
				WL_DEBUG_PRINT_INT(wl_get_xbee_id());
372
				WL_DEBUG_PRINT(" due to a packet from robot ");
373
				WL_DEBUG_PRINT_INT(source);
374
				WL_DEBUG_PRINT(".\r\n");
375
				sensor_matrix_set_in_ring(sensorMatrix, i, 0);
376
			}
377

  
378
			if (i == wl_get_xbee_id() && ringState == MEMBER)
379
			{
380
				sensor_matrix_set_in_ring(sensorMatrix,
381
						wl_get_xbee_id(), 1);
382
				ringState = NONMEMBER;
383
				wl_token_ring_join();
384
				
385
				WL_DEBUG_PRINT("We have been removed from the ring ");
386
				WL_DEBUG_PRINT("and are rejoining.\r\n");
387
			}
388
			
389
			//the person who accepted us is dead... let's ask again
390
			if (i == acceptor)
391
			{
392
				sensor_matrix_set_in_ring(sensorMatrix,
393
						wl_get_xbee_id(), 1);
394
				ringState = NONMEMBER;
395
				acceptor = -1;
396
				wl_token_ring_join();
397
			}
398
		}
399
	}
400

  
401
	wl_token_next_robot = nextRobot;
402
	
403
	deathDelay = get_token_distance(wl_get_xbee_id(), nextRobot) * DEATH_DELAY;
404
	
405
	//we have the token
406
	if (wl_token_next_robot == wl_get_xbee_id())
407
		wl_token_get_token();
408
}
409

  
410
/**
411
 * Gets the distance in the token ring between two robots.
412
 *
413
 * @param robot1 the first robot
414
 * @param robot2 the second robot
415
 *
416
 * @return the number of passes before the token is expected
417
 * to reach robot2 from robot1
418
 **/
419
int get_token_distance(int robot1, int robot2)
420
{
421
	int curr = robot1 + 1;
422
	int count = 1;
423
	while (1)
424
	{
425
		if (curr == sensor_matrix_get_size(sensorMatrix))
426
			curr = 0;
427
		if (curr == robot2)
428
			break;
429
		if (sensor_matrix_get_in_ring(sensorMatrix, curr))
430
			count++;
431
		curr++;
432
	}
433
	return count;
434
}
435

  
436
/**
437
 * Passes the token to the next robot in the token ring.
438
 **/
439
void wl_token_pass_token()
440
{
441
	char nextRobot;
442
	int i = wl_get_xbee_id() + 1;
443
	if (accepted == -1)
444
	{
445
		while (1)
446
		{
447
			if (i == sensor_matrix_get_size(sensorMatrix))
448
				i = 0;
449
			if (sensor_matrix_get_in_ring(sensorMatrix, i))
450
			{
451
				nextRobot = (char)i;
452
				break;
453
			}
454
			i++;
455
		}
456
	}
457
	else
458
	{
459
		WL_DEBUG_PRINT("Accepting new robot, sending it the token.\r\n");
460
		//add a new robot to the token ring
461
		sensor_matrix_set_in_ring(sensorMatrix, accepted, 1);
462
		nextRobot = accepted;
463
		accepted = -1;
464
	}
465

  
466
	//we don't include ourself
467
	int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
468
	char* buf = (char*)malloc(packetSize * sizeof(char));
469
	if (!buf)
470
	{
471
		WL_DEBUG_PRINT_INT(packetSize);
472
		WL_DEBUG_PRINT("Out of memory - pass token.\r\n");
473
		return;
474
	}
475
	buf[0] = nextRobot;
476

  
477
	int j = 0;
478
	for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
479
		if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
480
		{
481
			buf[2*j + 1] = i;
482
			buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
483
			j++;
484
		}
485
	
486
	WL_DEBUG_PRINT("Passing the token to robot ");
487
	WL_DEBUG_PRINT_INT(buf[0]);
488
	WL_DEBUG_PRINT(".\r\n");
489
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
490
		buf, packetSize, 3);
491

  
492
	wl_token_next_robot = nextRobot;
493
	deathDelay = DEATH_DELAY;
494
	free(buf);
495
}
496

  
497
/**
498
 * Called when a packet is received stating that another robot has turned
499
 * its BOM on. Our BOM is then read, and the data is added to the sensor
500
 * matrix.
501
 *
502
 * @param source the robot whose BOM is on
503
 **/
504
void wl_token_bom_on_receive(int source)
505
{
506
	WL_DEBUG_PRINT("Robot ");
507
	WL_DEBUG_PRINT_INT(source);
508
	WL_DEBUG_PRINT(" has flashed its bom.\r\n");
509
	sensor_matrix_set_reading(sensorMatrix, wl_get_xbee_id(), 
510
		source, get_max_bom_function());
511
}
512

  
513
/**
514
 * This method is called when we receive the token. Upon receiving
515
 * the token, we must send a BOM_ON packet, flash the BOM, and send
516
 * the token to the next robot.
517
 * 
518
 * If there is a pending request for the token, this is processed first.
519
 **/
520
void wl_token_get_token()
521
{
522
	WL_DEBUG_PRINT("We have the token.\r\n");
523
	if (ringState == ACCEPTED)
524
	{
525
		sensor_matrix_set_in_ring(sensorMatrix,
526
			wl_get_xbee_id(), 1);
527
		WL_DEBUG_PRINT("Now a member of the token ring.\r\n");
528
		ringState = MEMBER;
529
	}
530

  
531
	if (ringState == LEAVING || ringState == NONMEMBER)
532
	{
533
		sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
534
		if (ringState == NONMEMBER)
535
		{
536
			WL_DEBUG_PRINT("We should have left the token ring, but didn't.\r\n");
537
		}
538
	}
539
	
540
	//check for interruption requests
541
	if (queue_size(interrupting) > 0)
542
	{
543
		char buf[1];
544
		buf[0] = (char)(int)queue_remove(interrupting);
545
		
546
		//in case this robot has requested multiple times
547
		queue_remove_all(interrupting, (void*)(int)buf[0]);
548

  
549
		wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_INTERRUPT_PASS,
550
			buf, 1, 0);
551

  
552
		deathDelay = DEATH_DELAY;
553
		wl_token_next_robot = buf[0];
554
		return;
555
	}
556

  
557
	WL_DEBUG_PRINT("Our BOM has been flashed.\r\n");
558
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
559
		NULL, 0, 0);
560

  
561
	bom_on_function();
562
	#ifdef ROBOT
563
	delay_ms(BOM_DELAY);
564
	#endif
565
	bom_off_function();
566
	
567
	if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
568
	{
569
		WL_DEBUG_PRINT("Removed from sensor matrix while flashing BOM.\r\n");
570
	}
571
	
572
	wl_token_pass_token();
573
}
574

  
575
/**
576
 * Called when a request to join the token ring is received.
577
 * If we are the robot preceding the requester in the ring,
578
 * we respond with a JOIN_ACCEPT packet and pass the token to
579
 * this robot when we receive the token.
580
 *
581
 * @param source the robot who requested to join
582
 **/
583
void wl_token_join_receive(int source)
584
{
585
	WL_DEBUG_PRINT("Received joining request from robot ");
586
	WL_DEBUG_PRINT_INT(source);
587
	WL_DEBUG_PRINT(".\r\n");
588

  
589
	//we cannot accept the request if we are not a member
590
	if (ringState != MEMBER)
591
		return;
592
	//if they didn't get our response, see if we should respond again
593
	if (accepted == source)
594
		accepted = -1;
595
	//we can only accept one request at a time
596
	if (accepted != -1)
597
		return;
598
	
599
	//check if we are the preceding robot in the token ring
600
	int i = source - 1;
601
	while (1)
602
	{
603
		if (i < 0)
604
			i = sensor_matrix_get_size(sensorMatrix) - 1;
605
		//we must send a join acceptance
606
		if (i == wl_get_xbee_id())
607
			break;
608

  
609
		//another robot will handle it
610
		if (sensor_matrix_get_in_ring(sensorMatrix, i))
611
			return;
612
		i--;
613
	}
614

  
615
	accepted = source;
616
	wl_send_robot_to_robot_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN_ACCEPT,
617
		NULL, 0, source, TOKEN_JOIN_ACCEPT_FRAME);
618
	
619
	WL_DEBUG_PRINT("Accepting robot ");
620
	WL_DEBUG_PRINT_INT(source);
621
	WL_DEBUG_PRINT(" into the token ring.\r\n");
622

  
623
	joinDelay = -1;
624
	
625
	// the token ring has not started yet
626
	if (sensor_matrix_get_joined(sensorMatrix) == 1)
627
		wl_token_pass_token();
628
}
629

  
630
/**
631
 * Called when we receive a JOIN_ACCEPT packet in attempting to join
632
 * the token ring.
633
 * Our attempt to join the ring is stopped, and we wait for the token.
634
 *
635
 * @param source the robot who accepted us
636
 **/
637
void wl_token_join_accept_receive(int source)
638
{
639
	WL_DEBUG_PRINT("Accepted into the token ring by robot ");
640
	WL_DEBUG_PRINT_INT(source);
641
	WL_DEBUG_PRINT(".\r\n");
642
	joinDelay = -1;
643
	ringState = ACCEPTED;
644
	acceptor = source;
645

  
646
	//add ourselves to the token ring
647
	sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
648
}
649

  
650
/**
651
 * Called when we receive a packet passing the token and interrupting
652
 * the token ring.
653
 * If the token has been passed to us, we flash our BOM
654
 * and pass it back.
655
 *
656
 * @param source the robot who sent the interrupt packet
657
 * @param robot the robot the token has been passed to
658
 **/
659
void wl_token_interrupt_pass_receive(int source, int robot)
660
{
661
	if (wl_get_xbee_id() != robot)
662
	{
663
		queue_remove_all(interrupting, (void*)robot);
664
		wl_token_next_robot = robot;
665
		deathDelay = DEATH_DELAY + rand() / (RAND_MAX / (2 * DEATH_DELAY));
666
		return;
667
	}
668
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
669
		NULL, 0, 0);
670
	
671
	bom_on_function();
672
	#ifdef ROBOT
673
	delay_ms(BOM_DELAY);
674
	#endif
675
	bom_off_function();
676

  
677
	//we don't include ourself, only if we are in the ring
678
	int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
679
	if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
680
		packetSize += 2;
681
	char* buf = (char*)malloc(packetSize * sizeof(char));
682
	if (!buf)
683
	{
684
		WL_DEBUG_PRINT("Out of memory - pass_receive.\r\n");
685
		return;
686
	}
687
	
688
	//return the token to where we got it from
689
	buf[0] = source;
690

  
691
	int i = 0, j = 0;
692
	for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
693
		if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
694
		{
695
			buf[2*j + 1] = i;
696
			buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
697
			j++;
698
		}
699
	
700
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
701
		buf, packetSize, 0);
702

  
703
	wl_token_next_robot = source;
704
	deathDelay = DEATH_DELAY;
705
	free(buf);
706
}
707

  
708
/**
709
 * Called when we receive a request to interrupt the token ring.
710
 * We add the robot to our list of interrupt requests,
711
 * and will send the token to this robot when we next receive the
712
 * token, unless someone else does so first.
713
 *
714
 * @param source the robot requesting interruption
715
 * @param robt the robot requested to interrupt the token ring
716
 **/
717
void wl_token_interrupt_request_receive(int source, int robot)
718
{
719
	queue_add(interrupting, (void*)robot);
720
}
721

  
trunk/code/lib/src/libwireless/xbee.c
1
#include "xbee.h"
2
#include "wl_defs.h"
3

  
4
#ifndef ROBOT
5

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

  
11
#else
12

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

  
16
#endif
17

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

  
22
#include <queue.h>
23

  
24
#define XBEE_FRAME_START 0x7E
25

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

  
36
/*Internal Function Prototypes*/
37

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

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

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

  
55
/*API Mode Functions*/
56

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

  
67
/*Global Variables*/
68

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

  
74
Queue* xbee_queue;
75

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

  
80
//XBee status
81
unsigned int xbee_panID = XBEE_PAN_DEFAULT;
82
unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
83
unsigned int xbee_address = 0;
84

  
85
/*Function Implementations*/
86

  
87
#ifdef ROBOT
88

  
89
/**
90
 * Interrupt for the robot. Adds bytes received from the xbee
91
 * to the queue.
92
 **/
93
ISR(USART1_RX_vect)
94
{
95
	char c = UDR1;
96
	queue_add(xbee_queue, (void*)(int)c);
97
}
98

  
99
#else
100

  
101
/**
102
 * Thread that listens to the xbee.
103
 **/
104
void* listen_to_xbee(void* x)
105
{
106
	char c;
107
	while (1)
108
	{
109
		xbee_read(&c, 1);
110
		queue_add(xbee_queue, (void*)(int)c);
111
	}
112
	return 0;
113
}
114

  
115
#endif
116

  
117
/**
118
 * Initializes the XBee library so that other functions may be used.
119
 *
120
 * @param pan_id the PAN to join initially. Use XBEE_PAN_DEFAULT
121
 * to leave the PAN as it is initially.
122
 **/
123
void xbee_lib_init(int pan_id)
124
{
125
	xbee_queue = queue_create();
126
	
127
	#ifdef ROBOT
128

  
129
	//enable the receiving interrupt
130
	UCSR1B |= _BV(RXCIE);
131
	sei();
132
	#else
133
	xbee_stream = open("/dev/ttyUSB0", O_RDWR);
134
	if (xbee_stream == -1 || lockf(xbee_stream, F_TEST, 0) != 0)
135
		xbee_stream = open("/dev/ttyUSB1", O_RDWR);
136
	if (xbee_stream == -1 || lockf(xbee_stream, F_TEST, 0) != 0)
137
	{
138
		printf("Failed to open connection to XBee.\r\n");
139
		exit(0);
140
	}
141
	lockf(xbee_stream, F_LOCK, 0);
142
	
143
	xbee_listen_thread =
144
		(pthread_t*)malloc(sizeof(pthread_t));
145
	
146
	int ret = pthread_create(xbee_listen_thread, NULL, 
147
		listen_to_xbee, NULL);
148
	if (ret)
149
	{
150
		printf("Failed to create listener thread.\r\n");
151
		exit(0);
152
	}
153
	#endif
154
	xbee_enter_command_mode();
155
	xbee_enter_api_mode();
156
	xbee_exit_command_mode();
157
	xbee_send_read_at_command("MY");
158
	
159
	//wait to return until the address is set
160
	while (xbee_address == 0) xbee_get_packet(NULL);
161
	
162
	if (pan_id != XBEE_PAN_DEFAULT)
163
	{
164
		xbee_set_pan_id(pan_id);
165
		while (xbee_panID == XBEE_PAN_DEFAULT) xbee_get_packet(NULL);
166
	}
167
}
168

  
169
/**
170
 * Call when finished using the XBee library. This releases
171
 * all sued resources.
172
 **/
173
void xbee_terminate()
174
{
175
	#ifndef ROBOT
176
	pthread_cancel(*xbee_listen_thread);
177
	free(xbee_listen_thread);
178
	lockf(xbee_stream, F_ULOCK, 0);
179
	close(xbee_stream);
180
	#endif
181
	queue_destroy(xbee_queue);
182
}
183

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

  
214
	//write was interrupted after writing ret bytes
215
	xbee_send(buf + ret, size - ret);
216
	#endif
217
}
218

  
219
/**
220
 * Sends a string to the XBee.
221
 *
222
 * @param c the string to send to the XBEE
223
 **/
224
void xbee_send_string(char* c)
225
{
226
	xbee_send(c, strlen(c));
227
}
228

  
229
#ifndef ROBOT
230
void xbee_read(char* buf, int size)
231
{
232
	if (read(xbee_stream, buf, size) == -1)
233
		printf("Failed to read from xbee.\r\n");
234
}
235
#endif
236

  
237
/**
238
 * Enter into command mode.
239
 **/
240
void xbee_enter_command_mode()
241
{
242
	xbee_send_string("+++");
243
	xbee_wait_for_ok();
244
}
245

  
246
/**
247
 * Exit from command mode.
248
 **/
249
void xbee_exit_command_mode()
250
{
251
	xbee_send_string("ATCN\r");
252
	xbee_wait_for_ok();
253
}
254

  
255
/**
256
 * Enter API mode.
257
 **/
258
void xbee_enter_api_mode()
259
{
260
	xbee_send_string("ATAP 1\r");
261
	xbee_wait_for_ok();
262
}
263

  
264
/**
265
 * Wait until the string "OK\r" is received from the XBee.
266
 **/
267
void xbee_wait_for_ok()
268
{
269
	xbee_wait_for_string("OK\r", 3);
270
}
271

  
272
/**
273
 * Delay until the specified string is received from
274
 * the XBee. Discards all other XBee data.
275
 *
276
 * @param s the string to receive
277
 * @param len the length of the string
278
 **/
279
void xbee_wait_for_string(char* s, int len)
280
{
281
	char* curr = s;
282
	while (curr - s < len)
283
	{
284
		if (queue_is_empty(xbee_queue))
285
			continue;
286
		char c = (char)(int)queue_remove(xbee_queue);
287
		if (c == *curr)
288
			curr++;
289
		else
290
			curr = s;
291
	}
292
}
293

  
294
/**
295
 * Verifies that the packets checksum is correct.
296
 * (If the checksum is correct, the sum of the bytes
297
 * is 0xFF.)
298
 *
299
 * @param packet the packet received. This includes the first
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff