diff --git a/build.sh b/build.sh
index de4d9f1..ef9ce68 100755
--- a/build.sh
+++ b/build.sh
@@ -18,9 +18,6 @@ fi
cd circle-stdlib/
make mrproper || true
./configure -r ${RPI} --prefix "${TOOLCHAIN_PREFIX}"
-if [ "${RPI}" -gt "1" ]; then
- echo "DEFINE += -DARM_ALLOW_MULTI_CORE" >> libs/circle/Config.mk
-fi
echo "DEFINE += -DUSE_PWM_AUDIO_ON_ZERO" >> libs/circle/Config.mk
echo "DEFINE += -DSAVE_VFP_REGS_ON_IRQ" >> libs/circle/Config.mk
echo "DEFINE += -DREALTIME" >> libs/circle/Config.mk
diff --git a/src/kernel.cpp b/src/kernel.cpp
index dde24f0..2ad706d 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -18,6 +18,7 @@
// along with this program. If not, see .
//
#include "kernel.h"
+#include
#include
#include
#include
@@ -64,7 +65,27 @@ bool CKernel::Initialize (void)
m_Config.Load ();
- m_pDexed = new CMiniDexed (&m_Config, &mInterrupt, &m_GPIOManager, &m_I2CMaster);
+ // select the sound device
+ const char *pSoundDevice = m_Config.GetSoundDevice ();
+ if (strcmp (pSoundDevice, "i2s") == 0)
+ {
+ LOGNOTE ("I2S mode");
+
+ m_pDexed = new CMiniDexedI2S (&m_Config, &mInterrupt, &m_GPIOManager, &m_I2CMaster);
+ }
+ else if (strcmp (pSoundDevice, "hdmi") == 0)
+ {
+ LOGNOTE ("HDMI mode");
+
+ m_pDexed = new CMiniDexedHDMI (&m_Config, &mInterrupt, &m_GPIOManager);
+ }
+ else
+ {
+ LOGNOTE ("PWM mode");
+
+ m_pDexed = new CMiniDexedPWM (&m_Config, &mInterrupt, &m_GPIOManager);
+ }
+
assert (m_pDexed);
if (!m_pDexed->Initialize ())
diff --git a/src/minidexed.cpp b/src/minidexed.cpp
index 23f64cb..476a8f3 100644
--- a/src/minidexed.cpp
+++ b/src/minidexed.cpp
@@ -19,28 +19,18 @@
//
#include "minidexed.h"
#include
-#include
-#include
-#include
-#include
-#include
#include
#include
LOGMODULE ("minidexed");
-CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
- CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster)
+CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, CGPIOManager *pGPIOManager)
: CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()),
-#ifdef ARM_ALLOW_MULTI_CORE
- CMultiCoreSupport (CMemorySystem::Get ()),
-#endif
m_pConfig (pConfig),
m_UI (this, pGPIOManager, pConfig),
m_PCKeyboard (this),
m_SerialMIDI (this, pInterrupt, pConfig),
m_bUseSerial (false),
- m_pSoundDevice (0),
m_GetChunkTimer ("GetChunk",
1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()),
m_bProfileEnabled (m_pConfig->GetProfileEnabled ())
@@ -50,38 +40,10 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, i);
assert (m_pMIDIKeyboard[i]);
}
-
- // select the sound device
- const char *pDeviceName = pConfig->GetSoundDevice ();
- if (strcmp (pDeviceName, "i2s") == 0)
- {
- LOGNOTE ("I2S mode");
-
- m_pSoundDevice = new CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
- pConfig->GetChunkSize (), false,
- pI2CMaster, pConfig->GetDACI2CAddress ());
- }
- else if (strcmp (pDeviceName, "hdmi") == 0)
- {
- LOGNOTE ("HDMI mode");
-
- m_pSoundDevice = new CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
- pConfig->GetChunkSize ());
- }
- else
- {
- LOGNOTE ("PWM mode");
-
- m_pSoundDevice = new CPWMSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
- pConfig->GetChunkSize ());
- }
};
bool CMiniDexed::Initialize (void)
{
- assert (m_pConfig);
- assert (m_pSoundDevice);
-
if (!m_UI.Initialize ())
{
return false;
@@ -101,37 +63,11 @@ bool CMiniDexed::Initialize (void)
ProgramChange (0);
setTranspose (24);
- // setup and start the sound device
- if (!m_pSoundDevice->AllocateQueueFrames (m_pConfig->GetChunkSize ()/2))
- {
- LOGERR ("Cannot allocate sound queue");
-
- return false;
- }
-
- m_pSoundDevice->SetWriteFormat (SoundFormatSigned16, 1); // 16-bit Mono
-
- m_nQueueSizeFrames = m_pSoundDevice->GetQueueSizeFrames ();
-
- m_pSoundDevice->Start ();
-
-#ifdef ARM_ALLOW_MULTI_CORE
- // start secondary cores
- if (!CMultiCoreSupport::Initialize ())
- {
- return false;
- }
-#endif
-
return true;
}
void CMiniDexed::Process (bool bPlugAndPlayUpdated)
{
-#ifndef ARM_ALLOW_MULTI_CORE
- ProcessSound ();
-#endif
-
for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++)
{
assert (m_pMIDIKeyboard[i]);
@@ -153,21 +89,6 @@ void CMiniDexed::Process (bool bPlugAndPlayUpdated)
}
}
-#ifdef ARM_ALLOW_MULTI_CORE
-
-void CMiniDexed::Run (unsigned nCore)
-{
- if (nCore == 1)
- {
- while (1)
- {
- ProcessSound ();
- }
- }
-}
-
-#endif
-
CSysExFileLoader *CMiniDexed::GetSysExFileLoader (void)
{
return &m_SysExFileLoader;
@@ -199,30 +120,159 @@ void CMiniDexed::ProgramChange (unsigned nProgram)
m_UI.ProgramChanged (nProgram);
}
-void CMiniDexed::ProcessSound (void)
+//// PWM //////////////////////////////////////////////////////////////////////
+
+CMiniDexedPWM::CMiniDexedPWM (CConfig *pConfig, CInterruptSystem *pInterrupt,
+ CGPIOManager *pGPIOManager)
+: CMiniDexed (pConfig, pInterrupt, pGPIOManager),
+ CPWMSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
+ pConfig->GetChunkSize ())
{
- assert (m_pSoundDevice);
+}
- unsigned nFrames = m_nQueueSizeFrames - m_pSoundDevice->GetQueueFramesAvail ();
- if (nFrames >= m_nQueueSizeFrames/2)
+bool CMiniDexedPWM::Initialize (void)
+{
+ if (!CMiniDexed::Initialize ())
{
- if (m_bProfileEnabled)
- {
- m_GetChunkTimer.Start ();
- }
+ return false;
+ }
- int16_t SampleBuffer[nFrames];
- getSamples (nFrames, SampleBuffer);
+ return Start ();
+}
- if ( m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer)
- != (int) sizeof SampleBuffer)
- {
- LOGERR ("Sound data dropped");
- }
+unsigned CMiniDexedPWM::GetChunk (u32 *pBuffer, unsigned nChunkSize)
+{
+ if (m_bProfileEnabled)
+ {
+ m_GetChunkTimer.Start ();
+ }
+
+ unsigned nResult = nChunkSize;
+
+ int16_t SampleBuffer[nChunkSize/2];
+ getSamples (nChunkSize/2, SampleBuffer);
+
+ for (unsigned i = 0; nChunkSize > 0; nChunkSize -= 2) // fill the whole buffer
+ {
+ s32 nSample = SampleBuffer[i++];
+ nSample += 32768;
+ nSample *= GetRangeMax()/2;
+ nSample /= 32768;
- if (m_bProfileEnabled)
+ *pBuffer++ = nSample; // 2 stereo channels
+ *pBuffer++ = nSample;
+ }
+
+ if (m_bProfileEnabled)
+ {
+ m_GetChunkTimer.Stop ();
+ }
+
+ return nResult;
+};
+
+//// I2S //////////////////////////////////////////////////////////////////////
+
+CMiniDexedI2S::CMiniDexedI2S (CConfig *pConfig, CInterruptSystem *pInterrupt,
+ CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster)
+: CMiniDexed (pConfig, pInterrupt, pGPIOManager),
+ CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
+ pConfig->GetChunkSize (), false, pI2CMaster,
+ pConfig->GetDACI2CAddress ())
+{
+}
+
+bool CMiniDexedI2S::Initialize (void)
+{
+ if (!CMiniDexed::Initialize ())
+ {
+ return false;
+ }
+
+ return Start ();
+}
+
+unsigned CMiniDexedI2S::GetChunk (u32 *pBuffer, unsigned nChunkSize)
+{
+ if (m_bProfileEnabled)
+ {
+ m_GetChunkTimer.Start ();
+ }
+
+ unsigned nResult = nChunkSize;
+
+ int16_t SampleBuffer[nChunkSize/2];
+ getSamples (nChunkSize/2, SampleBuffer);
+
+ for (unsigned i = 0; nChunkSize > 0; nChunkSize -= 2) // fill the whole buffer
+ {
+ s32 nSample = SampleBuffer[i++];
+ nSample <<= 8;
+
+ *pBuffer++ = nSample; // 2 stereo channels
+ *pBuffer++ = nSample;
+ }
+
+ if (m_bProfileEnabled)
+ {
+ m_GetChunkTimer.Stop ();
+ }
+
+ return nResult;
+};
+
+//// HDMI /////////////////////////////////////////////////////////////////////
+
+CMiniDexedHDMI::CMiniDexedHDMI (CConfig *pConfig, CInterruptSystem *pInterrupt,
+ CGPIOManager *pGPIOManager)
+: CMiniDexed (pConfig, pInterrupt, pGPIOManager),
+ CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
+ pConfig->GetChunkSize ())
+{
+}
+
+bool CMiniDexedHDMI::Initialize (void)
+{
+ if (!CMiniDexed::Initialize ())
+ {
+ return false;
+ }
+
+ return Start ();
+}
+
+unsigned CMiniDexedHDMI::GetChunk(u32 *pBuffer, unsigned nChunkSize)
+{
+ if (m_bProfileEnabled)
+ {
+ m_GetChunkTimer.Start ();
+ }
+
+ unsigned nResult = nChunkSize;
+
+ int16_t SampleBuffer[nChunkSize/2];
+ getSamples (nChunkSize/2, SampleBuffer);
+
+ unsigned nFrame = 0;
+ for (unsigned i = 0; nChunkSize > 0; nChunkSize -= 2) // fill the whole buffer
+ {
+ s32 nSample = SampleBuffer[i++];
+ nSample <<= 8;
+
+ nSample = ConvertIEC958Sample (nSample, nFrame);
+ if (++nFrame == IEC958_FRAMES_PER_BLOCK)
{
- m_GetChunkTimer.Stop ();
+ nFrame = 0;
}
+
+ *pBuffer++ = nSample; // 2 stereo channels
+ *pBuffer++ = nSample;
}
-}
+
+ if (m_bProfileEnabled)
+ {
+ m_GetChunkTimer.Stop();
+ }
+
+ return nResult;
+};
diff --git a/src/minidexed.h b/src/minidexed.h
index ae0eff6..d817f87 100644
--- a/src/minidexed.h
+++ b/src/minidexed.h
@@ -33,34 +33,25 @@
#include
#include
#include
-#include
-#include
+#include
+#include
+#include
class CMiniDexed : public CDexedAdapter
-#ifdef ARM_ALLOW_MULTI_CORE
- , public CMultiCoreSupport
-#endif
{
public:
CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
- CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster);
+ CGPIOManager *pGPIOManager);
- bool Initialize (void);
+ virtual bool Initialize (void);
void Process (bool bPlugAndPlayUpdated);
-#ifdef ARM_ALLOW_MULTI_CORE
- void Run (unsigned nCore);
-#endif
-
CSysExFileLoader *GetSysExFileLoader (void);
void BankSelectLSB (unsigned nBankLSB);
void ProgramChange (unsigned nProgram);
-private:
- void ProcessSound (void);
-
private:
CConfig *m_pConfig;
@@ -72,12 +63,48 @@ private:
CSerialMIDIDevice m_SerialMIDI;
bool m_bUseSerial;
- CSoundBaseDevice *m_pSoundDevice;
- unsigned m_nQueueSizeFrames;
-
protected:
CPerformanceTimer m_GetChunkTimer;
bool m_bProfileEnabled;
};
+//// PWM //////////////////////////////////////////////////////////////////////
+
+class CMiniDexedPWM : public CMiniDexed, public CPWMSoundBaseDevice
+{
+public:
+ CMiniDexedPWM (CConfig *pConfig, CInterruptSystem *pInterrupt,
+ CGPIOManager *pGPIOManager);
+
+ bool Initialize (void);
+
+ unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize);
+};
+
+//// I2S //////////////////////////////////////////////////////////////////////
+
+class CMiniDexedI2S : public CMiniDexed, public CI2SSoundBaseDevice
+{
+public:
+ CMiniDexedI2S (CConfig *pConfig, CInterruptSystem *pInterrupt,
+ CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster);
+
+ bool Initialize (void);
+
+ unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize);
+};
+
+//// HDMI /////////////////////////////////////////////////////////////////////
+
+class CMiniDexedHDMI : public CMiniDexed, public CHDMISoundBaseDevice
+{
+public:
+ CMiniDexedHDMI (CConfig *pConfig, CInterruptSystem *pInterrupt,
+ CGPIOManager *pGPIOManager);
+
+ bool Initialize (void);
+
+ unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize);
+};
+
#endif