Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / libwireless / lib / wl_token_ring.c @ 418

History | View | Annotate | Download (20.3 KB)

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

    
26
/**
27
 * @file wl_token_ring.c
28
 * @brief Token Ring Implementation
29
 *
30
 * Implementation of the token ring packet group.
31
 *
32
 * @author Brian Coltin, Colony Project, CMU Robotics Club
33
 **/
34

    
35
#include <wl_token_ring.h>
36

    
37
#include <stdlib.h>
38
#include <stdio.h>
39

    
40
#include <wl_defs.h>
41
#include <wireless.h>
42
#include <sensor_matrix.h>
43

    
44
#ifdef ROBOT
45
#ifndef FIREFLY
46
#include <bom.h>
47
#endif
48
#include <time.h>
49
#endif
50

    
51
#define DEFAULT_SENSOR_MATRIX_SIZE 20
52

    
53
/*Ring States*/
54

    
55
#define NONMEMBER 0
56
#define MEMBER 1
57
#define JOINING 2
58
#define ACCEPTED 3
59
#define LEAVING 4
60

    
61
/*Frame Types*/
62
#define TOKEN_JOIN_ACCEPT_FRAME 1
63

    
64
/*Function Prototypes*/
65

    
66
/*Wireless Library Prototypes*/
67
static void wl_token_ring_timeout_handler(void);
68
static void wl_token_ring_response_handler(int frame, int received);
69
static void wl_token_ring_receive_handler(char type, int source, unsigned char* packet, int length);
70
static void wl_token_ring_cleanup(void);
71

    
72
/*Helper Functions*/
73
static void wl_token_pass_token(void);
74
static int get_token_distance(int robot1, int robot2);
75
static void wl_token_get_token(void);
76

    
77
/*Packet Handling Routines*/
78
static void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength);
79
static void wl_token_bom_on_receive(int source);
80
static void wl_token_join_receive(int source);
81
static void wl_token_join_accept_receive(int source);
82

    
83
/*Global Variables*/
84

    
85
//the sensor matrix
86
static SensorMatrix* sensorMatrix;
87

    
88
//the robot we are waiting to say it has received the token. -1 if unspecified
89
static int wl_token_next_robot = -1;
90

    
91
//true if the robot should be in the token ring, 0 otherwise
92
static int ringState = NONMEMBER;
93
//the id of the robot who accepted us into the token ring, only used in ACCEPTED state
94
static int acceptor = -1;
95
//id of the robot we are accepting
96
static int accepted = -1;
97

    
98
//the counter for when we assume a robot is dead
99
static int deathDelay = -1;
100
//the counter for joining, before we form our own token ring
101
static int joinDelay = -1;
102

    
103
//current robot to check in the iterator
104
static int iteratorCount = 0;
105

    
106
// the amount of time a robot has had its BOM on for
107
static int bom_on_count = 0;
108

    
109
static void do_nothing(void) {}
110
static int get_nothing(void) {return -1;}
111

    
112
#ifdef ROBOT
113
#ifndef FIREFLY
114
static void (*bom_on_function) (void) = bom_on;
115
static void (*bom_off_function) (void) = bom_off;
116
static int (*get_max_bom_function) (void) = get_max_bom;
117
#else
118
static void (*bom_on_function) (void) = do_nothing;
119
static void (*bom_off_function) (void) = do_nothing;
120
static int (*get_max_bom_function) (void) = get_nothing;
121
#endif
122
#else
123
static void (*bom_on_function) (void) = do_nothing;
124
static void (*bom_off_function) (void) = do_nothing;
125
static int (*get_max_bom_function) (void) = get_nothing;
126
#endif
127

    
128
static PacketGroupHandler wl_token_ring_handler =
129
        {WL_TOKEN_RING_GROUP, wl_token_ring_timeout_handler,
130
                wl_token_ring_response_handler, wl_token_ring_receive_handler,
131
                wl_token_ring_cleanup};
132

    
133
/**
134
 * Initialize the token ring packet group and register it with the
135
 * wireless library. The robot will not join a token ring.
136
 **/
137
int wl_token_ring_register()
138
{
139
        if (wl_get_xbee_id() > 0xFF)
140
        {
141
                //Note: if this becomes an issue (unlikely), we could limit sensor information
142
                //to half a byte and use 12 bits for the id
143
                WL_DEBUG_PRINT("XBee ID must be single byte for token ring, is ");
144
                WL_DEBUG_PRINT_INT(wl_get_xbee_id());
145
                WL_DEBUG_PRINT(".\r\n");
146
                return -1;
147
        }
148

    
149
        sensorMatrix = sensor_matrix_create();
150
        //add ourselves to the sensor matrix
151
        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
152

    
153
        wl_register_packet_group(&wl_token_ring_handler);
154

    
155
        return 0;
156
}
157

    
158
/**
159
 * Removes the packet group from the wireless library.
160
 **/
161
void wl_token_ring_unregister()
162
{
163
        wl_unregister_packet_group(&wl_token_ring_handler);
164
}
165

    
166
/**
167
 * Sets the functions that are called when the BOM ought to be
168
 * turned on or off. This could be used for things such as
169
 * charging stations, which have multiple BOMs.
170
 *
171
 * @param on_function the function to be called when the BOM
172
 * should be turned on
173
 * @param off_function the function to be called when the BOM
174
 * should be turned off
175
 * @param max_bom_function the function to be called when a
176
 * measurement of the maximum BOM reading is needed.
177
 **/
178
void wl_token_ring_set_bom_functions(void (*on_function) (void),
179
        void (*off_function) (void), int (*max_bom_function) (void))
180
{
181
        bom_on_function = on_function;
182
        bom_off_function = off_function;
183
        get_max_bom_function = max_bom_function;
184
}
185

    
186
/**
187
 * Called to cleanup the token ring packet group.
188
 **/
189
void wl_token_ring_cleanup()
190
{
191
        sensor_matrix_destroy(sensorMatrix);
192
}
193

    
194
/**
195
 * Called approximately every quarter second by the wireless library.
196
 **/
197
static void wl_token_ring_timeout_handler()
198
{
199
        //someone is not responding, assume they are dead
200
        if (deathDelay == 0)
201
        {
202
                //pass the token to the next robot if we think someone has died
203
                //also, declare that person dead, as long as it isn't us
204
                if (wl_token_next_robot != wl_get_xbee_id())
205
                {
206
                        sensor_matrix_set_in_ring(sensorMatrix, wl_token_next_robot, 0);
207
                        WL_DEBUG_PRINT("Robot ");
208
                        WL_DEBUG_PRINT_INT(wl_token_next_robot);
209
                        WL_DEBUG_PRINT(" has died.\r\n");
210
                        wl_token_next_robot = -1;
211
                        deathDelay = DEATH_DELAY;
212
                }
213

    
214
                // we may have been dropped from the ring when this is received
215
                if (ringState == MEMBER)
216
                        wl_token_pass_token();
217
        }
218

    
219
        //we must start our own token ring, no one is responding to us
220
        if (joinDelay == 0)
221
        {
222
                if (sensor_matrix_get_joined(sensorMatrix) == 0)
223
                {
224
                        WL_DEBUG_PRINT("Creating our own token ring, no robots seem to exist.\r\n");
225
                        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
226
                        ringState = MEMBER;
227
                        //this will make us pass the token to ourself
228
                        //repeatedly, and other robots when they join
229
                        deathDelay = DEATH_DELAY;
230
                        wl_token_next_robot = wl_get_xbee_id();
231
                }
232
                else
233
                {
234
                        WL_DEBUG_PRINT("Attempting to join the token ring again.\r\n");
235
                        //attempt to rejoin with a random delay
236
                        wl_token_ring_join();
237
                        joinDelay = rand() / (RAND_MAX / JOIN_DELAY) + 1;
238
                }
239
        }
240

    
241
        if (deathDelay >= 0)
242
                deathDelay--;
243
        if (joinDelay >= 0)
244
                joinDelay--;
245
        if (bom_on_count >= 0)
246
                bom_on_count++;
247
}
248

    
249
/**
250
 * Called when the XBee tells us if a packet we sent has been received.
251
 *
252
 * @param frame the frame number assigned when the packet was sent
253
 * @param received 1 if the packet was received, 0 otherwise
254
 **/
255
static void wl_token_ring_response_handler(int frame, int received)
256
{
257
        if (!received)
258
        {
259
                WL_DEBUG_PRINT("FAILED.\r\n");
260
        }
261
}
262

    
263
/**
264
 * Called when we recieve a token ring packet.
265
 * @param type the type of the packet
266
 * @param source the id of the robot who sent the packet
267
 * @param packet the data in the packet
268
 * @param length the length of the packet in bytes
269
 **/
270
static void wl_token_ring_receive_handler(char type, int source, unsigned char* packet, int length)
271
{
272
        switch (type)
273
        {
274
                case WL_TOKEN_PASS:
275
                        if (length < 1)
276
                        {
277
                                WL_DEBUG_PRINT("Malformed Token Pass packet received.\r\n");
278
                                return;
279
                        }
280
                        wl_token_pass_receive(source, packet[0], packet + 1, length - 1);
281
                        break;
282
                case WL_TOKEN_BOM_ON:
283
                        //add the robot to the sensor matrix if it is not already there
284
                        wl_token_bom_on_receive(source);
285
                        break;
286
                case WL_TOKEN_JOIN:
287
                        wl_token_join_receive(source);
288
                        break;
289
                case WL_TOKEN_JOIN_ACCEPT:
290
                        wl_token_join_accept_receive(source);
291
                        break;
292
                default:
293
                        WL_DEBUG_PRINT("Unimplemented token ring packet received.\r\n");
294
                        break;
295
        }
296
}
297

    
298
/**
299
 * Causes the robot to join an existing token ring, or create one
300
 * if no token ring exists. The token ring uses global and robot to robot
301
 * packets, and does not rely on any PAN.
302
 **/
303
int wl_token_ring_join()
304
{
305
        WL_DEBUG_PRINT("Joining the token ring.\r\n");
306
        ringState = JOINING;
307
        joinDelay = DEATH_DELAY * 2;
308
        if (wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN, NULL, 0, 0) != 0) {
309
                return -1;
310
        }
311

    
312
        return 0;
313
}
314

    
315
/**
316
 * Causes the robot to leave the token ring. The robot stops
317
 * alerting others of its location, but continues storing the
318
 * locations of other robots.
319
 **/
320
void wl_token_ring_leave()
321
{
322
        ringState = LEAVING;
323
}
324

    
325
/**
326
 * Returns the BOM reading robot source has for robot dest.
327
 *
328
 * @param source the robot that made the BOM reading
329
 * @param dest the robot whose relative location is returned
330
 *
331
 * @return a BOM reading from robot source to robot dest,
332
 * in the range 0-15, or -1 if it is unknown
333
 **/
334
int wl_token_get_sensor_reading(int source, int dest)
335
{
336
        if (wl_token_is_robot_in_ring(dest) &&
337
                        (source == wl_get_xbee_id() || wl_token_is_robot_in_ring(source))) {
338
                return sensor_matrix_get_reading(sensorMatrix, source, dest);
339
        }
340

    
341
        return -1;
342
}
343

    
344
/**
345
 * Returns the BOM reading we have for robot dest.
346
 *
347
 * @param dest the robot whose relative location is returned
348
 *
349
 * @return a BOM reading from us to robot dest, in the range
350
 * 0-15, or -1 if it is unkown
351
 **/
352
int wl_token_get_my_sensor_reading(int dest)
353
{
354
        return wl_token_get_sensor_reading(wl_get_xbee_id(), dest);
355
}
356

    
357
/**
358
 * This method is called when we receive a token pass packet.
359
 * @param source is the robot it came from
360
 * @param nextRobot is the robot the token was passed to
361
 * @param sensorData a char with an id followed by a char with the sensor
362
 *                reading for that robot, repeated for sensorDataLength bytes
363
 * @param sensorDataLength the length in bytes of sensorData
364
 */
365
static void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength)
366
{
367
        int i, j;
368

    
369
        // this prevents two tokens from being passed around at a time (second clause is in case we are joining)
370
        if (source != wl_token_next_robot && bom_on_count <= DEATH_DELAY / 2 &&
371
                ringState != ACCEPTED)
372
        {
373
                WL_DEBUG_PRINT("Received token pass when a robot should not have died yet.\n");
374
                WL_DEBUG_PRINT("There are probably two tokens going around, packet ignored.\n");
375
                return;
376
        }
377

    
378
        bom_on_count = -1;
379
        deathDelay = -1;
380
        WL_DEBUG_PRINT("Received the token from robot");
381
        WL_DEBUG_PRINT_INT(source);
382
        WL_DEBUG_PRINT(", next robot is ");
383
        WL_DEBUG_PRINT_INT((int)nextRobot);
384
        WL_DEBUG_PRINT(" \r\n");
385
        sensor_matrix_set_in_ring(sensorMatrix, source, 1);
386

    
387
        //with this packet, we are passed the id of the next robot in the ring
388
        //and the sensor matrix, a list of id and sensor reading pairs (two bytes for both)
389
        j = 0;
390
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
391
        {
392
                if (i == source)
393
                        continue;
394

    
395
                //set the sensor information we receive
396
                if (j < sensorDataLength / 2 && sensorData[2 * j] == i)
397
                {
398
                        //the robot we were going to accept has already been accepted
399
                        if (accepted == i)
400
                        {
401
                                accepted = -1;
402
                                WL_DEBUG_PRINT("Someone accepted the robot we did.\r\n");
403
                        }
404
                        sensor_matrix_set_reading(sensorMatrix, source, i,
405
                                                sensorData[2 * j + 1]);
406
                        sensor_matrix_set_in_ring(sensorMatrix, i, 1);
407
                        j++;
408
                }
409
                else
410
                {
411
                        if (sensor_matrix_get_in_ring(sensorMatrix, i))
412
                        {
413
                                WL_DEBUG_PRINT("Robot ");
414
                                WL_DEBUG_PRINT_INT(i);
415
                                WL_DEBUG_PRINT(" has been removed from the sensor matrix of robot ");
416
                                WL_DEBUG_PRINT_INT(wl_get_xbee_id());
417
                                WL_DEBUG_PRINT(" due to a packet from robot ");
418
                                WL_DEBUG_PRINT_INT(source);
419
                                WL_DEBUG_PRINT(".\r\n");
420
                                sensor_matrix_set_in_ring(sensorMatrix, i, 0);
421
                        }
422

    
423
                        if (i == wl_get_xbee_id() && ringState == MEMBER)
424
                        {
425
                                ringState = NONMEMBER;
426
                                wl_token_ring_join();
427

    
428
                                WL_DEBUG_PRINT("We have been removed from the ring ");
429
                                WL_DEBUG_PRINT("and are rejoining.\r\n");
430
                        }
431

    
432
                        //the person who accepted us is dead... let's ask again
433
                        if (i == acceptor)
434
                        {
435
                                sensor_matrix_set_in_ring(sensorMatrix,
436
                                                wl_get_xbee_id(), 1);
437
                                ringState = NONMEMBER;
438
                                acceptor = -1;
439
                                wl_token_ring_join();
440
                        }
441
                }
442
        }
443

    
444
        wl_token_next_robot = nextRobot;
445

    
446
        deathDelay = get_token_distance(wl_get_xbee_id(), nextRobot) * DEATH_DELAY;
447

    
448
        //we have the token
449
        if (wl_token_next_robot == wl_get_xbee_id())
450
                wl_token_get_token();
451
}
452

    
453
/**
454
 * Gets the distance in the token ring between two robots.
455
 *
456
 * @param robot1 the first robot
457
 * @param robot2 the second robot
458
 *
459
 * @return the number of passes before the token is expected
460
 * to reach robot2 from robot1
461
 **/
462
int get_token_distance(int robot1, int robot2)
463
{
464
        int curr = robot1 + 1;
465
        int count = 1;
466
        while (1)
467
        {
468
                if (curr == sensor_matrix_get_size(sensorMatrix))
469
                        curr = 0;
470
                if (curr == robot2)
471
                        break;
472
                if (sensor_matrix_get_in_ring(sensorMatrix, curr))
473
                        count++;
474
                curr++;
475
        }
476
        return count;
477
}
478

    
479
/**
480
 * Passes the token to the next robot in the token ring.
481
 **/
482
void wl_token_pass_token()
483
{
484
        char nextRobot;
485
        int i = wl_get_xbee_id() + 1;
486
        if (accepted == -1)
487
        {
488
                while (1)
489
                {
490
                        if (i == sensor_matrix_get_size(sensorMatrix))
491
                                i = 0;
492
                        if (sensor_matrix_get_in_ring(sensorMatrix, i))
493
                        {
494
                                nextRobot = (char)i;
495
                                break;
496
                        }
497
                        i++;
498
                }
499
        }
500
        else
501
        {
502
                WL_DEBUG_PRINT("Accepting new robot, sending it the token.\r\n");
503
                //add a new robot to the token ring
504
                sensor_matrix_set_in_ring(sensorMatrix, accepted, 1);
505
                nextRobot = accepted;
506
                accepted = -1;
507
        }
508

    
509
        //we don't include ourself
510
        int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
511
        char* buf = (char*)malloc(packetSize * sizeof(char));
512
        if (!buf)
513
        {
514
                WL_DEBUG_PRINT_INT(packetSize);
515
                WL_DEBUG_PRINT("Out of memory - pass token.\r\n");
516
                return;
517
        }
518
        buf[0] = nextRobot;
519

    
520
        int j = 0;
521
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
522
                if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
523
                {
524
                        buf[2*j + 1] = i;
525
                        buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
526
                        j++;
527
                }
528

    
529
        WL_DEBUG_PRINT("Passing the token to robot ");
530
        WL_DEBUG_PRINT_INT(buf[0]);
531
        WL_DEBUG_PRINT(".\r\n");
532
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
533
                buf, packetSize, 3);
534

    
535
        wl_token_next_robot = nextRobot;
536
        deathDelay = DEATH_DELAY;
537
        free(buf);
538
}
539

    
540
/**
541
 * Called when a packet is received stating that another robot has turned
542
 * its BOM on. Our BOM is then read, and the data is added to the sensor
543
 * matrix.
544
 *
545
 * @param source the robot whose BOM is on
546
 **/
547
void wl_token_bom_on_receive(int source)
548
{
549
        WL_DEBUG_PRINT("Robot ");
550
        WL_DEBUG_PRINT_INT(source);
551
        WL_DEBUG_PRINT(" has flashed its bom.\r\n");
552

    
553
        bom_on_count = 0;
554

    
555
        sensor_matrix_set_reading(sensorMatrix, wl_get_xbee_id(),
556
                source, get_max_bom_function());
557
}
558

    
559
/**
560
 * This method is called when we receive the token. Upon receiving
561
 * the token, we must send a BOM_ON packet, flash the BOM, and send
562
 * the token to the next robot.
563
 *
564
 * If there is a pending request for the token, this is processed first.
565
 **/
566
void wl_token_get_token()
567
{
568
        WL_DEBUG_PRINT("We have the token.\r\n");
569
        if (ringState == ACCEPTED)
570
        {
571
                sensor_matrix_set_in_ring(sensorMatrix,
572
                        wl_get_xbee_id(), 1);
573
                WL_DEBUG_PRINT("Now a member of the token ring.\r\n");
574
                ringState = MEMBER;
575
                joinDelay = -1;
576
        }
577

    
578
        if (ringState == LEAVING || ringState == NONMEMBER)
579
        {
580
                sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
581
                if (ringState == NONMEMBER)
582
                {
583
                        WL_DEBUG_PRINT("We should have left the token ring, but didn't.\r\n");
584
                }
585
                return;
586
        }
587

    
588
        WL_DEBUG_PRINT("Our BOM has been flashed.\r\n");
589
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
590
                NULL, 0, 0);
591

    
592
        bom_on_function();
593
        #ifdef ROBOT
594
        delay_ms(BOM_DELAY);
595
        #endif
596
        bom_off_function();
597

    
598
        if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
599
        {
600
                WL_DEBUG_PRINT("Removed from sensor matrix while flashing BOM.\r\n");
601
                return;
602
        }
603

    
604
        wl_token_pass_token();
605
}
606

    
607
/**
608
 * Called when a request to join the token ring is received.
609
 * If we are the robot preceding the requester in the ring,
610
 * we respond with a JOIN_ACCEPT packet and pass the token to
611
 * this robot when we receive the token.
612
 *
613
 * @param source the robot who requested to join
614
 **/
615
void wl_token_join_receive(int source)
616
{
617
        WL_DEBUG_PRINT("Received joining request from robot ");
618
        WL_DEBUG_PRINT_INT(source);
619
        WL_DEBUG_PRINT(".\r\n");
620

    
621
        //we cannot accept the request if we are not a member
622
        if (ringState != MEMBER)
623
                return;
624
        //if they didn't get our response, see if we should respond again
625
        if (accepted == source)
626
                accepted = -1;
627
        //we can only accept one request at a time
628
        if (accepted != -1)
629
                return;
630

    
631
        //check if we are the preceding robot in the token ring
632
        int i = source - 1;
633
        while (1)
634
        {
635
                if (i < 0)
636
                        i = sensor_matrix_get_size(sensorMatrix) - 1;
637
                //we must send a join acceptance
638
                if (i == wl_get_xbee_id())
639
                        break;
640

    
641
                //another robot will handle it
642
                if (sensor_matrix_get_in_ring(sensorMatrix, i))
643
                        return;
644
                i--;
645
        }
646

    
647
        accepted = source;
648
        wl_send_robot_to_robot_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN_ACCEPT,
649
                NULL, 0, source, TOKEN_JOIN_ACCEPT_FRAME);
650

    
651
        WL_DEBUG_PRINT("Accepting robot ");
652
        WL_DEBUG_PRINT_INT(source);
653
        WL_DEBUG_PRINT(" into the token ring.\r\n");
654

    
655
        // the token ring has not started yet
656
        if (sensor_matrix_get_joined(sensorMatrix) == 1)
657
                wl_token_pass_token();
658
}
659

    
660
/**
661
 * Called when we receive a JOIN_ACCEPT packet in attempting to join
662
 * the token ring.
663
 * Our attempt to join the ring is stopped, and we wait for the token.
664
 *
665
 * @param source the robot who accepted us
666
 **/
667
void wl_token_join_accept_receive(int source)
668
{
669
        WL_DEBUG_PRINT("Accepted into the token ring by robot ");
670
        WL_DEBUG_PRINT_INT(source);
671
        WL_DEBUG_PRINT(".\r\n");
672
        joinDelay = JOIN_DELAY;
673
        ringState = ACCEPTED;
674
        acceptor = source;
675

    
676
        //add ourselves to the token ring
677
        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
678
}
679

    
680
/**
681
 * Returns the number of robots in the token ring.
682
 *
683
 * @return the number of robots in the token ring
684
 **/
685
int wl_token_get_robots_in_ring(void)
686
{
687
        return sensor_matrix_get_joined(sensorMatrix);
688
}
689

    
690
/**
691
 * Returns true if the specified robot is in the token ring, false
692
 * otherwise.
693
 *
694
 * @param robot the robot to check for whether it is in the token ring
695
 * @return nonzero if the robot is in the token ring, zero otherwise
696
 **/
697
int wl_token_is_robot_in_ring(int robot)
698
{
699
        return sensor_matrix_get_in_ring(sensorMatrix, robot);
700
}
701

    
702
/**
703
 * Begins iterating through the robots in the token ring.
704
 *
705
 * @see wl_token_iterator_has_next, wl_token_iterator_next
706
 **/
707
void wl_token_iterator_begin(void)
708
{
709
        int i = 0;
710

    
711
        while (!sensor_matrix_get_in_ring(sensorMatrix, i) && i < sensor_matrix_get_size(sensorMatrix)) {
712
                i++;
713
        }
714

    
715
        if (i == sensor_matrix_get_size(sensorMatrix)) {
716
                i = -1;
717
        }
718

    
719
        iteratorCount = i;
720
}
721

    
722
/**
723
 * Returns true if there are more robots in the token ring
724
 * to iterate through, and false otherwise.
725
 *
726
 * @return nonzero if there are more robots to iterate through,
727
 * zero otherwise
728
 *
729
 * @see wl_token_iterator_begin, wl_token_iterator_next
730
 **/
731
int wl_token_iterator_has_next(void)
732
{
733
        return iteratorCount != -1;
734
}
735

    
736
/**
737
 * Returns the next robot ID in the token ring.
738
 *
739
 * @return the next robot ID in the token ring, or -1 if none exists
740
 *
741
 * @see wl_token_iterator_begin, wl_token_iterator_has_next
742
 **/
743
int wl_token_iterator_next(void)
744
{
745
        int result = iteratorCount;
746
        if (result < 0) {
747
                return result;
748
        }
749

    
750
        iteratorCount++;
751
        while (!sensor_matrix_get_in_ring(sensorMatrix, iteratorCount)
752
                && iteratorCount < sensor_matrix_get_size(sensorMatrix)) {
753
                iteratorCount++;
754
        }
755

    
756
        if (iteratorCount == sensor_matrix_get_size(sensorMatrix)) {
757
                iteratorCount = -1;
758
        }
759

    
760
        return result;
761
}
762

    
763
/**
764
 * Returns the number of robots currently in the token ring.
765
 *
766
 * @return the number of robots in the token ring
767
 **/
768
int wl_token_get_num_robots(void)
769
{
770
        return sensor_matrix_get_joined(sensorMatrix);
771
}
772

    
773
/**
774
 * Returns the number of robots in the sensor matrix.
775
 *
776
 * @return the number of robots in the sensor matrix
777
 **/
778
int wl_token_get_matrix_size(void)
779
{
780
        return sensor_matrix_get_size(sensorMatrix);
781
}
782