#include <SPI.h>
#include <Wire.h>
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/* OLED DISPLAY VARIABLES */
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);
/* CHANGE PINS TO SUIT YOUR ARDUINO PINOUT */
const int sw1Pin = A0;
const int sw2Pin = A1;
const int sw3Pin = A2;
const int sw4Pin = A3;
const int sw5Pin = 10;
const int RELAY1 = 2; //set pin for RELAY 1 (CLEAN) D2
const int RELAY2 = 3; //set pin for RELAY 2 (GAIN1/GAIN2) D3
const int RELAY3 = 4; //set pin for RELAY 3 (BOOST) D4
const int RELAY4 = 5; //set pin for RELAY 4 (SAT) D5
const int RELAY5 = 6; //set pin for RELAY 5 (PLEXI) D6
const int RELAY6 = 7; //set pin for RELAY 6 (FX LOOP)
const int RELAY7 = 8; //set pin for RELAY 7 (SPARE)
const int RELAY8 = 9; //set pin for RELAY 8 (SPARE)
const int storeControl = 11;
const int storePin = 12;
const int mutePin = 13;
#define StoreSave 104
// define output pins
int outputPin[] = {2, 3, 4, 5, 6, 7, 8, 9};
int swPush = 0;
boolean swState = LOW;
boolean swStateLast = LOW;
const unsigned char NaN [] PROGMEM = {
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03,
0x80, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00,
0x00, 0x00, 0x03, 0xf8, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x3f, 0xe0, 0x00, 0x00, 0x00,
0x03, 0xf8, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf8,
0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0xe0, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x1f, 0xe0, 0x00,
0x00, 0x07, 0xfc, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x03,
0xfc, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00,
0x00, 0x04, 0x7f, 0xe0, 0x03, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x01, 0xfc, 0x00, 0x00, 0xff,
0xff, 0xf0, 0x00, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x0c, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x03, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0x83, 0xf0,
0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe3, 0x80, 0x00, 0x00,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xf7, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf7, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x8f, 0xf0, 0x00, 0x00,
0x00, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x80, 0x00, 0x00
};
uint8_t midi_channel = 0;
MIDI_CREATE_DEFAULT_INSTANCE();
void handleError(int8_t err)
{
digitalWrite(LED_BUILTIN, (err == 0) ? LOW : HIGH);
}
void midiStore() {
boolean storeState = false;
storeState = digitalRead(storeControl);
if (!storeState) {
midiCtrlChange(MIDI.getInputChannel(), 104);
digitalWrite (storePin, LOW);
delay(40);
digitalWrite (storePin, HIGH);
}
}
//MIDI PROG NUMBER
int currentProgramNumber = 0;
#define channelAddress 129 //0 to 127 used for MIDI program presets
#define firstOnAddress 130 //0 to 127 used for MIDI program presets
#define lastProgram 131 //load the last selected program on startup
//MIDI MUTE FUNCTIONS
void mute() {
digitalWrite(mutePin, HIGH);
delay(40);
digitalWrite(mutePin, LOW);
}
void recallPinStates(int programNumber);
void recallPinStates(int programNumber) {
int pinStates = 0;
int loopCount = 0;
int outputPin = 12;
pinStates = EEPROM.read(programNumber);
for (int loopCount = 7; loopCount >=0 ; loopCount--) {
//read individual bits and set matching output pin
digitalWrite(outputPin, bitRead(pinStates, loopCount));
outputPin++;
}
}
//MIDI PC FUNCTIONS
void handleProgramChange(byte channel, byte number) {
mute();
delay(5);
currentProgramNumber = number;
recallPinStates(currentProgramNumber);
//store as the last selected PC
EEPROM.write(lastProgram,currentProgramNumber);
}
//MIDI CC FUNCTIONS
void midiCtrlChange(byte c, byte v) {
int address = currentProgramNumber;
int number = 0;
byte pinStateArray[8] = {0,0,0,0,0,0,0,0};
int pinState = 0;
int i = 0;
mute();
MIDI.sendControlChange(c, v, 0xB0 | midi_channel);
if (c == 102 && v == 0) {
for (int resetAddress = 0; resetAddress < 128; resetAddress++) {
EEPROM.write(resetAddress, 0x01);
}
}
if (c == 104 && v == 0) {
for (int outputPin = 1; outputPin < 10; outputPin++) {
//read output pin and store in bit array
pinStateArray[i] = digitalRead(outputPin);
//add individual pin state into total byte
pinState += (pinStateArray[i] << (7-i));
i++;
}
EEPROM.write(address, pinState);
}
if (v > 64) {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.print(" SIRIUS AMPLIFICATION ");
display.setCursor(0, 55);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.print("CC:");
display.setCursor(20, 55);
display.print(c);
display.setCursor(40, 55);
display.print("V:");
display.display();
display.print(v);
display.print(" ");
display.display();
}
if (v <= 64) {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.print(" SIRIUS AMPLIFICATION ");
display.setCursor(0, 55);
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.print("CC:");
display.setCursor(20, 55);
display.print(c);
display.setCursor(40, 55);
display.print("V:");
display.display();
display.print(v);
display.print(" ");
display.display();
}
if (c == 59 && v > 64) {
//FX Loop Bypass CC MSG
digitalWrite(RELAY6, HIGH);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("FX:");
if (v == 127) display.print("ON");
display.print(" ");
display.display();
}
if (c == 59 && v <= 64) {
//FX Loop Bypass CC MSG
digitalWrite(RELAY6, LOW);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("FX:");
if (v == 0) display.print("OFF");
display.print(" ");
display.display();
}
if (c == 85 && v > 64) {
//Clean Channel On CC MSG
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY3, LOW);
digitalWrite(RELAY4, LOW);
digitalWrite(RELAY5, LOW);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("CLEAN");
display.print(" ");
display.display();
}
if (c == 85 && v <= 64) {
//Clean Channel Off CC MSG
}
if (c == 86 && v > 64) {
//Gain Channel On CC MSG
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("GAIN 1");
display.print(" ");
display.display();
}
if (c == 86 && v <= 64) {
//Gain Channel Off CC MSG
}
if (c == 87 && v > 64) {
//Channel On CC MSG
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, HIGH);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("GAIN 2");
display.print(" ");
display.display();
}
if (c == 87 && v <= 64) {
//Channel Off CC MSG
digitalWrite(RELAY2, LOW);
}
if (c == 88 && v > 64) {
//Channel On CC MSG
digitalWrite(RELAY3, HIGH);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("BOOST:");
if (v == 127) display.print("ON");
display.print(" ");
display.display();
}
if (c == 88 && v <= 64) {
//Channel Off CC MSG
digitalWrite(RELAY3, LOW);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("BOOST:");
if (v == 0) display.print("OFF");
display.print(" ");
display.display();
}
if (c == 89 && v > 64) {
//Toggle On CC MSG
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY5, HIGH);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("PLEXI:");
if (v == 127) display.print("ON");
display.print(" ");
display.display();
}
if (c == 89 && v <= 64) {
//Toggle Off CC MSG
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY3, LOW);
digitalWrite(RELAY4, LOW);
digitalWrite(RELAY5, LOW);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("PLEXI:");
if (v == 0) display.print("OFF");
display.print(" ");
display.display();
}
if (c == 90 && v > 64) {
//Toggle On CC MSG
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY4, HIGH);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("JTS:");
if (v == 127) display.print("ON");
display.print(" ");
display.display();
}
if (c == 90 && v <= 64) {
//Toggle Off CC MSG
digitalWrite(RELAY4, LOW);
display.setCursor(0, 20);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("JTS:");
if (v == 0) display.print("OFF");
display.print(" ");
display.display();
}
if (c == 91 && v > 64) {
//Reverb Volume On CC MSG
//Use digitalWrite(OUTPUT,HIGH); for direct functions
}
if (c == 91 && v <= 64) {
//Reverb Volume Off CC MSG
//Use digitalWrite(OUTPUT,LOW); for direct functions
}
if (c == 92 && v > 64) {
//Tremelo Volume On CC MSG
//Use digitalWrite(OUTPUT,HIGH); for direct functions
}
if (c == 92 && v <= 64) {
//Tremelo Volume Off CC MSG
//Use digitalWrite(OUTPUT,LOW); for direct functions
}
}
void setup() {
//INITIATE INPUT & OUTPUTS
pinMode(sw1Pin, INPUT_PULLUP);
pinMode(sw2Pin, INPUT_PULLUP);
pinMode(sw3Pin, INPUT_PULLUP);
pinMode(sw4Pin, INPUT_PULLUP);
pinMode(sw5Pin, INPUT_PULLUP);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
pinMode(RELAY5, OUTPUT);
pinMode(RELAY6, OUTPUT);
pinMode(RELAY7, OUTPUT);
pinMode(RELAY8, OUTPUT);
pinMode(mutePin, OUTPUT);
pinMode(storePin, OUTPUT);
pinMode(storeControl, INPUT_PULLUP);
// INITIATE CLEAN CHANNEL
digitalWrite(RELAY1, HIGH);
// INITIATE MIDI
Serial.begin(9600);
MIDI.setHandleError(handleError);
MIDI.begin(MIDI_CHANNEL_OMNI);
// INITIATE DISPLAY SPLASHSCREEN
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.drawBitmap(40, 5, NaN, 50, 50, WHITE);
display.display();
delay(3000);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);
display.setCursor(0, 0);
display.print(" SIRIUS AMPLIFICATION ");
display.display();
midiCtrlChange(85, 127);
}
void loop() {
MIDI.read();
//SWITCH 1 FUNCTIONS
swState = digitalRead(sw1Pin);
if (swState != swStateLast)
{
if (swState == LOW)
{
swPush++;
if (swPush > 1)
{
swPush = 0;
}
switch (swPush)
{
case 1:
midiCtrlChange(86, 127);
break;
case 0:
midiCtrlChange(87, 127);
break;
}
}
swStateLast = swState;
delay(10);
while (digitalRead(sw1Pin) == LOW)
{
delay(5);
}
}
//SWITCH 2 FUNCTIONS
swState = digitalRead(sw2Pin);
if (swState != swStateLast)
{
if (swState == LOW)
{
swPush++;
if (swPush > 1)
{
swPush = 0;
}
switch (swPush)
{
case 1:
midiCtrlChange(88, 127);
break;
case 0:
midiCtrlChange(88, 0);
break;
}
}
swStateLast = swState;
delay(10);
while (digitalRead(sw2Pin) == LOW)
{
delay(5);
}
}
//SWITCH 3 FUNCTIONS
swState = digitalRead(sw3Pin);
if (swState != swStateLast)
{
if (swState == LOW)
{
swPush++;
if (swPush > 1)
{
swPush = 0;
}
switch (swPush)
{
case 1:
midiCtrlChange(90, 127);
break;
case 0:
midiCtrlChange(90, 0);
break;
}
}
swStateLast = swState;
delay(10);
while (digitalRead(sw3Pin) == LOW)
{
delay(5);
}
}
//SWITCH 4 FUNCTIONS
swState = digitalRead(sw4Pin);
if (swState != swStateLast)
{
if (swState == LOW)
{
swPush++;
if (swPush > 1)
{
swPush = 0;
}
switch (swPush)
{
case 1:
midiCtrlChange(89, 127);
break;
case 0:
midiCtrlChange(89, 0);
break;
}
}
swStateLast = swState;
delay(10);
while (digitalRead(sw4Pin) == LOW)
{
delay(5);
}
}
//SWITCH 5 FUNCTIONS
swState = digitalRead(sw5Pin);
if (swState != swStateLast)
{
if (swState == LOW)
{
swPush++;
if (swPush > 1)
{
swPush = 0;
}
switch (swPush)
{
case 1:
midiCtrlChange(59, 127);
break;
case 0:
midiCtrlChange(59, 0);
break;
}
}
swStateLast = swState;
delay(10);
while (digitalRead(sw5Pin) == LOW)
{
delay(5);
}
}
//STORE FUNCTIONS
swState = digitalRead(storeControl);
if (swState != swStateLast)
{
if (swState == LOW)
{
swPush++;
if (swPush > 1)
{
swPush = 0;
}
switch (swPush)
{
case 1:
midiCtrlChange(104, 0);
break;
}
}
swStateLast = swState;
delay(10);
while (digitalRead(storeControl) == LOW)
{
delay(5);
}
}
}