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) { return sNow; }
59
platformAlarmAdvanceNow(uint64_t aDelta)60 void platformAlarmAdvanceNow(uint64_t aDelta) { sNow += aDelta; }
61
otPlatAlarmMilliGetNow(void)62 uint32_t otPlatAlarmMilliGetNow(void) { return (uint32_t)(sNow / US_PER_MS); }
63
otPlatAlarmMilliStartAt(otInstance * aInstance,uint32_t aT0,uint32_t aDt)64 void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
65 {
66 OT_UNUSED_VARIABLE(aInstance);
67
68 sMsAlarm = aT0 + aDt;
69 sIsMsRunning = true;
70 }
71
otPlatAlarmMilliStop(otInstance * aInstance)72 void otPlatAlarmMilliStop(otInstance *aInstance)
73 {
74 OT_UNUSED_VARIABLE(aInstance);
75
76 sIsMsRunning = false;
77 }
78
otPlatAlarmMicroGetNow(void)79 uint32_t otPlatAlarmMicroGetNow(void) { return (uint32_t)sNow; }
80
otPlatAlarmMicroStartAt(otInstance * aInstance,uint32_t aT0,uint32_t aDt)81 void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
82 {
83 OT_UNUSED_VARIABLE(aInstance);
84
85 sUsAlarm = aT0 + aDt;
86 sIsUsRunning = true;
87 }
88
otPlatAlarmMicroStop(otInstance * aInstance)89 void otPlatAlarmMicroStop(otInstance *aInstance)
90 {
91 OT_UNUSED_VARIABLE(aInstance);
92
93 sIsUsRunning = false;
94 }
95
platformAlarmGetNext(void)96 uint64_t platformAlarmGetNext(void)
97 {
98 uint64_t remaining = INT64_MAX;
99
100 if (sIsMsRunning)
101 {
102 int32_t milli = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
103
104 if (milli < 0)
105 {
106 remaining = 0;
107 }
108 else
109 {
110 remaining = (uint64_t)milli;
111 remaining *= US_PER_MS;
112 }
113 }
114
115 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
116 if (sIsUsRunning)
117 {
118 int32_t micro = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
119
120 if (micro < 0)
121 {
122 remaining = 0;
123 }
124 else if (remaining > ((uint64_t)micro))
125 {
126 remaining = (uint64_t)micro;
127 }
128 }
129 #endif
130
131 return remaining;
132 }
133
platformAlarmProcess(otInstance * aInstance)134 void platformAlarmProcess(otInstance *aInstance)
135 {
136 int32_t remaining;
137
138 if (sIsMsRunning)
139 {
140 remaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
141
142 if (remaining <= 0)
143 {
144 sIsMsRunning = false;
145
146 #if OPENTHREAD_CONFIG_DIAG_ENABLE
147
148 if (otPlatDiagModeGet())
149 {
150 otPlatDiagAlarmFired(aInstance);
151 }
152 else
153 #endif
154 {
155 otPlatAlarmMilliFired(aInstance);
156 }
157 }
158 }
159
160 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
161
162 if (sIsUsRunning)
163 {
164 remaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
165
166 if (remaining <= 0)
167 {
168 sIsUsRunning = false;
169
170 otPlatAlarmMicroFired(aInstance);
171 }
172 }
173
174 #endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
175 }
176
otPlatTimeGet(void)177 uint64_t otPlatTimeGet(void) { return platformAlarmGetNow(); }
178
179 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
otPlatTimeGetXtalAccuracy(void)180 uint16_t otPlatTimeGetXtalAccuracy(void) { return 0; }
181 #endif
182
183 #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
184