@@ -323,9 +323,6 @@ def __init__(
323323 self ._mosi = None
324324 self ._miso = None
325325
326- self .configure ()
327- self .unlock ()
328-
329326 # Set pins as outputs/inputs.
330327 self ._sclk = DigitalInOut (clock )
331328 self ._sclk .switch_to_output ()
@@ -338,6 +335,9 @@ def __init__(
338335 self ._miso = DigitalInOut (MISO )
339336 self ._miso .switch_to_input ()
340337
338+ self .configure ()
339+ self .unlock ()
340+
341341 def deinit (self ) -> None :
342342 """Free any hardware used by the object."""
343343 self ._sclk .deinit ()
@@ -372,12 +372,30 @@ def configure(
372372 self ._bits = bits
373373 self ._half_period = (1 / self ._baudrate ) / 2 # 50% Duty Cyle delay
374374
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+
375380 def _wait (self , start : Optional [int ] = None ) -> float :
376381 """Wait for up to one half cycle"""
377382 while (start + self ._half_period ) > monotonic ():
378383 pass
379384 return monotonic () # Return current time
380385
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+
381399 def write (
382400 self , buffer : ReadableBuffer , start : int = 0 , end : Optional [int ] = None
383401 ) -> None :
@@ -392,24 +410,26 @@ def write(
392410
393411 if self ._check_lock ():
394412 start_time = monotonic ()
413+ # Note: when we come here, our clock must always be its idle state.
395414 for byte in buffer [start :end ]:
396415 for bit_position in range (self ._bits ):
397416 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 ):
400419 self ._mosi .value = bit_value
401- self . _sclk . value = not self . _polarity
420+ # clock: wait in idle for half a period
402421 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 ):
406425 self ._mosi .value = bit_value
407- self . _sclk . value = self . _polarity
426+ # clock: wait in active for half a period
408427 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 )
413433
414434 # pylint: disable=too-many-branches
415435 def readinto (
@@ -433,36 +453,38 @@ def readinto(
433453 for bit_position in range (self ._bits ):
434454 bit_mask = 0x80 >> bit_position
435455 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 ):
441458 if self ._mosi is not None :
442459 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 ):
443465 if self ._miso .value :
444466 # Set bit to 1 at appropriate location.
445467 buffer [byte_position ] |= bit_mask
446468 else :
447469 # Set bit to 0 at appropriate location.
448470 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 ):
454472 if self ._mosi is not None :
455473 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 ):
456479 if self ._miso .value :
457480 # Set bit to 1 at appropriate location.
458481 buffer [byte_position ] |= bit_mask
459482 else :
460483 # Set bit to 0 at appropriate location.
461484 buffer [byte_position ] &= ~ bit_mask
462485
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 )
466488
467489 def write_readinto (
468490 self ,
@@ -499,34 +521,34 @@ def write_readinto(
499521 buffer_out [byte_position + out_start ] & 0x80 >> bit_position
500522 )
501523 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 ):
507526 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 ):
508532 if self ._miso .value :
509533 # Set bit to 1 at appropriate location.
510534 buffer_in [in_byte_position ] |= bit_mask
511535 else :
512- # Set bit to 0 at appropriate location.
513536 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 ):
519538 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 ):
520544 if self ._miso .value :
521545 # Set bit to 1 at appropriate location.
522546 buffer_in [in_byte_position ] |= bit_mask
523547 else :
524- # Set bit to 0 at appropriate location.
525548 buffer_in [in_byte_position ] &= ~ bit_mask
526549
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 )
530552
531553 # pylint: enable=too-many-branches
532554
0 commit comments