First, try using 1 MHz clock speed. Adafruit's library defaults to 400 kHz, so this should give you about a 2.5X speedup.
If you started with Adafruit's example, you probably have this in your program:
Code:
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Fortunately Adafruit designed it to take a 5th parameter for the clock speed, like this:
Code:
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET, 1000000);
Usually these displays can work at 1 MHz, but you might need to add 1K pullup resistors on SDA & SCL. If the display has resistors like 10K or even 4.7K, the signals might be able to change fast enough for 1 MHz speed.
Now for some guessing about your code.... Maybe you're updating the display for every MIDI message? If so, only call the drawing functions but do not call the slow display.display() function.
Instead, use an elapsedMillis in loop() to cause the display to update at a controlled rate. Maybe like this:
Code:
void loop() {
// other stuff your program does, like receiving MIDI messages
static elapsedMillis display_update_timer;
if (display_update_timer > 50) {
display_update_timer = 0;
display.display(); // slow display update
}
}
This way you program will be able to process all the MIDI messages (the drawing functions are very fast since they only alter Teensy's memory) and only every 50ms spend time updating the display over slow I2C communication.
You could try to use interrupts or IntervalTimer, but interrupts can be a very painful path when you need to share data. Really do not recommend.
In an ideal world, we would have a non-blocking DMA based library like Kurt's ILI9341_t3n. Then the display update happens in the background without blocking the CPU. Sadly, it just doesn't exist (yet) for this popular display using I2C. If you're not fully locked into this SSD1306 display, and if you can spare the pins and fit a large screen into your project, moving to a ILI9341 display might be a good choice. ILI9341_t3n really is the best way.