Skip to content
Permalink
Browse files

Fixed behaviour when analog is disabled. Now the SPI bus is (mostly) …

…left alone and the audio still runs. Closes #7. We could use an improvement to the PRU code that removes any SPI transaction.
  • Loading branch information
giuliomoro committed Jan 17, 2017
1 parent 4479ea0 commit d7f71f02e68ffb569ada85b0be6c3925623e26f3
Showing with 8 additions and 37 deletions.
  1. +8 −15 core/PRU.cpp
  2. +0 −11 core/RTAudio.cpp
  3. +0 −11 include/Bela.h
@@ -309,7 +309,12 @@ int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, int mu
/* Set up flags */
pru_buffer_comm[PRU_SHOULD_STOP] = 0;
pru_buffer_comm[PRU_CURRENT_BUFFER] = 0;
pru_buffer_comm[PRU_BUFFER_FRAMES] = context->analogFrames;
unsigned int pruFrames;

This comment has been minimized.

Copy link
@giuliomoro

giuliomoro Jan 17, 2017

Author Contributor

@apmcpherson The issue was that by setting

pru_buffer_comm[PRU_BUFFER_FRAMES] = context->analogFrames;

when analog was disabled (and thus context->analogFrames == 0), then the PRU loop would never exit because reg_frame_total would be in turn set to 0 and the condition

     QBNE WRITE_LOOP, reg_frame_current, reg_frame_total

would never be met (given that you get there the first time when reg_frame_current == 2).

if(analog_enabled)
pruFrames = context->analogFrames;
else
pruFrames = context->audioFrames / 2; // PRU assumes 8 "fake" channels when SPI is disabled
pru_buffer_comm[PRU_BUFFER_FRAMES] = pruFrames;
pru_buffer_comm[PRU_SHOULD_SYNC] = 0;
pru_buffer_comm[PRU_SYNC_ADDRESS] = 0;
pru_buffer_comm[PRU_SYNC_PIN_MASK] = 0;
@@ -531,23 +536,18 @@ int PRU::start(char * const filename)
return 0;
}

#ifdef PRU_SIGXCPU_BUG_WORKAROUND
extern bool gProcessAnalog;
#endif /* PRU_SIGXCPU_BUG_WORKAROUND */

// Main loop to read and write data from/to PRU
void PRU::loop(RT_INTR *pru_interrupt, void *userData)
{
#ifdef BELA_USE_XENOMAI_INTERRUPTS
RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024; // Timeout for PRU interrupt: about 10ms, much longer than any expected period
#else
// Polling interval is 1/4 of the period
if(context->analogInChannels != context->analogOutChannels){
printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
return;
}
unsigned int analogChannels = context->analogInChannels;
RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (analogChannels / 2) * context->analogFrames / 4;
// Polling interval is 1/4 of the period
RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->audioInChannels) * context->audioFrames / 4;
#endif

uint32_t pru_audio_offset, pru_spi_offset;
@@ -582,13 +582,6 @@ void PRU::loop(RT_INTR *pru_interrupt, void *userData)
uint32_t lastPRUBuffer = 0;
#endif

#ifdef PRU_SIGXCPU_BUG_WORKAROUND
if(gProcessAnalog == false){
context->analogFrames = 0;
context->analogInChannels = 0;
context->analogOutChannels = 0;
}
#endif

while(!gShouldStop) {
#ifdef BELA_USE_XENOMAI_INTERRUPTS
@@ -78,9 +78,6 @@ int gRTAudioVerbose = 0; // Verbosity level for debugging
int gAmplifierMutePin = -1;
int gAmplifierShouldBeginMuted = 0;

#ifdef PRU_SIGXCPU_BUG_WORKAROUND
bool gProcessAnalog;
#endif /* PRU_SIGXCPU_BUG_WORKAROUND */

// Context which holds all the audio/sensor data passed to the render routines
InternalBelaContext gContext;
@@ -193,14 +190,6 @@ int Bela_initAudio(BelaInitSettings *settings, void *userData)
gContext.audioInChannels = 2;
gContext.audioOutChannels = 2;

#ifdef PRU_SIGXCPU_BUG_WORKAROUND
// TODO: see PRU bug mentioned above. We catch here if useAnalog was set to false, store it in gProcessAnalog
// and use this value to decide whether we should process the analogs in PRU::loop, but then we
// set it to true so that the PRU is init'd and the code runs AS IF the analogs were in use.
gProcessAnalog = settings->useAnalog;
settings->useAnalog = true;
#endif /* PRU_SIGXCPU_BUG_WORKAROUND */

if(settings->useAnalog) {
gContext.audioFrames = settings->periodSize;

@@ -736,15 +736,4 @@ int Bela_startAuxiliaryTask(AuxiliaryTask task);
/** @} */
#include <Utilities.h>

/**\cond HIDDEN_SYMBOLS
// TODO: There is a bug in the PRU code that prevents it from working when SPI is disabled.
// To work around it, we leave the SPI enabled ( as it does not affect the load of the ARM core), but
// we avoid processing the analog channels, to save CPU time. We use global variable gProcessAnalog
// in RTAudio.cpp and PRU.cpp to store the actual value of analog_enabled. To reproduce the bug,
// undefine the line below and run with -N0 (analog disabled)
*/
#define PRU_SIGXCPU_BUG_WORKAROUND
/**
* \endcond
*/
#endif /* BELA_H_ */

0 comments on commit d7f71f0

Please sign in to comment.
You can’t perform that action at this time.