Project

General

Profile

Statistics
| Revision:

root / branches / autonomous_recharging / code / projects / autonomous_recharging / charging_station / wl_token_ring.c @ 120

History | View | Annotate | Download (21 KB)

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
#ifndef FIREFLY
13
#include <bom.h>
14
#endif
15
#include <time.h>
16
#endif
17

    
18
#define DEFAULT_SENSOR_MATRIX_SIZE 20
19

    
20
/*Ring States*/
21

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

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

    
31
/*Function Prototypes*/
32

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

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

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

    
53
/*Global Variables*/
54

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

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

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

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

    
75
//current robot to check in the iterator
76
int iteratorCount = 0;
77

    
78
void do_nothing(void) {}
79
int get_nothing(void) {return -1;}
80

    
81
#ifdef ROBOT
82
#ifndef FIREFLY
83
void (*bom_on_function) (void) = bom_on;
84
void (*bom_off_function) (void) = bom_off;
85
int (*get_max_bom_function) (void) = get_max_bom;
86
#else
87
void (*bom_on_function) (void) = do_nothing;
88
void (*bom_off_function) (void) = do_nothing;
89
int (*get_max_bom_function) (void) = get_nothing;
90
#endif
91
#else
92
void (*bom_on_function) (void) = do_nothing;
93
void (*bom_off_function) (void) = do_nothing;
94
int (*get_max_bom_function) (void) = get_nothing;
95
#endif
96

    
97
PacketGroupHandler wl_token_ring_handler =
98
                {WL_TOKEN_RING_GROUP, wl_token_ring_timeout_handler,
99
                wl_token_ring_response_handler, wl_token_ring_receive_handler,
100
                wl_token_ring_cleanup};
101

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

    
123
        wl_register_packet_group(&wl_token_ring_handler);
124
}
125

    
126
/**
127
 * Removes the packet group from the wireless library.
128
 **/
129
void wl_token_ring_unregister()
130
{
131
        wl_unregister_packet_group(&wl_token_ring_handler);
132
}
133

    
134
/**
135
 * Sets the functions that are called when the BOM ought to be
136
 * turned on or off. This could be used for things such as 
137
 * charging stations, which have multiple BOMs.
138
 *
139
 * @param on_function the function to be called when the BOM
140
 * should be turned on
141
 * @param off_function the function to be called when the BOM
142
 * should be turned off
143
 * @param max_bom_function the function to be called when a
144
 * measurement of the maximum BOM reading is needed.
145
 **/
146
void wl_token_ring_set_bom_functions(void (*on_function) (void),
147
        void (*off_function) (void), int (*max_bom_function) (void))
148
{
149
        bom_on_function = on_function;
150
        bom_off_function = off_function;
151
        get_max_bom_function = max_bom_function;
152
}
153

    
154
/**
155
 * Called to cleanup the token ring packet group.
156
 **/
157
void wl_token_ring_cleanup()
158
{
159
        sensor_matrix_destroy(sensorMatrix);
160
        queue_destroy(interrupting);
161
}
162

    
163
/**
164
 * Called approximately every quarter second by the wireless library.
165
 **/
166
void wl_token_ring_timeout_handler()
167
{
168
        //someone is not responding, assume they are dead
169
        if (deathDelay == 0)
170
        {
171
                //pass the token to the next robot if we think someone has died
172
                //also, declare that person dead, as long as it isn't us
173
                if (wl_token_next_robot != wl_get_xbee_id())
174
                {
175
                        sensor_matrix_set_in_ring(sensorMatrix, wl_token_next_robot, 0);
176
                        WL_DEBUG_PRINT("Robot ");
177
                        WL_DEBUG_PRINT_INT(wl_token_next_robot);
178
                        WL_DEBUG_PRINT(" has died.\r\n");
179
                }
180
                
181
                // we may have been dropped from the ring when this is received
182
                if (ringState == MEMBER)
183
                        wl_token_pass_token();
184
        }
185

    
186
        //we must start our own token ring, no one is responding to us
187
        if (joinDelay == 0)
188
        {
189
                if (sensor_matrix_get_joined(sensorMatrix) == 0)
190
                {
191
                        WL_DEBUG_PRINT("Creating our own token ring, no robots seem to exist.\r\n");
192
                        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
193
                        ringState = MEMBER;
194
                        //this will make us pass the token to ourself
195
                        //repeatedly, and other robots when they join
196
                        deathDelay = DEATH_DELAY;
197
                        wl_token_next_robot = wl_get_xbee_id();
198
                }
199
                else
200
                {
201
                        WL_DEBUG_PRINT("Attempting to join the token ring again.\r\n");
202
                        //attempt to rejoin with a random delay
203
                        wl_token_ring_join();
204
                        joinDelay = rand() / (RAND_MAX / JOIN_DELAY) + 1;
205
                }
206
        }
207

    
208
        if (deathDelay >= 0)
209
                deathDelay--;
210
        if (joinDelay >= 0)
211
                joinDelay--;
212
}
213

    
214
/**
215
 * Called when the XBee tells us if a packet we sent has been received.
216
 * 
217
 * @param frame the frame number assigned when the packet was sent
218
 * @param received 1 if the packet was received, 0 otherwise
219
 **/
220
void wl_token_ring_response_handler(int frame, int received)
221
{
222
        if (!received)
223
        {
224
                WL_DEBUG_PRINT("FAILED.\r\n");
225
        }
226
}
227

    
228
/**
229
 * Called when we recieve a token ring packet.
230
 * @param type the type of the packet
231
 * @param source the id of the robot who sent the packet
232
 * @param packet the data in the packet
233
 * @param length the length of the packet in bytes
234
 **/
235
void wl_token_ring_receive_handler(char type, int source, unsigned char* packet,
236
                                                        int length)
237
{
238
        switch (type)
239
        {
240
                case WL_TOKEN_PASS:
241
                        usb_puts("received token pass from robot\n");
242
                        if (length < 1)
243
                        {
244
                                WL_DEBUG_PRINT("Malformed Token Pass packet received.\r\n");
245
                                return;
246
                        }
247
                        wl_token_pass_receive(source, packet[0], packet + 1, length - 1);
248
                        break;
249
                case WL_TOKEN_BOM_ON:
250
                        usb_puts("received bom on from robot\n");
251
                        //add the robot to the sensor matrix if it is not already there
252
                        wl_token_bom_on_receive(source);
253
                        break;
254
                case WL_TOKEN_INTERRUPT_REQUEST:
255
                        wl_token_interrupt_request_receive(source, packet[0]);
256
                        break;
257
                case WL_TOKEN_INTERRUPT_PASS:
258
                        wl_token_interrupt_pass_receive(source, packet[0]);
259
                        break;
260
                case WL_TOKEN_JOIN:
261
                        wl_token_join_receive(source);
262
                        break;
263
                case WL_TOKEN_JOIN_ACCEPT:
264
                        wl_token_join_accept_receive(source);
265
                        break;
266
                default:
267
                        WL_DEBUG_PRINT("Unimplemented token ring packet received.\r\n");
268
                        break;
269
        }
270
}
271

    
272
/**
273
 * Causes the robot to join an existing token ring, or create one
274
 * if no token ring exists. The token ring uses global and robot to robot
275
 * packets, and does not rely on any PAN.
276
 **/
277
void wl_token_ring_join()
278
{
279
        WL_DEBUG_PRINT("Joining the token ring.\r\n");
280
        ringState = JOINING;
281
        joinDelay = JOIN_DELAY;
282
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN,
283
                NULL, 0, 0);
284
}
285

    
286
/**
287
 * Causes the robot to leave the token ring. The robot stops
288
 * alerting others of its location, but continues storing the
289
 * locations of other robots.
290
 **/
291
void wl_token_ring_leave()
292
{
293
        ringState = LEAVING;
294
}
295

    
296
/**
297
 * Requests that the specified robot be given the token and
298
 * allowed to flash its BOM. After its BOM is flashed, the
299
 * token will return to the robot who sent it.
300
 *
301
 * @param robot the ID of the robot which should flash its BOM
302
 **/
303
void wl_token_request(int robot)
304
{
305
        char buf[1];
306
        buf[0] = robot;
307
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_INTERRUPT_REQUEST,
308
                buf, 1, 0);
309
}
310

    
311
/**
312
 * Returns the BOM reading robot source has for robot dest.
313
 *
314
 * @param source the robot that made the BOM reading
315
 * @param dest the robot whose relative location is returned
316
 *
317
 * @return a BOM reading from robot source to robot dest,
318
 * in the range 0-15, or -1 if it is unknown
319
 **/
320
int wl_token_get_sensor_reading(int source, int dest)
321
{
322
        return sensor_matrix_get_reading(sensorMatrix, source, dest);
323
}
324

    
325
/**
326
 * Returns the BOM reading we have for robot dest.
327
 * 
328
 * @param dest the robot whose relative location is returned
329
 *
330
 * @return a BOM reading from us to robot dest, in the range
331
 * 0-15, or -1 if it is unkown
332
 **/
333
int wl_token_get_my_sensor_reading(int dest)
334
{
335
        return wl_token_get_sensor_reading(wl_get_xbee_id(), dest);
336
}
337

    
338
/**
339
 * This method is called when we receive a token pass packet.
340
 * @param source is the robot it came from
341
 * @param nextRobot is the robot the token was passed to
342
 * @param sensorData a char with an id followed by a char with the sensor
343
 *                reading for that robot, repeated for sensorDataLength bytes
344
 * @param sensorDataLength the length in bytes of sensorData
345
 */
346
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength)
347
{
348
        int i, j;
349
        deathDelay = -1;
350

    
351
        WL_DEBUG_PRINT("Received the token, next robot is ");
352
        WL_DEBUG_PRINT_INT((int)nextRobot);
353
        WL_DEBUG_PRINT(" \r\n");
354
        sensor_matrix_set_in_ring(sensorMatrix, source, 1);
355

    
356
        //with this packet, we are passed the id of the next robot in the ring
357
        //and the sensor matrix, a list of id and sensor reading pairs (two bytes for both)
358
        j = 0;
359
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
360
        {
361
                if (i == source)
362
                        continue;
363
                
364
                //set the sensor information we receive
365
                if (j < sensorDataLength / 2 && sensorData[2 * j] == i)
366
                {
367
                        //the robot we were going to accept has already been accepted
368
                        if (accepted == i)
369
                        {
370
                                accepted = -1;
371
                                WL_DEBUG_PRINT("Someone accepted the robot we did.\r\n");
372
                        }
373
                        sensor_matrix_set_reading(sensorMatrix, source, i,
374
                                                sensorData[2 * j + 1]);
375
                        sensor_matrix_set_in_ring(sensorMatrix, i, 1);
376
                        j++;
377
                }
378
                else
379
                {
380
                        if (sensor_matrix_get_in_ring(sensorMatrix, i))
381
                        {
382
                                WL_DEBUG_PRINT("Robot ");
383
                                WL_DEBUG_PRINT_INT(i);
384
                                WL_DEBUG_PRINT(" has been removed from the sensor matrix of robot ");
385
                                WL_DEBUG_PRINT_INT(wl_get_xbee_id());
386
                                WL_DEBUG_PRINT(" due to a packet from robot ");
387
                                WL_DEBUG_PRINT_INT(source);
388
                                WL_DEBUG_PRINT(".\r\n");
389
                                sensor_matrix_set_in_ring(sensorMatrix, i, 0);
390
                        }
391

    
392
                        if (i == wl_get_xbee_id() && ringState == MEMBER)
393
                        {
394
                                ringState = NONMEMBER;
395
                                wl_token_ring_join();
396
                                
397
                                WL_DEBUG_PRINT("We have been removed from the ring ");
398
                                WL_DEBUG_PRINT("and are rejoining.\r\n");
399
                        }
400
                        
401
                        //the person who accepted us is dead... let's ask again
402
                        if (i == acceptor)
403
                        {
404
                                sensor_matrix_set_in_ring(sensorMatrix,
405
                                                wl_get_xbee_id(), 1);
406
                                ringState = NONMEMBER;
407
                                acceptor = -1;
408
                                wl_token_ring_join();
409
                        }
410
                }
411
        }
412

    
413
        wl_token_next_robot = nextRobot;
414
        
415
        deathDelay = get_token_distance(wl_get_xbee_id(), nextRobot) * DEATH_DELAY;
416
        
417
        //we have the token
418
        if (wl_token_next_robot == wl_get_xbee_id())
419
                wl_token_get_token();
420
}
421

    
422
/**
423
 * Gets the distance in the token ring between two robots.
424
 *
425
 * @param robot1 the first robot
426
 * @param robot2 the second robot
427
 *
428
 * @return the number of passes before the token is expected
429
 * to reach robot2 from robot1
430
 **/
431
int get_token_distance(int robot1, int robot2)
432
{
433
        int curr = robot1 + 1;
434
        int count = 1;
435
        while (1)
436
        {
437
                if (curr == sensor_matrix_get_size(sensorMatrix))
438
                        curr = 0;
439
                if (curr == robot2)
440
                        break;
441
                if (sensor_matrix_get_in_ring(sensorMatrix, curr))
442
                        count++;
443
                curr++;
444
        }
445
        return count;
446
}
447

    
448
/**
449
 * Passes the token to the next robot in the token ring.
450
 **/
451
void wl_token_pass_token()
452
{
453
        char nextRobot;
454
        int i = wl_get_xbee_id() + 1;
455
        if (accepted == -1)
456
        {
457
                while (1)
458
                {
459
                        if (i == sensor_matrix_get_size(sensorMatrix))
460
                                i = 0;
461
                        if (sensor_matrix_get_in_ring(sensorMatrix, i))
462
                        {
463
                                nextRobot = (char)i;
464
                                break;
465
                        }
466
                        i++;
467
                }
468
        }
469
        else
470
        {
471
                WL_DEBUG_PRINT("Accepting new robot, sending it the token.\r\n");
472
                //add a new robot to the token ring
473
                sensor_matrix_set_in_ring(sensorMatrix, accepted, 1);
474
                nextRobot = accepted;
475
                accepted = -1;
476
        }
477

    
478
        //we don't include ourself
479
        int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
480
        char* buf = (char*)malloc(packetSize * sizeof(char));
481
        if (!buf)
482
        {
483
                WL_DEBUG_PRINT_INT(packetSize);
484
                WL_DEBUG_PRINT("Out of memory - pass token.\r\n");
485
                return;
486
        }
487
        buf[0] = nextRobot;
488

    
489
        int j = 0;
490
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
491
                if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
492
                {
493
                        buf[2*j + 1] = i;
494
                        buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
495
                        j++;
496
                }
497
        
498
        WL_DEBUG_PRINT("Passing the token to robot ");
499
        WL_DEBUG_PRINT_INT(buf[0]);
500
        WL_DEBUG_PRINT(".\r\n");
501
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
502
                buf, packetSize, 3);
503

    
504
        wl_token_next_robot = nextRobot;
505
        deathDelay = DEATH_DELAY;
506
        free(buf);
507
}
508

    
509
/**
510
 * Called when a packet is received stating that another robot has turned
511
 * its BOM on. Our BOM is then read, and the data is added to the sensor
512
 * matrix.
513
 *
514
 * @param source the robot whose BOM is on
515
 **/
516
void wl_token_bom_on_receive(int source)
517
{
518
        WL_DEBUG_PRINT("Robot ");
519
        WL_DEBUG_PRINT_INT(source);
520
        WL_DEBUG_PRINT(" has flashed its bom.\r\n");
521
        sensor_matrix_set_reading(sensorMatrix, wl_get_xbee_id(), 
522
                source, get_max_bom_function());
523
}
524

    
525
/**
526
 * This method is called when we receive the token. Upon receiving
527
 * the token, we must send a BOM_ON packet, flash the BOM, and send
528
 * the token to the next robot.
529
 * 
530
 * If there is a pending request for the token, this is processed first.
531
 **/
532
void wl_token_get_token()
533
{
534
        WL_DEBUG_PRINT("We have the token.\r\n");
535
        if (ringState == ACCEPTED)
536
        {
537
                sensor_matrix_set_in_ring(sensorMatrix,
538
                        wl_get_xbee_id(), 1);
539
                WL_DEBUG_PRINT("Now a member of the token ring.\r\n");
540
                ringState = MEMBER;
541
        }
542

    
543
        if (ringState == LEAVING || ringState == NONMEMBER)
544
        {
545
                sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
546
                if (ringState == NONMEMBER)
547
                {
548
                        WL_DEBUG_PRINT("We should have left the token ring, but didn't.\r\n");
549
                }
550
                return;
551
        }
552
        
553
        //check for interruption requests
554
        if (queue_size(interrupting) > 0)
555
        {
556
                char buf[1];
557
                buf[0] = (char)(int)queue_remove(interrupting);
558
                
559
                //in case this robot has requested multiple times
560
                queue_remove_all(interrupting, (void*)(int)buf[0]);
561

    
562
                wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_INTERRUPT_PASS,
563
                        buf, 1, 0);
564

    
565
                deathDelay = DEATH_DELAY;
566
                wl_token_next_robot = buf[0];
567
                return;
568
        }
569

    
570
        WL_DEBUG_PRINT("Our BOM has been flashed.\r\n");
571
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
572
                NULL, 0, 0);
573

    
574
        bom_on_function();
575
        #ifdef ROBOT
576
        delay_ms(BOM_DELAY);
577
        #endif
578
        bom_off_function();
579
        
580
        if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
581
        {
582
                WL_DEBUG_PRINT("Removed from sensor matrix while flashing BOM.\r\n");
583
        }
584
        
585
        wl_token_pass_token();
586
}
587

    
588
/**
589
 * Called when a request to join the token ring is received.
590
 * If we are the robot preceding the requester in the ring,
591
 * we respond with a JOIN_ACCEPT packet and pass the token to
592
 * this robot when we receive the token.
593
 *
594
 * @param source the robot who requested to join
595
 **/
596
void wl_token_join_receive(int source)
597
{
598
        WL_DEBUG_PRINT("Received joining request from robot ");
599
        WL_DEBUG_PRINT_INT(source);
600
        WL_DEBUG_PRINT(".\r\n");
601

    
602
        //we cannot accept the request if we are not a member
603
        if (ringState != MEMBER)
604
                return;
605
        //if they didn't get our response, see if we should respond again
606
        if (accepted == source)
607
                accepted = -1;
608
        //we can only accept one request at a time
609
        if (accepted != -1)
610
                return;
611
        
612
        //check if we are the preceding robot in the token ring
613
        int i = source - 1;
614
        while (1)
615
        {
616
                if (i < 0)
617
                        i = sensor_matrix_get_size(sensorMatrix) - 1;
618
                //we must send a join acceptance
619
                if (i == wl_get_xbee_id())
620
                        break;
621

    
622
                //another robot will handle it
623
                if (sensor_matrix_get_in_ring(sensorMatrix, i))
624
                        return;
625
                i--;
626
        }
627

    
628
        accepted = source;
629
        wl_send_robot_to_robot_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN_ACCEPT,
630
                NULL, 0, source, TOKEN_JOIN_ACCEPT_FRAME);
631
        
632
        WL_DEBUG_PRINT("Accepting robot ");
633
        WL_DEBUG_PRINT_INT(source);
634
        WL_DEBUG_PRINT(" into the token ring.\r\n");
635

    
636
        joinDelay = -1;
637
        
638
        // the token ring has not started yet
639
        if (sensor_matrix_get_joined(sensorMatrix) == 1)
640
                wl_token_pass_token();
641
}
642

    
643
/**
644
 * Called when we receive a JOIN_ACCEPT packet in attempting to join
645
 * the token ring.
646
 * Our attempt to join the ring is stopped, and we wait for the token.
647
 *
648
 * @param source the robot who accepted us
649
 **/
650
void wl_token_join_accept_receive(int source)
651
{
652
        WL_DEBUG_PRINT("Accepted into the token ring by robot ");
653
        WL_DEBUG_PRINT_INT(source);
654
        WL_DEBUG_PRINT(".\r\n");
655
        joinDelay = -1;
656
        ringState = ACCEPTED;
657
        acceptor = source;
658

    
659
        //add ourselves to the token ring
660
        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
661
}
662

    
663
/**
664
 * Called when we receive a packet passing the token and interrupting
665
 * the token ring.
666
 * If the token has been passed to us, we flash our BOM
667
 * and pass it back.
668
 *
669
 * @param source the robot who sent the interrupt packet
670
 * @param robot the robot the token has been passed to
671
 **/
672
void wl_token_interrupt_pass_receive(int source, int robot)
673
{
674
        if (wl_get_xbee_id() != robot)
675
        {
676
                queue_remove_all(interrupting, (void*)robot);
677
                wl_token_next_robot = robot;
678
                deathDelay = DEATH_DELAY + rand() / (RAND_MAX / (2 * DEATH_DELAY));
679
                return;
680
        }
681
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
682
                NULL, 0, 0);
683
        
684
        bom_on_function();
685
        #ifdef ROBOT
686
        delay_ms(BOM_DELAY);
687
        #endif
688
        bom_off_function();
689

    
690
        //we don't include ourself, only if we are in the ring
691
        int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
692
        if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
693
                packetSize += 2;
694
        char* buf = (char*)malloc(packetSize * sizeof(char));
695
        if (!buf)
696
        {
697
                WL_DEBUG_PRINT("Out of memory - pass_receive.\r\n");
698
                return;
699
        }
700
        
701
        //return the token to where we got it from
702
        buf[0] = source;
703

    
704
        int i = 0, j = 0;
705
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
706
                if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
707
                {
708
                        buf[2*j + 1] = i;
709
                        buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
710
                        j++;
711
                }
712
        
713
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
714
                buf, packetSize, 0);
715

    
716
        wl_token_next_robot = source;
717
        deathDelay = DEATH_DELAY;
718
        free(buf);
719
}
720

    
721
/**
722
 * Returns the number of robots in the token ring.
723
 *
724
 * @return the number of robots in the token ring
725
 **/
726
int wl_token_get_robots_in_ring(void)
727
{
728
        return sensor_matrix_get_joined(sensorMatrix);
729
}
730

    
731
/**
732
 * Returns true if the specified robot is in the token ring, false
733
 * otherwise.
734
 *
735
 * @param robot the robot to check for whether it is in the token ring
736
 * @return nonzero if the robot is in the token ring, zero otherwise
737
 **/
738
int wl_token_is_robot_in_ring(int robot)
739
{
740
        return sensor_matrix_get_in_ring(sensorMatrix, robot);
741
}
742

    
743
/**
744
 * Begins iterating through the robots in the token ring.
745
 *
746
 * @see wl_token_iterator_has_next, wl_token_iterator_next
747
 **/
748
void wl_token_iterator_begin(void)
749
{
750
        int i = 0;
751
        iteratorCount = 0;
752
        while (!sensor_matrix_get_in_ring(sensorMatrix, i) &&
753
                        i < sensor_matrix_get_size(sensorMatrix))
754
                i++;
755
        if (i == sensor_matrix_get_size(sensorMatrix))
756
                i = -1;
757
}
758

    
759
/**
760
 * Returns true if there are more robots in the token ring
761
 * to iterate through, and false otherwise.
762
 *
763
 * @return nonzero if there are more robots to iterate through,
764
 * zero otherwise
765
 *
766
 * @see wl_token_iterator_begin, wl_token_iterator_next
767
 **/
768
int wl_token_iterator_has_next(void)
769
{
770
        return iteratorCount == -1;
771
}
772

    
773
/**
774
 * Returns the next robot ID in the token ring.
775
 *
776
 * @return the next robot ID in the token ring, or -1 if none exists
777
 *
778
 * @see wl_token_iterator_begin, wl_token_iterator_has_next
779
 **/
780
int wl_token_iterator_next(void)
781
{
782
        int result = iteratorCount;
783
        if (result < 0)
784
                return result;
785

    
786
        iteratorCount++;
787
        while (!sensor_matrix_get_in_ring(sensorMatrix, iteratorCount) &&
788
                iteratorCount < sensor_matrix_get_size(sensorMatrix))
789
                iteratorCount++;
790
        if (iteratorCount == sensor_matrix_get_size(sensorMatrix))
791
                iteratorCount = -1;
792
        return result;
793
}
794

    
795
/**
796
 * Called when we receive a request to interrupt the token ring.
797
 * We add the robot to our list of interrupt requests,
798
 * and will send the token to this robot when we next receive the
799
 * token, unless someone else does so first.
800
 *
801
 * @param source the robot requesting interruption
802
 * @param robt the robot requested to interrupt the token ring
803
 **/
804
void wl_token_interrupt_request_receive(int source, int robot)
805
{
806
        queue_add(interrupting, (void*)robot);
807
}
808

    
809
int wl_token_get_num_robots(void){
810
  return sensor_matrix_get_joined(sensorMatrix);
811
}
812

    
813
int wl_token_get_matrix_size(void){
814
  return sensor_matrix_get_size(sensorMatrix);
815
}