Skip to content

Commit

Permalink
Initial implementation of system-level, i.e. all TG, MIDI control maps (
Browse files Browse the repository at this point in the history
#704)

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

* Ensure msg only handled once by the first TG with a matching receiving MIDI channel.

* Optimise system CC handling esp when unrecognised CCs are received.

* Update in optimisation of System CC handling.
  • Loading branch information
diyelectromusic authored Sep 29, 2024
1 parent 6c56960 commit 8c18e60
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 5 deletions.
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

0 comments on commit 8c18e60

Please sign in to comment.