/* Macro Board Made by Bozarre */ /* * saving presets in eeprom */ #include struct MemSlot { String displayName; int address; byte value; }; MemSlot memory[] = //128 bytes for the Teensy LC { {"prst", 1, 0}, {"p2_1", 2, 63}, {"p2_2", 3, 63}, }; /* * Menu */ bool isInMenu = false; struct MenuItem { String path; bool isValue; String displayName; }; MenuItem menuEntries[] = { {"", true, "prst"}, {"", false, "edit"}, {"/edit", false, "p2"}, {"/edit/p2", true, "p2_1"}, {"/edit/p2", true, "p2_2"}, }; String menuCurrentPath = ""; unsigned int menuSelectionIndex = 0; unsigned int menuCurrentPathItems = 0; MenuItem menuCurrentItem; bool menuIsSettingValue = false; /* * 7 Segment 4 digits display */ #include "SevSeg.h" SevSeg sevseg; /* * key button matrix */ //#include #include const byte rows = 4; //four rows const byte cols = 3; //three columns char keys[rows][cols] = { // assiging arbitraty uid to each button {9,5,1}, {10,6,2}, {11,7,3}, {12,8,4} }; byte rowPins[rows] = {1, 2, 3, 0}; //connect to the row pinouts of the keypad byte colPins[cols] = {21, 22, 23}; //connect to the column pinouts of the keypad Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols ); /* * Rotary Encoder */ #include SimpleRotary rotaryEncoder(19, 20, 4); byte rotaryEncoderState = 0; // Rotary push button const int BUTTON_Rotary = 4; /* * mode presets and action */ #include "modeAction.h" /* * custom display animations */ //#include "animations.h" //int animationFrame = 0; //bool animationLooping = true; /* * time cooldown managment */ unsigned int lastInputMillis = 0; unsigned int inputCoolDown = 10; unsigned int sevSegCoolDown = 5000; /* * INIT */ void setup() { //debug Serial.begin(9600); Serial.println("setup start"); //write eeprom first init byte memValue = EEPROM.read(0); if (memValue == 255) // cannot find settings, writes defualt ones { for (byte i = 0; i < (sizeof(memory)/sizeof(MemSlot)); i++) { EEPROM.write(memory[i].address, memory[i].value); } EEPROM.write(0,1); } //read eeprom for (byte i = 0; i < (sizeof(memory)/sizeof(MemSlot)); i++) { memory[i].value = EEPROM.read(memory[i].address); } //Init display byte numDigits = 4; byte digitPins[] = {7, 8, 9, 6}; byte segmentPins[] = {10, 12, 14, 16, 17, 11, 13, 15}; bool resistorsOnSegments = true; //bool updateWithDelaysIn = true; byte hardwareConfig = COMMON_CATHODE; sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); sevseg.setBrightness(90); //Init rotary encoders rotaryEncoder.setDebounceDelay(2); rotaryEncoder.setErrorDelay(100); pinMode(BUTTON_Rotary, INPUT_PULLUP); // Init keyboard output Keyboard.begin(); //init cooldowns lastInputMillis = millis(); Serial.println("setup complete"); } /* * Tick Loop */ void loop() { //INPUTS if (millis() > lastInputMillis + inputCoolDown) { char customKey = keypad.getKey(); if (customKey) { sendInputOuput(customKey); } if (rotaryEncoder.push() == 1) // = pressed { sendInputOuput(15); } rotaryEncoderState = rotaryEncoder.rotate(); if (rotaryEncoderState == 1 || rotaryEncoderState == 2) { if ( rotaryEncoderState == 1 ) //Turned Clockwise { sendInputOuput(14); } if ( rotaryEncoderState == 2 ) //Turned Counter-Clockwise { sendInputOuput(13); } } } //clear screen after no input delay if (millis() > lastInputMillis + sevSegCoolDown) { sevseg.blank(); } sevseg.refreshDisplay(); } void printMenu() { Serial.println("printMenu"); Serial.print(menuCurrentPath + "/ "); if (isInMenu) { if(menuIsSettingValue) { sevseg.setNumber(menuGetValue(menuCurrentItem.displayName)); Serial.println(menuGetValue(menuCurrentItem.displayName)); } else { updateMenu(); sevseg.setChars(menuCurrentItem.displayName.c_str()); Serial.println(menuCurrentItem.displayName); } } } void updateMenu() { unsigned int correspondingPathItemIndex = 0; for (unsigned int i = 0; i < (sizeof(menuEntries)/sizeof(MenuItem)); i++) { if (menuEntries[i].path == menuCurrentPath) { if(correspondingPathItemIndex == menuSelectionIndex) { menuCurrentItem = menuEntries[i]; } correspondingPathItemIndex++; } } menuCurrentPathItems = correspondingPathItemIndex; //Serial.println(menuCurrentPathItems); } void menuBack() { if (isInMenu) { if (menuCurrentPath == "/" || menuCurrentPath == "" ) { Serial.println("menuExit"); isInMenu = false; menuSelectionIndex = 0; menuCurrentPath = ""; sevseg.blank(); } else { Serial.println("menuBack"); menuSelectionIndex = menuGetSelectionIndexFromPath(menuCurrentPath); menuCurrentPath = menuCurrentPath.substring(0,menuCurrentPath.lastIndexOf('/')); menuIsSettingValue = false; printMenu(); } } } void menuEnter() { Serial.println("menuEnter"); if (isInMenu) { menuCurrentPath = menuCurrentItem.path + '/'; menuCurrentPath+= menuCurrentItem.displayName; menuSelectionIndex = 0; if (menuCurrentItem.isValue) { if (menuIsSettingValue) { for (unsigned int i = 0; i < (sizeof(memory)/sizeof(MemSlot)); i++) { if (memory[i].displayName == menuCurrentItem.displayName) { EEPROM.write(memory[i].address, memory[i].value); Serial.println("value saved in eeprom"); menuBack(); return; } } } else { menuIsSettingValue = true; Serial.println("menuIsSettingValue"); } } printMenu(); } } void menuPrev() { if (isInMenu) { if (menuIsSettingValue) { menuSetValue(menuCurrentItem.displayName, menuGetValue(menuCurrentItem.displayName) - 1); } else if (menuSelectionIndex > 0) { menuSelectionIndex = menuSelectionIndex - 1; } printMenu(); } } void menuNext() { if (isInMenu) { if (menuIsSettingValue) { menuSetValue(menuCurrentItem.displayName, menuGetValue(menuCurrentItem.displayName) + 1); } else if (menuSelectionIndex < menuCurrentPathItems-1) { menuSelectionIndex = menuSelectionIndex + 1; } printMenu(); } } byte menuGetValue(String variableName) { MemSlot* memorySlot = getMemorySlot(variableName); if (memorySlot != NULL) { return memorySlot->value; } return 0; } bool menuSetValue(String variableName, byte newValue) { MemSlot* memorySlot = getMemorySlot(variableName); if (memorySlot != NULL) { memorySlot->value = newValue; return true; } return false; } int menuGetSelectionIndexFromPath(String path) { int correspondingPathItemIndex = 0; String makePath = ""; String parentPath = path.substring(0,path.lastIndexOf('/')); for (unsigned int i = 0; i < (sizeof(menuEntries)/sizeof(MenuItem)); i++) { if (menuEntries[i].path == parentPath) { makePath = menuEntries[i].path + '/'; makePath += menuEntries[i].displayName; if(makePath == path) { return correspondingPathItemIndex; } correspondingPathItemIndex++; } } return 0; } MemSlot* getMemorySlot(String memSlotName) { for (unsigned int i = 0; i < (sizeof(memory)/sizeof(MemSlot)); i++) { if (memory[i].displayName == memSlotName) { return &memory[i]; } } return NULL; } void sendInputOuput(int input) { lastInputMillis = millis(); sevseg.setNumber(input, -1); int mode = (getMemorySlot("prst")->value) % (sizeof(modes)/(sizeof(Action)*15)); Action actionToRun = modes[mode][input-1]; if (actionToRun.keyID == -1) //menu { if (isInMenu) { menuBack(); } else { isInMenu = true; sevseg.blank(); printMenu(); } } else if (isInMenu && input == 13) //menu prev { menuPrev(); } else if (isInMenu && input == 14) //menu next { menuNext(); } else if (isInMenu && input == 15) //menu enter { menuEnter(); } else { clickKey(actionToRun.keyID, actionToRun.keyModifierID); } } void clickKey(int key, int modifier) { if (modifier != -1) Keyboard.set_modifier(modifier); Keyboard.press(key); Keyboard.release(key); Keyboard.set_modifier(0); Keyboard.send_now(); }