#include #include "TimedPin.h" #include "ui.h" /***************************************************************************//** * @brief Timer class for generate cyclic signals *******************************************************************************/ struct Tmr { int32_t Period; // cycle length (it must be initialized!) uint32_t TrefMillis; //--------------------------------------------------------------------------- bool Check(uint32_t t) { // check with external timebase int32_t tdif = t - TrefMillis; if (tdif >= Period) { // period expired TrefMillis += Period; return true; } return false; }; bool Check() { // check with millisec timebase uint32_t t = millis(); int32_t tdif = t - TrefMillis; if (tdif >= Period) { // period expired TrefMillis += Period; return true; } return false; }; }; Tmr Tmr10ms = { .Period = 10 }; Tmr Tmr100ms = { .Period = 100 }; Tmr Tmr1s = { .Period = 1000 }; /***************************************************************************//** * @brief Button - port assignment *******************************************************************************/ const uint8_t pinBtnInc1 = 8; const uint8_t pinBtnDec1 = 9; const uint8_t pinBtnInc2 = 10; const uint8_t pinBtnDec2 = 11; const uint8_t pinBtnChOn1 = 12; const uint8_t pinBtnChOn2 = 13; /***************************************************************************//** * @brief Button codes *******************************************************************************/ enum _BTN_CODES { BTN_INC1 = 0, BTN_DEC1, BTN_INC2, BTN_DEC2, BTN_CH_ON1, BTN_CH_ON2, BTN_MAX }; /***************************************************************************//** * @brief LED *******************************************************************************/ TimedPin LedBoard(LED_BUILTIN); TimedPin LedChOn1(2); TimedPin LedChOn2(3); /***************************************************************************//** * @brief MIDI instance (serial port) *******************************************************************************/ MIDI_CREATE_DEFAULT_INSTANCE(); // ----------------------------------------------------------------------------- // This function will be automatically called when a NoteOn is received. // It must be a void-returning function with the correct parameters, see documentation here: // https://github.com/FortySevenEffects/arduino_midi_library/wiki/Using-Callbacks void handleNoteOn(byte channel, byte pitch, byte velocity) { // Do whatever you want when a note is pressed. // Try to keep your callbacks short (no delays ect) otherwise it would slow down the loop() and have a bad impact on real-time performance. } void handleNoteOff(byte channel, byte pitch, byte velocity) { // Do something when the note is released. Note that NoteOn messages with 0 velocity are interpreted as NoteOffs. } // ----------------------------------------------------------------------------- void setup() { pinMode(pinBtnInc1, INPUT_PULLUP); pinMode(pinBtnDec1, INPUT_PULLUP); pinMode(pinBtnInc2, INPUT_PULLUP); pinMode(pinBtnDec2, INPUT_PULLUP); pinMode(pinBtnChOn1, INPUT_PULLUP); pinMode(pinBtnChOn2, INPUT_PULLUP); LedBoard.begin(); LedChOn1.begin(); LedChOn2.begin(); // Connect the handleNoteOn function to the library, so it is called upon reception of a NoteOn. MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function MIDI.setHandleNoteOff(handleNoteOff); // Do the same for NoteOffs MIDI.begin(MIDI_CHANNEL_OMNI); // Initiate MIDI communications, listen to all channels UI_Init(); // Start user interface (main state machine) } /***************************************************************************//** * @brief Main loop *******************************************************************************/ void loop() { MIDI.read(); // Call MIDI.read the fastest you can for real-time performance. uint32_t t = millis(); // execute every 10ms ******************************************************* if (Tmr10ms.Check(t)) { static uint8_t BtnPrev = 0xFF; static uint8_t BtnNew = 0; static uint8_t BtnRel = 0; uint8_t btn = (digitalRead(pinBtnInc1) ? (1 << BTN_INC1 ) : 0) | (digitalRead(pinBtnDec1) ? (1 << BTN_DEC1 ) : 0) | (digitalRead(pinBtnInc2) ? (1 << BTN_INC2 ) : 0) | (digitalRead(pinBtnInc2) ? (1 << BTN_DEC2 ) : 0) | (digitalRead(pinBtnChOn1) ? (1 << BTN_CH_ON1) : 0) | (digitalRead(pinBtnChOn1) ? (1 << BTN_CH_ON2) : 0); BtnNew |= (~btn) & BtnPrev; BtnRel |= btn & (~BtnPrev); uint8_t mask = 1; if (BtnNew) { for (uint_fast8_t i = 0; i < BTN_MAX; i++) { if (BtnNew & mask) { BtnNew &= ~mask; // Bit clr UI_EventProc(EV_UI_KEY_PRESS + i); break; } mask <<= 1; } }else if (BtnRel) { // released button for (uint_fast8_t i = 0; i < BTN_MAX; i++) { if (BtnRel & mask) { BtnRel &= ~mask; // Bit clr UI_EventProc(EV_UI_KEY_REL + i); break; } mask <<= 1; } } UI_EventProc(EV_TIMER_TICK); UI_EventProc(EV_UI_TICK_10MS); UI_CheckEvent(); LedBoard.loop(); LedChOn1.loop(); LedChOn2.loop(); } // execute every 100ms ****************************************************** if (Tmr100ms.Check(t)) { UI_EventProc(EV_UI_TICK_100MS); } // execute every 1s ********************************************************* if (Tmr1s.Check(t)) { UI_EventProc(EV_UI_TICK_1S); } }