Enable buttons on MIDI controllers to be used (#365)

* Initial commit for MIDI user interface button support.
Status: first successful build.

* Second try with more functionality plugged in and compiling...

* First "it seems to work for me" version for initial testing of MIDI buttons.

* Fix Off/Omni logic

* Fix order of Prev/Next when initialising the button UI.

Co-authored-by: Kevin <68612569+diyelectromusic@users.noreply.github.com>
pull/366/head^2
probonopd 2 years ago committed by GitHub
parent d53aeb40f5
commit c7168d434f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Makefile
  2. 37
      src/config.cpp
  3. 15
      src/config.h
  4. 19
      src/mididevice.cpp
  5. 4
      src/mididevice.h
  6. 4
      src/midikeyboard.cpp
  7. 2
      src/midikeyboard.h
  8. 55
      src/midipin.cpp
  9. 54
      src/midipin.h
  10. 6
      src/minidexed.cpp
  11. 11
      src/minidexed.ini
  12. 4
      src/pckeyboard.cpp
  13. 2
      src/pckeyboard.h
  14. 4
      src/serialmididevice.cpp
  15. 2
      src/serialmididevice.h
  16. 109
      src/uibuttons.cpp
  17. 27
      src/uibuttons.h
  18. 45
      src/userinterface.cpp
  19. 6
      src/userinterface.h

@ -9,7 +9,7 @@ CMSIS_DIR = ../CMSIS_5/CMSIS
OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \
mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \
sysexfileloader.o performanceconfig.o perftimer.o \
effect_compressor.o effect_platervbstereo.o uibuttons.o
effect_compressor.o effect_platervbstereo.o uibuttons.o midipin.o
OPTIMIZE = -O3

@ -104,6 +104,13 @@ void CConfig::Load (void)
m_nDoubleClickTimeout = m_Properties.GetNumber ("DoubleClickTimeout", 400);
m_nLongPressTimeout = m_Properties.GetNumber ("LongPressTimeout", 600);
m_nMIDIButtonCh = m_Properties.GetNumber ("MIDIButtonCh", 0);
m_nMIDIButtonPrev = m_Properties.GetNumber ("MIDIButtonPrev", 0);
m_nMIDIButtonNext = m_Properties.GetNumber ("MIDIButtonNext", 0);
m_nMIDIButtonBack = m_Properties.GetNumber ("MIDIButtonBack", 0);
m_nMIDIButtonSelect = m_Properties.GetNumber ("MIDIButtonSelect", 0);
m_nMIDIButtonHome = m_Properties.GetNumber ("MIDIButtonHome", 0);
m_bEncoderEnabled = m_Properties.GetNumber ("EncoderEnabled", 0) != 0;
m_nEncoderPinClock = m_Properties.GetNumber ("EncoderPinClock", 10);
m_nEncoderPinData = m_Properties.GetNumber ("EncoderPinData", 9);
@ -293,6 +300,36 @@ unsigned CConfig::GetLongPressTimeout (void) const
return m_nLongPressTimeout;
}
unsigned CConfig::GetMIDIButtonCh (void) const
{
return m_nMIDIButtonCh;
}
unsigned CConfig::GetMIDIButtonPrev (void) const
{
return m_nMIDIButtonPrev;
}
unsigned CConfig::GetMIDIButtonNext (void) const
{
return m_nMIDIButtonNext;
}
unsigned CConfig::GetMIDIButtonBack (void) const
{
return m_nMIDIButtonBack;
}
unsigned CConfig::GetMIDIButtonSelect (void) const
{
return m_nMIDIButtonSelect;
}
unsigned CConfig::GetMIDIButtonHome (void) const
{
return m_nMIDIButtonHome;
}
bool CConfig::GetEncoderEnabled (void) const
{
return m_bEncoderEnabled;

@ -117,6 +117,14 @@ public:
unsigned GetDoubleClickTimeout (void) const;
unsigned GetLongPressTimeout (void) const;
// MIDI Button Navigation
unsigned GetMIDIButtonCh (void) const;
unsigned GetMIDIButtonPrev (void) const;
unsigned GetMIDIButtonNext (void) const;
unsigned GetMIDIButtonBack (void) const;
unsigned GetMIDIButtonSelect (void) const;
unsigned GetMIDIButtonHome (void) const;
// KY-040 Rotary Encoder
// GPIO pin numbers are chip numbers, not header positions
bool GetEncoderEnabled (void) const;
@ -177,6 +185,13 @@ private:
unsigned m_nDoubleClickTimeout;
unsigned m_nLongPressTimeout;
unsigned m_nMIDIButtonCh;
unsigned m_nMIDIButtonPrev;
unsigned m_nMIDIButtonNext;
unsigned m_nMIDIButtonBack;
unsigned m_nMIDIButtonSelect;
unsigned m_nMIDIButtonHome;
bool m_bEncoderEnabled;
unsigned m_nEncoderPinClock;
unsigned m_nEncoderPinData;

@ -27,6 +27,7 @@
#include "config.h"
#include <stdio.h>
#include <assert.h>
#include "userinterface.h"
LOGMODULE ("mididevice");
@ -59,9 +60,10 @@ LOGMODULE ("mididevice");
CMIDIDevice::TDeviceMap CMIDIDevice::s_DeviceMap;
CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig)
CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI)
: m_pSynthesizer (pSynthesizer),
m_pConfig (pConfig)
m_pConfig (pConfig),
m_pUI (pUI)
{
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
{
@ -181,6 +183,19 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
}
else
{
// Perform any MiniDexed level MIDI handling before specific Tone Generators
switch (ucType)
{
case MIDI_CONTROL_CHANGE:
if (nLength < 3)
{
break;
}
m_pUI->UIMIDICCHandler (ucChannel, pMessage[1], pMessage[2]);
break;
}
// Process MIDI for each Tone Generator
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
{
if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN)

@ -28,6 +28,7 @@
#include <unordered_map>
#include <circle/types.h>
#include <circle/spinlock.h>
#include "userinterface.h"
class CMiniDexed;
@ -43,7 +44,7 @@ public:
};
public:
CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig);
CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI);
virtual ~CMIDIDevice (void);
void SetChannel (u8 ucChannel, unsigned nTG);
@ -59,6 +60,7 @@ protected:
private:
CMiniDexed *m_pSynthesizer;
CConfig *m_pConfig;
CUserInterface *m_pUI;
u8 m_ChannelMap[CConfig::ToneGenerators];

@ -35,8 +35,8 @@ TMIDIPacketHandler * const CMIDIKeyboard::s_pMIDIPacketHandler[MaxInstances] =
MIDIPacketHandler3
};
CMIDIKeyboard::CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, unsigned nInstance)
: CMIDIDevice (pSynthesizer, pConfig),
CMIDIKeyboard::CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI, unsigned nInstance)
: CMIDIDevice (pSynthesizer, pConfig, pUI),
m_nInstance (nInstance),
m_pMIDIDevice (0)
{

@ -39,7 +39,7 @@ public:
static const unsigned MaxInstances = 4;
public:
CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, unsigned nInstance = 0);
CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI, unsigned nInstance = 0);
~CMIDIKeyboard (void);
void Process (boolean bPlugAndPlayUpdated);

@ -0,0 +1,55 @@
//
// midipin.cpp
//
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2022 The MiniDexed Team
//
// 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 <http://www.gnu.org/licenses/>.
//
#include "midipin.h"
#include <circle/logger.h>
#include <assert.h>
LOGMODULE ("midipin");
CMIDIPin::CMIDIPin (unsigned nPinNumber)
: m_nPinNumber (nPinNumber),
m_nValue (HIGH)
{
}
CMIDIPin::~CMIDIPin (void)
{
}
unsigned CMIDIPin::Read (void)
{
return m_nValue;
}
void CMIDIPin::Write (unsigned nValue)
{
// Takes values in the MIDI controller range 0 to 127
// and OFF < 64 < ON.
// Simulates a PULLUP IO pin, so "true" is LOW (0)
if (nValue >= 64) {
// "on"
m_nValue = LOW;
} else {
// "off"
m_nValue = HIGH;
}
return;
}

@ -0,0 +1,54 @@
//
// midipin.h
//
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2022 The MiniDexed Team
//
// 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 <http://www.gnu.org/licenses/>.
//
#ifndef _midipin_h
#define _midipin_h
#include <circle/gpiopin.h>
#include <circle/types.h>
// MIDI CC numbers go 0 to 127.
// Normal GPIO pins are below 100.
// So use a "pin number" of 128 + MIDI CC message for a "MIDI Pin"
#define MIDI_PINS 128
#define ccToMidiPin(c) ((c)+MIDI_PINS)
#define MidiPinToCC(p) ((p)-MIDI_PINS)
#define isMidiPin(p) (((p)>=MIDI_PINS)?1:0)
class CMIDIPin
{
public:
CMIDIPin (unsigned nPinNumber); // pinNumber = ccToMidiPin (MIDI CC number)
~CMIDIPin (void);
// Will return MP_HIGH or MP_LOW.
// Should be treated as a PULLED UP IO pin
// i.e. treated as "active low" (LOW) when pressed.
unsigned Read (void);
// MIDI CC values >=64 will set the MIDI pin to LOW ("on")
// MIDI CC values <= 63 will set the MIDI pin to HIGH ("off")
void Write (unsigned nValue);
private:
unsigned m_nPinNumber;
unsigned m_nValue;
};
#endif

@ -39,8 +39,8 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pConfig (pConfig),
m_UI (this, pGPIOManager, pI2CMaster, pConfig),
m_PerformanceConfig (pFileSystem),
m_PCKeyboard (this, pConfig),
m_SerialMIDI (this, pInterrupt, pConfig),
m_PCKeyboard (this, pConfig, &m_UI),
m_SerialMIDI (this, pInterrupt, pConfig, &m_UI),
m_bUseSerial (false),
m_pSoundDevice (0),
m_bChannelsSwapped (pConfig->GetChannelsSwapped ()),
@ -98,7 +98,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++)
{
m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, i);
m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, &m_UI, i);
assert (m_pMIDIKeyboard[i]);
}

@ -57,6 +57,17 @@ ButtonPinShortcut=11
DoubleClickTimeout=400
LongPressTimeout=400
# MIDI Button Navigation
# Specify MIDI CC to act as a button
# NB: Off < 64 < ON
# CC channel: 0=OFF; 1-16 MIDI Ch; >16 Omni
MIDIButtonCh=0
MIDIButtonPrev=85
MIDIButtonNext=86
MIDIButtonHome=87
MIDIButtonSelect=89
MIDIButtonBack=90
# KY-040 Rotary Encoder
EncoderEnabled=1
EncoderPinClock=10

@ -60,8 +60,8 @@ static TKeyInfo KeyTable[] =
CPCKeyboard *CPCKeyboard::s_pThis = 0;
CPCKeyboard::CPCKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig)
: CMIDIDevice (pSynthesizer, pConfig),
CPCKeyboard::CPCKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI)
: CMIDIDevice (pSynthesizer, pConfig, pUI),
m_pKeyboard (0)
{
s_pThis = this;

@ -31,7 +31,7 @@ class CMiniDexed;
class CPCKeyboard : public CMIDIDevice
{
public:
CPCKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig);
CPCKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInterface *pUI);
~CPCKeyboard (void);
void Process (boolean bPlugAndPlayUpdated);

@ -29,8 +29,8 @@
LOGMODULE("serialmididevice");
CSerialMIDIDevice::CSerialMIDIDevice (CMiniDexed *pSynthesizer, CInterruptSystem *pInterrupt,
CConfig *pConfig)
: CMIDIDevice (pSynthesizer, pConfig),
CConfig *pConfig, CUserInterface *pUI)
: CMIDIDevice (pSynthesizer, pConfig, pUI),
m_pConfig (pConfig),
m_Serial (pInterrupt, TRUE),
m_nSerialState (0),

@ -38,7 +38,7 @@ class CMiniDexed;
class CSerialMIDIDevice : public CMIDIDevice
{
public:
CSerialMIDIDevice (CMiniDexed *pSynthesizer, CInterruptSystem *pInterrupt, CConfig *pConfig);
CSerialMIDIDevice (CMiniDexed *pSynthesizer, CInterruptSystem *pInterrupt, CConfig *pConfig, CUserInterface *pUI);
~CSerialMIDIDevice (void);
boolean Initialize (void);

@ -4,9 +4,6 @@
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2022 The MiniDexed Team
//
// Original author of this class:
// R. Stange <rsta2@o2online.de>
//
// 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
@ -31,6 +28,7 @@ LOGMODULE ("uibuttons");
CUIButton::CUIButton (void)
: m_pinNumber (0),
m_pin (0),
m_midipin (0),
m_lastValue (1),
m_timer (0),
m_debounceTimer (0),
@ -49,6 +47,10 @@ CUIButton::~CUIButton (void)
{
delete m_pin;
}
if (m_midipin)
{
delete m_midipin;
}
}
void CUIButton::reset (void)
@ -72,7 +74,14 @@ boolean CUIButton::Initialize (unsigned pinNumber, unsigned doubleClickTimeout,
if (m_pinNumber != 0)
{
m_pin = new CGPIOPin (m_pinNumber, GPIOModeInputPullUp);
if (isMidiPin(m_pinNumber))
{
LOGDBG("MIDI Button on pin: %d (%x)", m_pinNumber, m_pinNumber);
m_midipin = new CMIDIPin (m_pinNumber);
} else {
LOGDBG("GPIO Button on pin: %d (%x)", m_pinNumber, m_pinNumber);
m_pin = new CGPIOPin (m_pinNumber, GPIOModeInputPullUp);
}
}
return TRUE;
}
@ -99,13 +108,25 @@ unsigned CUIButton::getPinNumber(void)
CUIButton::BtnTrigger CUIButton::ReadTrigger (void)
{
if (!m_pin)
unsigned value;
if (isMidiPin(m_pinNumber))
{
// Always return "not pressed" if not configured
return BtnTriggerNone;
if (!m_midipin)
{
// Always return "not pressed" if not configured
return BtnTriggerNone;
}
value = m_midipin->Read();
}
else
{
if (!m_pin)
{
// Always return "not pressed" if not configured
return BtnTriggerNone;
}
value = m_pin->Read();
}
unsigned value = m_pin->Read();
if (m_timer < m_longPressTimeout) {
m_timer++;
@ -188,6 +209,15 @@ CUIButton::BtnTrigger CUIButton::ReadTrigger (void)
return BtnTriggerNone;
}
void CUIButton::Write (unsigned nValue) {
// This only makes sense for MIDI buttons.
if (m_midipin && isMidiPin(m_pinNumber))
{
// Update the "MIDI Pin"
m_midipin->Write(nValue);
}
}
CUIButton::BtnEvent CUIButton::Read (void) {
BtnTrigger trigger = ReadTrigger();
@ -233,7 +263,8 @@ CUIButtons::CUIButtons (
unsigned backPin, const char *backAction,
unsigned selectPin, const char *selectAction,
unsigned homePin, const char *homeAction,
unsigned doubleClickTimeout, unsigned longPressTimeout
unsigned doubleClickTimeout, unsigned longPressTimeout,
unsigned prevMidi, unsigned nextMidi, unsigned backMidi, unsigned selectMidi, unsigned homeMidi
)
: m_doubleClickTimeout(doubleClickTimeout),
m_longPressTimeout(longPressTimeout),
@ -247,6 +278,11 @@ CUIButtons::CUIButtons (
m_selectAction(CUIButton::triggerTypeFromString(selectAction)),
m_homePin(homePin),
m_homeAction(CUIButton::triggerTypeFromString(homeAction)),
m_prevMidi(ccToMidiPin(prevMidi)),
m_nextMidi(ccToMidiPin(nextMidi)),
m_backMidi(ccToMidiPin(backMidi)),
m_selectMidi(ccToMidiPin(selectMidi)),
m_homeMidi(ccToMidiPin(homeMidi)),
m_eventHandler (0),
m_lastTick (0)
{
@ -274,15 +310,27 @@ boolean CUIButtons::Initialize (void)
longPressTimeout = doubleClickTimeout;
}
// Each button can be assigned up to 3 actions: click, doubleclick and
// longpress. We may not initialise all of the buttons
// Each normal button can be assigned up to 3 actions: click, doubleclick and
// longpress. We may not initialise all of the buttons.
// MIDI buttons only support a single click.
unsigned pins[MAX_BUTTONS] = {
m_prevPin, m_nextPin, m_backPin, m_selectPin, m_homePin
m_prevPin, m_nextPin, m_backPin, m_selectPin, m_homePin,
m_prevMidi, m_nextMidi, m_backMidi, m_selectMidi, m_homeMidi
};
CUIButton::BtnTrigger triggers[MAX_BUTTONS] = {
m_prevAction, m_nextAction, m_backAction, m_selectAction, m_homeAction
// Normal buttons
m_prevAction, m_nextAction, m_backAction, m_selectAction, m_homeAction,
// MIDI Buttons only support a single click (at present)
CUIButton::BtnTriggerClick, CUIButton::BtnTriggerClick, CUIButton::BtnTriggerClick, CUIButton::BtnTriggerClick, CUIButton::BtnTriggerClick
};
CUIButton::BtnEvent events[MAX_BUTTONS] = {
// Normal buttons
CUIButton::BtnEventPrev,
CUIButton::BtnEventNext,
CUIButton::BtnEventBack,
CUIButton::BtnEventSelect,
CUIButton::BtnEventHome,
// MIDI buttons
CUIButton::BtnEventPrev,
CUIButton::BtnEventNext,
CUIButton::BtnEventBack,
@ -290,7 +338,8 @@ boolean CUIButtons::Initialize (void)
CUIButton::BtnEventHome
};
for (unsigned i=0; i<MAX_BUTTONS; i++) {
// Setup normal GPIO buttons first
for (unsigned i=0; i<MAX_GPIO_BUTTONS; i++) {
// if this pin is 0 it means it's disabled - so continue
if (pins[i] == 0) {
continue;
@ -311,6 +360,25 @@ boolean CUIButtons::Initialize (void)
}
}
}
// Now setup the MIDI buttons.
// Note: the configuration is simpler as the only trigger supported is a single, short press
for (unsigned i=MAX_GPIO_BUTTONS; i<MAX_BUTTONS; i++) {
// if this pin is 0 it means it's disabled - so continue
if (pins[i] == 0) {
continue;
}
// Carry on in the list from where GPIO buttons left off
for (unsigned j=0; j<MAX_BUTTONS; j++) {
if (m_buttons[j].getPinNumber() == 0) {
// This is un-initialised so can be assigned
// doubleClickTimeout and longPressTimeout are ignored for MIDI buttons at present
m_buttons[j].Initialize(pins[i], doubleClickTimeout, longPressTimeout);
break;
}
}
}
// All of the buttons are now initialised, they just need to have their
// events assigned to them
@ -390,3 +458,14 @@ void CUIButtons::ResetButton (unsigned pinNumber)
}
}
}
void CUIButtons::BtnMIDICCHandler (unsigned nMidiCC, unsigned nMidiData)
{
unsigned midiPin = ccToMidiPin(nMidiCC);
for (unsigned i=0; i<MAX_BUTTONS; i++) {
if (m_buttons[i].getPinNumber() == midiPin) {
m_buttons[i].Write (nMidiData);
}
}
}

@ -4,9 +4,6 @@
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
// Copyright (C) 2022 The MiniDexed Team
//
// Original author of this class:
// R. Stange <rsta2@o2online.de>
//
// 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
@ -25,11 +22,14 @@
#include <circle/gpiopin.h>
#include <circle/types.h>
#include "midipin.h"
#include "config.h"
#define BUTTONS_UPDATE_NUM_TICKS 100
#define DEBOUNCE_TIME 100
#define MAX_BUTTONS 5
#define MAX_GPIO_BUTTONS 5
#define MAX_MIDI_BUTTONS 5
#define MAX_BUTTONS (MAX_GPIO_BUTTONS+MAX_MIDI_BUTTONS)
class CUIButtons;
@ -69,14 +69,17 @@ public:
BtnTrigger ReadTrigger (void);
BtnEvent Read (void);
void Write (unsigned nValue); // MIDI buttons only!
static BtnTrigger triggerTypeFromString(const char* triggerString);
private:
// Pin number
unsigned m_pinNumber;
// GPIO pin
CGPIOPin *m_pin;
// MIDI pin
CMIDIPin *m_midipin;
// The value of the pin at the end of the last loop
unsigned m_lastValue;
// Set to 0 on press, increment each read, use to trigger events
@ -110,7 +113,8 @@ public:
unsigned backPin, const char *backAction,
unsigned selectPin, const char *selectAction,
unsigned homePin, const char *homeAction,
unsigned doubleClickTimeout, unsigned longPressTimeout
unsigned doubleClickTimeout, unsigned longPressTimeout,
unsigned prevMidi, unsigned nextMidi, unsigned backMidi, unsigned selectMidi, unsigned homeMidi
);
~CUIButtons (void);
@ -121,9 +125,11 @@ public:
void Update (void);
void ResetButton (unsigned pinNumber);
void BtnMIDICCHandler (unsigned nMidiCC, unsigned nMidiData);
private:
// Array of 5 buttons
// Array of normal GPIO buttons and "MIDI buttons"
CUIButton m_buttons[MAX_BUTTONS];
// Timeout for double click in tenths of a millisecond
@ -142,6 +148,13 @@ private:
CUIButton::BtnTrigger m_selectAction;
unsigned m_homePin;
CUIButton::BtnTrigger m_homeAction;
// MIDI button configuration
unsigned m_prevMidi;
unsigned m_nextMidi;
unsigned m_backMidi;
unsigned m_selectMidi;
unsigned m_homeMidi;
BtnEventHandler *m_eventHandler;
void *m_eventParam;

@ -114,7 +114,13 @@ bool CUserInterface::Initialize (void)
m_pConfig->GetButtonPinHome (),
m_pConfig->GetButtonActionHome (),
m_pConfig->GetDoubleClickTimeout (),
m_pConfig->GetLongPressTimeout () );
m_pConfig->GetLongPressTimeout (),
m_pConfig->GetMIDIButtonPrev (),
m_pConfig->GetMIDIButtonNext (),
m_pConfig->GetMIDIButtonBack (),
m_pConfig->GetMIDIButtonSelect (),
m_pConfig->GetMIDIButtonHome ()
);
assert (m_pUIButtons);
if (!m_pUIButtons->Initialize ())
@ -123,6 +129,7 @@ bool CUserInterface::Initialize (void)
}
m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this);
UISetMIDICCChannel (m_pConfig->GetMIDIButtonCh ());
LOGDBG ("Button User Interface initialized");
@ -322,3 +329,39 @@ void CUserInterface::UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam
pThis->UIButtonsEventHandler (Event);
}
void CUserInterface::UIMIDICCHandler (unsigned nMidiCh, unsigned nMidiCC, unsigned nMidiData)
{
if (m_nMIDIButtonCh == CMIDIDevice::Disabled)
{
// MIDI buttons are not enabled
return;
}
if ((m_nMIDIButtonCh != nMidiCh) && (m_nMIDIButtonCh != CMIDIDevice::OmniMode))
{
// Message not on the MIDI Button channel and MIDI buttons not in OMNI mode
return;
}
if (m_pUIButtons)
{
m_pUIButtons->BtnMIDICCHandler (nMidiCC, nMidiData);
}
}
void CUserInterface::UISetMIDICCChannel (unsigned uCh)
{
// Mirrors the logic in Performance Config for handling MIDI channel configuration
if (uCh == 0)
{
m_nMIDIButtonCh = CMIDIDevice::Disabled;
}
else if (uCh < CMIDIDevice::Channels)
{
m_nMIDIButtonCh = uCh - 1;
}
else
{
m_nMIDIButtonCh = CMIDIDevice::OmniMode;
}
}

@ -52,6 +52,9 @@ public:
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);
// To be called from the MIDI device on reception of a MIDI CC message
void UIMIDICCHandler (unsigned nMidiCh, unsigned nMidiCC, unsigned nMidiData);
private:
void LCDWrite (const char *pString); // Print to optional HD44780 display
@ -59,6 +62,7 @@ private:
static void EncoderEventStub (CKY040::TEvent Event, void *pParam);
void UIButtonsEventHandler (CUIButton::BtnEvent Event);
static void UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam);
void UISetMIDICCChannel (unsigned uCh);
private:
CMiniDexed *m_pMiniDexed;
@ -73,6 +77,8 @@ private:
CUIButtons *m_pUIButtons;
unsigned m_nMIDIButtonCh;
CKY040 *m_pRotaryEncoder;
bool m_bSwitchPressed;

Loading…
Cancel
Save