-
Notifications
You must be signed in to change notification settings - Fork 2
/
SlotSchedulerP.nc
92 lines (73 loc) · 2.33 KB
/
SlotSchedulerP.nc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <Timer.h>
generic module SlotSchedulerP(uint32_t slotDuration, uint8_t maxSlotId) {
provides interface SlotScheduler;
uses {
interface Timer<T32khz> as EpochTimer;
interface Timer<T32khz> as SlotTimer;
}
} implementation {
//Defined at compile time
uint32_t epochDuration = slotDuration * ((uint16_t) maxSlotId + 1);
bool isStarted = FALSE;
bool isSlotActive = FALSE;
uint32_t epoch_reference_time;
uint8_t schedSlot;
command error_t SlotScheduler.start(uint32_t epoch_time, uint8_t firstSlot) {
if(isStarted == TRUE) {
return EALREADY;
} if(firstSlot > maxSlotId)
return FAIL;
isStarted = TRUE;
schedSlot = firstSlot;
epoch_reference_time = epoch_time;
call SlotTimer.startOneShotAt(epoch_time, slotDuration * firstSlot);
call EpochTimer.startPeriodicAt(epoch_time, epochDuration);
return SUCCESS;
}
command bool SlotScheduler.isRunning() {
return isStarted;
}
command error_t SlotScheduler.stop() {
bool wasStarted = isStarted;
call SlotTimer.stop();
call EpochTimer.stop();
isStarted = FALSE;
return (wasStarted) ? EALREADY : SUCCESS;
}
command void SlotScheduler.syncEpochTime(uint32_t reference_time) {
epoch_reference_time = reference_time;
call EpochTimer.startPeriodicAt(reference_time, epochDuration);
}
command uint32_t SlotScheduler.getEpochTime() {
return epoch_reference_time;
}
command uint8_t SlotScheduler.getScheduledSlot() {
return schedSlot;
}
event void EpochTimer.fired() {
epoch_reference_time += epochDuration;
}
event void SlotTimer.fired() {
uint8_t nextSlot;
if(!isSlotActive) {
isSlotActive = TRUE;
call SlotTimer.startOneShot(slotDuration);
signal SlotScheduler.slotStarted(schedSlot);
return;
}
isSlotActive = FALSE;
nextSlot = signal SlotScheduler.slotEnded(schedSlot);
//If scheduler is not running don't schedule other slots
if(!isStarted)
return;
//Next slot in the same epoch or current and next slot are one just after the other between current and next epoch
if (nextSlot > schedSlot || (schedSlot == maxSlotId && nextSlot == 0)) {
schedSlot = nextSlot;
call SlotTimer.startOneShotAt(epoch_reference_time, slotDuration * schedSlot);
} else {
//Next slot is in next epoch
schedSlot = nextSlot;
call SlotTimer.startOneShotAt(epoch_reference_time + epochDuration, slotDuration * schedSlot);
}
}
}