The MIDI Controller library has been obsoleted by its successor, the Control Surface library.
It has more features, a better architecture, unit tests, continuous integration, clearer documentation, support for more and newer Arduino boards, etc.
It adds support for MIDI input, SysEx, the Mackie Control Universal protocol, VU meters, LEDs, OLED displays, audio over USB, MIDI over Bluetooth, MIDI routing ...
And it is supported by the author, but anyway i think this is created by someone different.
Since you aren't planning to use a multiplexer, it is fine to use the overloaded function (mind you it seems controller.cpp is not complete the way it is now. (the function for the multiplexer are declared but there is no implementation.
We can add an extra argument to the Button in controller.h, but then the compiler might not be able to keep it apart from the muxButton. Where is the rest of conrtroller.cpp ?
I can't do this unless you provide me with the full file.
public:
Button(byte pin, byte command, byte value, byte channel, byte debounce);
Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce); // this function
byte getValue();
void muxUpdate(); // and this function is missing from Controller.cpp
void newValue(byte command, byte value, byte channel);
byte Bcommand;
byte Bvalue;
byte Bchannel;
byte Btoggle;
Understand that i anyway have the feeling that i am doing this twice, just a couple of weeks ago i added extra arguments for mapping to the mux-buttons.
This time it's going to be a bit more tricky, i'll have a proper check with a clear head in the morning. Understand i didn't write this code. But i think it's like this. i've put comments where i've changed things
Controller.h
#ifndef Controller_h
#define Controller_h
#include <Arduino.h>
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
public:
Button(byte pin, byte kcbutton, byte command, byte value, byte channel, byte debounce); // change this line
//Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
byte getValue();
//void muxUpdate();
void newValue(byte command, byte value, byte channel);
byte Bcommand;
byte Bvalue;
byte Bchannel;
byte Btoggle;
private:
byte buttonFromValue(int adValue); // add this line
byte _previous;
byte _current;
unsigned long _time;
int _debounce;
byte _pin;
byte _kcbutton; // and this one
//byte _muxpin;
//byte _numMuxPins;
byte _value;
byte _command;
bool _busy;
byte _status;
byte _last;
byte _enablepin;
};
#endif
Now in the getvalue() function the pin is read, and now instead of a digitalread() we need to do analogRead() pass that to the buttonFromValue() function, and compare the return value of that to the value that is stored in the new argument kcbutton. I think that works out to be like this
if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) , but that would invert the logic,
keep that in mind.
so now the whole controller.cpp ends up like
#include "Controller.h"
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte kcbutton, byte command, byte value, byte channel, byte debounce)
{
_pin = pin;
_kcbutton = kcbutton; // add this line
//pinMode(_pin, INPUT_PULLUP); // remove this line
pinMode(_pin, INPUT); // add this line
_value = value;
_command = command;
_debounce = debounce;
_time = 0;
_busy = false;
_status = 0b00000010;
_last = 1;
Bcommand = command;
Bvalue = value;
Bchannel = channel;
Btoggle = 0;
}
byte buttonFromValue(int adValue) { // add this whole function
if (adValue > 300 && adValue < 500) {
return 1;
}
if (adValue > 500 && adValue < 700) {
return 2;
}
if (adValue > 700 && adValue < 900) {
return 3;
}
if (adValue > 900) {
return 4;
}
return 0;
}
byte Button::getValue()
{
// If BUSY bit not set - read button
if (bitRead(_status, 0) == false) { // If busy false
if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) return 2; // If same as last state - exit
} // i think it is like this
// If NEW Bit set - Key just pressed, record time
if (bitRead(_status, 1) == true) { // If new is true
bitSet(_status, 0); // Set busy TRUE
bitClear(_status, 1); // Set New FALSE
_time = millis();
return 255;
}
// Check if debounce time has passed - If no, exit
if (millis() - _time < _debounce) return 255;
// Debounce time has passed. Read pin to see if still set the same
// If it has changed back - assume false alarm
if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) {
bitClear(_status, 0); // Set busy false
bitSet(_status, 1); // Set new true
return 255;
}
// If this point is reached, event is valid. return event type
else {
bitClear(_status, 0); // Set busy false
bitSet(_status, 1); // Set new true
_last = ((~_last) & 0b00000001); // invert _last
return _last;
}
}
void Button::newValue(byte command, byte value, byte channel)
{
Bvalue = value;
Bcommand = command;
Bchannel = channel;
}
and now you can declare buttons pretty much the same way as it was
//Button (Analog Pin Number, Button From keypad Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE 1=CC 2=Toggle CC **
//Button BU1(A0, 1, 0, 60, 1, 5 );
//Button BU2(A0, 2, 0, 61, 1, 5 );
etc.
The updateButtons() functions deals with action to take upon a button being pressed, now we need to invert the logic here as well.
void updateButtons() {
// Cycle through Button array
for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
byte message = BUTTONS[i]->getValue();
// Button is pressed
if (message == 1) { // invert the logic here
switch (BUTTONS[i]->Bcommand) {
case 0: //Note
MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
break;
case 1: //CC
MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
break;
case 2: //Toggle
if (BUTTONS[i]->Btoggle == 0) {
MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
BUTTONS[i]->Btoggle = 1;
}
else if (BUTTONS[i]->Btoggle == 1) {
MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
BUTTONS[i]->Btoggle = 0;
}
break;
}
}
// Button is not pressed
if (message == 0) { // and invert it here
switch (BUTTONS[i]->Bcommand) {
case 0:
MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
break;
case 1:
MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
break;
}
}
}
}
Now it should work (but it's after dinner time, and i haven't compiled it yet), still it would be easier to start using control-surface.h , it has all these keypad functions built in and more importantly, i wouldn't have to do the support, Pieter would do it 