Skip to content

Commit 0093b21

Browse files
committed
Align serial and I2C reset with note-c.
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. While doing this work, I also discovered that for serial-over-I2C reads on MicroPython we were generating a STOP condition after the initial write required before a read (see https://dev.blues.io/guides-and-tutorials/notecard-guides/serial-over-i2c-protocol/#data-read). This isn't expected as part of the protocol, nor were we doing it for the Linux and CircuitPython cases, so I adjusted the MicroPython code to match.
1 parent 7d9f2a3 commit 0093b21

File tree

1 file changed

+56
-15
lines changed

1 file changed

+56
-15
lines changed

notecard/notecard.py

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -255,25 +255,49 @@ def _read_byte_circuitpython(self):
255255
@serial_lock
256256
def Reset(self):
257257
"""Reset the Notecard."""
258+
notecard_ready = False
258259
for i in range(10):
259260
try:
261+
# Send a newline to the Notecard to terminate any partial
262+
# request that might be sitting in its input buffer.
260263
self.uart.write(b'\n')
261264
except:
265+
# Wait 500 ms and before trying to send the newline again.
266+
time.sleep(.5)
262267
continue
263-
time.sleep(0.5)
264-
somethingFound = False
265-
nonControlCharFound = False
266-
while True:
268+
269+
something_found = False
270+
non_control_char_found = False
271+
# Drain serial for 500 ms.
272+
start = start_timeout()
273+
while not has_timed_out(start, 0.5):
267274
data = self._read_byte()
268-
if (data is None) or (data == b''):
269-
break
270-
somethingFound = True
271-
if data[0] >= 0x20:
272-
nonControlCharFound = True
273-
if somethingFound and not nonControlCharFound:
275+
# If data was read from the Notecard, inspect what we received.
276+
# If it isn't a \n or \r, the host and the Notecard aren't
277+
# synced up yet, and we'll need to retransmit the \n and try
278+
# again.
279+
while data is not None and data != b'':
280+
something_found = True
281+
if data[0] != ord('\n') and data[0] != ord('\r'):
282+
non_control_char_found = True
283+
284+
data = self._read_byte()
285+
286+
# If there was no data read from the Notecard, wait 1 ms and try
287+
# again. Keep doing this for 500 ms.
288+
time.sleep(.001)
289+
290+
# If we received anything other than newlines from the Notecard, we
291+
# aren't in sync, yet.
292+
if something_found and not non_control_char_found:
293+
notecard_ready = True
274294
break
275-
else:
276-
raise Exception('Notecard not responding')
295+
296+
# Wait 500 ms before trying again.
297+
time.sleep(.5)
298+
299+
if not notecard_ready:
300+
raise Exception('Failed to reset Notecard.')
277301

278302
def __init__(self, uart_id, debug=False):
279303
"""Initialize the Notecard before a reset."""
@@ -408,8 +432,25 @@ def _transact(self, req, rsp_expected):
408432
@i2c_lock
409433
def Reset(self):
410434
"""Reset the Notecard."""
411-
# Read from the Notecard until there's nothing left to read.
412-
self._receive(0, .001, False)
435+
# Send a newline to the Notecard to terminate any partial request that
436+
# might be sitting in its input buffer.
437+
self._transmit(b'\n')
438+
439+
time.sleep(CARD_REQUEST_SEGMENT_DELAY_MS / 1000)
440+
441+
# Read from the Notecard until there's nothing left, retrying a max of 3
442+
# times.
443+
retries = 3
444+
while retries > 0:
445+
try:
446+
self._receive(0, .001, False)
447+
except:
448+
retries -= 1
449+
else:
450+
break
451+
452+
if retries == 0:
453+
raise Exception('Failed to reset Notecard.')
413454

414455
def _linux_write(self, length, data):
415456
msgs = [I2C.Message(length + data)]
@@ -426,7 +467,7 @@ def _linux_read(self, initiate_read_msg, read_buf):
426467
return read_buf
427468

428469
def _micropython_read(self, initiate_read_msg, read_buf):
429-
self.i2c.writeto(self.addr, initiate_read_msg, False)
470+
self.i2c.writeto(self.addr, initiate_read_msg)
430471
self.i2c.readfrom_into(self.addr, read_buf)
431472

432473
return read_buf

0 commit comments

Comments
 (0)