Cleanup and fix issue with DMA transfers on T4 (#13)

pull/14/head
Blackaddr Audio 3 years ago committed by GitHub
parent 8b2b0b066b
commit 7de9898bc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/BAGpio.h
  2. 7
      src/common/AudioDelay.cpp
  3. 6
      src/common/ExtMemSlot.cpp
  4. 76
      src/effects/AudioEffectAnalogDelay.cpp
  5. 15
      src/effects/AudioEffectTremolo.cpp
  6. 51
      src/peripherals/BAGpio.cpp
  7. 3
      src/peripherals/BAPhysicalControls.cpp
  8. 80
      src/peripherals/BASpiMemory.cpp

@ -67,6 +67,11 @@ public:
/// @returns the new stage of the user LED.
int toggleLed();
/// Convert the GPIO enum to the underlying logical pin number
/// @param gpio the enum value to convert
/// @returns the logical pin number for the GPIO
uint8_t enumToPinNumber(GPIO gpio);
private:
uint8_t m_ledState;
};

@ -87,7 +87,6 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block)
setSpiDmaCopyBuffer();
#endif
// this causes pops
m_slot->writeAdvance16(block->data, AUDIO_BLOCK_SAMPLES);
}
blockToRelease = block;
@ -115,7 +114,10 @@ size_t AudioDelay::getMaxDelaySamples()
bool AudioDelay::getSamples(audio_block_t *dest, size_t offsetSamples, size_t numSamples)
{
return m_getSamples(dest->data, offsetSamples, numSamples);
if (!dest) { return false; }
else {
return m_getSamples(dest->data, offsetSamples, numSamples);
}
}
bool AudioDelay::getSamples(int16_t *dest, size_t offsetSamples, size_t numSamples)
@ -221,6 +223,7 @@ bool AudioDelay::interpolateDelay(int16_t *extendedSourceBuffer, int16_t *destBu
bool AudioDelay::setSpiDmaCopyBuffer(void)
{
bool returnValue = false;
if (m_slot->isUseDma()) {
// For DMA use on T4.0 we need this kluge
BASpiMemoryDMA * spiDma = static_cast<BASpiMemoryDMA*>(m_slot->getSpiMemoryHandle());

@ -144,11 +144,17 @@ bool ExtMemSlot::writeAdvance16(int16_t *src, size_t numWords)
// this write will wrap the memory slot
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<uint16_t*>(src), wrDataNum);
size_t remainingData = numWords - wrDataNum;
m_spi->write16(m_start, reinterpret_cast<uint16_t*>(src + wrDataNum), remainingData); // write remaining bytes are start
m_currentWrPosition = m_start + (remainingData*sizeof(int16_t));
}
// If a write transaction landed exactly on the end of the memory, the next position must be
// manually put back to the start
if (m_currentWrPosition > m_end) { m_currentWrPosition = m_start; }
return true;
}

@ -77,50 +77,52 @@ void AudioEffectAnalogDelay::setFilter(Filter filter)
void AudioEffectAnalogDelay::update(void)
{
audio_block_t *inputAudioBlock = receiveReadOnly(); // get the next block of input samples
// Check is block is disabled
if (m_enable == false) {
// do not transmit or process any audio, return as quickly as possible.
if (inputAudioBlock) release(inputAudioBlock);
// release all held memory resources
if (m_previousBlock) {
release(m_previousBlock); m_previousBlock = nullptr;
}
if (!m_externalMemory) {
// when using internal memory we have to release all references in the ring buffer
while (m_memory->getRingBuffer()->size() > 0) {
audio_block_t *releaseBlock = m_memory->getRingBuffer()->front();
m_memory->getRingBuffer()->pop_front();
if (releaseBlock) release(releaseBlock);
}
}
return;
}
// Check is block is bypassed, if so either transmit input directly or create silence
if (m_bypass == true) {
// transmit the input directly
if (!inputAudioBlock) {
// create silence
inputAudioBlock = allocate();
if (!inputAudioBlock) { return; } // failed to allocate
else {
clearAudioBlock(inputAudioBlock);
}
}
transmit(inputAudioBlock, 0);
release(inputAudioBlock);
return;
}
// Check is block is disabled
if (m_enable == false) {
// release all held memory resources
if (m_previousBlock) {
release(m_previousBlock); m_previousBlock = nullptr;
}
if (!m_externalMemory) {
// when using internal memory we have to release all references in the ring buffer
while (m_memory->getRingBuffer()->size() > 0) {
audio_block_t *releaseBlock = m_memory->getRingBuffer()->front();
m_memory->getRingBuffer()->pop_front();
if (releaseBlock) release(releaseBlock);
}
}
return;
}
audio_block_t *inputAudioBlock = receiveReadOnly(); // get the next block of input samples
// Check is block is bypassed, if so either transmit input directly or create silence
if ((m_bypass == true) || (!inputAudioBlock)) {
// transmit the input directly
if (!inputAudioBlock) {
// create silence
inputAudioBlock = allocate();
if (!inputAudioBlock) { return; } // failed to allocate
else {
clearAudioBlock(inputAudioBlock);
}
}
transmit(inputAudioBlock, 0);
release(inputAudioBlock);
return;
}
// 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
if (!blockToOutput) {
transmit(inputAudioBlock, 0);
release(inputAudioBlock);
return; // skip this update cycle due to failure
}
// get the data. If using external memory with DMA, this won't be filled until
// later.

@ -28,17 +28,16 @@ AudioEffectTremolo::~AudioEffectTremolo()
void AudioEffectTremolo::update(void)
{
audio_block_t *inputAudioBlock = receiveWritable(); // get the next block of input samples
// Check is block is disabled
if (m_enable == false) {
// do not transmit or process any audio, return as quickly as possible.
return;
}
// Check is block is disabled
if (m_enable == false) {
// do not transmit or process any audio, return as quickly as possible.
if (inputAudioBlock) release(inputAudioBlock);
return;
}
audio_block_t *inputAudioBlock = receiveWritable(); // get the next block of input samples
// Check is block is bypassed, if so either transmit input directly or create silence
if (m_bypass == true) {
if ((m_bypass == true) || (!inputAudioBlock)) {
// transmit the input directly
if (!inputAudioBlock) {
// create silence

@ -26,18 +26,18 @@ namespace BALibrary {
BAGpio::BAGpio()
{
// Set all GPIOs to input
pinMode(static_cast<uint8_t>(GPIO::GPIO0), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO1), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO2), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO3), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO4), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO5), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO6), INPUT);
pinMode(static_cast<uint8_t>(GPIO::GPIO7), INPUT);
pinMode(static_cast<uint8_t>(GPIO::TP1), INPUT);
pinMode(static_cast<uint8_t>(GPIO::TP2), INPUT);
pinMode(GPIO0, INPUT);
pinMode(GPIO1, INPUT);
pinMode(GPIO2, INPUT);
pinMode(GPIO3, INPUT);
pinMode(GPIO4, INPUT);
pinMode(GPIO5, INPUT);
pinMode(GPIO6, INPUT);
pinMode(GPIO7, INPUT);
pinMode(TP1, INPUT);
pinMode(TP2, INPUT);
// Set the LED ot ouput
// Set the LED to ouput
pinMode(USR_LED_ID, OUTPUT);
clearLed(); // turn off the LED
@ -49,21 +49,21 @@ BAGpio::~BAGpio()
void BAGpio::setGPIODirection(GPIO gpioId, int direction)
{
pinMode(static_cast<uint8_t>(gpioId), direction);
pinMode(enumToPinNumber(gpioId), direction);
}
void BAGpio::setGPIO(GPIO gpioId)
{
digitalWrite(static_cast<uint8_t>(gpioId), 0x1);
digitalWrite(enumToPinNumber(gpioId), 0x1);
}
void BAGpio::clearGPIO(GPIO gpioId)
{
digitalWrite(static_cast<uint8_t>(gpioId), 0);
digitalWrite(enumToPinNumber(gpioId), 0);
}
int BAGpio::toggleGPIO(GPIO gpioId)
{
int data = digitalRead(static_cast<uint8_t>(gpioId));
digitalWrite(static_cast<uint8_t>(gpioId), ~data);
int data = digitalRead(enumToPinNumber(gpioId));
digitalWrite(enumToPinNumber(gpioId), ~data);
return ~data;
}
@ -84,5 +84,24 @@ int BAGpio::toggleLed()
return m_ledState;
}
uint8_t enumToPinNumber(GPIO gpio)
{
uint8_t pinNumber;
switch(gpio) {
case GPIO::GPIO0 : pinNumber = GPIO0; break;
case GPIO::GPIO1 : pinNumber = GPIO1; break;
case GPIO::GPIO2 : pinNumber = GPIO2; break;
case GPIO::GPIO3 : pinNumber = GPIO3; break;
case GPIO::GPIO4 : pinNumber = GPIO4; break;
case GPIO::GPIO5 : pinNumber = GPIO5; break;
case GPIO::GPIO6 : pinNumber = GPIO6; break;
case GPIO::GPIO7 : pinNumber = GPIO7; break;
case GPIO::TP1 : pinNumber = TP1; break;
case GPIO::TP2 : pinNumber = TP2; break;
default : pinNumber = 0; break;
}
return pinNumber;
}
} /* namespace BALibrary */

@ -319,6 +319,9 @@ void Potentiometer::setChangeThreshold(float changeThreshold)
Potentiometer::Calib Potentiometer::calibrate(uint8_t pin) {
Calib calib;
// Flush the serial port input buffer
while (Serial.available() > 0) {}
Serial.print("Calibration pin "); Serial.println(pin);
Serial.println("Move the pot fully counter-clockwise to the minimum setting and press any key then ENTER");
while (true) {

@ -24,19 +24,19 @@
namespace BALibrary {
// MEM0 Settings
constexpr int SPI_CS_MEM0 = SPI0_CS_PIN;
constexpr int SPI_MOSI_MEM0 = SPI0_MOSI_PIN;
constexpr int SPI_MISO_MEM0 = SPI0_MISO_PIN;
constexpr int SPI_SCK_MEM0 = SPI0_SCK_PIN;
#if defined(SPI1_AVAILABLE)
// MEM1 Settings
constexpr int SPI_CS_MEM1 = SPI1_CS_PIN;
constexpr int SPI_MOSI_MEM1 = SPI1_MOSI_PIN;
constexpr int SPI_MISO_MEM1 = SPI1_MISO_PIN;
constexpr int SPI_SCK_MEM1 = SPI1_SCK_PIN;
#endif
//// MEM0 Settings
//int SPI_CS_MEM0 = SPI0_CS_PIN;
//int SPI_MOSI_MEM0 = SPI0_MOSI_PIN;
//int SPI_MISO_MEM0 = SPI0_MISO_PIN;
//int SPI_SCK_MEM0 = SPI0_SCK_PIN;
//
//#if defined(SPI1_AVAILABLE)
//// MEM1 Settings
//int SPI_CS_MEM1 = SPI1_CS_PIN;
//int SPI_MOSI_MEM1 = SPI1_MOSI_PIN;
//int SPI_MISO_MEM1 = SPI1_MISO_PIN;
//int SPI_SCK_MEM1 = SPI1_SCK_PIN;
//#endif
// SPI Constants
constexpr int SPI_WRITE_MODE_REG = 0x1;
@ -73,22 +73,22 @@ void BASpiMemory::begin()
{
switch (m_memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
m_csPin = SPI_CS_MEM0;
m_csPin = SPI0_CS_PIN;
m_spi = &SPI;
m_spi->setMOSI(SPI_MOSI_MEM0);
m_spi->setMISO(SPI_MISO_MEM0);
m_spi->setSCK(SPI_SCK_MEM0);
m_spi->setMOSI(SPI0_MOSI_PIN);
m_spi->setMISO(SPI0_MISO_PIN);
m_spi->setSCK(SPI0_SCK_PIN);
m_spi->begin();
m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM0).DIE_BOUNDARY;
break;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case SpiDeviceId::SPI_DEVICE1 :
m_csPin = SPI_CS_MEM1;
m_csPin = SPI1_CS_PIN;
m_spi = &SPI1;
m_spi->setMOSI(SPI_MOSI_MEM1);
m_spi->setMISO(SPI_MISO_MEM1);
m_spi->setSCK(SPI_SCK_MEM1);
m_spi->setMOSI(SPI1_MOSI_PIN);
m_spi->setMISO(SPI1_MISO_PIN);
m_spi->setSCK(SPI1_SCK_PIN);
m_spi->begin();
m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM1).DIE_BOUNDARY;
break;
@ -367,17 +367,17 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId)
int cs;
switch (memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
cs = SPI_CS_MEM0;
cs = SPI0_CS_PIN;
m_cs = new ActiveLowChipSelect(cs, m_settings);
break;
#if defined(__MK66FX1M0__)
case SpiDeviceId::SPI_DEVICE1 :
cs = SPI_CS_MEM1;
cs = SPI1_CS_PIN;
m_cs = new ActiveLowChipSelect1(cs, m_settings);
break;
#endif
default :
cs = SPI_CS_MEM0;
cs = SPI0_CS_PIN;
}
// add 4 bytes to buffer for SPI CMD and 3 bytes of address
@ -393,17 +393,17 @@ BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz)
int cs;
switch (memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
cs = SPI_CS_MEM0;
cs = SPI0_CS_PIN;
m_cs = new ActiveLowChipSelect(cs, m_settings);
break;
#if defined(__MK66FX1M0__)
case SpiDeviceId::SPI_DEVICE1 :
cs = SPI_CS_MEM1;
cs = SPI1_CS_PIN;
m_cs = new ActiveLowChipSelect1(cs, m_settings);
break;
#endif
default :
cs = SPI_CS_MEM0;
cs = SPI0_CS_PIN;
}
m_txCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
@ -433,11 +433,11 @@ void BASpiMemoryDMA::begin(void)
{
switch (m_memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
m_csPin = SPI_CS_MEM0;
m_csPin = SPI0_CS_PIN;
m_spi = &SPI;
m_spi->setMOSI(SPI_MOSI_MEM0);
m_spi->setMISO(SPI_MISO_MEM0);
m_spi->setSCK(SPI_SCK_MEM0);
m_spi->setMOSI(SPI0_MOSI_PIN);
m_spi->setMISO(SPI0_MISO_PIN);
m_spi->setSCK(SPI0_SCK_PIN);
m_spi->begin();
m_spiDma = new DmaSpiGeneric();
m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM0).DIE_BOUNDARY;
@ -445,11 +445,11 @@ void BASpiMemoryDMA::begin(void)
#if defined(__MK66FX1M0__) // DMA on SPI1 is only supported on T3.6
case SpiDeviceId::SPI_DEVICE1 :
m_csPin = SPI_CS_MEM1;
m_csPin = SPI1_CS_PIN;
m_spi = &SPI1;
m_spi->setMOSI(SPI_MOSI_MEM1);
m_spi->setMISO(SPI_MISO_MEM1);
m_spi->setSCK(SPI_SCK_MEM1);
m_spi->setMOSI(SPI1_MOSI_PIN);
m_spi->setMISO(SPI1_MISO_PIN);
m_spi->setSCK(SPI1_SCK_PIN);
m_spi->begin();
m_spiDma = new DmaSpiGeneric(1);
m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM1).DIE_BOUNDARY;
@ -478,6 +478,8 @@ void BASpiMemoryDMA::write(size_t address, uint8_t *src, size_t numBytes)
size_t nextAddress = address;
uint8_t *intermediateBuffer = nullptr;
while ( m_txTransfer[1].busy() || m_txTransfer[0].busy()) { yield(); } // wait until not busy
// Check for intermediate buffer use
if (m_dmaCopyBufferSize) {
// copy to the intermediate buffer;
@ -487,8 +489,6 @@ void BASpiMemoryDMA::write(size_t address, uint8_t *src, size_t numBytes)
while (bytesRemaining > 0) {
m_txXferCount = m_bytesToXfer(nextAddress, min(bytesRemaining, static_cast<size_t>(MAX_DMA_XFER_SIZE))); // check for die boundary
while ( m_txTransfer[1].busy() || m_txTransfer[0].busy()) { yield(); } // 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]);
@ -559,14 +559,13 @@ void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes)
}
while (bytesRemaining > 0) {
m_rxXferCount = m_bytesToXfer(nextAddress, min(bytesRemaining, static_cast<size_t>(MAX_DMA_XFER_SIZE))); // check for die boundary
while ( m_rxTransfer[1].busy() || m_rxTransfer[0].busy()) { yield(); }
m_rxXferCount = m_bytesToXfer(nextAddress, min(bytesRemaining, static_cast<size_t>(MAX_DMA_XFER_SIZE))); // check for die boundary
m_setSpiCmdAddr(SPI_READ_CMD, nextAddress, m_rxCommandBuffer);
while ( m_rxTransfer[1].busy() || m_rxTransfer[0].busy()) { yield(); }
m_rxTransfer[1] = DmaSpi::Transfer(m_rxCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
m_spiDma->registerTransfer(m_rxTransfer[1]);
while ( m_rxTransfer[0].busy() || m_rxTransfer[1].busy()) { yield(); }
m_rxTransfer[0] = DmaSpi::Transfer(nullptr, m_rxXferCount, destPtr, 0, m_cs, TransferType::NO_START_CS, nullptr, intermediateBuffer);
m_spiDma->registerTransfer(m_rxTransfer[0]);
@ -615,7 +614,6 @@ bool BASpiMemoryDMA::setDmaCopyBufferSize(size_t numBytes)
m_dmaReadCopyBuffer = (volatile uint8_t*)dma_aligned_malloc(MEM_ALIGNED_ALLOC, numBytes);
if (!m_dmaReadCopyBuffer) {
// allocate failed
m_dmaCopyBufferSize = 0;
return false;
}

Loading…
Cancel
Save