Not updating the screen causes my audio output to slow down

Hi guys,
I'm working with the samd21 xiao.

In my project, I generate an audio output, updating the DAC at a quick rate with timers.

The project also takes a midi input, but since I was updating the screen on every loop, the processing of the midi messages was laggy.

My idea was to update the OLED screen only if a button was pressed. The solution works, but I'm facing a problem that not seems logical for me.

When updating the screen at every loop the audio output I expect is ok.
But when adding a condition (if(needDisplay)){/* do the updating screen stuff */}), the audio output is very laggy, against all expectations, precisely because it should be faster.

(loud audio take care)

Here is a video with the audio, first without the condition, and after with the condition.

Do u have any toughts about that ?

I can post the three files concerned by the problem:

main.cpp

// BB LIBRARY
#include <globals.h>
#include <assetsBmps.h>
#include <modesHelper.h>
#include <formulaHelper.h>
#include <sdHelper.h>
#include <visualizerHelper.h>
#include <interfaceHelper.h>
#include <displayHelper.h>
// #include <samplerHelper.h>
#include <midiHelper.h>

// LIBRARIES
#include <TimerTC3.h>
#define USE_TIMER_TC3  // use TimerTc3
#define TIMER_TIME 125 // 1/8000 Hz = 125 micro seconds
#define TIMER TimerTc3
#define DAC_PIN 0 // pin of the XIAO DAC

// TIMERS && INTERRUPTS
void GenerateAudioStream();

void setup()
{
    beginDebug();

    debugln(F("Set up starting"));

    // sd::configure();
    // sd::importFormulas(formula::savedFormulas);

    interface::configure();

    display::configure();

    midi::configure();

    pinMode(DAC_PIN, OUTPUT);
    TIMER.initialize(TIMER_TIME);
    TIMER.attachInterrupt(GenerateAudioStream);

    debugln(F("Set up completed"));
}

void loop()
{
    interface::checkButtons();
    midi::readMidi();
    formula::compileFormula();
    display::updateDisplay();

    // static int i = 0;
    // if (i++ == 150)
    //     interface::doubleClickFunc();
}

void GenerateAudioStream()
{
    if (formula::compileFlag)
    {
        static int prescaler = 0;
        static int prescalerCounter = 0;
        if (++prescalerCounter < prescaler)
        {
            return;
        }
        prescalerCounter = 0;

        formula::byteBeatResult = te_eval((te_expr *)formula::expr);

        if (formula::resultResolution == 0)
        {
            analogWrite(DAC_PIN, (uint8_t)formula::byteBeatResult);
        }
        else if (formula::resultResolution == 1)
        {
            analogWrite(DAC_PIN, (uint16_t)formula::byteBeatResult);
        }
        else if (formula::resultResolution == 2)
        {
            analogWrite(DAC_PIN, (uint32_t)formula::byteBeatResult);
        }
        else
        {
        }
    }
    else
    {
        analogWrite(DAC_PIN, 0);
    }

    if (formula::modeT)
    {
        formula::t += formula::tIncrement;
    }
    else
    {
        formula::t -= formula::tIncrement;
    }
}

displayHelper.h

#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

interfaceHelper.h

#ifndef INTERFACE_HELPER_H
#define INTERFACE_HELPER_H

using namespace ace_button;

// Boutton function séparé pour permettre la combinaison de touches
AceButton button(PIN_DIGITAL_2);

// bouttons regroupés sur la pin analogue 1
static const uint8_t NUM_BUTTONS = 7;
static AceButton b0(nullptr, 0);
static AceButton b1(nullptr, 1);
static AceButton b2(nullptr, 2);
static AceButton b3(nullptr, 3);
static AceButton b4(nullptr, 4);
static AceButton b5(nullptr, 5);
static AceButton b6(nullptr, 6);
static AceButton *const BUTTONS[NUM_BUTTONS] = {
    &b0, &b1, &b2, &b3, &b4, &b5, &b6};

// Define the ADC voltage levels for each button.
// For 4 buttons, we need 5 levels.
static const uint8_t NUM_LEVELS = NUM_BUTTONS + 1;
static const uint16_t LEVELS[NUM_LEVELS] = {
    0,
    130,
    250,
    370,
    460,
    530,
    620,
    1023};

// The LadderButtonConfig constructor binds the AceButton to the
// LadderButtonConfig.
static LadderButtonConfig buttonsConfig(
    PIN_ANALOG_1, NUM_LEVELS, LEVELS, NUM_BUTTONS, BUTTONS);

namespace interface
{

    const static int SYMBOLS = 0;
    const static int NUMBERS = 1;
    const static int FUNCTIONS = 2;
    const int EXPR_MODES_SIZE = 3;
    const int exprModes[EXPR_MODES_SIZE] = {SYMBOLS, NUMBERS, FUNCTIONS};
    int exprModeIndex = 0;

    modes::bytebeat_modes previousSamplerMode = modes::bytebeatMode;

    int cursorMenuState = 0;
    int tabMenuState = 0;
    int indexFormula = 0;

    int currentFileIndex = 0;
    int settingsIndex = 0;

    int savedFormulasIndex = 0;

    bool funcState = 0;

    const int NUMBER_ARRAY_SIZE = 10;
    const char numberArray[NUMBER_ARRAY_SIZE] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    int numberArrayIndex = 0;

    const int PSI_ARRAY_SIZE = 11;
    const char psiArray[PSI_ARRAY_SIZE] PROGMEM = {'%', '^', '&', '|', '>', '<', '!', '/', '+', '-', '*'};
    int psiArrayIndex = 0;

    // TODO rajouter la PROGMEM pour ce tableau aussi
    const int TRIGO_ARRAY_SIZE = 3;
    const char *trigoArray[TRIGO_ARRAY_SIZE] = {"sin(", "cos(", "tan("};
    int trigoArrayIndex = 0;

    bool needDisplay = 1;

    void configure();

    void pressedFunc();
    void handleEventButton(AceButton *, uint8_t, uint8_t);

    void pressedDown();
    void pressedUp();
    void pressedLeft();
    void pressedRight();
    void pressedMenu();
    void pressedYes();
    void pressedNo();
    void repeatPressLeft();
    void repeatPressRight();
    void longPressNo();
    void checkButtons();
    void handleEventButtons(AceButton *, uint8_t, uint8_t);

    bool isBeforeAFunc(const char *, int);
    bool isAfterAFunc(const char *, int);
    void eraseNextFourChar(volatile char *, int);

    void configure()
    {
        pinMode(PIN_ANALOG_1, INPUT);
        pinMode(PIN_DIGITAL_2, INPUT_PULLUP);

        modes::setBytebeatMode(modes::EDITOR);

        ButtonConfig *buttonConfig = button.getButtonConfig();
        buttonConfig->setEventHandler(handleEventButton);
        buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);

        // Configure the ButtonConfig with the event handler, and enable all higher
        // level events.
        buttonsConfig.setEventHandler(handleEventButtons);
        buttonsConfig.setFeature(ButtonConfig::kFeatureClick);
        buttonsConfig.setFeature(ButtonConfig::kFeatureLongPress);
        buttonsConfig.setFeature(ButtonConfig::kFeatureRepeatPress);
    }

    void pressedFunc()
    {
        funcState = 1;
        return;
    }
    void releaseFunc()
    {
        funcState = 0;
        return;
    }

    void doubleClickFunc()
    {
        needDisplay = 1;

        if (modes::bytebeatMode != modes::VISUALIZER)
        {
            modes::setBytebeatMode(modes::VISUALIZER);
        }
        else
        {
            interface::needDisplay = 1;
            modes::setBytebeatMode(modes::EDITOR);
        }
    }

    void handleEventButton(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedFunc();
            break;
        case AceButton::kEventReleased:
            releaseFunc();
            break;
        case AceButton::kEventDoubleClicked:
            doubleClickFunc();
            break;
        }
    }

    // The buttonConfig.checkButtons() should be called every 4-5ms or faster, if
    // the debouncing time is ~20ms. On ESP8266, analogRead() must be called *no*
    // faster than 4-5ms to avoid a bug which disconnects the WiFi connection.
    void checkButtons()
    {
        static unsigned long prev = millis();

        unsigned long now = millis();
        if (now - prev > 4)
        {
            button.check();
            buttonsConfig.checkButtons();
            prev = now;
        }
    }

    void pressedLeft()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (funcState)
            {
                formula::insertAt("(", indexFormula);
                return;
            }

            if (indexFormula != 0 && isAfterAFunc((const char *)formula::formula, indexFormula))
            {
                indexFormula -= 4;
            }
            else if (--indexFormula < 0)
            {
                indexFormula = 0;
            }
            return;
        }
        case modes::CHAOS:
        {
            for (int i = 0; i < formula::FORMULA_SIZE; i++)
            {
                for (int j = 0; j < PSI_ARRAY_SIZE; j++)
                {
                    bool isNotForbiddenSymbol = formula::formula[i] != '(' && formula::formula[i] != ')' && formula::formula[i] != 't';
                    if (formula::formula[i] == pgm_read_byte(psiArray + j) && isNotForbiddenSymbol)
                    {
                        int index = j;

                        if (index <= 0)
                        {
                            index = PSI_ARRAY_SIZE - 1;
                        }
                        if (pgm_read_byte(psiArray + (index - 1)) == 't')
                        {
                            index = PSI_ARRAY_SIZE - 1;
                        }
                        else
                        {
                            index -= 1;
                        }
                        formula::formula[i] = pgm_read_word_near(psiArray + index);

                        break;
                    }
                }
            }
            return;
        }
            // case modes::CONFIG:
            // {
            //     if (--tabMenuState < 0)
            //     {
            //         tabMenuState = 0;
            //     }
            //     return;
            // }
            // case modes::READING:
            // {

            //     if (funcState)
            //     {
            //         sampler::agrandirByRight(8);
            //     }
            //     else
            //     {
            //         sampler::trimByRight(8);
            //     }
            //     return;
            // }

        default:
            return;
        }
    }

    void repeatPressLeft()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (indexFormula != 0 && isAfterAFunc((const char *)formula::formula, indexFormula))
            {
                indexFormula -= 4;
            }
            else if (--indexFormula < 0)
            {
                indexFormula = 0;
            }
            break;
        }
        // case modes::READING:
        // {
        //     if (funcState)
        //     {
        //         sampler::agrandirByRight(8);
        //     }
        //     else
        //     {
        //         sampler::trimByRight(8);
        //     }
        //     return;
        // }
        default:
            return;
        }
    }

    void pressedRight()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (funcState)
            {
                formula::insertAt(")", indexFormula);
                return;
            }

            if (indexFormula != formula::FORMULA_SIZE - 3 && isBeforeAFunc((const char *)formula::formula, indexFormula))
            {
                indexFormula += 4;
            }
            else if (++indexFormula >= formula::FORMULA_SIZE - 1)
            {
                indexFormula = formula::FORMULA_SIZE - 1;
            }
            return;
        }
        case modes::CHAOS:
        {
            for (int i = 0; i < formula::FORMULA_SIZE; i++)
            {
                for (int j = 0; j < PSI_ARRAY_SIZE; j++)
                {
                    bool isNotForbiddenSymbol = formula::formula[i] != '(' && formula::formula[i] != ')' && formula::formula[i] != 't';
                    if (formula::formula[i] == pgm_read_byte(psiArray + j) && isNotForbiddenSymbol)
                    {

                        int index = j;

                        if (index >= PSI_ARRAY_SIZE - 1)
                        {
                            index = 0;
                        }
                        if (pgm_read_byte(psiArray + (index + 1)) == 't')
                        {
                            index += 2;
                        }
                        else
                        {
                            index += 1;
                        }
                        formula::formula[i] = pgm_read_byte(psiArray + index);
                        break;
                    }
                }
            }
            return;
        }
        // case modes::CONFIG:
        // {
        //     if (++tabMenuState > 1)
        //     {
        //         tabMenuState = 1;
        //     }
        //     return;
        // }
        // case modes::READING:
        // {
        //     if (funcState)
        //     {
        //         agrandirByLeft(8);
        //     }
        //     else
        //     {
        //         trimByLeft(8);
        //     }
        //     return;
        // }
        default:
            return;
        }
    }

    void repeatPressRight()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (indexFormula != formula::FORMULA_SIZE - 3 && isBeforeAFunc((const char *)formula::formula, indexFormula))
            {
                indexFormula += 4;
            }
            else if (++indexFormula >= formula::FORMULA_SIZE - 1)
            {
                indexFormula = formula::FORMULA_SIZE - 1;
            }
            return;
        }
        // case modes::READING:
        // {
        //     if (funcState)
        //     {
        //         agrandirByLeft(8);
        //     }
        //     else
        //     {
        //         trimByLeft(8);
        //     }
        //     return;
        // }
        default:
            return;
        }
    }

    void pressedDown()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (funcState)
            {
                formula::insertAt(" ", indexFormula);
                return;
            }

            switch (exprModes[exprModeIndex])
            {
            case SYMBOLS:

                if (--psiArrayIndex < 0)
                {
                    psiArrayIndex = PSI_ARRAY_SIZE - 1;
                }

                if (isBeforeAFunc((const char *)formula::formula, indexFormula))
                {
                    eraseNextFourChar(formula::formula, indexFormula);
                    if (--indexFormula < 0)
                        indexFormula = 0;
                }

                formula::formula[indexFormula] = pgm_read_word_near(psiArray + psiArrayIndex);
                break;
            case NUMBERS:

                if (--numberArrayIndex < 0)
                {
                    numberArrayIndex = NUMBER_ARRAY_SIZE - 1;
                }

                if (indexFormula != 0 && isBeforeAFunc((const char *)formula::formula, indexFormula))
                {
                    eraseNextFourChar(formula::formula, indexFormula);
                    if (--indexFormula < 0)
                        indexFormula = 0;
                }

                formula::formula[indexFormula] = pgm_read_word_near(numberArray + numberArrayIndex);

                break;
            case FUNCTIONS:
                if (--trigoArrayIndex < 0)
                {
                    trigoArrayIndex = TRIGO_ARRAY_SIZE - 1;
                }
                const char *insert = trigoArray[trigoArrayIndex];
                if (isBeforeAFunc((const char *)formula::formula, indexFormula))
                {
                    formula::formula[indexFormula] = insert[0];
                    formula::formula[indexFormula + 1] = insert[1];
                    formula::formula[indexFormula + 2] = insert[2];
                    formula::formula[indexFormula + 3] = insert[3];
                }
                else
                {
                    if (indexFormula < formula::FORMULA_SIZE - 4)
                    {
                        formula::insertAt(insert, indexFormula);
                    }
                }
                break;
            }
            return;
        }
        case modes::CHAOS:
        {
            for (int i = 0; i < formula::FORMULA_SIZE; i++)
            {
                for (int j = 0; j < NUMBER_ARRAY_SIZE; j++)
                {
                    bool isNotForbiddenSymbol = formula::formula[i] != ' ';
                    if (formula::formula[i] == pgm_read_byte(numberArray + j) && isNotForbiddenSymbol)
                    {

                        int index = j;
                        if (index <= 0)
                        {
                            index = NUMBER_ARRAY_SIZE - 1;
                        }
                        else
                        {
                            index -= 1;
                        }
                        formula::formula[i] = pgm_read_byte(numberArray + index);

                        break;
                    }
                }
            }
            return;
        }
        case modes::VISUALIZER:
        {
            visualizer::incrementVisualizersIndex();
            return;
        }
        case modes::CONFIG:
        {
            if (tabMenuState == 1)
            {
                if (++settingsIndex > 1)
                {
                    settingsIndex = 1;
                    // bbConfig.setPrescaler(4);
                }
                // bbConfig.setPrescaler(prescaler);
                // bbConfig.configSave();
            }
            else if (tabMenuState == 0)
            {
                ++savedFormulasIndex;
            }
            return;
        }
        default:
            return;
        }
    }

    void pressedUp()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (funcState)
            {
                formula::insertAt("t", indexFormula);
                return;
            }

            switch (exprModes[exprModeIndex])
            {
            case SYMBOLS:
                if (++psiArrayIndex > PSI_ARRAY_SIZE - 1)
                {
                    psiArrayIndex = 0;
                }

                if (indexFormula != 0 && isBeforeAFunc((const char *)formula::formula, indexFormula))
                {
                    eraseNextFourChar(formula::formula, indexFormula);
                }

                formula::formula[indexFormula] = pgm_read_word_near(psiArray + psiArrayIndex);
                break;
            case NUMBERS:

                if (++numberArrayIndex > NUMBER_ARRAY_SIZE - 1)
                {
                    numberArrayIndex = 0;
                }

                if (indexFormula != 0 && isBeforeAFunc((const char *)formula::formula, indexFormula))
                {
                    eraseNextFourChar(formula::formula, indexFormula);
                }

                formula::formula[indexFormula] = pgm_read_word_near(numberArray + numberArrayIndex);
                break;
            case FUNCTIONS:
                if (++trigoArrayIndex > TRIGO_ARRAY_SIZE - 1)
                {
                    trigoArrayIndex = 0;
                }
                const char *insert = trigoArray[trigoArrayIndex];

                if (isBeforeAFunc((const char *)formula::formula, indexFormula))
                {
                    formula::formula[indexFormula] = insert[0];
                    formula::formula[indexFormula + 1] = insert[1];
                    formula::formula[indexFormula + 2] = insert[2];
                    formula::formula[indexFormula + 3] = insert[3];
                }
                else
                {
                    if (indexFormula < formula::FORMULA_SIZE - 4)
                    {
                        formula::insertAt(insert, indexFormula);
                    }
                }
                break;
            }
            return;
        }
        case modes::CHAOS:
        {
            for (int i = 0; i < formula::FORMULA_SIZE; i++)
            {
                for (int j = 0; j < NUMBER_ARRAY_SIZE; j++)
                {
                    bool isNotForbiddenSymbol = formula::formula[i] != ' ';
                    if (formula::formula[i] == pgm_read_byte(numberArray + j) && isNotForbiddenSymbol)
                    {

                        int index = j;
                        if (index >= NUMBER_ARRAY_SIZE - 1)
                        {
                            index = 0;
                        }
                        else
                        {
                            index += 1;
                        }
                        formula::formula[i] = pgm_read_byte(numberArray + index);
                        break;
                    }
                }
            }
            return;
        }
        case modes::VISUALIZER:
        {
            visualizer::decrementVisualizersIndex();
            return;
        }
        case modes::CONFIG:
        {
            if (tabMenuState == 1)
            {
                if (--settingsIndex < 0)
                {
                    settingsIndex = 0;
                }
                // bbConfig.setPrescaler(prescaler);
                // bbConfig.configSave();
            }
            else if (tabMenuState == 0)
            {
                if (--savedFormulasIndex < 0)
                    savedFormulasIndex = 5;
            }
            return;
        }
        default:
            return;
        }
    }

    void pressedMenu()
    {
        switch (modes::bytebeatMode)
        {
        case modes::CHAOS:
        case modes::EDITOR:
        {
            if (funcState)
            {
                formula::compileFlag = 0;
                strcpy(formula::holdedFormula, (const char *)formula::formula);
                formula::compileFlag = 1;
                formula::liveMode = !(formula::liveMode);

                // modes::setBytebeatMode(modes::SAMPLING;
            }
            else
            {
                modes::setBytebeatMode(modes::CONFIG);
            }
            return;
        }
        case modes::CONFIG:
        {
            modes::setBytebeatMode(modes::EDITOR);
            return;
        }
        case modes::SAMPLING:
        {
            modes::setBytebeatMode(modes::SAMPLED);
            return;
        }
        case modes::READING:
        {
            modes::setBytebeatMode(modes::SAMPLING);
            return;
        }
        default:
            return;
        }
    }

    void pressedYes()
    {
        switch (modes::bytebeatMode)
        {
        case modes::CHAOS:
        case modes::EDITOR:
        {
            if (funcState)
            {
                modes::setBytebeatMode(modes::POPUP);
                return;
            }

            if (++exprModeIndex >= EXPR_MODES_SIZE)
            {
                exprModeIndex = 0;
            }
            return;
        }
        case modes::POPUP:
        {
            if (!funcState)
            {
                if (currentFileIndex > 6)
                {
                    // sd::saveFormula(currentFileIndex);
                }
                modes::setBytebeatMode(modes::EDITOR);
            }
            return;
        }
        case modes::CONFIG:
        {
            if (tabMenuState == 0)
            {
                strncpy((char *)formula::formula, formula::savedFormulas[savedFormulasIndex], formula::FORMULA_SIZE - 1);
                currentFileIndex = savedFormulasIndex + 1;
                modes::setBytebeatMode(modes::EDITOR);
            }
            return;
        }
        default:
            return;
        }
    }

    void pressedNo()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            if (funcState)
            {
                modes::setBytebeatMode(modes::CHAOS);
                return;
            }

            if (indexFormula != 0 && isBeforeAFunc((const char *)formula::formula, indexFormula))
            {
                eraseNextFourChar(formula::formula, indexFormula);
                if (isAfterAFunc((const char *)formula::formula, indexFormula))
                {
                    indexFormula -= 4;
                }
                else
                {
                    --(indexFormula);
                }
            }
            else if (indexFormula == 0 && isBeforeAFunc((const char *)formula::formula, indexFormula))
            {
                eraseNextFourChar(formula::formula, indexFormula);
            }
            else
            {
                formula::formula[indexFormula] = ' ';
                if (indexFormula > 0)
                {
                    if (isAfterAFunc((const char *)formula::formula, indexFormula))
                    {
                        indexFormula -= 4;
                    }
                    else
                    {
                        --(indexFormula);
                    }
                }
            }
            return;
        }
        case modes::CHAOS:
        case modes::VISUALIZER:
        case modes::CONFIG:
        case modes::POPUP:
        case modes::SAMPLING:
        case modes::SAMPLED:
        case modes::READING:
        {
            modes::setBytebeatMode(modes::EDITOR);
            return;
        }
        default:
            return;
        }
    }

    void longPressedNo()
    {
        switch (modes::bytebeatMode)
        {
        case modes::EDITOR:
        {
            strncpy((char *)formula::formula, "", formula::FORMULA_SIZE);
            indexFormula = 0;
        }
        default:
            return;
        }
    }

    bool isBeforeAFunc(const char *formula, int indexFormula)
    {
        bool isTrigo = formula[indexFormula] == 'c' || formula[indexFormula] == 's' || ((formula[indexFormula] == 't' && formula[indexFormula + 1] == 'a'));
        return isTrigo;
    }

    bool isAfterAFunc(const char *formula, int indexFormula)
    {
        bool isTrigo = formula[indexFormula - 2] == 's' || formula[indexFormula - 2] == 'n';
        return isTrigo;
    }

    void eraseNextFourChar(volatile char *formula, int indexFormula)
    {
        formula[indexFormula] = ' ';
        formula[indexFormula + 1] = ' ';
        formula[indexFormula + 2] = ' ';
        formula[indexFormula + 3] = ' ';
    }

    void button0Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {

        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedYes();
            break;
        case AceButton::kEventLongPressed:;
            break;
        }
    }
    void button1Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedUp();
            break;
        case AceButton::kEventLongPressed:;
            break;
        }
    }

    void button2Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedNo();
            break;
        case AceButton::kEventLongPressed:
            longPressedNo();
            break;
        }
    }

    void button3Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {

        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedLeft();
            break;
        case AceButton::kEventRepeatPressed:
            repeatPressLeft();
            break;
        }
    }
    void button4Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedDown();
            break;
        case AceButton::kEventLongPressed:;
            break;
        }
    }
    void button5Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedRight();
            break;
        case AceButton::kEventRepeatPressed:
            repeatPressRight();
            break;
        }
    }
    void button6Handler(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        switch (eventType)
        {
        case AceButton::kEventPressed:
            pressedMenu();
            break;
        case AceButton::kEventLongPressed:;
            break;
        }
    }

    // The event handler for the button.
    void handleEventButtons(AceButton *button, uint8_t eventType, uint8_t buttonState)
    {
        needDisplay = 1;
        switch (button->getPin())
        {
        case 0:
            button0Handler(button, eventType, buttonState);
            break;
        case 1:
            button1Handler(button, eventType, buttonState);
            break;
        case 2:
            button2Handler(button, eventType, buttonState);
            break;
        case 3:
            button3Handler(button, eventType, buttonState);
            break;
        case 4:
            button4Handler(button, eventType, buttonState);
            break;
        case 5:
            button5Handler(button, eventType, buttonState);
            break;
        case 6:
            button6Handler(button, eventType, buttonState);
            break;
        }
    }
}
#endif

The part that I'm talking about is the if l227-228 in displayHelper.h, the variable needDisplay is updated in interfaceHelper when a button is pressed

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.