#include <Arduino.h>
#include <Wire.h>
#include "AxeFxControl.h"
#include "LiquidCrystal_I2C.h"
#include "OneButton.h"
#define SCENE_1 1 // Scene 1
#define SCENE_2 2 // Scene 2
#define SCENE_3 3 // Scene 3
#define SCENE_4 4 // Scene 4
#define SCENE_5 5 // Scene 5
#define SCENE_6 6 // Scene 6
#define SCENE_7 7 // Scene 7
#define SCENE_8 8 // Scene 8
#define MODES1 "1 Scenes "
#define MODES2 "2 Effects "
#define MODES3 "3 Config "
#define MODES4 "4 Looper "
// Create an instance of the AxeSystem class
AxeSystem Axe;
// Create the lcd object with address 0x27 and 16 columns x 2 rows
LiquidCrystal_I2C lcd(0x27,20,4);
// Variable that stores the last button pressed
int lastButton = 0;
// Variable thar stores mode
String mode = "Scn";
// Variable that stores if mode is changing
bool modeChanging = false;
// Create buttons
OneButton button1(53);
OneButton button2(52);
OneButton button3(51);
OneButton button4(50);
OneButton button5(49);
OneButton button6(48);
OneButton button7(47);
OneButton button8(46);
// Function executed when button is pressed
void click1();
void click2();
void click3();
void click4();
void click5();
void click6();
void click7();
void click8();
void printLCD(String message1 = "",String message2 = "",String message3 = "",String message4 = "");
void clearLcd();
void modeScreen();
void onPresetChange(AxePreset preset);
void PresetDecrement();
void PresetIncrement();
void down10Presets();
void up10Presets();
void down100Presets();
void up100Presets();
void sceneMode();
void effectMode();
void configMode();
void loopMode();
void setup() {
// Initialize serial port for debugging
Serial.begin(9600);
button3.setLongPressIntervalMs(300);
button6.setLongPressIntervalMs(300);
// Procedures when button is pressed
button1.attachClick(click1);
button2.attachClick(click2);
button3.attachClick(click3);
button4.attachClick(click4);
button5.attachClick(click5);
button6.attachClick(click6);
button7.attachClick(click7);
button8.attachClick(click8);
// Prodecure when longpressing occurs
button1.attachLongPressStart(modeScreen);
button4.attachLongPressStart(PresetDecrement);
button8.attachLongPressStart(PresetIncrement);
button4.attachDoubleClick(down10Presets);
button8.attachDoubleClick(up10Presets);
button4.attachMultiClick(down100Presets);
button8.attachMultiClick(up100Presets);
// Initialize the LCD
lcd.init();
// Turn on the backlight
lcd.backlight();
printLCD("** Piggy MidiBox **","",""," An FM3 Controller");
delay(1000);
printLCD("Fractal FM III ","Firmware 1.4","AxeFxControl","by David Granados ");
delay(750);
clearLcd();
sceneMode(); // Set the initial mode to "Scenes"
// Initialize the AxeSystem with Serial1
Axe.begin(Serial1,AxeSystem::MIDI_CHANNEL_OMNI);
Axe.registerPresetChangeCallback(onPresetChange);
Axe.requestPresetDetails();
Axe.fetchEffects(true);
Axe.enableRefresh(3000,500);
Axe.refresh(true);
}
void loop() {
// Update the AxeSystem to process incoming data
Axe.update();
// Update the state of the buttons
button1.tick();
button2.tick();
button3.tick();
button4.tick();
button5.tick();
button6.tick();
button7.tick();
button8.tick();
}
void click1()
{
Serial.println("Click 1");
if (modeChanging)
{
sceneMode(); // Change to scene mode
onPresetChange(Axe.getCurrentPreset()); // Update the LCD with the current preset and scene
}
else
{
if (lastButton != 1)
{
lastButton = 1;
Axe.sendSceneChange(SCENE_1);
}
}
}
void click2()
{
Serial.println("Click 2");
if (modeChanging)
{
effectMode(); // Change to effect mode
onPresetChange(Axe.getCurrentPreset()); // Update the LCD with the current preset and scene
}
else
{
if (lastButton != 2)
{
lastButton = 2;
Axe.sendSceneChange(SCENE_2); // Send the effect change command to the AxeFX
}
}
}
void click3()
{
Serial.println("Click 3");
if (modeChanging)
{
configMode();
onPresetChange(Axe.getCurrentPreset()); // Update the LCD with the current preset and scene
}
else
{
if (lastButton != 3)
{
lastButton = 3;
Axe.sendSceneChange(SCENE_3);
}
}
}
void click4()
{
Serial.println("Click 4");
if (modeChanging)
{
loopMode();
onPresetChange(Axe.getCurrentPreset()); // Update the LCD with the current preset and scene
}
else
{
if (lastButton != 4)
{
lastButton = 4;
Axe.sendSceneChange(SCENE_4); // Send the effect change command to the AxeFX
}
}
}
void click5()
{
Serial.println("Click 5");
if (modeChanging)
{
modeChanging = false;
}
else
{
if (lastButton != 5)
{
lastButton = 5;
Axe.sendSceneChange(SCENE_5); // Send the effect change command to the AxeFX
}
}
}
void click6()
{
Serial.println("Click 6");
if (modeChanging)
{
modeChanging = false;
}
else
{
if (lastButton != 6)
{
lastButton = 6;
Axe.sendSceneChange(SCENE_6); // Send the effect change command to the AxeFX
}
}
}
void click7()
{
Serial.println("Click 7");
if (modeChanging)
{
modeChanging = false;
}
else
{
if (lastButton != 7)
{
lastButton = 7;
Axe.sendSceneChange(SCENE_7); // Send the effect change command to the AxeFX
}
}
}
void click8()
{
Serial.println("Click 8");
if (modeChanging)
{
modeChanging = false;
}
else
{
if (lastButton != 8)
{
lastButton = 8;
Axe.sendSceneChange(SCENE_8); // Send the effect change command to the AxeFX
}
}
}
void down10Presets()
{
PresetNumber preset = Axe.getCurrentPreset().getPresetNumber();
if (preset < 10) {
preset = 0;
} else {
preset -= 10;
}
Axe.sendPresetChange(preset);
Serial.print("Retrocede 10 presets: ");
}
void up10Presets()
{
PresetNumber preset = Axe.getCurrentPreset().getPresetNumber();
if (preset > 500) {
preset = 511;
} else {
preset += 10;
}
Axe.sendPresetChange(preset);
Serial.print("Avanza 10 presets: ");
}
void down100Presets()
{
PresetNumber preset = Axe.getCurrentPreset().getPresetNumber();
if (preset < 100) {
preset = 0;
} else {
preset -= 100;
}
Axe.sendPresetChange(preset);
Serial.print("Retrocede 100 presets: ");
}
void up100Presets()
{
PresetNumber preset = Axe.getCurrentPreset().getPresetNumber();
if (preset > 410) {
preset = 511;
} else {
preset += 100;
}
Axe.sendPresetChange(preset);
Serial.print("Avanza 100 presets: ");
}
void modeScreen()
{
clearLcd();
printLCD(MODES1,MODES2,MODES3,MODES4);
modeChanging = true;
lastButton = 0;
}
void clearLcd() {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,2);
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print(" ");
}
void printLCD(String message1, String message2, String message3, String message4)
{
if (message1.length() > 0)
{
lcd.setCursor(0,0);lcd.print(message1);
}
if (message2.length() > 0)
{
lcd.setCursor(0,1);lcd.print(message2);
}
if (message3.length() > 0)
{
lcd.setCursor(0,2);lcd.print(message3);
}
if (message4.length() > 0)
{
lcd.setCursor(0,3);lcd.print(message4);
}
}
void PresetDecrement(){ Axe.sendPresetDecrement();}
void PresetIncrement(){ Axe.sendPresetIncrement();}
void onPresetChange(AxePreset preset) {
// Preset and scene Number & Name to LCD display
printLCD("P"+String(preset.getPresetNumber())+" "+String(preset.getPresetName()).substring(0,10)+" "+String(mode),
"S"+String(preset.getSceneNumber())+" "+String(preset.getSceneName()).substring(0,15)+" ","","");
}
void sceneMode()
{
mode = " Scn";
modeChanging = false;
printLCD("","","5 6 7 8 ","1 2 3 4 ");
}
void effectMode()
{
mode = " Fx";
modeChanging = false;
printLCD("",""," Cmp Drv Flg Trm "," Cmp Drv Flg Trm ");
}
void configMode()
{
mode = " Cfg";
modeChanging = false;
printLCD("","","Contrast ","Midi Channel ");
}
void loopMode()
{
mode = " loop";
modeChanging = false;
printLCD("",""," ","Play Record Undo");
}