#include <LiquidCrystal_I2C.h>
#include <avr/pgmspace.h>
#define SwitchMenu 11
#define LedPin 10
#define DISPLAYS 2
char buffer[17];
int switchState = -1;
const int PINS[][3] = {{2,3,A0}, {4,5,A1}, {6,7,A2}, {8,9,A3}};
int VALUES[][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
LiquidCrystal_I2C LCD[] = {LiquidCrystal_I2C(0x27,16,2), LiquidCrystal_I2C(0x26,16,2)};
//Command Strings 12 charactere max
const char fx01[] PROGMEM = "Delay %3d%%";
const char fx02[] PROGMEM = "Echo %3d%%";
const char fx03[] PROGMEM = "Reverb %3d%%";
const char fx04[] PROGMEM = "Phaser %3d%%";
const char fx05[] PROGMEM = "Flanger %3d%%";
const char fx06[] PROGMEM = "LPF %3d%%";
const char fx07[] PROGMEM = "LFO Filter %3d%%";
const char fx08[] PROGMEM = "HPF %3d%%";
const char fx09[] PROGMEM = "Combo Filter%3d%%";
const char fx10[] PROGMEM = "Pan Delay %3d%%";
const char fx11[] PROGMEM = "Distortion %3d%%";
const char fx12[] PROGMEM = "Version Echo%3d%%";
const char fx13[] PROGMEM = "Epic Reverb %3d%%";
const char fx14[] PROGMEM = "EpicVerbDrop%3d%%";
const char fx15[] PROGMEM = "Bit Crush %3d%%";
const char fx16[] PROGMEM = "Tremolo %3d%%";
const char fx17[] PROGMEM = "Transform %3d%%";
const char fx18[] PROGMEM = "Repeater %3d%%";
const char fx19[] PROGMEM = "Shredder %3d%%";
const char fx20[] PROGMEM = "Braker %3d%%";
const char fx21[] PROGMEM = "Brake Echo %3d%%";
const char fx22[] PROGMEM = "CleanEchoOut%3d%%";
const char fx23[] PROGMEM = "Echo Out %3d%%";
const char fx24[] PROGMEM = "Fader/Echo %3d%%";
const char fx25[] PROGMEM = "Tape Echo %3d%%";
const char fx26[] PROGMEM = "CombTapeEcho%3d%%";
const char fx27[] PROGMEM = "Twist Echo %3d%%";
const char fx28[] PROGMEM = "Looper %3d%%";
const char fx29[] PROGMEM = "Pitch Looper%3d%%";
const char fx30[] PROGMEM = "Shuffler %3d%%";
const char fx31[] PROGMEM = "Time Stretch%3d%%";
const char fx32[] PROGMEM = "Time Freeze %3d%%";
const char fx33[] PROGMEM = "SpiralEchoUp%3d%%";
const char fx34[] PROGMEM = "Sp.Echo Down%3d%%";
const char fx35[] PROGMEM = "Res LPF Auto%3d%%";
const char fx36[] PROGMEM = "Res HPF Auto%3d%%";
const char fx37[] PROGMEM = "AutoFilter %3d%%";
const char fx38[] PROGMEM = "Spiral Flang%3d%%";
const char fx39[] PROGMEM = "Pitch Delay %3d%%";
const char fx40[] PROGMEM = "Chiptunes %3d%%";
const char fx41[] PROGMEM = "ShortCircuit%3d%%";
const char fx42[] PROGMEM = "Shifter Lofi%3d%%";
const char fx43[] PROGMEM = "Side Delay %3d%%";
const char fx44[] PROGMEM = "Crush Echo %3d%%";
const char fx45[] PROGMEM = "ParticleDela%3d%%";
const char fx46[] PROGMEM = "Noise Sweep %3d%%";
const char fx47[] PROGMEM = "Noise Synth %3d%%";
const char fx48[] PROGMEM = "Sheppard Fil%3d%%";
const char fx49[] PROGMEM = "UFO %3d%%";
const char fx50[] PROGMEM = "Space Verb %3d%%";
const char fx51[] PROGMEM = "Sp Verb Lift%3d%%";
const char fx52[] PROGMEM = "Sp Verb Drop%3d%%";
const char fx53[] PROGMEM = "Filter Echo %3d%%";
const char fx54[] PROGMEM = "Dub Echo %3d%%";
const char fx55[] PROGMEM = "Filter Gate %3d%%";
const char fx56[] PROGMEM = "Bass Ducker %3d%%";
const char fx57[] PROGMEM = "Noise Pulse %3d%%";
PGM_P const fxtable[] PROGMEM =
{fx01, fx02, fx03, fx04, fx05, fx06, fx07, fx08, fx09, fx10, fx11, fx12, fx13, fx14, fx15, fx16, fx17, fx18, fx19,
fx20, fx21, fx22, fx23, fx24, fx25, fx26, fx27, fx28, fx29, fx30, fx31, fx32, fx33, fx34, fx35, fx36, fx37, fx38,
fx39, fx40, fx41, fx42, fx43, fx44, fx45, fx46, fx47, fx48, fx49, fx50, fx51, fx52, fx53, fx54, fx55, fx56, fx57};
//Command Strings 12 charactere max
const char efx01[] PROGMEM = "Delay %3d%%"; //const char efx03[] PROGMEM = "%4s <%3d>";
//const char efx02[] PROGMEM = "%7s %3d%%"; const char efx04[] PROGMEM = "%3d%% TAP";
const char efx02[] PROGMEM = "Echo %3d%%"; //const char efx07[] PROGMEM = "%4s <%3d>";
//const char efx06[] PROGMEM = "%7s %3d%%"; const char efx08[] PROGMEM = "%3d%% TAP";
const char efx03[] PROGMEM = "Reverb %3d%%"; //const char efx11[] PROGMEM = "%6s <%3d>";
//const char efx10[] PROGMEM = "%7s %3d%%"; const char efx12[] PROGMEM = "%3d%% TAP";
const char efx04[] PROGMEM = "Phaser %3d%%";
const char efx05[] PROGMEM = "Flanger %3d%%";
const char efx06[] PROGMEM = "LPF %3d%%";
const char efx07[] PROGMEM = "HPF %3d%%";
const char efx08[] PROGMEM = "Combo Filter%3d%%";
const char efx09[] PROGMEM = "Distortion %3d%%";
const char efx10[] PROGMEM = "Pan Delay %3d%%";
const char efx11[] PROGMEM = "Epic Reverb %3d%%";
const char efx12[] PROGMEM = "Bit Crush %3d%%";
const char efx13[] PROGMEM = "Tremolo %3d%%";
const char efx14[] PROGMEM = "Repeater %3d%%";
const char efx15[] PROGMEM = "Braker %3d%%";
const char efx16[] PROGMEM = "Brake Echo %3d%%";
const char efx17[] PROGMEM = "Tape Echo %3d%%";
const char efx18[] PROGMEM = "Looper %3d%%";
const char efx19[] PROGMEM = "Time Stretch%3d%%";
const char efx20[] PROGMEM = "SpiralEcho %3d%%";
const char efx21[] PROGMEM = "AutoFilter %3d%%";
const char efx22[] PROGMEM = "Spiral Flang%3d%%";
const char efx23[] PROGMEM = "Pitch Delay %3d%%";
const char efx24[] PROGMEM = "Crush Echo %3d%%";
const char efx25[] PROGMEM = "ParticlDelay%3d%%";
const char efx26[] PROGMEM = "Noise Sweep %3d%%";
const char efx27[] PROGMEM = "Sheppard Fil%3d%%";
const char efx28[] PROGMEM = "Space Verb %3d%%";
const char efx29[] PROGMEM = "Filter Echo %3d%%";
const char efx30[] PROGMEM = "Filter Gate %3d%%";
const char efx31[] PROGMEM = "Noise Pulse %3d%%";
PGM_P const efxtable[] PROGMEM =
{efx01, efx02, efx03, efx04, efx05, efx06, efx07, efx08, efx09, efx10, efx11, efx12, efx13, efx14, efx15, efx16,
efx17, efx18, efx19, efx20, efx21, efx22, efx23, efx24, efx25, efx26, efx27, efx28, efx29, efx30, efx31};
void setup() {
for(int i=0; i<DISPLAYS; i++) {
LCD[i].init();
LCD[i].backlight();
pinMode(PINS[i*2][0] , INPUT_PULLUP);
pinMode(PINS[i*2][1] , INPUT_PULLUP);
pinMode(PINS[i*2+1][0], INPUT_PULLUP);
pinMode(PINS[i*2+1][1], INPUT_PULLUP);
}
pinMode(SwitchMenu, INPUT_PULLUP);
pinMode(LedPin, OUTPUT);
return;
LCD[0].print(F(" SeratoFxduino "));
LCD[0].setCursor(0,1);
LCD[0].print(F(" Midi controler "));
delay(1500);
LCD[0].clear();
LCD[0].setCursor(0,0);
LCD[0].print(F(" Initialisation "));
delay(1000);
LCD[0].clear();
delay(300);
LCD[0].setCursor(0,1);
LCD[0].print(F(" Terminee ! "));
delay(1000);
LCD[0].clear();
}
void loop() {
if (switchState != digitalRead(SwitchMenu)) {
digitalWrite(LedPin, switchState = digitalRead(SwitchMenu));
for(int i=0; i<DISPLAYS; i++) VALUES[i][0] = VALUES[i][1] = -1;
}
switchState == LOW ? update_menu1() : update_menu2();
delay(110);
}
void update_menu1() {
for(int i=0; i<DISPLAYS*2; i++) {
int fxid = VALUES[i][0];
if (fxid == -1 || digitalRead(PINS[i][1]) == LOW) {
if (fxid < 56) fxid++;
} else if (digitalRead(PINS[i][0]) == LOW) {
if (fxid > 0) fxid--;
}
int pot = map(analogRead(PINS[i][2]), 0, 1023, 0, 100);
if (VALUES[i][0] != fxid || VALUES[i][1] != pot) {
strcpy_P(buffer, (char*)pgm_read_ptr(&(fxtable[VALUES[i][0] = fxid])));
snprintf(buffer, 17, buffer, VALUES[i][1] = pot);
LCD[i/2].setCursor(0, i%2);
LCD[i/2].print(buffer);
}
}
}
void update_menu2() {
for(int i=0; i<DISPLAYS/2; i++) {
int fxid = VALUES[i*4][0];
if (fxid == -1 || digitalRead(PINS[i*4][1]) == LOW) {
if (fxid < 30) fxid++;
} else if (digitalRead(PINS[i*4][0]) == LOW) {
if (fxid > 0) fxid--;
}
int pot = map(analogRead(PINS[i*4][2]), 0, 1023, 0, 100);
if (VALUES[i*4][0] != fxid || VALUES[i*4][1] != pot) {
strcpy_P(buffer, (char*)pgm_read_ptr(&(efxtable[VALUES[i*4][0] = fxid])));
snprintf(buffer, 17, buffer, VALUES[i*4][1] = pot);
LCD[i*2].setCursor(0, 0);
LCD[i*2].print(buffer);
VALUES[i*4+1][0] = VALUES[i*4+1][1] = -1;
}
int id_max = 1;
switch(fxid) {
case 14: case 17: id_max = 2; break;
case 11: id_max = 3; break;
case 26: case 28: case 30: id_max = 4; break;
case 3: case 12: case 19: case 20: case 23: case 29: id_max = 5; break;
case 25: id_max = 6; break;
case 24: id_max = 8; break;
case 15: id_max = 9; break;
case 27: id_max = 11; break; }
int id = VALUES[i*4+1][0];
if (id == -1 || digitalRead(PINS[i*4+1][1]) == LOW) {
if (id < id_max) id++;
} else if (digitalRead(PINS[i*4+1][0]) == LOW) {
if (id > 0) id--;
}
pot = map(analogRead(PINS[i*4+1][2]), 0, 1023, 0, 100);
const char *str;
if (VALUES[i*4+1][0] != id || VALUES[i*4+1][1] != pot) {
switch(fxid) {
case 0: case 1: case 9: str = id==0 ? "" : "Reverse"; break;
case 2: case 10: case 16: str = id==0 ? "Wet Mix" : "Send Level"; break;
case 3: str = id==0 ? "0,2" : id==1 ? "0,4" : id==2 ? "0,6" : id==3 ? "1" : id==4 ? "1,4" : "2"; break;
case 4: case 21: str = id==0 ? "Positive" : "Negative"; break;
case 5: case 6: case 7: str = id==0 ? "LFO" : "Resonance"; break;
case 8: str = id==0 ? "Smooth Drive" : "Nasty Boy"; break;
case 11: str = id==0 ? "Low" : id==1 ? "Med" : id==2 ? "High" : "OFF"; break;
case 12: str = id==0 ? "Sine" : id==1 ? "Square" : id==2 ? "Parabole" : id==3 ? "Saw Up" : "Saw Down"; break;
case 13: str = id==0 ? "Loop" : "Shreds"; break;
case 14: str = id==0 ? "Effect On" : id==1 ? "Mix Off Zero" : "Mix to Max"; break;
case 15: str = id==0 ? "10%" : id==1 ? "25%" : id==2 ? "50%" : id==3 ? "75%" : id==4 ? "100%" : id==5 ? "110%" : id==6 ? "125%" : id==7 ? "150%" : id==8 ? "175%" : "200%"; break;
case 17: str = id==0 ? "1/2x - 2x" : id==1 ? "1x - 2x" : "1/4x - 4x"; break;
case 18: str = id==0 ? "Manual Trig" : "Stretch Amnt"; break;
case 19: str = id==0 ? "Hi-Analog" : id==1 ? "Vinyl" : id==2 ? "Warm" : id==3 ? "Neutral" : id==4 ? "Tape" : "Hi-Tape"; break;
case 20: str = id==0 ? "LPF" : id==1 ? "Res LPF" : id==2 ? "HPF" : id==3 ? "Res HPF" : id==4 ? "BPF" : "Res BPF"; break;
case 22: str = id==0 ? "1 8ve Delay" : "Step Shift"; break;
case 23: str = id==0 ? "11 kHz" : id==1 ? "8 kHz" : id==2 ? "4 kHz" : id==3 ? "2 kHz" : id==4 ? "1 kHz" : "44,1 kHz"; break;
case 24: str = id==0 ? "20 ms" : id==1 ? "40 ms" : id==2 ? "80 ms" : id==3 ? "160 ms" : id==4 ? "OFF" : id==5 ? "1,25 ms" : id==6 ? "2,5 ms" : id==7 ? "5 ms" : "10 ms"; break;
case 25: str = id==0 ? "Hp Hi-Q" : id==1 ? "BP" : id==2 ? "LP 24" : id==3 ? "LP 12 Mid-Q" : id==4 ? "LP 12 Hi-Q" : id==5 ? "Vocal" : "HP"; break;
case 26: str = id==0 ? "6 Peak" : id==1 ? "4 Bandpass" : id==2 ? "6 Bandpass" : id==3 ? "4 Phaker" : "6 Phaker"; break;
case 27: str = id==0 ? "Min 9th" : id==1 ? "Maj 9th" : id==2 ? "Min 10th" : id==3 ? "Maj 10th" : id==4 ? "11th" : id==5 ? "Tritone" : id==6 ? "5th" : id==7 ? "Min 6th" : id==8 ? "Maj 6th" : id==9 ? "Min 7th" : id==10 ? "Maj 7th" : "Octave"; break;
case 28: str = id==0 ? "Narrow" : id==1 ? "Normal" : id==2 ? "Wide" : id==3 ? "Full" : "Mono"; break;
case 29: str = id==0 ? "Instant" : id==1 ? "Fast" : id==2 ? "Medium" : id==3 ? "Slow" : id==4 ? "Instant-Hold" : "Instant"; break;
case 30: str = id==0 ? "BP" : id==1 ? "LP" : id==2 ? "LP Hi-Q" : id==3 ? "Vocal" : "HP"; break;
}
VALUES[i*4+1][0] = id;
snprintf(buffer, 17, "%-12s%3d%%", str, VALUES[i*4+1][1] = pot);
LCD[i*2].setCursor(0, 1);
LCD[i*2].print(buffer);
}
}
}
/*
int cmdID = findCommand(Command);
switch( cmdID)
{
case
Delay ; potValue1 Loop(ON-Off) <[Beatvalue]>
Reverse=On/OFF potValue2 potValue3 TAP
default Beatvalue=1
<[Beatvalue]>
TAP
case
Echo ; potValue1 Loop(ON-Off) <[Beatvalue]>
Reverse=On/OFF potValue2 potValue3 TAP
default Beatvalue=1
<[Beatvalue]>
TAP
case
Reverb ; potValue1 Width(VAL1) <[Beatvalue]>
MixMode(VAL1) potValue2 potValue3 TAP
MixMode(VAL1)= Wet Mix ou Send
Width(VAL1)= Normal; Wide; Narrow
default Beatvalue=1
<[Beatvalue]>
TAP
case
Phaser ; potValue1 Filter(VAL1) <[Beatvalue]>
Q Factor(VAL1) potValue2 potValue3 TAP
Q Factor(VAL1)= 0,2; 0,4; 0,6; 1; 1,4; 2
Filter(VAL1)= 1 Stages; 3 Stages; 5 Stages; 7 Stages; 11 Stages
default Beatvalue=4
<[Beatvalue]>
TAP
case
Flanger ; potValue1 Waveform(VAL1) <[Beatvalue]>
Feedback(VAL1) potValue2 potValue3 TAP
Feedback(VAL1)= Positive; Negative
Waveform(VAL1)= Parabole; Saw Up; Saw Down; Sine; Square; Triangle
default Beatvalue=4
<[Beatvalue]>
TAP
case
LPF ; potValue1 Waveform(VAL1) <[Beatvalue]>
LFO=On/Resonance=OFF potValue2 potValue3 TAP
Waveform(VAL1)= Sine; Square; Triangle; Parabole; Saw Up; Saw Down
default Beatvalue=2
<[Beatvalue]>
TAP
case
HPF ; potValue1 Waveform(VAL1) <[Beatvalue]>
LFO=On/Resonance=OFF potValue2 potValue3 TAP
Waveform(VAL1)= Sine; Square; Triangle; Parabole; Saw Up; Saw Down
default Beatvalue=2
<[Beatvalue]>
TAP
case
Combo Filter; potValue1 Noise Injector(ON-Off) <[Beatvalue]>
LFO=On/Resonance=OFF potValue2 potValue3 TAP
default Beatvalue=4
<[Beatvalue]>
TAP
case
Distortion ; potValue1 Bass Bypass(ON-Off) <[Beatvalue]>
Type(VAL1) potValue2 potValue3 TAP
Type(VAL1)= Smooth Drive; Nasty Boy
default Beatvalue=1
<[Beatvalue]>
TAP
case
Pan Delay ; potValue1 Loop(ON-Off) <[Beatvalue]>
Reverse=On/OFF potValue2 potValue3 TAP
default Beatvalue=1
<[Beatvalue]>
TAP
case
Epic Reverb ; potValue1 Width(VAL1) <[Beatvalue]>
MixMode(VAL1) potValue2 potValue3 TAP
VMixMode(VAL1)= Wet Mix ou Send
Width(VAL1)= Normal; Wide; Narrow
default Beatvalue=1
<[Beatvalue]>
TAP
case
Bit Crush ; potValue1 Character(VAL1) <[Beatvalue]>
Low Drive(VAL1) potValue2 potValue3 TAP
Low Drive(VAL1)= Low; Med; High; OFF
Character(VAL1)= Some; More; Most; Epic; None
default Beatvalue=1
<[Beatvalue]>
TAP
case
Tremolo ; potValue1 Noise_Injector(VAL1) <[Beatvalue]>
Waveform(VAL1) potValue2 potValue3 TAP
Waveform(VAL1)= Sine; Square; Triangle; Parabole; Saw Up; Saw Down
Noise_Injector(VAL1)= Small; Medium; Large; Epic; OFF
default Beatvalue=1/4
<[Beatvalue]>
TAP
case
Repeater ; potValue1 Donain(VAL1) <[Beatvalue]>
Loop=On/Shreds=OFF potValue2 potValue3 TAP
Donain(VAL1)= 1 Beat; 4 Beats;
default Beatvalue=4
<[Beatvalue]>
TAP
case
Braker ; potValue1 Spinback(VAL1) <[Beatvalue]>
Trigger(VAL1) potValue2 potValue3 TAP
Trigger(VAL1)= Effect On; Mix Off Zero; Mix to Max
Spinback(VAL1)= Off Max; Follow Brake; None
default Beatvalue=1
<[Beatvalue]>
TAP
case
Brake Echo ; potValue1 Mode(VAL1) <[Beatvalue]>
Rollout Time(VAL1) potValue2 potValue3 TAP
Rollout Time(VAL1)= 10%; 25%; 50%; 75%; 100%; 110%; 125%; 150%; 175%; 200%
Mode(VAL1)= Brake; Fade; Re-Brake; Re-Fade
default Beatvalue=1
<[Beatvalue]>
TAP
case
Tape Echo ; potValue1 Drive(VAL1) <[Beatvalue]>
MixMode(VAL1) potValue2 potValue3 TAP
MixMode(VAL1)= Wet Mix; Send Level
Drive(VAL1)= Light; Medium; Heavy; None
default Beatvalue=1
<[Beatvalue]>
TAP
case
Looper ; potValue1 Mode(VAL2) <[Beatvalue]>
Range(VAL1) potValue2 potValue3 TAP
Range(VAL1)= 1/2x - 2x; 1x - 2x; 1/4x - 4x
Mode(VAL2)= Varispeed; Pitch; Time
default Beatvalue=4
<[Beatvalue]>
TAP
case
Time Stretch; potValue1 Gain Size(VAL1) <[Beatvalue]>
(ValOn/OFF) potValue2 potValue3 TAP
(ValOn/OFF)= On=Manual Trigger , OFF=Stretch Amount ;
Gain Size(VAL1)= Long; Loose; Tripping; Tight; Short; Medium
default Beatvalue=4
<[Beatvalue]>
TAP
case
Spiral Echo; potValue1 Inertia(VAL1) <[Beatvalue]>
Character(VAL2) potValue2 potValue3 TAP
Character(VAL2)= Hi-Analog; Vinyl; Warm; Neutral; Tape; Hi-Tape
Inertia(VAL1)= Fast; Slow; Medium
default Beatvalue=1/2
<[Beatvalue]>
TAP
case
Auto Filter; potValue1 Attack(VAL1) <[Beatvalue]>
Mode(VAL3) potValue2 potValue3 TAP
Mode(VAL3)= LPF; Res LPF; HPF; Res HPF; BPF; Res BPF
Attack(VAL1)= Fast; Medium; Slow; Fast-Hold; Fast
default Beatvalue=1
<[Beatvalue]>
TAP
case
SpiralFlange; potValue1 Spread(VAL1) <[Beatvalue]>
Feedback(VAL1) potValue2 potValue3 TAP
Feedback(VAL1)= Positive; Negative
Spread(VAL1)= Medium; Wide; Mono
default Beatvalue=1
<[Beatvalue]>
TAP
case
Pitch Delay; potValue1 Width(VAL1) <[Beatvalue]>
Mode(VAL4) potValue2 potValue3 TAP
Mode(VAL4)= 1 8ve Delay; Step Shift
Width(VAL1)= Normal; Wide; Narrow
default Beatvalue=1
<[Beatvalue]>
TAP
case
Crush Echo ; potValue1 Bit Depth(VAL1) <[Beatvalue]>
Downsample(VAL1) potValue2 potValue3 TAP
Downsample(VAL1)= 11 kHz; 8 kHz; 4 kHz; 2 kHz; 1kHz; 44,1 kHz
Bit Depth(VAL1)= 8 Bit; 7 Bit; 6 Bit; 5 Bit; 4 Bit; 16 Bit
default Beatvalue=1
<[Beatvalue]>
TAP
case
ParticlDelay; potValue1 With(VAL2) <[Beatvalue]>
Spray(VAL1) potValue2 potValue3 TAP
Spray(VAL1)= 20 ms; 40 ms; 80 ms; 160 ms; OFF; 1,25 ms; 2,5 ms; 5 ms; 10 ms
With(VAL2)= 40%; 60%; 80%; 100%; 0%; 20%
default Beatvalue=1/2D
<[Beatvalue]>
TAP
case
Noise Sweep ; potValue1 Auto(VAL1) <[Beatvalue]>
Character(VAL3) potValue2 potValue3 TAP
Character(VAL3)= Hp Hi-Q; BP; LP 24; LP 12 Mid-Q;LP 12 Hi-Q; Vocal; HP
Auto(VAL1)= None; Up; Up-Down; Down; Down-Up
default Beatvalue=1
<[Beatvalue]>
TAP
case
SheppardFilt; potValue1 Direction(VAL1) <[Beatvalue]>
Type(VAL2) potValue2 potValue3 TAP
Type(VAL2)= 6 Peak; 4 Bandpass; 6 Bandpass; 4 Phaker; 6 Phaker
Direction(VAL1)= Up; Down
default Beatvalue=8
<[Beatvalue]>
TAP
case
Space Verb ; potValue1 Resonance(VAL1) <[Beatvalue]>
Type(VAL3) potValue2 potValue3 TAP
Type(VAL3)= Min 9th; Maj 9th; Min 10th; Maj 10th; 11th; Tritone; 5th; Min 6th; Maj 6th; Min 7th; Maj 7th; Octave
Resonance(VAL1)= High; OFF; Low; Medium; High; OFF
default Beatvalue=1
<[Beatvalue]>
TAP
case
Filter Echo ; potValue1 Filter_Mode(VAL1) <[Beatvalue]>
Spreed(VAL2) potValue2 potValue3 TAP
Spreed(VAL2)= Narrow; Normal; Wide; Full; Mono
Filter_Mode(VAL1)= Tight; Agressive; Regular
default Beatvalue=1
<[Beatvalue]>
TAP
page30
Filter Gate ; potValue1 Attack(VAL2) <[Beatvalue]>
Mode(VAL5) potValue2 potValue3 TAP
Mode(VAL5)= HPF; HPF Hi-Q: BPF; BRF; LPF; LPF Hi-Q
Attack(VAL2)= Instant; Fast; Medium; Slow;Instant-Hold; Instant
default Beatvalue=1
<[Beatvalue]>
TAP
case
Noise Pulse ; potValue1 Shape(VAL2) <[Beatvalue]>
Character (VAL4) potValue2 potValue3 TAP
Character (VAL4)= BP; LP; LP Hi-Q; Vocal; HP
Shape(VAL2)= Flat; Curve Atk; Curve Rel; Curved
default Beatvalue=1
<[Beatvalue]>
TAP
exemple
// 1 = output debug to serial port, 0 = no debug
#define debug 1
// define the buffer size...
#define serialbufferSize 50
#define commandDelimeters "|,. " // '-' removed as it is needed as a value leader
#define progMemBuffer 128
// Define some Digital pins
// Dont use the PWM capable ones
#define D0 0
#define D1 1
#define D2 2
#define D3 4
#define D4 7
#define D5 8
#define D6 12
#define D7 13
// define the PWM Pins
#define PWM0 3
#define PWM1 5
#define PWM2 6
#define PWM3 9
#define PWM4 10
#define PWM5 11
#define MAXPWM 255
#define MINPWM 0
#define analogToVolts 5/1023 // Volts per step in ADC
// End of Constants
// Now the real varibles
char inputBuffer[serialbufferSize] ;
int serialIndex = 0; // keep track of where we are in the buffer
// End of real variables
// Strings to be stored into Program space
//enumeration to make accessing the strings easier
enum {welcomeText0, welcomeText1, welcomeText2, webText0, webText1, webText2, errorText, helloReply,
goodbyReply, dosomethingReply, invalidValue
#if debug
, isnumericParam, notNumericParam
#endif
};
//welcome text
const char welcomeTxt_0[] PROGMEM = "Hello, please ask me something\ntype \"Hello\", \"Goodby\", \"web\" or \"dosomething\"\n";
const char PROGMEM welcomeTxt_1[] = "or \"pwmx where x is from 0 to 5\"\nor \"analogx where x is from 0 to 5\"\n";
const char PROGMEM welcomeTxt_2[] = "or \"digitalx where x is from 0 to 7\"\nor make up your own command\n";
// end of welcome text
const char PROGMEM webTxt_0[] = "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: close\n";
const char PROGMEM webTxt_1[] = "<!DOCTYPE html><html><head><title>Hello from www.thebreadboard.ca</title></head><body>";
const char PROGMEM webTxt_2[] = "</body></html>\n";
// error text
const char PROGMEM errorTxt_0[] = "I dont understand you \nYou said: ";
const char PROGMEM helloRepTxt_0[] = "Hello back at you ";
const char PROGMEM goodbyRepTxt_0[] = "Goodby back at you ";
const char PROGMEM dosomethingRepTxt_0[] = "what would you like me to do?";
const char PROGMEM invalidValueRepTxt_0[] = "Invalid Value, setting unchanged";
#if debug // yes you can even use compiler directives here
const char PROGMEM paramIsNumeric_0[] = "Remaining Param is numeric and = ";
const char PROGMEM paramIsNotNumeric_0[] = "Remaining Param is not numeric or invalid, value = ";
#endif
//array of pointers to the above message strings
const char* const Txt_table[] PROGMEM =
{welcomeTxt_0, welcomeTxt_1, welcomeTxt_2, webTxt_0, webTxt_1, webTxt_2, errorTxt_0,
helloRepTxt_0,goodbyRepTxt_0,dosomethingRepTxt_0, invalidValueRepTxt_0,
#if debug // yes you can even use compiler directives here
paramIsNumeric_0,paramIsNotNumeric_0
#endif
};
//enumeration to make accessing the command strings easier
enum {hello, goodby, dosomething, web1, web2, web3, web4, web5, analog0, analog1, analog2
, analog3, analog4, analog5, digital0, digital1, digital2, digital3, digital4
, digital5, digital6, digital7, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5};
//Command Strings
const char PROGMEM helloCmd[] = "Hello";
const char PROGMEM goodbyCmd[] = "Goodby";
const char PROGMEM dosomethingCmd[] = "dosomething";
const char PROGMEM web1Cmd[] = "web1";
const char PROGMEM web2Cmd[] = "web2";
const char PROGMEM web3Cmd[] = "web3";
const char PROGMEM web4Cmd[] = "web4";
const char PROGMEM web5Cmd[] = "web5";
const char PROGMEM analog0Cmd[] = "analog0";
const char PROGMEM analog1Cmd[] = "analog1";
const char PROGMEM analog2Cmd[] = "analog2";
const char PROGMEM analog3Cmd[] = "analog3";
const char PROGMEM analog4Cmd[] = "analog4";
const char PROGMEM analog5Cmd[] = "analog5";
const char PROGMEM digital0Cmd[] = "digital0";
const char PROGMEM digital1Cmd[] = "digital1";
const char PROGMEM digital2Cmd[] = "digital2";
const char PROGMEM digital3Cmd[] = "digital3";
const char PROGMEM digital4Cmd[] = "digital4";
const char PROGMEM digital5Cmd[] = "digital5";
const char PROGMEM digital6Cmd[] = "digital6";
const char PROGMEM digital7Cmd[] = "digital7";
const char PROGMEM pwm0Cmd[] = "pwm0";
const char PROGMEM pwm1Cmd[] = "pwm1";
const char PROGMEM pwm2Cmd[] = "pwm2";
const char PROGMEM pwm3Cmd[] = "pwm3";
const char PROGMEM pwm4Cmd[] = "pwm4";
const char PROGMEM pwm5Cmd[] = "pwm5";
//array of pointers to the above command strings
const char* const Cmd_table[] PROGMEM =
{helloCmd,goodbyCmd,dosomethingCmd,web1Cmd,web2Cmd,web3Cmd,web4Cmd,web5Cmd,
analog0Cmd,analog1Cmd,analog2Cmd,analog3Cmd,analog4Cmd,analog5Cmd,
digital0Cmd,digital1Cmd,digital2Cmd,digital3Cmd,digital4Cmd,digital5Cmd,digital6Cmd,digital7Cmd,
pwm0Cmd,pwm1Cmd,pwm2Cmd,pwm3Cmd,pwm4Cmd,pwm5Cmd};
int cmdCount = sizeof(Cmd_table) / sizeof(Cmd_table[0]);
// Function that finds the string in prog mem arrays and gets it into usable space
char buffer[progMemBuffer];
char* getStringfromProgMem(const char* const Table[], int i)
{
strcpy_P(buffer, (char*)pgm_read_word(&(Table[i])));
return buffer;
};
// Search through the comands untill we find one or run out
int findCommand(char* searchText)
{
int startCount = 0;
int foundIndex = -1; // -1 = not found
while (startCount < cmdCount)
{
if(strcmp(searchText,getStringfromProgMem(Cmd_table,startCount))==0)
{
foundIndex = startCount;
break;
}
startCount++;
}
return foundIndex;
}
void setup()
{
// initialise all the digital outputs
pinMode(D0, OUTPUT);
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
pinMode(D3, OUTPUT);
pinMode(D4, OUTPUT);
pinMode(D5, OUTPUT);
pinMode(D6, OUTPUT);
pinMode(D7, OUTPUT);
// initialise all the PWM outputs
pinMode(PWM0, OUTPUT);
pinMode(PWM1, OUTPUT);
pinMode(PWM2, OUTPUT);
pinMode(PWM3, OUTPUT);
pinMode(PWM4, OUTPUT);
pinMode(PWM5, OUTPUT);
// initialize serial:
Serial.begin(9600);
delay(200);
// do other setup here as needed
// Print some pretty instructions
Serial.print(getStringfromProgMem(Txt_table,welcomeText0));
Serial.print(getStringfromProgMem(Txt_table,welcomeText1));
Serial.print(getStringfromProgMem(Txt_table,welcomeText2));
}
void loop()
{
// Notice how the main loop is very simple and the functions
// seperate the logic into easily manageable parts
if (CheckSerial()) DoCommand(inputBuffer);
// Do other stuff
}
// Enhanced Command Processor using strtok to strip out command from multi parameter string
boolean DoCommand(char * commandBuffer)
{
char* Command; // Command Parameter
char* Parameter; // Additional Parameter
int analogVal = 0; // additional parameter converted to analog if possible
// Get the command from the input string
Command = strtok(commandBuffer,commandDelimeters); // get the command
Parameter = strtok(NULL, commandDelimeters); // get the parameter if any
//if there are more than one parameter they will be ignored for now
// Make sure we have an analog value if we are to allow PWM output
int outparameter = isNumeric (Parameter);
//if it is a number then convert it
if (outparameter)
{
analogVal = atoi(Parameter);
}
// Switch / Case way to handle commands
int cmdID = findCommand(Command);
switch( cmdID)
{
case hello : Serial.println(getStringfromProgMem(Txt_table,helloReply));break;
case goodby : Serial.println(getStringfromProgMem(Txt_table,goodbyReply)); break;
case dosomething : Serial.println(getStringfromProgMem(Txt_table,dosomethingReply)); break;
case web1 : processWebCmd("<H1>Test1</H1>");break;
case web2 : processWebCmd("<H1>Test2</H1>");break;
case web3 : processWebCmd("<H1>Test3</H1>");break;
case web4 : processWebCmd("<H1>Test4</H1>");break;
case web5 : processWebCmd("<H1>Test5</H1>");break;
case analog0 : getAnalog(A0); break;
case analog1 : getAnalog(A1); break;
case analog2 : getAnalog(A2); break;
case analog3 : getAnalog(A3); break;
case analog4 : getAnalog(A4); break;
case analog5 : getAnalog(A5); break;
case digital0 : getsetDigital(D0, analogVal);break;
case digital1 : getsetDigital(D1, analogVal);break;
case digital2 : getsetDigital(D2, analogVal);break;
case digital3 : getsetDigital(D3, analogVal);break;
case digital4 : getsetDigital(D4, analogVal);break;
case digital5 : getsetDigital(D5, analogVal);break;
case digital6 : getsetDigital(D6, analogVal);break;
case digital7 : getsetDigital(D7, analogVal);break;
case pwm0 : setPWM(PWM0, analogVal, outparameter);break;
case pwm1 : setPWM(PWM1, analogVal, outparameter);break;
case pwm2 : setPWM(PWM2, analogVal, outparameter);break;
case pwm3 : setPWM(PWM3, analogVal, outparameter);break;
case pwm4 : setPWM(PWM4, analogVal, outparameter);break;
case pwm5 : setPWM(PWM5, analogVal, outparameter);break;
default : {
Serial.print(getStringfromProgMem(Txt_table,errorText));
Serial.println(commandBuffer);
break;
}
}
// debug code after here
#if debug
if (Parameter != '\0'){
Serial.print((outparameter)? getStringfromProgMem(Txt_table,isnumericParam) : getStringfromProgMem(Txt_table,notNumericParam) );
Serial.println(Parameter);
}
Serial.print("Free Ram = "); Serial.println(freeRam(), DEC);
#endif
return true;
}
//
Checks the serial input for a string, returns true once a '\n' is seen
users can always look at the global variable "serialIndex" to see if characters have been received already
//
boolean CheckSerial()
{
boolean lineFound = false;
// if there's any serial available, read it:
while (Serial.available() > 0) {
//Read a character as it comes in:
//currently this will throw away anything after the buffer is full or the \n is detected
char charBuffer = Serial.read();
if (charBuffer == '\n') {
inputBuffer[serialIndex] = 0; // terminate the string
lineFound = (serialIndex > 0); // only good if we sent more than an empty line
serialIndex=0; // reset for next line of data
}
else if(charBuffer == '\r') {
// Just ignore the Carrage return, were only interested in new line
}
else if(serialIndex < serialbufferSize && lineFound == false) {
//Place the character in the string buffer://
inputBuffer[serialIndex++] = charBuffer; // auto increment index
}
}// End of While
return lineFound;
}// End of CheckSerial()
// check to see if value is nomeric.. only dealing with signed integers
int isNumeric (const char * s)
{
if (s == NULL || *s == '\0' || isspace(*s)) return 0; // extra protection
if (*s == '-' || *s == '+') s++; // allow a + or - in the first char space
while(*s)
{
if(!isdigit(*s))
return 0;
s++;
}
return 1;
}
// end of check is numeric
#if debug
// check free ram
int freeRam ()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
#endif
// output to PWM Channels
void setPWM(int pin, int value, int IsValid)
{
// check the analog value is in the correct range if not then make isvalid false
if (((value < MINPWM )|| (value > MAXPWM)) && IsValid) IsValid = false;
Serial.print("pwm "); Serial.print(pin); Serial.print(" = ");
Serial.println(value); // read the input pin "A1" is already defined
// dont change value if invalid
if(IsValid) analogWrite(pin, value); else Serial.println(getStringfromProgMem(Txt_table,invalidValue));
}
// get analog Channels
void getAnalog(int pin)
{
int readValue = analogRead(pin);
Serial.print("Analog "); Serial.print(pin); Serial.print(" = ");
Serial.print(readValue); // read the input pin "Ax" is already defined
Serial.print(" Volts = ");
Serial.println(double(readValue)*analogToVolts); // read the input pin "Ax"
}
// get Digital Channels
void getsetDigital(int pin, int value)
{
Serial.print("Digital "); Serial.print(pin); Serial.print(" was = "); Serial.println(digitalRead(pin));
if(value == -1)digitalWrite(pin, !digitalRead(pin)); // invert value
else if(value == 0)digitalWrite(pin, LOW); // set value low
else if(value == 1)digitalWrite(pin, HIGH); // set value high
else Serial.println(getStringfromProgMem(Txt_table,invalidValue));
}
// get Digital Channels
void processWebCmd(char* webText)
{
Serial.print(getStringfromProgMem(Txt_table,webText0));
Serial.print(getStringfromProgMem(Txt_table,webText1));
Serial.print(webText);
Serial.print(getStringfromProgMem(Txt_table,webText2));
}
*/