Line data Source code
1 : #pragma once 2 : 3 : #include <AH/Hardware/Button.hpp> 4 : #include <Banks/BankableMIDIOutput.hpp> 5 : #include <Def/Def.hpp> 6 : #include <AH/Containers/Array.hpp> 7 : #include <MIDI_Outputs/Abstract/MIDIOutputElement.hpp> 8 : 9 : BEGIN_CS_NAMESPACE 10 : 11 : namespace Bankable { 12 : 13 : /** 14 : * @brief An abstract class for momentary push buttons that send MIDI events. 15 : * 16 : * The buttons are debounced. 17 : * 18 : * @todo Use BankAddresses? 19 : * 20 : * @see Button 21 : */ 22 : template <class Sender, uint8_t NUMBER_OF_BUTTONS> 23 4 : class MIDIButtons : public BankableMIDIOutput, public MIDIOutputElement { 24 : protected: 25 : /** 26 : * @brief Construct a new MIDIButtons. 27 : * 28 : * @todo Documentation 29 : */ 30 4 : MIDIButtons(const OutputBankConfig &config, 31 : const Array<AH::Button, NUMBER_OF_BUTTONS> &buttons, 32 : const MIDICNChannelAddress &baseAddress, 33 : const RelativeMIDICNChannelAddress &incrementAddress, 34 : const Sender &sender) 35 8 : : BankableMIDIOutput(config), buttons{buttons}, 36 4 : baseAddress(baseAddress), 37 20 : incrementAddress(incrementAddress), sender{sender} {} 38 : 39 : public: 40 2 : void begin() final override { 41 6 : for (auto &button : buttons) 42 4 : button.begin(); 43 2 : } 44 16 : void update() final override { 45 16 : MIDICNChannelAddress address = baseAddress; 46 48 : for (auto &button : buttons) { 47 32 : AH::Button::State state = button.update(); 48 32 : if (state == AH::Button::Falling) { 49 5 : if (!activeButtons) 50 3 : lock(); // Don't allow changing of the bank setting 51 5 : MIDICNChannelAddress sendAddress = address + getAddressOffset(); 52 5 : activeButtons++; 53 5 : sender.sendOn(sendAddress); 54 32 : } else if (state == AH::Button::Rising) { 55 5 : MIDICNChannelAddress sendAddress = address + getAddressOffset(); 56 5 : sender.sendOff(sendAddress); 57 5 : activeButtons--; 58 5 : if (!activeButtons) 59 3 : unlock(); 60 5 : } 61 32 : address += incrementAddress; 62 : } 63 16 : } 64 : 65 : #ifdef INDIVIDUAL_BUTTON_INVERT 66 : void invert() { 67 : for (auto &button : buttons) 68 : button.invert(); 69 : } 70 : #endif 71 : 72 : AH::Button::State getButtonState(size_t index) const { 73 : return buttons[index].getState(); 74 : } 75 : 76 : private: 77 : Array<AH::Button, NUMBER_OF_BUTTONS> buttons; 78 : const MIDICNChannelAddress baseAddress; 79 : const RelativeMIDICNChannelAddress incrementAddress; 80 4 : uint8_t activeButtons = 0; 81 : 82 : public: 83 : Sender sender; 84 : }; 85 : 86 : } // namespace Bankable 87 : 88 : END_CS_NAMESPACE