Damien wrote:I think we should add a callback mechanism to UART receive, but would you use it in this case for more than just buffering data at the Python level? If you had a callback, how exactly would you user it? Would it be better to have a callback for "receive buffer half full" rather than "one char received"? If your data rate is very large and bursty (eg 115200 baud but only for a short time once per second) then it makes sense to just buffer the input and process it all at once.
My original thought was to trigger the callback on every character, but your question made me wonder how fast can I can actually parse. I whipped up a little code to run on the pyboard:
https://gist.github.com/inmcm/bf22a292a7609314937f This code returns the number of microseconds it takes to run each character of a sentence through the update() function.
The results were pretty cool. The time for various pieces of data were:
Most Normal Characters: 113-127us
',' which end segments: ~110us
'*' which signifies the end of GPS data: ~90us
When the test gets to the last valid character of the sentence, it also calls the sentence function to update the object. These times were a bit more noisy, so I rigged up another test to get the average time to parse the final character and update the GPS object with fix data:
https://gist.github.com/inmcm/179e31c3890349c4aad9
The times for each sentence type were pretty close:
RMC: 583us
GGA: 534us
GSA: 555us
GSV: 596us
Thinking about baud rates; 9600 baud is 104us per bit, so receiving a single NMEA sentence character takes 1041us (assuming 8N1 encoding). That's plenty slow enough to do the call back on every new character. On the other hand, 115200 baud only takes 86us to send a character. Based on the times above, we'd have to buffer before processing.
So to answer your question, I would vote for a UART callback system based off of the "fullness" of the UART buffer. The UART would collect characters in its buffer till a certain percentage was reached at which point, the callback would be triggered. With that system, you can use the size of the buffer to control how often you service the callback. Want the callback serviced a lot? Set the buffer to 5 characters. You have a lot of fast incoming data, set the buffer to 1K. The fullness of FIFO wouldn't need to configurable; just low enough that some characters could be read before it overruns. With that sort of system you could have something like the code below
Code: Select all
my_uart = (UART3,9600,512) # Create UART with 512 byte buffer
my_gps = MicropyGPS()
# Create the callback with a special GPS update method
my_uart.callback(my_gps.auto_update(UART3))
# Do other stuff.......
### Within micropyGPS class
# This method gets called once the X% of 512 bytes is filled
def auto_update(self,some_uart):
while some_uart.any():
self.update(chr(some_uart.readchr()))