#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <Wire.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/Picopixel.h>
#include <OSCMessage.h>
#include <OSCBoards.h>
/*
Make an OSC message and send it over serial
*/
#ifdef BOARD_HAS_USB_SERIAL
#include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial( thisBoardsSerialUSB );
#else
#include <SLIPEncodedSerial.h>
SLIPEncodedSerial SLIPSerial(Serial); // Change to Serial1 or Serial2 etc. for boards with multiple serial ports that don’t have Serial
#endif
String shapes[9] = {"BELL", "LOW_SHELF", "LOW_CUT", "HIGH_SHELF", "HIGH_CUT", "NOTCH", "BAND", "TILT_SHELF", "FLAT_TILT"};
// Display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// MIDI
int currentMidiChannel = 1;
// Leds
#define ledStripActive 4
#define ledBandActive 4
// buttons
#define buttonSwitchLed 5
#define buttonPreviousChannel 6
#define buttonNextChannel 7
#define buttonEqActive 13
// EQ
bool currentBandActive = true;
// pots
// Frequency Pot
#define frequencyRangePotDT 9
#define frequencyRangePotCLK 8
#define frequencyRangePotSW A2
int frequencyLastModeChange = 0;
int frequencyLastClk;
uint8_t frequencyHzValue = 0;
// Gain Pot
#define gainPotDT 12
#define gainPotCLK 13
#define gainPotSW A0
int gainLastClk;
int gainLastModeChange = 0;
uint8_t gainValue = 0;
// Q Pot
#define qPotDT 11
#define qPotCLK 10
#define qPotSW A1
int qLastClk;
int qLastModeChange = 0;
uint8_t qValue = 0;
int currentEqShape = 6; //BAND
int lastEqShapeChange = 0;
// IO Pot
#define ioPotDT 11
#define ioPotCLK 10
#define ioPotSW A1
int ioLastClk;
int ioLastModeChange = 0;
uint8_t inputValue = 50;
uint8_t outputValue = 50;
bool stripActive = true;
void setup() {
SLIPSerial.begin(19200);
// Leds
pinMode(ledStripActive, OUTPUT);
pinMode(ledBandActive, OUTPUT);
// Buttons
pinMode(buttonSwitchLed, INPUT_PULLUP);
pinMode(buttonPreviousChannel, INPUT_PULLUP);
pinMode(buttonNextChannel, INPUT_PULLUP);
// Pots
pinMode(frequencyRangePotCLK, INPUT);
pinMode(frequencyRangePotDT, INPUT);
pinMode(frequencyRangePotSW, INPUT_PULLUP);
frequencyLastClk = digitalRead(frequencyRangePotCLK);
pinMode(gainPotCLK, INPUT);
pinMode(gainPotDT, INPUT);
pinMode(gainPotSW, INPUT_PULLUP);
gainLastClk = digitalRead(gainPotCLK);
// Display
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
delay(2000); // Pause for 2 seconds
updateDisplay();
}
void loop() {
if (digitalRead(A2) == LOW){
OSCMessage analog0("/analog/2");
stripActive = !stripActive;
analog0.add(stripActive);
SLIPSerial.beginPacket();
analog0.send(SLIPSerial); // send the bytes to the SLIP stream
SLIPSerial.endPacket(); // mark the end of the OSC Packet
analog0.empty(); // free space occupied by message
}
// if (digitalRead(buttonNextChannel) == LOW){
// delay(100);
// int newValue = currentMidiChannel + 1;
// if(newValue == 0 || newValue == 16) return;
// currentMidiChannel = newValue;
// updateDisplay();
// }
// if (digitalRead(buttonPreviousChannel) == LOW){
// delay(100);
// int newValue = currentMidiChannel - 1;
// if(newValue == 0 || newValue == 16) return;
// currentMidiChannel = newValue;
// }
// processRotary(frequencyRangePotCLK, frequencyRangePotDT, frequencyLastClk, frequencyHzValue, 5, 0, 1023);
// processRotary(gainPotCLK, gainPotDT, gainLastClk, gainValue, 1, 0, 1023);
// processRotary(qPotCLK, qPotDT, qLastClk, qValue, 1, 0, 1023);
// processRotaryMomentaryButtonIncremental(gainPotSW, currentEqShape, 9, lastEqShapeChange);
// processRotaryMomentaryButtonLed(frequencyRangePotSW, ledBandActive, currentBandActive, frequencyLastModeChange);
}
void processRotary(int clkPin, int dtPin, int &lastClk, uint8_t ¤tValue, int sensibility, int minimum, int maximum) {
int clkRead = digitalRead(clkPin);
if (clkRead != lastClk && clkRead == LOW) {
int dtRead = digitalRead(dtPin);
int delta = dtRead == HIGH ? sensibility : -sensibility;
currentValue = constrain(currentValue + delta, minimum, maximum);
updateDisplay();
}
lastClk = &clkRead;
}
void processRotaryMomentaryButtonBool(int swPin, bool &value, int &modeLastChanged) {
if (digitalRead(swPin) == LOW && millis() - modeLastChanged > 300) {
modeLastChanged = millis();
value = !value;
updateDisplay();
}
}
void processRotaryMomentaryButtonLed(int swPin, int ledPin, bool &value, int &modeLastChanged) {
if (digitalRead(swPin) == LOW && millis() - modeLastChanged > 300) {
modeLastChanged = millis();
value = !value;
digitalWrite(ledPin, value ? HIGH : LOW);
}
}
void processRotaryMomentaryButtonIncremental(int swPin, int &value, int limit, int &modeLastChanged) {
if (digitalRead(swPin) == LOW && millis() - modeLastChanged > 300) {
modeLastChanged = millis();
int newValue = value + 1;
if(newValue > limit) {
value = 0;
}
else {
value = newValue;
}
updateDisplay();
}
}
void updateDisplay() {
display.clearDisplay();
display.setFont();
display.setTextColor(2);
display.setCursor(24, 2);
display.print("Channel: ");
display.print(currentMidiChannel);
display.setCursor(24, 12);
// display.print("Enabled: ");
// display.print(currentBandActive ? "yes" : "no");
display.setCursor(24, 22);
display.print("Freq: ");
int hz = (frequencyHzValue * 19.5) + 20;
display.print(hz);
display.print(" Hz");
display.setCursor(24, 32);
display.print("Gain: ");
display.print(gainValue);
display.print(" dB");
display.setCursor(24, 42);
display.print("Q: ");
display.print(qValue);
display.setCursor(24, 52);
display.print("Filter: ");
display.print(shapes[currentEqShape]);
display.display();
}