tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.
GNU General Public License v3.0
1.24k stars 139 forks source link

Change address of one encoder with two physical buttons and one cycling button, IncrementSelector and ManyButtonsSelector #224

Open ParametricToroid opened 4 years ago

ParametricToroid commented 4 years ago

Hello,

Thank you again for creating this excellent library! I have been able to change the address of a set of encoders in the past with Bankable::ManyAddresses:CCRotaryEncoder. However, I'd like to implement a more complex method of changing the address of a single encoder.

If have one encoder that I would like to have 5 different addresses, I could change the address using banks and something like ManyButtonsSelector, or IncrementSelector. However, I'd like to use three buttons, where two of them (physical) will each correspond to an address, and the third I will be able to press multiple times to cycle through addresses (each press simulates a different button press).

I suppose that this would look like: Button_1 press -> midi cc address 1 Button_2 press -> midi cc address 2 Button_3 press -> midi cc address 3 Button_3 press -> midi cc address 4 Button_3 press -> midi cc address 5 And the cycle would continue: Button_1 press -> midi cc address 1

What I'd like to do would be to use ManyButtonSelector, and simulate multiple third button presses being treated like physical buttons. I would think it would look like this:

#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library.
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Create Bank Object
Bank<5> bank; //create bank for multi selector
Bankable::ManyAddresses::CCRotaryEncoder<5> enc2_16 = {
  bank,
  {5, 4},         // pins
  {
    31, // address for Bank 1
    32,    // address for Bank 2
    57, //addr 3
    58, //addr 4
    59, //addr 5
  },
  1,              // optional multiplier if the control isn't fast enough
  1,              //Pulses per step
};

CD74HC4067 mux2 = {
  40,            // input pin
  {0, 1, 2, 3}, // Address pins S0, S1, S2, S3
  // 7, // Optionally, specify the enable pin
};

bool Button3_1 { false }; //declares the virtual button press 3_1
bool Button3_2 { false }; //declares the virtual button press 3_2
bool Button3_3 { false }; //declares the virtual button press 3_2

//declares the status of the virtual buttons
bool Button3_1_state { true };
bool Button3_2_state { false };
bool Button3_3_state { false };

//Create HSL_Basic_Bank switching button
ManyButtonsSelector<5> selector = {
  bank,
  {{mux2.pin(4),mux2.pin(5),Button3_1,Button3_2,Button3_3}}, //two PHYSICAL buttons, and three VIRTUAL buttons that are cycled through as button three is pressed
};

void setup() {
  RelativeCCSender::setMode(relativeCCmode::BINARY_OFFSET);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface

  //Determine the state of Button3 to change the bank of the encoder
  if (digitalRead(mux2.pin(3)) == 0 && Button3_1_state == true) { //if button 3 is pressed and button3_1_state is true, send virtual button input button3_1
    Button3_1 = true; //send the virtual button press button3_1 which would activate the third bank of the encoder
    Button3_1_state = false; //sets the status of button3_1 to false, to cycle through the functions of the third button
    Button3_2_state = true; //sets the next function of the third button (button3_2) to active so that if button 3 is pressed, button3_2 will be sent
  }
  if (digitalRead(mux2.pin(3)) == 0 && Button3_2_state == true) { //if button 3 is pressed and button3_2_state is true, send virtual button input button3_2
    Button3_2 = true; //send the virtual button press button3_2 which would activate the third bank of the encoder
    Button3_2_state = false; //sets the status of button3_2 to false, to cycle through the functions of the third button
    Button3_3_state = true; //sets the next function of the third button (button3_3) to active so that if button 3 is pressed, button3_3 will be sent
  }
  if (digitalRead(mux2.pin(3)) == 0 && Button3_3_state == true) { //if button 3 is pressed and button3_3_state is true, send virtual button input button3_3
    Button3_3 = true; //send the virtual button press button3_3 which would activate the third bank of the encoder
    Button3_3_state = false; //sets the status of button3_3 to false, to cycle through the functions of the third button
    Button3_1_state = true; //resets the cycle so that the next time button three is pressed, button3_1 will be sent
  }
}

This is what I would like to be able to do. However, it does not seem like ManyButtonsSelector works this way. Is there an alternative to being able to use two physical buttons, and three (virtual) buttons being cycled through?

I greatly appreciate your help figuring this out.

Thank you!!

tttapa commented 4 years ago

I'm on mobile right now, so I'll keep it short, but I'd leave out the ManyButtonsSelector (it doesn't work with variables, the arguments are pin numbers). You can call bank.select(setting) directly: https://tttapa.github.io/Control-Surface-doc/Doxygen/db/dbd/classBank.html#a801ab5dedea8200f1cdb26533cb6f78b, where setting is a number between zero and N-1.

ParametricToroid commented 4 years ago

Awesome! I'll give that a try. Thanks for your quick reply!