PieterP:
This would be my approach:
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
class PushButton
{
public:
PushButton(uint8_t pin) // Constructor (executes when a PushButton object is created)
: pin(pin) { // remember the push button pin
pinMode(pin, INPUT_PULLUP); // enable the internal pull-up resistor
};
bool isPressed() // read the button state check if the button has been pressed, debounce the button as well
{
bool pressed = false;
bool state = digitalRead(pin); // read the button's state
int8_t stateChange = state - previousState; // calculate the state change since last time
if (stateChange == falling) { // If the button is pressed (went from high to low)
if (millis() - previousBounceTime > debounceTime) { // check if the time since the last bounce is higher than the threshold
pressed = true; // the button is pressed
}
}
if (stateChange == rising) { // if the button is released or bounces
previousBounceTime = millis(); // remember when this happened
}
previousState = state; // remember the current state
return pressed; // return true if the button was pressed and didn't bounce
};
private:
uint8_t pin;
bool previousState = HIGH;
unsigned long previousBounceTime = 0;
const unsigned long debounceTime = 25;
const static int8_t rising = HIGH - LOW;
const static int8_t falling = LOW - HIGH;
};
/--------------------------------------------------------------------------------------------------------------------------------/
class ProgramSelector
{
public:
ProgramSelector(uint8_t incrementPin, uint8_t decrementPin, uint8_t minProgram, uint8_t maxProgram)
: incrementButton{incrementPin}, decrementButton{decrementPin},
minProgram(minProgram), maxProgram(maxProgram), program(minProgram)
{}
void refresh() {
uint8_t newProgram = program;
if (incrementButton.isPressed())
newProgram = program < maxProgram ? program + 1 : minProgram; // Increment program number or wrap around
if (decrementButton.isPressed())
newProgram = program == minProgram ? maxProgram : program - 1; // Decrement program number or wrap around
if (newProgram != program) {
if (onChangeFn != nullptr)
onChangeFn(newProgram, program);
program = newProgram;
}
}
void onChange(void (*fn)(uint8_t newProgram, uint8_t program)) {
onChangeFn = fn;
}
uint8_t getProgram() {
return program;
}
void setProgram(uint8_t newProgram) {
if (onChangeFn != nullptr)
onChangeFn(newProgram, program);
program = newProgram;
}
private:
PushButton incrementButton, decrementButton;
const uint8_t minProgram, maxProgram;
uint8_t program;
void (*onChangeFn)(uint8_t newProgram, uint8_t program) = nullptr;
};
/--------------------------------------------------------------------------------------------------------------------------------/
const uint8_t incrementPin = 10;
const uint8_t decrementPin = 11;
const uint8_t channel = 1; // MIDI channel 1
const uint8_t minProgram = 0;
const uint8_t maxProgram = 127;
ProgramSelector ps = {incrementPin, decrementPin, minProgram, maxProgram};
PushButton presetButtons[] = {
{2}, {3}, {4}, {5}, {6}, {7}, // ...
};
const size_t numberOfPresets = sizeof(presetButtons) / sizeof(presetButtons[0]);
const uint8_t presets[numberOfPresets] = {
43, 49, 57, 58, 60, 61, // ...
};
const uint8_t ledPins[numberOfPresets] {
A0, A1, A2, A3, A4, A5, // ...
};
const char* presetNames[] = {
"Delay 500m",
"EQ Blues",
"Reverb 8v Down",
"Reverb Noise G.",
"Reverb Tremolo N",
"Reverb + 8v 5^",
// ...
};
/--------------------------------------------------------------------------------------------------------------------------------/
void refreshButtons() {
for (uint8_t i = 0; i < numberOfPresets; i++)
if (presetButtons[i].isPressed())
ps.setProgram(presets[i]);
}
const uint8_t NO_PRESET = -1;
uint8_t programToPreset(uint8_t program) {
for (uint8_t i = 0; i < numberOfPresets; i++)
if (presets[i] == program)
return i;
return NO_PRESET;
}
void onProgramChange(uint8_t newProgram, uint8_t oldProgram) {
lcd.clear();
lcd.print(newProgram + 1);
static uint8_t previousPreset = NO_PRESET;
if (previousPreset != NO_PRESET) {
digitalWrite(ledPins[previousPreset], LOW);
}
uint8_t preset = programToPreset(newProgram);
if (preset != NO_PRESET) {
lcd.setCursor(10, 0);
lcd.print("Bank ");
lcd.setCursor(15, 0);
lcd.print(preset + 1);
lcd.setCursor(0, 1);
lcd.print(presetNames[preset]);
digitalWrite(ledPins[preset], HIGH);
}
previousPreset = preset;
sendMIDIProgramChange(channel, newProgram);
}
void initializeLCD() {
lcd.begin();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" DIGITECH ");
lcd.setCursor(0, 1);
lcd.print("Edge Control 2.0");
delay(500);
}
void initializeMIDI() {
Serial.begin(31250);
}
void initializeIO() {
for (uint8_t i = 0; i < numberOfPresets; i++)
pinMode(ledPins[i], OUTPUT);
}
void sendMIDIProgramChange(uint8_t channel, uint8_t program) {
Serial.write(0xC0 | ((channel - 1) & 0xF));
Serial.write(program & 0x7F);
}
/--------------------------------------------------------------------------------------------------------------------------------/
void setup() {
initializeMIDI();
initializeLCD();
initializeIO();
ps.onChange(onProgramChange);
}
void loop() {
ps.refresh();
refreshButtons();
}
You could rewrite the ProgramSelector class as normal functions, because you don't really need it to be object-oriented, but this is just what I started from.
I'll see if I find the time to document the code, if you don't understand what's going on, just ask.
Pieter
You rock Peter! at first try everything is working fine, just a coulpe of questions, now I'm with Arduino Uno, but since has more buttons now I will go with Mega board, LCD pins on UNo are A4 and A5, on Mega should be 20 and 21 I guess right?
the button up and down works as I wanted, is there any change to wirte the name complete? I mean shows only number but if I pass thourgh bank 44 for explame shows the name complete writen on code of const char* presetNames. I gues is not easy as filling the names on that because should I write ll banks names and start from 1 to 128 and the variable should be different, each const characthert equals number preset above, this idea will work if I should have start from bank 1 and not 44 right?
thank!