@@ -323,9 +323,6 @@ def __init__(
323
323
self ._mosi = None
324
324
self ._miso = None
325
325
326
- self .configure ()
327
- self .unlock ()
328
-
329
326
# Set pins as outputs/inputs.
330
327
self ._sclk = DigitalInOut (clock )
331
328
self ._sclk .switch_to_output ()
@@ -338,6 +335,9 @@ def __init__(
338
335
self ._miso = DigitalInOut (MISO )
339
336
self ._miso .switch_to_input ()
340
337
338
+ self .configure ()
339
+ self .unlock ()
340
+
341
341
def deinit (self ) -> None :
342
342
"""Free any hardware used by the object."""
343
343
self ._sclk .deinit ()
@@ -372,12 +372,30 @@ def configure(
372
372
self ._bits = bits
373
373
self ._half_period = (1 / self ._baudrate ) / 2 # 50% Duty Cyle delay
374
374
375
+ # Initialize the clock to the idle state. This is important to
376
+ # guarantee that the clock is at a known (idle) state before
377
+ # any read/write operations.
378
+ self ._sclk .value = self ._polarity
379
+
375
380
def _wait (self , start : Optional [int ] = None ) -> float :
376
381
"""Wait for up to one half cycle"""
377
382
while (start + self ._half_period ) > monotonic ():
378
383
pass
379
384
return monotonic () # Return current time
380
385
386
+ def _should_write (self , to_active : Literal [0 , 1 ]) -> bool :
387
+ """Return true if a bit should be written on the given clock transition."""
388
+ # phase 0: write when active is 0
389
+ # phase 1: write when active is 1
390
+ return self ._phase == to_active
391
+
392
+ def _should_read (self , to_active : Literal [0 , 1 ]) -> bool :
393
+ """Return true if a bit should be read on the given clock transition."""
394
+ # phase 0: read when active is 1
395
+ # phase 1: read when active is 0
396
+ # Data is read on the idle->active transition only when the phase is 1
397
+ return self ._phase == 1 - to_active
398
+
381
399
def write (
382
400
self , buffer : ReadableBuffer , start : int = 0 , end : Optional [int ] = None
383
401
) -> None :
@@ -392,24 +410,26 @@ def write(
392
410
393
411
if self ._check_lock ():
394
412
start_time = monotonic ()
413
+ # Note: when we come here, our clock must always be its idle state.
395
414
for byte in buffer [start :end ]:
396
415
for bit_position in range (self ._bits ):
397
416
bit_value = byte & 0x80 >> bit_position
398
- # Set clock to base
399
- if not self ._phase : # Mode 0, 2
417
+ # clock: idle, or has made an active->idle transition.
418
+ if self ._should_write ( to_active = 0 ):
400
419
self ._mosi .value = bit_value
401
- self . _sclk . value = not self . _polarity
420
+ # clock: wait in idle for half a period
402
421
start_time = self ._wait (start_time )
403
-
404
- # Flip clock off base
405
- if self ._phase : # Mode 1, 3
422
+ # clock: idle->active
423
+ self . _sclk . value = not self . _polarity
424
+ if self ._should_write ( to_active = 1 ):
406
425
self ._mosi .value = bit_value
407
- self . _sclk . value = self . _polarity
426
+ # clock: wait in active for half a period
408
427
start_time = self ._wait (start_time )
409
-
410
- # Return pins to base positions
411
- self ._mosi .value = 0
412
- self ._sclk .value = self ._polarity
428
+ # clock: active->idle
429
+ self ._sclk .value = self ._polarity
430
+ # clock: stay in idle for the last active->idle transition
431
+ # to settle.
432
+ start_time = self ._wait (start_time )
413
433
414
434
# pylint: disable=too-many-branches
415
435
def readinto (
@@ -433,36 +453,38 @@ def readinto(
433
453
for bit_position in range (self ._bits ):
434
454
bit_mask = 0x80 >> bit_position
435
455
bit_value = write_value & 0x80 >> bit_position
436
- # Return clock to base
437
- self ._sclk .value = self ._polarity
438
- start_time = self ._wait (start_time )
439
- # Handle read on leading edge of clock.
440
- if not self ._phase : # Mode 0, 2
456
+ # clock: idle, or has made an active->idle transition.
457
+ if self ._should_write (to_active = 0 ):
441
458
if self ._mosi is not None :
442
459
self ._mosi .value = bit_value
460
+ # clock: wait half a period.
461
+ start_time = self ._wait (start_time )
462
+ # clock: idle->active
463
+ self ._sclk .value = not self ._polarity
464
+ if self ._should_read (to_active = 1 ):
443
465
if self ._miso .value :
444
466
# Set bit to 1 at appropriate location.
445
467
buffer [byte_position ] |= bit_mask
446
468
else :
447
469
# Set bit to 0 at appropriate location.
448
470
buffer [byte_position ] &= ~ bit_mask
449
- # Flip clock off base
450
- self ._sclk .value = not self ._polarity
451
- start_time = self ._wait (start_time )
452
- # Handle read on trailing edge of clock.
453
- if self ._phase : # Mode 1, 3
471
+ if self ._should_write (to_active = 1 ):
454
472
if self ._mosi is not None :
455
473
self ._mosi .value = bit_value
474
+ # clock: wait half a period
475
+ start_time = self ._wait (start_time )
476
+ # Clock: active->idle
477
+ self ._sclk .value = self ._polarity
478
+ if self ._should_read (to_active = 0 ):
456
479
if self ._miso .value :
457
480
# Set bit to 1 at appropriate location.
458
481
buffer [byte_position ] |= bit_mask
459
482
else :
460
483
# Set bit to 0 at appropriate location.
461
484
buffer [byte_position ] &= ~ bit_mask
462
485
463
- # Return pins to base positions
464
- self ._mosi .value = 0
465
- self ._sclk .value = self ._polarity
486
+ # clock: wait another half period for the last transition.
487
+ start_time = self ._wait (start_time )
466
488
467
489
def write_readinto (
468
490
self ,
@@ -499,34 +521,34 @@ def write_readinto(
499
521
buffer_out [byte_position + out_start ] & 0x80 >> bit_position
500
522
)
501
523
in_byte_position = byte_position + in_start
502
- # Return clock to 0
503
- self ._sclk .value = self ._polarity
504
- start_time = self ._wait (start_time )
505
- # Handle read on leading edge of clock.
506
- if not self ._phase : # Mode 0, 2
524
+ # clock: idle, or has made an active->idle transition.
525
+ if self ._should_write (to_active = 0 ):
507
526
self ._mosi .value = bit_value
527
+ # clock: wait half a period.
528
+ start_time = self ._wait (start_time )
529
+ # clock: idle->active
530
+ self ._sclk .value = not self ._polarity
531
+ if self ._should_read (to_active = 1 ):
508
532
if self ._miso .value :
509
533
# Set bit to 1 at appropriate location.
510
534
buffer_in [in_byte_position ] |= bit_mask
511
535
else :
512
- # Set bit to 0 at appropriate location.
513
536
buffer_in [in_byte_position ] &= ~ bit_mask
514
- # Flip clock off base
515
- self ._sclk .value = not self ._polarity
516
- start_time = self ._wait (start_time )
517
- # Handle read on trailing edge of clock.
518
- if self ._phase : # Mode 1, 3
537
+ if self ._should_write (to_active = 1 ):
519
538
self ._mosi .value = bit_value
539
+ # clock: wait half a period
540
+ start_time = self ._wait (start_time )
541
+ # Clock: active->idle
542
+ self ._sclk .value = self ._polarity
543
+ if self ._should_read (to_active = 0 ):
520
544
if self ._miso .value :
521
545
# Set bit to 1 at appropriate location.
522
546
buffer_in [in_byte_position ] |= bit_mask
523
547
else :
524
- # Set bit to 0 at appropriate location.
525
548
buffer_in [in_byte_position ] &= ~ bit_mask
526
549
527
- # Return pins to base positions
528
- self ._mosi .value = 0
529
- self ._sclk .value = self ._polarity
550
+ # clock: wait another half period for the last transition.
551
+ start_time = self ._wait (start_time )
530
552
531
553
# pylint: enable=too-many-branches
532
554
0 commit comments