/*
* Arduino Ribbon Synth MIDI controller
* ------------------------------------
* ©2014 Dean Miller
* ©2016-2018 Simon Iten many additions, 4 strings, 24 frets, fsr, channelmode,
* midi message thinning, usb and din midi etc..
*/
#pragma GCC optimize ("-O3")
#include <EEPROM.h>
#include <Arduino.h>
#include <U8x8lib.h>
#include <MIDI.h> // access to serial (5 pin DIN) MIDI
#include <USBHost_t36.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#include <Wire.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE, /* clock=*/ 7, /* data=*/ 8);
// Create the ports for USB devices plugged into Teensy's 2nd USB port (via hubs)
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);
MIDIDevice_BigBuffer midi01(myusb);
MIDIDevice_BigBuffer midi02(myusb);
MIDIDevice_BigBuffer midi03(myusb);
MIDIDevice_BigBuffer midi04(myusb);
MIDIDevice_BigBuffer midi05(myusb);
MIDIDevice_BigBuffer midi06(myusb);
MIDIDevice_BigBuffer midi07(myusb);
MIDIDevice_BigBuffer * midilist[07] = {
&midi01, &midi02, &midi03, &midi04, &midi05, &midi06, &midi07
};
//------- Constants -------//
#define PIN_LED 13
// the 4 strings softpots
#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
#define PIN_SOFTPOT_4 A3
//the 4 fsrs under the strings
#define PIN_STRINGFSR_1 A16
#define PIN_STRINGFSR_2 A17
#define PIN_STRINGFSR_3 A18
#define PIN_STRINGFSR_4 A19
//the 4 fsr's
#define PIN_FSR_1 A4
#define PIN_FSR_2 A5
#define PIN_FSR_3 A6
#define PIN_FSR_4 A7
#define PIN_FSR_5 A22
#define PIN_FSR_FOOT 29 //replace with midi fulllegato tapping command
#define PIN_BUTTON_CHANNEL 28
#define PIN_BUTTON_PANIC 27
#define PIN_OCTAVE_UP 24
#define PIN_OCTAVE_DOWN 25
#define PIN_BUTTON_FSR 26
//joystick
#define PIN_JOYSTICK_X A14
#define PIN_JOYSTICK_Y A15
//accelerometer
#define PIN_ACCEL_X A9
#define PIN_ACCEL_Y A10
#define PIN_ACCEL_Z A11
//hothand
#define PIN_HOTHAND_X A13
#define PIN_HOTHAND_Y A12
//lfo wheel
#define PIN_WHEEL A21
//arp softpot and fsr
#define PIN_ARP_SOFTPOT A8
#define PIN_ARP_FSR A20
#define UP 0
#define DOWN 1
#define FULLLEGATO 2
#define NUM_STRINGS 4
//resistance to change note when finger position not precise...
#define PADDING 2
#define MAXREADING 1300
#define MINVELOCITY 60
//where does the channelmode start, default mode starts on channel 2 general modulation happens on channel one (kind of mpe))
#define CHANNEL_OFFSET 4
//how long before a note stays on when you release the fsr in non-bowmode
#define ATTACK 1000
#define ATTACK_LEGATO 1000
//which cc numbers are used to save settings and change the modes via midi.
#define SAVE_CC 115
#define CHANNELMODE_CC 119
#define FULLLEGATO_CC 118
#define OCTAVE_CC 117
#define FSR_SLAVE_CC 116
#define ALLMUTE_CC 123
#define BOWMODE_CC 114
#define DUMMY_CC 113
//lowest open string to calculate midi note values on the neck
#define LOWEST_NOTE 4
// corrects false note splutter when softpot is released
#define STABLETIME 14
//buttonpresstime (detect multiple presses, debounce)
#define BUTTONPRESS 1000
//thin out cc messages
#define CONTROL_RATE 15
//thin out aftertouch messages
#define AFTERTOUCH_RATE 15
//------ Global Variables ---------//
/*
fret defs stored in EEPROM for calibration purposes.
Lower output voltages from USB ports result in different values read from
SoftPots and wonky fret definitions.
*/
byte fret_Defs[4][25];
byte map_fsr_string[] = {
127,126,125,124,124,123,122,121,120,119,118,118,117,116,115,114,114,113,112,111,110,110,109,108,107,107,106,105,104,104,103,102,102,101,100,100,99,98,97,97,96,95,95,94,93,93,92,92,91,90,
90,89,88,88,87,87,86,85,85,84,84,83,82,82,81,81,80,80,79,79,78,77,77,76,76,75,75,74,74,73,73,72,72,71,71,70,70,69,69,68,68,67,67,66,66,66,65,65,64,64,
63,63,62,62,62,61,61,60,60,59,59,59,58,58,57,57,57,56,56,55,55,55,54,54,54,53,53,52,52,52,51,51,51,50,50,50,49,49,49,48,48,48,47,47,47,46,46,46,45,45,
45,44,44,44,43,43,43,43,42,42,42,41,41,41,41,40,40,40,39,39,39,39,38,38,38,38,37,37,37,37,36,36,36,36,35,35,35,35,34,34,34,34,33,33,33,33,32,32,32,32,
32,31,31,31,31,30,30,30,30,30,29,29,29,29,29,28,28,28,28,28,27,27,27,27,27,26,26,26,26,26,26,25,25,25,25,25,25,24,24,24,24,24,24,23,23,23,23,23,23,22,
22,22,22,22,22,22,21,21,21,21,21,21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,18,18,18,18,18,18,18,18,17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,
16,16,15,15,15,15,15,15,15,15,15,15,14,14,14,14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,11,
11,11,11,11,11,11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,
};
byte map_fsr[] = {
127,126,126,125,124,124,123,123,122,121,121,120,120,119,118,118,117,117,116,116,115,114,114,113,113,112,112,111,110,110,109,109,108,108,107,107,106,106,105,105,104,104,103,103,102,102,101,101,100,100,
99,99,98,98,97,97,96,96,95,95,94,94,93,93,92,92,91,91,91,90,90,89,89,88,88,87,87,87,86,86,85,85,84,84,84,83,83,82,82,82,81,81,80,80,80,79,79,78,78,78,
77,77,76,76,76,75,75,75,74,74,73,73,73,72,72,72,71,71,71,70,70,70,69,69,69,68,68,68,67,67,67,66,66,66,65,65,65,64,64,64,63,63,63,62,62,62,61,61,61,61,
60,60,60,59,59,59,58,58,58,58,57,57,57,56,56,56,56,55,55,55,55,54,54,54,53,53,53,53,52,52,52,52,51,51,51,51,50,50,50,50,49,49,49,49,48,48,48,48,47,47,
47,47,46,46,46,46,46,45,45,45,45,44,44,44,44,44,43,43,43,43,43,42,42,42,42,41,41,41,41,41,40,40,40,40,40,39,39,39,39,39,38,38,38,38,38,38,37,37,37,37,
37,36,36,36,36,36,36,35,35,35,35,35,34,34,34,34,34,34,33,33,33,33,33,33,32,32,32,32,32,32,32,31,31,31,31,31,31,30,30,30,30,30,30,30,29,29,29,29,29,29,
29,28,28,28,28,28,28,28,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,25,25,25,25,25,25,25,25,24,24,24,24,24,24,24,24,24,23,23,23,23,23,23,23,23,22,22,
22,22,22,22,22,22,22,22,21,21,21,21,21,21,21,21,21,20,20,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,19,19,19,19,18,18,18,18,18,18,18,18,18,18,18,17,
17,17,17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,14,
14,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,
};
byte map_hothand[] = {
0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,8,9,
9,9,9,9,9,10,10,10,11,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
48,49,50,51,52,53,53,54,55,56,57,58,58,59,59,60,60,61,61,62,62,63,63,64,64,65,65,66,66,67,67,68,68,69,69,70,70,71,71,72,72,73,73,74,74,75,75,76,76,77,77,
78,78,79,79,80,80,81,81,82,82,83,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,90,91,91,91,92,92,92,93,93,93,94,94,94,95,95,95,96,96,
96,97,97,97,98,98,98,99,99,99,100,100,100,100,101,101,101,101,102,102,102,102,103,103,103,103,104,104,104,104,105,105,105,105,106,106,106,106,107,107,
107,107,108,108,108,108,109,109,109,110,110,110,111,111,112,112,112,112,112,113,113,113,113,114,114,114,114,114,114,115,115,115,115,
115,115,116,116,116,116,116,116,117,117,117,117,117,117,118,118,118,118,118,118,119,119,119,119,119,119,119,120,
120,120,120,121,122,123,124,
124,124,125,126,126,127 };
/*
byte map_wheel[] {
0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,3,3,
3,3,4,4,4,4,5,5,5,6,6,6,7,7,7,8,8,9,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,21,21,22,22,23,24,24,25,26,
26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,36,37,38,39,39,40,41,42,42,43,44,45,45,46,47,48,48,49,50,51,52,52,53,54,55,56,56,57,58,59,60,60,61,62,63,64,64,65,66,67,67,68,69,70,71,71,72,73,74,75,75,76,77,78,79,79,80,81,82,82,83,84,85,85,86,87,88,88,89,90,91,91,92,93,93,94,95,95,96,97,98,98,99,100,100,
101,101,102,103,103,104,105,105,106,106,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,118,119,119,120,120,120,121,121,121,122,122,122,123,123,123,123,124,
124,124,124,125,125,125,125,125,126,126,126,126,126,126,126,126,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,126,126,126,126,126,126,126,126,125,125,125,125,125,124,124,
124,124,123,123,123,123,122,122,122,121,121,121,120,120,120,119,119,118,118,118,117,117,116,116,115,115,114,114,113,113,112,112,111,111,110,110,109,109,108,108,107,106,106,105,105,104,103,103,102,101,
101,100,100,99,98,98,97,96,95,95,94,93,93,92,91,91,90,89,88,88,87,86,85,85,84,83,82,82,81,80,79,79,78,77,76,75,75,74,73,72,71,71,70,69,68,67,67,66,65,64,
64,63,62,61,60,60,59,58,57,56,56,55,54,53,52,52,51,50,49,48,48,47,46,45,45,44,43,42,42,41,40,39,39,38,37,36,36,35,34,34,33,32,32,31,30,29,29,28,27,27,
26,26,25,24,24,23,22,22,21,21,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,11,11,10,10,9,9,9,8,8,7,7,7,6,6,6,5,5,5,4,4,4,4,3,
3,3,3,2,2,2,2,2,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
}; */
byte map_wheel[] {
0,3,5,7,10,12,14,17,
19,21,23,25,27,29,31,33,
35,37,38,40,42,44,45,47,
48,50,51,53,54,56,57,59,
60,61,63,64,65,66,68,69,
70,71,72,73,74,75,76,77,
78,79,80,81,82,83,84,85,
86,86,87,88,89,90,90,91,
92,92,93,94,94,95,96,96,
97,98,98,99,99,100,100,101,
101,102,102,103,103,104,104,105,
105,106,106,106,107,107,108,108,
108,109,109,109,110,110,110,111,
111,111,112,112,112,113,113,113,
113,114,114,114,115,115,115,115,
115,116,116,116,116,117,117,117,
117,117,118,118,118,118,118,118,
119,119,119,119,119,119,120,120,
120,120,120,120,120,121,121,121,121,121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,123,123,123,123,123,123,123,123,
123,123,123,123,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,
125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
126,126,126,126,126,126,126,126,126,126,126,127,127,127,127,127,127,127,127,127,126,126,126,126,126,126,126,126,125,125,125,125,125,124,124,
124,124,123,123,123,123,122,122,122,121,121,121,120,120,120,119,119,118,118,118,117,117,116,116,115,115,114,114,113,113,112,112,111,111,110,110,109,109,108,108,107,106,106,105,105,104,103,103,102,101,
101,100,100,99,98,98,97,96,95,95,94,93,93,92,91,91,90,89,88,88,87,86,85,85,84,83,82,82,81,80,79,79,78,77,76,75,75,74,73,72,71,71,70,69,68,67,67,66,65,64,
64,63,62,61,60,60,59,58,57,56,56,55,54,53,52,52,51,50,49,48,48,47,46,45,45,44,43,42,42,41,40,39,39,38,37,36,36,35,34,34,33,32,32,31,30,29,29,28,27,27,
26,26,25,24,24,23,22,22,21,21,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,11,11,10,10,9,9,9,8,8,7,7,7,6,6,6,5,5,5,4,4,4,4,3,
3,3,3,2,2,2,2,2,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
};
byte fsr_Touched[] = {false, false, false, false};
byte active_Note[] = {0,0,0,0};
byte arp_Note[] = {0,0,0,0};
//byte active_Velo[] = {0,0,0,0};
unsigned int fsr_Vals[] = {0, 0, 0, 0};
byte fsr_Read_Old[] = {0, 0, 0, 0};
byte fsr_Pins[] = {PIN_FSR_1, PIN_FSR_2, PIN_FSR_3, PIN_FSR_4};
unsigned int fsr_Init[] = {0, 0, 0, 0};
unsigned int soft_Pot_Vals[4];
unsigned int string_Fsr_Vals[4];
unsigned int string_Fsr_Old[4];
unsigned int string_Fsr_Init[4];
byte soft_Pot_Pins[] = {PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3, PIN_SOFTPOT_4};
byte string_Fsr_Pins[] = {PIN_STRINGFSR_1,PIN_STRINGFSR_2, PIN_STRINGFSR_3, PIN_STRINGFSR_4};
bool string_fsr_active[] = {false, false, false, false};
byte soft_Pot_Vals_Old[] = {0, 0, 0, 0};
byte fret_Touched[4];
byte maybe_Note[] {0,0,0,0};
byte stable_Count[] = {0,0,0,0};
byte note_Fretted[4];
byte string_Active[] = {false, false, false, false};
//debug to print to serial every 2 seconds
elapsedMillis debugsession;
elapsedMillis hothand_on;
//unsigned int calibration_Max[] = {630, 630, 630, 630};
unsigned int calibration_Min[4];
//octave offset
byte octave = 2;
//default offsets for the 4 strings
byte offsets[] = {28, 33, 38, 43};
//states of control buttons
byte button_States[] = {false, false, false};
unsigned int stick_Zero_Y = 0;
unsigned int stick_Zero_X = 0;
// fifth fsr mode, when off fifth fsr is fixed to fourth fsr sound otherwise dynamic (last hit fsr)
boolean fsr_Add_Slave_Mode = false;
//no need to press the fsr to trigger a note, simply press a finger on a softpot
boolean full_Legato_Mode = false;
// allows for 4 sounds to be triggered by the 4 fsr's.
boolean channel_Mode = false;
//toggle bowmode (hold sound only as long as fsr is touched) and regular mode (hold sound as long as string is pressed)
boolean bow_Mode = false;
// store which fsr has been hit in channelmode
byte c = 0;
byte old_c = 0;
int y_Pos_old = 0;
int y_Pos2_old = 0;
//accelerometer
int accel_y_old = 0;
int accel_z_old = 0;
int accel_x_old = 0;
int stick_x_old = 0;
int wheel_old = 0;
int wheel_older = 0;
int hothand_x_old = 0;
int hothand_y_old = 0;
int hothand_stable;
int hothand_counter = 0;
byte hothand_array[40];
unsigned int stick_average = 0;
unsigned int stick_average_y = 0;
unsigned int accel_average_y = 0;
unsigned int accel_average_z = 0;
unsigned int accel_average_x = 0;
unsigned int wheel_average = 0;
int wheel_counter = 0;
int old_wheel = 0;
int wheel_stable = 0;
byte wheel_array[40];
unsigned int hothand_average_x = 0;
unsigned int hothand_average_y = 0;
int attack_counter[] = {0,0,0,0};
byte running_byte = 0;
//midi in variables
byte state = 0;
byte save_Slot = 0;
byte status_Byte;
byte data_Byte1;
byte data_Byte2;
byte button_read = 0;
int button_count = 0;
//make sure multimode program changes work on the blofeld!!
byte first_programchange = 0;
//joystick
bool is_Middle_stick_y = 0;
bool is_Middle_stick_x = 0;
// thin control data a little
byte control_counter = 0;
byte at_counter[] = {0,0,0,0};
byte fsr_counter[] = {0,0,0,0};
unsigned int fsr_Add_Init;
unsigned int fsr_Foot_Init;
unsigned int fsr_Arp_Init;
byte fsr_Add_Touched = 0;
bool fsr_Foot_Touched = 0;
bool fsr_Arp_Touched = 0;
byte fsr_Add_Old = 0;
byte fsr_Arp_Old = 0;
byte fsr_Foot_Old = 0;
byte at_counter_add = 0;
byte at_counter_foot = 0;
byte arp_counter_add = 0;
//arpeggiator softpot and fsr stuff
byte temp_active;
byte divider;
byte old_pos_arp;
byte arp_pos;
byte old_arp;
//usb host stuff serials of attached devices
int serialNumbers[7];
//specific devices are saved to be able to send/receive to specific devices regardless of order they are plugged in
int blofeld;
int keysaxo;
int footpedal;
//sustain via midi cc
bool sustain_mode = 1;
//--------- Setup ----------------//
void setup() {
Wire.setSDA(8);
Wire.setSCL(7);
MIDI1.begin(MIDI_CHANNEL_OMNI);
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFont(u8x8_font_7x14B_1x2_f);
// u8x8.drawString(0,0,"Booting");
// digitalWrite(PIN_LED, HIGH);
//read fret definitions from EEPROM
//
for (byte i=NUM_STRINGS; i--;){
fret_Defs[i][0] = 255;
for (byte j=1; j<24; j++){
fret_Defs[i][j] = EEPROM.read(j + (24*i));
}
fret_Defs[i][24]=0;
calibration_Min[i] = EEPROM.read(24 + (24*i));
}
pinMode(PIN_BUTTON_PANIC, INPUT);
pinMode(PIN_BUTTON_FSR, INPUT);
pinMode(PIN_OCTAVE_UP, INPUT);
pinMode(PIN_OCTAVE_DOWN, INPUT);
pinMode(PIN_BUTTON_CHANNEL, INPUT);
analogReadResolution(11);
// pinMode(PIN_LED, OUTPUT);
while(millis() < 800) {
for (byte i=NUM_STRINGS; i--;){
fsr_Init[i] = analogRead(fsr_Pins[i])>>1;
string_Fsr_Init[i] = analogRead(string_Fsr_Pins[i])>>1;
// unsigned int val = analogRead(soft_Pot_Pins[i]);
// if (val > calibration_Max[i]) calibration_Max[i] = val;
}
fsr_Add_Init = analogRead(PIN_FSR_5)>>1;
// fsr_Foot_Init = analogRead(PIN_FSR_FOOT);
fsr_Arp_Init = analogRead(PIN_ARP_FSR)>>1;
//calibrate joystick
int temp_stick_y;
for (int i=CONTROL_RATE; i--;){
temp_stick_y = analogRead(PIN_JOYSTICK_Y);
stick_Zero_Y = stick_Zero_Y + temp_stick_y;
}
stick_Zero_Y = stick_Zero_Y / (CONTROL_RATE);
stick_Zero_X = analogRead(PIN_JOYSTICK_X);
//calibrate accelerometer
}
myusb.begin();
delay(1500);
for (int i=0; i<7; i++) {
if (midilist[i]->manufacturer() != NULL && midilist[i]->serialNumber() != NULL) {
Serial.println((char*)midilist[i]->serialNumber());
Serial.println(midilist[i]->idProduct());
if (!strcmp(midilist[i]->serialNumber(), "11390072173-1304284600")) { //Waldorf Blofeld Serial
Serial.println("here is blofeld");
blofeld = i;
}
if (!strcmp(midilist[i]->serialNumber(),"003600433435511733353932")) {//Axoloti for qunexus/vocoder serial
Serial.println("here is axovocoder");
keysaxo = i;
}
if (!strcmp(midilist[i]->serialNumber(),"EncoderFanel")) {//Axoloti for qunexus/vocoder serial
Serial.println("here is the footcontroller");
footpedal = i;
}
}
}
Serial.println(keysaxo);
Serial.println(footpedal);
midilist[footpedal]->setHandleProgramChange(footProgramChange);
midilist[footpedal]->setHandleControlChange(footControlChange);
midilist[footpedal]->setHandleNoteOn(footNoteOn);
midilist[footpedal]->setHandleNoteOff(footNoteOff);
//send to blofeld to activate multi program change
midilist[blofeld]->sendControlChange(0,127,6);
midilist[blofeld]->sendControlChange(32,127,6);
//load first program on all synths
loadSettings(0);
for (int i=0; i<7; i++) {
if (i != footpedal) midilist[i]->sendProgramChange(0,1);
}
// digitalWrite(PIN_LED, LOW);
//press leftmost (from above) button during startup to calibrate
if ( digitalRead(PIN_BUTTON_CHANNEL) == LOW ) {
u8x8.drawString(0,0,"Calibration:");
calibrate();
}
//write defaults to all program locations, overwriting everything
/* if (digitalRead(PIN_BUTTON_FSR) == LOW && !button_States[BREATH]) {
button_States[BREATH] = true;
writeDefaults();
} */
if (!channel_Mode) u8x8.drawString(0,0,"MPE ");
else u8x8.drawString(0,0,"POLY");
u8x8.drawString(0,50,"OCT:");
enum {BufSize=3}; // If a is short use a smaller number, eg 5 or 6
char buf[BufSize];
snprintf (buf, BufSize, "%d", octave);
u8x8.drawString(5,50,buf);
}
//----------Main Loop---------------//
void loop() {
//------midi input from the qunexus keyboard-----------//
if (MIDI1.read()) {
sendQunexus(MIDI1.getType(), MIDI1.getData1(), MIDI1.getData2(), MIDI1.getChannel() + 9);
}
//---midi from the footpedal----//
myusb.Task();
midilist[footpedal]->read();
//-------------------start of the bass-midi controller code-------------------------------//
//reset fsr_Vals to zero
memset(fsr_Vals,0,sizeof(fsr_Vals));
//------------------------- READ ALL SENSORS (Softpots and FSRs)---------------//
//read values of all sensors
unsigned int fsr_Read[4];
unsigned int stringfsr_Read[4];
byte fret_touch = fret_Touched[0] + fret_Touched[1] + fret_Touched[2] + fret_Touched[3];
unsigned int fsr_Add = analogRead(PIN_FSR_5)>>1;
unsigned int fsr_Arp = analogRead(PIN_ARP_FSR)>>1;
unsigned int softpot_Arp = analogRead(PIN_ARP_SOFTPOT);
//code for the "arpeggiator" softpot and fsr
if (channel_Mode) {
if (fsr_Arp < (fsr_Arp_Init - 50) && !fsr_Arp_Touched) {
fsr_Arp_Touched = 1;
divider = 0;
for (int i=0; i<NUM_STRINGS; i++) {
arp_Note[i] = 0;
if (fret_Touched[i]) {
divider = divider + 1;
arp_Note[divider - 1] = active_Note[i];
noteOn(0x91 + c, active_Note[i],0);
}
}
for (int i=divider; i<NUM_STRINGS; i++) {
arp_Note[i] = arp_Note[i-divider] + 12;
}
}
if (fsr_Arp < (fsr_Arp_Init - 30) && fsr_Arp_Touched) {
fsr_Arp = map_fsr[constrain(int(fsr_Arp*1.6f) - 450,0,1005)];
if ((fsr_Arp - fsr_Arp_Old)) {
arp_counter_add = arp_counter_add + 1;
if (arp_counter_add == AFTERTOUCH_RATE) {
if (fret_touch) aftertouchChange(0xD1 + c + CHANNEL_OFFSET, fsr_Arp);
arp_counter_add = 0;
}
}
fsr_Arp_Old = fsr_Arp;
}
if ((softpot_Arp > 880) ) arp_pos = 0;
if ((softpot_Arp > 740) && (softpot_Arp <= 852)) arp_pos = 1;
if ((softpot_Arp > 692) && (softpot_Arp <= 730)) arp_pos = 0;
if ((softpot_Arp > 540) && (softpot_Arp <= 682)) arp_pos = 2;
if ((softpot_Arp > 500) && (softpot_Arp <= 530))arp_pos = 0;
if ((softpot_Arp > 300) && (softpot_Arp <= 490))arp_pos = 3;
if ((softpot_Arp > 250) && (softpot_Arp <= 295))arp_pos = 0;
if ((softpot_Arp > 130) && (softpot_Arp <= 240))arp_pos = 4;
if ((softpot_Arp > 0) && (softpot_Arp <= 120))arp_pos = 0;
if (divider) {
if (arp_pos != old_arp) {
old_arp = arp_pos;
switch (arp_pos) {
case 0:
if (temp_active)noteOn(0x91 + c, temp_active, 0);
temp_active = 0;
break;
case 1:
if (temp_active)noteOn(0x91 + c, temp_active, 0);
noteOn(0x91 + c, arp_Note[0] + 12, 80);
temp_active = arp_Note[0] + 12;
break;
case 2:
if (temp_active)noteOn(0x91 + c, temp_active, 0);
noteOn(0x91 + c, arp_Note[1] + 12, 80);
temp_active = arp_Note[1] + 12;
break;
case 3:
if (temp_active)noteOn(0x91 + c, temp_active, 0);
noteOn(0x91 + c, arp_Note[2] + 12, 80);
temp_active = arp_Note[2] + 12;
break;
case 4:
if (temp_active)noteOn(0x91 + c, temp_active, 0);
noteOn(0x91 + c, arp_Note[3] + 12, 80);
temp_active = arp_Note[3] + 12;
break;
}
}
}
if (fsr_Arp > (fsr_Arp_Init - 15) && fsr_Arp_Touched) {
if (temp_active)noteOn(0x91 + c, temp_active, 0);
temp_active = 0;
old_arp = -1;
fsr_Arp_Touched = 0;
aftertouchChange(0xD1 + c + CHANNEL_OFFSET, 0);
}
}
if (!fsr_Foot_Touched && !fsr_Arp_Touched) {
if (channel_Mode) {
// if (fret_touch) {
if (fsr_Add < (fsr_Add_Init - 30) && !fsr_Add_Touched) {
if (!fsr_Add_Slave_Mode) c = 3;
attack_counter[c] = 0;
// fsr_Vals[c] = map(fsr_Add, fsr_Add_Init - 30, 60, MINVELOCITY, 127);
fsr_Vals[c] = 80;
fsr_Add_Touched = 1;
fsr_Touched[c] = 1;
}
if (fsr_Add < (fsr_Add_Init - 20) && fsr_Add_Touched) {
fsr_Add = map_fsr[constrain(fsr_Add - 20,0,1005)];
if ((fsr_Add - fsr_Add_Old) && attack_counter[c]) {
at_counter_add = at_counter_add + 1;
if (at_counter_add == AFTERTOUCH_RATE) {
if (fret_touch) aftertouchChange(0xD1 + c + CHANNEL_OFFSET, fsr_Add);
at_counter_add = 0;
}
}
if (attack_counter[c] < ATTACK) attack_counter[c] = attack_counter[c] + 1;
fsr_Add_Old = fsr_Add;
}
if (fsr_Add > (fsr_Add_Init - 15) && fsr_Add_Touched) {
if (fret_touch) aftertouchChange(0xD1 + c + CHANNEL_OFFSET, 0);
fsr_Add_Touched = 0;
fsr_Touched[c] = 0;
}
//} else fsr_Add_Touched = 0;
} else {
if (fsr_Add < (fsr_Add_Init - 30) && !fsr_Add_Touched) {
memset(attack_counter,0,sizeof(attack_counter));
// fsr_Vals[0] = map(fsr_Add, fsr_Add_Init - 30, 60, MINVELOCITY, 127);
fsr_Vals[0] = 80;
fsr_Vals[1] = fsr_Vals[0];
fsr_Vals[2] = fsr_Vals[0];
fsr_Vals[3] = fsr_Vals[0];
fsr_Add_Touched = 1;
memset(fsr_Touched,1,sizeof(fsr_Touched));
}
if (fsr_Add < (fsr_Add_Init - 20) && fsr_Add_Touched) {
fsr_Add = map_fsr[constrain(fsr_Add - 20,0,1005) ];
if ((fsr_Add - fsr_Add_Old) && attack_counter[0]) {
at_counter_add = at_counter_add + 1;
if (at_counter_add == AFTERTOUCH_RATE) {
if (fret_Touched[0]) aftertouchChange(0xD1 , fsr_Add);
if (fret_Touched[1]) aftertouchChange(0xD2 , fsr_Add);
if (fret_Touched[2]) aftertouchChange(0xD3 , fsr_Add);
if (fret_Touched[3]) aftertouchChange(0xD4 , fsr_Add);
at_counter_add = 0;
}
}
if (attack_counter[0] < ATTACK) {
attack_counter[0] = attack_counter[0] + 1;
attack_counter[1] = attack_counter[0];
attack_counter[2] = attack_counter[0];
attack_counter[3] = attack_counter[0];
}
fsr_Add_Old = fsr_Add;
}
if (fsr_Add > (fsr_Add_Init - 15) && fsr_Add_Touched) {
if (fret_Touched[0]) aftertouchChange(0xD1 , 0);
if (fret_Touched[1]) aftertouchChange(0xD2 , 0);
if (fret_Touched[2]) aftertouchChange(0xD3 , 0);
if (fret_Touched[3]) aftertouchChange(0xD4 , 0);
fsr_Add_Touched = 0;
memset(fsr_Touched,0,sizeof(fsr_Touched));
}
}
}
//bool fsr_Foot = digitalRead(PIN_FSR_FOOT);
bool fsr_Foot = sustain_mode;
if (!fsr_Add_Touched && !fsr_Arp_Touched) {
if (channel_Mode) {
// if (fret_touch) {
if (fsr_Foot == LOW && !fsr_Foot_Touched) {
// if (!fsr_Add_Slave_Mode) c = 3;
attack_counter[c] = ATTACK;
// fsr_Vals[c] = map(fsr_Foot, fsr_Foot_Init - 450, 60, MINVELOCITY, 127);
fsr_Vals[c] = 80;
fsr_Foot_Touched = 1;
fsr_Touched[c] = 1;
}
if (fsr_Foot_Touched) {
int c_temp = c;
fsr_Read[0] = analogRead(fsr_Pins[0])>>1;
if (fsr_Read[0] < (fsr_Init[0] - 30)) {
fsr_Touched[c] = 0;
// fsr_Vals[c] = 0;
fsr_Touched[0] = 1;
// fsr_Vals[0] = 80;
c = 0;
}
fsr_Read[1] = analogRead(fsr_Pins[1])>>1;
if (fsr_Read[1] < (fsr_Init[1] - 30)) {
fsr_Touched[c] = 0;
fsr_Touched[1] = 1;
c = 1;
}
fsr_Read[2] = analogRead(fsr_Pins[2])>>1;
if (fsr_Read[2] < (fsr_Init[2] - 30)) {
fsr_Touched[c] = 0;
fsr_Touched[2] = 1;
c = 2;
}
fsr_Read[3] = analogRead(fsr_Pins[3])>>1;
if (fsr_Read[3] < (fsr_Init[3] - 30)) {
fsr_Touched[c] = 0;
fsr_Touched[3] = 1;
c = 3;
}
if (c_temp != c) {
if (fret_Touched[0]) {
noteOn(0x91 + c, active_Note[0], 80);
noteOn(0x91 + c_temp, active_Note[0], 0);
}
if (fret_Touched[1]) {
noteOn(0x91 + c, active_Note[1], 80);
noteOn(0x91 + c_temp, active_Note[1], 0);
}
if (fret_Touched[2]) {
noteOn(0x91 + c, active_Note[2], 80);
noteOn(0x91 + c_temp, active_Note[2], 0);
}
if (fret_Touched[3]) {
noteOn(0x91 + c, active_Note[3], 80);
noteOn(0x91 + c_temp, active_Note[3], 0);
}
}
}
if (fsr_Foot == HIGH && fsr_Foot_Touched) {
// if (fret_touch) aftertouchChange(0xD1 + c + CHANNEL_OFFSET, 0);
fsr_Foot_Touched = 0;
fsr_Touched[c] = 0;
}
} else {
if (fsr_Foot == LOW && !fsr_Foot_Touched) {
memset(attack_counter,ATTACK,sizeof(attack_counter));
// fsr_Vals[0] = map(fsr_Foot, fsr_Foot_Init - 450, 60, MINVELOCITY, 127);
fsr_Vals[0] = 80;
fsr_Vals[1] = fsr_Vals[0];
fsr_Vals[2] = fsr_Vals[0];
fsr_Vals[3] = fsr_Vals[0];
fsr_Foot_Touched = 1;
memset(fsr_Touched,1,sizeof(fsr_Touched));
}
if (fsr_Foot == HIGH && fsr_Foot_Touched) {
fsr_Foot_Touched = 0;
memset(fsr_Touched,0,sizeof(fsr_Touched));
}
}
}
//-STRING ONE-//
//read fsr vals
if(!fsr_Add_Touched && !fsr_Foot_Touched && !fsr_Arp_Touched) {
if (!channel_Mode) fret_touch = fret_Touched[0];
fsr_Read[0] = analogRead(fsr_Pins[0])>>1;
if (fret_touch) {
if (fsr_Read[0] < (fsr_Init[0] - 50) && !fsr_Touched[0]) {
attack_counter[0] = 0;
// fsr_Vals[0] = map((fsr_Read[0]), fsr_Init[0] - 30, 60, MINVELOCITY, 127);
fsr_Vals[0] = 80;
fsr_Touched[0] = 1;
c= 0;
}
if (fsr_Read[0] < (fsr_Init[0] - 35) && fsr_Touched[0]) {
fsr_Read[0] = map_fsr[constrain(fsr_Read[0] - 30,0,1005) ];
if ((fsr_Read[0] - fsr_Read_Old[0]) && attack_counter[0]) {
at_counter[0] = at_counter[0] + 1;
if (at_counter[0] == AFTERTOUCH_RATE) {
if (channel_Mode) aftertouchChange(0xD1 + CHANNEL_OFFSET, fsr_Read[0]);
else aftertouchChange(0xD1 ,fsr_Read[0]);
at_counter[0] = 0;
}
}
if (attack_counter[0] < ATTACK) attack_counter[0] = attack_counter[0] + 1;
fsr_Read_Old[0] = fsr_Read[0];
}
if (fsr_Read[0] > (fsr_Init[0] - 30) && fsr_Touched[0]) {
if (channel_Mode) aftertouchChange(0xD1 + CHANNEL_OFFSET, 0);
else aftertouchChange(0xD1 ,0);
fsr_Touched[0] = 0;
}
} else {
fsr_Touched[0] = 0;
if (fsr_Read[0] < (fsr_Init[0] - 30)) c = 0;
}
}
//read the value of all the softPots
soft_Pot_Vals[0] = analogRead(soft_Pot_Pins[0]);
soft_Pot_Vals[0] = map(soft_Pot_Vals[0], calibration_Min[0], MAXREADING, 0, 255);
soft_Pot_Vals[0] = constrain(soft_Pot_Vals[0], 0, 255);
// read the string_fsr and process it...send on string channel poly aftertouch
string_Fsr_Vals[0] = analogRead(string_Fsr_Pins[0])>>1;
if ((string_Fsr_Vals[0] < (string_Fsr_Init[0] - 30)) && string_Active[0]) {
string_fsr_active[0] = 1;
unsigned int map_string_Fsr = map_fsr_string[constrain(string_Fsr_Vals[0] - 30,0,1005)];
if (map_string_Fsr - string_Fsr_Old[0]) {
fsr_counter[0] = fsr_counter[0] + 1;
if (fsr_counter[0] == AFTERTOUCH_RATE) {
if (channel_Mode) {
usbMIDI.sendPolyPressure(active_Note[0],map_string_Fsr, c + CHANNEL_OFFSET + 2);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[0],map_string_Fsr, c + CHANNEL_OFFSET + 2);
midilist[i]->send_now();
}
}
}
else {
usbMIDI.sendPolyPressure(active_Note[0],map_string_Fsr, 2);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[0],map_string_Fsr, 2);
midilist[i]->send_now();
}
}
}
fsr_counter[0] = 0;
}
string_Fsr_Old[0] = map_string_Fsr;
}
} else string_fsr_active[0] = 0;
//--STRING TWO--//
if(!fsr_Add_Touched && !fsr_Foot_Touched && !fsr_Arp_Touched) {
if (!channel_Mode) fret_touch = fret_Touched[1];
fsr_Read[1] = analogRead(fsr_Pins[1])>>1;
if (fret_touch) {
if (fsr_Read[1] < (fsr_Init[1] - 50) && !fsr_Touched[1]) {
attack_counter[1] = 0;
// fsr_Vals[1] = map((fsr_Read[1]), fsr_Init[1] - 30, 60, MINVELOCITY, 127);
fsr_Vals[1] = 80;
fsr_Touched[1] = 1;
c= 1;
}
if (fsr_Read[1] < (fsr_Init[1] - 35) && fsr_Touched[1]) {
fsr_Read[1] = map_fsr[constrain(fsr_Read[1] - 30,0,1005) ];
if ((fsr_Read[1] - fsr_Read_Old[1]) && attack_counter[1]) {
at_counter[1] = at_counter[1] + 1;
if (at_counter[1] == AFTERTOUCH_RATE) {
if (channel_Mode) aftertouchChange(0xD2 + CHANNEL_OFFSET, fsr_Read[1]);
else aftertouchChange(0xD2 ,fsr_Read[1]);
at_counter[1] = 0;
}
}
if (attack_counter[1] < ATTACK) attack_counter[1] = attack_counter[1] + 1;
fsr_Read_Old[1] = fsr_Read[1];
}
if (fsr_Read[1] > (fsr_Init[1] - 30) && fsr_Touched[1]) {
if (channel_Mode) aftertouchChange(0xD2 + CHANNEL_OFFSET, 0);
else aftertouchChange(0xD2 ,0);
fsr_Touched[1] = 0;
}
} else {
fsr_Touched[1] = 0;
if (fsr_Read[1] < (fsr_Init[1] - 30)) c = 1;
}
}
//read the value of all the softPots
soft_Pot_Vals[1] = analogRead(soft_Pot_Pins[1]);
soft_Pot_Vals[1] = map(soft_Pot_Vals[1], calibration_Min[1], MAXREADING, 0, 255);
soft_Pot_Vals[1] = constrain(soft_Pot_Vals[1], 0, 255);
string_Fsr_Vals[1] = analogRead(string_Fsr_Pins[1])>>1;
// read the string_fsr and process it...send on string channel poly aftertouch
string_Fsr_Vals[1] = analogRead(string_Fsr_Pins[1])>>1;
if ((string_Fsr_Vals[1] < (string_Fsr_Init[1] - 30)) && string_Active[1]) {
string_fsr_active[1] = 1;
unsigned int map_string_Fsr = map_fsr_string[constrain(string_Fsr_Vals[1] - 30,0,1005)];
if (map_string_Fsr - string_Fsr_Old[1]) {
fsr_counter[1] = fsr_counter[1] + 1;
if (fsr_counter[1] == AFTERTOUCH_RATE) {
if (channel_Mode) {
usbMIDI.sendPolyPressure(active_Note[1],map_string_Fsr, c + CHANNEL_OFFSET + 2);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[1],map_string_Fsr, c + CHANNEL_OFFSET + 2);
midilist[i]->send_now();
}
}
}
else {
usbMIDI.sendPolyPressure(active_Note[1],map_string_Fsr, 3);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[1],map_string_Fsr, 3);
midilist[i]->send_now();
}
}
}
fsr_counter[1] = 0;
}
string_Fsr_Old[1] = map_string_Fsr;
}
} else string_fsr_active[1] = 0;
//-STRING THREE--//
if(!fsr_Add_Touched && !fsr_Foot_Touched && !fsr_Arp_Touched) {
if (!channel_Mode) fret_touch = fret_Touched[2];
fsr_Read[2] = analogRead(fsr_Pins[2])>>1;
if (fret_touch) {
if (fsr_Read[2] < (fsr_Init[2] - 50) && !fsr_Touched[2]) {
attack_counter[2] = 0;
// fsr_Vals[2] = map((fsr_Read[2]), fsr_Init[2] - 30, 60, MINVELOCITY, 127);
fsr_Vals[2] = 80;
fsr_Touched[2] = 1;
c= 2;
}
if (fsr_Read[2] < (fsr_Init[2] - 35) && fsr_Touched[2]) {
fsr_Read[2] = map_fsr[constrain(fsr_Read[2] - 30,0,1005) ];
if ((fsr_Read[2] - fsr_Read_Old[2]) && attack_counter[2]) {
at_counter[2] = at_counter[2] + 1;
if (at_counter[2] == AFTERTOUCH_RATE) {
if (channel_Mode) aftertouchChange(0xD3 + CHANNEL_OFFSET, fsr_Read[2]);
else aftertouchChange(0xD3 ,fsr_Read[2]);
at_counter[2] = 0;
}
}
if (attack_counter[2] < ATTACK) attack_counter[2] = attack_counter[2] + 1;
fsr_Read_Old[2] = fsr_Read[2];
}
if (fsr_Read[2] > (fsr_Init[2] - 30) && fsr_Touched[2]) {
if (channel_Mode) aftertouchChange(0xD2 + CHANNEL_OFFSET, 0);
else aftertouchChange(0xD2 ,0);
fsr_Touched[2] = 0;
}
} else {
fsr_Touched[2] = 0;
if (fsr_Read[2] < (fsr_Init[2] - 30)) c = 2;
}
}
//read the value of all the softPots
soft_Pot_Vals[2] = analogRead(soft_Pot_Pins[2]);
soft_Pot_Vals[2] = map(soft_Pot_Vals[2], calibration_Min[2], MAXREADING, 0, 255);
soft_Pot_Vals[2] = constrain(soft_Pot_Vals[2], 0, 255);
string_Fsr_Vals[2] = analogRead(string_Fsr_Pins[2])>>1;
// read the string_fsr and process it...send on string channel poly aftertouch
string_Fsr_Vals[2] = analogRead(string_Fsr_Pins[2])>>1;
if ((string_Fsr_Vals[2] < (string_Fsr_Init[2] - 30)) && string_Active[2]) {
string_fsr_active[2] = 1;
unsigned int map_string_Fsr = map_fsr_string[constrain(string_Fsr_Vals[2] - 30,0,1005)];
if (map_string_Fsr - string_Fsr_Old[2]) {
fsr_counter[2] = fsr_counter[2] + 1;
if (fsr_counter[2] == AFTERTOUCH_RATE) {
if (channel_Mode) {
usbMIDI.sendPolyPressure(active_Note[2],map_string_Fsr, c + CHANNEL_OFFSET + 2);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[2],map_string_Fsr, c + CHANNEL_OFFSET + 2);
midilist[i]->send_now();
}
}
}
else {
usbMIDI.sendPolyPressure(active_Note[2],map_string_Fsr,4);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[2],map_string_Fsr,4);
midilist[i]->send_now();
}
}
}
fsr_counter[2] = 0;
}
string_Fsr_Old[2] = map_string_Fsr;
}
} else string_fsr_active[2] = 0;
//-- STRING FOUR--//
if(!fsr_Add_Touched && !fsr_Foot_Touched && !fsr_Arp_Touched) {
if (!channel_Mode) fret_touch = fret_Touched[3];
fsr_Read[3] = analogRead(fsr_Pins[3])>>1;
if (fret_touch) {
if (fsr_Read[3] < (fsr_Init[3] - 50) && !fsr_Touched[3]) {
attack_counter[3] = 0;
// fsr_Vals[3] = map((fsr_Read[3]), fsr_Init[3] - 30, 60, MINVELOCITY, 127);
fsr_Vals[3] = 80;
fsr_Touched[3] = 1;
c=3;
}
if (fsr_Read[3] < (fsr_Init[3] - 35) && fsr_Touched[3]) {
fsr_Read[3] = map_fsr[constrain(fsr_Read[3] - 30,0,1005) ];
if ((fsr_Read[3] - fsr_Read_Old[3]) && attack_counter[3]) {
at_counter[3] = at_counter[3] + 1;
if (at_counter[3] == AFTERTOUCH_RATE) {
if (channel_Mode) aftertouchChange(0xD4 + CHANNEL_OFFSET, fsr_Read[3]);
else aftertouchChange(0xD4 ,fsr_Read[3]);
at_counter[3] = 0;
}
}
if (attack_counter[3] < ATTACK) attack_counter[3] = attack_counter[3] + 1;
fsr_Read_Old[3] = fsr_Read[3];
}
if (fsr_Read[3] > (fsr_Init[3] - 30) && fsr_Touched[3]) {
if (channel_Mode) aftertouchChange(0xD3 + CHANNEL_OFFSET, 0);
else aftertouchChange(0xD3 ,0);
fsr_Touched[3] = 0;
}
} else {
fsr_Touched[3] = 0;
if (fsr_Read[3] < (fsr_Init[3] - 30)) c = 3;
}
}
//read the value of all the softPots
soft_Pot_Vals[3] = analogRead(soft_Pot_Pins[3]);
soft_Pot_Vals[3] = map(soft_Pot_Vals[3], calibration_Min[3], MAXREADING, 0, 255);
soft_Pot_Vals[3] = constrain(soft_Pot_Vals[3], 0, 255);
string_Fsr_Vals[3] = analogRead(string_Fsr_Pins[3])>>1;
// read the string_fsr and process it...send on string channel poly aftertouch
string_Fsr_Vals[3] = analogRead(string_Fsr_Pins[3])>>1;
if ((string_Fsr_Vals[3] < (string_Fsr_Init[3] - 30)) && string_Active[3]) {
string_fsr_active[3] = 1;
unsigned int map_string_Fsr = map_fsr_string[constrain(string_Fsr_Vals[3] - 30,0,1005)];
if (map_string_Fsr - string_Fsr_Old[3]) {
fsr_counter[3] = fsr_counter[3] + 1;
if (fsr_counter[3] == AFTERTOUCH_RATE) {
if (channel_Mode) {
usbMIDI.sendPolyPressure(active_Note[3],map_string_Fsr, c + CHANNEL_OFFSET + 2);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[3],map_string_Fsr, c + CHANNEL_OFFSET + 2);
midilist[i]->send_now();
}
}
}
else {
usbMIDI.sendPolyPressure(active_Note[3],map_string_Fsr, 5);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendPolyPressure(active_Note[3],map_string_Fsr, 5);
midilist[i]->send_now();
}
}
}
fsr_counter[3] = 0;
}
string_Fsr_Old[3] = map_string_Fsr;
}
} else string_fsr_active[3] = 0;
//}
//------------------DETERMINE FRETS----------------------//
//---------Get Fret Numbers------//
//--STRING ONE--//
byte soft_Pot_Val = soft_Pot_Vals[0];
//check for open strings
if (soft_Pot_Val == 255) {
soft_Pot_Vals_Old[0] = soft_Pot_Val;
fret_Touched[0]=0;
}
//loop through the array of fret definitions
for (byte j=1; j<24; j++) {
byte k = j-1;
if (soft_Pot_Val <= fret_Defs[0][k] &&
soft_Pot_Val > fret_Defs[0][j] ) {
if (((uint8_t)(abs( (int8_t) (soft_Pot_Val-soft_Pot_Vals_Old[0]))) > PADDING)) {
soft_Pot_Vals_Old[0] = soft_Pot_Val;
fret_Touched[0] = j;
break;
}
}
}
if (soft_Pot_Val <= fret_Defs[0][23]) {
soft_Pot_Vals_Old[0] = soft_Pot_Val;
fret_Touched[0]=24;
}
//--STRING TWO--//
soft_Pot_Val = soft_Pot_Vals[1];
//check for open strings
if (soft_Pot_Val == 255) {
soft_Pot_Vals_Old[1] = soft_Pot_Val;
fret_Touched[1]=0;
}
//loop through the array of fret definitions
for (byte j=1; j<24; j++) {
byte k = j-1;
if (soft_Pot_Val <= fret_Defs[1][k] &&
soft_Pot_Val > fret_Defs[1][j] ) {
if (((uint8_t)(abs( (int8_t) (soft_Pot_Val-soft_Pot_Vals_Old[1]))) > PADDING)) {
soft_Pot_Vals_Old[1] = soft_Pot_Val;
fret_Touched[1] = j;
break;
}
}
}
if (soft_Pot_Val <= fret_Defs[1][23]) {
soft_Pot_Vals_Old[1] = soft_Pot_Val;
fret_Touched[1]=24;
}
//--STRING THREE--//
soft_Pot_Val = soft_Pot_Vals[2];
//check for open strings
if (soft_Pot_Val == 255) {
soft_Pot_Vals_Old[2] = soft_Pot_Val;
fret_Touched[2]=0;
}
//loop through the array of fret definitions
for (byte j=1; j<24; j++) {
byte k = j-1;
if (soft_Pot_Val <= fret_Defs[2][k] &&
soft_Pot_Val > fret_Defs[2][j]) {
if(((uint8_t)(abs( (int8_t) (soft_Pot_Val-soft_Pot_Vals_Old[2]))) > PADDING)) {
soft_Pot_Vals_Old[2] = soft_Pot_Val;
fret_Touched[2] = j;
break;
}
}
}
if (soft_Pot_Val <= fret_Defs[2][23]) {
soft_Pot_Vals_Old[2] = soft_Pot_Val;
fret_Touched[2]=24;
}
//---STRING FOUR--//
soft_Pot_Val = soft_Pot_Vals[3];
//check for open strings
if (soft_Pot_Val == 255) {
soft_Pot_Vals_Old[3] = soft_Pot_Val;
fret_Touched[3]=0;
}
//loop through the array of fret definitions
for (byte j=1; j<24; j++) {
byte k = j-1;
if (soft_Pot_Val <= fret_Defs[3][k] &&
soft_Pot_Val > fret_Defs[3][j] ) {
if (((uint8_t)(abs( (int8_t) (soft_Pot_Val-soft_Pot_Vals_Old[3]))) > PADDING)) {
soft_Pot_Vals_Old[3] = soft_Pot_Val;
fret_Touched[3] = j;
break;
}
}
}
if (soft_Pot_Val <= fret_Defs[3][23]) {
soft_Pot_Vals_Old[3] = soft_Pot_Val;
fret_Touched[3]=24;
}
//test for legato action
byte enable_legato;
if (channel_Mode) {
if(attack_counter[c] < ATTACK_LEGATO && fsr_Add_Touched) enable_legato = 0;
else enable_legato = 1;
}
//----STRING ONE--//
if (!channel_Mode) {
if(attack_counter[0] < ATTACK_LEGATO && fsr_Add_Touched) enable_legato = 0;
else enable_legato = 1;
c = 0;
old_c = 0;
}
if (string_Active[0] ) {
if (enable_legato ) {
if (fret_Touched[0]) note_Fretted[0] = fret_Touched[0] + offsets[0];
if (note_Fretted[0] > active_Note[0]) {
//turn on new note
noteOn(0x91 + c, note_Fretted[0], 80);
noteOn(0x91 + old_c, active_Note[0], 0);
//register new note as the active one
active_Note[0] = note_Fretted[0];
}
else if ((note_Fretted[0] < active_Note[0]) && string_fsr_active[0]) {
if (note_Fretted[0] == maybe_Note[0]) stable_Count[0] += 1;
if (stable_Count[0] == STABLETIME) {
noteOn(0x91 + c, note_Fretted[0], 80);
noteOn(0x91 + old_c, active_Note[0], 0);
//register new note as the active one
active_Note[0] = note_Fretted[0];
stable_Count[0] = 0;
// maybe_Note[0] = 0;
}
maybe_Note[0] = note_Fretted[0];
}
}
}
else if (fret_Touched[0] && fsr_Touched[c] && !fsr_Vals[c]) {
note_Fretted[0] = fret_Touched[0] + offsets[0];
noteOn(0x91 +c, note_Fretted[0], 80);
//register new note as the active one
active_Note[0] = note_Fretted[0];
string_Active[0] = true;
}
//----STRING TWO--//
if (!channel_Mode) {
if(attack_counter[1] < ATTACK_LEGATO && fsr_Add_Touched) enable_legato = 0;
else enable_legato = 1;
c = 1;
old_c = 1;
}
if (string_Active[1] ) {
if (enable_legato ) {
if (fret_Touched[1]) note_Fretted[1] = fret_Touched[1] + offsets[1];
if (note_Fretted[1] > active_Note[1]) {
//turn on new note
noteOn(0x91 + c, note_Fretted[1], 80);
noteOn(0x91 + old_c, active_Note[1], 0);
//register new note as the active one
active_Note[1] = note_Fretted[1];
}
else if ((note_Fretted[1] < active_Note[1]) && string_fsr_active[1]) {
if (note_Fretted[1] == maybe_Note[1]) stable_Count[1] += 1;
if (stable_Count[1] == STABLETIME) {
noteOn(0x91 + c, note_Fretted[1], 80);
noteOn(0x91 + old_c, active_Note[1], 0);
//register new note as the active one
active_Note[1] = note_Fretted[1];
stable_Count[1] = 0;
// maybe_Note[1] = 0;
}
maybe_Note[1] = note_Fretted[1];
}
}
}
else if (fret_Touched[1] && fsr_Touched[c] && !fsr_Vals[c]) {
note_Fretted[1] = fret_Touched[1] + offsets[1];
noteOn(0x91 +c, note_Fretted[1], 80);
//register new note as the active one
active_Note[1] = note_Fretted[1];
string_Active[1] = true;
}
//----STRING THREE--//
if (!channel_Mode) {
if(attack_counter[2] < ATTACK_LEGATO && fsr_Add_Touched) enable_legato = 0;
else enable_legato = 1;
c = 2;
old_c = 2;
}
if (string_Active[2] ) {
if (enable_legato) {
if (fret_Touched[2]) note_Fretted[2] = fret_Touched[2] + offsets[2];
if (note_Fretted[2] > active_Note[2]) {
//turn on new note
noteOn(0x91 + c, note_Fretted[2], 80);
noteOn(0x91 + old_c, active_Note[2], 0);
//register new note as the active one
active_Note[2] = note_Fretted[2];
}
else if ((note_Fretted[2] < active_Note[2]) && string_fsr_active[2]) {
if (note_Fretted[2] == maybe_Note[2]) stable_Count[2] += 1;
if (stable_Count[2] == STABLETIME) {
noteOn(0x91 + c, note_Fretted[2], 80);
noteOn(0x91 + old_c, active_Note[2], 0);
//register new note as the active one
active_Note[2] = note_Fretted[2];
stable_Count[2] = 0;
// maybe_Note[2] = 0;
}
maybe_Note[2] = note_Fretted[2];
}
}
}
else if (fret_Touched[2] && fsr_Touched[c] && !fsr_Vals[c] ) {
note_Fretted[2] = fret_Touched[2] + offsets[2];
noteOn(0x91 +c, note_Fretted[2], 80);
//register new note as the active one
active_Note[2] = note_Fretted[2];
string_Active[2] = true;
}
//----STRING FOUR--//
if (!channel_Mode) {
if(attack_counter[3] < ATTACK_LEGATO && fsr_Add_Touched) enable_legato = 0;
else enable_legato = 1;
c = 3;
old_c = 3;
}
if (string_Active[3] ) {
if (enable_legato) {
if (fret_Touched[3]) note_Fretted[3] = fret_Touched[3] + offsets[3];
if (note_Fretted[3] > active_Note[3]) {
//turn on new note
noteOn(0x91 + c, note_Fretted[3], 80);
noteOn(0x91 + old_c, active_Note[3], 0);
//register new note as the active one
active_Note[3] = note_Fretted[3];
}
else if ((note_Fretted[3] < active_Note[3]) && string_fsr_active[3]) {
if (note_Fretted[3] == maybe_Note[3]) stable_Count[3] += 1;
if (stable_Count[3] == STABLETIME) {
noteOn(0x91 + c, note_Fretted[3], 80);
noteOn(0x91 + old_c, active_Note[3], 0);
//register new note as the active one
active_Note[3] = note_Fretted[3];
stable_Count[3] = 0;
// maybe_Note[3] = 0;
}
maybe_Note[3] = note_Fretted[3];
}
}
}
else if (fret_Touched[3] && fsr_Touched[c] && !fsr_Vals[c]) {
note_Fretted[3] = fret_Touched[3] + offsets[3];
noteOn(0x91 +c, note_Fretted[3], 80);
//register new note as the active one
active_Note[3] = note_Fretted[3];
string_Active[3] = true;
}
//------------PICK NOTES--------------------//
//use this info to determine which notes to pluck
//---STRING ONE----//
if (!channel_Mode) {
c = 0;
old_c = 0;
}
//if the fsr was hit, play the fretted note
if ((fsr_Vals[c] && fret_Touched[0]) ){
note_Fretted[0] = fret_Touched[0] + offsets[0];
if (string_Active[0]){
if (!fsr_Foot_Touched) noteOn(0x91 + old_c , active_Note[0], 0);
}
if (!string_Active[0]) {
//mark string as active
string_Active[0] = true;
}
//register with active notes
active_Note[0] = note_Fretted[0];
// active_Velo[0] = fsr_Vals[c];
//turn on fretted note
if (!fsr_Foot_Touched) noteOn(0x91 + c, active_Note[0], 80);
}
//---STRING TWO----//
if (!channel_Mode) {
c = 1;
old_c = 1;
}
//if the fsr was hit, play the fretted note
if ((fsr_Vals[c] && fret_Touched[1]) ){
note_Fretted[1] = fret_Touched[1] + offsets[1];
if (string_Active[1]){
if (!fsr_Foot_Touched) noteOn(0x91 + old_c , active_Note[1], 0);
}
if (!string_Active[1]) {
//mark string as active
string_Active[1] = true;
}
//register with active notes
active_Note[1] = note_Fretted[1];
// active_Velo[1] = fsr_Vals[c];
//turn on fretted note
if (!fsr_Foot_Touched) noteOn(0x91 + c, active_Note[1], 80);
}
//---STRING THREE----//
if (!channel_Mode) {
c = 2;
old_c = 2;
}
//if the fsr was hit, play the fretted note
if ((fsr_Vals[c] && fret_Touched[2]) ){
note_Fretted[2] = fret_Touched[2] + offsets[2];
if (string_Active[2]){
if (!fsr_Foot_Touched) noteOn(0x91 + old_c , active_Note[2], 0);
}
if (!string_Active[2]) {
//mark string as active
string_Active[2] = true;
}
//register with active notes
active_Note[2] = note_Fretted[2];
// active_Velo[2] = fsr_Vals[c];
//turn on fretted note
if (!fsr_Foot_Touched) noteOn(0x91 + c, active_Note[2], 80);
}
//---STRING FOUR----//
if (!channel_Mode) {
c = 3;
old_c = 3;
}
//if the fsr was hit, play the fretted note
if ((fsr_Vals[c] && fret_Touched[3]) ){
note_Fretted[3] = fret_Touched[3] + offsets[3];
if (string_Active[3]){
if (!fsr_Foot_Touched) noteOn(0x91 + old_c , active_Note[3], 0);
}
if (!string_Active[3]) {
//mark string as active
string_Active[3] = true;
}
//register with active notes
active_Note[3] = note_Fretted[3];
// active_Velo[3] = fsr_Vals[c];
//turn on fretted note
if (!fsr_Foot_Touched) noteOn(0x91 + c, active_Note[3], 80);
}
//------------------CLEAN UP------------------------//
//send not off messages and reset necessary things
//---STRING ONE----//
if (!channel_Mode) {
c = 0;
old_c = 0;
}
//no fret is touched and the string is marked active
if (!fret_Touched[0] && string_Active[0]) {
noteOn(0x91 + old_c, active_Note[0], 0);
string_Active[0] = false;
}
if (!fsr_Touched[c] && string_Active[0] && (attack_counter[c] < ATTACK || bow_Mode)) {
noteOn(0x91 + old_c, active_Note[0], 0);
string_Active[0] = false;
}
//---STRING TWO----//
if (!channel_Mode) {
c = 1;
old_c = 1;
}
//no fret is touched and the string is marked active
if (!fret_Touched[1] && string_Active[1]) {
noteOn(0x91 + old_c, active_Note[1], 0);
string_Active[1] = false;
}
if (!fsr_Touched[c] && string_Active[1] && (attack_counter[c] < ATTACK || bow_Mode)){
noteOn(0x91 + old_c, active_Note[1], 0);
string_Active[1] = false;
}
//---STRING THREE----//
if (!channel_Mode) {
c = 2;
old_c = 2;
}
//no fret is touched and the string is marked active
if (!fret_Touched[2] && string_Active[2]) {
noteOn(0x91 + old_c, active_Note[2], 0);
string_Active[2] = false;
}
if (!fsr_Touched[c] && string_Active[2] && (attack_counter[c] < ATTACK || bow_Mode)) {
noteOn(0x91 + old_c, active_Note[2], 0);
string_Active[2] = false;
}
//---STRING FOUR----//
if (!channel_Mode) {
c = 3;
old_c = 3;
}
//no fret is touched and the string is marked active
if (!fret_Touched[3] && string_Active[3]) {
noteOn(0x91 + old_c, active_Note[3], 0);
string_Active[3] = false;
}
if (!fsr_Touched[c] && string_Active[3] && (attack_counter[c] < ATTACK || bow_Mode)) {
noteOn(0x91 + old_c, active_Note[3], 0);
string_Active[3] = false;
}
// }
old_c = c;
//------------------READ CONTROLS-----------------//
byte is_Hit = fsr_Vals[0] + fsr_Vals[1] + fsr_Vals[2] + fsr_Vals[3];
byte any_Active = string_Active[0] + string_Active[1] + string_Active[2] + string_Active[3];
//check for control changes
byte channel_button = !digitalRead(PIN_BUTTON_CHANNEL);
byte panic_button = !digitalRead(PIN_BUTTON_PANIC);
byte fsr_button = !digitalRead(PIN_BUTTON_FSR);
button_read = (channel_button << 2) | (panic_button << 1) | fsr_button;
if (button_read){
if(button_count < (BUTTONPRESS + 2)) {
button_count = button_count + 1;
}
}else {
button_count = 0;
}
if (button_count == BUTTONPRESS) {
switch (button_read) {
case 1:
fsr_Add_Slave_Mode = !fsr_Add_Slave_Mode;
if (!fsr_Add_Slave_Mode) u8x8.drawString(7,0,"FIX");
else u8x8.drawString(7,0,"DYN");
break;
case 2:
//mute all midi, release hanging notes etc.
controllerAllChannels(123,0);
break;
case 3:
//calibrate accelerometer
break;
case 4:
channel_Mode = !channel_Mode;
if (!channel_Mode) u8x8.drawString(0,0,"MPE ");
else u8x8.drawString(0,0,"POLY");
break;
case 5:
saveSettings();
break;
case 6:
bow_Mode = !bow_Mode;
break;
}
}
//---- CHANGING THE OCTAVE -------//
//UP and down buttons to change offset/octave.
//---- UP BUTTON ----
if (digitalRead(PIN_OCTAVE_UP) == LOW) {
if (!button_States[UP]) {
if (octave < 1) octave = 1;
octave = octave - 1;
byte string_base = 12*octave + LOWEST_NOTE;
offsets[0] = string_base;
offsets[1] = string_base + 5;
offsets[2] = string_base + 10;
offsets[3] = string_base + 15;
enum {BufSize=3}; // If a is short use a smaller number, eg 5 or 6
char buf[BufSize];
snprintf (buf, BufSize, "%d", octave);
u8x8.drawString(5,50,buf);
}
button_States[UP] = true;
}
//reset state once button is no longer being pressed
if (digitalRead(PIN_OCTAVE_UP) == HIGH && button_States[UP]) button_States[UP] = false;
//----DOWN BUTTON----
if (digitalRead(PIN_OCTAVE_DOWN) == LOW) {
if (!button_States[DOWN]) {
octave = octave + 1;
if (octave > 7) octave = 7;
byte string_base = 12*octave + LOWEST_NOTE;
offsets[0] = string_base;
offsets[1] = string_base + 5;
offsets[2] = string_base + 10;
offsets[3] = string_base + 15;
enum {BufSize=3}; // If a is short use a smaller number, eg 5 or 6
char buf[BufSize];
snprintf (buf, BufSize, "%d", octave);
u8x8.drawString(5,50,buf);
}
button_States[DOWN] = true;
}
//reset state once button is no longer being pressed
if (digitalRead(PIN_OCTAVE_DOWN) == HIGH && button_States[DOWN]) button_States[DOWN] = false;
if (!is_Hit && any_Active) {
int stick_x = analogRead(PIN_JOYSTICK_X);
int stick_y = analogRead(PIN_JOYSTICK_Y);
int accel_y = analogRead(PIN_ACCEL_Y);
int accel_z = analogRead(PIN_ACCEL_Z);
int accel_x = analogRead(PIN_ACCEL_X);
int wheel = analogRead(PIN_WHEEL);
int read_Hothand_x = analogRead(PIN_HOTHAND_X);
int read_Hothand_y = analogRead(PIN_HOTHAND_Y);
accel_average_y = accel_average_y + accel_y;
accel_average_z = accel_average_z + accel_z;
accel_average_x = accel_average_x + accel_x;
wheel_average = wheel_average + wheel;
stick_average = stick_average + stick_x;
stick_average_y = stick_average_y + stick_y;
hothand_average_x = hothand_average_x + read_Hothand_x;
hothand_average_y = hothand_average_y + read_Hothand_y;
if (control_counter == CONTROL_RATE) {
stick_x = stick_average / CONTROL_RATE; //actually wrong but i did all the math later already...
stick_y = stick_average_y / CONTROL_RATE;
accel_y = accel_average_y / (CONTROL_RATE);
accel_z = accel_average_z / (CONTROL_RATE);
accel_x = accel_average_x / (CONTROL_RATE);
wheel = wheel_average / (CONTROL_RATE + 1);
read_Hothand_x = hothand_average_x / CONTROL_RATE;
read_Hothand_y = hothand_average_y / CONTROL_RATE;
stick_average = 0;
stick_average_y = 0;
accel_average_y = 0;
accel_average_z = 0;
accel_average_x = 0;
wheel_average = 0;
hothand_average_x = 0;
hothand_average_y = 0;
control_counter = 0;
//read positions from joystick center
int bend;
if (abs(stick_x - stick_Zero_X) > 70) {
is_Middle_stick_x = 0;
bend = map(stick_x, 60, 2040, -8192, 8191);
bend = constrain(bend, -8192,8191);
bend = bend;
if (abs(stick_x - stick_x_old)>1) {
usbMIDI.sendPitchBend(bend, 1);
for (int i=0; i<7; i++) {
if (i != footpedal) {
if (!channel_Mode) {
midilist[i]->sendPitchBend(bend, 2);
midilist[i]->sendPitchBend(bend, 3);
midilist[i]->sendPitchBend(bend, 4);
midilist[i]->sendPitchBend(bend, 5);
midilist[i]->send_now();
} else {
midilist[i]->sendPitchBend(bend, 2 + c + CHANNEL_OFFSET);
midilist[i]->send_now();
}
}
}
}
stick_x_old = stick_x;
} else {
if (!is_Middle_stick_x) {
usbMIDI.sendPitchBend(0, 1);
for (int i=0; i<7; i++) {
if (i != footpedal) {
if (!channel_Mode) {
midilist[i]->sendPitchBend(0, 2);
midilist[i]->sendPitchBend(0, 3);
midilist[i]->sendPitchBend(0, 4);
midilist[i]->sendPitchBend(0, 5);
midilist[i]->send_now();
} else {
midilist[i]->sendPitchBend(0, 2 + c + CHANNEL_OFFSET);
midilist[i]->send_now();
}
}
}
is_Middle_stick_x = 1;
}
}
byte yPos;
byte yPos2;
if (stick_y > (stick_Zero_Y + 4)) {
yPos2 = 0;
yPos = map(stick_y, stick_Zero_Y+4, 2020, 0, 127);
if (yPos >= 127) yPos = 127;
}
else if (stick_y < (stick_Zero_Y - 4)) {
yPos = 0;
yPos2 = map(stick_y,stick_Zero_Y - 4,20, 0, 127);
if (yPos2 >= 127) yPos2 = 127;
} else {
yPos = 0;
yPos2 = 0;
}
if (yPos - y_Pos_old) controllerChange(1, yPos);
y_Pos_old = yPos;
if (yPos2 - y_Pos2_old) controllerChange(2, yPos2);
y_Pos2_old = yPos2;
//accelerometer y
accel_y = map(accel_y,840,1168,0,127);
accel_y = constrain(accel_y,0,127);
if (accel_y - accel_y_old) controllerChange(3, accel_y);
accel_y_old = accel_y;
//accelerometer_z
accel_z = map(accel_z,800,1300,0,127);
accel_z = constrain(accel_z,0,127);
if (accel_z - accel_z_old) controllerChange(4, accel_z);
accel_z_old = accel_z;
//accelerometer x
accel_x = map(accel_x,300,1300,0,127);
accel_x = constrain(accel_x,0,127);
if (accel_x - accel_x_old) controllerChange(6, accel_x);
accel_x_old = accel_x;
//lfo wheel
//int wheel_full = wheel;
wheel = map(wheel,0,1935,0,2000);
wheel = constrain(wheel,0,2000);
wheel_counter = (wheel_counter + 1) % 40;
int wheel_midi = map_wheel[wheel%500];
wheel_array[wheel_counter] = wheel_midi;
wheel_stable = 0;
for (int i=0; i<40; i++) {
if (abs(wheel_midi - wheel_array[i]) < 4) wheel_stable = wheel_stable + 1;
}
if ((wheel_midi - wheel_old) && (wheel_stable < 39)) {
if ((wheel_midi > 10) && (wheel_old<4)) {
} else {
if (hothand_stable > 20) controllerChange(8, wheel_midi);
}
}
wheel_old = wheel_midi;
wheel_older = old_wheel;
wheel = old_wheel;
int fsr_temp_touch = fsr_Touched[0] + fsr_Touched[1] + fsr_Touched[2] + fsr_Touched[3];
// hothand...x axis sends aftertouch y axis on cc 9
if (fsr_temp_touch && sustain_mode) hothand_on = 0;
if (hothand_on > 50) {
read_Hothand_x = map(read_Hothand_x,1400,700,-310,310); //was 1200 to 900
read_Hothand_x = constrain(read_Hothand_x,-310,310);
read_Hothand_x = abs(read_Hothand_x);
//read_Hothand_x = 310-read_Hothand_x;
int hothand_midi = map_hothand[read_Hothand_x];
//"debounce" analog readings, so there is less splutter on meandring values...
hothand_counter = (hothand_counter + 1) % 40;
hothand_array[hothand_counter] = hothand_midi;
hothand_stable = 0;
for (int i=0; i<40; i++) {
if (abs(hothand_midi - hothand_array[i]) < 4) hothand_stable = hothand_stable + 2;
if (hothand_array[i] < 6) hothand_stable = hothand_stable + 1;
}
if (read_Hothand_x != hothand_x_old) {
hothand_x_old = read_Hothand_x;
if (hothand_stable < 20) controllerChange(8, hothand_midi);
}
}
read_Hothand_y = map(read_Hothand_y,1170,970,0,127);
read_Hothand_y = constrain(read_Hothand_y,0,127);
if (read_Hothand_y != hothand_y_old) {
hothand_y_old = read_Hothand_y;
controllerChange(9, read_Hothand_y);
}
} else if (control_counter < CONTROL_RATE) control_counter = control_counter + 1;
}
}
//----CALIBRATION----//
/* Likely will only have to calibrate once. This is done by activating calibration mode and
* "plucking" each note on each string starting with the upper bound (after the 24st fret) and descending down
* to just after the 1st fret. Starts with the low E string, then the A string and then the D string.
* fret definitions are stored in EEPROM. Once it is calibrated for the voltage put out by the MIDI --> USB board
* you can just have the calibration button do something else because you probably won't need it again.
*/
void calibrate() {
for (byte i=0; i<NUM_STRINGS; i++) {
switch (i) {
case 0:
u8x8.drawString(0,50,"E:");
break;
case 1:
u8x8.drawString(0,50,"A:");
break;
case 2:
u8x8.drawString(0,50,"D:");
break;
case 3:
u8x8.drawString(0,50,"G:");
break;
}
int sensorMin = 1023;
int val;
//loop through the array of fret definitions
for (byte j=24; j>0; j--) {
enum {BufSize=3}; // If a is short use a smaller number, eg 5 or 6
char buf[BufSize];
snprintf (buf, BufSize, "%d", j);
u8x8.drawString(8,50,buf);
int response = false;
int fsrHit = 0;
//wait for response
while (!response) {
//read fsr val
int fsrVal = analogRead(fsr_Pins[i])>>1;
//get the sensor min value (highest fret) on the first round
if (j==24) {
enum {BufSize=3}; // If a is short use a smaller number, eg 5 or 6
char buf[BufSize];
snprintf (buf, BufSize, "%d", j);
u8x8.drawString(8,50,buf);
int fretVal = analogRead(soft_Pot_Pins[i]);
// if (fretVal > sensorMax) (sensorMax = fretVal);
//if the fsr is hit, register this as the definition for this fret
if (fsrVal < (fsr_Init[i] - 180) && fsrHit == 0) {
int fretVal = analogRead(soft_Pot_Pins[i]);
sensorMin = fretVal;
val = fretVal;
response = true;
fsrHit = 1;
}
if (fsrVal > (fsr_Init[i] - 100) && fsrHit == 1) fsrHit = 0;
}
else {
//get the rest of the fret definitions
//if the piezo is hit, register this as the definition for this fret
if (fsrVal < (fsr_Init[i] - 180) && fsrHit == 0) {
int fretVal = analogRead(soft_Pot_Pins[i]);
fretVal = map(fretVal, sensorMin, MAXREADING, 0, 255);
if (fretVal > 255) fretVal = 255;
val = fretVal;
response = true;
fsrHit = 1;
}
if (fsrVal > (fsr_Init[i] -100) && fsrHit == 1) fsrHit = 0;
}
}
//write to memory
// digitalWrite(PIN_LED, LOW);
EEPROM.write(j + (24*i), val);
delay(100);
// digitalWrite(PIN_LED, HIGH);
}
//update global definitions
calibration_Min[i] = EEPROM.read(24 + (24*i));
for (byte j=1; j<24; j++) {
fret_Defs[i][j] = EEPROM.read(j + (i*24));
}
}
// digitalWrite(PIN_LED, LOW);
}
//write default programs to eeprom, so unused slots don't output garbage values, restore defaults
//likely will only have to write defaults once
void writeDefaults() {
for (byte i=100; i<228; i++) {
EEPROM.write(i, 2);
}
}
//-------------MIDI OUT FUNCTIONS-----------------//
//note-on (and off) message
inline void noteOn(byte cmd, byte pitch, byte velocity) {
if (channel_Mode){ cmd = cmd + CHANNEL_OFFSET;
}
//kind of mpe, starting at channel 2, channel 1 is for general modulation only
usbMIDI.sendNoteOn(pitch, velocity, cmd + 1);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendNoteOn(pitch,velocity, cmd + 1);
midilist[i]->send_now();
}
}
midilist[footpedal]->sendNoteOn(pitch,velocity,1);
}
//Sends controller change to the specified controller
inline void controllerChange(byte controller, byte value) {
//kind of mpe, channel 1 is for general modulation only
usbMIDI.sendControlChange(controller,value,1);
for (int i=0; i<7; i++) {
if (i != footpedal) {
if (channel_Mode) {
midilist[i]->sendControlChange(controller,value, 2 + CHANNEL_OFFSET + c);
midilist[i]->send_now();
} else {
midilist[i]->sendControlChange(controller,value, 2);
midilist[i]->sendControlChange(controller,value, 3);
midilist[i]->sendControlChange(controller,value, 4);
midilist[i]->sendControlChange(controller,value, 5);
midilist[i]->send_now();
}
}
}
}
inline void controllerChangeChannel(byte controller, byte value, byte channel) {
if (channel_Mode) {
usbMIDI.sendControlChange(controller,value,channel + CHANNEL_OFFSET);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendControlChange(controller,value, channel + CHANNEL_OFFSET);
midilist[i]->send_now();
}
}
} else {
usbMIDI.sendControlChange(controller,value,channel);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendControlChange(controller,value, channel);
midilist[i]->send_now();
}
}
}
}
inline void controllerAllChannels(byte controller, byte value) {
if (channel_Mode) {
usbMIDI.sendControlChange(controller,value, 2 + CHANNEL_OFFSET);
usbMIDI.sendControlChange(controller,value, 3 + CHANNEL_OFFSET);
usbMIDI.sendControlChange(controller,value, 4 + CHANNEL_OFFSET);
usbMIDI.sendControlChange(controller,value, 5 + CHANNEL_OFFSET);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendControlChange(controller,value, 2 + CHANNEL_OFFSET);
midilist[i]->sendControlChange(controller,value, 3 + CHANNEL_OFFSET);
midilist[i]->sendControlChange(controller,value, 4 + CHANNEL_OFFSET);
midilist[i]->sendControlChange(controller,value, 5 + CHANNEL_OFFSET);
midilist[i]->send_now();
}
}
} else {
usbMIDI.sendControlChange(controller,value, 2);
usbMIDI.sendControlChange(controller,value, 3);
usbMIDI.sendControlChange(controller,value, 4);
usbMIDI.sendControlChange(controller,value, 5);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendControlChange(controller,value, 2);
midilist[i]->sendControlChange(controller,value, 3);
midilist[i]->sendControlChange(controller,value, 4);
midilist[i]->sendControlChange(controller,value, 5);
midilist[i]->send_now();
}
}
}
}
inline void aftertouchChange(byte cmd, byte value) {
//kind of mpe, starting at channel 2, channel 1 is for general modulation only
usbMIDI.sendAfterTouch(value, cmd + 1);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendAfterTouch(value, cmd + 1);
midilist[i]->send_now();
}
}
}
//-------------------OTHER FUNCTIONS---------------//
//save settings to eeprom on cc SAVE_CC (slot is last received program change)
void saveSettings() {
// if (octave < 0) octave = 0;
byte settings = (channel_Mode << 7) | (full_Legato_Mode << 6) | (fsr_Add_Slave_Mode << 5) | (bow_Mode << 4) | octave;
EEPROM.write(save_Slot + 100, settings);
}
// load settings from eeprom on program change
void loadSettings(byte prgCh) {
byte settings = EEPROM.read(prgCh + 100);
if (((settings >> 7) & 1) != channel_Mode) {
if (string_Active[0]) {
if (!channel_Mode) old_c = 0;
noteOn(0x91 + old_c, active_Note[0], 0);
}
if (string_Active[1]) {
if (!channel_Mode) old_c = 1;
noteOn(0x91 + old_c, active_Note[1], 0);
}
if (string_Active[2]) {
if (!channel_Mode) old_c = 2;
noteOn(0x91 + old_c, active_Note[2], 0);
}
if (string_Active[3]) {
if (!channel_Mode) old_c = 3;
noteOn(0x91 + old_c, active_Note[3], 0);
}
c = 0;
}
channel_Mode = (settings >> 7) & 1;
full_Legato_Mode = (settings >> 6) & 1;
fsr_Add_Slave_Mode = (settings >> 5) & 1;
bow_Mode = (settings >> 4) & 1;
octave = settings & 15;
if (octave > 7) octave = 7;
byte string_base = 12*octave + LOWEST_NOTE;
offsets[0] = string_base;
offsets[1] = string_base + 5;
offsets[2] = string_base + 10;
offsets[3] = string_base + 15;
u8x8.drawString(11,50,"P:");
enum {BufSize=4};
char buf[BufSize];
snprintf (buf, BufSize, "%03d", prgCh);
u8x8.drawString(13,50,buf);
if (!channel_Mode) u8x8.drawString(0,0,"MPE ");
else u8x8.drawString(0,0,"POLY");
if (bow_Mode) u8x8.drawString(12,0,"BOW ");
else u8x8.drawString(12,0,"PIZZ");
enum {BufSize2=3}; // If a is short use a smaller number, eg 5 or 6
char buf2[BufSize2];
snprintf (buf2, BufSize2, "%d", octave);
u8x8.drawString(5,50,buf2);
if (!fsr_Add_Slave_Mode) u8x8.drawString(7,0,"FIX");
else u8x8.drawString(7,0,"DYN");
}
void sendQunexus(byte type, byte data1, byte data2, byte channel )
{
midilist[keysaxo]->send(type, data1, data2, channel);
}
void footProgramChange(byte channel, byte program) {
save_Slot = program;
loadSettings(program);
for (int i=0; i<7; i++) {
if (i != footpedal) midilist[i]->sendProgramChange(program,1);
}
}
void footControlChange(byte channel, byte control, byte value) {
switch (control) {
case 11:
case 12:
case 14:
case 15:
case 16:
midilist[keysaxo]->sendControlChange(control,value, 1);
midilist[keysaxo]->send_now();
break;
case 114:
bow_Mode = !bow_Mode;
if (bow_Mode) u8x8.drawString(12,0,"BOW ");
else u8x8.drawString(12,0,"PIZZ");
break;
case 115:
saveSettings();
u8x8.drawString(11,50,"SAVED");
break;
case 119:
if (string_Active[0]) {
if (!channel_Mode) old_c = 0;
noteOn(0x91 + old_c, active_Note[0], 0);
}
if (string_Active[1]) {
if (!channel_Mode) old_c = 1;
noteOn(0x91 + old_c, active_Note[1], 0);
}
if (string_Active[2]) {
if (!channel_Mode) old_c = 2;
noteOn(0x91 + old_c, active_Note[2], 0);
}
if (string_Active[3]) {
if (!channel_Mode) old_c = 3;
noteOn(0x91 + old_c, active_Note[3], 0);
}
c = 0;
channel_Mode = !channel_Mode;
if (!channel_Mode) u8x8.drawString(0,0,"MPE ");
else u8x8.drawString(0,0,"POLY");
break;
case 123:
controllerAllChannels(123,0);
break;
case 124:
if (value) sustain_mode = 0;
else sustain_mode = 1;
}
}
void footNoteOn(byte channel, byte note, byte velocity) {
usbMIDI.sendNoteOn(note, velocity, channel);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendNoteOn(note,velocity, channel);
midilist[i]->send_now();
}
}
}
void footNoteOff(byte channel, byte note, byte velocity) {
usbMIDI.sendNoteOn(note, 0, channel);
for (int i=0; i<7; i++) {
if (i != footpedal) {
midilist[i]->sendNoteOn(note,0, channel);
midilist[i]->send_now();
}
}
}