jwllorens:
can you tell me if I am dynamically allocating in the following function:
uint8_t _data[_length.data];
No, you are not using the heap. In a sense, you are "dynamically allocating" an array on the stack. It is popped back off when you exit the routine. There is no problem with using this kind of stack variable.
jwllorens:
It seems like a waste to check Serial.available() every cycle
If you do use an ISR instead, loop
still gets called. It's the "idle task"; the MCU has to do something, unless:
-
You want to put the MCU into one of the sleep modes. Regardless of how you handle the characters, you can sleep immediately after a character is received. The next character will wake the MCU, and that's when you check Serial.available()
or your ISR gets called.
-
Other parts of your sketch block for long periods of time, and they cause input buffer overflow. The SD library can block while waiting for a write to complete. If it takes longer than 64 character times (~64ms @ 9600 baud), you will lose characters. Handling the characters in the RX ISR is one solution.
-
You're trying to squeeze every last cycle out of your sketch. Either technique allows incremental parsing, which spreads the parsing time out over the entire packet time. This avoids one large packet parse routine that may be blocking some other time-sensitive process. The good news is that using an ISR eliminates queueing the character, calling Serial.available()
and dequeueing the character. It's actually more efficient.
jwllorens:
I was simply wondering if anyone had a nifty way of using an ISR to handle an incoming byte rather than polling.
Of course there is a way, but I don't think it's necessary or worth the extra complexity. Given your description of what you're trying to do:
jwllorens:
It has to, for example, read the length MSB and LSB bytes, put them together with a union, and then compare to the bytes received so that I can set a bool stating that an entire frame has been received. It also needs to check for 0x7D, discard it, and then XOR the following incoming byte with 0x20 to restore the original data.
... this is a perfectly acceptable process to perform in an ISR (a background task). But it is also quick and easy to perform in the foreground (called from loop
).
Delta_G:
What you'll do is just note that a character came in, put it into a buffer, and when the code gets to the point that it needs to know what's in the buffer it will read it. What use is it to parse the data before you're ready. And when you are ready, you'll have to get the data out of that buffer one character at a time.
Sorry, I disagree that the ISR can only buffer bytes; it could easily "parse" the bytes into a received command structure. When correctly implemented as a Finite-state Machine, this is an excellent candidate for an ISR.
(NB: This is one reason my NeoGPS library can handle the GPS characters in the RX character interrupt. GPS parsing in an ISR? Yes. It wasn't easy, but yes. NeoGPS completely consumes each character as it arrives. There is no buffering, and this is one of the reasons it can be almost twice as fast as other GPS libraries.)
I'm not sure yet that the OP planned on incremental parsing, so that's why I asked a few questions about the application. Simply saving bytes into a struct and validating a checksum can be performed either in an ISR or in a routine called from loop
.
At this point, I agree with everyone else: use the easy approach and just call instance.update()
from loop
. Queue the valid structures into a ring buffer for some other process to use and call it done.
Cheers,
/dev