Working checking, needs performance enhancement

master
Steve Lascos 7 years ago
parent 7124306700
commit 2f5e8e72ee
  1. 13
      src/AudioEffectAnalogDelay.cpp
  2. 153
      src/BASpiMemory.cpp
  3. 21
      src/BASpiMemory.h
  4. 5
      src/LibBasicFunctions.cpp
  5. 3
      src/LibBasicFunctions.h
  6. 39
      src/LibMemoryManagement.cpp
  7. 10
      src/LibMemoryManagement.h

@ -123,7 +123,7 @@ void AudioEffectAnalogDelay::update(void)
// 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);
if (blockToRelease) release(blockToRelease);
// BACK TO OUTPUT PROCESSING
// audio_block_t *blockToOutput = nullptr;
@ -134,10 +134,11 @@ void AudioEffectAnalogDelay::update(void)
// // copy over data
// m_memory->getSamples(blockToOutput, m_delaySamples);
// Check if external DMA, if so, we need to copy out of the DMA buffer
// Check if external DMA, if so, we need to be sure the read is completed
if (m_externalMemory && m_memory->getSlot()->isUseDma()) {
// Using DMA
m_memory->readDmaBufferContents(blockToOutput);
unsigned loopCount = 0;
while (m_memory->getSlot()->isReadBusy()) { /*Serial.println(String("RB:") + loopCount); loopCount++; */}
}
// perform the wet/dry mix mix
@ -147,6 +148,12 @@ void AudioEffectAnalogDelay::update(void)
release(inputAudioBlock);
release(m_previousBlock);
m_previousBlock = blockToOutput;
if (m_externalMemory && m_memory->getSlot()->isUseDma()) {
// Using DMA
unsigned loopCount = 0;
while (m_memory->getSlot()->isWriteBusy()) { /*Serial.println(String("WB:") + loopCount); loopCount++; */}
}
if (blockToRelease) release(blockToRelease);
}
void AudioEffectAnalogDelay::delay(float milliseconds)

@ -45,6 +45,8 @@ constexpr int SPI_ADDR_1_MASK = 0x00FF00;
constexpr int SPI_ADDR_1_SHIFT = 8;
constexpr int SPI_ADDR_0_MASK = 0x0000FF;
constexpr int CMD_ADDRESS_SIZE = 4;
constexpr int MAX_DMA_XFER_SIZE = 0x4000;
BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId)
{
@ -262,8 +264,8 @@ void BASpiMemory::read16(size_t address, uint16_t *dest, size_t numWords)
/////////////////////////////////////////////////////////////////////////////
// BASpiMemoryDMA
/////////////////////////////////////////////////////////////////////////////
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes)
: BASpiMemory(memDeviceId), m_bufferSize(bufferSizeBytes)
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId)
: BASpiMemory(memDeviceId)
{
int cs;
switch (memDeviceId) {
@ -277,15 +279,15 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes)
cs = SPI_CS_MEM0;
}
m_cs = new ActiveLowChipSelect(cs, m_settings);
// add 4 bytes to buffer for SPI CMD and 3 bytes of addresse
m_txBuffer = new uint8_t[bufferSizeBytes+4];
m_rxBuffer = new uint8_t[bufferSizeBytes+4];
m_txTransfer = new DmaSpi::Transfer();
m_rxTransfer = new DmaSpi::Transfer();
// add 4 bytes to buffer for SPI CMD and 3 bytes of address
m_txCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
m_rxCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
m_txTransfer = new DmaSpi::Transfer[2];
m_rxTransfer = new DmaSpi::Transfer[2];
}
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes)
: BASpiMemory(memDeviceId, speedHz), m_bufferSize(bufferSizeBytes)
BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz)
: BASpiMemory(memDeviceId, speedHz)
{
int cs;
switch (memDeviceId) {
@ -299,19 +301,19 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t
cs = SPI_CS_MEM0;
}
m_cs = new ActiveLowChipSelect(cs, m_settings);
m_txBuffer = new uint8_t[bufferSizeBytes+4];
m_rxBuffer = new uint8_t[bufferSizeBytes+4];
m_txTransfer = new DmaSpi::Transfer();
m_rxTransfer = new DmaSpi::Transfer();
m_txCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
m_rxCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
m_txTransfer = new DmaSpi::Transfer[2];
m_rxTransfer = new DmaSpi::Transfer[2];
}
BASpiMemoryDMA::~BASpiMemoryDMA()
{
delete m_cs;
if (m_txBuffer) delete [] m_txBuffer;
if (m_rxBuffer) delete [] m_rxBuffer;
if (m_txTransfer) delete m_txTransfer;
if (m_rxTransfer) delete m_rxTransfer;
if (m_txTransfer) delete [] m_txTransfer;
if (m_rxTransfer) delete [] m_rxTransfer;
if (m_txCommandBuffer) delete [] m_txCommandBuffer;
if (m_rxCommandBuffer) delete [] m_txCommandBuffer;
}
void BASpiMemoryDMA::m_setSpiCmdAddr(int command, size_t address, uint8_t *dest)
@ -358,91 +360,102 @@ void BASpiMemoryDMA::begin(void)
m_started = true;
}
// SPI must build up a payload that starts the teh CMD/Address first. It will cycle
// through the payloads in a circular buffer and use the transfer objects to check if they
// are done before continuing.
void BASpiMemoryDMA::write(size_t address, uint8_t *src, size_t numBytes)
{
while ( m_txTransfer->busy()) {} // wait until not busy
uint16_t transferCount = numBytes + 4; // transfer must be increased by the SPI command and address
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, src, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
size_t bytesRemaining = numBytes;
uint8_t *srcPtr = src;
size_t nextAddress = address;
while (bytesRemaining > 0) {
m_txXferCount = min(bytesRemaining, MAX_DMA_XFER_SIZE);
while ( m_txTransfer[1].busy()) {Serial.println("W1");} // wait until not busy
m_setSpiCmdAddr(SPI_WRITE_CMD, nextAddress, m_txCommandBuffer);
m_txTransfer[1] = DmaSpi::Transfer(m_txCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
m_spiDma->registerTransfer(m_txTransfer[1]);
while ( m_txTransfer[0].busy()) { Serial.println("W2");} // wait until not busy
m_txTransfer[0] = DmaSpi::Transfer(srcPtr, m_txXferCount, nullptr, 0, m_cs, TransferType::NO_START_CS);
m_spiDma->registerTransfer(m_txTransfer[0]);
bytesRemaining -= m_txXferCount;
srcPtr += m_txXferCount;
nextAddress += m_txXferCount;
}
}
void BASpiMemoryDMA::zero(size_t address, size_t numBytes)
{
while ( m_txTransfer->busy()) {}
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memset(m_txBuffer+4, 0, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
size_t bytesRemaining = numBytes;
size_t nextAddress = address;
while (bytesRemaining > 0) {
m_txXferCount = min(bytesRemaining, MAX_DMA_XFER_SIZE);
while ( m_txTransfer[1].busy()) {} // wait until not busy
m_setSpiCmdAddr(SPI_WRITE_CMD, nextAddress, m_txCommandBuffer);
m_txTransfer[1] = DmaSpi::Transfer(m_txCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
m_spiDma->registerTransfer(m_txTransfer[1]);
while ( m_txTransfer[0].busy()) {} // wait until not busy
m_txTransfer[0] = DmaSpi::Transfer(nullptr, m_txXferCount, nullptr, 0, m_cs, TransferType::NO_START_CS);
m_spiDma->registerTransfer(m_txTransfer[0]);
bytesRemaining -= m_txXferCount;
nextAddress += m_txXferCount;
}
}
void BASpiMemoryDMA::write16(size_t address, uint16_t *src, size_t numWords)
{
while ( m_txTransfer->busy()) {}
size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memcpy(m_txBuffer+4, src, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
write(address, reinterpret_cast<uint8_t*>(src), sizeof(uint16_t)*numWords);
}
void BASpiMemoryDMA::zero16(size_t address, size_t numWords)
{
while ( m_txTransfer->busy()) {}
size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_WRITE_CMD, address, m_txBuffer);
memset(m_txBuffer+4, 0, numBytes);
*m_txTransfer = DmaSpi::Transfer(m_txBuffer, transferCount, nullptr, 0, m_cs);
m_spiDma->registerTransfer(*m_txTransfer);
zero(address, sizeof(uint16_t)*numWords);
}
void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes)
{
UNUSED(dest);
while ( m_rxTransfer->busy()) {}
uint16_t transferCount = numBytes + 4;
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
*m_rxTransfer = DmaSpi::Transfer(m_rxBuffer, transferCount, m_rxBuffer, 0, m_cs);
m_spiDma->registerTransfer(*m_rxTransfer);
size_t bytesRemaining = numBytes;
uint8_t *destPtr = dest;
size_t nextAddress = address;
while (bytesRemaining > 0) {
m_setSpiCmdAddr(SPI_READ_CMD, nextAddress, m_rxCommandBuffer);
while ( m_rxTransfer[1].busy()) { Serial.println("R1"); }
m_rxTransfer[1] = DmaSpi::Transfer(m_rxCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
m_spiDma->registerTransfer(m_rxTransfer[1]);
m_rxXferCount = min(bytesRemaining, MAX_DMA_XFER_SIZE);
while ( m_rxTransfer[0].busy()) {Serial.println("R2");}
m_rxTransfer[0] = DmaSpi::Transfer(nullptr, m_rxXferCount, destPtr, 0, m_cs, TransferType::NO_START_CS);
m_spiDma->registerTransfer(m_rxTransfer[0]);
bytesRemaining -= m_rxXferCount;
destPtr += m_rxXferCount;
nextAddress += m_rxXferCount;
}
}
void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
{
UNUSED(dest);
while ( m_rxTransfer->busy()) {}
m_setSpiCmdAddr(SPI_READ_CMD, address, m_rxBuffer);
size_t numBytes = sizeof(uint16_t)*numWords;
uint16_t transferCount = numBytes + 4;
*m_rxTransfer = DmaSpi::Transfer(m_rxBuffer, transferCount, m_rxBuffer, 0, m_cs);
m_spiDma->registerTransfer(*m_rxTransfer);
}
bool BASpiMemoryDMA::isWriteBusy(void)
void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
{
return m_txTransfer->busy();
read(address, reinterpret_cast<uint8_t*>(dest), sizeof(uint16_t)*numWords);
}
bool BASpiMemoryDMA::isReadBusy(void)
{
return m_rxTransfer->busy();
}
void BASpiMemoryDMA::readBufferContents(uint16_t *dest, size_t numWords, size_t wordOffset)
bool BASpiMemoryDMA::isWriteBusy(void) const
{
readBufferContents(reinterpret_cast<uint8_t *>(dest), sizeof(uint16_t)*numWords, sizeof(uint16_t)*wordOffset);
return (m_txTransfer[0].busy() or m_txTransfer[1].busy());
}
void BASpiMemoryDMA::readBufferContents(uint8_t *dest, size_t numBytes, size_t byteOffset)
bool BASpiMemoryDMA::isReadBusy(void) const
{
while (m_rxTransfer->busy()) {} // ensure transfer is complete
memcpy(dest, m_rxBuffer+4+byteOffset, numBytes);
return (m_rxTransfer[0].busy() or m_rxTransfer[1].busy());
}
} /* namespace BAGuitar */

@ -128,14 +128,12 @@ public:
/// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2).
/// @details default is 20 Mhz
/// @param memDeviceId specify which MEM to control with SpiDeviceId.
/// @param bufferSize size of buffer to store DMA transfers
BASpiMemoryDMA(SpiDeviceId memDeviceId, size_t bufferSizeBytes);
BASpiMemoryDMA(SpiDeviceId memDeviceId);
/// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2)
/// @param memDeviceId specify which MEM to control with SpiDeviceId.
/// @param speedHz specify the desired speed in Hz.
/// @param bufferSize size of buffer to store DMA transfers
BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz, size_t bufferSizeBytes);
BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz);
virtual ~BASpiMemoryDMA();
/// initialize and configure the SPI peripheral
@ -177,11 +175,11 @@ public:
/// Check if a DMA write is in progress
/// @returns true if a write DMA is in progress, else false
bool isWriteBusy();
bool isWriteBusy() const;
/// Check if a DMA read is in progress
/// @returns true if a read DMA is in progress, else false
bool isReadBusy();
bool isReadBusy() const;
/// Readout the 8-bit contents of the DMA storage buffer to the specified destination
/// @param dest pointer to the destination
@ -198,12 +196,17 @@ public:
private:
AbstractDmaSpi<DmaSpi0, SPIClass, SPI> *m_spiDma = nullptr;
ActiveLowChipSelect *m_cs = nullptr;
size_t m_bufferSize;
uint8_t *m_txBuffer = nullptr;
//size_t m_bufferSize;
//uint8_t *m_txBuffer = nullptr;
uint8_t *m_txCommandBuffer = nullptr;
DmaSpi::Transfer *m_txTransfer;
uint8_t *m_rxBuffer = nullptr;
//uint8_t *m_rxBuffer = nullptr;
uint8_t *m_rxCommandBuffer = nullptr;
DmaSpi::Transfer *m_rxTransfer;
uint16_t m_txXferCount;
uint16_t m_rxXferCount;
void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest);
};

@ -234,11 +234,6 @@ 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
////////////////////////////////////////////////////

@ -93,6 +93,7 @@ class RingBuffer; // forward declare so AudioDelay can use it.
* approach. When using EXTERNAL memory, data is actually copyied to/from an external
* SRAM device.
*****************************************************************************/
constexpr size_t AUDIO_BLOCK_SIZE = sizeof(int16_t)*AUDIO_BLOCK_SAMPLES;
class AudioDelay {
public:
AudioDelay() = delete;
@ -140,8 +141,6 @@ public:
/// @returns pointer to the underlying ExtMemSlot.
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; }
private:

@ -175,16 +175,6 @@ bool ExtMemSlot::zeroAdvance16(size_t numWords)
return true;
}
void ExtMemSlot::readDmaBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset)
{
if (m_useDma) {
(static_cast<BASpiMemoryDMA*>(m_spi))->readBufferContents(dest, numBytes, bufferOffset);
// BASpiMemoryDMA *spi = nullptr;
// spi = static_cast<BASpiMemoryDMA>(m_spi);
// spi->readBufferContents(dest, numBytes, bufferOffset);
}
}
bool ExtMemSlot::writeAdvance16(int16_t data)
{
@ -219,6 +209,21 @@ bool ExtMemSlot::isEnabled() const
else return false;
}
bool ExtMemSlot::isWriteBusy() const
{
if (m_useDma) {
return (static_cast<BASpiMemoryDMA*>(m_spi))->isWriteBusy();
} else { return false; }
}
bool ExtMemSlot::isReadBusy() const
{
if (m_useDma) {
return (static_cast<BASpiMemoryDMA*>(m_spi))->isReadBusy();
} else { return false; }
}
void ExtMemSlot::printStatus(void) const
{
Serial.println(String("valid:") + m_valid + String(" m_start:") + m_start + \
@ -261,14 +266,14 @@ size_t ExternalSramManager::availableMemory(BAGuitar::MemSelect mem)
return m_memConfig[mem].totalAvailable;
}
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem, size_t dmaBufferSize)
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem, bool useDma)
{
// convert the time to numer of samples
size_t delayLengthInt = (size_t)((delayMilliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f);
return requestMemory(slot, delayLengthInt * sizeof(int16_t), mem, dmaBufferSize);
return requestMemory(slot, delayLengthInt * sizeof(int16_t), mem, useDma);
}
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem, size_t dmaBufferSize)
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem, bool useDma)
{
if (m_memConfig[mem].totalAvailable >= sizeBytes) {
@ -281,16 +286,16 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGu
slot->m_size = sizeBytes;
if (!m_memConfig[mem].m_spi) {
if (dmaBufferSize > 0) {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemoryDMA(static_cast<BAGuitar::SpiDeviceId>(mem), dmaBufferSize);
if (useDma) {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemoryDMA(static_cast<BAGuitar::SpiDeviceId>(mem));
slot->m_useDma = true;
} else {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemory(static_cast<BAGuitar::SpiDeviceId>(mem));
slot->m_useDma = false;
}
if (!m_memConfig[mem].m_spi) {
Serial.println("requestMemory: new failed! m_spi is a nullptr");
} else {
Serial.println("Calling spi begin()");
m_memConfig[mem].m_spi->begin();
}
}
@ -301,7 +306,9 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGu
m_memConfig[mem].totalAvailable -= sizeBytes;
slot->m_valid = true;
if (!slot->isEnabled()) { slot->enable(); }
Serial.println("Clear the memory\n"); Serial.flush();
slot->clear();
Serial.println("Done Request memory\n"); Serial.flush();
return true;
} else {
// there is not enough memory available for the request

@ -128,8 +128,6 @@ public:
/// @returns true on success, else false on error
bool zeroAdvance16(size_t numWords);
void readDmaBufferContents(uint8_t *dest, size_t numBytes, size_t bufferOffset = 0);
/// Get the size of the memory slot
/// @returns size of the slot in bytes
size_t size() const { return m_size; }
@ -144,6 +142,10 @@ public:
bool isUseDma() const { return m_useDma; }
bool isWriteBusy() const;
bool isReadBusy() const;
/// DEBUG USE: prints out the slot member variables
void printStatus(void) const;
@ -188,7 +190,7 @@ public:
/// @param mem specify which external memory to allocate from
/// @param dmaBufferSize When > 0, DMA mode is used with the specified DMA buffer size
/// @returns true on success, otherwise false on error
bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0, size_t dmaBufferSize = 0);
bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0, bool useDma = false);
/// Request memory be allocated for the provided slot
/// @param slot a pointer to the global slot object to which memory will be allocated
@ -196,7 +198,7 @@ public:
/// @param mem specify which external memory to allocate from
/// @param dmaBufferSize When > 0, DMA mode is used with the specified DMA buffer size
/// @returns true on success, otherwise false on error
bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0, size_t dmaBufferSize = 0);
bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0, bool useDma = false);
private:
static bool m_configured; ///< there should only be one instance of ExternalSramManager in the whole project

Loading…
Cancel
Save