Line data Source code
1 : #include "Control_Surface_Class.hpp" 2 : #include <AH/Debug/Debug.hpp> 3 : #include <AH/Hardware/ExtendedInputOutput/ExtendedIOElement.hpp> 4 : #include <AH/Hardware/FilteredAnalog.hpp> 5 : #include <MIDI_Constants/Control_Change.hpp> 6 : #include <MIDI_Inputs/MIDIInputElementCC.hpp> 7 : #include <MIDI_Inputs/MIDIInputElementChannelPressure.hpp> 8 : #include <MIDI_Inputs/MIDIInputElementNote.hpp> 9 : #include <MIDI_Inputs/MIDIInputElementPC.hpp> 10 : #include <MIDI_Inputs/MIDIInputElementSysEx.hpp> 11 : #include <MIDI_Outputs/Abstract/MIDIOutputElement.hpp> 12 : #include <Selectors/Selector.hpp> 13 : 14 : #include <AH/Arduino-Wrapper.h> 15 : 16 : BEGIN_CS_NAMESPACE 17 : 18 : using AH::ExtendedIOElement; 19 : 20 1 : Control_Surface_ &Control_Surface_::getInstance() { 21 1 : static Control_Surface_ instance; 22 1 : return instance; 23 0 : } 24 : 25 0 : void Control_Surface_::begin() { 26 : #if defined(ARDUINO) && defined(DEBUG_OUT) 27 : DEBUG_OUT.begin(AH::defaultBaudRate); 28 : delay(250); 29 : #endif 30 : 31 0 : connectDefaultMIDI_Interface(); 32 : 33 0 : FilteredAnalog<>::setupADC(); 34 0 : ExtendedIOElement::beginAll(); 35 0 : Updatable<MIDI_Interface>::beginAll(); 36 0 : DisplayInterface::beginAll(); // initialize all displays 37 0 : MIDIInputElementCC::beginAll(); 38 0 : MIDIInputElementPC::beginAll(); 39 0 : MIDIInputElementChannelPressure::beginAll(); 40 0 : MIDIInputElementNote::beginAll(); 41 0 : MIDIInputElementSysEx::beginAll(); 42 0 : Updatable<>::beginAll(); 43 0 : Updatable<Potentiometer>::beginAll(); 44 0 : Updatable<MotorFader>::beginAll(); 45 0 : Updatable<Display>::beginAll(); 46 0 : potentiometerTimer.begin(); 47 0 : displayTimer.begin(); 48 0 : } 49 : 50 35 : bool Control_Surface_::connectDefaultMIDI_Interface() { 51 35 : if (hasSinkPipe() || hasSourcePipe()) 52 0 : return false; 53 35 : auto def = MIDI_Interface::getDefault(); 54 35 : if (def == nullptr) { 55 0 : FATAL_ERROR(F("No default MIDI Interface"), 0xF123); 56 0 : return false; 57 : } 58 35 : *this << inpipe << *def; 59 35 : *this >> outpipe >> *def; 60 35 : return true; 61 35 : } 62 : 63 0 : void Control_Surface_::disconnectMIDI_Interfaces() { 64 0 : disconnectSinkPipes(); 65 0 : disconnectSourcePipes(); 66 0 : } 67 : 68 0 : void Control_Surface_::loop() { 69 0 : ExtendedIOElement::updateAllBufferedInputs(); 70 0 : Updatable<>::updateAll(); 71 0 : if (potentiometerTimer) 72 0 : Updatable<Potentiometer>::updateAll(); 73 0 : updateMidiInput(); 74 0 : updateInputs(); 75 0 : if (displayTimer) 76 0 : updateDisplays(); 77 0 : ExtendedIOElement::updateAllBufferedOutputs(); 78 0 : } 79 : 80 0 : void Control_Surface_::updateMidiInput() { 81 0 : Updatable<MIDI_Interface>::updateAll(); 82 0 : } 83 : 84 103 : void Control_Surface_::sendImpl(uint8_t header, uint8_t d1, uint8_t d2, 85 : uint8_t cn) { 86 103 : this->sourceMIDItoPipe(ChannelMessage{header, d1, d2, cn}); 87 103 : } 88 0 : void Control_Surface_::sendImpl(uint8_t header, uint8_t d1, uint8_t cn) { 89 0 : this->sourceMIDItoPipe(ChannelMessage{header, d1, 0x00, cn}); 90 0 : } 91 0 : void Control_Surface_::sendImpl(const uint8_t *data, size_t length, 92 : uint8_t cn) { 93 0 : this->sourceMIDItoPipe(SysExMessage{data, length, cn}); 94 0 : } 95 0 : void Control_Surface_::sendImpl(uint8_t rt, uint8_t cn) { 96 0 : this->sourceMIDItoPipe(RealTimeMessage{rt, cn}); 97 0 : } 98 : 99 0 : void Control_Surface_::sinkMIDIfromPipe(ChannelMessage midichmsg) { 100 0 : ChannelMessageMatcher midimsg = {midichmsg}; 101 : 102 : #ifdef DEBUG_MIDI_PACKETS 103 : // TODO: print CN 104 : if (midimsg.type != PROGRAM_CHANGE && midimsg.type != CHANNEL_PRESSURE) 105 : DEBUG(">>> " << hex << midichmsg.header << ' ' << midimsg.data1 << ' ' 106 : << midimsg.data2 << dec); 107 : else 108 : DEBUG(">>> " << hex << midichmsg.header << ' ' << midimsg.data1 << dec); 109 : #endif 110 : 111 : // If the Channel Message callback exists, call it to see if we have to 112 : // continue handling it. 113 0 : if (channelMessageCallback && channelMessageCallback(midichmsg)) 114 0 : return; 115 : 116 0 : if (midimsg.type == MIDIMessageType::CONTROL_CHANGE && 117 0 : midimsg.data1 == MIDI_CC::Reset_All_Controllers) { 118 : // Reset All Controllers 119 0 : DEBUG(F("Reset All Controllers")); 120 0 : MIDIInputElementCC::resetAll(); 121 0 : MIDIInputElementChannelPressure::resetAll(); 122 0 : } else if (midimsg.type == MIDIMessageType::CONTROL_CHANGE && 123 0 : midimsg.data1 == MIDI_CC::All_Notes_Off) { 124 0 : MIDIInputElementNote::resetAll(); 125 0 : } else { 126 0 : if (midimsg.type == MIDIMessageType::CONTROL_CHANGE) { 127 : // Control Change 128 0 : DEBUGFN(F("Updating CC elements with new MIDI message.")); 129 0 : MIDIInputElementCC::updateAllWith(midimsg); 130 : 131 0 : } else if (midimsg.type == MIDIMessageType::NOTE_OFF || 132 0 : midimsg.type == MIDIMessageType::NOTE_ON) { 133 : // Note 134 0 : DEBUGFN(F("Updating Note elements with new MIDI message.")); 135 0 : MIDIInputElementNote::updateAllWith(midimsg); 136 : 137 0 : } else if (midimsg.type == MIDIMessageType::CHANNEL_PRESSURE) { 138 : // Channel Pressure 139 0 : DEBUGFN(F("Updating Channel Pressure elements with new " 140 : "MIDI message.")); 141 0 : MIDIInputElementChannelPressure::updateAllWith(midimsg); 142 0 : } else if (midimsg.type == MIDIMessageType::PROGRAM_CHANGE) { 143 : // Channel Pressure 144 0 : DEBUGFN(F("Updating Program Change elements with new " 145 : "MIDI message.")); 146 0 : MIDIInputElementPC::updateAllWith(midimsg); 147 0 : } 148 : } 149 0 : } 150 : 151 0 : void Control_Surface_::sinkMIDIfromPipe(SysExMessage msg) { 152 : // System Exclusive 153 : #ifdef DEBUG_MIDI_PACKETS 154 : const uint8_t *data = msg.data; 155 : size_t len = msg.length; 156 : // TODO: print CN 157 : DEBUG_OUT << hex; 158 : for (size_t i = 0; i < len; i++) 159 : DEBUG_OUT << data[i] << ' '; 160 : DEBUG_OUT << dec << endl; 161 : #endif 162 : // If the SysEx Message callback exists, call it to see if we have to 163 : // continue handling it. 164 0 : if (sysExMessageCallback && sysExMessageCallback(msg)) 165 0 : return; 166 0 : MIDIInputElementSysEx::updateAllWith(msg); 167 0 : } 168 : 169 0 : void Control_Surface_::sinkMIDIfromPipe(RealTimeMessage rtMessage) { 170 : // If the Real-Time Message callback exists, call it to see if we have to 171 : // continue handling it. 172 0 : if (realTimeMessageCallback && realTimeMessageCallback(rtMessage)) 173 0 : return; 174 : // TODO: handle Real-Time input 175 0 : } 176 : 177 0 : void Control_Surface_::updateInputs() { 178 0 : MIDIInputElementCC::updateAll(); 179 0 : MIDIInputElementNote::updateAll(); 180 0 : MIDIInputElementChannelPressure::updateAll(); 181 0 : MIDIInputElementPC::updateAll(); 182 0 : MIDIInputElementSysEx::updateAll(); 183 0 : } 184 : 185 0 : void Control_Surface_::updateDisplays() { 186 0 : DisplayInterface *previousDisplay = nullptr; 187 0 : for (DisplayElement &displayElement : DisplayElement::getAll()) { 188 0 : DisplayInterface *thisDisplay = &displayElement.getDisplay(); 189 0 : if (!thisDisplay->isEnabled()) 190 0 : continue; 191 0 : if (thisDisplay != previousDisplay) { 192 0 : if (previousDisplay) 193 0 : previousDisplay->display(); 194 0 : previousDisplay = thisDisplay; 195 0 : thisDisplay->clearAndDrawBackground(); 196 0 : } 197 0 : displayElement.draw(); 198 0 : } 199 0 : if (previousDisplay) 200 0 : previousDisplay->display(); 201 0 : } 202 : 203 1 : Control_Surface_ &Control_Surface = Control_Surface_::getInstance(); 204 : 205 : END_CS_NAMESPACE