/*
Coagula MIDI Ribbon controller 2.0
Copyright Giuseppe Di Cillo (www.coagula.org)
Contact: dicillo@coagula.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
void toRoot() {
setCurrent( &getRoot() );
}
*/
#include
#include
#include
#include
const int sensorPosition = A0; // pin that's connected to position sensor
const int sensorForce = A1; // pin that's connected to force sensor
const int buttonPinUp = 8; // pin for the Up button
const int buttonPinDown = 9; // pin for the Down button
const int buttonPinEsc = 10; // pin for the Esc button
const int buttonPinEnter = 11; // pin for the Enter button
const int securityRange=5; //value used to avoid glitch in note sending mode
const int addrSensorForceMin=1; //address in EEPROM to store Force Sensor minimum value
const int addrSensorForceMax=2; //address in EEPROM to store Force Sensor maximum value
const int addrSensorPosCC=3; //address in EEPROM to store Position Sensor CC
const int addrSensorForceCC=4; //address in EEPROM to store Force Sensor CC
const int addrMinNote=5; //address in EEPROM to store minimum note
const int addrMaxNote=6; //address in EEPROM to store maximum note
const int addrMidiChannel=7; //address in EEPROM to store midi channel
const int addrPlayMode=8; //address in EEPROM to store the play mode
//constants to identify different status
const int statusPlayMode1=1;
const int statusPlayMode2=2;
const int statusPlayMode3=3; //to be implemented
const int statusPlayMode4=4; //to be implemented
const int statusSetCCPosition=5;
const int statusSetCCForce=6;
const int statusSetMinNote=7;
const int statusSetMaxNote=8;
const int statusMidiTeach=9;
const int statusSetMidiChannel=10;
int midiChannel;
char strMenu[21] = " MENU ";
char strMenuMidi[21] = " MIDI SETUP MENU ";
char strMenuModes[21] = " MODES SETUP MENU ";
char strSetMinimumNote[21] = "Set minimum note ";
char strSetMaximumNote[21] = "Set maximum note ";
char strSetPositionCC[21] = "Set position CC";
char strSetForceCC[21] = "Set force CC ";
char strSetMidiChannel[21] = "Set MIDI channel ";
int lastButtonPushed = 0;
int lastButtonEnterState = LOW; // the previous reading from the Enter input pin
int lastButtonEscState = LOW; // the previous reading from the input pin
int lastButtonUpState = LOW; // the previous reading from the input pin
int lastButtonDownState = LOW; // the previous reading from the input pin
// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastEnterDebounceTime = 0; // the last time the output pin was toggled
long lastEscDebounceTime = 0; // the last time the output pin was toggled
long lastUpDebounceTime = 0; // the last time the output pin was toggled
long lastDownDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 500; // the debounce time; increase if the output flickers
// LiquidCrystal display with:
// rs on pin 2
// rw on pin 3
// d4, d5, d6, d7 on pins 4, 5, 6, 7
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int currentStatusMode;
int lastPlayingMode;
int ccPosition;
int ccForce;
int minNote=80;
int maxNote=100;
int noteVelocity=100;
int ccPositionSetting;
int ccForceSetting;
int minNoteSetting;
int maxNoteSetting;
int midiChannelSetting;
int sensorForceValue = 0; // the force sensor value
int sensorPositionValue = 0; // the position sensor value
int sensorForceMinValue; // minimum sensor value
int sensorForceMaxValue; // maximum sensor value
int sensorPositionMinValue=0; // minimum sensor value
int sensorPositionMaxValue=1023; // maximum sensor value
int sensorPositionLastValue=0;
int lastNote = 0;
int sensorForceRawValue = 0; // the force sensor value
int sensorPositionRawValue = 0; // the position sensor value
int sensorForcePreviousValue=-1;
int sensorPositionPreviousValue=-1;
//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem menuModesSetup = MenuItem("menuModesSetup");
MenuItem menuItemMode1 = MenuItem("menuItemMode1");
MenuItem menuItemMode2 = MenuItem("menuItemMode2");
MenuItem menuItemMidiSetup = MenuItem("menuItemMidiSetup");
MenuItem menuItemCCPosition = MenuItem("menuItemCCPosition");
MenuItem menuItemCCForce = MenuItem("menuItemCCForce");
MenuItem menuItemMinNote = MenuItem("menuItemMinNote");
MenuItem menuItemMaxNote = MenuItem("menuItemMaxNote");
MenuItem menuItemMidiChannel = MenuItem("menuItemMidiChannel");
MenuItem menuItemMidiTeach = MenuItem("menuItemMidiTeach");
MenuItem menuCalibration = MenuItem("menuCalibration");
void setup()
{
pinMode(sensorForce, INPUT);
pinMode(sensorPosition, INPUT);
pinMode(buttonPinUp, INPUT);
pinMode(buttonPinDown, INPUT);
pinMode(buttonPinEnter, INPUT);
pinMode(buttonPinEsc, INPUT);
lcd.begin(20, 4); //initialize lcd
int pressed=LOW;
while (millis()<2000 && pressed==LOW){
lcd.setCursor(0,0);
lcd.print("Push enter to");
lcd.setCursor(0,1);
lcd.print("reset controller");
pressed =digitalRead(buttonPinEnter);
}
sensorForceMinValue=EEPROM.read(addrSensorForceMin); //read fromm EEPROM the stored minimum force sensor value
if (sensorForceMinValue==255||pressed==HIGH){ //if settings are not stored or Enter has been pressed during startup reset defaults and start calibration
calibration();
ccPosition=20;//default
ccForce=21;//default
minNote=80;//default
maxNote=100;//default
midiChannel=1;//default
currentStatusMode=statusPlayMode1;//default
EEPROM.write(addrSensorPosCC, ccPosition);
EEPROM.write(addrSensorForceCC, ccForce);
EEPROM.write(addrMinNote, minNote);
EEPROM.write(addrMaxNote, maxNote);
EEPROM.write(addrMidiChannel, midiChannel);
EEPROM.write(addrPlayMode, currentStatusMode);
}else{
sensorForceMinValue=sensorForceMinValue*4;
sensorForceMaxValue=(EEPROM.read(addrSensorForceMax))*4;
ccPosition=EEPROM.read(addrSensorPosCC); //read fromm EEPROM the stored force sensor CC value
ccForce=EEPROM.read(addrSensorForceCC); //read fromm EEPROM the stored force sensor CC value
minNote=EEPROM.read(addrMinNote); //read fromm EEPROM the stored minimum note
maxNote=EEPROM.read(addrMaxNote); //read fromm EEPROM the stored maximum note
midiChannel=EEPROM.read(addrMidiChannel); //read fromm EEPROM the stored midi channel
currentStatusMode=EEPROM.read(addrPlayMode); //read fromm EEPROM the stored play mode
}
MIDI.begin(midiChannel); //initialize MIDI
//menu configuration
menu.getRoot().addRight(menuModesSetup).add(menuItemMidiSetup).add(menuCalibration);
menuModesSetup.addRight(menuItemMode1).add(menuItemMode2);
menuItemMidiSetup.addRight(menuItemCCPosition).add(menuItemCCForce).add(menuItemMinNote).add(menuItemMaxNote).add(menuItemMidiChannel).add(menuItemMidiTeach);
menu.toRoot();
} // setup()...
void loop()
{
readButtons(); //read buttons status
char strSetting[21] = "CC ";
char sett[4];
switch(currentStatusMode){
case statusPlayMode1: //playing mode 1
navigateMenus(); //Navigate menus
// sensors reading:
sensorPositionRawValue = analogRead(sensorPosition);
// if starts the touch. I added 10 to the minum just to avoid sensor little variations
if (sensorPositionRawValue>(sensorPositionMinValue+10)){
delay(5); //this delay is really important to let the position sensor settle its resistance
sensorPositionRawValue = analogRead(sensorPosition); //read the settled sensor position
sensorPositionValue = map(sensorPositionRawValue, sensorPositionMinValue, sensorPositionMaxValue, minNote, maxNote);// apply the calibration to the position sensor reading
sensorPositionValue = constrain(sensorPositionValue, minNote, maxNote); // in case the position sensor value is outside the range seen during calibration
sensorForceRawValue = analogRead(sensorForce);
sensorForceValue = map(sensorForceRawValue, sensorForceMinValue + 200, sensorForceMaxValue, 0, 127); // apply the calibration to force sensor reading
sensorForceValue = constrain(sensorForceValue, 0, 127); // in case the position sensor value is outside the range seen during calibration
MIDI.sendNoteOn(sensorPositionValue,noteVelocity,midiChannel); // Send a Note (pitch based on position, fixed velocity)
MIDI.sendControlChange(ccForce, sensorForceValue, midiChannel); // send midi control change defined by force sensor
lastNote=sensorPositionValue; // register the played note in order to stop it later
lcd.setCursor(0,1);
lcd.print("Sending Data ");
do{
sensorForceRawValue = analogRead(sensorForce);
sensorPositionRawValue = analogRead(sensorPosition);
sensorPositionLastValue=sensorPositionRawValue; //records the position sensor value before processing in order to use it later for the loop condition
sensorForceValue = map(sensorForceRawValue, sensorForceMinValue, sensorForceMaxValue, 0, 127); // apply the calibration to force sensor reading
sensorForceValue = constrain(sensorForceValue, 0, 127); // in case the position sensor value is outside the range seen during calibration
if (sensorPositionRawValue>(sensorPositionMinValue)){
if ((sensorPositionRawValue<(sensorPositionPreviousValue-securityRange))||(sensorPositionRawValue>(sensorPositionPreviousValue+securityRange))){ //ignores little variations
sensorPositionPreviousValue = sensorPositionRawValue; //records input value to check little variations at next do
sensorPositionValue = map(sensorPositionRawValue, sensorPositionMinValue, sensorPositionMaxValue,minNote, maxNote);// apply the calibration to the position sensor reading
sensorPositionValue = constrain(sensorPositionValue, minNote, maxNote);// in case the position sensor value is outside the range seen during calibration
if (sensorPositionValue!=lastNote){ //if changed
MIDI.sendNoteOff(lastNote,0,midiChannel); // Stop the note
MIDI.sendNoteOn(sensorPositionValue,100,midiChannel); // Send a Note (pitch 42, velo 127 on channel 1)
lastNote=sensorPositionValue; // register the played note in order to stop it later
}
}
if((sensorForceValue!=sensorForcePreviousValue)&&(sensorForceRawValue>(sensorForceMinValue+securityRange))){
sensorForcePreviousValue=sensorForceValue;
MIDI.sendControlChange(ccForce, sensorForceValue, midiChannel);// send midi control change defined by force sensor
}
}
}while(sensorPositionLastValue>(sensorPositionMinValue+10)); //loops till the sensor is pressed
MIDI.sendNoteOff(lastNote,0,midiChannel); // Stop the note
lcd.setCursor(0,1);
lcd.print(" ");
}
break;
case statusPlayMode2: //playing mode 2
navigateMenus();//Navigate menus
sensorPositionRawValue = analogRead(sensorPosition);// position sensor reading:
if (sensorPositionRawValue>(sensorPositionMinValue+10)){ // if starts the touch. I added 20 to hte minum just to avoid sensor little variations
delay(5); //this delay is really important to let the position sensor settle its resistance
sensorPositionRawValue = analogRead(sensorPosition); //read the settled sensor position
sensorPositionValue = map(sensorPositionRawValue, sensorPositionMinValue, sensorPositionMaxValue, minNote, maxNote);// apply the calibration to the position sensor reading and calculates the corrisponding value for midi command
sensorPositionValue = constrain(sensorPositionValue, minNote, maxNote);// in case the position sensor value is outside the range seen during calibration
MIDI.sendNoteOn(sensorPositionValue,noteVelocity,midiChannel); // Send a Note
lastNote=sensorPositionValue;// register the played note in order to stop it later
lcd.setCursor(0,1);
lcd.print("Sending Data ");
do{
sensorForceRawValue = analogRead(sensorForce);
sensorPositionRawValue = analogRead(sensorPosition);
sensorPositionLastValue=sensorPositionRawValue;//registers the position sensor value before processing in order to use it later for the loop condition
sensorForceValue = map(sensorForceRawValue, sensorForceMinValue, sensorForceMaxValue, 0, 127);// apply the calibration to force sensor reading
sensorForceValue = constrain(sensorForceValue, 0, 127);// in case the position sensor value is outside the range seen during calibration
if (sensorPositionRawValue>(sensorPositionMinValue)){
sensorPositionValue = map(sensorPositionRawValue, sensorPositionMinValue, sensorPositionMaxValue,minNote, maxNote);// apply the calibration to the position sensor reading
sensorPositionValue = constrain(sensorPositionValue, minNote, maxNote); // in case the position sensor value is outside the range seen during calibration
MIDI.sendControlChange(ccPosition, sensorPositionValue, midiChannel);// send midi control change defined by position sensor
MIDI.sendControlChange(ccForce, sensorForceValue, midiChannel);// send midi control change defined by force sensor
}
}while(sensorPositionLastValue>(sensorPositionMinValue+10)); //loops till the sensor is pressed
MIDI.sendNoteOff(lastNote,0,midiChannel); // Stop the note
lcd.setCursor(0,1);
lcd.print(" ");
}
break;
case statusSetCCPosition: //setting position cc
switch (lastButtonPushed){
case buttonPinEnter: //set the new position cc and go back to the main screen
ccPosition=ccPositionSetting;
currentStatusMode=lastPlayingMode;
EEPROM.write(addrSensorPosCC, ccPosition);
menu.toRoot();
break;
case buttonPinEsc: //go back to the main screen
ccPositionSetting=ccPosition;
currentStatusMode=lastPlayingMode;
menu.toRoot();
break;
case buttonPinUp: //increase position cc
if(ccPositionSetting<127){
ccPositionSetting=ccPositionSetting+1;
itoa(ccPositionSetting, sett, 10); //conversion needed to concatenate the value to a string in order to print it on lcd
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetPositionCC);
lcd.setCursor(0,1);
lcd.print(strcat(strSetting, sett));
}
break;
case buttonPinDown://decrease position cc
if(ccPositionSetting>0){
ccPositionSetting=ccPositionSetting-1;
itoa(ccPositionSetting, sett, 10);//conversion needed to concatenate the value to a string in order to print it on lcd
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetPositionCC);
lcd.setCursor(0,1);
lcd.print(strcat(strSetting, sett));
}
break;
}
break;
case statusSetCCForce: //set force cc
switch (lastButtonPushed){
case buttonPinEnter://set the new force cc and go back to the main screen
ccForce=ccForceSetting;
currentStatusMode=lastPlayingMode;
EEPROM.write(addrSensorForceCC, ccForce);
menu.toRoot();
break;
case buttonPinEsc://go back to the main screen
ccForceSetting=ccForce;
currentStatusMode=lastPlayingMode;
menu.toRoot();
break;
case buttonPinUp://increase force cc
if(ccForceSetting<127){
ccForceSetting=ccForceSetting+1;
itoa(ccForceSetting, sett, 10); //conversion needed to concatenate the value to a string in order to print it on lcd
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetForceCC);
lcd.setCursor(0,1);
lcd.print(strcat(strSetting, sett));
}
break;
case buttonPinDown://decrease force cc
if(ccForceSetting>0){
ccForceSetting=ccForceSetting-1;
itoa(ccForceSetting, sett, 10);//conversion needed to concatenate the value to a string in order to print it on lcd
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetForceCC);
lcd.setCursor(0,1);
lcd.print(strcat(strSetting, sett));
}
break;
}
break;
case statusSetMinNote: //set min note
switch (lastButtonPushed){
case buttonPinEnter://set the new minimum note and go back to the main screen
minNote=minNoteSetting;
currentStatusMode=lastPlayingMode;
EEPROM.write(addrMinNote, minNote);
menu.toRoot();
break;
case buttonPinEsc://go back to the main screen
minNoteSetting=minNote;
currentStatusMode=lastPlayingMode;
menu.toRoot();
break;
case buttonPinUp://increase minimum note
if(minNoteSetting<127){
minNoteSetting=minNoteSetting+1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMinimumNote);
lcd.setCursor(0,1);
lcd.print(minNoteSetting);
}
break;
case buttonPinDown://decrease minimum note
if(minNoteSetting>0){
minNoteSetting=minNoteSetting-1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMinimumNote);
lcd.setCursor(0,1);
lcd.print(minNoteSetting);
}
break;
}
break;
case statusSetMaxNote: //set max note
switch (lastButtonPushed){
case buttonPinEnter://set the new maximum note and go back to the main screen
maxNote=maxNoteSetting;
currentStatusMode=lastPlayingMode;
EEPROM.write(addrMaxNote, maxNote);
menu.toRoot();
break;
case buttonPinEsc://go back to the main screen
maxNoteSetting=maxNote;
currentStatusMode=lastPlayingMode;
menu.toRoot();
break;
case buttonPinUp://increase maximum note
if(maxNoteSetting<127){
maxNoteSetting=maxNoteSetting+1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMaximumNote);
lcd.setCursor(0,1);
lcd.print(maxNoteSetting);
}
break;
case buttonPinDown://decrease maximum note
if(maxNoteSetting>0){
maxNoteSetting=maxNoteSetting-1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMaximumNote);
lcd.setCursor(0,1);
lcd.print(maxNoteSetting);
}
break;
}
break;
case statusSetMidiChannel: //set midi channel
switch (lastButtonPushed){
case buttonPinEnter://set the new midi channel and go back to the main screen
midiChannel=midiChannelSetting;
currentStatusMode=lastPlayingMode;
EEPROM.write(addrMidiChannel, midiChannel);
menu.toRoot();
break;
case buttonPinEsc://go back to the main screen
midiChannelSetting=midiChannel;
currentStatusMode=lastPlayingMode;
menu.toRoot();
break;
case buttonPinUp://increase maximum note
if(midiChannelSetting<16){
midiChannelSetting=midiChannelSetting+1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMidiChannel);
lcd.setCursor(0,1);
lcd.print(midiChannelSetting);
}
break;
case buttonPinDown://decrease maximum note
if(midiChannelSetting>1){
midiChannelSetting=midiChannelSetting-1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMidiChannel);
lcd.setCursor(0,1);
lcd.print(midiChannelSetting);
}
break;
}
break;
case statusMidiTeach: //midi teach
switch (lastButtonPushed){
case buttonPinEsc://go back to the main screen
currentStatusMode=lastPlayingMode;
menu.toRoot();
break;
case buttonPinDown://send two control change command for force cc
MIDI.sendControlChange(ccForce, 64, 1);
MIDI.sendControlChange(ccForce, 65, 1);
break;
case buttonPinUp://send two control change command for position cc
MIDI.sendControlChange(ccPosition, 64, 1);
MIDI.sendControlChange(ccPosition, 65, 1);
break;
}
break;
}
} //loop()...
void menuChanged(MenuChangeEvent changed){ //change text on lcd display while navigating
MenuItem newMenuItem=changed.to;
lcd.setCursor(0,0);
if(newMenuItem.getName()==menu.getRoot()){
char modeNumber[2];
itoa(currentStatusMode, modeNumber, 10);//conversion needed to concatenate the value to a string in order to print it on lcd
char strPlaying[17] = "PLAYING MODE: ";
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strcat(strPlaying, modeNumber));
lcd.setCursor(0,3);
lcd.print("www.coagula.org ");
} else if(newMenuItem.getName()== "menuModesSetup" ){
lcd.print(strMenu);
lcd.setCursor(0,1);
lcd.print("Modes Setup <--");
lcd.setCursor(0,2);
lcd.print("MIDI Setup ");
lcd.setCursor(0,3);
lcd.print("Calibration ");
}else if(newMenuItem.getName()== "menuItemMidiSetup" ){
lcd.print(strMenu);
lcd.setCursor(0,1);
lcd.print("Modes Setup ");
lcd.setCursor(0,2);
lcd.print("MIDI Setup <--");
lcd.setCursor(0,3);
lcd.print("Calibration ");
}else if(newMenuItem.getName()== "menuCalibration" ){
lcd.print(strMenu);
lcd.setCursor(0,1);
lcd.print("Modes Setup ");
lcd.setCursor(0,2);
lcd.print("MIDI Setup ");
lcd.setCursor(0,3);
lcd.print("Calibration <--");
}else if( newMenuItem.getName() == "menuItemMode1" ){
lcd.print(strMenuModes);
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,2);
lcd.print("Mode 1 <--");
lcd.setCursor(0,3);
lcd.print("Mode 2 ");
}else if( newMenuItem.getName() == "menuItemMode2" ){
lcd.print(strMenuModes);
lcd.setCursor(0,1);
lcd.print("Mode 1 ");
lcd.setCursor(0,2);
lcd.print("Mode 2 <--");
lcd.setCursor(0,3);
lcd.print(" ");
}else if( newMenuItem.getName() == "menuItemCCPosition" ){
lcd.print(strMenuMidi);
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,2);
lcd.print("Set position CC <--");
lcd.setCursor(0,3);
lcd.print(strSetForceCC);
}else if( newMenuItem.getName() == "menuItemCCForce" ){
lcd.print(strMenuMidi);
lcd.setCursor(0,1);
lcd.print(strSetPositionCC);
lcd.setCursor(0,2);
lcd.print("Set force CC <--");
lcd.setCursor(0,3);
lcd.print(strSetMinimumNote);
}else if( newMenuItem.getName() == "menuItemMinNote" ){
lcd.print(strMenuMidi);
lcd.setCursor(0,1);
lcd.print(strSetForceCC);
lcd.setCursor(0,2);
lcd.print("Set minimum note <--");
lcd.setCursor(0,3);
lcd.print(strSetMaximumNote);
}else if( newMenuItem.getName() == "menuItemMaxNote" ){
lcd.print(strMenuMidi);
lcd.setCursor(0,1);
lcd.print(strSetMinimumNote);
lcd.setCursor(0,2);
lcd.print("Set maximum note <--");
lcd.setCursor(0,3);
lcd.print(strSetMidiChannel);
}else if( newMenuItem.getName() == "menuItemMidiChannel" ){
lcd.print(strMenuMidi);
lcd.setCursor(0,1);
lcd.print(strSetMaximumNote);
lcd.setCursor(0,2);
lcd.print("Set MIDI channel <--");
lcd.setCursor(0,3);
lcd.print("MIDI teach ");
}else if( newMenuItem.getName() == "menuItemMidiTeach" ){
lcd.print(strMenuMidi);
lcd.setCursor(0,1);
lcd.print(strSetMidiChannel);
lcd.setCursor(0,2);
lcd.print("MIDI teach <--");
lcd.setCursor(0,3);
lcd.print(" ");
}
}
void menuUsed(MenuUseEvent used){ //change status based on menu item used, or make some action
if( used.item == menuItemMode1 ){
currentStatusMode = statusPlayMode1;
EEPROM.write(addrPlayMode, statusPlayMode1);
menu.toRoot();
}else if( used.item == menuItemMode2 ){
currentStatusMode = statusPlayMode2;
EEPROM.write(addrPlayMode, statusPlayMode2);
menu.toRoot();
}else if(used.item == menuItemCCPosition){
ccPositionSetting=ccPosition;
lastPlayingMode=currentStatusMode;
currentStatusMode = statusSetCCPosition;
char ccPos[4];
itoa(ccPositionSetting, ccPos, 10);//conversion needed to concatenate the value to a string in order to print it on lcd
char strCcPos[17] = "CC ";
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetPositionCC);
lcd.setCursor(0,1);
lcd.print(strcat(strCcPos, ccPos));
}else if( used.item == menuItemCCForce ){
ccForceSetting=ccForce;
lastPlayingMode=currentStatusMode;
currentStatusMode = statusSetCCForce;
char ccPress[4];
itoa(ccForceSetting, ccPress, 10);//conversion needed to concatenate the value to a string in order to print it on lcd
char strCcPress[17] = "CC ";
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetForceCC);
lcd.setCursor(0,1);
lcd.print(strcat(strCcPress, ccPress));
}else if( used.item == menuItemMinNote ){
minNoteSetting=minNote;
lastPlayingMode=currentStatusMode;
currentStatusMode = statusSetMinNote;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMinimumNote);
lcd.setCursor(0,1);
lcd.print(minNote);
}else if( used.item == menuItemMaxNote ){
maxNoteSetting=maxNote;
lastPlayingMode=currentStatusMode;
currentStatusMode = statusSetMaxNote;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMaximumNote);
lcd.setCursor(0,1);
lcd.print(maxNote);
}else if( used.item == menuItemMidiChannel ){
midiChannelSetting=midiChannel;
lastPlayingMode=currentStatusMode;
currentStatusMode = statusSetMidiChannel;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(strSetMidiChannel);
lcd.setCursor(0,1);
lcd.print(midiChannelSetting);
}else if( used.item == menuItemMidiTeach ){
lastPlayingMode=currentStatusMode;
currentStatusMode = statusMidiTeach;
lcd.setCursor(0,0);
lcd.print("MIDI TEACH MODE ");
lcd.setCursor(0,1);
lcd.print("Up: send position CC");
lcd.setCursor(0,2);
lcd.print("Down: send force CC ");
}else if( used.item == menuCalibration ){
calibration();
menu.toRoot();
}
}
void readButtons(){ //read buttons status
int reading;
int buttonEnterState=LOW; // the current reading from the Enter input pin
int buttonEscState=LOW; // the current reading from the input pin
int buttonUpState=LOW; // the current reading from the input pin
int buttonDownState=LOW; // the current reading from the input pin
//Enter button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinEnter);
// check to see if you just pressed the enter button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonEnterState) {
// reset the debouncing timer
lastEnterDebounceTime = millis();
}
if ((millis() - lastEnterDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonEnterState=reading;
lastEnterDebounceTime=millis();
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonEnterState = reading;
//Esc button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinEsc);
// check to see if you just pressed the Down button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonEscState) {
// reset the debouncing timer
lastEscDebounceTime = millis();
}
if ((millis() - lastEscDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonEscState = reading;
lastEscDebounceTime=millis();
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonEscState = reading;
//Down button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinDown);
// check to see if you just pressed the Down button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonDownState) {
// reset the debouncing timer
lastDownDebounceTime = millis();
}
if ((millis() - lastDownDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonDownState = reading;
lastDownDebounceTime =millis();
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonDownState = reading;
//Up button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinUp);
// check to see if you just pressed the Down button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonUpState) {
// reset the debouncing timer
lastUpDebounceTime = millis();
}
if ((millis() - lastUpDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonUpState = reading;
lastUpDebounceTime=millis();;
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonUpState = reading;
//records which button has been pushed
if (buttonEnterState==HIGH){
lastButtonPushed=buttonPinEnter;
}else if(buttonEscState==HIGH){
lastButtonPushed=buttonPinEsc;
}else if(buttonDownState==HIGH){
lastButtonPushed=buttonPinDown;
}else if(buttonUpState==HIGH){
lastButtonPushed=buttonPinUp;
}else{
lastButtonPushed=0;
}
}
void navigateMenus() {
MenuItem currentMenu=menu.getCurrent();
switch (lastButtonPushed){
case buttonPinEnter:
if(!(currentMenu.moveRight())){
menu.use();
}else{
menu.moveRight();
}
break;
case buttonPinEsc:
menu.toRoot();
break;
case buttonPinDown:
menu.moveDown();
break;
case buttonPinUp:
menu.moveUp();
break;
}
lastButtonPushed=0; //reset the lastButtonPushed variable
}
void calibration(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" CALIBRATION ");
lcd.setCursor(0,1);
lcd.print("Please, push ribbon ");
lcd.setCursor(0,2);
lcd.print("controller with the ");
lcd.setCursor(0,3);
lcd.print("max useful force! ");
int startTime;
int whileTime;
startTime=millis();
whileTime=0;
sensorForceMinValue=1023;
sensorForceMaxValue=0;
while (whileTime < 5000) {
sensorForceValue = analogRead(sensorForce);
// record the maximum force sensor value
if (sensorForceValue > sensorForceMaxValue) {
sensorForceMaxValue = sensorForceValue;
}
// record the minimum force sensor value
if (sensorForceValue < sensorForceMinValue) {
sensorForceMinValue = sensorForceValue;
}
whileTime=millis()-startTime;
}
int sensorForceNewMinValue=sensorForceMinValue/4;
int sensorForceNewMaxValue=sensorForceMaxValue/4;
EEPROM.write(addrSensorForceMin, sensorForceNewMinValue);
EEPROM.write(addrSensorForceMax, sensorForceNewMaxValue);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" CALIBRATION ");
lcd.setCursor(0,1);
lcd.print("Calibration ended! ");
delay(1000); //delay to read ended calibration message
}