Skip to content

Commit

Permalink
Align serial and I2C reset with note-c.
Browse files Browse the repository at this point in the history
The "source of truth" for how to properly reset comms with the Notecard is in
note-c. This commit adjusts the `OpenI2C` and `OpenSerial` `Reset` methods so
that they implement the same logic as their note-c counterparts.
  • Loading branch information
haydenroche5 committed Sep 13, 2023
1 parent 7d9f2a3 commit 63778b7
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 21 deletions.
69 changes: 55 additions & 14 deletions notecard/notecard.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,25 +255,49 @@ def _read_byte_circuitpython(self):
@serial_lock
def Reset(self):
"""Reset the Notecard."""
notecard_ready = False
for i in range(10):
try:
# Send a newline to the Notecard to terminate any partial
# request that might be sitting in its input buffer.
self.uart.write(b'\n')
except:
# Wait 500 ms and before trying to send the newline again.
time.sleep(.5)
continue
time.sleep(0.5)
somethingFound = False
nonControlCharFound = False
while True:

something_found = False
non_control_char_found = False
# Drain serial for 500 ms.
start = start_timeout()
while not has_timed_out(start, 0.5):
data = self._read_byte()
if (data is None) or (data == b''):
break
somethingFound = True
if data[0] >= 0x20:
nonControlCharFound = True
if somethingFound and not nonControlCharFound:
# If data was read from the Notecard, inspect what we received.
# If it isn't a \n or \r, the host and the Notecard aren't
# synced up yet, and we'll need to retransmit the \n and try
# again.
while data is not None and data != b'':
something_found = True
if data[0] != ord('\n') and data[0] != ord('\r'):
non_control_char_found = True

data = self._read_byte()

# If there was no data read from the Notecard, wait 1 ms and try
# again. Keep doing this for 500 ms.
time.sleep(.001)

# If we received anything other than newlines from the Notecard, we
# aren't in sync, yet.
if something_found and not non_control_char_found:
notecard_ready = True
break
else:
raise Exception('Notecard not responding')

# Wait 500 ms before trying again.
time.sleep(.5)

if not notecard_ready:
raise Exception('Failed to reset Notecard.')

def __init__(self, uart_id, debug=False):
"""Initialize the Notecard before a reset."""
Expand Down Expand Up @@ -408,8 +432,25 @@ def _transact(self, req, rsp_expected):
@i2c_lock
def Reset(self):
"""Reset the Notecard."""
# Read from the Notecard until there's nothing left to read.
self._receive(0, .001, False)
# Send a newline to the Notecard to terminate any partial request that
# might be sitting in its input buffer.
self._transmit(b'\n')

time.sleep(CARD_REQUEST_SEGMENT_DELAY_MS / 1000)

# Read from the Notecard until there's nothing left, retrying a max of 3
# times.
retries = 3
while retries > 0:
try:
self._receive(0, .001, False)
except:
retries -= 1
else:
break

if retries == 0:
raise Exception('Failed to reset Notecard.')

def _linux_write(self, length, data):
msgs = [I2C.Message(length + data)]
Expand Down
18 changes: 11 additions & 7 deletions test/test_notecard.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ def get_serial_and_port():
port.read.side_effect = [b'\r', b'\n', None]
port.readline.return_value = "\r\n"

nCard = notecard.OpenSerial(port)
# Patch the Reset method so that we don't actually call it during __init__.
with patch('notecard.notecard.OpenSerial.Reset'):
nCard = notecard.OpenSerial(port)

return (nCard, port)

Expand All @@ -28,7 +30,9 @@ def get_i2c_and_port():
port = periphery.I2C("dev/i2c-foo")
port.try_lock.return_value = True

nCard = notecard.OpenI2C(port, 0x17, 255)
# Patch the Reset method so that we don't actually call it during __init__.
with patch('notecard.notecard.OpenI2C.Reset'):
nCard = notecard.OpenI2C(port, 0x17, 255)

return (nCard, port)

Expand Down Expand Up @@ -395,11 +399,11 @@ def test_open_serial(self):
assert nCard.uart is not None

def test_debug_mode_on_serial(self):
serial = Mock() # noqa: F811
port = serial.Serial("/dev/tty.foo", 9600)
port.read.side_effect = [b'\r', b'\n', None]

nCard = notecard.OpenSerial(port, debug=True)
# Patch the Reset method so that we don't actually call it during
# __init__.
with patch('notecard.notecard.OpenSerial.Reset'):
port = MagicMock()
nCard = notecard.OpenSerial(port, debug=True)

assert nCard._debug

Expand Down

0 comments on commit 63778b7

Please sign in to comment.