-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make changes to support binary transfers. #76
Conversation
99acf6d
to
23946e2
Compare
I'll put up the PR for COBS/binary transfers once we get this one merged. |
I'm converting this to a draft while I synchronize the serial and I2C logic here with a bunch of recent changes to note-c. I don't think it makes sense to try to merge this as it is; there's a lot missing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks awesome @haydenroche5 ! I don't have the ability to test this at the moment, so if it works for you, I'm good!
And coverage up to 88%! |
23946e2
to
a656fb2
Compare
a656fb2
to
0a1f2e2
Compare
To give you an idea of how this will fit in with binary transfers/COBS, see #77. Also, I just tested this code using the examples that we use for HIL testing on the 3 main platforms:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is beautiful!
notecard/notecard.py
Outdated
else: | ||
raise NotImplementedError(f'Unsupported platform: {sys.implementation.name}') | ||
self._available = self._available_default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought - instead of hoping for the best with the default implementation, the code could check for the presence of uart.in_waiting
and fail if that doesn't exist, so it fails early rather than when _available_default
is later called.
# The number of data bytes in this packet. | ||
data_len = header[1] | ||
# The rest is the data. | ||
data = read_buf[2:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about validating the length of data
equals data_len
? We can then skip returning data_len
since it's available "from the source" as len(data)
. This would remove a potential point of inconsistency.
data_left -= chunk_len | ||
sent_in_seg += chunk_len | ||
|
||
if sent_in_seg > CARD_REQUEST_SEGMENT_MAX_LEN: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took me a few seconds to figure out what is happening here. A doccomment or inline comment about chunking could be helpful. :-)
|
||
# Delay for 5ms. This prevents a fast host from hammering a slow/busy | ||
# Notecard with requests. | ||
time.sleep(0.005) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Outside of this PR it would be nice to shore up all these numbers into constants both here and in note-c.
|
||
class NotecardTest: | ||
|
||
@pytest.fixture |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like this! 💯
test/test_notecard.py
Outdated
card = notecard.Notecard() | ||
card.Transaction = MagicMock() | ||
|
||
rsp = card.Command({'cmd': 'card.sleep'}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe we document this? Couldn't find it in the API docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I'll move to something we do document.
- Add CRC support. - Align serial and I2C code with note-c. This encompasses mimicking the algorithms used in note-c and also things like delay lengths, number of retries, transaction timeout lengths, etc. - Align transaction logic with note-c. The majority of this work is in the reworked `Transaction` function, which is analogous to `noteTransactionShouldLock` in note-c. - Rework serial/I2C locking so that the lock can be held for the entirety of a binary transfer. For example, for a binary receive operation, the host needs to send a `card.binary.get` and then immediately receive the binary data from the Notecard. The serial/I2C lock should be held for the entirety of this operation, rather than be released after the `card.binary.get` and reacquired for the receipt of the binary data. - Add two methods for both serial and I2C: `transmit` and `receive`. `transmit` is used to transmit arbitrary bytes to the Notecard (e.g. after `card.binary.put`). `receive` is used to read a stream of bytes from the Notecard, stopping after reading a newline (e.g. after a `card.binary.get`). These are analogous to the `chunked(Receive|Transmit)` functions in note-c. - Overhaul unit testing. This commit adds many new unit tests, in addition to reorganizing things. Tests for the `Notecard` base class are in test_notecard.py. `OpenSerial` tests are in test_serial.py, and `OpenI2C` tests are in test_i2c.py. There is a some code repetition here, especially between the `_transact` and `Reset` methods of `OpenSerial` and `OpenI2C`. Again, this follows the pattern in note-c and was done consciously. We may want to factor out that repetition in the future, but for now, I'm prioritizing parity with the "source of truth" (note-c).
- Fail example scripts if an exception is raised at any point. - Rework `_crc_add` to produce a reliable CRC. This requires us to rely more on string manipulation and less on python dicts. Prior to this commit, the CRC was computed over the string representation of the request (via `json.dumps`) and then it was added to the request dict. Then, when it was time to serialize the request for transmission and we converted the dict to a string again, because the CRC field had been added, the order of the fields changed and the CRC was invalidated. This is because Python dicts are fundamentally unordered collections. - Add missing timeout reset to `OpenSerial`'s `receive` method. - Increase cpy_example.py UART RX buffer size. I was seeing the end of responses get cut off with the default size (64). Increased to 128.
ab20d7e
to
5d673d3
Compare
5d673d3
to
1a57fdf
Compare
See https://forum.micropython.org/viewtopic.php?f=2&t=11114. I also went ahead and changed to the new format for multiline strings that don't contain f-strings.
1a57fdf
to
1f783b8
Compare
algorithms used in note-c and also things like delay lengths, number of retries,
transaction timeout lengths, etc.
reworked
Transaction
function, which is analogous tonoteTransactionShouldLock
in note-c.binary transfer. For example, for a binary receive operation, the host needs to
send a
card.binary.get
and then immediately receive the binary data from theNotecard. The serial/I2C lock should be held for the entirety of this operation,
rather than be released after the
card.binary.get
and reacquired for thereceipt of the binary data.
transmit
andreceive
.transmit
is used to transmit arbitrary bytes to the Notecard (e.g. after
card.binary.put
).receive
is used to read a stream of bytes from theNotecard, stopping after reading a newline (e.g. after a
card.binary.get
).These are analogous to the
chunked(Receive|Transmit)
functions in note-c.to reorganizing things. Tests for the
Notecard
base class are intest_notecard.py.
OpenSerial
tests are in test_serial.py, andOpenI2C
testsare in test_i2c.py.
There is a some code repetition here, especially between the
_transact
andReset
methods ofOpenSerial
andOpenI2C
. Again, this follows the patternin note-c and was done consciously. We may want to factor out that repetition
in the future, but for now, I'm prioritizing parity with the "source of truth"
(note-c).