More code development

master
Steve Lascos 7 years ago
parent b86c583fb5
commit 19baaa34be
  1. 34
      src/AudioEffectAnalogDelay.cpp
  2. 13
      src/BASpiMemory.cpp
  3. 6
      src/BASpiMemory.h
  4. 32
      src/LibBasicFunctions.cpp
  5. 4
      src/LibBasicFunctions.h
  6. 40
      src/LibMemoryManagement.cpp
  7. 16
      src/LibMemoryManagement.h

@ -102,22 +102,44 @@ void AudioEffectAnalogDelay::update(void)
} }
// Otherwise perform normal processing // Otherwise perform normal processing
// In order to make use of the SPI DMA, we need to request the read from memory first,
// then do other processing while it fills in the back.
audio_block_t *blockToOutput = nullptr; // this will hold the output audio
blockToOutput = allocate();
if (!blockToOutput) return; // skip this update cycle due to failure
// get the data. If using external memory with DMA, this won't be filled until
// later.
m_memory->getSamples(blockToOutput, m_delaySamples);
// If using DMA, we need something else to do while that read executes, so
// move on to input preprocessing
// Preprocessing // Preprocessing
audio_block_t *preProcessed = allocate(); audio_block_t *preProcessed = allocate();
// mix the input with the feedback path in the pre-processing stage // mix the input with the feedback path in the pre-processing stage
m_preProcessing(preProcessed, inputAudioBlock, m_previousBlock); m_preProcessing(preProcessed, inputAudioBlock, m_previousBlock);
// consider doing the BBD post processing here to use up more time while waiting
// for the read data to come back
audio_block_t *blockToRelease = m_memory->addBlock(preProcessed); audio_block_t *blockToRelease = m_memory->addBlock(preProcessed);
if (blockToRelease) release(blockToRelease); if (blockToRelease) release(blockToRelease);
// OUTPUT PROCESSING // BACK TO OUTPUT PROCESSING
audio_block_t *blockToOutput = nullptr; // audio_block_t *blockToOutput = nullptr;
blockToOutput = allocate(); // blockToOutput = allocate();
// copy the output data // copy the output data
if (!blockToOutput) return; // skip this time due to failure // if (!blockToOutput) return; // skip this time due to failure
// copy over data // // copy over data
m_memory->getSamples(blockToOutput, m_delaySamples); // m_memory->getSamples(blockToOutput, m_delaySamples);
// Check if external DMA, if so, we need to copy out of the DMA buffer
if (m_externalMemory && m_memory->getSlot()->isUseDma()) {
// Using DMA
m_memory->readDmaBufferContents(blockToOutput);
}
// perform the wet/dry mix mix // perform the wet/dry mix mix
m_postProcessing(blockToOutput, inputAudioBlock, blockToOutput); m_postProcessing(blockToOutput, inputAudioBlock, blockToOutput);
transmit(blockToOutput); transmit(blockToOutput);

@ -355,8 +355,8 @@ void BASpiMemoryDMA::begin(void)
// are done before continuing. // are done before continuing.
void BASpiMemoryDMA::write(size_t address, uint8_t *data, size_t numBytes) void BASpiMemoryDMA::write(size_t address, uint8_t *data, size_t numBytes)
{ {
while ( m_txTransfer->busy()) {} while ( m_txTransfer->busy()) {} // wait until not busy
uint16_t transferCount = numBytes + 4; uint16_t transferCount = numBytes + 4; // transfer must be increased by the SPI command and address
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer); m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, data, numBytes); memcpy(m_txBuffer+4, data, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs); *m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
@ -394,8 +394,9 @@ void BASpiMemoryDMA::zero16(size_t address, size_t numWords)
m_spiDma->registerTransfer(*m_txTransfer); m_spiDma->registerTransfer(*m_txTransfer);
} }
void BASpiMemoryDMA::read(size_t address, uint8_t *data, size_t numBytes) void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes)
{ {
UNUSED(dest)
while ( m_rxTransfer->busy()) {} while ( m_rxTransfer->busy()) {}
uint16_t transferCount = numBytes + 4; uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer); m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
@ -405,6 +406,7 @@ void BASpiMemoryDMA::read(size_t address, uint8_t *data, size_t numBytes)
void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords) void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
{ {
UNUSED(dest)
while ( m_rxTransfer->busy()) {} while ( m_rxTransfer->busy()) {}
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer); m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
size_t numBytes = sizeof(uint16_t)*numWords; size_t numBytes = sizeof(uint16_t)*numWords;
@ -413,9 +415,10 @@ void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
m_spiDma->registerTransfer(*m_rxTransfer); m_spiDma->registerTransfer(*m_rxTransfer);
} }
void BASpiMemoryDMA::readBufferContents(size_t bufferOffset, uint8_t *dest, size_t numBytes) void BASpiMemoryDMA::readBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset)
{ {
memcpy(dest, m_rxBuffer+4, numBytes); while (m_rxTransfer->busy()) {} // ensure transfer is complete
memcpy(dest, m_rxBuffer+4+bufferOffset, numBytes);
} }
} /* namespace BAGuitar */ } /* namespace BAGuitar */

@ -115,7 +115,7 @@ class BASpiMemoryDMA : public BASpiMemory {
/// read a single 8-bit data word from the specified address /// read a single 8-bit data word from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
/// @return the data that was read /// @return the data that was read
void read(size_t address, uint8_t *data, size_t numBytes) override; void read(size_t address, uint8_t *dest, size_t numBytes) override;
/// read a block 16-bit data word from the specified address /// read a block 16-bit data word from the specified address
/// @param address the address in the SPI RAM to read from /// @param address the address in the SPI RAM to read from
@ -125,7 +125,7 @@ class BASpiMemoryDMA : public BASpiMemory {
void begin() override; void begin() override;
void readBufferContents(size_t bufferOffset, uint8_t *dest, size_t numBytes); void readBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset = 0);
private: private:
AbstractDmaSpi<DmaSpi0, SPIClass, SPI> *m_spiDma = nullptr; AbstractDmaSpi<DmaSpi0, SPIClass, SPI> *m_spiDma = nullptr;
@ -137,8 +137,6 @@ private:
DmaSpi::Transfer *m_rxTransfer; DmaSpi::Transfer *m_rxTransfer;
void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest); void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest);
// RingBuffer<DmaSpi::Transfer> m_txFifo(MAX_DMA_XFERS);
// RingBuffer<DmaSpi::Transfer> m_rxFifo(MAX_DMA_XFERS);
}; };

@ -119,11 +119,14 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block)
// srcPtr--; // srcPtr--;
// } // }
int16_t *srcPtr = block->data; m_slot->writeAdvance16(block->data, AUDIO_BLOCK_SAMPLES);
for (int i=0; i<AUDIO_BLOCK_SAMPLES; i++) {
m_slot->writeAdvance16(*srcPtr); // Code below worked
srcPtr++; // int16_t *srcPtr = block->data;
} // for (int i=0; i<AUDIO_BLOCK_SAMPLES; i++) {
// m_slot->writeAdvance16(*srcPtr);
// srcPtr++;
// }
} }
blockToRelease = block; blockToRelease = block;
@ -210,11 +213,15 @@ bool AudioDelay::getSamples(audio_block_t *dest, size_t offset, size_t numSample
// destPtr--; // destPtr--;
// } // }
int16_t *destPtr = dest->data; m_slot->readAdvance16(AUDIO_BLOCK_SAMPLES);
for (int i=0; i<AUDIO_BLOCK_SAMPLES; i++) {
*destPtr = m_slot->readAdvance16(); // // Code below worked
destPtr++; // int16_t *destPtr = dest->data;
} // for (int i=0; i<AUDIO_BLOCK_SAMPLES; i++) {
// *destPtr = m_slot->readAdvance16();
// destPtr++;
// }
return true; return true;
} else { } else {
// numSampmles is > than total slot size // numSampmles is > than total slot size
@ -225,6 +232,11 @@ bool AudioDelay::getSamples(audio_block_t *dest, size_t offset, size_t numSample
} }
void AudioDelay::readDmaBufferContents(audio_block_t *dest, size_t numSamples, size_t bufferOffset)
{
m_slot->readDmaBufferContents(reinterpret_cast<uint8_t*>(dest->data), sizeof(int16_t)*numSamples, sizeof(int16_t)*bufferOffset);
}
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
// IirBiQuadFilter // IirBiQuadFilter
//////////////////////////////////////////////////// ////////////////////////////////////////////////////

@ -109,7 +109,7 @@ public:
/// Construct an audio buffer using a slot configured with the BAGuitar::ExternalSramManager /// Construct an audio buffer using a slot configured with the BAGuitar::ExternalSramManager
/// @param slot a pointer to the slot representing the memory you wish to use for the buffer. /// @param slot a pointer to the slot representing the memory you wish to use for the buffer.
AudioDelay(ExtMemSlot *slot); AudioDelay(ExtMemSlot *slot, bool useDma=true);
~AudioDelay(); ~AudioDelay();
@ -140,6 +140,8 @@ public:
/// @returns pointer to the underlying ExtMemSlot. /// @returns pointer to the underlying ExtMemSlot.
ExtMemSlot *getSlot() const { return m_slot; } ExtMemSlot *getSlot() const { return m_slot; }
void readDmaBufferContents(audio_block_t *dest, size_t numSamples = AUDIO_BLOCK_SAMPLES, size_t bufferOffset = 0);
RingBuffer<audio_block_t*> *getRingBuffer() const { return m_ringBuffer; } RingBuffer<audio_block_t*> *getRingBuffer() const { return m_ringBuffer; }
private: private:

@ -108,6 +108,28 @@ uint16_t ExtMemSlot::readAdvance16()
return val; return val;
} }
bool ExtMemSlot::readAdvance16(int16_t *dest=nullptr, size_t numWords)
{
if (!m_valid) { return false; }
size_t numBytes = sizeof(int16_t)*numWords;
if (m_currentRdPosition + numBytes-1 <= m_end) {
// entire block fits in memory slot without wrapping
m_spi->read16(m_currentWrPosition, reinterpret_cast<uint16_t*>(dest), numWords); // cast audio data to uint.
m_currentRdPosition += numBytes;
} else {
// this read will wrap the memory slot
size_t rdBytes = m_end - m_currentRdPosition + 1;
size_t rdDataNum = rdBytes >> 1; // divide by two to get the number of data
m_spi->read16(m_currentRdPosition, reinterpret_cast<uint16_t*>(dest), rdDataNum);
size_t remainingData = numWords - rdDataNum;
m_spi->read16(m_start, reinterpret_cast<uint16_t*>(dest + rdDataNum), remainingData); // write remaining bytes are start
m_currentRdPosition = m_start + (remainingData*sizeof(int16_t));
}
return true;
}
bool ExtMemSlot::writeAdvance16(int16_t *src, size_t numWords) bool ExtMemSlot::writeAdvance16(int16_t *src, size_t numWords)
{ {
@ -153,6 +175,11 @@ bool ExtMemSlot::zeroAdvance16(size_t numWords)
return true; return true;
} }
void ExtMemSlot::readDmaBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset = 0)
{
m_spi->readBufferContents(dest, numBytes, bufferOffset);
}
bool ExtMemSlot::writeAdvance16(int16_t data) bool ExtMemSlot::writeAdvance16(int16_t data)
{ {
@ -229,14 +256,14 @@ size_t ExternalSramManager::availableMemory(BAGuitar::MemSelect mem)
return m_memConfig[mem].totalAvailable; return m_memConfig[mem].totalAvailable;
} }
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem) bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem, bool useDma)
{ {
// convert the time to numer of samples // convert the time to numer of samples
size_t delayLengthInt = (size_t)((delayMilliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f); size_t delayLengthInt = (size_t)((delayMilliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f);
return requestMemory(slot, delayLengthInt * sizeof(int16_t), mem); return requestMemory(slot, delayLengthInt * sizeof(int16_t), mem, useDma);
} }
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem) bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem, bool useDma)
{ {
if (m_memConfig[mem].totalAvailable >= sizeBytes) { if (m_memConfig[mem].totalAvailable >= sizeBytes) {
@ -249,7 +276,11 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGu
slot->m_size = sizeBytes; slot->m_size = sizeBytes;
if (!m_memConfig[mem].m_spi) { if (!m_memConfig[mem].m_spi) {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemory(static_cast<BAGuitar::SpiDeviceId>(mem)); if (useDma) {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemoryDma(static_cast<BAGuitar::SpiDeviceId>(mem));
} else {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemory(static_cast<BAGuitar::SpiDeviceId>(mem));
}
if (!m_memConfig[mem].m_spi) { if (!m_memConfig[mem].m_spi) {
Serial.println("requestMemory: new failed! m_spi is a nullptr"); Serial.println("requestMemory: new failed! m_spi is a nullptr");
} else { } else {
@ -264,6 +295,7 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGu
slot->m_valid = true; slot->m_valid = true;
if (!slot->isEnabled()) { slot->enable(); } if (!slot->isEnabled()) { slot->enable(); }
slot->clear(); slot->clear();
slot->m_useDma = useDma;
return true; return true;
} else { } else {
// there is not enough memory available for the request // there is not enough memory available for the request

@ -104,6 +104,14 @@ public:
/// @returns the next 16-bit data word in memory /// @returns the next 16-bit data word in memory
uint16_t readAdvance16(); uint16_t readAdvance16();
/// Read the next block of numWords during circular operation
/// @details, dest is ignored when using DMA
/// @param dest pointer to the destination of the read.
/// @param numWords number of 16-bit words to transfer
/// @returns true on success, else false on error
bool readAdvance16(int16_t *dest=nullptr, size_t numWords);
/// Write a block of 16-bit data from the specified location in circular operation /// Write a block of 16-bit data from the specified location in circular operation
/// @param src pointer to the start of the block of data to write to memory /// @param src pointer to the start of the block of data to write to memory
/// @param numWords number of 16-bit words to transfer /// @param numWords number of 16-bit words to transfer
@ -120,6 +128,7 @@ public:
/// @returns true on success, else false on error /// @returns true on success, else false on error
bool zeroAdvance16(size_t numWords); bool zeroAdvance16(size_t numWords);
void readDmaBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset = 0);
/// Get the size of the memory slot /// Get the size of the memory slot
/// @returns size of the slot in bytes /// @returns size of the slot in bytes
@ -133,6 +142,8 @@ public:
/// @returns true if enabled, false if not enabled /// @returns true if enabled, false if not enabled
bool isEnabled() const; bool isEnabled() const;
bool isUseDma() const { return m_useDma; }
/// DEBUG USE: prints out the slot member variables /// DEBUG USE: prints out the slot member variables
void printStatus(void) const; void printStatus(void) const;
@ -144,6 +155,7 @@ private:
size_t m_currentWrPosition = 0; ///< current write pointer for circular operation size_t m_currentWrPosition = 0; ///< current write pointer for circular operation
size_t m_currentRdPosition = 0; ///< current read pointer for circular operation size_t m_currentRdPosition = 0; ///< current read pointer for circular operation
size_t m_size = 0; ///< size of this slot in bytes size_t m_size = 0; ///< size of this slot in bytes
bool m_useDma = false; ///< when TRUE, BASpiMemoryDMA will be used.
SpiDeviceId m_spiId; ///< the SPI Device ID SpiDeviceId m_spiId; ///< the SPI Device ID
BASpiMemory *m_spi = nullptr; ///< pointer to an instance of the BASpiMemory interface class BASpiMemory *m_spi = nullptr; ///< pointer to an instance of the BASpiMemory interface class
}; };
@ -175,14 +187,14 @@ public:
/// @param delayMilliseconds request the amount of memory based on required time for audio samples, rather than number of bytes. /// @param delayMilliseconds request the amount of memory based on required time for audio samples, rather than number of bytes.
/// @param mem specify which external memory to allocate from /// @param mem specify which external memory to allocate from
/// @returns true on success, otherwise false on error /// @returns true on success, otherwise false on error
bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0); bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0, bool useDma = true);
/// Request memory be allocated for the provided slot /// Request memory be allocated for the provided slot
/// @param slot a pointer to the global slot object to which memory will be allocated /// @param slot a pointer to the global slot object to which memory will be allocated
/// @param sizeBytes request the amount of memory in bytes to request /// @param sizeBytes request the amount of memory in bytes to request
/// @param mem specify which external memory to allocate from /// @param mem specify which external memory to allocate from
/// @returns true on success, otherwise false on error /// @returns true on success, otherwise false on error
bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0); bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0, bool useDma = true);
private: private:
static bool m_configured; ///< there should only be one instance of ExternalSramManager in the whole project static bool m_configured; ///< there should only be one instance of ExternalSramManager in the whole project

Loading…
Cancel
Save