I’m currently writing an app that continually reads input from a serial port using the Boost ASIO library. After reading the signal, which is just a PCM-encoded waveform, I plot it on screen. Ideally, the plot is done in a sort of slow trace oscilloscope fashion, so that successive samples are tacked onto the existing stream and the display is updated accordingly in a smooth marquee from left to right, and the whole thing wraps around every 10 seconds or so. The sample rate is 250 Hz, so that I read in one new sample every 1/250th of a second.
Right now, the unoptimized program is doing something like
- (mutex on) Read new sample (mutex off)
- Add new sample to circular buffer of existing samples
- Have xxx amount of samples been read in since the last redraw? If so, pass pointer to buffer over to thread 2, which redraws the oscilloscope with th enew data
- Give my oscilloscope class instance a pointer to the buffer
- (MessageManagerLock on) plot (MessageManagerLock off)
- End thread
That’s it, pretty simple.
If I try to redraw every sample, so that it’s theoretically as smooth as possible, this fails. Repainting the oscilloscope 250 times a second causes the whole thing to lag and crash. Additionally, since plots require the MessageManager thread to have lock, if I do 250 calls per second, the MessageManager thread basically locks the whole program up, and my initial thread doesn’t end up reading the serial port in a timely fashion, causing buffering issues. Or maybe it’s the creation of 250 new threads per second to plot which causes it to fail. Either way, that doesn’t work.
But, even if I only plot once every 5 samples or so, which is one plot per 20 ms, it still crashes. And if I plot once every 25 samples, which is one plot per 100 ms, it still crashes. I have to do it like once or twice a second for it to not crash.
What’s a better approach? Is there a way to do a realtime oscilloscope plot without everything hanging up? Perhaps there’s a way to paint first to a buffer without having to lock the MessageManager thread, and then just drawing the whole thing at once? Or maybe the creation of a brand new thread on every single redraw is what’s screwing it up…?
Thanks, and your help is much appreciated!