Hmmm, as far as I understand the code (and I do not pretend to fully understand it…) the code you cited does the following:
- it sets „start“ to „true“
- „start" will be reset to „false“ once the first SYNC byte was received
- it sets „stop“ to „false“
- „stop" will be set to „true“, if a another SYNC byte is received after the first one AND it received more than XXX (20 or 90) bytes after the previous SYNC byte
- it sets „quit“ to „false“
- „quit“ will be set to „true“ if a „timerInterval“ is configured AND the time between the last SYNC byte and now exceeds that „timerInterval“
- I have not found a code location that actually sets „timerInterval“, so I assume we can ignore the „quit“ flag
If either „stop“ or „quit“ is set to true, reception is ended, regardless of whether a VBus data fragment was received.
So, lets see what happened when „vBusRead“ is called and XXX still was 20. If we assume you receive the same sequence of bytes like you recorded the function would have behaved like this:
- The first 0xAA is detected as a SYNC byte. „start“ is set to „false“
- The code receives the next 15 bytes and stores them in the buffer
- It then receives the second 0xAA. Since „start“ is already „false“, it checks whether less than 20 bytes have been stored to the buffer -> yes, so it resets the buffer and starts a new reception
- The code then receives the next 51 bytes and stores them in the buffer
- It then receives the third 0xAA. Since „start“ is already „false“, it checks whether less than 20 bytes have been stored to the buffer -> no, so end reception by setting „stop“ to „true“
This yields the packet addressed to 0x0015.
When the „vBusRead“ function is called again, it behaves like this:
- The code receives the remaining 99 bytes that belonged to the third 0xAA SYNC byte from last function call, but since „start“ is „true“ the whole time it ignores these bytes
- The fourth 0xAA is received. That again belongs to the same sequence of bytes like the first 0xAA
- From here on the code behaves like in the first call above
But as you can see your 100 byte packet is ignored, because your first call to „vBusRead“ already consumed the SYNC byte, so the the second call thinks that the remaining 99 bytes it receives are junk.
What happened when you changed XXX to 90:
- The first 0xAA is received, detected as a SYNC byte. „start“ is set to „false“
- The next 15 bytes are received and stored in the buffer
- The second 0xAA is received, detected as a SYNC byte, but since „start“ already is „false“, it checks whether less than 90 bytes have been stored to the buffer -> yes, so it resets the buffer and starts a new reception
- The next 51 bytes are received and stored in the buffer
- The first 0xAA is received, detected as a SYNC byte, but since „start“ already is „false“, it checks whether less then 90 bytes have been stored to the buffer -> yes, so it resets the buffer and starts a new reception
- The next 99 bytes are received and stored in the buffer
- The fourth 0xAA is received, detected as a SYNC byte, but since „start“ already is „false“, it checks whether less than 90 bytes have been stored to the buffer -> no, so it ends reception by setting „stop“ to „true“
This yields the packet addressed to 0x0010!
When the „vBusRead“ function is called again, it behaved like this:
- The remaining 15 bytes that belong to the fourth 0xAA from the previous function call are received, but since „start“ is „true“ they are ignored
- The fifth 0xAA is received, detected as a SYNC byte. „start“ is set to „false“
- From here on the code behave like the first call above after receiving the second 0xAA
So setting XXX to any value greater than 52 but less than 100 allowed you to receive the packet you wanted.
In my opinion the code „vBusRead“ is sub-optimal and brittle. It should not consume a SYNC byte to detect whether it should return a fragment of VBus data. Instead (in my opinion) the code should:
- Wait for the SYNC byte, reseting reception while receiving something else
- Once the SYNC byte is received, store it and all subsequent bytes into the buffer
- After receiving 6 bytes it should check the protocol version in byte 5
- if it is 0x10 the remainder is a VBus version 1.0 packet
- if it is 0x20 the remainder is a VBus version 2.0 datagram
- reset reception in any other case
For the VBus version 1.0 is should:
- Receive four additional bytes (10 in total)
- Check the checksum in byte 9, resetting reception if wrong
- Evaluate the frame count in byte 8
- For each frame
- Receive six additional bytes
- Check the frame’s checksum, resetting reception if wrong
- Once the full (10 + FrameCount * 6) bytes were received, exit the function
For the VBus version 2.0 it should:
- Receive ten additional bytes (16 in total)
- Check the checksum in byte 15, resetting reception if wrong
The advantage of this approach is that the SYNC byte of the next VBus fragment is still in the UART RX queue, waiting to be consumed once the function is called again.
I hope that explanation helps you understand the inner workings of the code. If you keep that magic constant at „90“ it should work for your case, but will break on other controllers / configurations.
Best regards,
Daniel