diff --git a/src/BAAudioEffectDelayExternal.cpp b/src/BAAudioEffectDelayExternal.cpp index d637a78..a8cd3eb 100644 --- a/src/BAAudioEffectDelayExternal.cpp +++ b/src/BAAudioEffectDelayExternal.cpp @@ -22,7 +22,6 @@ namespace BAGuitar { - #define SPISETTING SPISettings(20000000, MSBFIRST, SPI_MODE0) struct MemSpiConfig { @@ -39,35 +38,47 @@ constexpr MemSpiConfig Mem1Config = {21, 5, 20, 31, 65536 }; unsigned BAAudioEffectDelayExternal::m_usingSPICount[2] = {0,0}; BAAudioEffectDelayExternal::BAAudioEffectDelayExternal() -: AudioStream(1, inputQueueArray) +: AudioStream(1, m_inputQueueArray) { initialize(MemSelect::MEM0); } BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(MemSelect mem) -: AudioStream(1, inputQueueArray) +: AudioStream(1, m_inputQueueArray) { initialize(mem); } +BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(BAGuitar::MemSelect type, float delayLengthMs) +: AudioStream(1, m_inputQueueArray) +{ + unsigned delayLengthInt = (delayLengthMs*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f; + initialize(type, delayLengthInt); +} + +BAAudioEffectDelayExternal::~BAAudioEffectDelayExternal() +{ + if (m_spi) delete m_spi; +} + void BAAudioEffectDelayExternal::delay(uint8_t channel, float milliseconds) { if (channel >= 8) return; if (milliseconds < 0.0) milliseconds = 0.0; uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f; n += AUDIO_BLOCK_SAMPLES; - if (n > memory_length - AUDIO_BLOCK_SAMPLES) - n = memory_length - AUDIO_BLOCK_SAMPLES; - delay_length[channel] = n; - uint8_t mask = activemask; - if (activemask == 0) m_startUsingSPI(m_spiChannel); - activemask = mask | (1< m_memoryLength - AUDIO_BLOCK_SAMPLES) + n = m_memoryLength - AUDIO_BLOCK_SAMPLES; + m_channelDelayLength[channel] = n; + unsigned mask = m_activeMask; + if (m_activeMask == 0) m_startUsingSPI(m_spiChannel); + m_activeMask = mask | (1<= 8) return; - uint8_t mask = activemask & ~(1<data); - head_offset += AUDIO_BLOCK_SAMPLES; + write(m_headOffset, AUDIO_BLOCK_SAMPLES, block->data); + m_headOffset += AUDIO_BLOCK_SAMPLES; } else { // write wraps across end-of-memory - n = memory_length - head_offset; - write(head_offset, n, block->data); - head_offset = AUDIO_BLOCK_SAMPLES - n; - write(0, head_offset, block->data + n); + n = m_memoryLength - m_headOffset; + write(m_headOffset, n, block->data); + m_headOffset = AUDIO_BLOCK_SAMPLES - n; + write(0, m_headOffset, block->data + n); } release(block); } else { // if no input, store zeros, so later playback will // not be random garbage previously stored in memory - if (head_offset + AUDIO_BLOCK_SAMPLES <= memory_length) { - zero(head_offset, AUDIO_BLOCK_SAMPLES); - head_offset += AUDIO_BLOCK_SAMPLES; + if (m_headOffset + AUDIO_BLOCK_SAMPLES <= m_memoryLength) { + zero(m_headOffset, AUDIO_BLOCK_SAMPLES); + m_headOffset += AUDIO_BLOCK_SAMPLES; } else { - n = memory_length - head_offset; - zero(head_offset, n); - head_offset = AUDIO_BLOCK_SAMPLES - n; - zero(0, head_offset); + n = m_memoryLength - m_headOffset; + zero(m_headOffset, n); + m_headOffset = AUDIO_BLOCK_SAMPLES - n; + zero(0, m_headOffset); } } // transmit the delayed outputs for (channel = 0; channel < 8; channel++) { - if (!(activemask & (1<data); } else { // read wraps across end-of-memory - n = memory_length - read_offset; + n = m_memoryLength - read_offset; read(read_offset, n, block->data); read(0, AUDIO_BLOCK_SAMPLES - n, block->data + n); } @@ -131,138 +142,106 @@ void BAAudioEffectDelayExternal::update(void) } } -uint32_t BAAudioEffectDelayExternal::allocated[2] = {0, 0}; +unsigned BAAudioEffectDelayExternal::m_allocated[2] = {0, 0}; -void BAAudioEffectDelayExternal::initialize(MemSelect mem) +void BAAudioEffectDelayExternal::initialize(MemSelect mem, unsigned delayLength) { - uint32_t samples = 0; - uint32_t memsize, avail; + unsigned samples = 0; + unsigned memsize, avail; - activemask = 0; - head_offset = 0; - memsize = 65536; + m_activeMask = 0; + m_headOffset = 0; m_mem = mem; switch (mem) { case MemSelect::MEM0 : { - samples = Mem0Config.memSize; + memsize = Mem0Config.memSize; + m_spi = &SPI; m_spiChannel = 0; m_misoPin = Mem0Config.misoPin; m_mosiPin = Mem0Config.mosiPin; m_sckPin = Mem0Config.sckPin; m_csPin = Mem0Config.csPin; - SPI.setMOSI(m_mosiPin); - SPI.setMISO(m_misoPin); - SPI.setSCK(m_sckPin); - SPI.begin(); + m_spi->setMOSI(m_mosiPin); + m_spi->setMISO(m_misoPin); + m_spi->setSCK(m_sckPin); + m_spi->begin(); break; } case MemSelect::MEM1 : { +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + memsize = Mem1Config.memSize; + m_spi = &SPI1; m_spiChannel = 1; - samples = Mem1Config.memSize; m_misoPin = Mem1Config.misoPin; m_mosiPin = Mem1Config.mosiPin; m_sckPin = Mem1Config.sckPin; m_csPin = Mem1Config.csPin; - SPI1.setMOSI(m_mosiPin); - SPI1.setMISO(m_misoPin); - SPI1.setSCK(m_sckPin); - SPI1.begin(); + m_spi->setMOSI(m_mosiPin); + m_spi->setMISO(m_misoPin); + m_spi->setSCK(m_sckPin); + m_spi->begin(); +#endif break; } + } pinMode(m_csPin, OUTPUT); digitalWriteFast(m_csPin, HIGH); - avail = memsize - allocated[mem]; + avail = memsize - m_allocated[mem]; - if (samples > avail) samples = avail; - memory_begin = allocated[mem]; - allocated[mem] += samples; - memory_length = samples; + if (delayLength > avail) samples = avail; + m_memoryStart = m_allocated[mem]; + m_allocated[mem] += samples; + m_memoryLength = samples; + + zero(0, m_memoryLength); - zero(0, memory_length); } void BAAudioEffectDelayExternal::read(uint32_t offset, uint32_t count, int16_t *data) { - uint32_t addr = memory_begin + offset; + uint32_t addr = m_memoryStart + offset; addr *= 2; - switch(m_mem) { - case MemSelect::MEM0 : - SPI.beginTransaction(SPISETTING); - digitalWriteFast(m_csPin, LOW); - SPI.transfer16((0x03 << 8) | (addr >> 16)); - SPI.transfer16(addr & 0xFFFF); - - while (count) { - *data++ = (int16_t)(SPI.transfer16(0)); - count--; - } - digitalWriteFast(m_csPin, HIGH); - SPI.endTransaction(); - break; - case MemSelect::MEM1 : - SPI1.beginTransaction(SPISETTING); - digitalWriteFast(m_csPin, LOW); - SPI1.transfer16((0x03 << 8) | (addr >> 16)); - SPI1.transfer16(addr & 0xFFFF); - - while (count) { - *data++ = (int16_t)(SPI1.transfer16(0)); - count--; - } - digitalWriteFast(m_csPin, HIGH); - SPI1.endTransaction(); - break; + m_spi->beginTransaction(SPISETTING); + digitalWriteFast(m_csPin, LOW); + m_spi->transfer16((0x03 << 8) | (addr >> 16)); + m_spi->transfer16(addr & 0xFFFF); + + while (count) { + *data++ = (int16_t)(m_spi->transfer16(0)); + count--; } + digitalWriteFast(m_csPin, HIGH); + m_spi->endTransaction(); } void BAAudioEffectDelayExternal::write(uint32_t offset, uint32_t count, const int16_t *data) { - uint32_t addr = memory_begin + offset; + uint32_t addr = m_memoryStart + offset; - switch(m_mem) { - case MemSelect::MEM0 : - addr *= 2; - SPI.beginTransaction(SPISETTING); - digitalWriteFast(m_csPin, LOW); - SPI.transfer16((0x02 << 8) | (addr >> 16)); - SPI.transfer16(addr & 0xFFFF); - while (count) { - int16_t w = 0; - if (data) w = *data++; - SPI.transfer16(w); - count--; - } - digitalWriteFast(m_csPin, HIGH); - SPI.endTransaction(); - break; - case MemSelect::MEM1 : - addr *= 2; - SPI1.beginTransaction(SPISETTING); - digitalWriteFast(m_csPin, LOW); - SPI1.transfer16((0x02 << 8) | (addr >> 16)); - SPI1.transfer16(addr & 0xFFFF); - while (count) { - int16_t w = 0; - if (data) w = *data++; - SPI1.transfer16(w); - count--; - } - digitalWriteFast(m_csPin, HIGH); - SPI1.endTransaction(); - break; + addr *= 2; + m_spi->beginTransaction(SPISETTING); + digitalWriteFast(m_csPin, LOW); + m_spi->transfer16((0x02 << 8) | (addr >> 16)); + m_spi->transfer16(addr & 0xFFFF); + while (count) { + int16_t w = 0; + if (data) w = *data++; + m_spi->transfer16(w); + count--; } - + digitalWriteFast(m_csPin, HIGH); + m_spi->endTransaction(); } @@ -276,9 +255,9 @@ void BAAudioEffectDelayExternal::zero(uint32_t address, uint32_t count) { #ifdef SPI_HAS_NOTUSINGINTERRUPT inline void BAAudioEffectDelayExternal::m_startUsingSPI(int spiBus) { if (spiBus == 0) { - SPI.usingInterrupt(IRQ_SOFTWARE); + m_spi->usingInterrupt(IRQ_SOFTWARE); } else if (spiBus == 1) { - SPI1.usingInterrupt(IRQ_SOFTWARE); + m_spi->usingInterrupt(IRQ_SOFTWARE); } m_usingSPICount[spiBus]++; } @@ -287,9 +266,9 @@ inline void BAAudioEffectDelayExternal::m_stopUsingSPI(int spiBus) { if (m_usingSPICount[spiBus] == 0 || --m_usingSPICount[spiBus] == 0) { if (spiBus == 0) { - SPI.notUsingInterrupt(IRQ_SOFTWARE); + m_spi->notUsingInterrupt(IRQ_SOFTWARE); } else if (spiBus == 1) { - SPI1.notUsingInterrupt(IRQ_SOFTWARE); + m_spi->notUsingInterrupt(IRQ_SOFTWARE); } } @@ -298,9 +277,9 @@ inline void BAAudioEffectDelayExternal::m_stopUsingSPI(int spiBus) { #else inline void BAAudioEffectDelayExternal::m_startUsingSPI(int spiBus) { if (spiBus == 0) { - SPI.usingInterrupt(IRQ_SOFTWARE); + m_spi->usingInterrupt(IRQ_SOFTWARE); } else if (spiBus == 1) { - SPI1.usingInterrupt(IRQ_SOFTWARE); + m_spi->usingInterrupt(IRQ_SOFTWARE); } } diff --git a/src/BAAudioEffectDelayExternal.h b/src/BAAudioEffectDelayExternal.h index d51867d..3aaae79 100644 --- a/src/BAAudioEffectDelayExternal.h +++ b/src/BAAudioEffectDelayExternal.h @@ -9,16 +9,17 @@ #define __BAGUITAR_BAAUDIOEFFECTDELAYEXTERNAL_H #include - -namespace BAGuitar { - #include "Arduino.h" #include "AudioStream.h" #include "spi_interrupt.h" -enum MemSelect { - MEM0, - MEM1, +#include "BACommon.h" + +namespace BAGuitar { + +enum MemSelect : unsigned { + MEM0 = 0, + MEM1 = 1 }; class BAAudioEffectDelayExternal : public AudioStream @@ -26,7 +27,9 @@ class BAAudioEffectDelayExternal : public AudioStream public: BAAudioEffectDelayExternal(); - BAAudioEffectDelayExternal(MemSelect type); + BAAudioEffectDelayExternal(BAGuitar::MemSelect type); + BAAudioEffectDelayExternal(BAGuitar::MemSelect type, float delayLengthMs); + virtual ~BAAudioEffectDelayExternal(); void delay(uint8_t channel, float milliseconds); void disable(uint8_t channel); @@ -35,22 +38,22 @@ public: static unsigned m_usingSPICount[2]; private: - void initialize(MemSelect mem); + void initialize(BAGuitar::MemSelect mem, unsigned delayLength = 1e6); void read(uint32_t address, uint32_t count, int16_t *data); void write(uint32_t address, uint32_t count, const int16_t *data); void zero(uint32_t address, uint32_t count); - uint32_t memory_begin; // the first address in the memory we're using - uint32_t memory_length; // the amount of memory we're using - uint32_t head_offset; // head index (incoming) data into external memory - uint32_t delay_length[8]; // # of sample delay for each channel (128 = no delay) - uint8_t activemask; // which output channels are active - //uint8_t memory_type; // 0=23LC1024, 1=Frank's Memoryboard - static uint32_t allocated[2]; - audio_block_t *inputQueueArray[1]; + unsigned m_memoryStart; // the first address in the memory we're using + unsigned m_memoryLength; // the amount of memory we're using + unsigned m_headOffset; // head index (incoming) data into external memory + unsigned m_channelDelayLength[8]; // # of sample delay for each channel (128 = no delay) + unsigned m_activeMask; // which output channels are active + static unsigned m_allocated[2]; + audio_block_t *m_inputQueueArray[1]; - MemSelect m_mem; + BAGuitar::MemSelect m_mem; + SPIClass *m_spi = nullptr; int m_spiChannel = 0; int m_misoPin = 0; int m_mosiPin = 0; diff --git a/src/BACommon.h b/src/BACommon.h new file mode 100644 index 0000000..6c8cc55 --- /dev/null +++ b/src/BACommon.h @@ -0,0 +1,17 @@ +/* + * BACommon.h + * + * Created on: Nov 19, 2017 + * Author: slascos + */ + +#ifndef SRC_BACOMMON_H_ +#define SRC_BACOMMON_H_ + +namespace BAGuitar { +constexpr int MEM0_MAX_ADDR = 131071; ///< Max address size per chip +constexpr int MEM1_MAX_ADDR = 131071; ///< Max address size per chip + +} + +#endif /* SRC_BACOMMON_H_ */ diff --git a/src/BAGuitar.h b/src/BAGuitar.h index e5dbb4f..b1c63a6 100644 --- a/src/BAGuitar.h +++ b/src/BAGuitar.h @@ -31,6 +31,7 @@ *****************************************************************************/ namespace BAGuitar { + } #endif /* SRC_BATGUITAR_H_ */ diff --git a/src/BASpiMemory.cpp b/src/BASpiMemory.cpp index 46471ab..36f9522 100644 --- a/src/BASpiMemory.cpp +++ b/src/BASpiMemory.cpp @@ -45,42 +45,40 @@ constexpr int SPI_ADDR_1_SHIFT = 8; constexpr int SPI_ADDR_0_MASK = 0x0000FF; - - BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId) { m_memDeviceId = memDeviceId; m_settings = {20000000, MSBFIRST, SPI_MODE0}; - m_Init(); } BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz) { m_memDeviceId = memDeviceId; m_settings = {speedHz, MSBFIRST, SPI_MODE0}; - m_Init(); } // Intitialize the correct Arduino SPI interface -void BASpiMemory::m_Init() +void BASpiMemory::begin() { switch (m_memDeviceId) { case SpiDeviceId::SPI_DEVICE0 : m_csPin = SPI_CS_MEM0; - SPI.setMOSI(SPI_MOSI_MEM0); - SPI.setMISO(SPI_MISO_MEM0); - SPI.setSCK(SPI_SCK_MEM0); - SPI.begin(); + m_spi = &SPI; + m_spi->setMOSI(SPI_MOSI_MEM0); + m_spi->setMISO(SPI_MISO_MEM0); + m_spi->setSCK(SPI_SCK_MEM0); + m_spi->begin(); break; #if defined(__MK64FX512__) || defined(__MK66FX1M0__) case SpiDeviceId::SPI_DEVICE1 : m_csPin = SPI_CS_MEM1; - SPI1.setMOSI(SPI_MOSI_MEM1); - SPI1.setMISO(SPI_MISO_MEM1); - SPI1.setSCK(SPI_SCK_MEM1); - SPI1.begin(); + m_spi = &SPI1; + m_spi->setMOSI(SPI_MOSI_MEM1); + m_spi->setMISO(SPI_MISO_MEM1); + m_spi->setSCK(SPI_SCK_MEM1); + m_spi->begin(); break; #endif @@ -100,104 +98,41 @@ BASpiMemory::~BASpiMemory() { // Single address write void BASpiMemory::write(int address, int data) { - switch (m_memDeviceId) { - case SpiDeviceId::SPI_DEVICE0 : - SPI.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI.transfer(SPI_WRITE_CMD); - SPI.transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT); - SPI.transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT); - SPI.transfer((address & SPI_ADDR_0_MASK)); - SPI.transfer(data); - SPI.endTransaction(); - break; - -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) - case SpiDeviceId::SPI_DEVICE1 : - SPI1.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI1.transfer(SPI_WRITE_CMD); - SPI1.transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT); - SPI1.transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT); - SPI1.transfer((address & SPI_ADDR_0_MASK)); - SPI1.transfer(data); - SPI1.endTransaction(); - break; -#endif - - default : - break; - // unreachable - } + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer(SPI_WRITE_CMD); + m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT); + m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT); + m_spi->transfer((address & SPI_ADDR_0_MASK)); + m_spi->transfer(data); + m_spi->endTransaction(); digitalWrite(m_csPin, HIGH); } void BASpiMemory::write16(int address, uint16_t data) { - switch (m_memDeviceId) { - case SpiDeviceId::SPI_DEVICE0 : - SPI.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI.transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); - SPI.transfer16(address & 0xFFFF); - SPI.transfer16(data); - SPI.endTransaction(); - break; - -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) - case SpiDeviceId::SPI_DEVICE1 : - SPI1.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI1.transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); - SPI1.transfer16(address & 0xFFFF); - SPI1.transfer16(data); - SPI1.endTransaction(); - break; -#endif - - default : - break; - // unreachable - } + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); + m_spi->transfer16(address & 0xFFFF); + m_spi->transfer16(data); + m_spi->endTransaction(); digitalWrite(m_csPin, HIGH); } // single address read int BASpiMemory::read(int address) { - - int data = -1; - - switch (m_memDeviceId) { - case SpiDeviceId::SPI_DEVICE0 : - SPI.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI.transfer(SPI_READ_CMD); - SPI.transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT); - SPI.transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT); - SPI.transfer((address & SPI_ADDR_0_MASK)); - data = SPI.transfer(0); - SPI.endTransaction(); - break; - -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) - case SpiDeviceId::SPI_DEVICE1 : - SPI1.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI1.transfer(SPI_READ_CMD); - SPI1.transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT); - SPI1.transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT); - SPI1.transfer((address & SPI_ADDR_0_MASK)); - data = SPI1.transfer(0); - SPI1.endTransaction(); - break; -#endif - - default: - break; - // unreachable - } - + int data; + + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer(SPI_READ_CMD); + m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT); + m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT); + m_spi->transfer((address & SPI_ADDR_0_MASK)); + data = m_spi->transfer(0); + m_spi->endTransaction(); digitalWrite(m_csPin, HIGH); return data; } @@ -205,33 +140,13 @@ int BASpiMemory::read(int address) uint16_t BASpiMemory::read16(int address) { - uint16_t data=0; - - switch (m_memDeviceId) { - case SpiDeviceId::SPI_DEVICE0 : - SPI.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI.transfer16((SPI_READ_CMD << 8) | (address >> 16) ); - SPI.transfer16(address & 0xFFFF); - data = SPI.transfer16(0); - SPI.endTransaction(); - break; - -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) - case SpiDeviceId::SPI_DEVICE1 : - SPI1.beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - SPI1.transfer16((SPI_READ_CMD << 8) | (address >> 16) ); - SPI1.transfer16(address & 0xFFFF); - data = SPI1.transfer16(0); - SPI1.endTransaction(); - break; -#endif - - default: - break; - // unreachable - } + uint16_t data; + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer16((SPI_READ_CMD << 8) | (address >> 16) ); + m_spi->transfer16(address & 0xFFFF); + data = m_spi->transfer16(0); + m_spi->endTransaction(); digitalWrite(m_csPin, HIGH); return data; diff --git a/src/BASpiMemory.h b/src/BASpiMemory.h index 316fbb2..e6d38f9 100644 --- a/src/BASpiMemory.h +++ b/src/BASpiMemory.h @@ -55,6 +55,8 @@ public: BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz); virtual ~BASpiMemory(); + void begin(void); + /// write a single data word to the specified address /// @param address the address in the SPI RAM to write to /// @param data the value to write @@ -69,10 +71,10 @@ public: uint16_t read16(int address); private: + SPIClass *m_spi = nullptr; SpiDeviceId m_memDeviceId; // the MEM device being control with this instance uint8_t m_csPin; // the IO pin number for the CS on the controlled SPI device SPISettings m_settings; // the Wire settings for this SPI port - void m_Init(); };