From 61a301a24c2ed2246a8e47e6a56fa827d3c3c8d5 Mon Sep 17 00:00:00 2001 From: Jennifer Wilcox Date: Wed, 18 Jan 2023 14:08:48 -0600 Subject: [PATCH 1/4] Ignore clock and active sensing on serial MIDI (#417) * Ignore clock and active sensing on serial MIDI Fixes #416 I'm not entirely sure this is the correct way to fix it. But it does seem to fix the problem I was seeing. I can now completely mash the keyboard and no notes will get stuck on. * Handle all system real time messages in serial --- src/serialmididevice.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/serialmididevice.cpp b/src/serialmididevice.cpp index 186efc3..883fd4d 100644 --- a/src/serialmididevice.cpp +++ b/src/serialmididevice.cpp @@ -98,7 +98,13 @@ void CSerialMIDIDevice::Process (void) continue; } - if(m_nSysEx > 0) + // System Real Time messages may appear anywhere in the byte stream, so handle them specially + if(uchData == 0xF8 || uchData == 0xFA || uchData == 0xFB || uchData == 0xFC || uchData == 0xFE || uchData == 0xFF) + { + MIDIMessageHandler (&uchData, 1); + continue; + } + else if(m_nSysEx > 0) { m_SerialMessage[m_nSysEx++]=uchData; if ((uchData & 0x80) == 0x80 || m_nSysEx >= MAX_MIDI_MESSAGE) From ad9689a719504227201676e38ee32fdebd64711e Mon Sep 17 00:00:00 2001 From: Kevin <68612569+diyelectromusic@users.noreply.github.com> Date: Fri, 20 Jan 2023 17:49:27 +0000 Subject: [PATCH 2/4] Fix for Issue #369 to correctly recognise ChannelsSwapped config setting (#381) Co-authored-by: probonopd --- src/minidexed.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 0240ea5..328eab4 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -948,13 +948,7 @@ void CMiniDexed::ProcessSound (void) assert (CConfig::ToneGenerators == 8); - // swap stereo channels if needed uint8_t indexL=0, indexR=1; - if (m_bChannelsSwapped) - { - indexL=1; - indexR=0; - } // BEGIN TG mixing float32_t tmp_float[nFrames*2]; @@ -1003,6 +997,13 @@ void CMiniDexed::ProcessSound (void) } // END adding reverb + // swap stereo channels if needed prior to writing back out + if (m_bChannelsSwapped) + { + indexL=1; + indexR=0; + } + // Convert dual float array (left, right) to single int16 array (left/right) for(uint16_t i=0; i Date: Sun, 22 Jan 2023 13:02:05 +0000 Subject: [PATCH 3/4] Configuration option for automatic voice data dump on ProgramChange but only send it when a TG has a valid MIDI channel. (#388) Co-authored-by: diyelectromusic <68612569+diyelectromusic@users.noreply.github.com> --- src/config.cpp | 6 ++++++ src/config.h | 2 ++ src/mididevice.cpp | 2 +- src/minidexed.cpp | 17 +++++++++++++++-- src/minidexed.ini | 1 + 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 1143476..9ad98f0 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -70,6 +70,7 @@ void CConfig::Load (void) m_bMIDIRXProgramChange = m_Properties.GetNumber ("MIDIRXProgramChange", 1) != 0; m_bIgnoreAllNotesOff = m_Properties.GetNumber ("IgnoreAllNotesOff", 0) != 0; + m_bMIDIAutoVoiceDumpOnPC = m_Properties.GetNumber ("MIDIAutoVoiceDumpOnPC", 1) != 0; m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0; m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 4); @@ -171,6 +172,11 @@ bool CConfig::GetIgnoreAllNotesOff (void) const return m_bIgnoreAllNotesOff; } +bool CConfig::GetMIDIAutoVoiceDumpOnPC (void) const +{ + return m_bMIDIAutoVoiceDumpOnPC; +} + bool CConfig::GetLCDEnabled (void) const { return m_bLCDEnabled; diff --git a/src/config.h b/src/config.h index be75100..2465507 100644 --- a/src/config.h +++ b/src/config.h @@ -76,6 +76,7 @@ public: const char *GetMIDIThruOut (void) const; // "" if not specified bool GetMIDIRXProgramChange (void) const; // true if not specified bool GetIgnoreAllNotesOff (void) const; + bool GetMIDIAutoVoiceDumpOnPC (void) const; // true if not specified // HD44780 LCD // GPIO pin numbers are chip numbers, not header positions @@ -153,6 +154,7 @@ private: std::string m_MIDIThruOut; bool m_bMIDIRXProgramChange; bool m_bIgnoreAllNotesOff; + bool m_bMIDIAutoVoiceDumpOnPC; bool m_bLCDEnabled; unsigned m_nLCDPinEnable; diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 898c187..9b3deac 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -203,7 +203,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN) { // MIDI SYSEX per MIDI channel - uint8_t ucSysExChannel = (pMessage[2] & 0x07); + uint8_t ucSysExChannel = (pMessage[2] & 0x0F); if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode) { LOGNOTE("MIDI-SYSEX: channel: %u, len: %u, TG: %u",m_ChannelMap[nTG],nLength,nTG); diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 328eab4..8df8d6d 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -377,6 +377,8 @@ void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG) void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) { + assert (m_pConfig); + nProgram=constrain((int)nProgram,0,31); assert (nTG < CConfig::ToneGenerators); @@ -387,7 +389,16 @@ void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) assert (m_pTG[nTG]); m_pTG[nTG]->loadVoiceParameters (Buffer); - m_SerialMIDI.SendSystemExclusiveVoice(nProgram,0,nTG); + + if (m_pConfig->GetMIDIAutoVoiceDumpOnPC()) + { + // Only do the voice dump back out over MIDI if we have a specific + // MIDI channel configured for this TG + if (m_nMIDIChannel[nTG] < CMIDIDevice::Channels) + { + m_SerialMIDI.SendSystemExclusiveVoice(nProgram,0,nTG); + } + } m_UI.ParameterChanged (); } @@ -474,6 +485,8 @@ void CMiniDexed::SetResonance (int nResonance, unsigned nTG) void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG) { assert (nTG < CConfig::ToneGenerators); + assert (uchChannel < CMIDIDevice::ChannelUnknown); + m_nMIDIChannel[nTG] = uchChannel; for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++) @@ -1321,7 +1334,7 @@ void CMiniDexed::getSysExVoiceDump(uint8_t* dest, uint8_t nTG) dest[0] = 0xF0; // SysEx start dest[1] = 0x43; // ID=Yamaha - dest[2] = GetTGParameter(TGParameterMIDIChannel, nTG); // Sub-status and MIDI channel + dest[2] = 0x00 | m_nMIDIChannel[nTG]; // 0x0c Sub-status 0 and MIDI channel dest[3] = 0x00; // Format number (0=1 voice) dest[4] = 0x01; // Byte count MSB dest[5] = 0x1B; // Byte count LSB diff --git a/src/minidexed.ini b/src/minidexed.ini index 7d73416..f2bfbf6 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -16,6 +16,7 @@ MIDIBaudRate=31250 #MIDIThru=umidi1,ttyS1 MIDIRXProgramChange=1 IgnoreAllNotesOff=0 +MIDIAutoVoiceDumpOnPC=1 # HD44780 LCD LCDEnabled=1 From fcea41ead3fadd962342ffdf8241e48c1f84358e Mon Sep 17 00:00:00 2001 From: Kevin <68612569+diyelectromusic@users.noreply.github.com> Date: Sun, 22 Jan 2023 13:31:54 +0000 Subject: [PATCH 4/4] SSD1306 display rotation support and fix for #421 (#422) * Update Circle develop branch for SSD1306 display rotation support https://github.com/probonopd/MiniDexed/discussions/412 * Implements rotation and mirroring options for SSD1306 displays (only). (#420) Requires an update to circle (PR submitted to develop branch) Co-authored-by: diyelectromusic <68612569+diyelectromusic@users.noreply.github.com> * circle-stdlib e318f89 Needed to support Circle develop * Fix for Issue 421 - circle sound drivers have moved to their own subdirectory and library. * Updated to keep in step with updates from the original in circle-stdlib. * git checkout circle-newlib 48bf91d Needed for circle ec09d7e Co-authored-by: probonopd --- .github/workflows/build.yml | 10 ++++++++-- src/Rules.mk | 1 + src/circle_stdlib_app.h | 6 ++++-- src/config.cpp | 12 ++++++++++++ src/config.h | 4 ++++ src/minidexed.cpp | 6 +++--- src/minidexed.h | 2 +- src/minidexed.ini | 2 ++ src/userinterface.cpp | 4 +++- 9 files changed, 38 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbd4bdd..7ee4ebb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,11 +20,17 @@ jobs: run: | set -ex git submodule update --init --recursive - - name: Use Circle develop branch for WM8960 and i2c display support until it is merged upstream + - name: Use Circle develop branch for SSD1306 display rotation support until it is merged upstream run: | set -ex + cd circle-stdlib/ + git checkout e318f89 # Needed to support Circle develop? + cd - cd circle-stdlib/libs/circle - git checkout 646c362 # develop + git checkout ec09d7e # develop + cd - + cd circle-stdlib/libs/circle-newlib + git checkout 48bf91d # needed for circle ec09d7e cd - - name: Install toolchains run: | diff --git a/src/Rules.mk b/src/Rules.mk index 39b9f25..d466b74 100644 --- a/src/Rules.mk +++ b/src/Rules.mk @@ -23,6 +23,7 @@ LIBS += \ $(CIRCLEHOME)/addon/SDCard/libsdcard.a \ $(CIRCLEHOME)/lib/usb/libusb.a \ $(CIRCLEHOME)/lib/input/libinput.a \ + $(CIRCLEHOME)/lib/sound/libsound.a \ $(CIRCLEHOME)/addon/fatfs/libfatfs.a \ $(CIRCLEHOME)/lib/fs/libfs.a \ $(CIRCLEHOME)/lib/sched/libsched.a \ diff --git a/src/circle_stdlib_app.h b/src/circle_stdlib_app.h index 75cbde2..3c38f0d 100644 --- a/src/circle_stdlib_app.h +++ b/src/circle_stdlib_app.h @@ -214,8 +214,10 @@ public: return false; } - // Initialize newlib stdio with a reference to Circle's file system and console - CGlueStdioInit (mFileSystem, mConsole); + // Initialize newlib stdio with a reference to Circle's console + // (Remove mFileSystem as a parameter to mirror change in circle-stdlib's + // commit "Remove obsolete FATFS-related code", dated Dec 2022) + CGlueStdioInit (mConsole); mLogger.Write (GetKernelName (), LogNotice, "Compile time: " __DATE__ " " __TIME__); diff --git a/src/config.cpp b/src/config.cpp index 9ad98f0..b5279a8 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -85,6 +85,8 @@ void CConfig::Load (void) m_nSSD1306LCDI2CAddress = m_Properties.GetNumber ("SSD1306LCDI2CAddress", 0); m_nSSD1306LCDWidth = m_Properties.GetNumber ("SSD1306LCDWidth", 128); m_nSSD1306LCDHeight = m_Properties.GetNumber ("SSD1306LCDHeight", 32); + m_bSSD1306LCDRotate = m_Properties.GetNumber ("SSD1306LCDRotate", 0) != 0; + m_bSSD1306LCDMirror = m_Properties.GetNumber ("SSD1306LCDMirror", 0) != 0; m_nLCDColumns = m_Properties.GetNumber ("LCDColumns", 16); m_nLCDRows = m_Properties.GetNumber ("LCDRows", 2); @@ -237,6 +239,16 @@ unsigned CConfig::GetSSD1306LCDHeight (void) const return m_nSSD1306LCDHeight; } +bool CConfig::GetSSD1306LCDRotate (void) const +{ + return m_bSSD1306LCDRotate; +} + +bool CConfig::GetSSD1306LCDMirror (void) const +{ + return m_bSSD1306LCDMirror; +} + unsigned CConfig::GetLCDColumns (void) const { return m_nLCDColumns; diff --git a/src/config.h b/src/config.h index 2465507..8a34239 100644 --- a/src/config.h +++ b/src/config.h @@ -94,6 +94,8 @@ public: unsigned GetSSD1306LCDI2CAddress (void) const; unsigned GetSSD1306LCDWidth (void) const; unsigned GetSSD1306LCDHeight (void) const; + bool GetSSD1306LCDRotate (void) const; + bool GetSSD1306LCDMirror (void) const; unsigned GetLCDColumns (void) const; unsigned GetLCDRows (void) const; @@ -169,6 +171,8 @@ private: unsigned m_nSSD1306LCDI2CAddress; unsigned m_nSSD1306LCDWidth; unsigned m_nSSD1306LCDHeight; + bool m_bSSD1306LCDRotate; + bool m_bSSD1306LCDMirror; unsigned m_nLCDColumns; unsigned m_nLCDRows; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 8df8d6d..6a3897e 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -20,9 +20,9 @@ #include "minidexed.h" #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/minidexed.h b/src/minidexed.h index 3b7de4e..a74a04f 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include "common.h" #include "effect_mixer.hpp" diff --git a/src/minidexed.ini b/src/minidexed.ini index f2bfbf6..bb3edd7 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -35,6 +35,8 @@ LCDI2CAddress=0x00 SSD1306LCDI2CAddress=0x0 SSD1306LCDWidth=128 SSD1306LCDHeight=32 +SSD1306LCDRotate=0 +SSD1306LCDMirror=0 # Default is 16x2 display (e.g. HD44780) LCDColumns=16 diff --git a/src/userinterface.cpp b/src/userinterface.cpp index f34e561..0bcd931 100644 --- a/src/userinterface.cpp +++ b/src/userinterface.cpp @@ -58,7 +58,9 @@ bool CUserInterface::Initialize (void) unsigned i2caddr = m_pConfig->GetLCDI2CAddress (); unsigned ssd1306addr = m_pConfig->GetSSD1306LCDI2CAddress (); if (ssd1306addr != 0) { - m_pSSD1306 = new CSSD1306Device (m_pConfig->GetSSD1306LCDWidth (), m_pConfig->GetSSD1306LCDHeight (), m_pI2CMaster, ssd1306addr); + m_pSSD1306 = new CSSD1306Device (m_pConfig->GetSSD1306LCDWidth (), m_pConfig->GetSSD1306LCDHeight (), + m_pI2CMaster, ssd1306addr, + m_pConfig->GetSSD1306LCDRotate (), m_pConfig->GetSSD1306LCDMirror ()); LOGDBG ("LCD: SSD1306"); if (!m_pSSD1306->Initialize ()) {