From 76ea0078f94a4ed5eee387d00dea40d3cb55b860 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sun, 14 Jan 2018 18:42:25 +0100 Subject: [PATCH 01/16] Add files via upload --- src/MIDI_Outputs/DigitalCC.cpp | 53 ++++++++++++++++++++++++++++++++++ src/MIDI_Outputs/DigitalCC.h | 39 +++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 src/MIDI_Outputs/DigitalCC.cpp create mode 100644 src/MIDI_Outputs/DigitalCC.h diff --git a/src/MIDI_Outputs/DigitalCC.cpp b/src/MIDI_Outputs/DigitalCC.cpp new file mode 100644 index 0000000..6a1f056 --- /dev/null +++ b/src/MIDI_Outputs/DigitalCC.cpp @@ -0,0 +1,53 @@ +#include "DigitalCC.h" +#include + +using namespace ExtIO; + +DigitalCC::DigitalCC(pin_t pin, uint8_t controller, uint8_t channel) // Constructor + : pin(pin), controller(controller), channel(channel) { + ExtIO::pinMode(pin, INPUT_PULLUP); // Enable the internal pull-up resistor on the pin with the button/switch +} + +DigitalCC::~DigitalCC() { // Destructor + ExtIO::pinMode(pin, INPUT); // make it a normal input again, without the internal pullup resistor. +} + +void DigitalCC::invert() // Invert the button state +{ + invertState = true; +} + +void DigitalCC::refresh() { // Check if the button state changed, and send a MIDI CC accordingly + bool state = ExtIO::digitalRead(pin) ^ invertState; // read the button state and invert it if "invert" is true + + if (millis() - prevBounceTime > debounceTime) + { + int8_t stateChange = digitalMap(state) - buttonState; + + if (stateChange == falling) + { // Button is pushed + buttonState = state; + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, + channel + channelOffset * channelsPerBank, + controller + addressOffset * channelsPerBank, 127); + } + + if (stateChange == rising) + { // Button is released + buttonState = state; + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, + channel + channelOffset * channelsPerBank, + controller + addressOffset * channelsPerBank, 0); + } + } + if (state != prevState) + { + prevBounceTime = millis(); + prevState = state; + } +} + +void DigitalCC::map(int (*fn)(int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() +{ + digitalMap = fn; +} \ No newline at end of file diff --git a/src/MIDI_Outputs/DigitalCC.h b/src/MIDI_Outputs/DigitalCC.h new file mode 100644 index 0000000..3802ed8 --- /dev/null +++ b/src/MIDI_Outputs/DigitalCC.h @@ -0,0 +1,39 @@ +#ifndef DIGITALCC_H_ +#define DIGITALCC_H_ + +#include "Arduino.h" +#include "MIDI_Control_Element.h" +#include "../Settings/Settings.h" +#include "../ExtendedInputOutput/ExtendedInputOutput.h" + +class DigitalCC : public MIDI_Control_Element +{ +public: + DigitalCC(pin_t pin, uint8_t controller, uint8_t channel); // Constructor + ~DigitalCC(); // Destructor + void invert(); // Invert the button state + void map(int (*fn)(int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() + +private: + void refresh(); // Check if the button state changed, and send a MIDI CC accordingly + int (*digitalMap)(int) = identity; // function pointer to identity function f(x) → x + + static int identity(int x) + { // identity function f(x) → x + return x; + } + + pin_t pin; + uint8_t controller, channel; + bool prevState = HIGH, buttonState = HIGH; + unsigned long prevBounceTime = 0; + + bool invertState = false; + + const static unsigned long debounceTime = BUTTON_DEBOUNCE_TIME; + + const static int8_t falling = LOW - HIGH; + const static int8_t rising = HIGH - LOW; +}; + +#endif \ No newline at end of file From a8688475d3bcd0296a3cc7c8dae1ec0f4f7363a9 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sun, 14 Jan 2018 18:45:19 +0100 Subject: [PATCH 02/16] Added map() function like Analog class --- src/MIDI_Outputs/Digital.cpp | 7 ++++++- src/MIDI_Outputs/Digital.h | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/MIDI_Outputs/Digital.cpp b/src/MIDI_Outputs/Digital.cpp index a20d231..f40d6f0 100755 --- a/src/MIDI_Outputs/Digital.cpp +++ b/src/MIDI_Outputs/Digital.cpp @@ -28,7 +28,7 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No if (millis() - prevBounceTime > debounceTime) { - int8_t stateChange = state - buttonState; + int8_t stateChange = digitalMap(state) - buttonState; if (stateChange == falling) { // Button is pushed @@ -47,4 +47,9 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No prevBounceTime = millis(); prevState = state; } +} + +void Digital::map(int (*fn)(int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() +{ + digitalMap = fn; } \ No newline at end of file diff --git a/src/MIDI_Outputs/Digital.h b/src/MIDI_Outputs/Digital.h index b5f5ad5..958cec8 100755 --- a/src/MIDI_Outputs/Digital.h +++ b/src/MIDI_Outputs/Digital.h @@ -12,10 +12,17 @@ class Digital : public MIDI_Control_Element Digital(pin_t pin, uint8_t note, uint8_t channel, uint8_t velocity = 127); // Constructor ~Digital(); // Destructor void invert(); // Invert the button state (send Note On event when released, Note Off when pressed) + void map(int (*fn)(int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() private: void refresh(); // Check if the button state changed, and send a MIDI Note On or Off accordingly + int (*digitalMap)(int) = identity; // function pointer to identity function f(x) → x + static int identity(int x) + { // identity function f(x) → x + return x; + } + pin_t pin; uint8_t note, channel, velocity; bool prevState = HIGH, buttonState = HIGH; From a0a9472d38516ddae467e9ea983f02f083e7ab64 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sun, 14 Jan 2018 20:42:13 +0100 Subject: [PATCH 03/16] Added AnalogResponsive class --- src/MIDI_Outputs/AnalogResponsive.cpp | 41 +++++++++++++++++++++++++++ src/MIDI_Outputs/AnalogResponsive.h | 34 ++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/MIDI_Outputs/AnalogResponsive.cpp create mode 100644 src/MIDI_Outputs/AnalogResponsive.h diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp new file mode 100644 index 0000000..14bbbde --- /dev/null +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -0,0 +1,41 @@ +#include "Arduino.h" +#include "AnalogResponsive.h" +#include "MIDI_Controller.h" + +using namespace ExtIO; + +AnalogResponsive::AnalogResponsive(pin_t analogPin, uint8_t controllerNumber, uint8_t channel) // Constructor +{ + this->analogPin = analogPin; + this->controllerNumber = controllerNumber; + this->channel = channel; + this->respAnalog = new ResponsiveAnalogRead(analogPin, true); +} + +AnalogResponsive::~AnalogResponsive() // Destructor +{ + delete respAnalog; +} + +void AnalogResponsive::invert() // Invert the button state (send Note On event when released, Note Off when pressed) +{ + invertState = true; +} + +void AnalogResponsive::refresh() // read the analog value, update the average, map it to a MIDI value, check if it changed since last time, if so, send Control Change message over MIDI +{ + unsigned int input = ExtIO::analogRead(analogPin); // read the raw analog input value + if (invertState) input = 1023-input; // invert the scale + uint16_t value = analogMap(input); // apply the analogMap function to the value (identity function f(x) = x by default) + respAnalog->update(value); // update the responsive analog average + if (respAnalog->hasChanged()) // if the value changed since last time + { + value = respAnalog->getValue(); // get the responsive analog average value + MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, value); // send a Control Change MIDI event + } +} + +void AnalogResponsive::map(int (*fn)(int)) // change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() +{ + analogMap = fn; +} \ No newline at end of file diff --git a/src/MIDI_Outputs/AnalogResponsive.h b/src/MIDI_Outputs/AnalogResponsive.h new file mode 100644 index 0000000..6e0262d --- /dev/null +++ b/src/MIDI_Outputs/AnalogResponsive.h @@ -0,0 +1,34 @@ +#ifndef AnalogResponsive_h_ +#define AnalogResponsive_h_ + +#include "Arduino.h" +#include "../Settings/Settings.h" +#include "MIDI_Control_Element.h" +#include "../ExtendedInputOutput/ExtendedInputOutput.h" +#include + +class AnalogResponsive : public MIDI_Control_Element +{ +public: + AnalogResponsive(pin_t analogPin, uint8_t controllerNumber, uint8_t channel); // Constructor + ~AnalogResponsive(); // Destructor + void invert(); // Invert the analog scale + void map(int (*fn)(int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() + +private: + void refresh(); // Read the analog input value, update the average, map it to a MIDI value, check if it changed since last time, if so, send Control Change message over MIDI + + ResponsiveAnalogRead *respAnalog; + pin_t analogPin; + uint8_t controllerNumber, channel, oldVal = -1; + int (*analogMap)(int) = identity; // function pointer to identity function f(x) → x + + static int identity(int x) + { // identity function f(x) → x + return x; + } + + bool invertState = false; +}; + +#endif // AnalogResponsive_h_ From fca3da5f559527900b03d68294dcf146ce18788a Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sat, 20 Jan 2018 21:05:55 +0100 Subject: [PATCH 04/16] Add pin to map function as first parameter int *(fn)(int, int) --- src/MIDI_Outputs/Analog.cpp | 10 ++++++++-- src/MIDI_Outputs/Analog.h | 9 ++++++--- src/MIDI_Outputs/AnalogResponsive.cpp | 4 ++-- src/MIDI_Outputs/AnalogResponsive.h | 6 +++--- src/MIDI_Outputs/Digital.cpp | 4 ++-- src/MIDI_Outputs/Digital.h | 6 +++--- src/MIDI_Outputs/DigitalCC.cpp | 4 ++-- src/MIDI_Outputs/DigitalCC.h | 6 +++--- src/MIDI_Outputs/MIDI_Control_Element.h | 2 +- 9 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/MIDI_Outputs/Analog.cpp b/src/MIDI_Outputs/Analog.cpp index 0abf755..ed23ba8 100755 --- a/src/MIDI_Outputs/Analog.cpp +++ b/src/MIDI_Outputs/Analog.cpp @@ -11,10 +11,16 @@ Analog::Analog(pin_t analogPin, uint8_t controllerNumber, uint8_t channel) // Co this->channel = channel; } +void Analog::invert() // Invert the button state (send Note On event when released, Note Off when pressed) +{ + invertState = true; +} + void Analog::refresh() // read the analog value, update the average, map it to a MIDI value, check if it changed since last time, if so, send Control Change message over MIDI { unsigned int input = ExtIO::analogRead(analogPin); // read the raw analog input value - input = analogMap(input); // apply the analogMap function to the value (identity function f(x) = x by default) + if (invertState) input = 1023-input; // invert the scale + input = analogMap(analogPin, input); // apply the analogMap function to the value (identity function f(x) = x by default) #ifdef SINGLE_BYTE_AVERAGE // use 8-bit value for averaging uint8_t value = input >> 2; // map from the 10-bit analog input value [0, 1023] to the 8-bit value [0, 255] @@ -31,7 +37,7 @@ void Analog::refresh() // read the analog value, update the average, map it to a } } -void Analog::map(int (*fn)(int)) // change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() +void Analog::map(int (*fn)(int, int)) // change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() { analogMap = fn; } diff --git a/src/MIDI_Outputs/Analog.h b/src/MIDI_Outputs/Analog.h index 80522b5..ee007dc 100755 --- a/src/MIDI_Outputs/Analog.h +++ b/src/MIDI_Outputs/Analog.h @@ -10,19 +10,22 @@ class Analog : public MIDI_Control_Element { public: Analog(pin_t analogPin, uint8_t controllerNumber, uint8_t channel); // Constructor - void map(int (*fn)(int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() + void invert(); // Invert the analog scale + void map(int (*fn)(int, int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() private: void refresh(); // Read the analog input value, update the average, map it to a MIDI value, check if it changed since last time, if so, send Control Change message over MIDI pin_t analogPin; uint8_t controllerNumber, channel, oldVal = -1; - int (*analogMap)(int) = identity; // function pointer to identity function f(x) → x + int (*analogMap)(int, int) = identity; // function pointer to identity function f(x) → x - static int identity(int x) + static int identity(int p, int x) { // identity function f(x) → x return x; } + + bool invertState = false; #ifdef SINGLE_BYTE_AVERAGE uint8_t runningAverage(uint8_t value); // http://playground.arduino.cc/Main/RunningAverage diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 14bbbde..231104b 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -26,7 +26,7 @@ void AnalogResponsive::refresh() // read the analog value, update the average, m { unsigned int input = ExtIO::analogRead(analogPin); // read the raw analog input value if (invertState) input = 1023-input; // invert the scale - uint16_t value = analogMap(input); // apply the analogMap function to the value (identity function f(x) = x by default) + uint16_t value = analogMap(analogPin, input); // apply the analogMap function to the value (identity function f(x) = x by default) respAnalog->update(value); // update the responsive analog average if (respAnalog->hasChanged()) // if the value changed since last time { @@ -35,7 +35,7 @@ void AnalogResponsive::refresh() // read the analog value, update the average, m } } -void AnalogResponsive::map(int (*fn)(int)) // change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() +void AnalogResponsive::map(int (*fn)(int, int)) // change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() { analogMap = fn; } \ No newline at end of file diff --git a/src/MIDI_Outputs/AnalogResponsive.h b/src/MIDI_Outputs/AnalogResponsive.h index 6e0262d..474c330 100644 --- a/src/MIDI_Outputs/AnalogResponsive.h +++ b/src/MIDI_Outputs/AnalogResponsive.h @@ -13,7 +13,7 @@ class AnalogResponsive : public MIDI_Control_Element AnalogResponsive(pin_t analogPin, uint8_t controllerNumber, uint8_t channel); // Constructor ~AnalogResponsive(); // Destructor void invert(); // Invert the analog scale - void map(int (*fn)(int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() + void map(int (*fn)(int, int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() private: void refresh(); // Read the analog input value, update the average, map it to a MIDI value, check if it changed since last time, if so, send Control Change message over MIDI @@ -21,9 +21,9 @@ class AnalogResponsive : public MIDI_Control_Element ResponsiveAnalogRead *respAnalog; pin_t analogPin; uint8_t controllerNumber, channel, oldVal = -1; - int (*analogMap)(int) = identity; // function pointer to identity function f(x) → x + int (*analogMap)(int, int) = identity; // function pointer to identity function f(x) → x - static int identity(int x) + static int identity(int p, int x) { // identity function f(x) → x return x; } diff --git a/src/MIDI_Outputs/Digital.cpp b/src/MIDI_Outputs/Digital.cpp index f40d6f0..9023c6f 100755 --- a/src/MIDI_Outputs/Digital.cpp +++ b/src/MIDI_Outputs/Digital.cpp @@ -28,7 +28,7 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No if (millis() - prevBounceTime > debounceTime) { - int8_t stateChange = digitalMap(state) - buttonState; + int8_t stateChange = digitalMap(pin, state) - buttonState; if (stateChange == falling) { // Button is pushed @@ -49,7 +49,7 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No } } -void Digital::map(int (*fn)(int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() +void Digital::map(int (*fn)(int, int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() { digitalMap = fn; } \ No newline at end of file diff --git a/src/MIDI_Outputs/Digital.h b/src/MIDI_Outputs/Digital.h index 958cec8..52fe672 100755 --- a/src/MIDI_Outputs/Digital.h +++ b/src/MIDI_Outputs/Digital.h @@ -12,13 +12,13 @@ class Digital : public MIDI_Control_Element Digital(pin_t pin, uint8_t note, uint8_t channel, uint8_t velocity = 127); // Constructor ~Digital(); // Destructor void invert(); // Invert the button state (send Note On event when released, Note Off when pressed) - void map(int (*fn)(int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() + void map(int (*fn)(int, int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() private: void refresh(); // Check if the button state changed, and send a MIDI Note On or Off accordingly - int (*digitalMap)(int) = identity; // function pointer to identity function f(x) → x + int (*digitalMap)(int, int) = identity; // function pointer to identity function f(x) → x - static int identity(int x) + static int identity(int p, int x) { // identity function f(x) → x return x; } diff --git a/src/MIDI_Outputs/DigitalCC.cpp b/src/MIDI_Outputs/DigitalCC.cpp index 6a1f056..5a9e79c 100644 --- a/src/MIDI_Outputs/DigitalCC.cpp +++ b/src/MIDI_Outputs/DigitalCC.cpp @@ -22,7 +22,7 @@ void DigitalCC::refresh() { // Check if the button state changed, and send a MI if (millis() - prevBounceTime > debounceTime) { - int8_t stateChange = digitalMap(state) - buttonState; + int8_t stateChange = digitalMap(pin, state) - buttonState; if (stateChange == falling) { // Button is pushed @@ -47,7 +47,7 @@ void DigitalCC::refresh() { // Check if the button state changed, and send a MI } } -void DigitalCC::map(int (*fn)(int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() +void DigitalCC::map(int (*fn)(int, int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() { digitalMap = fn; } \ No newline at end of file diff --git a/src/MIDI_Outputs/DigitalCC.h b/src/MIDI_Outputs/DigitalCC.h index 3802ed8..0cc52e7 100644 --- a/src/MIDI_Outputs/DigitalCC.h +++ b/src/MIDI_Outputs/DigitalCC.h @@ -12,13 +12,13 @@ class DigitalCC : public MIDI_Control_Element DigitalCC(pin_t pin, uint8_t controller, uint8_t channel); // Constructor ~DigitalCC(); // Destructor void invert(); // Invert the button state - void map(int (*fn)(int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() + void map(int (*fn)(int, int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() private: void refresh(); // Check if the button state changed, and send a MIDI CC accordingly - int (*digitalMap)(int) = identity; // function pointer to identity function f(x) → x + int (*digitalMap)(int, int) = identity; // function pointer to identity function f(x) → x - static int identity(int x) + static int identity(int p, int x) { // identity function f(x) → x return x; } diff --git a/src/MIDI_Outputs/MIDI_Control_Element.h b/src/MIDI_Outputs/MIDI_Control_Element.h index 3614b3b..9f83d42 100644 --- a/src/MIDI_Outputs/MIDI_Control_Element.h +++ b/src/MIDI_Outputs/MIDI_Control_Element.h @@ -19,7 +19,7 @@ class MIDI_Control_Element DELETE_FROM_LINKED_LIST(this, first, last); } - virtual void map(int (*fn)(int)) {} // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() and AnalogHiRes::refresh() + virtual void map(int (*fn)(int, int)) {} // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() and AnalogHiRes::refresh() virtual void invert() {} // Invert the button state (send Note On event when released, Note Off when pressed). It will be applied in Digital::refresh() void setChannelOffset(uint8_t offset); // Set the channel offset From 312e40fcf1ada81fe9b73d4477363ab29bbbadb8 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sat, 20 Jan 2018 23:02:44 +0100 Subject: [PATCH 05/16] Add pin to map function as first parameter int *(fn)(int, int) --- src/Banks/Bank.cpp | 2 +- src/Banks/Bank.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Banks/Bank.cpp b/src/Banks/Bank.cpp index 45ea8ca..d857c38 100644 --- a/src/Banks/Bank.cpp +++ b/src/Banks/Bank.cpp @@ -47,7 +47,7 @@ void Bank::setBankSetting(uint8_t bankSetting) } } -void Bank::map(int (*fn)(int)) +void Bank::map(int (*fn)(int, int)) { MIDI_Element_list_node *element = firstMIDI_Element; while (element != nullptr) diff --git a/src/Banks/Bank.h b/src/Banks/Bank.h index 0eee059..4c0e465 100644 --- a/src/Banks/Bank.h +++ b/src/Banks/Bank.h @@ -26,7 +26,7 @@ class Bank } void setBankSetting(uint8_t bankSetting); - void map(int (*fn)(int)); + void map(int (*fn)(int, int)); private: const uint8_t channelsPerBank; From 2625832434f3247873acd9107b6853479bc3c07b Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sun, 28 Jan 2018 18:59:05 +0100 Subject: [PATCH 06/16] added Program Change, Control Change to Digital removed DigitalCC --- src/MIDI_Outputs/Digital.cpp | 29 ++++++++++++++++++++++++++--- src/MIDI_Outputs/Digital.h | 4 ++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/MIDI_Outputs/Digital.cpp b/src/MIDI_Outputs/Digital.cpp index 9023c6f..8700ab2 100755 --- a/src/MIDI_Outputs/Digital.cpp +++ b/src/MIDI_Outputs/Digital.cpp @@ -3,10 +3,11 @@ using namespace ExtIO; -Digital::Digital(pin_t pin, uint8_t note, uint8_t channel, uint8_t velocity) // Constructor +Digital::Digital(pin_t pin, uint8_t msg, uint8_t note, uint8_t channel, uint8_t velocity) // Constructor { ExtIO::pinMode(pin, INPUT_PULLUP); // Enable the internal pull-up resistor on the pin with the button/switch this->pin = pin; + this->msg = msg; this->note = note; this->channel = channel; this->velocity = velocity; @@ -33,13 +34,35 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No if (stateChange == falling) { // Button is pushed buttonState = state; - MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); + switch (msg) { + case NOTE_ON: + MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); + break; + case CONTROL_CHANGE: + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, 127); + break; + case PROGRAM_CHANGE: + if (!invertState) + MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); + break; + } } if (stateChange == rising) { // Button is released buttonState = state; - MIDI_Controller.MIDI()->send(NOTE_OFF, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); + switch (msg) { + case NOTE_ON: + MIDI_Controller.MIDI()->send(NOTE_OFF, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); + break; + case CONTROL_CHANGE: + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, 0); + break; + case PROGRAM_CHANGE: + if (invertState) + MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); + break; + } } } if (state != prevState) diff --git a/src/MIDI_Outputs/Digital.h b/src/MIDI_Outputs/Digital.h index 52fe672..58f9184 100755 --- a/src/MIDI_Outputs/Digital.h +++ b/src/MIDI_Outputs/Digital.h @@ -9,7 +9,7 @@ class Digital : public MIDI_Control_Element { public: - Digital(pin_t pin, uint8_t note, uint8_t channel, uint8_t velocity = 127); // Constructor + Digital(pin_t pin, uint8_t msg, uint8_t note, uint8_t channel, uint8_t velocity = 127); // Constructor ~Digital(); // Destructor void invert(); // Invert the button state (send Note On event when released, Note Off when pressed) void map(int (*fn)(int, int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() @@ -24,7 +24,7 @@ class Digital : public MIDI_Control_Element } pin_t pin; - uint8_t note, channel, velocity; + uint8_t msg, note, channel, velocity; bool prevState = HIGH, buttonState = HIGH; unsigned long prevBounceTime = 0; From 332564854c2afa3d685d6b8072930d0a92bd207d Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sun, 28 Jan 2018 18:59:40 +0100 Subject: [PATCH 07/16] Delete DigitalCC.cpp --- src/MIDI_Outputs/DigitalCC.cpp | 53 ---------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 src/MIDI_Outputs/DigitalCC.cpp diff --git a/src/MIDI_Outputs/DigitalCC.cpp b/src/MIDI_Outputs/DigitalCC.cpp deleted file mode 100644 index 5a9e79c..0000000 --- a/src/MIDI_Outputs/DigitalCC.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "DigitalCC.h" -#include - -using namespace ExtIO; - -DigitalCC::DigitalCC(pin_t pin, uint8_t controller, uint8_t channel) // Constructor - : pin(pin), controller(controller), channel(channel) { - ExtIO::pinMode(pin, INPUT_PULLUP); // Enable the internal pull-up resistor on the pin with the button/switch -} - -DigitalCC::~DigitalCC() { // Destructor - ExtIO::pinMode(pin, INPUT); // make it a normal input again, without the internal pullup resistor. -} - -void DigitalCC::invert() // Invert the button state -{ - invertState = true; -} - -void DigitalCC::refresh() { // Check if the button state changed, and send a MIDI CC accordingly - bool state = ExtIO::digitalRead(pin) ^ invertState; // read the button state and invert it if "invert" is true - - if (millis() - prevBounceTime > debounceTime) - { - int8_t stateChange = digitalMap(pin, state) - buttonState; - - if (stateChange == falling) - { // Button is pushed - buttonState = state; - MIDI_Controller.MIDI()->send(CONTROL_CHANGE, - channel + channelOffset * channelsPerBank, - controller + addressOffset * channelsPerBank, 127); - } - - if (stateChange == rising) - { // Button is released - buttonState = state; - MIDI_Controller.MIDI()->send(CONTROL_CHANGE, - channel + channelOffset * channelsPerBank, - controller + addressOffset * channelsPerBank, 0); - } - } - if (state != prevState) - { - prevBounceTime = millis(); - prevState = state; - } -} - -void DigitalCC::map(int (*fn)(int, int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() -{ - digitalMap = fn; -} \ No newline at end of file From c3860152a70c4f2d13b8056e958c1f7369f6b058 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sun, 28 Jan 2018 18:59:49 +0100 Subject: [PATCH 08/16] Delete DigitalCC.h --- src/MIDI_Outputs/DigitalCC.h | 39 ------------------------------------ 1 file changed, 39 deletions(-) delete mode 100644 src/MIDI_Outputs/DigitalCC.h diff --git a/src/MIDI_Outputs/DigitalCC.h b/src/MIDI_Outputs/DigitalCC.h deleted file mode 100644 index 0cc52e7..0000000 --- a/src/MIDI_Outputs/DigitalCC.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef DIGITALCC_H_ -#define DIGITALCC_H_ - -#include "Arduino.h" -#include "MIDI_Control_Element.h" -#include "../Settings/Settings.h" -#include "../ExtendedInputOutput/ExtendedInputOutput.h" - -class DigitalCC : public MIDI_Control_Element -{ -public: - DigitalCC(pin_t pin, uint8_t controller, uint8_t channel); // Constructor - ~DigitalCC(); // Destructor - void invert(); // Invert the button state - void map(int (*fn)(int, int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() - -private: - void refresh(); // Check if the button state changed, and send a MIDI CC accordingly - int (*digitalMap)(int, int) = identity; // function pointer to identity function f(x) → x - - static int identity(int p, int x) - { // identity function f(x) → x - return x; - } - - pin_t pin; - uint8_t controller, channel; - bool prevState = HIGH, buttonState = HIGH; - unsigned long prevBounceTime = 0; - - bool invertState = false; - - const static unsigned long debounceTime = BUTTON_DEBOUNCE_TIME; - - const static int8_t falling = LOW - HIGH; - const static int8_t rising = HIGH - LOW; -}; - -#endif \ No newline at end of file From e2f2a2d2acd9d0a8ddcbaaae2c089d9c902858da Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Wed, 31 Jan 2018 11:10:00 +0100 Subject: [PATCH 09/16] Add push() and release() method --- src/MIDI_Outputs/Analog.cpp | 12 ++++- src/MIDI_Outputs/Analog.h | 2 + src/MIDI_Outputs/AnalogResponsive.cpp | 12 ++++- src/MIDI_Outputs/AnalogResponsive.h | 6 ++- src/MIDI_Outputs/Digital.cpp | 56 +++++++++++++---------- src/MIDI_Outputs/Digital.h | 6 ++- src/MIDI_Outputs/DigitalLatch.cpp | 60 ++++++++++++++++++++++--- src/MIDI_Outputs/DigitalLatch.h | 18 ++++++-- src/MIDI_Outputs/MIDI_Control_Element.h | 4 +- 9 files changed, 136 insertions(+), 40 deletions(-) diff --git a/src/MIDI_Outputs/Analog.cpp b/src/MIDI_Outputs/Analog.cpp index ed23ba8..d92d5dc 100755 --- a/src/MIDI_Outputs/Analog.cpp +++ b/src/MIDI_Outputs/Analog.cpp @@ -11,6 +11,16 @@ Analog::Analog(pin_t analogPin, uint8_t controllerNumber, uint8_t channel) // Co this->channel = channel; } +void Analog::push() // +{ + MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, 127); // send a Control Change MIDI event +} + +void Analog::release() // +{ + MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, 0); // send a Control Change MIDI event +} + void Analog::invert() // Invert the button state (send Note On event when released, Note Off when pressed) { invertState = true; @@ -20,7 +30,7 @@ void Analog::refresh() // read the analog value, update the average, map it to a { unsigned int input = ExtIO::analogRead(analogPin); // read the raw analog input value if (invertState) input = 1023-input; // invert the scale - input = analogMap(analogPin, input); // apply the analogMap function to the value (identity function f(x) = x by default) + input = analogMap(analogPin, input); // apply the analogMap function to the value (identity function f(x) = x by default) #ifdef SINGLE_BYTE_AVERAGE // use 8-bit value for averaging uint8_t value = input >> 2; // map from the 10-bit analog input value [0, 1023] to the 8-bit value [0, 255] diff --git a/src/MIDI_Outputs/Analog.h b/src/MIDI_Outputs/Analog.h index ee007dc..ceccb27 100755 --- a/src/MIDI_Outputs/Analog.h +++ b/src/MIDI_Outputs/Analog.h @@ -10,6 +10,8 @@ class Analog : public MIDI_Control_Element { public: Analog(pin_t analogPin, uint8_t controllerNumber, uint8_t channel); // Constructor + void push(); + void release(); void invert(); // Invert the analog scale void map(int (*fn)(int, int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 231104b..66535df 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -17,6 +17,16 @@ AnalogResponsive::~AnalogResponsive() // Destructor delete respAnalog; } +void AnalogResponsive::push() // +{ + MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, 1023); // send a Control Change MIDI event +} + +void AnalogResponsive::release() // +{ + MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, 0); // send a Control Change MIDI event +} + void AnalogResponsive::invert() // Invert the button state (send Note On event when released, Note Off when pressed) { invertState = true; @@ -26,7 +36,7 @@ void AnalogResponsive::refresh() // read the analog value, update the average, m { unsigned int input = ExtIO::analogRead(analogPin); // read the raw analog input value if (invertState) input = 1023-input; // invert the scale - uint16_t value = analogMap(analogPin, input); // apply the analogMap function to the value (identity function f(x) = x by default) + uint16_t value = analogMap(analogPin, input); // apply the analogMap function to the value (identity function f(x) = x by default) respAnalog->update(value); // update the responsive analog average if (respAnalog->hasChanged()) // if the value changed since last time { diff --git a/src/MIDI_Outputs/AnalogResponsive.h b/src/MIDI_Outputs/AnalogResponsive.h index 474c330..f88c8f5 100644 --- a/src/MIDI_Outputs/AnalogResponsive.h +++ b/src/MIDI_Outputs/AnalogResponsive.h @@ -12,8 +12,10 @@ class AnalogResponsive : public MIDI_Control_Element public: AnalogResponsive(pin_t analogPin, uint8_t controllerNumber, uint8_t channel); // Constructor ~AnalogResponsive(); // Destructor - void invert(); // Invert the analog scale - void map(int (*fn)(int, int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() + void push(); + void release(); + void invert(); // Invert the analog scale + void map(int (*fn)(int, int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() private: void refresh(); // Read the analog input value, update the average, map it to a MIDI value, check if it changed since last time, if so, send Control Change message over MIDI diff --git a/src/MIDI_Outputs/Digital.cpp b/src/MIDI_Outputs/Digital.cpp index 8700ab2..4cba684 100755 --- a/src/MIDI_Outputs/Digital.cpp +++ b/src/MIDI_Outputs/Digital.cpp @@ -18,23 +18,9 @@ Digital::~Digital() // Destructor ExtIO::pinMode(pin, INPUT); // make it a normal input again, without the internal pullup resistor. } -void Digital::invert() // Invert the button state (send Note On event when released, Note Off when pressed) -{ - invertState = true; -} - -void Digital::refresh() // Check if the button state changed, and send a MIDI Note On or Off accordingly +void Digital::push() // { - bool state = ExtIO::digitalRead(pin) ^ invertState; // read the button state and invert it if "invert" is true - - if (millis() - prevBounceTime > debounceTime) - { - int8_t stateChange = digitalMap(pin, state) - buttonState; - - if (stateChange == falling) - { // Button is pushed - buttonState = state; - switch (msg) { + switch (msg) { case NOTE_ON: MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); break; @@ -45,13 +31,12 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No if (!invertState) MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); break; - } - } + } +} - if (stateChange == rising) - { // Button is released - buttonState = state; - switch (msg) { +void Digital::release() // +{ + switch (msg) { case NOTE_ON: MIDI_Controller.MIDI()->send(NOTE_OFF, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); break; @@ -62,7 +47,32 @@ void Digital::refresh() // Check if the button state changed, and send a MIDI No if (invertState) MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); break; - } + } +} + +void Digital::invert() // Invert the button state (send Note On event when released, Note Off when pressed) +{ + invertState = true; +} + +void Digital::refresh() // Check if the button state changed, and send a MIDI Note On or Off accordingly +{ + bool state = ExtIO::digitalRead(pin) ^ invertState; // read the button state and invert it if "invert" is true + + if (millis() - prevBounceTime > debounceTime) + { + int8_t stateChange = digitalMap(pin, state) - buttonState; + + if (stateChange == falling) + { // Button is pushed + buttonState = state; + this->push(); + } + + if (stateChange == rising) + { // Button is released + buttonState = state; + this->release(); } } if (state != prevState) diff --git a/src/MIDI_Outputs/Digital.h b/src/MIDI_Outputs/Digital.h index 58f9184..45b5da0 100755 --- a/src/MIDI_Outputs/Digital.h +++ b/src/MIDI_Outputs/Digital.h @@ -10,8 +10,10 @@ class Digital : public MIDI_Control_Element { public: Digital(pin_t pin, uint8_t msg, uint8_t note, uint8_t channel, uint8_t velocity = 127); // Constructor - ~Digital(); // Destructor - void invert(); // Invert the button state (send Note On event when released, Note Off when pressed) + ~Digital(); // Destructor + void push(); + void release(); + void invert(); // Invert the button state (send Note On event when released, Note Off when pressed) void map(int (*fn)(int, int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() private: diff --git a/src/MIDI_Outputs/DigitalLatch.cpp b/src/MIDI_Outputs/DigitalLatch.cpp index 22222f8..6d84b95 100755 --- a/src/MIDI_Outputs/DigitalLatch.cpp +++ b/src/MIDI_Outputs/DigitalLatch.cpp @@ -3,10 +3,11 @@ using namespace ExtIO; -DigitalLatch::DigitalLatch(pin_t pin, uint8_t note, uint8_t channel, uint8_t velocity, unsigned long latchTime) // Constructor +DigitalLatch::DigitalLatch(pin_t pin, uint8_t msg, uint8_t note, uint8_t channel, uint8_t velocity, unsigned long latchTime) // Constructor { ExtIO::pinMode(pin, INPUT_PULLUP); // Enable the internal pull-up resistor on the pin with the button/switch this->pin = pin; + this->msg = msg; this->note = note; this->channel = channel; this->velocity = velocity; @@ -18,28 +19,73 @@ DigitalLatch::~DigitalLatch() // Destructor ExtIO::pinMode(pin, INPUT); // make it a normal input again, without the internal pullup resistor. } +void DigitalLatch::push() // +{ + switch (msg) { + case NOTE_ON: + MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); + break; + case CONTROL_CHANGE: + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, 127); + break; + case PROGRAM_CHANGE: + if (!invertState) + MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); + break; + } +} + +void DigitalLatch::release() // +{ + switch (msg) { + case NOTE_ON: + MIDI_Controller.MIDI()->send(NOTE_OFF, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); + break; + case CONTROL_CHANGE: + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, 0); + break; + case PROGRAM_CHANGE: + if (invertState) + MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); + break; + } +} + +void DigitalLatch::invert() // Invert the button state (send Note On event when released, Note Off when pressed) +{ + invertState = true; +} + void DigitalLatch::refresh() // Check if the button state changed, if so, send a MIDI Note On, after a non-blocking delay of "latchTime", send a Note Off { - bool state = ExtIO::digitalRead(pin); // read the button state + bool state = ExtIO::digitalRead(pin) ^ invertState; // read the button state and invert it if "invert" is true + + state = digitalMap(pin, state); + if (state != oldState) // If the switch changed position { if (noteOffSent) // If the note is turned off { - MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); // Turn on the note + this->push(); noteOnTime = millis(); // store the time of the note on message noteOffSent = false; // The note is turned on } else // If the button is switched again, before latch time is reached { - MIDI_Controller.MIDI()->send(NOTE_OFF, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); // Turn off the note - MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); // Immediately turn the note on again - noteOnTime = millis(); // store the time of the note on message + this->release(); // Turn off the note + this->push(); // Immediately turn the note on again + noteOnTime = millis(); // store the time of the note on message } oldState = state; } if (millis() - noteOnTime > latchTime && !noteOffSent) // if the time elapsed since the Note On event is greater than the latch time, and if the note is still on { - MIDI_Controller.MIDI()->send(NOTE_OFF, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank, velocity); // Turn off the note + this->release(); noteOffSent = true; // The note is turned off } +} + +void DigitalLatch::map(int (*fn)(int, int)) // change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in Digital::refresh() +{ + digitalMap = fn; } \ No newline at end of file diff --git a/src/MIDI_Outputs/DigitalLatch.h b/src/MIDI_Outputs/DigitalLatch.h index 7e02448..55654dc 100755 --- a/src/MIDI_Outputs/DigitalLatch.h +++ b/src/MIDI_Outputs/DigitalLatch.h @@ -8,18 +8,30 @@ class DigitalLatch : public MIDI_Control_Element { public: - DigitalLatch(pin_t pin, uint8_t note, uint8_t channel, uint8_t velocity, unsigned long latchTime); // Constructor + DigitalLatch(pin_t pin, uint8_t msg, uint8_t note, uint8_t channel, uint8_t velocity = 127, unsigned long latchTime = 100); // Constructor ~DigitalLatch(); // Destructor + void push(); + void release(); + void invert(); // Invert the button state (send Note On event when released, Note Off when pressed) + void map(int (*fn)(int, int)); // Change the function pointer for digitalMap to a new function. It will be applied to the raw digital input value in DigitalLatch::refresh() -private: + private: void refresh(); // Check if the button state changed, if so, send a MIDI Note On, after a non-blocking delay of "latchTime", send a Note Off + int (*digitalMap)(int, int) = identity; // function pointer to identity function f(x) → x + static int identity(int p, int x) + { // identity function f(x) → x + return x; + } + pin_t pin; - uint8_t note, channel, velocity; + uint8_t msg, note, channel, velocity; bool oldState = HIGH; bool noteOffSent = true; unsigned long latchTime; unsigned long noteOnTime; + + bool invertState = false; }; #endif diff --git a/src/MIDI_Outputs/MIDI_Control_Element.h b/src/MIDI_Outputs/MIDI_Control_Element.h index 9f83d42..3109fff 100644 --- a/src/MIDI_Outputs/MIDI_Control_Element.h +++ b/src/MIDI_Outputs/MIDI_Control_Element.h @@ -18,7 +18,9 @@ class MIDI_Control_Element { DELETE_FROM_LINKED_LIST(this, first, last); } - + + virtual void push() {} + virtual void release() {} virtual void map(int (*fn)(int, int)) {} // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() and AnalogHiRes::refresh() virtual void invert() {} // Invert the button state (send Note On event when released, Note Off when pressed). It will be applied in Digital::refresh() From b7b86e823b3e27f3f66d91058ad4e61d714a04c2 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sat, 3 Feb 2018 23:12:21 +0100 Subject: [PATCH 10/16] Added PITCH_BEND midi event --- src/MIDI_Outputs/AnalogResponsive.cpp | 30 +++++++++++++++++++++------ src/MIDI_Outputs/AnalogResponsive.h | 8 +++---- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 66535df..55471ad 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -4,9 +4,10 @@ using namespace ExtIO; -AnalogResponsive::AnalogResponsive(pin_t analogPin, uint8_t controllerNumber, uint8_t channel) // Constructor +AnalogResponsive::AnalogResponsive(pin_t analogPin, uint8_t msg, uint8_t controllerNumber, uint8_t channel) // Constructor { this->analogPin = analogPin; + this->msg = msg; this->controllerNumber = controllerNumber; this->channel = channel; this->respAnalog = new ResponsiveAnalogRead(analogPin, true); @@ -17,14 +18,27 @@ AnalogResponsive::~AnalogResponsive() // Destructor delete respAnalog; } -void AnalogResponsive::push() // +void AnalogResponsive::push(uint16_t value) // { - MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, 1023); // send a Control Change MIDI event + switch (msg) { + case NOTE_ON: + MIDI_Controller.MIDI()->send(NOTE_ON, channel + channelOffset * channelsPerBank, value, 127); + break; + case CONTROL_CHANGE: + MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, value); + break; + case PROGRAM_CHANGE: + MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, value); + break; + case PITCH_BEND: + MIDI_Controller.MIDI()->send(PITCH_BEND, channel + channelOffset * channelsPerBank, value, value >> 7); + break; + } } -void AnalogResponsive::release() // +void AnalogResponsive::release(uint16_t value) // { - MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, 0); // send a Control Change MIDI event + this->push(value); } void AnalogResponsive::invert() // Invert the button state (send Note On event when released, Note Off when pressed) @@ -41,7 +55,11 @@ void AnalogResponsive::refresh() // read the analog value, update the average, m if (respAnalog->hasChanged()) // if the value changed since last time { value = respAnalog->getValue(); // get the responsive analog average value - MIDI_Controller.MIDI()->send(CC, channel + channelOffset * channelsPerBank, controllerNumber + addressOffset * channelsPerBank, value); // send a Control Change MIDI event + if ( msg == PITCH_BEND) + { + value = value << 4; // make it a 14-bit number (pad with 4 zeros) + } + this->push(value); // send a MIDI event } } diff --git a/src/MIDI_Outputs/AnalogResponsive.h b/src/MIDI_Outputs/AnalogResponsive.h index f88c8f5..59313ac 100644 --- a/src/MIDI_Outputs/AnalogResponsive.h +++ b/src/MIDI_Outputs/AnalogResponsive.h @@ -10,10 +10,10 @@ class AnalogResponsive : public MIDI_Control_Element { public: - AnalogResponsive(pin_t analogPin, uint8_t controllerNumber, uint8_t channel); // Constructor + AnalogResponsive(pin_t analogPin, uint8_t msg, uint8_t controllerNumber, uint8_t channel); // Constructor ~AnalogResponsive(); // Destructor - void push(); - void release(); + void push(uint16_t value = 0x4000); + void release(uint16_t value = 0); void invert(); // Invert the analog scale void map(int (*fn)(int, int)); // Change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() @@ -22,7 +22,7 @@ class AnalogResponsive : public MIDI_Control_Element ResponsiveAnalogRead *respAnalog; pin_t analogPin; - uint8_t controllerNumber, channel, oldVal = -1; + uint8_t msg, controllerNumber, channel, oldVal = -1; int (*analogMap)(int, int) = identity; // function pointer to identity function f(x) → x static int identity(int p, int x) From 775b18e6ae8748ca42fbf391e3ca21565b2b7954 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Sat, 3 Feb 2018 23:13:19 +0100 Subject: [PATCH 11/16] Added PITCH_BEND midi event --- src/MIDI_Outputs/Digital.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/MIDI_Outputs/Digital.cpp b/src/MIDI_Outputs/Digital.cpp index 4cba684..0e93130 100755 --- a/src/MIDI_Outputs/Digital.cpp +++ b/src/MIDI_Outputs/Digital.cpp @@ -31,6 +31,9 @@ void Digital::push() // if (!invertState) MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); break; + case PITCH_BEND: + MIDI_Controller.MIDI()->send(PITCH_BEND, channel + channelOffset * channelsPerBank, 127, note + addressOffset * channelsPerBank); + break; } } @@ -47,6 +50,9 @@ void Digital::release() // if (invertState) MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel + channelOffset * channelsPerBank, note + addressOffset * channelsPerBank); break; + case PITCH_BEND: + MIDI_Controller.MIDI()->send(PITCH_BEND, channel + channelOffset * channelsPerBank, 0, note + addressOffset * channelsPerBank); + break; } } From 2739ffbeaf49385ab0ae883bf0992738e9444734 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Fri, 23 Feb 2018 20:43:42 +0100 Subject: [PATCH 12/16] Update MIDI_Control_Element.h --- src/MIDI_Outputs/MIDI_Control_Element.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MIDI_Outputs/MIDI_Control_Element.h b/src/MIDI_Outputs/MIDI_Control_Element.h index 3109fff..90d4b93 100644 --- a/src/MIDI_Outputs/MIDI_Control_Element.h +++ b/src/MIDI_Outputs/MIDI_Control_Element.h @@ -14,7 +14,7 @@ class MIDI_Control_Element { INSERT_INTO_LINKED_LIST(this, first, last); } - ~MIDI_Control_Element() // Destructor + virtual ~MIDI_Control_Element() // Destructor { DELETE_FROM_LINKED_LIST(this, first, last); } @@ -51,4 +51,4 @@ class MIDI_Control_Element static MIDI_Control_Element *first; }; -#endif // MIDI_CONTROL_ELEMENT_h \ No newline at end of file +#endif // MIDI_CONTROL_ELEMENT_h From 98f0ec19b5e1311f86de637e58ee339e723653cc Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Fri, 23 Feb 2018 20:46:05 +0100 Subject: [PATCH 13/16] Update AnalogResponsive.cpp --- src/MIDI_Outputs/AnalogResponsive.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 55471ad..41847e0 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -16,6 +16,7 @@ AnalogResponsive::AnalogResponsive(pin_t analogPin, uint8_t msg, uint8_t control AnalogResponsive::~AnalogResponsive() // Destructor { delete respAnalog; + DELETE_FROM_LINKED_LIST(this, first, last); } void AnalogResponsive::push(uint16_t value) // @@ -66,4 +67,4 @@ void AnalogResponsive::refresh() // read the analog value, update the average, m void AnalogResponsive::map(int (*fn)(int, int)) // change the function pointer for analogMap to a new function. It will be applied to the raw analog input value in Analog::refresh() { analogMap = fn; -} \ No newline at end of file +} From 15c5812a81794fe0fc7ec16c9b2623e1d778b3eb Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Fri, 23 Feb 2018 20:47:25 +0100 Subject: [PATCH 14/16] Update AnalogResponsive.cpp --- src/MIDI_Outputs/AnalogResponsive.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 41847e0..1fa7a13 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -16,7 +16,6 @@ AnalogResponsive::AnalogResponsive(pin_t analogPin, uint8_t msg, uint8_t control AnalogResponsive::~AnalogResponsive() // Destructor { delete respAnalog; - DELETE_FROM_LINKED_LIST(this, first, last); } void AnalogResponsive::push(uint16_t value) // From a080c0ef8623e629f7ac139e0a0710109d93abc7 Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Fri, 23 Feb 2018 21:49:38 +0100 Subject: [PATCH 15/16] Update AnalogResponsive.cpp --- src/MIDI_Outputs/AnalogResponsive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 1fa7a13..0cf6809 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -1,5 +1,5 @@ #include "Arduino.h" -#include "AnalogResponsive.h" +#include #include "MIDI_Controller.h" using namespace ExtIO; From 50de726b5a89b6fa56bf0218d777e9875797893d Mon Sep 17 00:00:00 2001 From: alf45tar <35426671+alf45tar@users.noreply.github.com> Date: Fri, 23 Feb 2018 21:54:58 +0100 Subject: [PATCH 16/16] Update AnalogResponsive.cpp --- src/MIDI_Outputs/AnalogResponsive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MIDI_Outputs/AnalogResponsive.cpp b/src/MIDI_Outputs/AnalogResponsive.cpp index 0cf6809..1fa7a13 100644 --- a/src/MIDI_Outputs/AnalogResponsive.cpp +++ b/src/MIDI_Outputs/AnalogResponsive.cpp @@ -1,5 +1,5 @@ #include "Arduino.h" -#include +#include "AnalogResponsive.h" #include "MIDI_Controller.h" using namespace ExtIO;