hmmm what is drawWaveform()? If that is computing all the pixels of the screen, it could be already very time consuming, possibly enough to cause a dropout. If in addition to that it also calls sendBuffer() then it really shouldn't be called from there because that operation takes several milliseconds to complete. Keep in mind that the display has a limited refresh rate, this depends on how many pixels you redraw (normally all of them)* and the I2C speed (which should already be at the maximum). This means that you should only try to draw it every so often, e.g.: every 50 ms. This is best done from a separate thread, where you have something like:
void writeToScreen(void*)
{
while(!Bela_stopRequested()){
// set all the pixels
// .... your code here ...
// send the data via I2C to the display
u8g2.sendBuffer(); // this will take time to complete, possibly several milliseconds
// sleep a bit if needed to lower the frame rate:
// the overall period of the loop will be primarily determined by this sleep + the time it takes to complete sendBuffer() above.
usleep(10000);
}
}
you'd start this thread from setup() with something like:
Bela_runAuxiliaryTask(writeToScreen);
now, the magic is all in ... your code here ... there you'll probably put something very similar to drawWaveform(playheadIndex). You need playheadIndex to be a global variable so that it can be written from the audio render() thread and read from the writeToScreen() thread. This way you don't even need the if(readPointer % playheadInterval == 0) logic in render().
You can remove the usleep() line if you want the highest refresh rate that the I2C bus will allow, but that may put a significant load on your CPU and may make the IDE unresponsive, but it should in no way cause audio dropouts. If the IDE becomes unresponsive, briefly press the button on the Bela cape to stop the execution of the Bela program and wait a few seconds for the IDE to come back to life.
*
nickcamillo and if you know how to only update certain parts of an individual display using u8g2 I'd love to hear that too haha.
not sure. In csrc/u8g2_buffer.c , u8g2_send_buffer(), which is called from U8G2::sendBuffer(), calls u8g2_send_tile_row() and ultimately u8x8_DrawTile(). This last one u8x8_DrawTile() is also available directly from U8G2::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr). Not sure about the semantics of the arguments, but you can try looking at the existing code. Note that some displays will need to call refreshDisplay() for any change applied with drawTile() to take place. A tile seems to be an 8x8 pixel square, according to grepping through the docs.