FtcRobotController icon indicating copy to clipboard operation
FtcRobotController copied to clipboard

LynxI2cReadMultipleBytesCommand always reads extra byte

Open smartynenko opened this issue 4 years ago • 13 comments

We are communicating with serial I2C device which can send more than 100 bytes in a single response. Every response from the device contains header and cargo, first two bytes in header contain response length (including both cargo and header length). Per our observation, LynxI2cReadMultipleBytesCommand always reads one extra byte

Ie, per host request, device needs to send 6 cargo bytes 01 02 03 04 05 06. In this case devise will send back respond with 10 bytes 0A 00 FF FF 01 02 03 04 05 06 0A 00 FF FF - header - 4 bytes 01 02 03 04 05 06 - cargo - 6 bytes 0A - first byte=total packet length In every read request, host is required to read at least four bytes (header) Example expected exchange:

Scenario 1 – Host does not know expected response length Host -> Read 4 bytes [header] Device -> 0A 00 FF FF (I have 10 0A bytes to send) Host -> Read 10 bytes Device -> 0A 00 FF FF 01 02 03 04 05 06 (here are 10 bytes = 4 bytes in header + 6 bytes in cargo)

Scenario 2 – Host does know expected response length Host -> Read 10 bytes [header + cargo] Device -> 0A 00 FF FF 01 02 03 04 05 06 (ending 10 bytes including header and cargo)

Scenario 3 – Host does know expected response length, but has limited incoming buffer (7 bytes) Host -> Read 7 bytes [header + cargo] Device -> 0A 00 FF FF 01 02 03 (sending 7 bytes including header and first 3 bytes from cargo, host will need to come back and read 3 more cargo bytes = 0A – 07, or 7 total bytes (cargo + header)) Host -> Read 7 bytes [header + cargo] Device -> 07 00 FF FF 04 05 06 (sending 7 bytes, 4 in header and 3 remaining bytes from cargo)

Actual exchange Scenario 1 – Host does not know expected response length - data loss Host -> Read 4 bytes [header] Device -> 0A 00 FF FF (I have 10 0A bytes to send) [in this transaction Hub actually reads 5 bytes from the devices instead of 4] Host -> Read 10 bytes Device -> 09 00 FF FF 02 03 04 05 06 00 (here are 9 bytes = 4 bytes in header + 5 bytes in cargo + dummy byte) – this response indicates that instead of requesting and reading 4 bytes, host actually read 5 (4 bytes in header + 1 cargo), and device excluded original first cargo byte from second response. Byte 01 is lost

Scenario 2 – Host does know expected response length (response will fit into buffer)- no data loss Host -> Read 10 bytes [header + cargo] Device -> 0A 00 FF FF 01 02 03 04 05 06 (I am sending 10 bytes including header and cargo) In other words, based on what we currently see, Expansion Hub always reads extra byte from the device and we are missing information when expected cargo length exceeds 100 bytes since we need to read it in chunks

Scenario 3 – Host does know expected response length, but has limited incoming buffer (7 bytes, [actual limit is 100, but behavior is the same]) - data loss Host -> Read 7 bytes [header + cargo] Device -> 0A 00 FF FF 01 02 03 (sending 7 bytes including header and cargo, total length 10) Host -> Read 7 bytes [header + cargo] Device -> 06 00 FF FF 05 06 00 (sending 7 bytes, 4 in header, 2 remaining bytes from cargo and one dummy byte - byte 04 is lost)

In other words, LynxI2cReadMultipleBytesCommand always reads one extra byte from I2C device beyond of what is requested. It does not create any issues if requested length is greater than number of bytes that device needs to send, but causes data loses in case if device needs to send more than requested in single read request

smartynenko avatar Jan 15 '21 01:01 smartynenko