1 /*
2 * Copyright (c) 2018, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "platform-simulation.h"
30
31 #if OPENTHREAD_SIMULATION_VIRTUAL_TIME
32
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include <openthread/platform/alarm-micro.h>
38 #include <openthread/platform/alarm-milli.h>
39 #include <openthread/platform/diag.h>
40
41 #define US_PER_MS 1000
42
43 extern uint64_t sNow; // microseconds
44
45 static bool sIsMsRunning = false;
46 static uint32_t sMsAlarm = 0;
47
48 static bool sIsUsRunning = false;
49 static uint32_t sUsAlarm = 0;
50
platformAlarmInit(uint32_t aSpeedUpFactor)51 void platformAlarmInit(uint32_t aSpeedUpFactor)
52 {
53 OT_UNUSED_VARIABLE(aSpeedUpFactor);
54
55 sNow = 0;
56 }
57
platformAlarmGetNow(void)58 uint64_t platformAlarmGetNow(void)
59 {
60 return sNow;
61 }
62
platformAlarmAdvanceNow(uint64_t aDelta)63 void platformAlarmAdvanceNow(uint64_t aDelta)
64 {
65 sNow += aDelta;
66 }
67
otPlatAlarmMilliGetNow(void)68 uint32_t otPlatAlarmMilliGetNow(void)
69 {
70 return (uint32_t)(sNow / US_PER_MS);
71 }
72
otPlatAlarmMilliStartAt(otInstance * aInstance,uint32_t aT0,uint32_t aDt)73 void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
74 {
75 OT_UNUSED_VARIABLE(aInstance);
76
77 sMsAlarm = aT0 + aDt;
78 sIsMsRunning = true;
79 }
80
otPlatAlarmMilliStop(otInstance * aInstance)81 void otPlatAlarmMilliStop(otInstance *aInstance)
82 {
83 OT_UNUSED_VARIABLE(aInstance);
84
85 sIsMsRunning = false;
86 }
87
otPlatAlarmMicroGetNow(void)88 uint32_t otPlatAlarmMicroGetNow(void)
89 {
90 return (uint32_t)sNow;
91 }
92
otPlatAlarmMicroStartAt(otInstance * aInstance,uint32_t aT0,uint32_t aDt)93 void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
94 {
95 OT_UNUSED_VARIABLE(aInstance);
96
97 sUsAlarm = aT0 + aDt;
98 sIsUsRunning = true;
99 }
100
otPlatAlarmMicroStop(otInstance * aInstance)101 void otPlatAlarmMicroStop(otInstance *aInstance)
102 {
103 OT_UNUSED_VARIABLE(aInstance);
104
105 sIsUsRunning = false;
106 }
107
platformAlarmGetNext(void)108 uint64_t platformAlarmGetNext(void)
109 {
110 uint64_t remaining = INT64_MAX;
111
112 if (sIsMsRunning)
113 {
114 int32_t milli = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
115
116 if (milli < 0)
117 {
118 remaining = 0;
119 }
120 else
121 {
122 remaining = (uint64_t)milli;
123 remaining *= US_PER_MS;
124 }
125 }
126
127 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
128 if (sIsUsRunning)
129 {
130 int32_t micro = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
131
132 if (micro < 0)
133 {
134 remaining = 0;
135 }
136 else if (remaining > ((uint64_t)micro))
137 {
138 remaining = (uint64_t)micro;
139 }
140 }
141 #endif
142
143 return remaining;
144 }
145
platformAlarmProcess(otInstance * aInstance)146 void platformAlarmProcess(otInstance *aInstance)
147 {
148 int32_t remaining;
149
150 if (sIsMsRunning)
151 {
152 remaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
153
154 if (remaining <= 0)
155 {
156 sIsMsRunning = false;
157
158 #if OPENTHREAD_CONFIG_DIAG_ENABLE
159
160 if (otPlatDiagModeGet())
161 {
162 otPlatDiagAlarmFired(aInstance);
163 }
164 else
165 #endif
166 {
167 otPlatAlarmMilliFired(aInstance);
168 }
169 }
170 }
171
172 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
173
174 if (sIsUsRunning)
175 {
176 remaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
177
178 if (remaining <= 0)
179 {
180 sIsUsRunning = false;
181
182 otPlatAlarmMicroFired(aInstance);
183 }
184 }
185
186 #endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
187 }
188
otPlatTimeGet(void)189 uint64_t otPlatTimeGet(void)
190 {
191 return platformAlarmGetNow();
192 }
193
194 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
otPlatTimeGetXtalAccuracy(void)195 uint16_t otPlatTimeGetXtalAccuracy(void)
196 {
197 return 0;
198 }
199 #endif
200
201 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
202