Skip to content

Commit 8be0781

Browse files
rsta2probonopd
andauthored
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 <[email protected]>
1 parent 6baba1e commit 8be0781

26 files changed

+1413
-392
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ jobs:
6363
mkdir -p sdcard
6464
cp -r ./circle-stdlib/libs/circle/boot/* sdcard
6565
rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux
66-
cp ./src/config.txt ./src/*img sdcard/
67-
echo "usbspeed=full sounddev=sndpwm" > sdcard/cmdline.txt
66+
cp ./src/config.txt ./src/minidexed.txt ./src/*img sdcard/
67+
echo "usbspeed=full" > sdcard/cmdline.txt
6868
cd sdcard
6969
cp ../kernels/* . || true
7070
zip -r ../MiniDexed_$GITHUB_RUN_NUMBER_$(date +%Y-%m-%d).zip *

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ I am wondering whether we can run multiple Dexed instances, in order to recreate
3434
* Unzip
3535
* Put the files into the root directory of a FAT32 formatted partition on SD/microSD card
3636
* Put SD/microSD card into Raspberry Pi 1, 2, 3 or 4 (Zero and Zero 2 can probably be used but need HDMI or a supported i2c DAC for audio out)
37-
* Attach headphones to the headphone jack using `sounddev=sndpwm` in `cmdline.txt` (default)
38-
* Alternatively, attach a PCM5102A or PCM5122 based DAC and select i2c sound output using `sounddev=sndi2s | sndhdmi` in `cmdline.txt`
39-
* Alternatively, attach a HDMI display with sound and select HDMI sound output using `sounddev=sndhdmi` in `cmdline.txt` (this may introduce slight latency)
37+
* Attach headphones to the headphone jack using `SoundDevice=pwm` in `minidexed.ini` (default)
38+
* Alternatively, attach a PCM5102A or PCM5122 based DAC and select i2c sound output using `SoundDevice=i2s | sndhdmi` in `minidexed.ini`
39+
* Alternatively, attach a HDMI display with sound and select HDMI sound output using `SoundDevice=hdmi` in `minidexed.ini` (this may introduce slight latency)
4040
* Attach a MIDI keyboard via USB
4141
* Boot
4242
* Stat playing

build.sh

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ make -j
2626
cd libs/circle/addon/display/
2727
make clean || true
2828
make -j
29+
cd ../Properties/
30+
make clean || true
31+
make -j
2932
cd ../../../..
3033

3134
cd ..

src/Makefile

+3-8
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,13 @@
55
CIRCLE_STDLIB_DIR = ../circle-stdlib
66
SYNTH_DEXED_DIR = ../Synth_Dexed/src
77

8-
OBJS = main.o kernel.o minidexed.o pckeyboard.o sysexfileloader.o perftimer.o \
8+
OBJS = main.o kernel.o minidexed.o config.o userinterface.o \
9+
mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \
10+
sysexfileloader.o perftimer.o \
911
$(SYNTH_DEXED_DIR)/synth_dexed.o
1012

1113
INCLUDE += -I $(SYNTH_DEXED_DIR)
1214

1315
EXTRACLEAN = $(SYNTH_DEXED_DIR)/*.o $(SYNTH_DEXED_DIR)/*.d
1416

1517
include ./Rules.mk
16-
17-
%.o: %.cc
18-
@echo " CPP $@"
19-
@$(CPP) $(CPPFLAGS) -c -o $@ $<
20-
21-
%.d: %.cc
22-
@$(CPP) $(CPPFLAGS) -M -MG -MT $*.o -MT $@ -MF $@ $<

src/Rules.mk

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ LIBS += \
1818
$(NEWLIBDIR)/lib/libc.a \
1919
$(NEWLIBDIR)/lib/libcirclenewlib.a \
2020
$(CIRCLEHOME)/addon/display/libdisplay.a \
21+
$(CIRCLEHOME)/addon/Properties/libproperties.a \
2122
$(CIRCLEHOME)/addon/SDCard/libsdcard.a \
2223
$(CIRCLEHOME)/lib/usb/libusb.a \
2324
$(CIRCLEHOME)/lib/input/libinput.a \

src/circle_stdlib_app.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class CStdlibAppScreen : public CStdlibApp
9797
: CStdlibApp (kernel),
9898
mScreenUnbuffered (mOptions.GetWidth (), mOptions.GetHeight ()),
9999
mScreen (&mScreenUnbuffered),
100+
mbScreenAvailable (false),
100101
mTimer (&mInterrupt),
101102
mLogger (mOptions.GetLogLevel (), &mTimer)
102103
{
@@ -109,10 +110,7 @@ class CStdlibAppScreen : public CStdlibApp
109110
return false;
110111
}
111112

112-
if (!mScreenUnbuffered.Initialize ())
113-
{
114-
return false;
115-
}
113+
mbScreenAvailable = mScreenUnbuffered.Initialize ();
116114
#if 0
117115
if (!mSerial.Initialize (115200))
118116
{
@@ -138,6 +136,7 @@ class CStdlibAppScreen : public CStdlibApp
138136
CScreenDevice mScreenUnbuffered;
139137
//CSerialDevice mSerial;
140138
CWriteBufferDevice mScreen;
139+
bool mbScreenAvailable;
141140
CTimer mTimer;
142141
CLogger mLogger;
143142
};
@@ -164,7 +163,8 @@ class CStdlibAppStdio: public CStdlibAppScreen
164163
mUSBHCI (&mInterrupt, &mTimer, TRUE),
165164
mEMMC (&mInterrupt, &mTimer, &mActLED),
166165
#if !defined(__aarch64__) || !defined(LEAVE_QEMU_ON_HALT)
167-
mConsole (&mScreen, TRUE)
166+
//mConsole (&mScreen, TRUE)
167+
mConsole (&mNullDevice, &mScreen)
168168
#else
169169
mConsole (&mScreen)
170170
#endif

src/config.cpp

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//
2+
// config.cpp
3+
//
4+
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
5+
// Copyright (C) 2022 The MiniDexed Team
6+
//
7+
// Original author of this class:
8+
// R. Stange <[email protected]>
9+
//
10+
// This program is free software: you can redistribute it and/or modify
11+
// it under the terms of the GNU General Public License as published by
12+
// the Free Software Foundation, either version 3 of the License, or
13+
// (at your option) any later version.
14+
//
15+
// This program is distributed in the hope that it will be useful,
16+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
// GNU General Public License for more details.
19+
//
20+
// You should have received a copy of the GNU General Public License
21+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
//
23+
#include "config.h"
24+
25+
CConfig::CConfig (FATFS *pFileSystem)
26+
: m_Properties ("minidexed.ini", pFileSystem)
27+
{
28+
}
29+
30+
CConfig::~CConfig (void)
31+
{
32+
}
33+
34+
void CConfig::Load (void)
35+
{
36+
m_Properties.Load ();
37+
38+
m_SoundDevice = m_Properties.GetString ("SoundDevice", "pwm");
39+
40+
m_nSampleRate = m_Properties.GetNumber ("SampleRate", 48000);
41+
m_nChunkSize = m_Properties.GetNumber ("ChunkSize", m_SoundDevice == "hdmi" ? 384*6 : 256);
42+
m_nDACI2CAddress = m_Properties.GetNumber ("DACI2CAddress", 0);
43+
44+
m_nMIDIBaudRate = m_Properties.GetNumber ("MIDIBaudRate", 31250);
45+
46+
m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0;
47+
m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 17);
48+
m_nLCDPinRegisterSelect = m_Properties.GetNumber ("LCDPinRegisterSelect", 18);
49+
m_nLCDPinReadWrite = m_Properties.GetNumber ("LCDPinReadWrite", 19);
50+
m_nLCDPinData4 = m_Properties.GetNumber ("LCDPinData4", 22);
51+
m_nLCDPinData5 = m_Properties.GetNumber ("LCDPinData5", 23);
52+
m_nLCDPinData6 = m_Properties.GetNumber ("LCDPinData6", 24);
53+
m_nLCDPinData7 = m_Properties.GetNumber ("LCDPinData7", 25);
54+
55+
m_bMIDIDumpEnabled = m_Properties.GetNumber ("MIDIDumpEnabled", 0) != 0;
56+
m_bProfileEnabled = m_Properties.GetNumber ("ProfileEnabled", 0) != 0;
57+
}
58+
59+
const char *CConfig::GetSoundDevice (void) const
60+
{
61+
return m_SoundDevice.c_str ();
62+
}
63+
64+
unsigned CConfig::GetSampleRate (void) const
65+
{
66+
return m_nSampleRate;
67+
}
68+
69+
unsigned CConfig::GetChunkSize (void) const
70+
{
71+
return m_nChunkSize;
72+
}
73+
74+
unsigned CConfig::GetDACI2CAddress (void) const
75+
{
76+
return m_nDACI2CAddress;
77+
}
78+
79+
unsigned CConfig::GetMIDIBaudRate (void) const
80+
{
81+
return m_nMIDIBaudRate;
82+
}
83+
84+
bool CConfig::GetLCDEnabled (void) const
85+
{
86+
return m_bLCDEnabled;
87+
}
88+
89+
unsigned CConfig::GetLCDPinEnable (void) const
90+
{
91+
return m_nLCDPinEnable;
92+
}
93+
94+
unsigned CConfig::GetLCDPinRegisterSelect (void) const
95+
{
96+
return m_nLCDPinRegisterSelect;
97+
}
98+
99+
unsigned CConfig::GetLCDPinReadWrite (void) const
100+
{
101+
return m_nLCDPinReadWrite;
102+
}
103+
104+
unsigned CConfig::GetLCDPinData4 (void) const
105+
{
106+
return m_nLCDPinData4;
107+
}
108+
109+
unsigned CConfig::GetLCDPinData5 (void) const
110+
{
111+
return m_nLCDPinData5;
112+
}
113+
114+
unsigned CConfig::GetLCDPinData6 (void) const
115+
{
116+
return m_nLCDPinData6;
117+
}
118+
119+
unsigned CConfig::GetLCDPinData7 (void) const
120+
{
121+
return m_nLCDPinData7;
122+
}
123+
124+
bool CConfig::GetMIDIDumpEnabled (void) const
125+
{
126+
return m_bMIDIDumpEnabled;
127+
}
128+
129+
bool CConfig::GetProfileEnabled (void) const
130+
{
131+
return m_bProfileEnabled;
132+
}

src/config.h

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//
2+
// config.h
3+
//
4+
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
5+
// Copyright (C) 2022 The MiniDexed Team
6+
//
7+
// Original author of this class:
8+
// R. Stange <[email protected]>
9+
//
10+
// This program is free software: you can redistribute it and/or modify
11+
// it under the terms of the GNU General Public License as published by
12+
// the Free Software Foundation, either version 3 of the License, or
13+
// (at your option) any later version.
14+
//
15+
// This program is distributed in the hope that it will be useful,
16+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
// GNU General Public License for more details.
19+
//
20+
// You should have received a copy of the GNU General Public License
21+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
//
23+
#ifndef _config_h
24+
#define _config_h
25+
26+
#include <fatfs/ff.h>
27+
#include <Properties/propertiesfatfsfile.h>
28+
#include <string>
29+
30+
class CConfig // Configuration for MiniDexed
31+
{
32+
public:
33+
static const unsigned MaxNotes = 16; // polyphony
34+
35+
#if RASPPI <= 3
36+
static const unsigned MaxUSBMIDIDevices = 2;
37+
#else
38+
static const unsigned MaxUSBMIDIDevices = 4;
39+
#endif
40+
41+
static const unsigned LCDColumns = 16; // HD44780 LCD
42+
static const unsigned LCDRows = 2;
43+
44+
public:
45+
CConfig (FATFS *pFileSystem);
46+
~CConfig (void);
47+
48+
void Load (void);
49+
50+
// Sound device
51+
const char *GetSoundDevice (void) const;
52+
unsigned GetSampleRate (void) const;
53+
unsigned GetChunkSize (void) const;
54+
unsigned GetDACI2CAddress (void) const; // 0 for auto probing
55+
56+
// MIDI
57+
unsigned GetMIDIBaudRate (void) const;
58+
59+
// HD44780 LCD
60+
// GPIO pin numbers are chip numbers, not header positions
61+
bool GetLCDEnabled (void) const;
62+
unsigned GetLCDPinEnable (void) const;
63+
unsigned GetLCDPinRegisterSelect (void) const;
64+
unsigned GetLCDPinReadWrite (void) const; // set to 0 if not connected
65+
unsigned GetLCDPinData4 (void) const;
66+
unsigned GetLCDPinData5 (void) const;
67+
unsigned GetLCDPinData6 (void) const;
68+
unsigned GetLCDPinData7 (void) const;
69+
70+
// Debug
71+
bool GetMIDIDumpEnabled (void) const;
72+
bool GetProfileEnabled (void) const;
73+
74+
private:
75+
CPropertiesFatFsFile m_Properties;
76+
77+
std::string m_SoundDevice;
78+
unsigned m_nSampleRate;
79+
unsigned m_nChunkSize;
80+
unsigned m_nDACI2CAddress;
81+
82+
unsigned m_nMIDIBaudRate;
83+
84+
bool m_bLCDEnabled;
85+
unsigned m_nLCDPinEnable;
86+
unsigned m_nLCDPinRegisterSelect;
87+
unsigned m_nLCDPinReadWrite;
88+
unsigned m_nLCDPinData4;
89+
unsigned m_nLCDPinData5;
90+
unsigned m_nLCDPinData6;
91+
unsigned m_nLCDPinData7;
92+
93+
bool m_bMIDIDumpEnabled;
94+
bool m_bProfileEnabled;
95+
};
96+
97+
#endif

0 commit comments

Comments
 (0)