diff --git a/src/AudioEffectAnalogDelay.cpp b/src/AudioEffectAnalogDelay.cpp
index 97e2bfb..e08ecf7 100644
--- a/src/AudioEffectAnalogDelay.cpp
+++ b/src/AudioEffectAnalogDelay.cpp
@@ -71,7 +71,7 @@ void AudioEffectAnalogDelay::update(void)
m_callCount++;
Serial.println(String("AudioEffectAnalgDelay::update: ") + m_callCount);
- m_memory->getSlot()->printStatus();
+ //m_memory->getSlot()->printStatus();
audio_block_t *blockToRelease = m_memory->addBlock(inputAudioBlock);
// if (inputAudioBlock) {
@@ -113,7 +113,7 @@ void AudioEffectAnalogDelay::update(void)
if (!blockToOutput) continue; // skip this channel due to failure
// copy over data
m_memory->getSamples(blockToOutput, m_channelOffsets[channel]);
- //m_memory->read16(blockToOutput->data, 0, m_channelOffsets[channel], AUDIO_BLOCK_SAMPLES);
+
transmit(blockToOutput);
release(blockToOutput);
}
@@ -126,6 +126,8 @@ bool AudioEffectAnalogDelay::delay(unsigned channel, float milliseconds)
size_t delaySamples = calcAudioSamples(milliseconds);
+ if (!m_memory) { Serial.println("delay(): m_memory is not valid"); }
+
if (!m_externalMemory) {
// internal memory
QueuePosition queuePosition = calcQueuePosition(milliseconds);
@@ -134,10 +136,11 @@ bool AudioEffectAnalogDelay::delay(unsigned channel, float milliseconds)
// external memory
Serial.println(String("CONFIG: delay:") + delaySamples);
ExtMemSlot *slot = m_memory->getSlot();
+
+ if (!slot) { Serial.println("ERROR: slot ptr is not valid"); }
if (!slot->isEnabled()) {
slot->enable();
- } else {
- Serial.println("ERROR: slot ptr is not valid");
+ Serial.println("WEIRD: slot was not enabled");
}
}
@@ -151,12 +154,15 @@ bool AudioEffectAnalogDelay::delay(unsigned channel, size_t delaySamples)
if (channel > MAX_DELAY_CHANNELS-1) // channel id too high
return false;
+ if (!m_memory) { Serial.println("delay(): m_memory is not valid"); }
+
if (!m_externalMemory) {
// internal memory
QueuePosition queuePosition = calcQueuePosition(delaySamples);
Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
} else {
// external memory
+ Serial.println(String("CONFIG: delay:") + delaySamples);
ExtMemSlot *slot = m_memory->getSlot();
if (!slot->isEnabled()) {
slot->enable();
diff --git a/src/BAAudioControlWM8731.h b/src/BAAudioControlWM8731.h
index af00261..7d930c5 100644
--- a/src/BAAudioControlWM8731.h
+++ b/src/BAAudioControlWM8731.h
@@ -22,8 +22,8 @@
* along with this program. If not, see .
*****************************************************************************/
-#ifndef __INC_BAAUDIOCONTROLWM8731_H
-#define __INC_BAAUDIOCONTROLWM8731_H
+#ifndef __BAAUDIOCONTROLWM8731_H
+#define __BAAUDIOCONTROLWM8731_H
namespace BAGuitar {
@@ -128,4 +128,4 @@ private:
} /* namespace BAGuitar */
-#endif /* __INC_BAAUDIOCONTROLWM8731_H */
+#endif /* __BAAUDIOCONTROLWM8731_H */
diff --git a/src/BASpiMemory.h b/src/BASpiMemory.h
index efc2acc..2f2a765 100644
--- a/src/BASpiMemory.h
+++ b/src/BASpiMemory.h
@@ -59,7 +59,7 @@ public:
void write16(size_t address, uint16_t data);
void write16(size_t address, uint16_t *data, size_t numWords);
- void zero16(size_t address, size_t numBytes);
+ void zero16(size_t address, size_t numWords);
/// read a single 8-bit data word from the specified address
/// @param address the address in the SPI RAM to read from
diff --git a/src/LibBasicFunctions.cpp b/src/LibBasicFunctions.cpp
index e78049a..1272703 100644
--- a/src/LibBasicFunctions.cpp
+++ b/src/LibBasicFunctions.cpp
@@ -50,9 +50,10 @@ AudioDelay::AudioDelay(float maxDelayTimeMs)
}
AudioDelay::AudioDelay(ExtMemSlot *slot)
-: m_slot(slot)
+//: m_slot(slot)
{
m_type = MemType::MEM_EXTERNAL;
+ m_slot = slot;
}
AudioDelay::~AudioDelay()
@@ -77,15 +78,24 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block)
return blockToRelease;
} else {
// EXTERNAL memory
+ if (!m_slot) { Serial.println("addBlock(): m_slot is not valid"); }
- //m_slot->writeAdvance16(block->data, AUDIO_BLOCK_SAMPLES);
+ if (block) {
+
+ // Audio is stored in reverse in block so we need to write it backwards to external memory
+ // to maintain temporal coherency.
+// int16_t *srcPtr = block->data + AUDIO_BLOCK_SAMPLES - 1;
+// for (int i=0; iwriteAdvance16(*srcPtr);
+// srcPtr--;
+// }
+
+ int16_t *srcPtr = block->data;
+ for (int i=0; iwriteAdvance16(*srcPtr);
+ srcPtr++;
+ }
- // Audio is stored in reverse in block so we need to write it backwards to external memory
- // to maintain temporal coherency.
- int16_t *srcPtr = block->data + AUDIO_BLOCK_SAMPLES - 1;
- for (int i=0; iwriteAdvance16(*srcPtr);
- srcPtr--;
}
return block;
@@ -140,25 +150,36 @@ bool AudioDelay::getSamples(audio_block_t *dest, size_t offset, size_t numSample
} else {
// EXTERNAL Memory
- if (numSamples <= m_slot->size() ) {
- int currentPosition = (int)m_slot->getWritePosition() - (int)AUDIO_BLOCK_SAMPLES;
+ if (numSamples*sizeof(int16_t) <= m_slot->size() ) {
+ int currentPositionBytes = (int)m_slot->getWritePosition() - (int)(AUDIO_BLOCK_SAMPLES*sizeof(int16_t));
+ size_t offsetBytes = offset * sizeof(int16_t);
- if ((int)offset <= currentPosition) {
- m_slot->setReadPosition(currentPosition - offset);
+ if ((int)offsetBytes <= currentPositionBytes) {
+ m_slot->setReadPosition(currentPositionBytes - offsetBytes);
} else {
// It's going to wrap around to the end of the slot
- int readPosition = (int)m_slot->size() + currentPosition - offset;
+ int readPosition = (int)m_slot->size() + currentPositionBytes - offsetBytes;
m_slot->setReadPosition((size_t)readPosition);
}
+ m_slot->printStatus();
+
// write the data to the destination block in reverse
- int16_t *destPtr = dest->data + AUDIO_BLOCK_SAMPLES-1;
+// int16_t *destPtr = dest->data + AUDIO_BLOCK_SAMPLES-1;
+// for (int i=0; ireadAdvance16();
+// destPtr--;
+// }
+
+ int16_t *destPtr = dest->data;
for (int i=0; ireadAdvance16();
+ destPtr++;
}
return true;
} else {
// numSampmles is > than total slot size
+ Serial.println("getSamples(): ERROR numSamples > total slot size");
return false;
}
}
diff --git a/src/LibMemoryManagement.cpp b/src/LibMemoryManagement.cpp
index 9f413b1..9927121 100644
--- a/src/LibMemoryManagement.cpp
+++ b/src/LibMemoryManagement.cpp
@@ -1,9 +1,26 @@
-
+/*
+ * LibMemoryManagement.cpp
+ *
+ * Created on: Jan 19, 2018
+ * Author: slascos
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.*
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
#include
#include
#include "Audio.h"
-
#include "LibMemoryManagement.h"
namespace BAGuitar {
@@ -19,12 +36,21 @@ bool ExtMemSlot::clear()
return true;
}
-bool ExtMemSlot::write16(size_t offset, int16_t *dataPtr, size_t dataSize)
+bool ExtMemSlot::setWritePosition(size_t offsetBytes)
+{
+ if (m_start + offsetBytes <= m_end) {
+ m_currentWrPosition = m_start + offsetBytes;
+ return true;
+ } else { return false; }
+}
+
+bool ExtMemSlot::write16(size_t offsetBytes, int16_t *dest, size_t numWords)
{
if (!m_valid) { return false; }
- size_t writeStart = m_start + offset;
- if ((writeStart + dataSize-1) <= m_end) {
- m_spi->write16(writeStart, reinterpret_cast(dataPtr), dataSize); // cast audio data to uint
+ size_t writeStart = m_start + offsetBytes; // 2x because int16 is two bytes per data
+ size_t numBytes = sizeof(int16_t)*numWords;
+ if ((writeStart + numBytes-1) <= m_end) {
+ m_spi->write16(writeStart, reinterpret_cast(dest), numWords); // cast audio data to uint
return true;
} else {
// this would go past the end of the memory slot, do not perform the write
@@ -32,12 +58,23 @@ bool ExtMemSlot::write16(size_t offset, int16_t *dataPtr, size_t dataSize)
}
}
-bool ExtMemSlot::zero16(size_t offset, size_t dataSize)
+bool ExtMemSlot::setReadPosition(size_t offsetBytes)
+{
+ if (m_start + offsetBytes <= m_end) {
+ m_currentRdPosition = m_start + offsetBytes;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool ExtMemSlot::zero16(size_t offsetBytes, size_t numWords)
{
if (!m_valid) { return false; }
- size_t writeStart = m_start + offset;
- if ((writeStart + dataSize-1) <= m_end) {
- m_spi->zero16(writeStart, dataSize); // cast audio data to uint
+ size_t writeStart = m_start + offsetBytes;
+ size_t numBytes = sizeof(int16_t)*numWords;
+ if ((writeStart + numBytes-1) <= m_end) {
+ m_spi->zero16(writeStart, numWords); // cast audio data to uint
return true;
} else {
// this would go past the end of the memory slot, do not perform the write
@@ -45,16 +82,17 @@ bool ExtMemSlot::zero16(size_t offset, size_t dataSize)
}
}
-bool ExtMemSlot::read16(int16_t *dest, size_t srcOffset, size_t numData)
+bool ExtMemSlot::read16(int16_t *dest, size_t offsetBytes, size_t numWords)
{
if (!dest) return false; // invalid destination
- size_t readOffset = m_start + srcOffset;
+ size_t readOffset = m_start + offsetBytes;
+ size_t numBytes = sizeof(int16_t)*numWords;
- if ((readOffset + (numData*sizeof(int16_t))-1) <= m_end) {
- m_spi->read16(readOffset, reinterpret_cast(dest), numData);
+ if ((readOffset + numBytes-1) <= m_end) {
+ m_spi->read16(readOffset, reinterpret_cast(dest), numWords);
return true;
} else {
- // this would go past the end of the memory slot, do not perform the write
+ // this would go past the end of the memory slot, do not perform the read
return false;
}
}
@@ -62,8 +100,8 @@ bool ExtMemSlot::read16(int16_t *dest, size_t srcOffset, size_t numData)
uint16_t ExtMemSlot::readAdvance16()
{
uint16_t val = m_spi->read16(m_currentRdPosition);
- if (m_currentRdPosition < m_end) {
- m_currentRdPosition++;
+ if (m_currentRdPosition < m_end-1) {
+ m_currentRdPosition +=2; // position is in bytes and we read two
} else {
m_currentRdPosition = m_start;
}
@@ -71,70 +109,65 @@ uint16_t ExtMemSlot::readAdvance16()
}
-//void ExtMemSlot::read16FromPast(int16_t *dest, size_t currentOffset, size_t numData)
-//{
-// size_t readStart;
-// if (m_currentPosition - currentOffset >= m_start) {
-// readStart = m_currentPosition - currentOffset;
-// } else {
-// // this offset will wrap the memory slot
-// size_t numBytesToStart = m_currentPosition;
-// readStart = m_end - (currentOffset - numBytesToStart);
-// }
-// m_spi->read16(readStart, reinterpret_cast(dest), numData);
-//}
-
-bool ExtMemSlot::writeAdvance16(int16_t *dataPtr, size_t dataSize)
+bool ExtMemSlot::writeAdvance16(int16_t *src, size_t numWords)
{
if (!m_valid) { return false; }
- if (m_currentWrPosition + dataSize-1 <= m_end) {
+ size_t numBytes = sizeof(int16_t)*numWords;
+
+ if (m_currentWrPosition + numBytes-1 <= m_end) {
// entire block fits in memory slot without wrapping
- m_spi->write16(m_currentWrPosition, reinterpret_cast(dataPtr), dataSize); // cast audio data to uint.
- m_currentWrPosition += dataSize;
+ m_spi->write16(m_currentWrPosition, reinterpret_cast(src), numWords); // cast audio data to uint.
+ m_currentWrPosition += numBytes;
} else {
// this write will wrap the memory slot
- size_t numBytes = m_end - m_currentWrPosition + 1;
- m_spi->write16(m_currentWrPosition, reinterpret_cast(dataPtr), numBytes);
- size_t remainingBytes = dataSize - numBytes; // calculate the remaining bytes
- m_spi->write16(m_start, reinterpret_cast(dataPtr + numBytes), remainingBytes); // write remaining bytes are start
- m_currentWrPosition = m_start + remainingBytes;
+ size_t wrBytes = m_end - m_currentWrPosition + 1;
+ size_t wrDataNum = wrBytes >> 1; // divide by two to get the number of data
+ m_spi->write16(m_currentWrPosition, reinterpret_cast(src), wrDataNum);
+ size_t remainingData = numWords - wrDataNum;
+ m_spi->write16(m_start, reinterpret_cast(src + wrDataNum), remainingData); // write remaining bytes are start
+ m_currentWrPosition = m_start + (remainingData*sizeof(int16_t));
}
return true;
}
-bool ExtMemSlot::writeAdvance16(int16_t data)
+
+bool ExtMemSlot::zeroAdvance16(size_t numWords)
{
if (!m_valid) { return false; }
+ size_t numBytes = 2*numWords;
+ if (m_currentWrPosition + numBytes-1 <= m_end) {
+ // entire block fits in memory slot without wrapping
+ m_spi->zero16(m_currentWrPosition, numWords); // cast audio data to uint.
+ m_currentWrPosition += numBytes;
- m_spi->write16(m_currentWrPosition, static_cast(data));
- if (m_currentWrPosition < m_end) {
- m_currentWrPosition++;
} else {
- m_currentWrPosition = m_start;
+ // this write will wrap the memory slot
+ size_t wrBytes = m_end - m_currentWrPosition + 1;
+ size_t wrDataNum = wrBytes >> 1;
+ m_spi->zero16(m_currentWrPosition, wrDataNum);
+ size_t remainingWords = numWords - wrDataNum; // calculate the remaining bytes
+ m_spi->zero16(m_start, remainingWords); // write remaining bytes are start
+ m_currentWrPosition = m_start + remainingWords*sizeof(int16_t);
}
return true;
}
-bool ExtMemSlot::zeroAdvance16(size_t dataSize)
+
+bool ExtMemSlot::writeAdvance16(int16_t data)
{
if (!m_valid) { return false; }
- if (m_currentWrPosition + dataSize-1 <= m_end) {
- // entire block fits in memory slot without wrapping
- m_spi->zero16(m_currentWrPosition, dataSize); // cast audio data to uint.
- m_currentWrPosition += dataSize;
+ m_spi->write16(m_currentWrPosition, static_cast(data));
+ if (m_currentWrPosition < m_end-1) {
+ m_currentWrPosition+=2; // wrote two bytes
} else {
- // this write will wrap the memory slot
- size_t numBytes = m_end - m_currentWrPosition + 1;
- m_spi->zero16(m_currentWrPosition, numBytes);
- size_t remainingBytes = dataSize - numBytes; // calculate the remaining bytes
- m_spi->zero16(m_start, remainingBytes); // write remaining bytes are start
- m_currentWrPosition = m_start + remainingBytes;
+ m_currentWrPosition = m_start;
}
return true;
}
+
bool ExtMemSlot::enable() const
{
if (m_spi) {
@@ -158,6 +191,7 @@ void ExtMemSlot::printStatus(void) const
{
Serial.println(String("valid:") + m_valid + String(" m_start:") + m_start + \
String(" m_end:") + m_end + String(" m_currentWrPosition: ") + m_currentWrPosition + \
+ String(" m_currentRdPosition: ") + m_currentRdPosition + \
String(" m_size:") + m_size);
}
@@ -178,11 +212,6 @@ ExternalSramManager::ExternalSramManager(unsigned numMemories)
m_memConfig[i].nextAvailable = 0;
m_memConfig[i].m_spi = nullptr;
-// if (i < numMemories) {
-// m_memConfig[i].m_spi = new BAGuitar::BASpiMemory(static_cast(i));
-// } else {
-// m_memConfig[i].m_spi = nullptr;
-// }
}
m_configured = true;
}
@@ -204,7 +233,7 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMillisecond
{
// 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, mem);
+ return requestMemory(slot, delayLengthInt * sizeof(int16_t), mem);
}
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem)
diff --git a/src/LibMemoryManagement.h b/src/LibMemoryManagement.h
index 9fedbc8..e4e44c8 100644
--- a/src/LibMemoryManagement.h
+++ b/src/LibMemoryManagement.h
@@ -1,87 +1,196 @@
-/*
- * ExtMemoryManagement.h
+/**************************************************************************//**
+ * @file
+ * @author Steve Lascos
+ * @company Blackaddr Audio
*
- * Created on: Dec 23, 2017
- * Author: slascos
- */
+ * LibMemoryManagment is a class for providing access to external SPI based
+ * SRAM with the optional convience of breaking it up into 'slots' which are smaller
+ * memory entities.
+ * @details This class treats an external memory as a pool from which the user requests
+ * a block. When using that block, the user need not be concerned with where the pool
+ * it came from, they only deal with offsets from the start of their memory block. Ie.
+ * Your particular slot of memory appears to you to start at 0 and end at whatever size
+ * was requested.
+ *
+ * @copyright This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.*
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
-#ifndef SRC_LIBMEMORYMANAGEMENT_H_
-#define SRC_LIBMEMORYMANAGEMENT_H_
+#ifndef __LIBMEMORYMANAGEMENT_H
+#define __LIBMEMORYMANAGEMENT_H
#include
-
-//#include "Audio.h"
-
#include "BAHardware.h"
#include "BASpiMemory.h"
-//#include "LibBasicFunctions.h"
namespace BAGuitar {
+/**************************************************************************//**
+ * MemConfig contains the configuration information associated with a particular
+ * SPI interface.
+ *****************************************************************************/
struct MemConfig {
- size_t size;
- size_t totalAvailable;
- size_t nextAvailable;
- BASpiMemory *m_spi = nullptr;
+ size_t size; ///< the total size of the external SPI memory
+ size_t totalAvailable; ///< the number of bytes available (remaining)
+ size_t nextAvailable; ///< the starting point for the next available slot
+ BASpiMemory *m_spi = nullptr; ///< handle to the SPI interface
};
-class ExternalSramManager; // forward declare so ExtMemSlot can setup friendship
+class ExternalSramManager; // forward declare so ExtMemSlot can declared friendship with it
+/**************************************************************************//**
+ * ExtMemSlot provides a convenient interface to a particular slot of an
+ * external memory.
+ * @details the memory can be access randomly, as a single word, as a block of
+ * data, or as circular queue.
+ *****************************************************************************/
class ExtMemSlot {
public:
+ /// clear the entire contents of the slot by writing zeros
+ /// @returns true on success
bool clear();
- bool setWritePosition(size_t offset) { m_currentWrPosition = m_start + offset; return true;} // TODO add range check
+
+ /// set a new write position (in bytes) for circular operation
+ /// @param offsetBytes moves the write pointer to the specified offset from the slot start
+ /// @returns true on success, else false if offset is beyond slot boundaries.
+ bool setWritePosition(size_t offsetBytes);
+
+ /// returns the currently set write pointer pointer
+ /// @returns the write position value
size_t getWritePosition() const { return m_currentWrPosition-m_start; }
- bool setReadPosition(size_t offset) { m_currentRdPosition = m_start + offset; return true;} // TODO add range check
- size_t getReadPosition() const { return m_currentRdPosition-m_start; }
+ /// set a new read position (in bytes) for circular operation
+ /// @param offsetBytes moves the read pointer to the specified offset from the slot start
+ /// @returns true on success, else false if offset is beyond slot boundaries.
+ bool setReadPosition(size_t offsetBytes);
- bool write16(size_t offset, int16_t *dataPtr, size_t numData);
- bool zero16(size_t offset, size_t numData);
- bool read16(int16_t *dest, size_t srcOffset, size_t numData);
+ /// returns the currently set read pointer pointer
+ /// @returns the read position value
+ size_t getReadPosition() const { return m_currentRdPosition-m_start; }
+ /// Write a block of 16-bit data to the memory at the specified offset
+ /// @param offsetBytes offset in bytes from start of slot
+ /// @param dataPtr pointer to start of block of 16-bit data
+ /// @param numWords number of 16-bit words to transfer
+ /// @returns true on success, else false on error
+ bool write16(size_t offsetBytes, int16_t *dest, size_t numWords);
+
+ /// Write a block of zeros (16-bit) to the memory at the specified offset
+ /// @param offsetBytes offset in bytes from start of slot
+ /// @param numWords number of 16-bit words to transfer
+ /// @returns true on success, else false on error
+ bool zero16(size_t offsetBytes, size_t numWords);
+
+ /// Read a block of 16-bit data from the memory at the specified location
+ /// @param dest pointer to destination for the read data
+ /// @param offsetBytes offset in bytes from start of slot
+ /// @param numWords number of 16-bit words to transfer
+ /// @returns true on success, else false on error
+ bool read16(int16_t *dest, size_t offsetBytes, size_t numWords);
+
+ /// Read the next in memory during circular operation
+ /// @returns the next 16-bit data word in memory
uint16_t readAdvance16();
- bool writeAdvance16(int16_t *dataPtr, size_t numData);
+
+ /// 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 numWords number of 16-bit words to transfer
+ /// @returns true on success, else false on error
+ bool writeAdvance16(int16_t *src, size_t numWords);
+
+ /// Write a single 16-bit data to the next location in circular operation
+ /// @param data the 16-bit word to transfer
+ /// @returns true on success, else false on error
bool writeAdvance16(int16_t data); // write just one data
- bool zeroAdvance16(size_t numData);
- //void read16FromPast(int16_t *dest, size_t Offset, size_t numData);
+
+ /// Write a block of 16-bit data zeros in circular operation
+ /// @param numWords number of 16-bit words to transfer
+ /// @returns true on success, else false on error
+ bool zeroAdvance16(size_t numWords);
+
+
+ /// Get the size of the memory slot
+ /// @returns size of the slot in bytes
size_t size() const { return m_size; }
+
+ /// Ensures the underlying SPI interface is enabled
+ /// @returns true on success, false on error
bool enable() const;
+
+ /// Checks whether underlying SPI interface is enabled
+ /// @returns true if enabled, false if not enabled
bool isEnabled() const;
+
+ /// DEBUG USE: prints out the slot member variables
void printStatus(void) const;
private:
- friend ExternalSramManager;
- bool m_valid = false;
- size_t m_start = 0;
- size_t m_end = 0;
- size_t m_currentWrPosition = 0;
- size_t m_currentRdPosition = 0;
- size_t m_size = 0;
- SpiDeviceId m_spiId;
- BASpiMemory *m_spi = nullptr;
+ friend ExternalSramManager; ///< gives the manager access to the private variables
+ bool m_valid = false; ///< After a slot is successfully configured by the manager it becomes valid
+ size_t m_start = 0; ///< the external memory address in bytes where this slot starts
+ size_t m_end = 0; ///< the external memory address in bytes where this slot ends (inclusive)
+ 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_size = 0; ///< size of this slot in bytes
+ SpiDeviceId m_spiId; ///< the SPI Device ID
+ BASpiMemory *m_spi = nullptr; ///< pointer to an instance of the BASpiMemory interface class
};
+/**************************************************************************//**
+ * ExternalSramManager provides a class to handle dividing an external SPI RAM
+ * into independent slots for general use.
+ * @details the class does not support deallocated memory because this would cause
+ * fragmentation.
+ *****************************************************************************/
class ExternalSramManager final {
public:
ExternalSramManager() = delete;
- ExternalSramManager(unsigned numMemories);
+
+ /// The manager is constructed by specifying how many external memories to handle allocations for
+ /// @param numMemories the number of external memories
+ ExternalSramManager(unsigned numMemories = 1);
virtual ~ExternalSramManager();
- size_t availableMemory(BAGuitar::MemSelect mem);
+ /// Query the amount of available (unallocated) memory
+ /// @details note that currently, memory cannot be allocated.
+ /// @param mem specifies which memory to query, default is memory 0
+ /// @returns the available memory in bytes
+ size_t availableMemory(BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
+
+ /// Request memory be allocated for the provided slot
+ /// @param slot a pointer to the global slot object to which memory will be allocated
+ /// @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
+ /// @returns true on success, otherwise false on error
bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
- bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
+
+ /// Request memory be allocated for the provided slot
+ /// @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 mem specify which external memory to allocate from
+ /// @returns true on success, otherwise false on error
+ bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
private:
- static bool m_configured;
- static MemConfig m_memConfig[BAGuitar::NUM_MEM_SLOTS];
+ static bool m_configured; ///< there should only be one instance of ExternalSramManager in the whole project
+ static MemConfig m_memConfig[BAGuitar::NUM_MEM_SLOTS]; ///< store the configuration information for each external memory
};
}
-#endif /* SRC_LIBMEMORYMANAGEMENT_H_ */
+#endif /* __LIBMEMORYMANAGEMENT_H */