#include "SharedState.h" #include "LuckyStrategy.h" #include "ArpStrategy.h" #include "EuclideanStrategy.h" #include "MarkovStrategy.h" #include "CellularAutomataStrategy.h" #include "LSystemStrategy.h" // Global state variables Step sequence[NUM_TRACKS][NUM_STEPS]; Step nextSequence[NUM_TRACKS][NUM_STEPS]; volatile bool sequenceChangeScheduled = false; volatile bool needsPanic = false; UIState currentState = UI_MENU_MAIN; // Menus MenuItem menuItems[] = { { "Main", MENU_ID_GROUP_MAIN, true, true, 0 }, { "Playback", MENU_ID_PLAYBACK, false, false, 1 }, { "Melody", MENU_ID_MELODY, false, false, 1 }, { "Scale", MENU_ID_SCALE, false, false, 1 }, { "Steps", MENU_ID_STEPS, false, false, 1 }, { "Tempo", MENU_ID_TEMPO, false, false, 1 }, { "Song Mode", MENU_ID_SONG_MODE, false, false, 1 }, { "Track", MENU_ID_GROUP_TRACK, true, true, 0 }, { "Track", MENU_ID_TRACK_SELECT, false, false, 1 }, { "Mute", MENU_ID_MUTE, false, false, 1 }, { "Flavour", MENU_ID_FLAVOUR, false, false, 1 }, { "Mutation", MENU_ID_MUTATION, false, false, 1 }, { "Theme 1", MENU_ID_THEME_1, false, false, 1 }, { "Theme 2", MENU_ID_THEME_2, false, false, 1 }, { "Theme 3", MENU_ID_THEME_3, false, false, 1 }, { "Theme 4", MENU_ID_THEME_4, false, false, 1 }, { "Theme 5", MENU_ID_THEME_5, false, false, 1 }, { "Theme 6", MENU_ID_THEME_6, false, false, 1 }, { "Theme 7", MENU_ID_THEME_7, false, false, 1 }, { "Setup", MENU_ID_GROUP_SETUP, true, false, 0 }, { "Channel", MENU_ID_CHANNEL, false, false, 1 }, { "Reset", MENU_ID_RESET, false, false, 1 }, { "Patches", MENU_ID_GROUP_PATCHES, true, false, 0 }, { "Bank 1", MENU_ID_BANK_1, true, false, 1 }, { "Save 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 0), false, false, 2 }, { "Load 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 1), false, false, 2 }, { "Save 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 2), false, false, 2 }, { "Load 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 3), false, false, 2 }, { "Save 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 4), false, false, 2 }, { "Load 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 5), false, false, 2 }, { "Save 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 6), false, false, 2 }, { "Load 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 7), false, false, 2 }, { "Bank 2", MENU_ID_BANK_2, true, false, 1 }, { "Save 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 8), false, false, 2 }, { "Load 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 9), false, false, 2 }, { "Save 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 10), false, false, 2 }, { "Load 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 11), false, false, 2 }, { "Save 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 12), false, false, 2 }, { "Load 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 13), false, false, 2 }, { "Save 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 14), false, false, 2 }, { "Load 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 15), false, false, 2 }, { "Bank 3", MENU_ID_BANK_3, true, false, 1 }, { "Save 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 16), false, false, 2 }, { "Load 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 17), false, false, 2 }, { "Save 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 18), false, false, 2 }, { "Load 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 19), false, false, 2 }, { "Save 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 20), false, false, 2 }, { "Load 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 21), false, false, 2 }, { "Save 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 22), false, false, 2 }, { "Load 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 23), false, false, 2 }, { "Bank 4", MENU_ID_BANK_4, true, false, 1 }, { "Save 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 24), false, false, 2 }, { "Load 1", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 25), false, false, 2 }, { "Save 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 26), false, false, 2 }, { "Load 2", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 27), false, false, 2 }, { "Save 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 28), false, false, 2 }, { "Load 3", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 29), false, false, 2 }, { "Save 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 30), false, false, 2 }, { "Load 4", (MenuItemID)(MENU_ID_PATCH_ACTIONS_START + 31), false, false, 2 } }; extern const int menuItemsCount = sizeof(menuItems) / sizeof(MenuItem); bool isItemVisible(int index) { if (menuItems[index].indentLevel == 0) return true; for (int i = index - 1; i >= 0; i--) { if (menuItems[i].indentLevel < menuItems[index].indentLevel) { return menuItems[i].expanded; } } return true; } int menuSelection = 0; volatile bool trackMute[NUM_TRACKS]; int randomizeTrack = 0; volatile int numSteps = NUM_STEPS; volatile int playbackStep = 0; volatile int midiChannels[NUM_TRACKS]; int scaleNotes[12]; int numScaleNotes = 0; int melodySeeds[NUM_TRACKS]; volatile int queuedTheme = -1; volatile int currentThemeIndex = 1; extern const uint32_t EEPROM_MAGIC = 0x4242424D; MelodyStrategy* strategies[] = { new LuckyStrategy(), new ArpStrategy(), new EuclideanStrategy(), new MarkovStrategy(), new CellularAutomataStrategy(), new LSystemStrategy()}; extern const int numStrategies = 6; int currentStrategyIndices[NUM_TRACKS]; volatile PlayMode playMode = MODE_POLY; volatile bool mutationEnabled = false; volatile bool songModeEnabled = false; volatile int songRepeatsRemaining = 0; volatile int nextSongRepeats = 0; volatile bool songModeNeedsNext = false; volatile bool isPlaying = false; volatile int tempo = 120; // BPM volatile unsigned long lastClockTime = 0; volatile int clockCount = 0; // Encoder State volatile int encoderDelta = 0; // Button State bool lastButtonState = HIGH; unsigned long lastDebounceTime = 0; bool buttonActive = false; bool buttonConsumed = false; unsigned long buttonPressTime = 0;