29
29
import time
30
30
from random import randint
31
31
from micropython import const
32
+ from adafruit_ticks import ticks_ms , ticks_diff , ticks_add
32
33
from adafruit_wiznet5k .adafruit_wiznet5k_debug import ( # pylint: disable=ungrouped-imports
33
34
debug_msg ,
34
35
)
@@ -152,6 +153,7 @@ def __init__(
152
153
self ._dhcp_state = _STATE_INIT
153
154
self ._transaction_id = randint (1 , 0x7FFFFFFF )
154
155
self ._start_time = 0.0
156
+ self ._start_ticks = 0
155
157
self ._blocking = False
156
158
self ._renew = None
157
159
@@ -209,13 +211,14 @@ def _dsm_reset(self) -> None:
209
211
self ._renew = None
210
212
self ._increment_transaction_id ()
211
213
self ._start_time = time .monotonic ()
214
+ self ._start_ticks = ticks_ms ()
212
215
213
216
def _increment_transaction_id (self ) -> None :
214
217
"""Increment the transaction ID and roll over from 0x7fffffff to 0."""
215
218
debug_msg ("Incrementing transaction ID" , self ._debug )
216
219
self ._transaction_id = (self ._transaction_id + 1 ) & 0x7FFFFFFF
217
220
218
- def _next_retry_time (self , * , attempt : int , interval : int = 4 ) -> float :
221
+ def _next_retry_time (self , * , attempt : int , interval : int = 4 ) -> int :
219
222
"""Calculate a retry stop time.
220
223
221
224
The interval is calculated as an exponential fallback with a random variation to
@@ -227,18 +230,18 @@ def _next_retry_time(self, *, attempt: int, interval: int = 4) -> float:
227
230
:param int interval: The base retry interval in seconds. Defaults to 4 as per the
228
231
DHCP standard for Ethernet connections. Minimum value 2, defaults to 4.
229
232
230
- :returns float : The timeout in time.monotonic() seconds .
233
+ :returns int : The timeout in ticks_ms milliseconds .
231
234
232
235
:raises ValueError: If the interval is not > 1 second as this could return a zero or
233
236
negative delay.
234
237
"""
235
238
debug_msg ("Calculating next retry time and incrementing retries." , self ._debug )
236
239
if interval <= 1 :
237
240
raise ValueError ("Retry interval must be > 1 second." )
238
- delay = 2 ** attempt * interval + randint (- 1 , 1 ) + time . monotonic ()
241
+ delay = ( 2 ** attempt * interval + randint (- 1 , 1 )) * 1000
239
242
return delay
240
243
241
- def _receive_dhcp_response (self , socket_num : int , timeout : float ) -> int :
244
+ def _receive_dhcp_response (self , socket_num : int , timeout : int ) -> int :
242
245
"""
243
246
Receive data from the socket in response to a DHCP query.
244
247
@@ -249,12 +252,13 @@ def _receive_dhcp_response(self, socket_num: int, timeout: float) -> int:
249
252
maximum packet size is limited by the size of the global buffer.
250
253
251
254
:param int socket_num: Socket to read from.
252
- :param float timeout: time.monotonic at which attempt should time out.
255
+ :param int timeout: ticks_ms interval at which attempt should time out.
253
256
254
257
:returns int: The number of bytes stored in the global buffer.
255
258
"""
256
259
debug_msg ("Receiving a DHCP response." , self ._debug )
257
- while time .monotonic () < timeout :
260
+ start_time = ticks_ms ()
261
+ while ticks_diff (ticks_ms (), start_time ) < timeout :
258
262
# DHCP returns the query plus additional data. The query length is 236 bytes.
259
263
if self ._eth .socket_available (socket_num , _SNMR_UDP ) > 236 :
260
264
bytes_count , bytes_read = self ._eth .read_udp (socket_num , _BUFF_LENGTH )
@@ -285,9 +289,11 @@ def _process_messaging_states(self, *, message_type: int):
285
289
self ._dhcp_state = _STATE_INIT
286
290
elif message_type == _DHCP_ACK :
287
291
debug_msg ("Message is ACK, setting FSM state to BOUND." , self ._debug )
288
- self ._t1 = self ._start_time + self ._lease // 2
289
- self ._t2 = self ._start_time + self ._lease - self ._lease // 8
290
- self ._lease += self ._start_time
292
+ self ._t1 = ticks_add (self ._start_ticks , self ._lease // 2 )
293
+ self ._t2 = ticks_diff (
294
+ ticks_add (self ._start_ticks , self ._lease ), self ._lease // 8
295
+ )
296
+ self ._lease = ticks_add (self ._lease , self ._start_ticks )
291
297
self ._increment_transaction_id ()
292
298
if not self ._renew :
293
299
self ._eth .ifconfig = (
@@ -330,13 +336,14 @@ def _handle_dhcp_message(self) -> int:
330
336
else :
331
337
dhcp_server = _BROADCAST_SERVER_ADDR
332
338
sock_num = None
333
- deadline = time .monotonic () + 5.0
339
+ deadline = 5000
340
+ start_time = ticks_ms ()
334
341
try :
335
342
while sock_num is None :
336
343
sock_num = self ._eth .get_socket ()
337
344
if sock_num == 0xFF :
338
345
sock_num = None
339
- if time . monotonic ( ) > deadline :
346
+ if ticks_diff ( ticks_ms (), start_time ) > deadline :
340
347
raise RuntimeError ("Unable to initialize UDP socket." )
341
348
342
349
self ._eth .src_port = 68
@@ -349,7 +356,8 @@ def _handle_dhcp_message(self) -> int:
349
356
for attempt in range (4 ): # Initial attempt plus 3 retries.
350
357
self ._eth .socket_write (sock_num , _BUFF [:message_length ])
351
358
next_resend = self ._next_retry_time (attempt = attempt )
352
- while time .monotonic () < next_resend :
359
+ start_time = ticks_ms ()
360
+ while ticks_diff (ticks_ms (), start_time ) < next_resend :
353
361
if self ._receive_dhcp_response (sock_num , next_resend ):
354
362
try :
355
363
msg_type_in = self ._parse_dhcp_response ()
@@ -382,17 +390,17 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
382
390
self ._blocking = blocking
383
391
while True :
384
392
if self ._dhcp_state == _STATE_BOUND :
385
- now = time . monotonic ()
386
- if now < self ._t1 :
393
+ now = ticks_ms ()
394
+ if ticks_diff ( now , self ._t1 ) < 0 :
387
395
debug_msg ("No timers have expired. Exiting FSM." , self ._debug )
388
396
return
389
- if now > self ._lease :
397
+ if ticks_diff ( now , self ._lease ) > 0 :
390
398
debug_msg (
391
399
"Lease has expired, switching state to INIT." , self ._debug
392
400
)
393
401
self ._blocking = True
394
402
self ._dhcp_state = _STATE_INIT
395
- elif now > self ._t2 :
403
+ elif ticks_diff ( now , self ._t2 ) > 0 :
396
404
debug_msg (
397
405
"T2 has expired, switching state to REBINDING." , self ._debug
398
406
)
@@ -407,13 +415,15 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
407
415
debug_msg ("FSM state is RENEWING." , self ._debug )
408
416
self ._renew = "renew"
409
417
self ._start_time = time .monotonic ()
418
+ self ._start_ticks = ticks_ms ()
410
419
self ._dhcp_state = _STATE_REQUESTING
411
420
412
421
if self ._dhcp_state == _STATE_REBINDING :
413
422
debug_msg ("FSM state is REBINDING." , self ._debug )
414
423
self ._renew = "rebind"
415
424
self .dhcp_server_ip = _BROADCAST_SERVER_ADDR
416
425
self ._start_time = time .monotonic ()
426
+ self ._start_ticks = ticks_ms ()
417
427
self ._dhcp_state = _STATE_REQUESTING
418
428
419
429
if self ._dhcp_state == _STATE_INIT :
@@ -486,7 +496,9 @@ def option_writer(
486
496
# Transaction ID (xid)
487
497
_BUFF [4 :8 ] = self ._transaction_id .to_bytes (4 , "big" )
488
498
# Seconds elapsed
489
- _BUFF [8 :10 ] = int (time .monotonic () - self ._start_time ).to_bytes (2 , "big" )
499
+ _BUFF [8 :10 ] = int (ticks_diff (ticks_ms (), self ._start_ticks ) / 1000 ).to_bytes (
500
+ 2 , "big"
501
+ )
490
502
# Flags (only bit 0 is used, all other bits must be 0)
491
503
if broadcast :
492
504
_BUFF [10 ] = 0b10000000
0 commit comments