In this piece of code the delay is not a problem because it's a test, and it will hang up a first duty cycle value then the second, letting time analyze the pwm output
The OLED code
configure() is called in main setup(), updateDisplay() is called in every loop(), then user input set the interface values for displaying needed screen
#ifndef DISPLAY_HELPER_H
#define DISPLAY_HELPER_H
#define I2C_ADDRESS 0x3c
namespace display
{
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void configure();
void displayCursor(int);
void displaySettings(int);
void displayMenuState(int);
void displayCompileFlagState(bool);
void displaySavedFormulas();
void displayCurrentFile();
void displayLiveMode();
void updateDisplay();
void configure()
{
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SH110X_WHITE); // Draw white text
// display.cp437(true);
display.begin(I2C_ADDRESS);
// if (!display.begin(I2C_ADDRESS, 0x3C))
// { // Address 0x3C for 128x64
// Serial.println(F("SSD1306 allocation failed"));
// for (;;)
// ; // Don't proceed, loop forever
// }
display.clearDisplay();
display.display();
}
void displaySavedFormulas()
{
display.drawBitmap(0, 0, assetsBmp::FORMULAS_BMP, 128, 64, SH110X_WHITE);
int cursorX = 44;
int cursorY = 12;
display.setCursor(cursorX, cursorY);
display.setTextWrap(0);
int page = interface::savedFormulasIndex / 6;
for (int i = 0; i < 6; i++)
{
byte index = i + (page * 6);
char buffer[4];
snprintf(buffer, sizeof(buffer), "%02d", index + 1);
if (index == interface::savedFormulasIndex)
{
display.fillRect(cursorX - 1, cursorY - 1, (CHAR_WIDTH * 2) + 1, CHAR_HEIGHT + 1, SH110X_WHITE);
display.setTextColor(SH110X_BLACK);
}
display.print(buffer);
if (index == interface::savedFormulasIndex)
{
display.setTextColor(SH110X_WHITE);
}
display.print(" ");
display.print(formula::savedFormulas[index]);
cursorY += CHAR_HEIGHT;
display.setCursor(cursorX, cursorY);
}
display.setTextWrap(1);
}
void displaySettings(int settingsCursorState)
{
display.drawBitmap(0, 0, assetsBmp::SETTINGS_BMP, 128, 64, SH110X_WHITE);
if (settingsCursorState == 0)
{
display.drawBitmap(48, 16, assetsBmp::SETTINGS_CURSOR_SELECTED_BMP, 10, 10, SH110X_WHITE);
}
else if (settingsCursorState == 1)
{
display.drawBitmap(48, 43, assetsBmp::SETTINGS_CURSOR_SELECTED_BMP, 10, 10, SH110X_WHITE);
}
display.drawBitmap(56, 50, assetsBmp::SETTINGS_WAVEFORM_SINE_NO_SELECTED, 15, 10, SH110X_WHITE);
display.drawBitmap(96, 50, assetsBmp::SETTINGS_WAVEFORM_SQR_NO_SELECTED, 15, 10, SH110X_WHITE);
}
void displayExprMode()
{
display.setCursor(34, 1);
display.setTextColor(SH110X_BLACK);
if (interface::exprModeIndex == interface::SYMBOLS)
{
display.print(F("+-x"));
}
else if (interface::exprModeIndex == interface::NUMBERS)
{
display.print(F("123"));
}
else if (interface::exprModeIndex == interface::FUNCTIONS)
{
display.drawTriangle(34, 6, 34, 1, 40, 6, SH110X_BLACK);
}
display.setTextColor(SH110X_WHITE);
}
void displayLiveMode()
{
display.setCursor(58, 1);
display.setTextColor(SH110X_BLACK);
if (formula::liveMode)
{
display.print(F("live"));
}
else
{
display.print(F("hold"));
}
display.setTextColor(SH110X_WHITE);
}
void displayCompileFlagState(bool compileFlag)
{
if (compileFlag == 1)
{
display.drawBitmap(114, 1, assetsBmp::YES_COMPILE_BMP, 7, 7, SH110X_WHITE);
}
else
{
display.drawBitmap(114, 1, assetsBmp::NO_COMPILE_BMP, 7, 7, SH110X_WHITE);
}
}
void displayMenuState(int symbolsState)
{
display.setTextColor(SH110X_BLACK);
display.setCursor(50, 2);
if (symbolsState == 0)
{
display.print(F("+ - x"));
}
else if (symbolsState == 1)
{
display.print(F("1 2 3"));
}
else
{
display.drawTriangle(50, 6, 64, 6, 50, 1, SH110X_BLACK);
}
display.setTextColor(SH110X_WHITE);
}
void displayCursor(int indexFormula)
{
int underlineY = indexFormula / LINE_CHAR_WIDTH;
int underlineX = indexFormula;
for (int i = 0; i < underlineY; i++)
{
underlineX = underlineX - LINE_CHAR_WIDTH;
}
underlineX = underlineX * CHAR_WIDTH;
underlineY = (((underlineY + 1) * CHAR_HEIGHT) + (CHAR_HEIGHT + 2)) - 1;
display.drawFastHLine(underlineX, underlineY, CHAR_WIDTH, 1);
}
void displayPreview()
{
display.setCursor(7 * CHAR_WIDTH, 0);
display.print("PREVIEW");
display.setCursor(0, 8);
display.print(formula::savedFormulas[interface::savedFormulasIndex]);
}
void displayStatusBar()
{
displayCurrentFile();
displayExprMode();
displayLiveMode();
}
void displayCurrentFile()
{
char buffer[4];
snprintf(buffer, sizeof(buffer), "%03d", interface::currentFileIndex);
display.setCursor(8, 0);
display.print(buffer);
}
void displayChaosMode()
{
int x = display.getCursorX();
int y = display.getCursorY();
if (modes::bytebeatMode == modes::bytebeat_modes::CHAOS)
{
display.setCursor(87, 1);
display.setTextColor(SH110X_BLACK);
display.print("666");
display.setTextColor(SH110X_WHITE);
}
display.setCursor(x, y);
}
void displayEditor(int prevY)
{
display.drawBitmap(0, 0, assetsBmp::STATUSBAR_BMP, 128, 9, SH110X_WHITE);
displayStatusBar();
displayChaosMode();
displayCompileFlagState(formula::compileFlag);
displayCursor(interface::indexFormula);
display.setCursor(0, 10);
display.print((const char *)formula::formula);
display.setCursor(interface::indexFormula * CHAR_WIDTH, prevY);
}
bool needClear()
{
return !(modes::bytebeatMode == modes::VISUALIZER) && !(modes::bytebeatMode == modes::POPUP);
}
void updateDisplay()
{
// if (interface::needDisplay)
// {
if (!(modes::bytebeatMode == modes::VISUALIZER) && !(modes::bytebeatMode == modes::POPUP))
{
display.clearDisplay();
}
switch (modes::bytebeatMode)
{
case modes::bytebeat_modes::CHAOS:
case modes::bytebeat_modes::EDITOR:
{
int prevY = display.getCursorY();
display.clearDisplay();
display.setCursor(0, 0);
displayEditor(prevY);
break;
}
case modes::bytebeat_modes::VISUALIZER:
{
visualizer::displayVisualizer(display);
break;
}
case modes::bytebeat_modes::POPUP:
{
display.drawBitmap(24, 24, assetsBmp::SAVE_POPUP_BMP, 81, 35, SH110X_WHITE);
break;
}
case modes::bytebeat_modes::CONFIG:
{
if (interface::tabMenuState == 0)
{
if (interface::funcState == 1)
{
displayPreview();
}
else
{
displaySavedFormulas();
}
}
else if (interface::tabMenuState == 999)
{
displaySettings(interface::settingsIndex);
}
break;
}
default:
{
break;
}
}
display.display();
interface::needDisplay = 0;
// }
}
}
#endif
Something I noticed is trying to optimize calls to display() cause more problems than when not optimized.