Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of system-level, i.e. all TG, MIDI control maps #704

Merged
merged 4 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ void CConfig::Load (void)
m_bMIDIAutoVoiceDumpOnPC = m_Properties.GetNumber ("MIDIAutoVoiceDumpOnPC", 0) != 0;
m_bHeaderlessSysExVoices = m_Properties.GetNumber ("HeaderlessSysExVoices", 0) != 0;
m_bExpandPCAcrossBanks = m_Properties.GetNumber ("ExpandPCAcrossBanks", 1) != 0;

m_nMIDISystemCCVol = m_Properties.GetNumber ("MIDISystemCCVol", 0);
m_nMIDISystemCCPan = m_Properties.GetNumber ("MIDISystemCCPan", 0);
m_nMIDISystemCCDetune = m_Properties.GetNumber ("MIDISystemCCDetune", 0);

m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0;
m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 4);
Expand Down Expand Up @@ -283,6 +287,11 @@ unsigned CConfig::GetEngineType (void) const
return m_EngineType;
}

bool CConfig::GetQuadDAC8Chan (void) const
{
return m_bQuadDAC8Chan;
}

unsigned CConfig::GetMIDIBaudRate (void) const
{
return m_nMIDIBaudRate;
Expand Down Expand Up @@ -323,9 +332,19 @@ bool CConfig::GetExpandPCAcrossBanks (void) const
return m_bExpandPCAcrossBanks;
}

bool CConfig::GetQuadDAC8Chan (void) const
unsigned CConfig::GetMIDISystemCCVol (void) const
{
return m_bQuadDAC8Chan;
return m_nMIDISystemCCVol;
}

unsigned CConfig::GetMIDISystemCCPan (void) const
{
return m_nMIDISystemCCPan;
}

unsigned CConfig::GetMIDISystemCCDetune (void) const
{
return m_nMIDISystemCCDetune;
}

bool CConfig::GetLCDEnabled (void) const
Expand Down
10 changes: 8 additions & 2 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class CConfig // Configuration for MiniDexed
unsigned GetDACI2CAddress (void) const; // 0 for auto probing
bool GetChannelsSwapped (void) const;
unsigned GetEngineType (void) const;
bool GetQuadDAC8Chan (void) const; // false if not specified

// MIDI
unsigned GetMIDIBaudRate (void) const;
Expand All @@ -127,7 +128,9 @@ class CConfig // Configuration for MiniDexed
bool GetMIDIAutoVoiceDumpOnPC (void) const; // false if not specified
bool GetHeaderlessSysExVoices (void) const; // false if not specified
bool GetExpandPCAcrossBanks (void) const; // true if not specified
bool GetQuadDAC8Chan (void) const; // false if not specified
unsigned GetMIDISystemCCVol (void) const;
unsigned GetMIDISystemCCPan (void) const;
unsigned GetMIDISystemCCDetune (void) const;

// HD44780 LCD
// GPIO pin numbers are chip numbers, not header positions
Expand Down Expand Up @@ -245,6 +248,7 @@ class CConfig // Configuration for MiniDexed
unsigned m_nDACI2CAddress;
bool m_bChannelsSwapped;
unsigned m_EngineType;
bool m_bQuadDAC8Chan;

unsigned m_nMIDIBaudRate;
std::string m_MIDIThruIn;
Expand All @@ -254,7 +258,9 @@ class CConfig // Configuration for MiniDexed
bool m_bMIDIAutoVoiceDumpOnPC;
bool m_bHeaderlessSysExVoices;
bool m_bExpandPCAcrossBanks;
bool m_bQuadDAC8Chan;
unsigned m_nMIDISystemCCVol;
unsigned m_nMIDISystemCCPan;
unsigned m_nMIDISystemCCDetune;

bool m_bLCDEnabled;
unsigned m_nLCDPinEnable;
Expand Down
104 changes: 103 additions & 1 deletion src/mididevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ LOGMODULE ("mididevice");
#define MIDI_PROGRAM_CHANGE 0b1100
#define MIDI_PITCH_BEND 0b1110

// MIDI "System" level (i.e. all TG) custom CC maps
// Note: Even if number of TGs is not 8, there are only 8
// available to be used in the mappings here.
#define NUM_MIDI_CC_MAPS 8
const unsigned MIDISystemCCMap[NUM_MIDI_CC_MAPS][8] = {
{0,0,0,0,0,0,0,0}, // 0 = disabled
{16,17,18,19,80,81,82,83}, // 1 = General Purpose Controllers 1-8
{20,21,22,23,24,25,26,27},
{52,53,54,55,56,57,58,59},
{102,103,104,105,106,107,108,109},
{110,111,112,113,114,115,116,117},
{3,9,14,15,28,29,30,31},
{35,41,46,47,60,61,62,63}
};

#define MIDI_SYSTEM_EXCLUSIVE_BEGIN 0xF0
#define MIDI_SYSTEM_EXCLUSIVE_END 0xF7
#define MIDI_TIMING_CLOCK 0xF8
Expand All @@ -69,6 +84,34 @@ CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInter
{
m_ChannelMap[nTG] = Disabled;
}

m_nMIDISystemCCVol = m_pConfig->GetMIDISystemCCVol();
m_nMIDISystemCCPan = m_pConfig->GetMIDISystemCCPan();
m_nMIDISystemCCDetune = m_pConfig->GetMIDISystemCCDetune();

m_MIDISystemCCBitmap[0] = 0;
m_MIDISystemCCBitmap[1] = 0;
m_MIDISystemCCBitmap[2] = 0;
m_MIDISystemCCBitmap[3] = 0;

for (int tg=0; tg<8; tg++)
{
if (m_nMIDISystemCCVol != 0) {
u8 cc = MIDISystemCCMap[m_nMIDISystemCCVol][tg];
m_MIDISystemCCBitmap[cc>>5] |= (1<<(cc%32));
}
if (m_nMIDISystemCCPan != 0) {
u8 cc = MIDISystemCCMap[m_nMIDISystemCCPan][tg];
m_MIDISystemCCBitmap[cc>>5] |= (1<<(cc%32));
}
if (m_nMIDISystemCCDetune != 0) {
u8 cc = MIDISystemCCMap[m_nMIDISystemCCDetune][tg];
m_MIDISystemCCBitmap[cc>>5] |= (1<<(cc%32));
}
}
if (m_pConfig->GetMIDIDumpEnabled ()) {
LOGNOTE("MIDI System CC Map: %08X %08X %08X %08X", m_MIDISystemCCBitmap[3],m_MIDISystemCCBitmap[2],m_MIDISystemCCBitmap[1],m_MIDISystemCCBitmap[0]);
}
}

CMIDIDevice::~CMIDIDevice (void)
Expand Down Expand Up @@ -239,7 +282,9 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
}

// Process MIDI for each active Tone Generator
for (unsigned nTG = 0; nTG < m_pConfig->GetToneGenerators(); nTG++)
bool bSystemCCHandled = false;
bool bSystemCCChecked = false;
for (unsigned nTG = 0; nTG < m_pConfig->GetToneGenerators() && !bSystemCCHandled; nTG++)
{
if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN)
{
Expand Down Expand Up @@ -373,6 +418,17 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
m_pSynthesizer->notesOff (pMessage[2], nTG);
}
break;

default:
// Check for system-level, cross-TG MIDI Controls, but only do it once.
// Also, if successfully handled, then no need to process other TGs,
// so it is possible to break out of the main TG loop too.
// Note: We handle this here so we get the TG MIDI channel checking.
if (!bSystemCCChecked) {
bSystemCCHandled = HandleMIDISystemCC(pMessage[1], pMessage[2]);
bSystemCCChecked = true;
}
break;
}
break;

Expand Down Expand Up @@ -418,6 +474,52 @@ void CMIDIDevice::AddDevice (const char *pDeviceName)
s_DeviceMap.insert (std::pair<std::string, CMIDIDevice *> (pDeviceName, this));
}

bool CMIDIDevice::HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval)
{
// This only makes sense when there are at least 8 TGs.
// Note: If more than 8 TGs then only 8 TGs are controllable this way.
if (m_pConfig->GetToneGenerators() < 8) {
return false;
}

// Quickly reject any CCs not in the configured maps
if ((m_MIDISystemCCBitmap[ucCC>>5] & (1<<(ucCC%32))) == 0) {
// Not in the map
return false;
}

// Not looking for duplicate CCs so return once handled
for (unsigned tg=0; tg<8; tg++) {
if (m_nMIDISystemCCVol != 0) {
if (ucCC == MIDISystemCCMap[m_nMIDISystemCCVol][tg]) {
m_pSynthesizer->SetVolume (ucCCval, tg);
return true;
}
}
if (m_nMIDISystemCCPan != 0) {
if (ucCC == MIDISystemCCMap[m_nMIDISystemCCPan][tg]) {
m_pSynthesizer->SetPan (ucCCval, tg);
return true;
}
}
if (m_nMIDISystemCCDetune != 0) {
if (ucCC == MIDISystemCCMap[m_nMIDISystemCCDetune][tg]) {
if (ucCCval == 0)
{
m_pSynthesizer->SetMasterTune (0, tg);
}
else
{
m_pSynthesizer->SetMasterTune (maplong (ucCCval, 1, 127, -99, 99), tg);
}
return true;
}
}
}

return false;
}

void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG)
{
int16_t sysex_return;
Expand Down
9 changes: 9 additions & 0 deletions src/mididevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,21 @@ class CMIDIDevice
void MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsigned nCable = 0);
void AddDevice (const char *pDeviceName);
void HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG);

private:
bool HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval);

private:
CMiniDexed *m_pSynthesizer;
CConfig *m_pConfig;
CUserInterface *m_pUI;

u8 m_ChannelMap[CConfig::AllToneGenerators];

unsigned m_nMIDISystemCCVol;
unsigned m_nMIDISystemCCPan;
unsigned m_nMIDISystemCCDetune;
u32 m_MIDISystemCCBitmap[4]; // to allow for 128 bit entries

std::string m_DeviceName;

Expand Down
Loading