add DAW Display support for newer Arturia Keyboards with Display

based on https://github.com/PrzemekBarski/arturia-keylab-essential-mk3-programming-guide

Tested on a Arturia MiniLab 3

Probably works also on Keylab Essential mk3 / Keylab mk3
pull/743/head
Gergo Koteles 2 days ago
parent a4dcd4d8b2
commit 830843ded5
  1. 7
      src/config.cpp
  2. 4
      src/config.h
  3. 53
      src/midikeyboard.cpp
  4. 4
      src/midikeyboard.h
  5. 14
      src/minidexed.cpp
  6. 3
      src/minidexed.h
  7. 3
      src/minidexed.ini
  8. 32
      src/uimenu.cpp

@ -197,6 +197,8 @@ void CConfig::Load (void)
m_MIDIButtonActionTGUp = m_Properties.GetString ("MIDIButtonActionTGUp", "");
m_MIDIButtonActionTGDown = m_Properties.GetString ("MIDIButtonActionTGDown", "");
m_bDAWDisplayEnabled = m_Properties.GetNumber ("DAWDisplayEnabled", 0) != 0;
m_bEncoderEnabled = m_Properties.GetNumber ("EncoderEnabled", 0) != 0;
m_nEncoderPinClock = m_Properties.GetNumber ("EncoderPinClock", 10);
m_nEncoderPinData = m_Properties.GetNumber ("EncoderPinData", 9);
@ -703,6 +705,11 @@ const char *CConfig::GetMIDIButtonActionTGDown (void) const
return m_MIDIButtonActionTGDown.c_str();
}
bool CConfig::GetDAWDisplayEnabled (void) const
{
return m_bDAWDisplayEnabled;
}
bool CConfig::GetEncoderEnabled (void) const
{
return m_bEncoderEnabled;

@ -232,6 +232,8 @@ public:
const char *GetMIDIButtonActionTGUp (void) const;
const char *GetMIDIButtonActionTGDown (void) const;
bool GetDAWDisplayEnabled (void) const;
// KY-040 Rotary Encoder
// GPIO pin numbers are chip numbers, not header positions
bool GetEncoderEnabled (void) const;
@ -355,6 +357,8 @@ private:
std::string m_MIDIButtonActionTGUp;
std::string m_MIDIButtonActionTGDown;
bool m_bDAWDisplayEnabled;
bool m_bEncoderEnabled;
unsigned m_nEncoderPinClock;
unsigned m_nEncoderPinData;

@ -39,6 +39,7 @@ CMIDIKeyboard::CMIDIKeyboard (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserI
: CMIDIDevice (pSynthesizer, pConfig, pUI),
m_nSysExIdx (0),
m_nInstance (nInstance),
m_bDAWDisplayInitialized(false),
m_pMIDIDevice (0)
{
assert (m_nInstance < MaxInstances);
@ -87,6 +88,8 @@ void CMIDIKeyboard::Process (boolean bPlugAndPlayUpdated)
m_pMIDIDevice->RegisterRemovedHandler (DeviceRemovedHandler, this);
}
}
m_bDAWDisplayInitialized = false;
}
void CMIDIKeyboard::Send (const u8 *pMessage, size_t nLength, unsigned nCable)
@ -190,3 +193,53 @@ void CMIDIKeyboard::DeviceRemovedHandler (CDevice *pDevice, void *pContext)
pThis->m_pMIDIDevice = 0;
}
void CMIDIKeyboard::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp)
{
static unsigned L1MaxLen = 18;
static const uint8_t connect[] = {0xF0, 0x00, 0x20, 0x6B, 0x7F, 0x42, 0x02, 0x00, 0x40, 0x6A, 0x21, 0xF7};
static const uint8_t linesHdr[] = {0xF0, 0x00, 0x20, 0x6B, 0x7F, 0x42, 0x04, 0x02, 0x60, 0x12, 0x01};
CString line1 (pParam);
CString line2 (pValue);
size_t nLen = strlen (pParam) + strlen (pMenu);
if (nLen < L1MaxLen)
{
for (unsigned i = L1MaxLen - nLen; i > 0; i--)
{
line1.Append (" ");
}
}
line1.Append (pMenu);
int hdrLen = sizeof(linesHdr);
int line1Len = strlen(line1);
int line2Len = strlen(line2);
int offset = 0;
uint8_t lines[hdrLen + line1Len + 2 + line2Len + 2];
memcpy (lines, linesHdr, hdrLen);
offset += hdrLen;
memcpy (&lines[offset], line1, line1Len + 1);
offset += line1Len + 1;
lines[offset] = 0x02;
offset += 1;
memcpy (&lines[offset], line2, line2Len + 1);
offset += line2Len + 1;
lines[offset] = 0xf7;
offset += 1;
if (!m_bDAWDisplayInitialized) {
Send (connect, sizeof(connect), 0);
m_bDAWDisplayInitialized = true;
}
Send (lines, offset, 0);
}

@ -48,6 +48,9 @@ public:
void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) override;
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);
private:
static void MIDIPacketHandler0 (unsigned nCable, u8 *pPacket, unsigned nLength);
static void MIDIPacketHandler1 (unsigned nCable, u8 *pPacket, unsigned nLength);
@ -70,6 +73,7 @@ private:
private:
unsigned m_nInstance;
bool m_bDAWDisplayInitialized;
CString m_DeviceName;
CUSBMIDIDevice * volatile m_pMIDIDevice;

@ -1775,6 +1775,20 @@ void CMiniDexed::setMasterVolume (float32_t vol)
nMasterVolume=vol;
}
void CMiniDexed::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp)
{
m_UI.DisplayWrite (pMenu, pParam, pValue, bArrowDown, bArrowUp);
if (!m_pConfig->GetDAWDisplayEnabled())
return;
for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++)
{
m_pMIDIKeyboard[i]->DisplayWrite (pMenu, pParam, pValue, bArrowDown, bArrowUp);
}
}
std::string CMiniDexed::GetPerformanceFileName(unsigned nID)
{
return m_PerformanceConfig.GetPerformanceFileName(nID);

@ -228,6 +228,9 @@ public:
void setMasterVolume (float32_t vol);
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue,
bool bArrowDown, bool bArrowUp);
private:
int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note
uint8_t m_uchOPMask[CConfig::AllToneGenerators];

@ -139,6 +139,9 @@ MIDIButtonActionTGUp=
MIDIButtonTGDown=0
MIDIButtonActionTGDown=
# DAW Display (Arturia MiniLab 3 or other newer Arturias)
DAWDisplayEnabled=0
# KY-040 Rotary Encoder
EncoderEnabled=1
EncoderPinClock=10

@ -534,7 +534,7 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)
if (pUIMenu->m_pCurrentMenu) // if this is another menu?
{
pUIMenu->m_pUI->DisplayWrite (
pUIMenu->m_pMiniDexed->DisplayWrite (
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
"",
pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name,
@ -587,7 +587,7 @@ void CUIMenu::EditGlobalParameter (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetGlobalValueString (Param, pUIMenu->m_pMiniDexed->GetParameter (Param));
pUIMenu->m_pUI->DisplayWrite (pMenuName,
pUIMenu->m_pMiniDexed->DisplayWrite (pMenuName,
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -631,7 +631,7 @@ void CUIMenu::EditVoiceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = to_string (nValue+1) + "="
+ pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetBankName (nValue);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::MaxVoiceBankID);
@ -701,7 +701,7 @@ void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = to_string (nValue+1) + "=" + pUIMenu->m_pMiniDexed->GetVoiceName (nTG);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::VoicesPerBank-1);
@ -754,7 +754,7 @@ void CUIMenu::EditTGParameter (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG));
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -807,7 +807,7 @@ void CUIMenu::EditTGParameter2 (CUIMenu *pUIMenu, TMenuEvent Event) // second me
string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG));
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -860,7 +860,7 @@ void CUIMenu::EditVoiceParameter (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetVoiceValueString (nParam, nValue);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -963,7 +963,7 @@ void CUIMenu::EditOPParameter (CUIMenu *pUIMenu, TMenuEvent Event)
Value = GetOPValueString (nParam, nValue);
}
pUIMenu->m_pUI->DisplayWrite (OP.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (OP.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);
@ -982,7 +982,7 @@ void CUIMenu::SavePerformance (CUIMenu *pUIMenu, TMenuEvent Event)
pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth-1]
[pUIMenu->m_nMenuStackItem[pUIMenu->m_nCurrentMenuDepth-1]].Name;
pUIMenu->m_pUI->DisplayWrite (pMenuName,
pUIMenu->m_pMiniDexed->DisplayWrite (pMenuName,
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
bOK ? "Completed" : "Error",
false, false);
@ -1564,7 +1564,7 @@ void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event)
{
pUIMenu->m_nSelectedPerformanceID = 0;
pUIMenu->m_bConfirmDeletePerformance=false;
pUIMenu->m_pUI->DisplayWrite ("", "Delete", pUIMenu->m_pMiniDexed->DeletePerformance(nValue) ? "Completed" : "Error", false, false);
pUIMenu->m_pMiniDexed->DisplayWrite ("", "Delete", pUIMenu->m_pMiniDexed->DeletePerformance(nValue) ? "Completed" : "Error", false, false);
pUIMenu->m_bSplashShow=true;
CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandlerNoBack, 0, pUIMenu);
return;
@ -1597,13 +1597,13 @@ void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event)
nPSelected += " [L]";
}
pUIMenu->m_pUI->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(),
pUIMenu->m_pMiniDexed->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(),
Value.c_str (), true, true);
// (int) nValue > 0, (int) nValue < (int) pUIMenu->m_pMiniDexed->GetLastPerformance());
}
else
{
pUIMenu->m_pUI->DisplayWrite ("", "Delete?", pUIMenu->m_bConfirmDeletePerformance ? "Yes" : "No", false, false);
pUIMenu->m_pMiniDexed->DisplayWrite ("", "Delete?", pUIMenu->m_bConfirmDeletePerformance ? "Yes" : "No", false, false);
}
}
@ -1685,7 +1685,7 @@ void CUIMenu::EditPerformanceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
nPSelected += " [L]";
}
pUIMenu->m_pUI->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(),
pUIMenu->m_pMiniDexed->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(),
Value.c_str (),
nValue > 0,
nValue < pUIMenu->m_pMiniDexed->GetLastPerformanceBank()-1);
@ -1798,7 +1798,7 @@ void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event)
pUIMenu->m_pMiniDexed->SetNewPerformanceName(pUIMenu->m_InputText);
bOK = pUIMenu->m_pMiniDexed->SavePerformanceNewFile ();
MsgOk=bOK ? "Completed" : "Error";
pUIMenu->m_pUI->DisplayWrite (OkTitleR.c_str(), OkTitleL.c_str(), MsgOk.c_str(), false, false);
pUIMenu->m_pMiniDexed->DisplayWrite (OkTitleR.c_str(), OkTitleL.c_str(), MsgOk.c_str(), false, false);
CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandler, 0, pUIMenu);
return;
}
@ -1849,7 +1849,7 @@ void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event)
}
Value = Value + " " + escCursor ;
pUIMenu->m_pUI->DisplayWrite (MenuTitleR.c_str(),MenuTitleL.c_str(), Value.c_str(), false, false);
pUIMenu->m_pMiniDexed->DisplayWrite (MenuTitleR.c_str(),MenuTitleL.c_str(), Value.c_str(), false, false);
}
@ -1903,7 +1903,7 @@ void CUIMenu::EditTGParameterModulation (CUIMenu *pUIMenu, TMenuEvent Event)
string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG));
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pMiniDexed->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > rParam.Minimum, nValue < rParam.Maximum);

Loading…
Cancel
Save