|
1 | | -""" |
2 | | -Time related functions. |
3 | | -
|
4 | | -MicroPython module: https://docs.micropython.org/en/v1.27.0/library/time.html |
5 | | -
|
6 | | -CPython module: :mod:`python:time` https://docs.python.org/3/library/time.html . |
7 | | -
|
8 | | -The ``time`` module provides functions for getting the current time and date, |
9 | | -measuring time intervals, and for delays. |
10 | | -
|
11 | | -**Time Epoch**: The unix, windows, webassembly, alif, mimxrt and rp2 ports |
12 | | -use the standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC. |
13 | | -The other embedded ports use an epoch of 2000-01-01 00:00:00 UTC. |
14 | | -Epoch year may be determined with ``gmtime(0)[0]``. |
15 | | -
|
16 | | -**Maintaining actual calendar date/time**: This requires a |
17 | | -Real Time Clock (RTC). On systems with underlying OS (including some |
18 | | -RTOS), an RTC may be implicit. Setting and maintaining actual calendar |
19 | | -time is responsibility of OS/RTOS and is done outside of MicroPython, |
20 | | -it just uses OS API to query date/time. On baremetal ports however |
21 | | -system time depends on ``machine.RTC()`` object. The current calendar time |
22 | | -may be set using ``machine.RTC().datetime(tuple)`` function, and maintained |
23 | | -by following means: |
24 | | -
|
25 | | -* By a backup battery (which may be an additional, optional component for |
26 | | - a particular board). |
27 | | -* Using networked time protocol (requires setup by a port/user). |
28 | | -* Set manually by a user on each power-up (many boards then maintain |
29 | | - RTC time across hard resets, though some may require setting it again |
30 | | - in such case). |
31 | | -
|
32 | | -If actual calendar time is not maintained with a system/MicroPython RTC, |
33 | | -functions below which require reference to current absolute time may |
34 | | -behave not as expected. |
35 | | -
|
36 | | ---- |
37 | | -Module: 'time' on micropython-v1.27.0-stm32-PYBV11-NETWORK |
38 | | -""" |
39 | | - |
40 | | -# MCU: {'variant': 'NETWORK', 'build': '', 'arch': 'armv7emsp', 'port': 'stm32', 'board': 'PYBV11', 'board_id': 'PYBV11-NETWORK', 'mpy': 'v6.3', 'ver': '1.27.0', 'family': 'micropython', 'cpu': 'STM32F405RG', 'version': '1.27.0'} |
41 | | -# Stubber: v1.26.4 |
42 | | -from __future__ import annotations |
43 | | -from _typeshed import Incomplete |
44 | | -from _mpy_shed import _TimeTuple |
45 | | -from typing import Tuple |
46 | | -from typing_extensions import Awaitable, TypeAlias, TypeVar |
47 | | - |
48 | | -_TicksMs: TypeAlias = int |
49 | | -_TicksUs: TypeAlias = int |
50 | | -_TicksCPU: TypeAlias = int |
51 | | -_Ticks = TypeVar("_Ticks", _TicksMs, _TicksUs, _TicksCPU, int) |
52 | | - |
53 | | -def ticks_diff(ticks1: _Ticks, ticks2: _Ticks, /) -> int: |
54 | | - """ |
55 | | - Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`, |
56 | | - or `ticks_cpu()` functions, as a signed value which may wrap around. |
57 | | -
|
58 | | - The argument order is the same as for subtraction |
59 | | - operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. |
60 | | - However, values returned by `ticks_ms()`, etc. functions may wrap around, so |
61 | | - directly using subtraction on them will produce incorrect result. That is why |
62 | | - `ticks_diff()` is needed, it implements modular (or more specifically, ring) |
63 | | - arithmetic to produce correct result even for wrap-around values (as long as they not |
64 | | - too distant in between, see below). The function returns **signed** value in the range |
65 | | - [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for |
66 | | - two's-complement signed binary integers). If the result is negative, it means that |
67 | | - *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that |
68 | | - *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2* |
69 | | - are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does |
70 | | - not hold, incorrect result will be returned. Specifically, if two tick values are |
71 | | - apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function. |
72 | | - However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the |
73 | | - function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around |
74 | | - to the negative range of possible values. |
75 | | -
|
76 | | - Informal rationale of the constraints above: Suppose you are locked in a room with no |
77 | | - means to monitor passing of time except a standard 12-notch clock. Then if you look at |
78 | | - dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a |
79 | | - long sleep), then once you finally look again, it may seem to you that only 1 hour |
80 | | - has passed. To avoid this mistake, just look at the clock regularly. Your application |
81 | | - should do the same. "Too long sleep" metaphor also maps directly to application |
82 | | - behaviour: don't let your application run any single task for too long. Run tasks |
83 | | - in steps, and do time-keeping in between. |
84 | | -
|
85 | | - `ticks_diff()` is designed to accommodate various usage patterns, among them: |
86 | | -
|
87 | | - * Polling with timeout. In this case, the order of events is known, and you will deal |
88 | | - only with positive results of `ticks_diff()`:: |
89 | | -
|
90 | | - # Wait for GPIO pin to be asserted, but at most 500us |
91 | | - start = time.ticks_us() |
92 | | - while pin.value() == 0: |
93 | | - if time.ticks_diff(time.ticks_us(), start) > 500: |
94 | | - raise TimeoutError |
95 | | -
|
96 | | - * Scheduling events. In this case, `ticks_diff()` result may be negative |
97 | | - if an event is overdue:: |
98 | | -
|
99 | | - # This code snippet is not optimized |
100 | | - now = time.ticks_ms() |
101 | | - scheduled_time = task.scheduled_time() |
102 | | - if ticks_diff(scheduled_time, now) > 0: |
103 | | - print("Too early, let's nap") |
104 | | - sleep_ms(ticks_diff(scheduled_time, now)) |
105 | | - task.run() |
106 | | - elif ticks_diff(scheduled_time, now) == 0: |
107 | | - print("Right at time!") |
108 | | - task.run() |
109 | | - elif ticks_diff(scheduled_time, now) < 0: |
110 | | - print("Oops, running late, tell task to run faster!") |
111 | | - task.run(run_faster=true) |
112 | | -
|
113 | | - Note: Do not pass `time()` values to `ticks_diff()`, you should use |
114 | | - normal mathematical operations on them. But note that `time()` may (and will) |
115 | | - also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem . |
116 | | - """ |
117 | | - ... |
118 | | - |
119 | | -def ticks_add(ticks: _Ticks, delta: int, /) -> _Ticks: |
120 | | - """ |
121 | | - Offset ticks value by a given number, which can be either positive or negative. |
122 | | - Given a *ticks* value, this function allows to calculate ticks value *delta* |
123 | | - ticks before or after it, following modular-arithmetic definition of tick values |
124 | | - (see `ticks_ms()` above). *ticks* parameter must be a direct result of call |
125 | | - to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous |
126 | | - call to `ticks_add()`). However, *delta* can be an arbitrary integer number |
127 | | - or numeric expression. `ticks_add()` is useful for calculating deadlines for |
128 | | - events/tasks. (Note: you must use `ticks_diff()` function to work with |
129 | | - deadlines.) |
130 | | -
|
131 | | - Examples:: |
132 | | -
|
133 | | - # Find out what ticks value there was 100ms ago |
134 | | - print(ticks_add(time.ticks_ms(), -100)) |
135 | | -
|
136 | | - # Calculate deadline for operation and test for it |
137 | | - deadline = ticks_add(time.ticks_ms(), 200) |
138 | | - while ticks_diff(deadline, time.ticks_ms()) > 0: |
139 | | - do_a_little_of_something() |
140 | | -
|
141 | | - # Find out TICKS_MAX used by this port |
142 | | - print(ticks_add(0, -1)) |
143 | | - """ |
144 | | - ... |
145 | | - |
146 | | -def ticks_cpu() -> _TicksCPU: |
147 | | - """ |
148 | | - Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution |
149 | | - in the system. This is usually CPU clocks, and that's why the function is named that |
150 | | - way. But it doesn't have to be a CPU clock, some other timing source available in a |
151 | | - system (e.g. high-resolution timer) can be used instead. The exact timing unit |
152 | | - (resolution) of this function is not specified on ``time`` module level, but |
153 | | - documentation for a specific port may provide more specific information. This |
154 | | - function is intended for very fine benchmarking or very tight real-time loops. |
155 | | - Avoid using it in portable code. |
156 | | -
|
157 | | - Availability: Not every port implements this function. |
158 | | - """ |
159 | | - ... |
160 | | - |
161 | | -def time() -> int: |
162 | | - """ |
163 | | - Returns the number of seconds, as an integer, since the Epoch, assuming that |
164 | | - underlying RTC is set and maintained as described above. If an RTC is not set, this |
165 | | - function returns number of seconds since a port-specific reference point in time (for |
166 | | - embedded boards without a battery-backed RTC, usually since power up or reset). If you |
167 | | - want to develop portable MicroPython application, you should not rely on this function |
168 | | - to provide higher than second precision. If you need higher precision, absolute |
169 | | - timestamps, use `time_ns()`. If relative times are acceptable then use the |
170 | | - `ticks_ms()` and `ticks_us()` functions. If you need calendar time, `gmtime()` or |
171 | | - `localtime()` without an argument is a better choice. |
172 | | -
|
173 | | - Admonition:Difference to CPython |
174 | | - :class: attention |
175 | | -
|
176 | | - In CPython, this function returns number of |
177 | | - seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, |
178 | | - usually having microsecond precision. With MicroPython, only Unix port |
179 | | - uses the same Epoch, and if floating-point precision allows, |
180 | | - returns sub-second precision. Embedded hardware usually doesn't have |
181 | | - floating-point precision to represent both long time ranges and subsecond |
182 | | - precision, so they use integer value with second precision. Some embedded |
183 | | - hardware also lacks battery-powered RTC, so returns number of seconds |
184 | | - since last power-up or from other relative, hardware-specific point |
185 | | - (e.g. reset). |
186 | | - """ |
187 | | - ... |
188 | | - |
189 | | -def ticks_ms() -> int: |
190 | | - """ |
191 | | - Returns an increasing millisecond counter with an arbitrary reference point, that |
192 | | - wraps around after some value. |
193 | | -
|
194 | | - The wrap-around value is not explicitly exposed, but we will |
195 | | - refer to it as *TICKS_MAX* to simplify discussion. Period of the values is |
196 | | - *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of |
197 | | - two, but otherwise may differ from port to port. The same period value is used |
198 | | - for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for |
199 | | - simplicity). Thus, these functions will return a value in range [*0* .. |
200 | | - *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only |
201 | | - non-negative values are used. For the most part, you should treat values returned |
202 | | - by these functions as opaque. The only operations available for them are |
203 | | - `ticks_diff()` and `ticks_add()` functions described below. |
204 | | -
|
205 | | - Note: Performing standard mathematical operations (+, -) or relational |
206 | | - operators (<, <=, >, >=) directly on these value will lead to invalid |
207 | | - result. Performing mathematical operations and then passing their results |
208 | | - as arguments to `ticks_diff()` or `ticks_add()` will also lead to |
209 | | - invalid results from the latter functions. |
210 | | - """ |
211 | | - ... |
212 | | - |
213 | | -def ticks_us() -> _TicksUs: |
214 | | - """ |
215 | | - Just like `ticks_ms()` above, but in microseconds. |
216 | | - """ |
217 | | - ... |
218 | | - |
219 | | -def time_ns() -> int: |
220 | | - """ |
221 | | - Similar to `time()` but returns nanoseconds since the Epoch, as an integer (usually |
222 | | - a big integer, so will allocate on the heap). |
223 | | - """ |
224 | | - ... |
225 | | - |
226 | | -def localtime(secs: int | None = None, /) -> Tuple: |
227 | | - """ |
228 | | - Convert the time *secs* expressed in seconds since the Epoch (see above) into an |
229 | | - 8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)`` |
230 | | - If *secs* is not provided or None, then the current time from the RTC is used. |
231 | | -
|
232 | | - The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a |
233 | | - date-time tuple in local time. |
234 | | -
|
235 | | - The format of the entries in the 8-tuple are: |
236 | | -
|
237 | | - * year includes the century (for example 2014). |
238 | | - * month is 1-12 |
239 | | - * mday is 1-31 |
240 | | - * hour is 0-23 |
241 | | - * minute is 0-59 |
242 | | - * second is 0-59 |
243 | | - * weekday is 0-6 for Mon-Sun |
244 | | - * yearday is 1-366 |
245 | | - """ |
246 | | - ... |
247 | | - |
248 | | -def sleep_us(us: int, /) -> None: |
249 | | - """ |
250 | | - Delay for given number of microseconds, should be positive or 0. |
251 | | -
|
252 | | - This function attempts to provide an accurate delay of at least *us* |
253 | | - microseconds, but it may take longer if the system has other higher priority |
254 | | - processing to perform. |
255 | | - """ |
256 | | - ... |
257 | | - |
258 | | -def gmtime(secs: int | None = None, /) -> Tuple: |
259 | | - """ |
260 | | - Convert the time *secs* expressed in seconds since the Epoch (see above) into an |
261 | | - 8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)`` |
262 | | - If *secs* is not provided or None, then the current time from the RTC is used. |
263 | | -
|
264 | | - The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a |
265 | | - date-time tuple in local time. |
266 | | -
|
267 | | - The format of the entries in the 8-tuple are: |
268 | | -
|
269 | | - * year includes the century (for example 2014). |
270 | | - * month is 1-12 |
271 | | - * mday is 1-31 |
272 | | - * hour is 0-23 |
273 | | - * minute is 0-59 |
274 | | - * second is 0-59 |
275 | | - * weekday is 0-6 for Mon-Sun |
276 | | - * yearday is 1-366 |
277 | | - """ |
278 | | - ... |
279 | | - |
280 | | -def sleep_ms(ms: int, /) -> None: |
281 | | - """ |
282 | | - Delay for given number of milliseconds, should be positive or 0. |
283 | | -
|
284 | | - This function will delay for at least the given number of milliseconds, but |
285 | | - may take longer than that if other processing must take place, for example |
286 | | - interrupt handlers or other threads. Passing in 0 for *ms* will still allow |
287 | | - this other processing to occur. Use `sleep_us()` for more precise delays. |
288 | | - """ |
289 | | - ... |
290 | | - |
291 | | -def mktime(local_time: _TimeTuple, /) -> int: |
292 | | - """ |
293 | | - This is inverse function of localtime. It's argument is a full 8-tuple |
294 | | - which expresses a time as per localtime. It returns an integer which is |
295 | | - the number of seconds since the time epoch. |
296 | | - """ |
297 | | - ... |
298 | | - |
299 | | -def sleep(seconds: float, /) -> None: |
300 | | - """ |
301 | | - Sleep for the given number of seconds. Some boards may accept *seconds* as a |
302 | | - floating-point number to sleep for a fractional number of seconds. Note that |
303 | | - other boards may not accept a floating-point argument, for compatibility with |
304 | | - them use `sleep_ms()` and `sleep_us()` functions. |
305 | | - """ |
306 | | - ... |
| 1 | +""" |
| 2 | +MicroPython time module stub (self-contained, no external dependencies). |
| 3 | +
|
| 4 | +Overrides the CPython typeshed stub to add MicroPython-specific functions |
| 5 | +like sleep_ms(), sleep_us(), ticks_ms(), ticks_us(), ticks_cpu(), etc. |
| 6 | +""" |
| 7 | + |
| 8 | +from typing import Tuple |
| 9 | + |
| 10 | +def sleep(seconds: float, /) -> None: ... |
| 11 | +def sleep_ms(ms: int, /) -> None: ... |
| 12 | +def sleep_us(us: int, /) -> None: ... |
| 13 | +def ticks_ms() -> int: ... |
| 14 | +def ticks_us() -> int: ... |
| 15 | +def ticks_cpu() -> int: ... |
| 16 | +def ticks_diff(ticks1: int, ticks2: int, /) -> int: ... |
| 17 | +def ticks_add(ticks: int, delta: int, /) -> int: ... |
| 18 | +def time() -> int: ... |
| 19 | +def time_ns() -> int: ... |
| 20 | +def localtime(secs: int | None = None, /) -> Tuple: ... |
| 21 | +def gmtime(secs: int | None = None, /) -> Tuple: ... |
| 22 | +def mktime(local_time: Tuple, /) -> int: ... |
0 commit comments