Moved over the rotation menu to new system

Had to change how the values where stored in RAM from singed to unsigned to be able to use the generic menu features. Also had to add the MenuEntrySub as a parameter to the menu callback functions to be able fo display and store the correct values.

Did some major cleanup now that the special case of rotator menu is gone together with all uses of the old version of the sub menu struct.
This commit is contained in:
Mikael Degerfält 2019-06-23 01:17:56 +02:00
parent 6c721e8b65
commit bddbffd51d
4 changed files with 189 additions and 287 deletions

View file

@ -81,8 +81,8 @@ unsigned short fastPatch[7] = {0,0,0,0,0,0,0};
byte rotatorOn = 0; byte rotatorOn = 0;
byte currentRotation = 0; byte currentRotation = 0;
int rotations[4] = { -5, -10, -7, -14 }; // semitones { -5, -10, -7, -14 }; uint16_t rotations[4]; // semitones { -5, -10, -7, -14 };
int parallel = 7; // semitones uint16_t parallel; // = 7; // semitones
byte gateOpen = 0; // setting for gate always open, note on sent for every time fingering changes, no matter the breath status byte gateOpen = 0; // setting for gate always open, note on sent for every time fingering changes, no matter the breath status
@ -335,11 +335,11 @@ void setup() {
fastPatch[5] = readSetting(FP6_ADDR); fastPatch[5] = readSetting(FP6_ADDR);
fastPatch[6] = readSetting(FP7_ADDR); fastPatch[6] = readSetting(FP7_ADDR);
dipSwBits = readSetting(DIPSW_BITS_ADDR); dipSwBits = readSetting(DIPSW_BITS_ADDR);
parallel = readSetting(PARAL_ADDR)-24; parallel = readSetting(PARAL_ADDR);
rotations[0] = readSetting(ROTN1_ADDR)-24; rotations[0] = readSetting(ROTN1_ADDR);
rotations[1] = readSetting(ROTN2_ADDR)-24; rotations[1] = readSetting(ROTN2_ADDR);
rotations[2] = readSetting(ROTN3_ADDR)-24; rotations[2] = readSetting(ROTN3_ADDR);
rotations[3] = readSetting(ROTN4_ADDR)-24; rotations[3] = readSetting(ROTN4_ADDR);
priority = readSetting(PRIO_ADDR); priority = readSetting(PRIO_ADDR);
vibSens = readSetting(VIB_SENS_ADDR); vibSens = readSetting(VIB_SENS_ADDR);
vibRetn = readSetting(VIB_RETN_ADDR); vibRetn = readSetting(VIB_RETN_ADDR);
@ -639,10 +639,10 @@ void loop() {
} }
} }
if (rotatorOn) { if (rotatorOn) {
midiSendNoteOn(noteValueCheck(fingeredNote + parallel), velocitySend); // send Note On message for new note midiSendNoteOn(noteValueCheck(fingeredNote + parallel-24), velocitySend); // send Note On message for new note
if (currentRotation < 3) currentRotation++; if (currentRotation < 3) currentRotation++;
else currentRotation = 0; else currentRotation = 0;
midiSendNoteOn(noteValueCheck(fingeredNote + rotations[currentRotation]), velocitySend); // send Note On message for new note midiSendNoteOn(noteValueCheck(fingeredNote + rotations[currentRotation]-24), velocitySend); // send Note On message for new note
} }
if (!priority) { // mono prio to base note if (!priority) { // mono prio to base note
midiSendNoteOn(fingeredNote, velocitySend); // send Note On message for new note midiSendNoteOn(fingeredNote, velocitySend); // send Note On message for new note
@ -676,8 +676,8 @@ void loop() {
} }
} }
if (rotatorOn) { if (rotatorOn) {
midiSendNoteOff(noteValueCheck(activeNote + parallel)); // send Note Off message for old note midiSendNoteOff(noteValueCheck(activeNote + parallel-24 )); // send Note Off message for old note
midiSendNoteOff(noteValueCheck(activeNote + rotations[currentRotation])); // send Note Off message for old note midiSendNoteOff(noteValueCheck(activeNote + rotations[currentRotation]-24)); // send Note Off message for old note
} }
if (!priority) { if (!priority) {
midiSendNoteOff(activeNote); // send Note Off message midiSendNoteOff(activeNote); // send Note Off message
@ -725,8 +725,8 @@ void loop() {
} }
} }
if (rotatorOn) { if (rotatorOn) {
midiSendNoteOff(noteValueCheck(activeNote + parallel)); // send Note Off message for old note midiSendNoteOff(noteValueCheck(activeNote + parallel-24)); // send Note Off message for old note
midiSendNoteOff(noteValueCheck(activeNote + rotations[currentRotation])); // send Note Off message for old note midiSendNoteOff(noteValueCheck(activeNote + rotations[currentRotation]-24)); // send Note Off message for old note
} }
if ((parallelChord || subOctaveDouble || rotatorOn) && !priority) { // poly playing, send old note off before new note on if ((parallelChord || subOctaveDouble || rotatorOn) && !priority) { // poly playing, send old note off before new note on
midiSendNoteOff(activeNote); // send Note Off message for old note midiSendNoteOff(activeNote); // send Note Off message for old note
@ -750,10 +750,10 @@ void loop() {
} }
} }
if (rotatorOn) { if (rotatorOn) {
midiSendNoteOn(noteValueCheck(fingeredNote + parallel), velocitySend); // send Note On message for new note midiSendNoteOn(noteValueCheck(fingeredNote + parallel-24), velocitySend); // send Note On message for new note
if (currentRotation < 3) currentRotation++; if (currentRotation < 3) currentRotation++;
else currentRotation = 0; else currentRotation = 0;
midiSendNoteOn(noteValueCheck(fingeredNote + rotations[currentRotation]), velocitySend); // send Note On message for new note midiSendNoteOn(noteValueCheck(fingeredNote + rotations[currentRotation]-24), velocitySend); // send Note On message for new note
} }
if (!priority) { if (!priority) {

View file

@ -37,8 +37,8 @@ extern unsigned short vibDirection; //direction of first vibrato wave UPWD or DN
extern unsigned short fastPatch[7]; extern unsigned short fastPatch[7];
extern byte rotatorOn; extern byte rotatorOn;
extern byte currentRotation; extern byte currentRotation;
extern int rotations[4]; extern uint16_t rotations[4];
extern int parallel; // semitones extern uint16_t parallel; // semitones
extern int touch_Thr; extern int touch_Thr;

View file

@ -37,7 +37,6 @@ static byte activeSub[CursorIdx::NUM_CURSORS];
byte cursorNow; byte cursorNow;
static byte forceRedraw = 0;
static byte FPD = 0; static byte FPD = 0;
@ -216,20 +215,15 @@ static void plotSubOption(const char* label, int color) {
static bool drawSubMenu(const MenuPage &page, int color) { static bool drawSubMenu(const MenuPage &page, int color) {
int index = cursors[page.cursor]; int index = cursors[page.cursor];
// TODO: Handle MenuEntrySubRotator case
// TODO: Null check subMenuFunc // TODO: Null check subMenuFunc
const MenuEntry* subEntry = page.entries[index]; const MenuEntry* subEntry = page.entries[index];
switch(subEntry->type) { switch(subEntry->type) {
case MenuType::ESub: case MenuType::ESub:
((const MenuEntrySub*)subEntry)->subMenuFunc(color);
break;
case MenuType::ESubNew:
{ {
char buffer[12]; char buffer[12];
const char* labelPtr = nullptr; const char* labelPtr = nullptr;
const MenuEntrySubNew* sub = (const MenuEntrySubNew*)subEntry; const MenuEntrySub* sub = (const MenuEntrySub*)subEntry;
sub->getSubTextFunc(buffer, &labelPtr); sub->getSubTextFunc(*sub, buffer, &labelPtr);
// If ECustom flag is set, we assume that the getSubTextFunc // If ECustom flag is set, we assume that the getSubTextFunc
// rendered by it self. // rendered by it self.
@ -354,7 +348,6 @@ static void drawPatchView(){
} }
} }
static void drawSubBox(const char* label) static void drawSubBox(const char* label)
{ {
display.fillRect(63,11,64,52,BLACK); display.fillRect(63,11,64,52,BLACK);
@ -372,20 +365,6 @@ void drawMenuCursor(byte itemNo, byte color){
display.drawTriangle(57, ymid,61, ymid+2,61, ymid-2, color); display.drawTriangle(57, ymid,61, ymid+2,61, ymid-2, color);
} }
static void plotRotator(int color,int value){
char buff[12];
numToString(value, buff, true);
plotSubOption(buff, color);
}
static void plotPriority(int color){
if (priority){
plotSubOption("ROT", color);
} else {
plotSubOption("MEL", color);
}
}
static void plotMIDI(int color) { static void plotMIDI(int color) {
char buff[7]; char buff[7];
numToString(MIDIchannel, buff); numToString(MIDIchannel, buff);
@ -400,13 +379,6 @@ static void plotMIDI(int color) {
display.print("S"); display.print("S");
} }
static void drawSubRotator(int __unused color){
// HACKY HACK ROTATOR MENU
// drawSubBox("SEMITONES");
//plotRotator(WHITE,value);
forceRedraw = 1;
}
//*********************************************************** //***********************************************************
// TODO: Move these to a settings.cpp maybe? // TODO: Move these to a settings.cpp maybe?
@ -455,30 +427,30 @@ static void clearFPS(int trills) {
//*********************************************************** //***********************************************************
// Main menu // Main menu
const MenuEntrySubNew transposeMenu = { const MenuEntrySub transposeMenu = {
MenuType::ESubNew, "TRANSPOSE", "TRANSPOSE", &transpose, 0, 24, MenuEntryFlags::ENone, MenuType::ESub, "TRANSPOSE", "TRANSPOSE", &transpose, 0, 24, MenuEntryFlags::ENone,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
numToString(transpose - 12, out, true); numToString(transpose - 12, out, true);
}, },
[]() { writeSetting(TRANSP_ADDR,transpose); } [](const MenuEntrySub &sub) { writeSetting(TRANSP_ADDR,*sub.valuePtr); }
, nullptr , nullptr
}; };
const MenuEntrySubNew octaveMenu = { const MenuEntrySub octaveMenu = {
MenuType::ESubNew, "OCTAVE", "OCTAVE", &octave, 0, 6, MenuEntryFlags::ENone, MenuType::ESub, "OCTAVE", "OCTAVE", &octave, 0, 6, MenuEntryFlags::ENone,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
numToString(octave-3, out, true); numToString(octave-3, out, true);
}, },
[]() { writeSetting(OCTAVE_ADDR,octave); } [](SubMenuRef __unused) { writeSetting(OCTAVE_ADDR,octave); }
, nullptr , nullptr
}; };
const MenuEntrySubNew midiMenu = { const MenuEntrySub midiMenu = {
MenuType::ESubNew, "MIDI CH", "MIDI CHNL", &MIDIchannel, 1, 16, MenuEntryFlags::ECustom | MenuEntryFlags::EEnterHandler, MenuType::ESub, "MIDI CH", "MIDI CHNL", &MIDIchannel, 1, 16, MenuEntryFlags::ECustom | MenuEntryFlags::EEnterHandler,
[](char* __unused out, const char** __unused unit) { [](SubMenuRef __unused, char* __unused out, const char** __unused unit) {
plotMIDI(WHITE); plotMIDI(WHITE);
}, },
[]() { writeSetting(MIDI_ADDR, MIDIchannel); }, [](const MenuEntrySub & __unused sub) { writeSetting(MIDI_ADDR, MIDIchannel); },
[]() -> bool { // On enter handler []() -> bool { // On enter handler
readSwitches(); readSwitches();
if (pinkyKey){ if (pinkyKey){
@ -513,13 +485,80 @@ const MenuPage mainMenuPage = {
ARR_LEN(mainMenuEntries), mainMenuEntries ARR_LEN(mainMenuEntries), mainMenuEntries
}; };
//***********************************************************
// Rotator menu // Rotator menu
const MenuEntrySub rotatorParaMenu = { MenuType::ESub, "PARALLEL", "SEMITONES", &subParallel, drawSubRotator };
const MenuEntrySubRotator rotator1Menu = { MenuType::ESubRotator, "ROTATE 1", "SEMITONES", 1, &subRotator, drawSubRotator }; static void rotatorSave(const MenuEntrySub& __unused sub) {
const MenuEntrySubRotator rotator2Menu = { MenuType::ESubRotator, "ROTATE 2", "SEMITONES", 2, &subRotator, drawSubRotator }; int16_t stored;
const MenuEntrySubRotator rotator3Menu = { MenuType::ESubRotator, "ROTATE 3", "SEMITONES", 3, &subRotator, drawSubRotator }; for(int i = 0; i < 4; ++i) {
const MenuEntrySubRotator rotator4Menu = { MenuType::ESubRotator, "ROTATE 4", "SEMITONES", 4, &subRotator, drawSubRotator }; stored = readSetting(ROTN1_ADDR+2*i);
const MenuEntrySub rotatorPrioMenu = { MenuType::ESub, "PRIORITY", "MONO PRIO", &subPriority, plotPriority }; if(stored != rotations[i])
writeSetting(ROTN1_ADDR+2*i,(rotations[i]));
}
}
static void rotatorOptionGet(SubMenuRef sub, char *out, const char** __unused unit) {
numToString((*sub.valuePtr) - 24, out, true);
}
static void parallelOptionGet(SubMenuRef __unused, char *out, const char** __unused unit) {
numToString(parallel-24, out, true);
}
static void parallelSave(SubMenuRef __unused) {
writeSetting(PARAL_ADDR, parallel);
}
const MenuEntrySub rotatorParaMenu = {
MenuType::ESub, "PARALLEL", "SEMITONES", &parallel, 0, 48, MenuEntryFlags::ENone,
parallelOptionGet,
parallelSave,
nullptr
};
const MenuEntrySub rotator1Menu = {
MenuType::ESub, "ROTATE 1", "SEMITONES", &rotations[0], 0, 48, MenuEntryFlags::ENone,
rotatorOptionGet,
rotatorSave,
nullptr
};
const MenuEntrySub rotator2Menu = {
MenuType::ESub, "ROTATE 2", "SEMITONES", &rotations[1], 0, 48, MenuEntryFlags::ENone,
rotatorOptionGet,
rotatorSave,
nullptr
};
const MenuEntrySub rotator3Menu = {
MenuType::ESub, "ROTATE 3", "SEMITONES", &rotations[2], 0, 48, MenuEntryFlags::ENone,
rotatorOptionGet,
rotatorSave,
nullptr
};
const MenuEntrySub rotator4Menu = {
MenuType::ESub, "ROTATE 4", "SEMITONES", &rotations[3], 0, 48, MenuEntryFlags::ENone,
rotatorOptionGet,
rotatorSave,
nullptr
};
static void rotatorPrioOptionGet(SubMenuRef __unused, char* out, const char** __unused) {
if (priority) strncpy(out, "ROT", 4);
else strncpy(out, "MEL", 4);
}
static void rotatorPrioSave(SubMenuRef __unused) {
writeSetting(PRIO_ADDR,priority);
}
const MenuEntrySub rotatorPrioMenu = {
MenuType::ESub, "PRIORITY", "MONO PRIO", &priority, 0,1, MenuEntryFlags::EWrap,
rotatorPrioOptionGet,
rotatorPrioSave,
nullptr,
};
const MenuEntry* rotatorMenuEntries[] = { const MenuEntry* rotatorMenuEntries[] = {
(MenuEntry*)&rotatorParaMenu, (MenuEntry*)&rotatorParaMenu,
@ -539,14 +578,14 @@ const MenuPage rotatorMenuPage = {
//*********************************************************** //***********************************************************
// Breath menu // Breath menu
const MenuEntrySubNew breathCCMenu = { const MenuEntrySub breathCCMenu = {
MenuType::ESubNew, "BREATH CC", "BREATH CC", &breathCC, 0, 10, MenuEntryFlags::EWrap, MenuType::ESub, "BREATH CC", "BREATH CC", &breathCC, 0, 10, MenuEntryFlags::EWrap,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
const char* breathCCMenuLabels[] = { "OFF", "MW", "BR", "VL", "EX", "MW+", const char* breathCCMenuLabels[] = { "OFF", "MW", "BR", "VL", "EX", "MW+",
"BR+", "VL+", "EX+", "CF", "20" }; "BR+", "VL+", "EX+", "CF", "20" };
strncpy(out, breathCCMenuLabels[breathCC], 4); strncpy(out, breathCCMenuLabels[breathCC], 4);
}, },
[](){ [](const MenuEntrySub & __unused sub){
if (readSetting(BREATH_CC_ADDR) != breathCC) { if (readSetting(BREATH_CC_ADDR) != breathCC) {
writeSetting(BREATH_CC_ADDR,breathCC); writeSetting(BREATH_CC_ADDR,breathCC);
midiReset(); midiReset();
@ -555,11 +594,11 @@ const MenuEntrySubNew breathCCMenu = {
, nullptr , nullptr
}; };
const MenuEntrySubNew breathATMenu = { const MenuEntrySub breathATMenu = {
MenuType::ESubNew, "BREATH AT", "BREATH AT", &breathAT, 0, 1, MenuEntryFlags::EWrap, MenuType::ESub, "BREATH AT", "BREATH AT", &breathAT, 0, 1, MenuEntryFlags::EWrap,
[](char* out, const char ** __unused unit) { [](SubMenuRef __unused, char* out, const char ** __unused unit) {
strncpy(out, breathAT?"ON":"OFF", 4); strncpy(out, breathAT?"ON":"OFF", 4);
}, []() { }, [](const MenuEntrySub & __unused sub) {
if (readSetting(BREATH_AT_ADDR) != breathAT) { if (readSetting(BREATH_AT_ADDR) != breathAT) {
writeSetting(BREATH_AT_ADDR, breathAT); writeSetting(BREATH_AT_ADDR, breathAT);
midiReset(); midiReset();
@ -568,46 +607,46 @@ const MenuEntrySubNew breathATMenu = {
, nullptr , nullptr
}; };
const MenuEntrySubNew velocityMenu = { const MenuEntrySub velocityMenu = {
MenuType::ESubNew, "VELOCITY", "VELOCITY", &velocity, 0, 127, MenuEntryFlags::EWrap, MenuType::ESub, "VELOCITY", "VELOCITY", &velocity, 0, 127, MenuEntryFlags::EWrap,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
if(velocity) numToString(velocity, out); if(velocity) numToString(velocity, out);
else strncpy(out, "DYN", 4); else strncpy(out, "DYN", 4);
}, },
[]() { writeSetting(VELOCITY_ADDR,velocity); } [](const MenuEntrySub & __unused sub) { writeSetting(VELOCITY_ADDR,velocity); }
, nullptr , nullptr
}; };
const MenuEntrySubNew curveMenu = { const MenuEntrySub curveMenu = {
MenuType::ESubNew, "CURVE", "CURVE", &curve, 0, 12, MenuEntryFlags::EWrap, MenuType::ESub, "CURVE", "CURVE", &curve, 0, 12, MenuEntryFlags::EWrap,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
const char* curveMenuLabels[] = {"-4", "-3", "-2", "-1", "LIN", "+1", "+2", const char* curveMenuLabels[] = {"-4", "-3", "-2", "-1", "LIN", "+1", "+2",
"+3", "+4", "S1", "S2", "Z1", "Z2" }; "+3", "+4", "S1", "S2", "Z1", "Z2" };
strncpy(out, curveMenuLabels[curve], 4); strncpy(out, curveMenuLabels[curve], 4);
}, },
[](){ writeSetting(BREATHCURVE_ADDR,curve); } [](const MenuEntrySub & __unused sub){ writeSetting(BREATHCURVE_ADDR,curve); }
, nullptr , nullptr
}; };
const MenuEntrySubNew velSmpDlMenu = { const MenuEntrySub velSmpDlMenu = {
MenuType::ESubNew, "VEL DELAY", "VEL DELAY", &velSmpDl, 0, 30, MenuEntryFlags::EWrap, MenuType::ESub, "VEL DELAY", "VEL DELAY", &velSmpDl, 0, 30, MenuEntryFlags::EWrap,
[](char *out, const char** label) { [](SubMenuRef __unused, char *out, const char** label) {
if (velSmpDl) { if (velSmpDl) {
numToString(velSmpDl, out); numToString(velSmpDl, out);
*label = "ms"; *label = "ms";
} else strncpy(out, "OFF", 4); } else strncpy(out, "OFF", 4);
}, },
[]() { writeSetting(VEL_SMP_DL_ADDR,velSmpDl); } [](const MenuEntrySub & __unused sub) { writeSetting(VEL_SMP_DL_ADDR,velSmpDl); }
, nullptr , nullptr
}; };
const MenuEntrySubNew velBiasMenu = { const MenuEntrySub velBiasMenu = {
MenuType::ESubNew, "VEL BIAS", "VEL BIAS", &velBias, 0, 9, MenuEntryFlags::EWrap, MenuType::ESub, "VEL BIAS", "VEL BIAS", &velBias, 0, 9, MenuEntryFlags::EWrap,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
if (velBias) numToString(velBias, out); if (velBias) numToString(velBias, out);
else strncpy(out, "OFF", 4); else strncpy(out, "OFF", 4);
}, },
[](){ writeSetting(VEL_BIAS_ADDR,velBias); } [](SubMenuRef __unused){ writeSetting(VEL_BIAS_ADDR,velBias); }
, nullptr , nullptr
}; };
@ -629,63 +668,63 @@ const MenuPage breathMenuPage = {
//*********************************************************** //***********************************************************
// Control menu // Control menu
const MenuEntrySubNew portMenu = { const MenuEntrySub portMenu = {
MenuType::ESubNew, "PORT/GLD", "PORT/GLD", &portamento, 0, 2, MenuEntryFlags::EWrap, MenuType::ESub, "PORT/GLD", "PORT/GLD", &portamento, 0, 2, MenuEntryFlags::EWrap,
[](char* out, const char ** __unused unit) { [](SubMenuRef __unused,char* out, const char ** __unused unit) {
const char* labs[] = { "OFF", "ON", "SW" }; const char* labs[] = { "OFF", "ON", "SW" };
strncpy(out, labs[portamento], 4); strncpy(out, labs[portamento], 4);
}, },
[]() { writeSetting(PORTAM_ADDR,portamento); } [](SubMenuRef __unused sub) { writeSetting(PORTAM_ADDR,portamento); }
, nullptr , nullptr
}; };
const MenuEntrySubNew pitchBendMenu = { const MenuEntrySub pitchBendMenu = {
MenuType::ESubNew, "PITCHBEND", "PITCHBEND", &PBdepth, 0, 12, MenuEntryFlags::ENone, MenuType::ESub, "PITCHBEND", "PITCHBEND", &PBdepth, 0, 12, MenuEntryFlags::ENone,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
if(PBdepth) { if(PBdepth) {
memcpy(out, "1/", 2); memcpy(out, "1/", 2);
numToString(PBdepth, &out[2]); numToString(PBdepth, &out[2]);
} }
else strncpy(out, "OFF", 4); else strncpy(out, "OFF", 4);
}, },
[](){ writeSetting(PB_ADDR,PBdepth); } [](SubMenuRef __unused){ writeSetting(PB_ADDR,PBdepth); }
, nullptr , nullptr
}; };
const MenuEntrySubNew extraMenu = { const MenuEntrySub extraMenu = {
MenuType::ESubNew, "EXTRA CTR", "EXTRA CTR", &extraCT, 0,4, MenuEntryFlags::EWrap, MenuType::ESub, "EXTRA CTR", "EXTRA CTR", &extraCT, 0,4, MenuEntryFlags::EWrap,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused,char* out, const char** __unused unit) {
const char* extraMenuLabels[] = { "OFF", "MW", "FP", "CF", "SP" }; const char* extraMenuLabels[] = { "OFF", "MW", "FP", "CF", "SP" };
strncpy(out, extraMenuLabels[extraCT], 12); strncpy(out, extraMenuLabels[extraCT], 12);
}, },
[]() { writeSetting(EXTRA_ADDR,extraCT); } [](const MenuEntrySub & __unused sub) { writeSetting(EXTRA_ADDR,extraCT); }
, nullptr , nullptr
}; };
const MenuEntryStateCh vibratoSubMenu = { MenuType::EStateChange, "VIBRATO", VIBRATO_MENU }; const MenuEntryStateCh vibratoSubMenu = { MenuType::EStateChange, "VIBRATO", VIBRATO_MENU };
const MenuEntrySubNew deglitchMenu = { const MenuEntrySub deglitchMenu = {
MenuType::ESubNew, "DEGLITCH", "DEGLITCH", &deglitch, 0, 70, MenuEntryFlags::ENone, MenuType::ESub, "DEGLITCH", "DEGLITCH", &deglitch, 0, 70, MenuEntryFlags::ENone,
[](char* textBuffer, const char** label) { [](SubMenuRef __unused,char* textBuffer, const char** label) {
if(deglitch) { if(deglitch) {
numToString(deglitch, textBuffer); numToString(deglitch, textBuffer);
*label = "ms"; *label = "ms";
} else } else
strncpy(textBuffer, "OFF", 4); strncpy(textBuffer, "OFF", 4);
}, },
[]() { writeSetting(DEGLITCH_ADDR,deglitch); } [](const MenuEntrySub & __unused sub) { writeSetting(DEGLITCH_ADDR,deglitch); }
, nullptr , nullptr
}; };
const MenuEntrySubNew pinkyMenu = { const MenuEntrySub pinkyMenu = {
MenuType::ESubNew, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 24, MenuEntryFlags::ENone, MenuType::ESub, "PINKY KEY", "PINKY KEY", &pinkySetting, 0, 24, MenuEntryFlags::ENone,
[](char* textBuffer, const char** __unused unit) { [](SubMenuRef __unused,char* textBuffer, const char** __unused unit) {
if (pinkySetting == PBD) if (pinkySetting == PBD)
strncpy(textBuffer, "PBD", 4); strncpy(textBuffer, "PBD", 4);
else else
numToString(pinkySetting-12, textBuffer, true); numToString(pinkySetting-12, textBuffer, true);
}, },
[]() { writeSetting(PINKY_KEY_ADDR,pinkySetting); } [](const MenuEntrySub & __unused sub) { writeSetting(PINKY_KEY_ADDR,pinkySetting); }
, nullptr , nullptr
}; };
@ -709,60 +748,60 @@ const MenuPage controlMenuPage = {
//*********************************************************** //***********************************************************
// Vibrato menu // Vibrato menu
static void vibGetStr(char* textBuffer, const char** __unused unit) { static void vibGetStr(SubMenuRef __unused, char* textBuffer, const char** __unused unit) {
if(vibrato) if(vibrato)
numToString(vibrato, textBuffer); numToString(vibrato, textBuffer);
else else
strncpy(textBuffer, "OFF", 4); strncpy(textBuffer, "OFF", 4);
} }
static void vibStore() { static void vibStore(const MenuEntrySub & __unused sub) {
writeSetting(VIBRATO_ADDR,vibrato); writeSetting(VIBRATO_ADDR,vibrato);
} }
const MenuEntrySubNew vibDepthMenu = { const MenuEntrySub vibDepthMenu = {
MenuType::ESubNew, "DEPTH", "LEVEL", &vibrato, 0, 9, MenuEntryFlags::ENone, MenuType::ESub, "DEPTH", "LEVEL", &vibrato, 0, 9, MenuEntryFlags::ENone,
vibGetStr, vibGetStr,
vibStore, vibStore,
nullptr nullptr
}; };
const MenuEntrySubNew vibSenseMenu = { const MenuEntrySub vibSenseMenu = {
MenuType::ESubNew, "SENSE", "LEVEL", &vibSens, 1, 12, MenuEntryFlags::ENone, MenuType::ESub, "SENSE", "LEVEL", &vibSens, 1, 12, MenuEntryFlags::ENone,
[](char* textBuffer, const char** __unused unit) { [](SubMenuRef __unused,char* textBuffer, const char** __unused unit) {
numToString(vibSens, textBuffer); numToString(vibSens, textBuffer);
}, },
[]() { writeSetting(VIB_SENS_ADDR,vibSens); } [](const MenuEntrySub & __unused sub) { writeSetting(VIB_SENS_ADDR,vibSens); }
, nullptr , nullptr
}; };
const MenuEntrySubNew vibRetnMenu = { const MenuEntrySub vibRetnMenu = {
MenuType::ESubNew, "RETURN", "LEVEL", &vibRetn, 0, 4, MenuEntryFlags::ENone, MenuType::ESub, "RETURN", "LEVEL", &vibRetn, 0, 4, MenuEntryFlags::ENone,
[](char* textBuffer, const char** __unused unit) { [](SubMenuRef __unused, char* textBuffer, const char** __unused unit) {
numToString(vibRetn, textBuffer); numToString(vibRetn, textBuffer);
}, },
[]() { writeSetting(VIB_RETN_ADDR,vibRetn); } [](const MenuEntrySub & __unused sub) { writeSetting(VIB_RETN_ADDR,vibRetn); }
, nullptr , nullptr
}; };
const MenuEntrySubNew vibSquelchMenu = { const MenuEntrySub vibSquelchMenu = {
MenuType::ESubNew, "SQUELCH", "LEVEL", &vibSquelch, 1, 30, MenuEntryFlags::ENone, MenuType::ESub, "SQUELCH", "LEVEL", &vibSquelch, 1, 30, MenuEntryFlags::ENone,
[](char* textBuffer, const char** __unused unit) { [](SubMenuRef __unused, char* textBuffer, const char** __unused unit) {
numToString(vibSquelch, textBuffer); numToString(vibSquelch, textBuffer);
}, },
[]() { writeSetting(VIB_SQUELCH_ADDR,vibSquelch); } [](const MenuEntrySub & __unused sub) { writeSetting(VIB_SQUELCH_ADDR,vibSquelch); }
, nullptr , nullptr
}; };
const MenuEntrySubNew vibDirMenu = { const MenuEntrySub vibDirMenu = {
MenuType::ESubNew, "DIRECTION", "DIRECTION", &vibDirection , 0, 1, MenuEntryFlags::EWrap, MenuType::ESub, "DIRECTION", "DIRECTION", &vibDirection , 0, 1, MenuEntryFlags::EWrap,
[](char* out, const char** __unused unit) { [](SubMenuRef __unused, char* out, const char** __unused unit) {
if (DNWD == vibDirection) if (DNWD == vibDirection)
strncpy(out, "NRM", 4); strncpy(out, "NRM", 4);
else else
strncpy(out, "REV", 4); strncpy(out, "REV", 4);
}, },
[]() { writeSetting(VIB_DIRECTION_ADDR,vibDirection); } [](const MenuEntrySub & __unused sub) { writeSetting(VIB_DIRECTION_ADDR,vibDirection); }
, nullptr , nullptr
}; };
@ -784,25 +823,16 @@ const MenuPage vibratoMenuPage = {
//*********************************************************** //***********************************************************
static bool ExecuteMenuSelection(const MenuPage &page) //int cursorPosition, const struct MenuEntry *menuEntry) static bool selectMenuOption(const MenuPage &page) {
{
int cursorPosition = cursors[page.cursor]; int cursorPosition = cursors[page.cursor];
const MenuEntry* menuEntry = page.entries[cursorPosition]; const MenuEntry* menuEntry = page.entries[cursorPosition];
cursorBlinkTime = millis(); cursorBlinkTime = millis();
switch(menuEntry->type) { switch(menuEntry->type) {
case MenuType::ESub: case MenuType::ESub:
*((const MenuEntrySub*)menuEntry)->flag = 1;
activeSub[page.cursor] = cursorPosition+1; activeSub[page.cursor] = cursorPosition+1;
drawMenuCursor(cursorPosition, WHITE); drawMenuCursor(cursorPosition, WHITE);
drawSubBox( ((const MenuEntrySub*)menuEntry)->subTitle); drawSubBox( ((const MenuEntrySub*)menuEntry)->subTitle);
((const MenuEntrySub*)menuEntry)->subMenuFunc(WHITE);
return true;
case MenuType::ESubNew:
activeSub[page.cursor] = cursorPosition+1;
drawMenuCursor(cursorPosition, WHITE);
drawSubBox( ((const MenuEntrySubNew*)menuEntry)->subTitle);
drawSubMenu(page, WHITE); drawSubMenu(page, WHITE);
return true; return true;
@ -810,24 +840,11 @@ static bool ExecuteMenuSelection(const MenuPage &page) //int cursorPosition, con
state = ((const MenuEntryStateCh*)menuEntry)->state; state = ((const MenuEntryStateCh*)menuEntry)->state;
stateFirstRun = 1; stateFirstRun = 1;
break; break;
case MenuType::ESubRotator:
activeSub[page.cursor] = cursorPosition+1;
*((const MenuEntrySubRotator*)menuEntry)->flag = ((const MenuEntrySubRotator*)menuEntry)->flagValue;
drawMenuCursor(cursorPosition, WHITE);
((const MenuEntrySubRotator*)menuEntry)->subMenuFunc(WHITE);
break;
} }
return false; return false;
} }
//***********************************************************
static bool selectMenuOption(const MenuPage &page){
// const MenuEntry* entry = menuEntries[cursorPosition];
return ExecuteMenuSelection( page );
}
//*********************************************************** //***********************************************************
@ -843,7 +860,7 @@ static bool updateSubMenu(const MenuPage &page, uint32_t timeNow) {
if( current_sub < 0) if( current_sub < 0)
return false; return false;
auto sub = (const MenuEntrySubNew*)page.entries[current_sub]; auto sub = (const MenuEntrySub*)page.entries[current_sub];
uint16_t currentVal = *sub->valuePtr; uint16_t currentVal = *sub->valuePtr;
switch (deumButtonState){ switch (deumButtonState){
@ -871,13 +888,13 @@ static bool updateSubMenu(const MenuPage &page, uint32_t timeNow) {
} }
} else { } else {
activeSub[page.cursor] = 0; activeSub[page.cursor] = 0;
sub->applyFunc(); sub->applyFunc(*sub);
} }
break; break;
case BTN_MENU: case BTN_MENU:
activeSub[page.cursor] = 0; activeSub[page.cursor] = 0;
sub->applyFunc(); sub->applyFunc(*sub);
break; break;
} }
*sub->valuePtr = currentVal; *sub->valuePtr = currentVal;
@ -1009,7 +1026,6 @@ void menu() {
unsigned long timeNow = millis(); unsigned long timeNow = millis();
const MenuPage *currentPage = nullptr; const MenuPage *currentPage = nullptr;
bool redrawSubValue = false;
bool redraw = stateFirstRun; bool redraw = stateFirstRun;
// read the state of the switches // read the state of the switches
uint8_t deumButtons = 0x0f ^(digitalRead(dPin) | (digitalRead(ePin) << 1) | (digitalRead(uPin) << 2) | (digitalRead(mPin)<<3)); uint8_t deumButtons = 0x0f ^(digitalRead(dPin) | (digitalRead(ePin) << 1) | (digitalRead(uPin) << 2) | (digitalRead(mPin)<<3));
@ -1225,109 +1241,21 @@ void menu() {
redraw |= updateSubMenu(*currentPage, timeNow); redraw |= updateSubMenu(*currentPage, timeNow);
} else { } else {
bool hadButtons = buttonPressedAndNotUsed; bool hadButtons = buttonPressedAndNotUsed;
redraw |= updateMenuPage( *currentPage, timeNow ); redraw |= updateMenuPage(*currentPage, timeNow);
if (hadButtons) if (hadButtons)
checkForPatchView(deumButtonState); checkForPatchView(deumButtonState);
} }
} else if (state == ROTATOR_MENU) { // ROTATOR MENU HERE <<<<<<<<<<<<<<< } else if (state == ROTATOR_MENU) { // ROTATOR MENU HERE <<<<<<<<<<<<<<<
currentPage = &rotatorMenuPage;
if (stateFirstRun) { if (stateFirstRun) {
drawMenu(rotatorMenuPage); drawMenu(*currentPage);
stateFirstRun = 0; stateFirstRun = 0;
} }
currentPage = &rotatorMenuPage; if(activeSub[currentPage->cursor]) {
if (subParallel){ redraw |= updateSubMenu(*currentPage, timeNow);
if (((timeNow - cursorBlinkTime) > cursorBlinkInterval) || forceRedraw) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
if (forceRedraw){
forceRedraw = 0;
cursorNow = WHITE;
}
plotRotator(cursorNow,parallel);
redraw = true;
cursorBlinkTime = timeNow;
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case BTN_DOWN:
if (parallel > -24)
parallel--;
break;
case BTN_UP:
if (parallel < 24)
parallel++;
break;
case BTN_ENTER: // fallthrough
case BTN_MENU:
subParallel = 0;
writeSetting(PARAL_ADDR,(parallel + 24));
break;
}
clearSubValue();
plotRotator(WHITE,parallel);
cursorNow = BLACK;
redraw = true;
cursorBlinkTime = timeNow;
}
} else if (subRotator){
if (((timeNow - cursorBlinkTime) > cursorBlinkInterval) || forceRedraw) {
if (cursorNow == WHITE) cursorNow = BLACK; else cursorNow = WHITE;
if (forceRedraw){
forceRedraw = 0;
cursorNow = WHITE;
}
plotRotator(cursorNow,rotations[subRotator-1]);
redraw = true;
cursorBlinkTime = timeNow;
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case BTN_DOWN:
if (rotations[subRotator-1] > -24)
rotations[subRotator-1]--;
break;
case BTN_UP:
if (rotations[subRotator-1] < 24)
rotations[subRotator-1]++;
break;
case BTN_ENTER: // fallthrough
case BTN_MENU:
writeSetting(ROTN1_ADDR+2*(subRotator-1),(rotations[subRotator-1]+24));
subRotator = 0;
break;
}
clearSubValue();
plotRotator(WHITE,rotations[subRotator-1]);
cursorNow = BLACK;
redraw = true;
cursorBlinkTime = timeNow;
}
} else if (subPriority){
updateSubMenuCursor( *currentPage, timeNow );
if (buttonPressedAndNotUsed) {
buttonPressedAndNotUsed = 0;
switch (deumButtonState){
case BTN_DOWN: // fallthrough
case BTN_UP:
priority = !priority;
break;
case BTN_ENTER: // fallthrough
case BTN_MENU:
subPriority = 0;
writeSetting(PRIO_ADDR,priority);
break;
}
redrawSubValue = true;
}
} else { } else {
bool hadButtons = buttonPressedAndNotUsed; bool hadButtons = buttonPressedAndNotUsed;
redraw |= updateMenuPage(*currentPage, timeNow ); redraw |= updateMenuPage(*currentPage, timeNow);
if (hadButtons) if (hadButtons)
checkForPatchView(deumButtonState); checkForPatchView(deumButtonState);
} }
@ -1359,13 +1287,6 @@ void menu() {
redraw |= updatePage(vibratoMenuPage, timeNow); redraw |= updatePage(vibratoMenuPage, timeNow);
} }
if(redrawSubValue && currentPage) {
clearSubValue();
redraw |= drawSubMenu(*currentPage, WHITE);
cursorNow = BLACK;
cursorBlinkTime = timeNow;
}
if(redraw) { if(redraw) {
display.display(); display.display();
} }

View file

@ -5,24 +5,9 @@
enum MenuType { enum MenuType {
ESub, ESub,
ESubNew,
ESubRotator,
EStateChange, EStateChange,
}; };
struct MenuEntry {
enum MenuType type;
const char* title;
};
struct MenuEntrySub {
enum MenuType type;
const char* title;
const char* subTitle;
byte* flag;
void (*subMenuFunc)(int color);
};
enum MenuEntryFlags { enum MenuEntryFlags {
ENone = 0, ENone = 0,
EWrap = (1<<0), EWrap = (1<<0),
@ -30,7 +15,15 @@ enum MenuEntryFlags {
EEnterHandler = (1<<2), EEnterHandler = (1<<2),
}; };
struct MenuEntrySubNew { struct MenuEntry {
enum MenuType type;
const char* title;
};
struct MenuEntrySub;
typedef const MenuEntrySub& SubMenuRef;
struct MenuEntrySub {
enum MenuType type; enum MenuType type;
const char* title; const char* title;
const char* subTitle; const char* subTitle;
@ -38,21 +31,11 @@ struct MenuEntrySubNew {
uint16_t min; uint16_t min;
uint16_t max; uint16_t max;
uint16_t flags; uint16_t flags;
void (*getSubTextFunc)(char*textBuffer, const char**label); void (*getSubTextFunc)(SubMenuRef, char*textBuffer, const char**label);
void (*applyFunc)(void); void (*applyFunc)(SubMenuRef);
bool (*onEnterFunc)(void); bool (*onEnterFunc)(void);
}; };
struct MenuEntrySubRotator {
enum MenuType type;
const char* title;
const char* subTitle;
byte flagValue;
byte* flag;
void (*subMenuFunc)(int color);
};
struct MenuEntryStateCh { struct MenuEntryStateCh {
enum MenuType type; enum MenuType type;
const char* title; const char* title;
@ -70,8 +53,6 @@ struct MenuPage {
//*********************************************************** //***********************************************************
struct AdjustValue { struct AdjustValue {
uint16_t *value; uint16_t *value;
uint16_t limitLow; uint16_t limitLow;