You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MiniDexed/src/userinterface.cpp

458 lines
12 KiB

Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
//
// userinterface.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 "userinterface.h"
#include "minidexed.h"
#include <circle/logger.h>
#include <circle/string.h>
#include <circle/startup.h>
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
#include <string.h>
#include <assert.h>
LOGMODULE ("ui");
CUserInterface::CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster, CSPIMaster *pSPIMaster, CConfig *pConfig)
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
: m_pMiniDexed (pMiniDexed),
m_pGPIOManager (pGPIOManager),
m_pI2CMaster (pI2CMaster),
m_pSPIMaster (pSPIMaster),
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
m_pConfig (pConfig),
m_pLCD (0),
m_pLCDBuffered (0),
m_pUIButtons (0),
m_pRotaryEncoder (0),
m_bSwitchPressed (false),
m_Menu (this, pMiniDexed)
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
{
}
CUserInterface::~CUserInterface (void)
{
delete m_pRotaryEncoder;
delete m_pUIButtons;
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
delete m_pLCDBuffered;
delete m_pLCD;
}
bool CUserInterface::Initialize (void)
{
assert (m_pConfig);
if (m_pConfig->GetLCDEnabled ())
{
unsigned i2caddr = m_pConfig->GetLCDI2CAddress ();
unsigned ssd1306addr = m_pConfig->GetSSD1306LCDI2CAddress ();
bool st7789 = m_pConfig->GetST7789Enabled ();
if (ssd1306addr != 0) {
m_pSSD1306 = new CSSD1306Device (m_pConfig->GetSSD1306LCDWidth (), m_pConfig->GetSSD1306LCDHeight (),
m_pI2CMaster, ssd1306addr,
m_pConfig->GetSSD1306LCDRotate (), m_pConfig->GetSSD1306LCDMirror ());
if (!m_pSSD1306->Initialize ())
{
LOGDBG("LCD: SSD1306 initialization failed");
return false;
}
LOGDBG ("LCD: SSD1306");
m_pLCD = m_pSSD1306;
}
else if (st7789)
{
if (m_pSPIMaster == nullptr)
{
LOGDBG("LCD: ST7789 Enabled but SPI Initialisation Failed");
return false;
}
unsigned long nSPIClock = 1000 * m_pConfig->GetSPIClockKHz();
unsigned nSPIMode = m_pConfig->GetSPIMode();
unsigned nCPHA = (nSPIMode & 1) ? 1 : 0;
unsigned nCPOL = (nSPIMode & 2) ? 1 : 0;
LOGDBG("SPI: CPOL=%u; CPHA=%u; CLK=%u",nCPOL,nCPHA,nSPIClock);
m_pST7789Display = new CST7789Display (m_pSPIMaster,
m_pConfig->GetST7789Data(),
m_pConfig->GetST7789Reset(),
m_pConfig->GetST7789Backlight(),
m_pConfig->GetST7789Width(),
m_pConfig->GetST7789Height(),
nCPOL, nCPHA, nSPIClock,
m_pConfig->GetST7789Select());
if (m_pST7789Display->Initialize())
{
m_pST7789Display->SetRotation (m_pConfig->GetST7789Rotation());
bool bLargeFont = !(m_pConfig->GetST7789SmallFont());
m_pST7789 = new CST7789Device (m_pSPIMaster, m_pST7789Display, m_pConfig->GetLCDColumns (), m_pConfig->GetLCDRows (), bLargeFont, bLargeFont);
if (m_pST7789->Initialize())
{
LOGDBG ("LCD: ST7789");
m_pLCD = m_pST7789;
}
else
{
LOGDBG ("LCD: Failed to initalize ST7789 character device");
delete (m_pST7789);
delete (m_pST7789Display);
m_pST7789 = nullptr;
m_pST7789Display = nullptr;
return false;
}
}
else
{
LOGDBG ("LCD: Failed to initialize ST7789 display");
delete (m_pST7789Display);
m_pST7789Display = nullptr;
return false;
}
}
else if (i2caddr == 0)
{
m_pHD44780 = new CHD44780Device (m_pConfig->GetLCDColumns (), m_pConfig->GetLCDRows (),
m_pConfig->GetLCDPinData4 (),
m_pConfig->GetLCDPinData5 (),
m_pConfig->GetLCDPinData6 (),
m_pConfig->GetLCDPinData7 (),
m_pConfig->GetLCDPinEnable (),
m_pConfig->GetLCDPinRegisterSelect (),
m_pConfig->GetLCDPinReadWrite ());
if (!m_pHD44780->Initialize ())
{
LOGDBG("LCD: HD44780 initialization failed");
return false;
}
LOGDBG ("LCD: HD44780");
m_pLCD = m_pHD44780;
}
else
{
m_pHD44780 = new CHD44780Device (m_pI2CMaster, i2caddr,
m_pConfig->GetLCDColumns (), m_pConfig->GetLCDRows ());
if (!m_pHD44780->Initialize ())
{
LOGDBG("LCD: HD44780 (I2C) initialization failed");
return false;
}
LOGDBG ("LCD: HD44780 I2C");
m_pLCD = m_pHD44780;
}
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
assert (m_pLCD);
m_pLCDBuffered = new CWriteBufferDevice (m_pLCD);
assert (m_pLCDBuffered);
LCDWrite ("\x1B[?25l\x1B""d+"); // cursor off, autopage mode
LCDWrite ("MiniDexed\nLoading...");
m_pLCDBuffered->Update ();
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
LOGDBG ("LCD initialized");
}
m_pUIButtons = new CUIButtons ( m_pConfig->GetButtonPinPrev (),
m_pConfig->GetButtonActionPrev (),
m_pConfig->GetButtonPinNext (),
m_pConfig->GetButtonActionNext (),
m_pConfig->GetButtonPinBack (),
m_pConfig->GetButtonActionBack (),
m_pConfig->GetButtonPinSelect (),
m_pConfig->GetButtonActionSelect (),
m_pConfig->GetButtonPinHome (),
m_pConfig->GetButtonActionHome (),
m_pConfig->GetButtonPinPgmUp (),
m_pConfig->GetButtonActionPgmUp (),
m_pConfig->GetButtonPinPgmDown (),
m_pConfig->GetButtonActionPgmDown (),
m_pConfig->GetButtonPinTGUp (),
m_pConfig->GetButtonActionTGUp (),
m_pConfig->GetButtonPinTGDown (),
m_pConfig->GetButtonActionTGDown (),
m_pConfig->GetDoubleClickTimeout (),
m_pConfig->GetLongPressTimeout (),
m_pConfig->GetMIDIButtonNotes (),
m_pConfig->GetMIDIButtonPrev (),
m_pConfig->GetMIDIButtonNext (),
m_pConfig->GetMIDIButtonBack (),
m_pConfig->GetMIDIButtonSelect (),
m_pConfig->GetMIDIButtonHome (),
m_pConfig->GetMIDIButtonPgmUp (),
m_pConfig->GetMIDIButtonPgmDown (),
m_pConfig->GetMIDIButtonTGUp (),
m_pConfig->GetMIDIButtonTGDown ()
);
assert (m_pUIButtons);
if (!m_pUIButtons->Initialize ())
{
return false;
}
m_pUIButtons->RegisterEventHandler (UIButtonsEventStub, this);
UISetMIDIButtonChannel (m_pConfig->GetMIDIButtonCh ());
LOGDBG ("Button User Interface initialized");
if (m_pConfig->GetEncoderEnabled ())
{
m_pRotaryEncoder = new CKY040 (m_pConfig->GetEncoderPinClock (),
m_pConfig->GetEncoderPinData (),
m_pConfig->GetButtonPinShortcut (),
m_pGPIOManager);
assert (m_pRotaryEncoder);
if (!m_pRotaryEncoder->Initialize ())
{
return false;
}
m_pRotaryEncoder->RegisterEventHandler (EncoderEventStub, this);
LOGDBG ("Rotary encoder initialized");
}
m_Menu.EventHandler (CUIMenu::MenuEventUpdate);
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
return true;
}
void CUserInterface::Process (void)
{
if (m_pLCDBuffered)
{
m_pLCDBuffered->Update ();
}
if (m_pUIButtons)
{
m_pUIButtons->Update();
}
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
}
void CUserInterface::ParameterChanged (void)
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
{
m_Menu.EventHandler (CUIMenu::MenuEventUpdate);
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
}
void CUserInterface::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp)
{
assert (pMenu);
assert (pParam);
assert (pValue);
CString Msg ("\x1B[H\E[?25l"); // cursor home and off
// first line
Msg.Append (pParam);
size_t nLen = strlen (pParam) + strlen (pMenu);
if (nLen < m_pConfig->GetLCDColumns ())
{
for (unsigned i = m_pConfig->GetLCDColumns ()-nLen; i > 0; i--)
{
Msg.Append (" ");
}
}
Msg.Append (pMenu);
// second line
CString Value (" ");
if (bArrowDown)
{
Value = "<"; // arrow left character
}
Value.Append (pValue);
if (bArrowUp)
{
if (Value.GetLength () < m_pConfig->GetLCDColumns ()-1)
{
for (unsigned i = m_pConfig->GetLCDColumns ()-Value.GetLength ()-1; i > 0; i--)
{
Value.Append (" ");
}
}
Value.Append (">"); // arrow right character
}
Msg.Append (Value);
if (Value.GetLength () < m_pConfig->GetLCDColumns ())
{
Msg.Append ("\x1B[K"); // clear end of line
}
LCDWrite (Msg);
}
Restructure code and add new features (#37) * Make synth parameters configurable * Add class CConfig, which holds the configuration * Add template config file minidexed.ini * Register panic handler in CKernel to allow to display assertions * Fix: Performance timer did not show correct percent value with HDMI * Add class CDexedAdapter Some Dexed methods require to be guarded from being interrupted by other Dexed calls. This is done in the class CDexedAdapter. * Add class CUserInterface The user interface should be implemented here. As a start it supports showing the program number and name on the LCD display. The LCD output is buffered, so that LCD writes from an IRQ handler are possible. * Move MIDI handling from CMiniDexed to specific classes * CMIDIDevice is the generic MIDI handler * CMIDIKeyboard handles USB audio class MIDI devices * CSerialMIDIDevice handles the serial MIDI device * Now all MIDI inputs can work simultaneous * Program change and bank select work with serial MIDI * Add headers to all files * Include voices.c in sysexfileloader.cpp * Cleanup Makefile * Support headless operation on Raspberry Pi 4 Some code cleanup for src/kernel.* * Code cleanup for src/minidexed.* Move implementation of constructors to minidexed.cpp Reorder member variables * Support multiple USB MIDI inputs at once * Maximum 2 inputs on Raspberry Pi 1-3 * Maximum 4 inputs on Raspberry Pi 4 * Suppress frequent messages in MIDI dump * Use minidexed.txt * Document `SoundDevice` in `minidexed.ini` Co-authored-by: probonopd <probonopd@users.noreply.github.com>
2 years ago
void CUserInterface::LCDWrite (const char *pString)
{
if (m_pLCDBuffered)
{
m_pLCDBuffered->Write (pString, strlen (pString));
}
}
void CUserInterface::EncoderEventHandler (CKY040::TEvent Event)
{
switch (Event)
{
case CKY040::EventSwitchDown:
m_bSwitchPressed = true;
break;
case CKY040::EventSwitchUp:
m_bSwitchPressed = false;
break;
case CKY040::EventClockwise:
if (m_bSwitchPressed) {
// We must reset the encoder switch button to prevent events from being
// triggered after the encoder is rotated
m_pUIButtons->ResetButton(m_pConfig->GetButtonPinShortcut());
m_Menu.EventHandler(CUIMenu::MenuEventPressAndStepUp);
}
else {
m_Menu.EventHandler(CUIMenu::MenuEventStepUp);
}
break;
case CKY040::EventCounterclockwise:
if (m_bSwitchPressed) {
m_pUIButtons->ResetButton(m_pConfig->GetButtonPinShortcut());
m_Menu.EventHandler(CUIMenu::MenuEventPressAndStepDown);
}
else {
m_Menu.EventHandler(CUIMenu::MenuEventStepDown);
}
break;
case CKY040::EventSwitchHold:
if (m_pRotaryEncoder->GetHoldSeconds () >= 120)
{
delete m_pLCD; // reset LCD
reboot ();
}
break;
default:
break;
}
}
void CUserInterface::EncoderEventStub (CKY040::TEvent Event, void *pParam)
{
CUserInterface *pThis = static_cast<CUserInterface *> (pParam);
assert (pThis != 0);
pThis->EncoderEventHandler (Event);
}
void CUserInterface::UIButtonsEventHandler (CUIButton::BtnEvent Event)
{
switch (Event)
{
case CUIButton::BtnEventPrev:
m_Menu.EventHandler (CUIMenu::MenuEventStepDown);
break;
case CUIButton::BtnEventNext:
m_Menu.EventHandler (CUIMenu::MenuEventStepUp);
break;
case CUIButton::BtnEventBack:
m_Menu.EventHandler (CUIMenu::MenuEventBack);
break;
case CUIButton::BtnEventSelect:
m_Menu.EventHandler (CUIMenu::MenuEventSelect);
break;
case CUIButton::BtnEventHome:
m_Menu.EventHandler (CUIMenu::MenuEventHome);
break;
case CUIButton::BtnEventPgmUp:
m_Menu.EventHandler (CUIMenu::MenuEventPgmUp);
break;
case CUIButton::BtnEventPgmDown:
m_Menu.EventHandler (CUIMenu::MenuEventPgmDown);
break;
case CUIButton::BtnEventTGUp:
m_Menu.EventHandler (CUIMenu::MenuEventTGUp);
break;
case CUIButton::BtnEventTGDown:
m_Menu.EventHandler (CUIMenu::MenuEventTGDown);
break;
default:
break;
}
}
void CUserInterface::UIButtonsEventStub (CUIButton::BtnEvent Event, void *pParam)
{
CUserInterface *pThis = static_cast<CUserInterface *> (pParam);
assert (pThis != 0);
pThis->UIButtonsEventHandler (Event);
}
void CUserInterface::UIMIDICmdHandler (unsigned nMidiCh, unsigned nMidiCmd, unsigned nMidiData1, unsigned nMidiData2)
{
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->BtnMIDICmdHandler (nMidiCmd, nMidiData1, nMidiData2);
}
}
void CUserInterface::UISetMIDIButtonChannel (unsigned uCh)
{
// Mirrors the logic in Performance Config for handling MIDI channel configuration
if (uCh == 0)
{
m_nMIDIButtonCh = CMIDIDevice::Disabled;
Performance file handling (#581) Implements #580 * Initial update in performance file handling. This change makes the 6-digit number in the filename indicate a performance "voice number" in MiniDexed. The external filename numbers will now match any Program Change messages using the common MIDI concept of user selecting 1..128 whilst internally they are treated as 0..127. Note: in the case of performances, performance 1 (index 0) is the Default "performance.ini" file for backwards compatibility. Also note that in this version, new performances, when saved, cannot occupy free slots between other performances - they are added to the end. Even though the filename standard gives 6 digit numbers, the actual number of performances is still limited to 256. * Start of subdirectory implementation for performance banks. * Initial version with performance banks, selectable over MIDI only. * Initial implementation of performance bank switching in the UI menu. * Remove debug information, fix few bugs, including PgmUpDown handling and performance numbers out of range. * Bugfixes for legacy cases when no performance directory exists plus some extra checks for saving and deleting performances. * Remove verbose debug options (doh!) * Fix a minor off-by-one error found in review. * Bugfix - removed redundant legacy check that results in out of order performance files being skipped on load. * Fix bug in MIDI button handling commands. * Fix for issue where wrong performance is selected [L] on new save. * Suggested update to UI to show bank/performance numbers. * Make performance bank select asynchronous to MIDI and UI to stop corruptions on loading performances. * Fix an assert that should be a run-time test. * Ensure bank selection works when PCCH is not enabled, and that UI remains consistent when changing banks. --------- Co-authored-by: Kevin <68612569+diyelectromusic@users.noreply.github.com>
4 months ago
LOGNOTE("MIDI Button channel not set");
}
else if (uCh <= CMIDIDevice::Channels)
{
m_nMIDIButtonCh = uCh - 1;
LOGNOTE("MIDI Button channel set to: %d", m_nMIDIButtonCh+1);
}
else
{
m_nMIDIButtonCh = CMIDIDevice::OmniMode;
Performance file handling (#581) Implements #580 * Initial update in performance file handling. This change makes the 6-digit number in the filename indicate a performance "voice number" in MiniDexed. The external filename numbers will now match any Program Change messages using the common MIDI concept of user selecting 1..128 whilst internally they are treated as 0..127. Note: in the case of performances, performance 1 (index 0) is the Default "performance.ini" file for backwards compatibility. Also note that in this version, new performances, when saved, cannot occupy free slots between other performances - they are added to the end. Even though the filename standard gives 6 digit numbers, the actual number of performances is still limited to 256. * Start of subdirectory implementation for performance banks. * Initial version with performance banks, selectable over MIDI only. * Initial implementation of performance bank switching in the UI menu. * Remove debug information, fix few bugs, including PgmUpDown handling and performance numbers out of range. * Bugfixes for legacy cases when no performance directory exists plus some extra checks for saving and deleting performances. * Remove verbose debug options (doh!) * Fix a minor off-by-one error found in review. * Bugfix - removed redundant legacy check that results in out of order performance files being skipped on load. * Fix bug in MIDI button handling commands. * Fix for issue where wrong performance is selected [L] on new save. * Suggested update to UI to show bank/performance numbers. * Make performance bank select asynchronous to MIDI and UI to stop corruptions on loading performances. * Fix an assert that should be a run-time test. * Ensure bank selection works when PCCH is not enabled, and that UI remains consistent when changing banks. --------- Co-authored-by: Kevin <68612569+diyelectromusic@users.noreply.github.com>
4 months ago
LOGNOTE("MIDI Button channel set to: OMNI");
}
}