// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h> // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!
// SET THESE SIX VALUES FOR JOYSTICK!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int modPin2 = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down
// SET THESE VALUES FOR RIBBON
//const int ribbonPin = touch_pressed; // Max reading on right side... as raw 10-bit value
const int ribbonMaxRaw = 474; // Max reading on right side... as raw 10-bit value
//
int Button1 = 0; //This is the default "Button Off" and 1 is "Button On"
int Button2 = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton1 = 0; //Variable to store button1 old value
int OldButton2 = 0; //Variable to store button2 old value
byte data1On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data1Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
byte data2On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data2Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int mod2;
int pitchRaw;
int modRaw;
int modRaw2;
int pitchLag;
int modLag;
int modLag2;
int ribbon;
int ribbonRaw;
int ribbonLag;
int pcrec;
int pcold;
int pcnew;
int sw1recd1 = 0;
int sw1recd2 = 0;
int sw1oldd1 = 0;
int sw1oldd2 = 0;
int sw1newd1 = 0;
int sw1newd2 = 0;
int sw2recd1 = 0;
int sw2recd2 = 0;
int sw2oldd1 = 0;
int sw2oldd2 = 0;
int sw2newd1 = 0;
int sw2newd2 = 0;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;
elapsedMillis modUpdate2;
elapsedMillis ribbonUpdate;
// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};
ResponsiveAnalogRead readMod2 = {modPin2, true};
#include <Adafruit_GFX.h> // Core graphics library
#define LCD_ROTATION 1 //should work in all rotations
#define USE_READID 0 //Adafruit and ILI9488 can't read ID
//#include <MCUFRIEND_kbv.h> // Hardware-specific library
//MCUFRIEND_kbv tft;
//#include <Adafruit_ILI9341.h> // Hardware-specific library
//Adafruit_ILI9341 tft(10, 9, 8);
//#include <HX8347D_kbv.h> // Hardware-specific library
//HX8347D_kbv tft;
#include <ILI9488.h> // Hardware-specific library
ILI9488 tft(10, 9, 8);
//#include <ILI9488_kbv.h> // Hardware-specific library
//ILI9488_kbv tft;
extern void Touch_initialise(int aspect, int wid, int ht);
extern bool Touch_getXY(void);
bool touch_pressed;
int pixel_x, pixel_y;
boolean SW1on = false;
boolean SW2on = false;
boolean ribbonCtrl = false;
// Color definitions
#define TFT_BLACK 0x0000 /* 0, 0, 0 */
#define TFT_NAVY 0x000F /* 0, 0, 128 */
#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */
#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */
#define TFT_MAROON 0x7800 /* 128, 0, 0 */
#define TFT_PURPLE 0x780F /* 128, 0, 128 */
#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */
#define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */
#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */
#define TFT_BLUE 0x001F /* 0, 0, 255 */
#define TFT_GREEN 0x07E0 /* 0, 255, 0 */
#define TFT_CYAN 0x07FF /* 0, 255, 255 */
#define TFT_RED 0xF800 /* 255, 0, 0 */
#define TFT_RED2 0xF88D /* 254, 18, 106 */
#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */
#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */
#define TFT_WHITE 0xFFFF /* 255, 255, 255 */
#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */
#define TFT_ORANGE2 0xFB20 /* 254, 102, 1 */
#define TFT_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define TFT_PINK 0xF81F
/******************* UI details */
#define SW1FRAME_X 90
#define SW1FRAME_Y 110
#define SW1FRAME_W 130
#define SW1FRAME_H 70
#define SW1BUTTON_X SW1FRAME_X
#define SW1BUTTON_Y SW1FRAME_Y
#define SW1BUTTON_W SW1FRAME_W
#define SW1BUTTON_H SW1FRAME_H
#define SW2FRAME_X 310
#define SW2FRAME_Y 110
#define SW2FRAME_W 130
#define SW2FRAME_H 70
#define SW2BUTTON_X SW2FRAME_X
#define SW2BUTTON_Y SW2FRAME_Y
#define SW2BUTTON_W SW2FRAME_W
#define SW2BUTTON_H SW2FRAME_H
#define RIBBONFRAME_X 10
#define RIBBONFRAME_Y 240
#define RIBBONFRAME_W 470
#define RIBBONFRAME_H 70
#define RIBBON_X RIBBONFRAME_X
#define RIBBON_Y RIBBONFRAME_Y
#define RIBBON_W RIBBONFRAME_W
#define RIBBON_H RIBBONFRAME_H
void sw1Btn()
{
tft.drawRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_RED);
tft.setCursor(160, 140);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.println("SW1");
SW1on = false;
}
void sw2Btn()
{
tft.drawRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_RED);
tft.setCursor(340,140);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.println("SW2");
SW2on = false;
}
void rbCtrl()
{
tft.drawRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
tft.fillRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
tft.setCursor(10,240);
//remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
ribbon = map(pixel_x, 11, 474, 0, 127);
//ribbon = max(ribbon, 0); // need this now that the bottom isn't zero
// ribbon = min(ribbon, 127); // cap to avoid overflow
// if (abs(ribbon - ribbonLag) > 0 && ribbonUpdate > MIDIdelay ) {
// ribbonLag = ribbon;
usbMIDI.sendControlChange(16, ribbon, channel);
// ribbonUpdate = 0;
// }
ribbonCtrl = false;
}
void setup(void)
{
Serial.begin(9600);
Serial.println(F("TFT LCD test"));
tft.begin();
int aspect = LCD_ROTATION; //PORTRAIT
tft.setRotation(aspect);
Touch_initialise(aspect, tft.width(), tft.height()); //.kbv external function
tft.fillScreen(TFT_BLACK);
// create 'SW1 Switch'
tft.drawRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_RED);
tft.setCursor(155, 140);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
tft.print("SW1");
// create 'SW2 Switch'
tft.drawRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_RED);
tft.setCursor(340, 140);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
tft.print("SW2");
// create 'Ribbon Emulator field'
tft.drawRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_DARKGREY);
tft.fillRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
}
unsigned long t=0;
void loop(void)
{
int type, note, velocity, channel, d1, d2;
if (usbMIDI.read()) { // Is there a MIDI message incoming ?
byte type = usbMIDI.getType();
switch (type) {
case usbMIDI.NoteOn:
note = usbMIDI.getData1();
velocity = usbMIDI.getData2();
channel = usbMIDI.getChannel();
if (velocity > 0) {
Serial.println(String("Note On: ch=") + channel + ", note=" + note + ", velocity=" + velocity);
} else {
Serial.println(String("Note Off: ch=") + channel + ", note=" + note);
}
break;
case usbMIDI.NoteOff:
note = usbMIDI.getData1();
velocity = usbMIDI.getData2();
channel = usbMIDI.getChannel();
Serial.println(String("Note Off: ch=") + channel + ", note=" + note + ", velocity=" + velocity);
break;
default:
d1 = usbMIDI.getData1();
d2 = usbMIDI.getData2();
Serial.println(String("Message, type=") + type + ", data = " + d1 + " " + d2);
}
t = millis();
}
if (millis() - t > 10000) {
t += 10000;
Serial.println("(inactivity)");
}
//usbMIDI.read();
//if (usbMIDI.getType() == 0xB0) {//check for CC
//const byte korgdata1 = usbMIDI.getData1();
//const byte korgdata2 = usbMIDI.getData2();
// Serial.print(korgdata1);Serial.print(" "); Serial.println(korgdata2);
// }
int x = -1, y = -1; //regular pixel coordinates
touch_pressed = Touch_getXY(); //external function
#if 0
Serial.print("X="); Serial.print(pixel_x);
Serial.print(" Y="); Serial.print(pixel_y);
Serial.print(" Z="); Serial.print(touch_pressed);
Serial.println("");
#endif
if (touch_pressed) {
x = pixel_x; //copy global variable
y = pixel_y;
}
{
if((x > SW1BUTTON_X) && (x < (SW1BUTTON_X + SW1BUTTON_W))) {
if ((y > SW1BUTTON_Y) && (y <= (SW1BUTTON_Y + SW1BUTTON_H))) {
Serial.println("SW1 btn hit");
delay(100); // UI debouncing
sw1Btn();
}
}
}
{
if((x > SW2BUTTON_X) && (x < (SW2BUTTON_X + SW2BUTTON_W))) {
if ((y > SW2BUTTON_Y) && (y <= (SW2BUTTON_Y + SW2BUTTON_H))) {
Serial.println("SW2 btn hit");
delay(100); // UI debouncing
sw2Btn();
}
}
}
{
if((x > RIBBON_X) && (x < (RIBBON_X + RIBBON_W))) {
if ((y > RIBBON_Y) && (y <= (RIBBON_Y + RIBBON_H))) {
Serial.println("Ribbon pressed");
Serial.println(pixel_x);
Serial.println(ribbon);
delay(100); // UI debouncing
rbCtrl();
}
}
}
}
Message, type=192, data = 7 0
Message, type=176, data = 65 0
int pcrec; // Program Change receive
int pcold; // Old Program Change value
int pcnew; // New Program Change value. Just in case i decide to have the Preset numbers on the screen
int sw1recd1 = 0; // SW1 Data1 received value
int sw1recd2 = 0; // SW1 Data2 received value
int sw1oldd1 = 0; // SW1 Data1 old value
int sw1oldd2 = 0; // SW1 Data2 old value
int sw1newd1 = 0; // SW1 Data1 new value ... daah
int sw1newd2 = 0; // SW1 Data2 new value ... daah
int sw2recd1 = 0; // SW2 Data1 received value
int sw2recd2 = 0; // SW2 Data2 received value
int sw2oldd1 = 0; // SW2 Data1 old value
int sw2oldd2 = 0; // SW2 Data2 old value
int sw2newd1 = 0; // SW2 Data1 new value
int sw2newd2 = 0; // SW2 Data2 new value
elapsedMillis scanStart; // add to the pre-setup code
...
void loop(){
usbMIDI.read();
if (scanStart < 8) {
SW1 = SW2;
SW2 = D1;
}else{
scanStart = 0;
if (!SW1) {
SW1 = SW2;
SW2 = 81; // or leave it as is or blank it or whatever you want
}
}
}
Message, type=176, data = 0 0
Message, type=176, data = 32 0
Message, type=192, data = 9 0
Message, type=176, data = 80 0
Message, type=176, data = 81 0
Message, type=176, data = 80 0
Message, type=176, data = 81 0
Message, ch, type=176,channel=1, data = 0 0
Message, ch, type=176,channel=1, data = 32 0
Message, type=192,channel1, data = 0 0
Message, ch, type=176,channel=1, data = 7 127
Message, ch, type=176,channel=1, data = 10 64
Message, ch, type=176,channel=1, data = 93 0
Message, ch, type=176,channel=1, data = 91 0
Message, ch, type=176,channel=2, data = 0 0
Message, ch, type=176,channel=2, data = 32 0
Message, type=192,channel2, data = 0 0
Message, ch, type=176,channel=2, data = 7 127
Message, ch, type=176,channel=2, data = 10 64
Message, ch, type=176,channel=2, data = 93 0
Message, ch, type=176,channel=2, data = 91 0
Message, ch, type=176,channel=3, data = 0 0
Message, ch, type=176,channel=3, data = 32 0
Message, type=192,channel3, data = 0 0
Message, ch, type=176,channel=3, data = 7 127
Message, ch, type=176,channel=3, data = 10 64
Message, ch, type=176,channel=3, data = 93 0
Message, ch, type=176,channel=3, data = 91 0
Message, ch, type=176,channel=4, data = 0 0
Message, ch, type=176,channel=4, data = 32 0
Message, type=192,channel4, data = 0 0
MessagMessage, ch, type=176,channel=13, data = 10 64
Message, ch, type=176,channel=13, data = 93 0
Message, ch, type=176,channel=13, data = 91 0
Message, ch, type=176,channel=14, data = 0 0
Message, ch, type=176,channel=14, data = 32 0
Message, type=192,channel14, data = 0 0
Message, ch, type=176,channel=14, data = 7 127
Message, ch, type=176,channel=14, data = 10 64
Message, ch, type=176,channel=14, data = 93 0
Message, ch, type=176,channel=14, data = 91 0
Message, ch, type=176,channel=15, data = 0 0
Message, ch, type=176,channel=15, data = 32 0
Message, type=192,channel15, data = 0 0
Message, ch, type=176,channel=15, data = 7 127
Message, ch, type=176,channel=15, data = 10 64
Message, ch, type=176,channel=15, data = 93 0
Message, ch, type=176,channel=15, data = 91 0
Message, ch, type=176,channel=16, data = 0 0
Message, ch, type=176,channel=16, data = 32 0
Message, type=192,channel16, data = 0 0
Message, ch, type=176,channel=16, data = 7 127
Message, ch, type=176,channel=16, data = 10 64
Message, ch, type=176,channel=16, data = 93 0
Message, ch, type=176,channel=16, data = 91 0
Message, ch, type=176,channel=1, data = 80 0
Message, ch, type=176,channel=1, data = 81 0
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h> // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!
// SET THESE SIX VALUES FOR JOYSTICK!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int modPin2 = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down
// SET THESE VALUES FOR RIBBON
//const int ribbonPin = touch_pressed; // Max reading on right side... as raw 10-bit value
const int ribbonMaxRaw = 474; // Max reading on right side... as raw 10-bit value
//
int Button1 = 0; //This is the default "Button Off" and 1 is "Button On"
int Button2 = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton1 = 0; //Variable to store button1 old value
int OldButton2 = 0; //Variable to store button2 old value
byte data1On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data1Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
byte data2On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data2Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
int SW1 = 0;
int SW2 = 0;
int d1 = 0;
int d2 = 0;
int ch;
int SW1D1 = 0;
int SW1D2 = 0;
int SW2D1 = 0;
int SW2D2 = 0;
const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int mod2;
int pitchRaw;
int modRaw;
int modRaw2;
int pitchLag;
int modLag;
int modLag2;
int ribbon;
int ribbonRaw;
int ribbonLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;
elapsedMillis modUpdate2;
elapsedMillis ribbonUpdate;
elapsedMillis scanStart;
// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};
ResponsiveAnalogRead readMod2 = {modPin2, true};
#include <Adafruit_GFX.h> // Core graphics library
#define LCD_ROTATION 1 //should work in all rotations
#define USE_READID 0 //Adafruit and ILI9488 can't read ID
//#include <MCUFRIEND_kbv.h> // Hardware-specific library
//MCUFRIEND_kbv tft;
//#include <Adafruit_ILI9341.h> // Hardware-specific library
//Adafruit_ILI9341 tft(10, 9, 8);
//#include <HX8347D_kbv.h> // Hardware-specific library
//HX8347D_kbv tft;
#include <ILI9488.h> // Hardware-specific library
ILI9488 tft(10, 9, 8);
//#include <ILI9488_kbv.h> // Hardware-specific library
//ILI9488_kbv tft;
extern void Touch_initialise(int aspect, int wid, int ht);
extern bool Touch_getXY(void);
bool touch_pressed;
int pixel_x, pixel_y;
boolean SW1on = false;
boolean SW2on = false;
boolean ribbonCtrl = false;
// Color definitions
#define TFT_BLACK 0x0000 /* 0, 0, 0 */
#define TFT_NAVY 0x000F /* 0, 0, 128 */
#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */
#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */
#define TFT_MAROON 0x7800 /* 128, 0, 0 */
#define TFT_PURPLE 0x780F /* 128, 0, 128 */
#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */
#define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */
#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */
#define TFT_BLUE 0x001F /* 0, 0, 255 */
#define TFT_GREEN 0x07E0 /* 0, 255, 0 */
#define TFT_CYAN 0x07FF /* 0, 255, 255 */
#define TFT_RED 0xF800 /* 255, 0, 0 */
#define TFT_RED2 0xF88D /* 254, 18, 106 */
#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */
#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */
#define TFT_WHITE 0xFFFF /* 255, 255, 255 */
#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */
#define TFT_ORANGE2 0xFB20 /* 254, 102, 1 */
#define TFT_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define TFT_PINK 0xF81F
/******************* UI details */
#define SW1FRAME_X 90
#define SW1FRAME_Y 110
#define SW1FRAME_W 130
#define SW1FRAME_H 70
#define SW1BUTTON_X SW1FRAME_X
#define SW1BUTTON_Y SW1FRAME_Y
#define SW1BUTTON_W SW1FRAME_W
#define SW1BUTTON_H SW1FRAME_H
#define SW2FRAME_X 310
#define SW2FRAME_Y 110
#define SW2FRAME_W 130
#define SW2FRAME_H 70
#define SW2BUTTON_X SW2FRAME_X
#define SW2BUTTON_Y SW2FRAME_Y
#define SW2BUTTON_W SW2FRAME_W
#define SW2BUTTON_H SW2FRAME_H
#define RIBBONFRAME_X 10
#define RIBBONFRAME_Y 240
#define RIBBONFRAME_W 470
#define RIBBONFRAME_H 70
#define RIBBON_X RIBBONFRAME_X
#define RIBBON_Y RIBBONFRAME_Y
#define RIBBON_W RIBBONFRAME_W
#define RIBBON_H RIBBONFRAME_H
void sw1Btn()
{
tft.drawRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_RED);
tft.setCursor(160, 140);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.println("SW1");
usbMIDI.sendControlChange(SW1, d2, 1);
SW1on = false;
}
void sw2Btn()
{
tft.drawRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_RED);
tft.setCursor(340,140);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.println("SW2");
usbMIDI.sendControlChange(SW2, d2, 1);
SW2on = false;
}
void rbCtrl()
{
tft.drawRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
tft.fillRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
tft.setCursor(10,240);
//remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
ribbon = map(pixel_x, 11, 474, 0, 127);
//ribbon = max(ribbon, 0); // need this now that the bottom isn't zero
// ribbon = min(ribbon, 127); // cap to avoid overflow
// if (abs(ribbon - ribbonLag) > 0 && ribbonUpdate > MIDIdelay ) {
// ribbonLag = ribbon;
usbMIDI.sendControlChange(16, ribbon, channel);
// ribbonUpdate = 0;
// }
ribbonCtrl = false;
}
void setup(void)
{
Serial.begin(9600);
Serial.println(F("TFT LCD test"));
tft.begin();
int aspect = LCD_ROTATION; //PORTRAIT
tft.setRotation(aspect);
Touch_initialise(aspect, tft.width(), tft.height()); //.kbv external function
tft.fillScreen(TFT_BLACK);
// create 'SW1 Switch'
tft.drawRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_RED);
tft.setCursor(155, 140);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
tft.print("SW1");
// create 'SW2 Switch'
tft.drawRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_RED);
tft.setCursor(340, 140);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
tft.print("SW2");
// create 'Ribbon Emulator field'
tft.drawRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_DARKGREY);
tft.fillRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
}
unsigned long t=0;
void loop(void)
{
int type, note, velocity, channel, d1, d2;
if (usbMIDI.read()) { // Is there a MIDI message incoming ?
byte type = usbMIDI.getType();
switch (type) {
case usbMIDI.ControlChange:
d1 = usbMIDI.getData1();
d2 = usbMIDI.getData2();
channel = usbMIDI.getChannel();
Serial.println(String("Message, type=") + type + ",channel " + channel + ", data = " + d1 + " " + d2);
if (scanStart < 8) {
SW1 = SW2;
Serial.println (String("scanStart<8 SW1=SW2: SW1 ") + SW1 + ", SW2 " + SW2); // This print is only to control what is happening
SW2 = d1;
Serial.println (String("SW2=dl: " "SW2 ") + SW2 + ", D1 " + d1); // This print is only to control what is happening
}else{
scanStart = 0;
if (!SW1) {
SW1 = SW2;
Serial.println (String("scanStart = 0: SW1=SW2 " "=SW1 ") + SW1 + ", SW2 " + SW2); // This print is only to control what is happening
SW2 = 81; // or leave it as is or blank it or whatever you want
}
}
}
t = millis();
}
if (millis() - t > 10000) {
t += 10000;
Serial.println("(inactivity)");
}
int x = -1, y = -1; //regular pixel coordinates
touch_pressed = Touch_getXY(); //external function
#if 0
Serial.print("X="); Serial.print(pixel_x);
Serial.print(" Y="); Serial.print(pixel_y);
Serial.print(" Z="); Serial.print(touch_pressed);
Serial.println("");
#endif
if (touch_pressed) {
x = pixel_x; //copy global variable
y = pixel_y;
}
{
if((x > SW1BUTTON_X) && (x < (SW1BUTTON_X + SW1BUTTON_W))) {
if ((y > SW1BUTTON_Y) && (y <= (SW1BUTTON_Y + SW1BUTTON_H))) {
Serial.println("SW1 btn hit");
Serial.println(String("Message,") + ",channel " + channel + ",data = " + SW1 + " " + d2);
delay(100); // UI debouncing
sw1Btn();
}
}
}
{
if((x > SW2BUTTON_X) && (x < (SW2BUTTON_X + SW2BUTTON_W))) {
if ((y > SW2BUTTON_Y) && (y <= (SW2BUTTON_Y + SW2BUTTON_H))) {
Serial.println("SW2 btn hit");
Serial.println(String("Message,") + ",channel " + channel + ",data = " + SW2 + " " + d2);
delay(100); // UI debouncing
sw2Btn();
}
}
}
{
if((x > RIBBON_X) && (x < (RIBBON_X + RIBBON_W))) {
if ((y > RIBBON_Y) && (y <= (RIBBON_Y + RIBBON_H))) {
Serial.println("Ribbon pressed");
Serial.println(pixel_x);
Serial.println(ribbon);
delay(100); // UI debouncing
rbCtrl();
}
}
}
}
(inactivity)
Message, type=176,channel 1, data = 80 0
scanStart = 0: SW1=SW2 =SW1 0, SW2 0
Message, type=176,channel 1, data = 81 0
scanStart<8 SW1=SW2: SW1 81, SW2 81
SW2=dl: SW2 81, D1 81
(inactivity)
elapsedMillis scanStart; // add to the pre-setup code
...
void loop(){
usbMIDI.read();
if (getType=usbMIDI.programChnage) {
scanStart = 0;
}
if (scanStart < 8) {
SW1 = SW2;
SW2 = D1;
}else{
if (!SW1) {
SW1 = SW2;
SW2 = 0 ; // blank SW2 if there was only 1 CC
}
}
}
Hey oddson, no rush.
Maybe you're lacking a pint of beer to put that engine on track!
const int scanMax = 250;
const byte channel = 1;
byte SW1;
byte SW1lag;
byte SW2;
byte SW2lag;
elapsedMillis scanStart;
elapsedMillis reportLast;
void setup() {
Serial.begin(9600);
}
void loop(void)
{
if (usbMIDI.read(channel)) { // limit reads to single channel
if (usbMIDI.getType() == usbMIDI.ProgramChange){
scanStart = 0;
SW1 = SW2;
SW2 = 0;
}else if(usbMIDI.getType() == usbMIDI.ControlChange) {
if (scanStart <= scanMax) {
SW1 = SW2;
SW2 = usbMIDI.getData1();
}
}
}
if (scanStart >= scanMax) {
if (SW1 == 0) { // if there was only 1 CC SW1 is blank and we will swap
SW1 = SW2;
SW2 = 0;
}
if ((SW1 != SW1lag) || (SW2 != SW2lag)) { // if there is a change...
Serial.println(SW1);
Serial.println(SW2);
SW1lag = SW1;
SW2lag = SW2;
scanStart = 0;
}
}
}
if ((SW1 != SW1lag) || (SW2 != SW2lag)) { // if there is a change...
Serial.println(SW1);
Serial.println(SW2);
SW1lag = SW1;
SW2lag = SW2;
}
scanStart = 0;
(inactivity)
80
81
SW1 btn hit
Message,,channel 1,data = 80 0
(inactivity)
SW2 btn hit
Message,,channel 1,data = 81 0
(inactivity)
(inactivity)
(inactivity)
(inactivity)
void loop(void)
{
if (usbMIDI.read(channel)) { // limit reads to single channel
if (usbMIDI.getType() == usbMIDI.ProgramChange){
scanStart = 0;
SW1 = SW2;
SW2 = 0;
}else if(usbMIDI.getType() == usbMIDI.ControlChange) {
if (scanStart <= scanMax) {
SW1 = SW2;
SW2 = usbMIDI.getData1();
}
}
}
if (scanStart >= scanMax) {
if (SW1 == 0) { // if there was only 1 CC SW1 is blank and we will swap
SW1 = SW2;
SW2 = 0;
}
if ((SW1 != SW1lag) || (SW2 != SW2lag)) { // if there is a change...
Serial.println(SW1);
Serial.println(SW2);
SW1lag = SW1;
SW2lag = SW2;
}
scanStart = 0;
}
}
yeah... I guess I'll have to debug it sober.
...as a hunch try changing SW1 = SW2; to SW1 = 0; in the PC part of the code (first instance).
I meant to post that as a correction last night but didn't... I thought it was harmless but that could be why it's not working as it might be messing up the flags as I thought they work but I can't quite think it through in my head right now.
(Something to do with blanking them by accident when SW2 gets copied to SW1 after the first message is processed.)
if (scanStart >= scanMax) {
if (SW1 == 0) { // if there was only 1 CC SW1 is blank and we will swap
SW1 = SW2;
SW2 = 0;
}
[COLOR="#A9A9A9"] //if ((SW1 != SW1lag) || (SW2 != SW2lag)) { // if there is a change...[/COLOR]
Serial.println(SW1);
Serial.println(SW2);
SW1lag = SW1;
SW2lag = SW2;
[COLOR="#A9A9A9"] //}[/COLOR]
scanStart = 0;
}
It won't do anything if the same parameters are present but the SW1 and SW2 values will still be correct if/when they are pressed again if these variables are used in the MIDI message.
E.g.: usbMIDI.sendProgramChange(SW1, channel);
Remove the conditional and it should report every time.Code:if (scanStart >= scanMax) { if (SW1 == 0) { // if there was only 1 CC SW1 is blank and we will swap SW1 = SW2; SW2 = 0; } [COLOR=#A9A9A9] //if ((SW1 != SW1lag) || (SW2 != SW2lag)) { // if there is a change...[/COLOR] Serial.println(SW1); Serial.println(SW2); SW1lag = SW1; SW2lag = SW2; [COLOR=#A9A9A9] //}[/COLOR] scanStart = 0; }
0
0
0
0
0
0
0
0
0
(inactivity)
0
0
0
0
0
0
0
0
0
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h> // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!
// SET THESE SIX VALUES FOR JOYSTICK!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int modPin2 = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down
// SET THESE VALUES FOR RIBBON
//const int ribbonPin = touch_pressed; // Max reading on right side... as raw 10-bit value
const int ribbonMaxRaw = 474; // Max reading on right side... as raw 10-bit value
//
int Button1 = 0; //This is the default "Button Off" and 1 is "Button On"
int Button2 = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton1 = 0; //Variable to store button1 old value
int OldButton2 = 0; //Variable to store button2 old value
const int scanMax = 9;
//const byte channel = 1;
byte SW1;
byte SW1D2;
byte SW1lag;
byte SW2;
byte SW2D2;
byte SW2lag;
byte d2;
const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int mod2;
int pitchRaw;
int modRaw;
int modRaw2;
int pitchLag;
int modLag;
int modLag2;
int ribbon;
int ribbonRaw;
int ribbonLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;
elapsedMillis modUpdate2;
elapsedMillis ribbonUpdate;
elapsedMillis scanStart;
elapsedMillis reportLast;
// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};
ResponsiveAnalogRead readMod2 = {modPin2, true};
#include <Adafruit_GFX.h> // Core graphics library
#define LCD_ROTATION 1 //should work in all rotations
#define USE_READID 0 //Adafruit and ILI9488 can't read ID
//#include <MCUFRIEND_kbv.h> // Hardware-specific library
//MCUFRIEND_kbv tft;
//#include <Adafruit_ILI9341.h> // Hardware-specific library
//Adafruit_ILI9341 tft(10, 9, 8);
//#include <HX8347D_kbv.h> // Hardware-specific library
//HX8347D_kbv tft;
#include <ILI9488.h> // Hardware-specific library
ILI9488 tft(10, 9, 8);
//#include <ILI9488_kbv.h> // Hardware-specific library
//ILI9488_kbv tft;
extern void Touch_initialise(int aspect, int wid, int ht);
extern bool Touch_getXY(void);
bool touch_pressed;
int pixel_x, pixel_y;
boolean SW1on = false;
boolean SW2on = false;
boolean ribbonCtrl = false;
// Color definitions
#define TFT_BLACK 0x0000 /* 0, 0, 0 */
#define TFT_NAVY 0x000F /* 0, 0, 128 */
#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */
#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */
#define TFT_MAROON 0x7800 /* 128, 0, 0 */
#define TFT_PURPLE 0x780F /* 128, 0, 128 */
#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */
#define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */
#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */
#define TFT_BLUE 0x001F /* 0, 0, 255 */
#define TFT_GREEN 0x07E0 /* 0, 255, 0 */
#define TFT_CYAN 0x07FF /* 0, 255, 255 */
#define TFT_RED 0xF800 /* 255, 0, 0 */
#define TFT_RED2 0xF88D /* 254, 18, 106 */
#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */
#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */
#define TFT_WHITE 0xFFFF /* 255, 255, 255 */
#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */
#define TFT_ORANGE2 0xFB20 /* 254, 102, 1 */
#define TFT_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define TFT_PINK 0xF81F
/******************* UI details */
#define SW1FRAME_X 90
#define SW1FRAME_Y 110
#define SW1FRAME_W 130
#define SW1FRAME_H 70
#define SW1BUTTON_X SW1FRAME_X
#define SW1BUTTON_Y SW1FRAME_Y
#define SW1BUTTON_W SW1FRAME_W
#define SW1BUTTON_H SW1FRAME_H
#define SW2FRAME_X 310
#define SW2FRAME_Y 110
#define SW2FRAME_W 130
#define SW2FRAME_H 70
#define SW2BUTTON_X SW2FRAME_X
#define SW2BUTTON_Y SW2FRAME_Y
#define SW2BUTTON_W SW2FRAME_W
#define SW2BUTTON_H SW2FRAME_H
#define RIBBONFRAME_X 10
#define RIBBONFRAME_Y 240
#define RIBBONFRAME_W 470
#define RIBBONFRAME_H 70
#define RIBBON_X RIBBONFRAME_X
#define RIBBON_Y RIBBONFRAME_Y
#define RIBBON_W RIBBONFRAME_W
#define RIBBON_H RIBBONFRAME_H
void sw1Btn()
{
tft.drawRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_RED);
tft.setCursor(160, 140);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.println("SW1");
usbMIDI.sendControlChange(SW1, SW1D2, 1);
SW1on = false;
}
void sw2Btn()
{
tft.drawRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_RED);
tft.setCursor(340,140);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.println("SW2");
usbMIDI.sendControlChange(SW2, SW2D2, 1);
SW2on = false;
}
void rbCtrl()
{
tft.drawRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
tft.fillRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
tft.setCursor(10,240);
//remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
ribbon = map(pixel_x, 11, 474, 0, 127);
//ribbon = max(ribbon, 0); // need this now that the bottom isn't zero
// ribbon = min(ribbon, 127); // cap to avoid overflow
// if (abs(ribbon - ribbonLag) > 0 && ribbonUpdate > MIDIdelay ) {
// ribbonLag = ribbon;
usbMIDI.sendControlChange(16, ribbon, channel);
// ribbonUpdate = 0;
// }
ribbonCtrl = false;
}
void setup(void)
{
Serial.begin(9600);
Serial.println(F("TFT LCD test"));
tft.begin();
int aspect = LCD_ROTATION; //PORTRAIT
tft.setRotation(aspect);
Touch_initialise(aspect, tft.width(), tft.height()); //.kbv external function
tft.fillScreen(TFT_BLACK);
// create 'SW1 Switch'
tft.drawRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW1BUTTON_X, SW1BUTTON_Y, SW1BUTTON_W, SW1BUTTON_H, TFT_RED);
tft.setCursor(155, 140);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
tft.print("SW1");
// create 'SW2 Switch'
tft.drawRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_DARKGREY);
tft.fillRect(SW2BUTTON_X, SW2BUTTON_Y, SW2BUTTON_W, SW2BUTTON_H, TFT_RED);
tft.setCursor(340, 140);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(2);
tft.print("SW2");
// create 'Ribbon Emulator field'
tft.drawRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_DARKGREY);
tft.fillRect(RIBBON_X, RIBBON_Y, RIBBON_W, RIBBON_H, TFT_LIGHTGREY);
}
unsigned long t=0;
void loop(void)
{
{
if (usbMIDI.read(channel)) { // limit reads to single channel
if (usbMIDI.getType() == usbMIDI.ProgramChange){
scanStart = 0;
SW1 = 0;
SW2 = 0;
}else if(usbMIDI.getType() == usbMIDI.ControlChange) {
if (scanStart <= scanMax) {
SW1 = SW2;
SW1D2 = SW2D2;
SW2 = usbMIDI.getData1();
SW2D2 = usbMIDI.getData2();
}
}
}
if (scanStart >= scanMax) {
if (SW1 == 0) { // if there was only 1 CC SW1 is blank and we will swap
SW1 = SW2;
SW2 = 0;
}
if ((SW1 != SW1lag) || (SW2 != SW2lag)) { // if there is a change...
Serial.println(SW1);
Serial.println(SW2);
SW1lag = SW1;
SW2lag = SW2;
}
scanStart = 0;
}
}
if (millis() - t > 10000) {
t += 10000;
Serial.println("(inactivity)");
}
int x = -1, y = -1; //regular pixel coordinates
touch_pressed = Touch_getXY(); //external function
#if 0
Serial.print("X="); Serial.print(pixel_x);
Serial.print(" Y="); Serial.print(pixel_y);
Serial.print(" Z="); Serial.print(touch_pressed);
Serial.println("");
#endif
if (touch_pressed) {
x = pixel_x; //copy global variable
y = pixel_y;
}
{
if((x > SW1BUTTON_X) && (x < (SW1BUTTON_X + SW1BUTTON_W))) {
if ((y > SW1BUTTON_Y) && (y <= (SW1BUTTON_Y + SW1BUTTON_H))) {
Serial.println("SW1 btn hit");
Serial.println(String("Message,") + ",channel " + channel + ",data = " + SW1 + " " + d2);
delay(100); // UI debouncing
sw1Btn();
}
}
}
{
if((x > SW2BUTTON_X) && (x < (SW2BUTTON_X + SW2BUTTON_W))) {
if ((y > SW2BUTTON_Y) && (y <= (SW2BUTTON_Y + SW2BUTTON_H))) {
Serial.println("SW2 btn hit");
Serial.println(String("Message,") + ",channel " + channel + ",data = " + SW2 + " " + d2);
delay(100); // UI debouncing
sw2Btn();
}
}
}
{
if((x > RIBBON_X) && (x < (RIBBON_X + RIBBON_W))) {
if ((y > RIBBON_Y) && (y <= (RIBBON_Y + RIBBON_H))) {
Serial.println("Ribbon pressed");
Serial.println(pixel_x);
Serial.println(ribbon);
delay(100); // UI debouncing
rbCtrl();
}
}
}
}