From b6a94c4bf25d4e8fd15264a86147315dad1818b2 Mon Sep 17 00:00:00 2001 From: Blackaddr Audio Date: Sun, 27 Oct 2019 16:03:17 -0400 Subject: [PATCH] Add teensy4 support (#9) * T4 SPI DMA is a work in progress * Final checkin for T4 support before hardware release --- .../BA1_TGA_Pro_NOMEM_demo.ino | 4 +- .../BA2_TGA_Pro_1MEM/BA2_TGA_Pro_1MEM.ino | 11 +- .../BA3_TGA_Pro_2MEM/BA3_TGA_Pro_2MEM.ino | 14 +- .../Delay/AnalogDelayDemo/AnalogDelayDemo.ino | 1 + .../AnalogDelayDemoExpansion.ino | 6 +- .../ExternalDelayDemo/ExternalDelayDemo.ino | 9 +- .../SoundOnSoundDemo/SoundOnSoundDemo.ino | 5 +- .../SoundOnSoundExpansionDemo.ino | 6 +- examples/Modulation/TemoloDemo/TemoloDemo.ino | 1 - .../TremoloDemoExpansion.ino | 4 +- examples/Tests/BaudrateTest/BaudrateTest.ino | 2 +- .../Tests/DMA_MEM0_test/DMA_MEM0_test.ino | 25 +- .../Tests/DMA_MEM1_test/DMA_MEM1_test.ino | 24 +- .../TGA_PRO_MEM2_EXP/PhysicalControls.cpp | 7 +- .../TGA_PRO_MEM2_EXP/TGA_PRO_MEM2_EXP.ino | 19 +- examples/Tests/TGA_PRO_MEM2_EXP/UartTest.cpp | 5 +- examples/Tests/TGA_PRO_MEM2_EXP/spiTest.cpp | 10 +- keywords.txt | 11 +- src/BAAudioControlWM8731.h | 4 + src/BAAudioEffectDelayExternal.h | 10 +- src/BAHardware.h | 263 +++++++++++++-- src/BAPhysicalControls.h | 28 +- src/BASpiMemory.h | 35 +- src/DmaSpi.h | 155 ++++++++- src/LibMemoryManagement.h | 1 + src/common/AudioDelay.cpp | 2 +- src/common/BAHardware.cpp | 99 ++++++ src/common/ExternalSramManager.cpp | 31 +- src/effects/AudioEffectDelayExternal.cpp | 73 +++-- src/peripherals/BAAudioControlWM8731.cpp | 38 ++- src/peripherals/BAPhysicalControls.cpp | 41 ++- src/peripherals/BASpiMemory.cpp | 308 ++++++++++++------ src/peripherals/DmaSpi.cpp | 4 +- 33 files changed, 960 insertions(+), 296 deletions(-) create mode 100644 src/common/BAHardware.cpp diff --git a/examples/Basic/BA1_TGA_Pro_NOMEM_demo/BA1_TGA_Pro_NOMEM_demo.ino b/examples/Basic/BA1_TGA_Pro_NOMEM_demo/BA1_TGA_Pro_NOMEM_demo.ino index 8eb459f..292c871 100644 --- a/examples/Basic/BA1_TGA_Pro_NOMEM_demo/BA1_TGA_Pro_NOMEM_demo.ino +++ b/examples/Basic/BA1_TGA_Pro_NOMEM_demo/BA1_TGA_Pro_NOMEM_demo.ino @@ -8,8 +8,6 @@ * This demo will provide an audio passthrough, as well as exercise the * MIDI interface. * - * It can optionally exercise the SPI MEM0 if installed on the TGA Pro board. - * */ #include #include @@ -37,6 +35,7 @@ void setup() { MIDI.begin(MIDI_CHANNEL_OMNI); Serial.begin(57600); delay(5); + while (!Serial) { yield(); } // If the codec was already powered up (due to reboot) power itd own first codecControl.disable(); @@ -105,4 +104,3 @@ void loop() { gpio.toggleLed(); } - diff --git a/examples/Basic/BA2_TGA_Pro_1MEM/BA2_TGA_Pro_1MEM.ino b/examples/Basic/BA2_TGA_Pro_1MEM/BA2_TGA_Pro_1MEM.ino index 44ceee4..09481d7 100644 --- a/examples/Basic/BA2_TGA_Pro_1MEM/BA2_TGA_Pro_1MEM.ino +++ b/examples/Basic/BA2_TGA_Pro_1MEM/BA2_TGA_Pro_1MEM.ino @@ -38,7 +38,7 @@ BASpiMemory spiMem0(SpiDeviceId::SPI_DEVICE0); unsigned long t=0; // SPI stuff -int spiAddress0 = 0; +unsigned spiAddress0 = 0; uint16_t spiData0 = 0xABCD; int spiErrorCount0 = 0; @@ -52,9 +52,11 @@ void setup() { MIDI.begin(MIDI_CHANNEL_OMNI); Serial.begin(57600); - while (!Serial) {} + while (!Serial) { yield(); } delay(5); + SPI_MEM0_1M(); // Set the Spi memory size to 1Mbit + // If the codec was already powered up (due to reboot) power itd own first codecControl.disable(); delay(100); @@ -98,7 +100,7 @@ void loop() { // Write test data to the SPI Memory 0 ////////////////////////////////////////////////////////////////// maskPhase = 0; - for (spiAddress0=0; spiAddress0 <= SPI_MAX_ADDR; spiAddress0=spiAddress0+2) { + for (spiAddress0=0; spiAddress0 <= BAHardwareConfig.getSpiMemMaxAddr(0); spiAddress0=spiAddress0+2) { if ((spiAddress0 % 32768) == 0) { //Serial.print("Writing to "); //Serial.println(spiAddress0, HEX); @@ -117,7 +119,7 @@ void loop() { spiAddress0 = 0; maskPhase = 0; - for (spiAddress0=0; spiAddress0 <= SPI_MAX_ADDR; spiAddress0=spiAddress0+2) { + for (spiAddress0=0; spiAddress0 <= BAHardwareConfig.getSpiMemMaxAddr(0); spiAddress0=spiAddress0+2) { if ((spiAddress0 % 32768) == 0) { // Serial.print("Reading "); // Serial.print(spiAddress0, HEX); @@ -205,4 +207,3 @@ void loop() { gpio.toggleLed(); } - diff --git a/examples/Basic/BA3_TGA_Pro_2MEM/BA3_TGA_Pro_2MEM.ino b/examples/Basic/BA3_TGA_Pro_2MEM/BA3_TGA_Pro_2MEM.ino index 1887512..5f570a7 100644 --- a/examples/Basic/BA3_TGA_Pro_2MEM/BA3_TGA_Pro_2MEM.ino +++ b/examples/Basic/BA3_TGA_Pro_2MEM/BA3_TGA_Pro_2MEM.ino @@ -57,8 +57,13 @@ void setup() { MIDI.begin(MIDI_CHANNEL_OMNI); Serial.begin(57600); + while (!Serial) { yield(); } delay(5); + // Set the SPI memory sizes + SPI_MEM0_1M(); + SPI_MEM1_1M(); + // If the codec was already powered up (due to reboot) power itd own first codecControl.disable(); delay(100); @@ -103,7 +108,7 @@ void loop() { // Write test data to the SPI Memory 0 ////////////////////////////////////////////////////////////////// maskPhase = 0; - for (spiAddress0=0; spiAddress0 <= SPI_MAX_ADDR; spiAddress0=spiAddress0+2) { + for (spiAddress0=0; spiAddress0 <= BAHardwareConfig.getSpiMemMaxAddr(0); spiAddress0=spiAddress0+2) { if ((spiAddress0 % 32768) == 0) { //Serial.print("Writing to "); //Serial.println(spiAddress0, HEX); @@ -122,7 +127,7 @@ void loop() { spiAddress0 = 0; maskPhase = 0; - for (spiAddress0=0; spiAddress0 <= SPI_MAX_ADDR; spiAddress0=spiAddress0+2) { + for (spiAddress0=0; spiAddress0 <= BAHardwareConfig.getSpiMemMaxAddr(0); spiAddress0=spiAddress0+2) { if ((spiAddress0 % 32768) == 0) { // Serial.print("Reading "); // Serial.print(spiAddress0, HEX); @@ -159,7 +164,7 @@ void loop() { // Write test data to the SPI Memory 1 ////////////////////////////////////////////////////////////////// maskPhase = 0; - for (spiAddress1=0; spiAddress1 <= SPI_MAX_ADDR; spiAddress1+=2) { + for (spiAddress1=0; spiAddress1 <= BAHardwareConfig.getSpiMemMaxAddr(1); spiAddress1+=2) { if ((spiAddress1 % 32768) == 0) { //Serial.print("Writing to "); //Serial.println(spiAddress1, HEX); @@ -178,7 +183,7 @@ void loop() { spiAddress1 = 0; maskPhase = 0; - for (spiAddress1=0; spiAddress1 <= SPI_MAX_ADDR; spiAddress1+=2) { + for (spiAddress1=0; spiAddress1 <= BAHardwareConfig.getSpiMemMaxAddr(1); spiAddress1+=2) { if ((spiAddress1 % 32768) == 0) { //Serial.print("Reading "); //Serial.print(spiAddress1, HEX); @@ -264,4 +269,3 @@ void loop() { gpio.toggleLed(); } - diff --git a/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino b/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino index f68612e..2340fb9 100644 --- a/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino +++ b/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino @@ -82,6 +82,7 @@ void setup() { // If using external memory request request memory from the manager // for the slot #ifdef USE_EXT + SPI_MEM0_1M(); Serial.println("Using EXTERNAL memory"); // We have to request memory be allocated to our slot. externalSram.requestMemory(&delaySlot, 500.0f, MemSelect::MEM0, true); diff --git a/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino b/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino index a0fd4ad..6b04677 100644 --- a/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino +++ b/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino @@ -22,9 +22,6 @@ * Using the Serial Montitor, send 'u' and 'd' characters to increase or decrease * the headphone volume between values of 0 and 9. */ -#define TGA_PRO_REVB // Set which hardware revision of the TGA Pro we're using -#define TGA_PRO_EXPAND_REV2 // pull in the pin definitions for the Blackaddr Audio Expansion Board. - #include "BALibrary.h" #include "BAEffects.h" @@ -99,6 +96,9 @@ void setup() { Serial.begin(57600); // Start the serial port delay(100); + // Configure the hardware + SPI_MEM0_1M(); + // Setup the controls. The return value is the handle to use when checking for control changes, etc. // pushbuttons bypassHandle = controls.addSwitch(BA_EXPAND_SW1_PIN); // will be used for bypass control diff --git a/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino b/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino index a6a4eac..1d4ef97 100644 --- a/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino +++ b/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino @@ -22,6 +22,7 @@ AudioInputI2S i2sIn; AudioOutputI2S i2sOut; BAAudioControlWM8731 codecControl; +//AudioEffectDelayExternal longDelay; BAAudioEffectDelayExternal longDelay(MemSelect::MEM0); // comment this line to use MEM1 //BAAudioEffectDelayExternal longDelay(MemSelect::MEM1); // and uncomment this one to use MEM1 AudioMixer4 delayOutMixerA, delayOutMixerB, delayMixer; @@ -49,12 +50,16 @@ AudioConnection outputRight(delayMixer, 0, i2sOut, 1); void setup() { Serial.begin(57600); - AudioMemory(128); + while(!Serial) { yield(); } + AudioMemory(64); - delay(100); + delay(500); Serial.println(String("Starting...\n")); delay(100); + SPI_MEM0_1M(); // set the SPI MEM0 memory size + // SPI_MEM1_1M(); // set the MEM1 memory aize + Serial.println("Enabling codec...\n"); codecControl.enable(); delay(100); diff --git a/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino b/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino index 7209d07..820642d 100644 --- a/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino +++ b/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino @@ -101,13 +101,15 @@ delay(100); AudioMemory(128); delay(5); + SPI_MEM0_1M(); // Configure the SPI memory size + // Enable the codec Serial.println("Enabling codec...\n"); codec.enable(); delay(100); // We have to request memory be allocated to our slot. - externalSram.requestMemory(&delaySlot, SPI_MEM0_SIZE_BYTES, MemSelect::MEM0, true); + externalSram.requestMemory(&delaySlot, BAHardwareConfig.getSpiMemSizeBytes(MemSelect::MEM0), MemSelect::MEM0, true); //externalSram.requestMemory(&delaySlot, 50.0f, MemSelect::MEM0, true); // Setup MIDI @@ -192,4 +194,3 @@ void loop() { // } } - diff --git a/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino b/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino index 1be4d60..f9b7e22 100644 --- a/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino +++ b/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino @@ -100,6 +100,7 @@ delay(100); delay(100); // wait a bit for serial to be available Serial.begin(57600); // Start the serial port delay(100); // wait a bit for serial to be available + BAHardwareConfig.set(MemSelect::MEM0, SPI_MEMORY_1M); // Setup the controls. The return value is the handle to use when checking for control changes, etc. // pushbuttons @@ -117,13 +118,15 @@ delay(100); codec.disable(); AudioMemory(128); + SPI_MEM0_1M(); // set the Spi memory size + // Enable the codec Serial.println("Enabling codec...\n"); codec.enable(); codec.setHeadphoneVolume(1.0f); // Max headphone volume // We have to request memory be allocated to our slot. - externalSram.requestMemory(&delaySlot, SPI_MEM0_SIZE_BYTES, MemSelect::MEM0, true); + externalSram.requestMemory(&delaySlot, BAHardwareConfig.getSpiMemSizeBytes(MemSelect::MEM0), MemSelect::MEM0, true); // Configure the LED to indicate the gate status, this is controlled directly by SOS effect, not by // by BAPhysicalControls @@ -223,4 +226,3 @@ void loop() { loopCount++; } - diff --git a/examples/Modulation/TemoloDemo/TemoloDemo.ino b/examples/Modulation/TemoloDemo/TemoloDemo.ino index d20ea2c..014ecc2 100644 --- a/examples/Modulation/TemoloDemo/TemoloDemo.ino +++ b/examples/Modulation/TemoloDemo/TemoloDemo.ino @@ -31,7 +31,6 @@ BAAudioControlWM8731 codec; // YOU MUST USE TEENSYDUINO 1.41 or greater // YOU MUST COMPILE THIS DEMO USING Serial + Midi -//#define USE_EXT // uncomment this line to use External MEM0 #define MIDI_DEBUG // uncomment to see raw MIDI info in terminal AudioEffectTremolo tremolo; diff --git a/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino b/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino index 6892fe2..fbbcc14 100644 --- a/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino +++ b/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino @@ -18,8 +18,6 @@ * Using the Serial Montitor, send 'u' and 'd' characters to increase or decrease * the headphone volume between values of 0 and 9. */ -#define TGA_PRO_REVB // Set which hardware revision of the TGA Pro we're using -#define TGA_PRO_EXPAND_REV2 // pull in the pin definitions for the Blackaddr Audio Expansion Board. #include "BALibrary.h" #include "BAEffects.h" @@ -76,6 +74,8 @@ void setup() { Serial.begin(57600); // Start the serial port delay(100); + TGA_PRO_EXPAND_REV2(); // Configure the expansion board revision + // Setup the controls. The return value is the handle to use when checking for control changes, etc. // pushbuttons bypassHandle = controls.addSwitch(BA_EXPAND_SW1_PIN); // will be used for bypass control diff --git a/examples/Tests/BaudrateTest/BaudrateTest.ino b/examples/Tests/BaudrateTest/BaudrateTest.ino index 6bf83c0..97c9a6c 100644 --- a/examples/Tests/BaudrateTest/BaudrateTest.ino +++ b/examples/Tests/BaudrateTest/BaudrateTest.ino @@ -11,7 +11,7 @@ */ constexpr unsigned LOW_RATE = 2400; constexpr unsigned MIDI_RATE = 31250; -constexpr unsigned HIGH_RATE = 250000; +constexpr unsigned HIGH_RATE = 230400; constexpr unsigned TEST_TIME = 5; // 5 second test each unsigned baudRate = LOW_RATE; // start with low speed diff --git a/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino b/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino index cedb884..10edd02 100644 --- a/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino +++ b/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino @@ -55,14 +55,18 @@ bool compareBuffers16(uint16_t *a, uint16_t *b, size_t numWords) return compareBuffers(reinterpret_cast(a), reinterpret_cast(b), sizeof(uint16_t)*numWords); } -constexpr size_t TEST_END = SPI_MAX_ADDR; +size_t SPI_MAX_ADDR; +; void setup() { Serial.begin(57600); - while (!Serial) {} + while (!Serial) { yield(); } delay(5); + SPI_MEM0_1M(); + SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(MemSelect::MEM0); + Serial.println("Enabling SPI, testing MEM0"); spiMem0.begin(); } @@ -82,7 +86,7 @@ bool spi8BitTest(void) { Serial.println("\nStarting 8-bit test Write/Read"); while (spiPhase < 4) { spiAddress = 0; - while (spiAddress < TEST_END) { + while (spiAddress <= SPI_MAX_ADDR) { // fill the write data buffer switch (spiPhase) { @@ -117,7 +121,7 @@ bool spi8BitTest(void) { // Read back the data using 8-bit transfers spiAddress = 0; - while (spiAddress < TEST_END) { + while (spiAddress <= SPI_MAX_ADDR) { // generate the golden data switch (spiPhase) { case 0 : @@ -165,7 +169,7 @@ bool spi8BitTest(void) { // Clear the memory spiAddress = 0; memset(src8, 0, DMA_SIZE); - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Send the DMA transfer spiMem0.zero(spiAddress, DMA_SIZE); // wait until write is done @@ -175,7 +179,7 @@ bool spi8BitTest(void) { // Check the memory is clear spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Read back the DMA data spiMem0.read(spiAddress, dest8, DMA_SIZE); // wait until read is done @@ -201,7 +205,7 @@ bool spi16BitTest(void) { Serial.println("\nStarting 16-bit test"); while (spiPhase < 4) { spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // fill the write data buffer switch (spiPhase) { @@ -236,7 +240,7 @@ bool spi16BitTest(void) { // Read back the data using 8-bit transfers spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // generate the golden data switch (spiPhase) { case 0 : @@ -283,7 +287,7 @@ bool spi16BitTest(void) { // Clear the memory spiAddress = 0; memset(src16, 0, DMA_SIZE); - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Send the DMA transfer spiMem0.zero16(spiAddress, NUM_DATA); // wait until write is done @@ -293,7 +297,7 @@ bool spi16BitTest(void) { // Check the memory is clear spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Read back the DMA data spiMem0.read16(spiAddress, dest16, NUM_DATA); // wait until read is done @@ -313,4 +317,3 @@ void loop() { while(true) {} } - diff --git a/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino b/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino index a895cfa..953e44a 100644 --- a/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino +++ b/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino @@ -54,14 +54,17 @@ bool compareBuffers16(uint16_t *a, uint16_t *b, size_t numWords) return compareBuffers(reinterpret_cast(a), reinterpret_cast(b), sizeof(uint16_t)*numWords); } -constexpr size_t TEST_END = SPI_MAX_ADDR; +size_t SPI_MAX_ADDR = 0; void setup() { Serial.begin(57600); - while (!Serial) {} + while (!Serial) { yield(); } delay(5); + SPI_MEM1_1M(); + SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(MemSelect::MEM1); + Serial.println("Enabling SPI, testing MEM1"); spiMem1.begin(); } @@ -81,7 +84,7 @@ bool spi8BitTest(void) { Serial.println("\nStarting 8-bit test Write/Read"); while (spiPhase < 4) { spiAddress = 0; - while (spiAddress < TEST_END) { + while (spiAddress <= SPI_MAX_ADDR) { // fill the write data buffer switch (spiPhase) { @@ -116,7 +119,7 @@ bool spi8BitTest(void) { // Read back the data using 8-bit transfers spiAddress = 0; - while (spiAddress < TEST_END) { + while (spiAddress <= SPI_MAX_ADDR) { // generate the golden data switch (spiPhase) { case 0 : @@ -164,7 +167,7 @@ bool spi8BitTest(void) { // Clear the memory spiAddress = 0; memset(src8, 0, DMA_SIZE); - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Send the DMA transfer spiMem1.zero(spiAddress, DMA_SIZE); // wait until write is done @@ -174,7 +177,7 @@ bool spi8BitTest(void) { // Check the memory is clear spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Read back the DMA data spiMem1.read(spiAddress, dest8, DMA_SIZE); // wait until read is done @@ -200,7 +203,7 @@ bool spi16BitTest(void) { Serial.println("\nStarting 16-bit test"); while (spiPhase < 4) { spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // fill the write data buffer switch (spiPhase) { @@ -235,7 +238,7 @@ bool spi16BitTest(void) { // Read back the data using 8-bit transfers spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // generate the golden data switch (spiPhase) { case 0 : @@ -282,7 +285,7 @@ bool spi16BitTest(void) { // Clear the memory spiAddress = 0; memset(src16, 0, DMA_SIZE); - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Send the DMA transfer spiMem1.zero16(spiAddress, NUM_DATA); // wait until write is done @@ -292,7 +295,7 @@ bool spi16BitTest(void) { // Check the memory is clear spiAddress = 0; - while (spiAddress < SPI_MAX_ADDR) { + while (spiAddress <= SPI_MAX_ADDR) { // Read back the DMA data spiMem1.read16(spiAddress, dest16, NUM_DATA); // wait until read is done @@ -312,4 +315,3 @@ void loop() { while(true) {} } - diff --git a/examples/Tests/TGA_PRO_MEM2_EXP/PhysicalControls.cpp b/examples/Tests/TGA_PRO_MEM2_EXP/PhysicalControls.cpp index 99fbd0c..51f4c76 100644 --- a/examples/Tests/TGA_PRO_MEM2_EXP/PhysicalControls.cpp +++ b/examples/Tests/TGA_PRO_MEM2_EXP/PhysicalControls.cpp @@ -3,8 +3,8 @@ #include "BALibrary.h" using namespace BALibrary; -constexpr int potCalibMin = 1; -constexpr int potCalibMax = 1018; +constexpr int potCalibMin = 8; +constexpr int potCalibMax = 1016; constexpr bool potSwapDirection = true; int pot1Handle, pot2Handle, pot3Handle, sw1Handle, sw2Handle, led1Handle, led2Handle; bool mute = false; @@ -51,6 +51,7 @@ void checkPot(unsigned id) if (controlPtr->checkPotValue(handle, potValue)) { // Pot has changed codecPtr->setHeadphoneVolume(potValue); + Serial.println(String("POT") + id + String(" value: ") + potValue); } } @@ -79,5 +80,3 @@ void checkSwitch(unsigned id) bool pressed = controlPtr->isSwitchHeld(swHandle); controlPtr->setOutput(ledHandle, pressed); } - - diff --git a/examples/Tests/TGA_PRO_MEM2_EXP/TGA_PRO_MEM2_EXP.ino b/examples/Tests/TGA_PRO_MEM2_EXP/TGA_PRO_MEM2_EXP.ino index aacb327..591f5ec 100644 --- a/examples/Tests/TGA_PRO_MEM2_EXP/TGA_PRO_MEM2_EXP.ino +++ b/examples/Tests/TGA_PRO_MEM2_EXP/TGA_PRO_MEM2_EXP.ino @@ -42,13 +42,11 @@ * */ -//#define RUN_MIDI_TEST // Uncomment this line to skip the MIDI test. -//#define RUN_MEMO_TEST // Uncomment this line to skip the MEM0 test. -//#define RUN_MEM1_TEST // (Teensy 3.5/3/6 only!) Comment out or delete this line to skip the MEM1 test. +#define RUN_MIDI_TEST // Uncomment this line to run the MIDI test. +#define RUN_MEMO_TEST // Uncomment this line to run the MEM0 test. +//#define RUN_MEM1_TEST // (Teensy 3.5/3/6 only!) Uncomment this line to run the MEM1 test. #include - -#define TGA_PRO_EXPAND_REV2 #include "BALibrary.h" using namespace BALibrary; @@ -67,7 +65,7 @@ BAGpio gpio; // access to User LED BASpiMemoryDMA spiMem0(SpiDeviceId::SPI_DEVICE0); #endif -#if defined(RUN_MEM1_TEST) +#if defined(RUN_MEM1_TEST) && !defined(__IMXRT1062__) // SPI1 not supported on T4.0 BASpiMemoryDMA spiMem1(SpiDeviceId::SPI_DEVICE1); #endif @@ -78,13 +76,14 @@ BAPhysicalControls controls(BA_EXPAND_NUM_SW, BA_EXPAND_NUM_POT, BA_EXPAND_NUM_E void configPhysicalControls(BAPhysicalControls &controls, BAAudioControlWM8731 &codec); void checkPot(unsigned id); void checkSwitch(unsigned id); -bool spiTest(BASpiMemoryDMA *mem); // returns true if passed +bool spiTest(BASpiMemory *mem); // returns true if passed bool uartTest(); // returns true if passed unsigned loopCounter = 0; void setup() { Serial.begin(57600); + while (!Serial) { yield(); } delay(500); // Disable the audio codec first @@ -101,11 +100,13 @@ void setup() { #endif #if defined(RUN_MEMO_TEST) + SPI_MEM0_1M(); spiMem0.begin(); delay(10); if (spiTest(&spiMem0)) { Serial.println("SPI0 testing PASSED!");} #endif -#if defined(RUN_MEM1_TEST) +#if defined(RUN_MEM1_TEST) && !defined(__IMXRT1062__) + SPI_MEM1_1M(); spiMem1.begin(); delay(10); if (spiTest(&spiMem1)) { Serial.println("SPI1 testing PASSED!");} #endif @@ -121,7 +122,7 @@ void loop() { checkSwitch(0); checkSwitch(1); - delay(10); + delay(20); loopCounter++; if ((loopCounter % 100) == 0) { gpio.toggleLed(); diff --git a/examples/Tests/TGA_PRO_MEM2_EXP/UartTest.cpp b/examples/Tests/TGA_PRO_MEM2_EXP/UartTest.cpp index 0e2602e..3ae3953 100644 --- a/examples/Tests/TGA_PRO_MEM2_EXP/UartTest.cpp +++ b/examples/Tests/TGA_PRO_MEM2_EXP/UartTest.cpp @@ -4,7 +4,7 @@ using namespace BALibrary; constexpr unsigned MIDI_RATE = 31250; -constexpr unsigned HIGH_RATE = 250000; +constexpr unsigned HIGH_RATE = 230400; constexpr unsigned TEST_TIME = 5; // 5 second test each static unsigned baudRate = MIDI_RATE; // start with low speed @@ -58,7 +58,7 @@ bool uartTest(void) if (Serial1.available()) { uint8_t readData= Serial1.read(); if (readData != writeData) { - Serial.println(String("ERROR: readData = ") + readData + String(" writeData = ") + writeData); + Serial.println(String("MIDI ERROR: readData = ") + readData + String(" writeData = ") + writeData); errorCount++; } @@ -79,4 +79,3 @@ bool uartTest(void) return testFailed; } - diff --git a/examples/Tests/TGA_PRO_MEM2_EXP/spiTest.cpp b/examples/Tests/TGA_PRO_MEM2_EXP/spiTest.cpp index fce9b22..25ba45b 100644 --- a/examples/Tests/TGA_PRO_MEM2_EXP/spiTest.cpp +++ b/examples/Tests/TGA_PRO_MEM2_EXP/spiTest.cpp @@ -12,6 +12,8 @@ constexpr int mask1 = 0xaaaa; using namespace BALibrary; +size_t SPI_MAX_ADDR = 0; + int calcData(int spiAddress, int loopPhase, int maskPhase) { int data; @@ -35,7 +37,7 @@ int calcData(int spiAddress, int loopPhase, int maskPhase) return (data & 0xffff); } -bool spiTest(BASpiMemoryDMA *mem) +bool spiTest(BASpiMemory *mem) { int spiAddress = 0; int spiErrorCount = 0; @@ -45,7 +47,10 @@ bool spiTest(BASpiMemoryDMA *mem) uint16_t memBlock[NUM_BLOCK_WORDS]; uint16_t goldData[NUM_BLOCK_WORDS]; - Serial.println("Starting SPI MEM Test"); + SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(0); // assume for this test both memories are the same size so use MEM0 + const size_t SPI_MEM0_SIZE_BYTES = BAHardwareConfig.getSpiMemSizeBytes(0); + + Serial.println(String("Starting SPI MEM Test of ") + SPI_MEM0_SIZE_BYTES + String(" bytes")); for (int cnt = 0; cnt < NUM_TESTS; cnt++) { @@ -122,4 +127,3 @@ bool spiTest(BASpiMemoryDMA *mem) } return true; } - diff --git a/keywords.txt b/keywords.txt index bac835a..02b9b41 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,5 +1,5 @@ ####################################### -# Syntax Coloring Map For ExampleLibrary +# Syntax Coloring Map For BALibrary ####################################### ####################################### @@ -15,11 +15,18 @@ BAAudioEffectDelayExternal KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### -doSomething KEYWORD2 +TGA_PRO_REVA KEYWORD2 +TGA_PRO_REVB KEYWORD2 +TGA_PRO_EXPAND_REV2 KEYWORD2 +SPI_MEM0_1M KEYWORD2 +SPI_MEM0_4M KEYWORD2 +SPI_MEM1_1M KEYWORD2 +SPI_MEM1_4M KEYWORD2 ####################################### # Instances (KEYWORD2) ####################################### +BAHardwareConfig KEYWORD1 ####################################### # Constants (LITERAL1) diff --git a/src/BAAudioControlWM8731.h b/src/BAAudioControlWM8731.h index f0e5d6c..c284e22 100644 --- a/src/BAAudioControlWM8731.h +++ b/src/BAAudioControlWM8731.h @@ -123,9 +123,13 @@ protected: private: // low-level write command bool write(unsigned int reg, unsigned int val); + // resets the internal shadow register array void resetInternalReg(void); + // Sets pullups, slew rate and drive strength + void setOutputStrength(void); + bool m_wireStarted = false; }; diff --git a/src/BAAudioEffectDelayExternal.h b/src/BAAudioEffectDelayExternal.h index 9e88b21..574873f 100644 --- a/src/BAAudioEffectDelayExternal.h +++ b/src/BAAudioEffectDelayExternal.h @@ -45,12 +45,12 @@ public: /// Specifiy which external memory to use /// @param type specify which memory to use - BAAudioEffectDelayExternal(BALibrary::MemSelect type); + BAAudioEffectDelayExternal(BALibrary::MemSelect mem); /// Specify external memory, and how much of the memory to use /// @param type specify which memory to use /// @param delayLengthMs maximum delay length in milliseconds - BAAudioEffectDelayExternal(BALibrary::MemSelect type, float delayLengthMs); + BAAudioEffectDelayExternal(BALibrary::MemSelect mem, float delayLengthMs); virtual ~BAAudioEffectDelayExternal(); /// set the actual amount of delay on a given delay tap @@ -67,7 +67,10 @@ public: static unsigned m_usingSPICount[2]; // internal use for all instances private: - void initialize(BALibrary::MemSelect mem, unsigned delayLength = 1e6); + bool m_configured = false; + unsigned m_requestedDelayLength = 1e6; + BALibrary::MemSelect m_mem = BALibrary::MemSelect::MEM0; + void initialize(void); 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); @@ -79,7 +82,6 @@ private: static unsigned m_allocated[2]; audio_block_t *m_inputQueueArray[1]; - BALibrary::MemSelect m_mem; SPIClass *m_spi = nullptr; int m_spiChannel = 0; int m_misoPin = 0; diff --git a/src/BAHardware.h b/src/BAHardware.h index 68e77db..f11d691 100644 --- a/src/BAHardware.h +++ b/src/BAHardware.h @@ -32,19 +32,164 @@ *****************************************************************************/ namespace BALibrary { -// uncomment the line that corresponds to your hardware -//#define TGA_PRO_REVA -#if (!defined(TGA_PRO_REVA) && !defined(TGA_PRO_REVB)) -#define TGA_PRO_REVA -#endif +// In your Arudino .ino file, use #defines for your TGA Pro revision and options +// to correctly configure your hardware +#define TGA_PRO_REVA(x) BALibrary::BAHardwareConfig.m_tgaBoard = TgaBoard::REV_A ///< Macro for specifying REV A of the TGA Pro +#define TGA_PRO_REVB(x) BALibrary::BAHardwareConfig.m_tgaBoard = TgaBoard::REV_B ///< Macro for specifying REV B of the TGA Pro +#define TGA_PRO_EXPAND_REV2(x) BALibrary::BAHardwareConfig.m_expansionBoard = ExpansionBoard::REV_1 ///< Macro for specifying REV 1 of the Expansion Board +#define SPI_MEM0_1M(x) BALibrary::BAHardwareConfig.m_spiMem0 = SPI_MEMORY_1M ///< Macro for specifying MEM0 is 1Mbit +#define SPI_MEM0_4M(x) BALibrary::BAHardwareConfig.m_spiMem0 = SPI_MEMORY_4M ///< Macro for specifying MEM1 is 4Mbit +#define SPI_MEM1_1M(x) BALibrary::BAHardwareConfig.m_spiMem1 = SPI_MEMORY_1M ///< Macro for specifying MEM0 is 1Mbit +#define SPI_MEM1_4M(x) BALibrary::BAHardwareConfig.m_spiMem1 = SPI_MEMORY_4M ///< Macro for specifying MEM1 is 1Mbit -#if defined(TGA_PRO_REVA) || defined(TGA_PRO_REVB) +/****************************************************************************** + * Hardware Configuration + *****************************************************************************/ +/// enum to specify the TGA Board revision +enum class TgaBoard : unsigned { + REV_A = 0, ///< indicates using REV A of the TGA Pro + REV_B ///< indicates using REV B of the TGA Pro +}; -constexpr uint8_t USR_LED_ID = 16; ///< Teensy IO number for the user LED. +/// enum to specify the TGA Pro Expansion Board revision +enum class ExpansionBoard : unsigned { + NO_EXPANSION = 0, ///< default, indicates no expansion board is present + REV_1, ///< indicates using REV 1 of the Expansion Board + REV_2 ///< indicates using REV 2 of the Expansion Board +}; + +/// enum to specify SPI memory dize +enum class SpiMemorySize : unsigned { + NO_MEMORY = 0, ///< default, indicates no SPI memory installed + MEM_1M, ///< indicates 1Mbit memory is installed + MEM_4M ///< indicates 4Mbit memory is installed +}; + +constexpr unsigned NUM_MEM_SLOTS = 2; ///< The TGA Pro has two SPI ports for memory +/// enum to specify MEM0 or MEM1 +enum MemSelect : unsigned { + MEM0 = 0, ///< SPI RAM MEM0 + MEM1 = 1 ///< SPI RAM MEM1 +}; + +/****************************************************************************** + * SPI Memory Definitions + *****************************************************************************/ +/// stores Spi memory size information +struct SpiMemoryDefinition { + size_t MEM_SIZE_BYTES; + size_t DIE_BOUNDARY; +}; + +/// Settings for 4Mbit SPI MEM +constexpr SpiMemoryDefinition SPI_MEMORY_4M = { + .MEM_SIZE_BYTES = 524288, + .DIE_BOUNDARY = 262144 +}; + +/// Settings for 1Mbit SPI MEM +constexpr SpiMemoryDefinition SPI_MEMORY_1M = { + .MEM_SIZE_BYTES = 131072, + .DIE_BOUNDARY = 0 +}; + +/// Settings for No memory +constexpr SpiMemoryDefinition SPI_MEMORY_NONE = { + .MEM_SIZE_BYTES = 0, + .DIE_BOUNDARY = 0 +}; + +/****************************************************************************** + * General Purpose SPI Interfaces + *****************************************************************************/ +/// enum to specify which SPI port is being used +enum class SpiDeviceId : unsigned { + SPI_DEVICE0 = 0, ///< Arduino SPI device + SPI_DEVICE1 = 1 ///< Arduino SPI1 device +}; /**************************************************************************//** - * GPIOs and Testpoints are accessed via enumerated class constants. + * BAHardware is a global object that holds hardware configuration options for + * board revisions and ordering options. It is created automatically, and only + * one is present. For configuration, the MACROS specified at the top of + * BAHardware.h should be used. *****************************************************************************/ +class BAHardware { +public: + BAHardware() = default; ///< default constructor + + /// sets the TGA Pro board revision + /// @param tgaBoard enum to specify board revision + void set(TgaBoard tgaBoard); + + /// get the configured TGA Pro board revision + /// @returns enum for the board revision + TgaBoard getTgaBoard(void); + + /// sets the Expansion board revision + /// @param expansionBoard enum to specify the expansion board revision + void set(ExpansionBoard expansionBoard); + + /// get the configured Expansion Board revision + /// @returns enum for the board revision + ExpansionBoard getExpansionBoard(void); + + /// sets the configured size of a SPI memory + /// @param memSelect specifies which memory device you are configuring + /// @param spiMem specifies the memory definition provide (Size, etc.) + void set(MemSelect memSelect, SpiMemoryDefinition spiMem); + + /// gets the memory definition for a given memory device + /// @param mem enum to specify memory device to query + SpiMemoryDefinition getSpiMemoryDefinition(MemSelect mem); + + /// get the size of the given memory in bytes, defaults to MEM0 + /// @param memSelect enum specifies the memory to query + /// @returns size in bytes + size_t getSpiMemSizeBytes(MemSelect memSelect = MemSelect::MEM0); + + /// get the size of the given memory in bytes, defaults to MEM0 + /// @param memIndex unsigned specifies the memory to query + /// @returns size in bytes + size_t getSpiMemSizeBytes(unsigned memIndex); + + /// get the maximum address in a given memory, defaults to MEM0 + /// @param memSelect enum specifies the memory to query + /// @returns the last valid address location in the memory + size_t getSpiMemMaxAddr (MemSelect memSelect = MemSelect::MEM0); + + /// get the maximum address in a given memory, defaults to MEM0 + /// @param memIndex unsigned specifies the memory to query + /// @returns the last valid address location in the memory + size_t getSpiMemMaxAddr (unsigned memIndex); + + TgaBoard m_tgaBoard = TgaBoard::REV_B; ///< stores the configured TGA Pro revision + ExpansionBoard m_expansionBoard = ExpansionBoard::NO_EXPANSION; ///< stores the configured Expansion Board revision + SpiMemoryDefinition m_spiMem0 = SPI_MEMORY_NONE; ///< stores the definition for MEM0 + SpiMemoryDefinition m_spiMem1 = SPI_MEMORY_NONE; ///< stores the definition for MEM1 +}; + +extern BAHardware BAHardwareConfig; ///< external definition of global configuration class object + +/**************************************************************************//** + * Teensy 3.6/3.5 Hardware Pinout + *****************************************************************************/ +#if defined(__MK66FX1M0__) || defined(__MK64FX512__) // T3.6 or T3.5 +constexpr uint8_t USR_LED_ID = 16; ///< Teensy IO number for the user LED. + +// SPI0 and SPI1 pinouts +constexpr uint8_t SPI0_SCK_PIN = 14; +constexpr uint8_t SPI0_CS_PIN = 15; +constexpr uint8_t SPI0_MISO_PIN = 8; +constexpr uint8_t SPI0_MOSI_PIN = 7; + +#define SPI1_AVAILABLE +constexpr uint8_t SPI1_SCK_PIN = 20; +constexpr uint8_t SPI1_CS_PIN = 31; +constexpr uint8_t SPI1_MISO_PIN = 5; +constexpr uint8_t SPI1_MOSI_PIN = 21; + +// GPIOs and Testpoints are accessed via enumerated class constants. enum class GPIO : uint8_t { GPIO0 = 2, GPIO1 = 3, @@ -61,46 +206,77 @@ enum class GPIO : uint8_t { }; /**************************************************************************//** - * Optionally installed SPI RAM + * Teensy 4.0 Hardware Settings *****************************************************************************/ -constexpr unsigned NUM_MEM_SLOTS = 2; -enum MemSelect : unsigned { - MEM0 = 0, ///< SPI RAM MEM0 - MEM1 = 1 ///< SPI RAM MEM1 -}; +#elif defined(__IMXRT1062__) // T4.0 +constexpr uint8_t USR_LED_ID = 2; ///< Teensy IO number for the user LED. -/**************************************************************************//** - * Set the maximum address (byte-based) in the external SPI memories - *****************************************************************************/ -constexpr size_t MEM_MAX_ADDR[NUM_MEM_SLOTS] = { 131071, 131071 }; +// SPI0 pinouts +constexpr uint8_t SPI0_SCK_PIN = 13; +constexpr uint8_t SPI0_CS_PIN = 10; +constexpr uint8_t SPI0_MISO_PIN = 12; +constexpr uint8_t SPI0_MOSI_PIN = 11; +// GPIOs and Testpoints are accessed via enumerated class constants. +enum class GPIO : uint8_t { + GPIO0 = 3, + GPIO1 = 4, + GPIO2 = 5, + GPIO3 = 6, -/**************************************************************************//** - * General Purpose SPI Interfaces - *****************************************************************************/ -enum class SpiDeviceId : unsigned { - SPI_DEVICE0 = 0, ///< Arduino SPI device - SPI_DEVICE1 = 1 ///< Arduino SPI1 device -}; -constexpr int SPI_MAX_ADDR = 131071; ///< Max address size per chip -constexpr size_t SPI_MEM0_SIZE_BYTES = 131072; -constexpr size_t SPI_MEM0_MAX_AUDIO_SAMPLES = SPI_MEM0_SIZE_BYTES/sizeof(int16_t); + GPIO4 = 17, + GPIO5 = 16, + GPIO6 = 15, + GPIO7 = 14, -constexpr size_t SPI_MEM1_SIZE_BYTES = 131072; -constexpr size_t SPI_MEM1_MAX_AUDIO_SAMPLES = SPI_MEM1_SIZE_BYTES/sizeof(int16_t); + TP1 = 9, + TP2 = 22 +}; +#define SCL_PAD_CTRL IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_00 +#define SDA_PAD_CTRL IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_01 +constexpr uint32_t SCL_SDA_PAD_CFG = 0xF808; +#define MCLK_PAD_CTRL IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09 +#define BCLK_PAD_CTRL IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_10 +#define LRCLK_PAD_CTRL IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_11 +#define DAC_PAD_CTRL IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_01 +constexpr uint32_t I2S_PAD_CFG = 0x0008; +/**************************************************************************//** + * DEFAULT Teensy 3.2 Hardware Settings + *****************************************************************************/ #else +constexpr uint8_t USR_LED_ID = 16; ///< Teensy IO number for the user LED. -#error "No hardware declared" +// SPI0 and SPI1 pinouts +constexpr uint8_t SPI0_SCK_PIN = 14; +constexpr uint8_t SPI0_CS_PIN = 15; +constexpr uint8_t SPI0_MISO_PIN = 8; +constexpr uint8_t SPI0_MOSI_PIN = 7; + +// GPIOs and Testpoints are accessed via enumerated class constants. +enum class GPIO : uint8_t { + GPIO0 = 2, + GPIO1 = 3, + GPIO2 = 4, + GPIO3 = 6, + GPIO4 = 12, + GPIO5 = 32, + GPIO6 = 27, + GPIO7 = 28, + + TP1 = 34, + TP2 = 33 +}; #endif -#if defined (TGA_PRO_EXPAND_REV2) /**************************************************************************//** - * Blackaddr Audio Expansion Board + * Blackaddr Audio Expansion Board Pin Configuration *****************************************************************************/ +#if defined(__MK66FX1M0__) || defined(__MK64FX512__) // T3.6 or T3.5 +// Teensy 3.6 Pinout constexpr unsigned BA_EXPAND_NUM_POT = 3; constexpr unsigned BA_EXPAND_NUM_SW = 2; constexpr unsigned BA_EXPAND_NUM_LED = 2; @@ -113,9 +289,28 @@ constexpr uint8_t BA_EXPAND_SW1_PIN = 2; // 2)PWM constexpr uint8_t BA_EXPAND_SW2_PIN = 3; // 3_SCL2_PWM constexpr uint8_t BA_EXPAND_LED1_PIN = 4; // 4_SDA2_PWM constexpr uint8_t BA_EXPAND_LED2_PIN = 6; // 6_PWM + +#elif defined(__IMXRT1062__) +// Teensy 4.0 pinout +constexpr unsigned BA_EXPAND_NUM_POT = 3; +constexpr unsigned BA_EXPAND_NUM_SW = 2; +constexpr unsigned BA_EXPAND_NUM_LED = 2; +constexpr unsigned BA_EXPAND_NUM_ENC = 0; + +constexpr uint8_t BA_EXPAND_POT1_PIN = A0; // 14_A0_TX3_SPDIFOUT +constexpr uint8_t BA_EXPAND_POT2_PIN = A1; // 15_A1_RX3_SPDIFIN +constexpr uint8_t BA_EXPAND_POT3_PIN = A2; // 16_A2_RX4_SCL1 +constexpr uint8_t BA_EXPAND_SW1_PIN = 3; // 3_LRCLK2 +constexpr uint8_t BA_EXPAND_SW2_PIN = 4; // 4_BCLK2 +constexpr uint8_t BA_EXPAND_LED1_PIN = 5; // 5_IN2 +constexpr uint8_t BA_EXPAND_LED2_PIN = 6; // 6_OUT1D + +#else + +#warning Your processor is not yet supported in BALibrary + #endif } // namespace BALibrary - #endif /* __BALIBRARY_BAHARDWARE_H */ diff --git a/src/BAPhysicalControls.h b/src/BAPhysicalControls.h index 859d698..eb0201b 100644 --- a/src/BAPhysicalControls.h +++ b/src/BAPhysicalControls.h @@ -26,6 +26,8 @@ #include #include +#include "Arduino.h" + namespace BALibrary { constexpr bool SWAP_DIRECTION = true; ///< Use when specifying direction should be swapped @@ -132,12 +134,27 @@ public: void adjustCalibrationThreshold(float thresholdFactor); /// Set the amount of feedback in the IIR filter used to smooth the pot readings - /// @details actual filter reponse deptnds on the rate you call getValue() + /// @details actual filter response depends on the rate you call getValue() /// @param filterValue typical values are 0.80f to 0.95f void setFeedbackFitlerValue(float fitlerValue); + /// Set the calibration values for the pots + /// @param min analog pot reading for min value + /// @param max analog pot reading for max value + /// @param swapDirection when true min and max are reversed. (Depends on physical pot orientation) void setCalibrationValues(unsigned min, unsigned max, bool swapDirection); + /// Sets a MINIMUM sampling interval for the pot in milliseconds. + /// @details When making a call to getValue(), if the time since the last reading is + /// less than this interval, a new reading will not be taken. + /// @param intervalMs the desired minimum sampling interval in milliseconds + void setSamplingIntervalMs(unsigned intervalMs); + + /// Sets the minimum change between previous reading and new reading to be considered valid. + /// @details Increasing this value will help remove noise. Default is 8. + /// @param changeThreshold new change threshold for ADC + void setChangeThreshold(float changeThreshold); + /// Call this static function before creating the object to obtain calibration data. The sequence /// involves prompts over the Serial port. /// @details E.g. call Potentiometer::calibrate(PIN). See BAExpansionCalibrate.ino in the library examples. @@ -151,11 +168,16 @@ private: unsigned m_minCalibration; ///< stores the min pot value unsigned m_maxCalibration; ///< stores the max pot value unsigned m_lastValue = 0; ///< stores previous value - float m_feedbackFitlerValue = 0.9f; ///< feedback value for POT filter + float m_feedbackFitlerValue = 0.8f; ///< feedback value for POT filter float m_thresholdFactor = 0.05f; ///< threshold factor causes values pot to saturate faster at the limits, default is 5% unsigned m_minCalibrationThresholded; ///< stores the min pot value after thresholding unsigned m_maxCalibrationThresholded; ///< stores the max pot value after thresholding unsigned m_rangeThresholded; ///< stores the range of max - min after thresholding + + unsigned m_changeThreshold = 8; ///< a new reading must change by this amount to be valid + unsigned m_lastValidValue = 0; ///< stores previous value + unsigned m_samplingIntervalMs = 20; ///< the sampling interval in milliseconds + elapsedMillis m_timerMs; ///< special Teensy variable that tracks time }; /// Convenience class for rotary (quadrature) encoders. Uses Arduino Encoder under the hood. @@ -306,8 +328,6 @@ private: std::vector m_outputs; ///< a vector of all added outputs }; - } // BALibrary - #endif /* __BAPHYSICALCONTROLS_H */ diff --git a/src/BASpiMemory.h b/src/BASpiMemory.h index 92e83fc..f4f5950 100644 --- a/src/BASpiMemory.h +++ b/src/BASpiMemory.h @@ -23,6 +23,7 @@ #ifndef __BALIBRARY_BASPIMEMORY_H #define __BALIBRARY_BASPIMEMORY_H +#include #include #include @@ -33,7 +34,7 @@ namespace BALibrary { /**************************************************************************//** * This wrapper class uses the Arduino SPI (Wire) library to access the SPI ram. - * @details The purpose of this class is primilary for functional testing since + * @details The purpose of this class is primarily for functional testing since * it currently support single-word access. High performance access should be * done using DMA techniques in the Teensy library. *****************************************************************************/ @@ -43,7 +44,7 @@ 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. - BASpiMemory(SpiDeviceId memDeviceId); + BASpiMemory(SpiDeviceId memDeviceId = SpiDeviceId::SPI_DEVICE0); /// 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. @@ -111,16 +112,39 @@ public: /// @returns true if initialized, false if not yet initialized bool isStarted() const { return m_started; } + /// Dummy function for non-DMA writes + virtual bool isWriteBusy() const { return false; } + + /// Dummy function for non-DMA reads + virtual bool isReadBusy() const { return false; } + protected: 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 bool m_started = false; + size_t m_dieBoundary; // the address at which a SPI memory die rollsover + + size_t m_bytesToXfer(size_t address, size_t numBytes); + void m_rawWrite (size_t address, uint8_t *src, size_t numBytes); // raw function for writing bytes + void m_rawZero (size_t address, size_t numBytes); // raw function for zeroing memory + void m_rawRead (size_t address, uint8_t *dest, size_t numBytes); // raw function for reading bytes + void m_rawWrite16(size_t address, uint16_t *src, size_t numBytes); // raw function for writing words + void m_rawZero16 (size_t address, size_t numBytes); // raw function for zeroing memory words + void m_rawRead16 (size_t address, uint16_t *dest, size_t numBytes); // raw function for reading words }; +#if defined (__IMXRT1062__) +//#if 0 +using BASpiMemoryDMA = BASpiMemory; +#else +/**************************************************************************//** + * This wrapper class uses the Arduino SPI (Wire) library to access the SPI ram + * via DMA. + *****************************************************************************/ class BASpiMemoryDMA : public BASpiMemory { public: BASpiMemoryDMA() = delete; @@ -181,11 +205,11 @@ public: /// Check if a DMA write is in progress /// @returns true if a write DMA is in progress, else false - bool isWriteBusy() const; + bool isWriteBusy() const override; /// Check if a DMA read is in progress /// @returns true if a read DMA is in progress, else false - bool isReadBusy() const; + bool isReadBusy() const override; /// Readout the 8-bit contents of the DMA storage buffer to the specified destination /// @param dest pointer to the destination @@ -212,8 +236,9 @@ private: uint16_t m_txXferCount; uint16_t m_rxXferCount; - void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest); + void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest); }; +#endif // BASpiMemoryDMA declaration } /* namespace BALibrary */ diff --git a/src/DmaSpi.h b/src/DmaSpi.h index 9f57c25..00edcfa 100644 --- a/src/DmaSpi.h +++ b/src/DmaSpi.h @@ -12,6 +12,11 @@ #include "DMAChannel.h" #include +//#include +#include + +//#define DEBUG_DMASPI 1 + /** \brief Specifies the desired CS suppression **/ @@ -152,7 +157,6 @@ class ActiveLowChipSelect1 : public AbstractChipSelect #endif -//#define DEBUG_DMASPI 1 #if defined(DEBUG_DMASPI) #define DMASPI_PRINT(x) do {Serial.printf x ; Serial.flush();} while (0); @@ -488,8 +492,10 @@ class AbstractDmaSpi static void post_finishCurrentTransfer() {DMASPI_INSTANCE::post_finishCurrentTransfer_impl();} + // finishCurrentTransfer is called from rxISR_() static void finishCurrentTransfer() { + DMASPI_PRINT((" inside finishCurrentTransfer()\n")); if (m_pCurrentTransfer->m_pSelect != nullptr) { m_pCurrentTransfer->m_pSelect->deselect(m_pCurrentTransfer->m_transferType); @@ -581,12 +587,12 @@ class AbstractDmaSpi { if (m_pNextTransfer == nullptr) { - DMASPI_PRINT(("DmaSpi::beginNextTransfer: no pending transfer\n")); + DMASPI_PRINT(("DmaSpi::beginPendingTransfer: no pending transfer\n")); return; } m_pCurrentTransfer = m_pNextTransfer; - DMASPI_PRINT(("DmaSpi::beginNextTransfer: starting transfer @ %p\n", m_pCurrentTransfer)); + DMASPI_PRINT(("DmaSpi::beginPendingTransfer: starting transfer @ %p\n", m_pCurrentTransfer)); m_pCurrentTransfer->m_state = Transfer::State::inProgress; m_pNextTransfer = m_pNextTransfer->m_pNext; if (m_pNextTransfer == nullptr) @@ -600,6 +606,7 @@ class AbstractDmaSpi { // real data sink DMASPI_PRINT((" real sink\n")); + arm_dcache_flush_delete((void *)m_pCurrentTransfer->m_pDest, m_pCurrentTransfer->m_transferCount); rxChannel_()->destinationBuffer(m_pCurrentTransfer->m_pDest, m_pCurrentTransfer->m_transferCount); } @@ -616,6 +623,7 @@ class AbstractDmaSpi { // real data source DMASPI_PRINT((" real source\n")); + arm_dcache_flush_delete((void *)m_pCurrentTransfer->m_pSource, m_pCurrentTransfer->m_transferCount); txChannel_()->sourceBuffer(m_pCurrentTransfer->m_pSource, m_pCurrentTransfer->m_transferCount); } @@ -627,6 +635,7 @@ class AbstractDmaSpi txChannel_()->transferCount(m_pCurrentTransfer->m_transferCount); } + DMASPI_PRINT(("calling pre_cs() ")); pre_cs(); // Select Chip @@ -639,6 +648,7 @@ class AbstractDmaSpi m_Spi.beginTransaction(SPISettings()); } + DMASPI_PRINT(("calling post_cs() ")); post_cs(); } @@ -669,7 +679,17 @@ typename AbstractDmaSpi::Transfer* volatile Ab template volatile uint8_t AbstractDmaSpi::m_devNull = 0; -#if defined(KINETISK) +//void dump_dma(DMAChannel *dmabc) +//{ +// Serial.printf("%x %x:", (uint32_t)dmabc, (uint32_t)dmabc->TCD); +// +// Serial.printf("SA:%x SO:%d AT:%x NB:%x SL:%d DA:%x DO: %d CI:%x DL:%x CS:%x BI:%x\n", (uint32_t)dmabc->TCD->SADDR, +// dmabc->TCD->SOFF, dmabc->TCD->ATTR, dmabc->TCD->NBYTES, dmabc->TCD->SLAST, (uint32_t)dmabc->TCD->DADDR, +// dmabc->TCD->DOFF, dmabc->TCD->CITER, dmabc->TCD->DLASTSGA, dmabc->TCD->CSR, dmabc->TCD->BITER); +// Serial.flush(); +//} + +#if defined(__IMXRT1062__) // T4.0 class DmaSpi0 : public AbstractDmaSpi { @@ -677,24 +697,136 @@ public: static void begin_setup_txChannel_impl() { txChannel_()->disable(); - txChannel_()->destination((volatile uint8_t&)SPI0_PUSHR); + txChannel_()->destination((volatile uint8_t&)IMXRT_LPSPI4_S.TDR); txChannel_()->disableOnCompletion(); - txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX); + txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI4_TX); + //txChannel_()->triggerAtTransfersOf(*rxChannel_); } static void begin_setup_rxChannel_impl() { rxChannel_()->disable(); - rxChannel_()->source((volatile uint8_t&)SPI0_POPR); + rxChannel_()->source((volatile uint8_t&)IMXRT_LPSPI4_S.RDR); // POPR is the receive fifo register for the SPI rxChannel_()->disableOnCompletion(); - rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_RX); + rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI4_RX); // The DMA RX id for MT66 is 14 rxChannel_()->attachInterrupt(rxIsr_); rxChannel_()->interruptAtCompletion(); + } static void pre_cs_impl() { - SPI0_SR = 0xFF0F0000; + if (LPSPI4_SR & 0x1800) { + DMASPI_PRINT(("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ERROR SR reg is %08X\n", LPSPI4_SR)); + } + DMASPI_PRINT(("********************************************CHECK SR reg is %08X\n", LPSPI4_SR)); + + IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7); + IMXRT_LPSPI4_S.FCR = 0; + + //IMXRT_LPSPI4_S.CR = LPSPI_CR_MEN | LPSPI_CR_RRF | LPSPI_CR_RTF; + IMXRT_LPSPI4_S.CR = LPSPI_CR_MEN; // I had to add the enable otherwise it wont' work + + // Lets try to output the first byte to make sure that we are in 8 bit mode... + IMXRT_LPSPI4_S.DER = LPSPI_DER_TDDE | LPSPI_DER_RDDE; //enable DMA on both TX and RX + IMXRT_LPSPI4_S.SR = 0x3f00; // clear out all of the other status... + +// if (m_pCurrentTransfer->m_pSource) { +// arm_dcache_flush((void *)m_pCurrentTransfer->m_pSource, m_pCurrentTransfer->m_transferCount); +// } + + } + +// static void pre_cs_impl() +// { +// +// //LPSPI4_PARAM = LPSPI4_PARAM; +// //LPSPI4_PARAM = 0x0404; +// //DMASPI_PRINT(("!!!!!!!!!!!!!!!!!!!!!PARAM reg is %08X\n", LPSPI4_PARAM)); +// txChannel_()->TCD->ATTR_SRC = 0; //Make sure set for 8 bit mode... +// txChannel_()->TCD->SLAST = 0; // Finish with it pointing to next location +// rxChannel_()->TCD->ATTR_DST = 0; //Make sure set for 8 bit mode... +// rxChannel_()->TCD->DLASTSGA = 0; +// +// //DMASPI_PRINT(("STATUS SR reg is %08X\n", LPSPI4_SR)); +// if (LPSPI4_SR & 0x1800) { +// DMASPI_PRINT(("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ERROR SR reg is %08X\n", LPSPI4_SR)); +// } +// LPSPI4_SR = 0x3f00; // clear various error and status flags +// DMASPI_PRINT(("********************************************CHECK SR reg is %08X\n", LPSPI4_SR)); +// +// LPSPI4_TCR = (LPSPI4_TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7); // Set the FRAMESZ to 7 for 8-bit frame size +// LPSPI4_FCR = 0; // set watermarks to zero, this ensures ready flag is set whenever fifo is not empty +// +// LPSPI4_CR = LPSPI_CR_MEN | LPSPI_CR_RRF | LPSPI_CR_RTF; //enable module and reset both FIFOs +// LPSPI4_DER = LPSPI_DER_TDDE | LPSPI_DER_RDDE; // enable DMA on both TX and RX +// } + + static void post_cs_impl() + { + rxChannel_()->enable(); + txChannel_()->enable(); + DMASPI_PRINT(("Done post_cs_impl()\n")); + } + + static void post_finishCurrentTransfer_impl() + { + IMXRT_LPSPI4_S.FCR = LPSPI_FCR_TXWATER(15); // _spi_fcr_save; // restore the FSR status... + IMXRT_LPSPI4_S.DER = 0; // DMA no longer doing TX (or RX) + + IMXRT_LPSPI4_S.CR = LPSPI_CR_MEN | LPSPI_CR_RRF | LPSPI_CR_RTF; // actually clear both... + IMXRT_LPSPI4_S.SR = 0x3f00; // clear out all of the other status... + +// if (m_pCurrentTransfer->m_pDest) { +// arm_dcache_delete((void *)m_pCurrentTransfer->m_pDest, m_pCurrentTransfer->m_transferCount); +// } + } + +// static void post_finishCurrentTransfer_impl() +// { +// //LPSPI4_FCR = LPSPI_FCR_TXWATER(15); // restore FSR status +// LPSPI4_DER = 0; // DMA no longer doing TX or RX +// LPSPI4_CR = LPSPI_CR_MEN | LPSPI_CR_RRF | LPSPI_CR_RTF; //enable module and reset both FIFOs +// LPSPI4_SR = 0x3f00; // clear out all the other statuses +// } + +private: +}; + +extern DmaSpi0 DMASPI0; + +#elif defined(KINETISK) + +class DmaSpi0 : public AbstractDmaSpi +{ +public: + static void begin_setup_txChannel_impl() + { + txChannel_()->disable(); + txChannel_()->destination((volatile uint8_t&)SPI0_PUSHR); // PUSHR is the transmit fifo register for the SPI + txChannel_()->disableOnCompletion(); + txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX); // The DMA TX id for MT66 is 15 + } + + static void begin_setup_rxChannel_impl() + { + rxChannel_()->disable(); + rxChannel_()->source((volatile uint8_t&)SPI0_POPR); // POPR is the receive fifo register for the SPI + rxChannel_()->disableOnCompletion(); + rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_RX); // The DMA RX id for MT66 is 14 + rxChannel_()->attachInterrupt(rxIsr_); + rxChannel_()->interruptAtCompletion(); + } + + static void pre_cs_impl() + { + SPI0_SR = 0xFF0F0000; // Clear various flags including Transfer complete, TXRX Status, End of Queue, Transmit FIFO underflow, Transmit FIFO Fill, Rx FIFO overflow, Rx fifo drain + + // Request Select Enable Register + // RFDF_RE Rx fifo drain request enable, enables the RFDF flag in SPI0_SR + // RFDF_DIRS Rx fifo drain selects DMA request instead of interrupt request + // TFFF_RE Transmit Fifo fill request enable + // TFFF_DIRS Transmit fifo fill selct DMA instead of interrupt SPI0_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS; } @@ -706,8 +838,8 @@ public: static void post_finishCurrentTransfer_impl() { - SPI0_RSER = 0; - SPI0_SR = 0xFF0F0000; + SPI0_RSER = 0; //DSPI DMA/Interrupt Request Select and Enable Register + SPI0_SR = 0xFF0F0000; // DSPI status register clear flags, same as above } private: @@ -715,6 +847,7 @@ private: extern DmaSpi0 DMASPI0; + #if defined(__MK66FX1M0__) class DmaSpi1 : public AbstractDmaSpi diff --git a/src/LibMemoryManagement.h b/src/LibMemoryManagement.h index 288e581..50c8c38 100644 --- a/src/LibMemoryManagement.h +++ b/src/LibMemoryManagement.h @@ -203,6 +203,7 @@ public: private: static bool m_configured; ///< there should only be one instance of ExternalSramManager in the whole project static MemConfig m_memConfig[BALibrary::NUM_MEM_SLOTS]; ///< store the configuration information for each external memory + void m_configure(void); ///< configure the memory manager }; diff --git a/src/common/AudioDelay.cpp b/src/common/AudioDelay.cpp index 3c1f704..4153f25 100644 --- a/src/common/AudioDelay.cpp +++ b/src/common/AudioDelay.cpp @@ -203,7 +203,7 @@ bool AudioDelay::interpolateDelay(int16_t *extendedSourceBuffer, int16_t *destBu } /// @todo optimize this later - for (int i=0; i> 16) + ((frac2*extendedSourceBuffer[i+1]) >> 16); } return true; diff --git a/src/common/BAHardware.cpp b/src/common/BAHardware.cpp new file mode 100644 index 0000000..2ce9eb1 --- /dev/null +++ b/src/common/BAHardware.cpp @@ -0,0 +1,99 @@ +/* + * ParameterAutomation.cpp + * + * Created on: October 23, 2019 + * 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 "BAHardware.h" + +namespace BALibrary { + +BAHardware BAHardwareConfig; // create the global configuration struct + +void BAHardware::set(TgaBoard tgaBoard) +{ + m_tgaBoard = tgaBoard; +} +TgaBoard BAHardware::getTgaBoard(void) +{ + return m_tgaBoard; +} + +void BAHardware::set(ExpansionBoard expansionBoard) +{ + m_expansionBoard = expansionBoard; +} + +ExpansionBoard BAHardware::getExpansionBoard(void) +{ + return m_expansionBoard; +} + +void BAHardware::set(MemSelect memSelect, SpiMemoryDefinition spiMem) +{ + switch(memSelect) { + case MemSelect::MEM0 : m_spiMem0 = spiMem; break; + case MemSelect::MEM1 : m_spiMem1 = spiMem; break; + default : + break; + } +} +SpiMemoryDefinition BAHardware::getSpiMemoryDefinition(MemSelect memSelect) +{ + switch(memSelect) { + case MemSelect::MEM0 : return m_spiMem0; break; + case MemSelect::MEM1 : return m_spiMem1; break; + default : + return m_spiMem0; + } +} + +size_t BAHardware::getSpiMemSizeBytes(unsigned memIndex) +{ + size_t sizeBytes = 0; + switch(memIndex) { + case 0 : sizeBytes = m_spiMem0.MEM_SIZE_BYTES; break; + case 1 : sizeBytes = m_spiMem1.MEM_SIZE_BYTES; break; + default : break; + } + return sizeBytes; +} + +size_t BAHardware::getSpiMemSizeBytes(MemSelect memSelect) +{ + size_t sizeBytes = 0; + unsigned memIndex = static_cast(memSelect); + switch(memIndex) { + case 0 : sizeBytes = m_spiMem0.MEM_SIZE_BYTES; break; + case 1 : sizeBytes = m_spiMem1.MEM_SIZE_BYTES; break; + default : break; + } + return sizeBytes; +} + +size_t BAHardware::getSpiMemMaxAddr(unsigned memIndex) +{ + return getSpiMemSizeBytes(memIndex)-1; +} + +size_t BAHardware::getSpiMemMaxAddr(MemSelect memSelect) +{ + return getSpiMemSizeBytes(memSelect)-1; +} + +} + + diff --git a/src/common/ExternalSramManager.cpp b/src/common/ExternalSramManager.cpp index 7083e0c..377f646 100644 --- a/src/common/ExternalSramManager.cpp +++ b/src/common/ExternalSramManager.cpp @@ -34,21 +34,9 @@ MemConfig ExternalSramManager::m_memConfig[BALibrary::NUM_MEM_SLOTS]; ExternalSramManager::ExternalSramManager(unsigned numMemories) { - // Initialize the static memory configuration structs - if (!m_configured) { - for (unsigned i=0; i < NUM_MEM_SLOTS; i++) { - m_memConfig[i].size = MEM_MAX_ADDR[i]+1; - m_memConfig[i].totalAvailable = MEM_MAX_ADDR[i]+1; - m_memConfig[i].nextAvailable = 0; - - m_memConfig[i].m_spi = nullptr; - } - m_configured = true; - } } ExternalSramManager::ExternalSramManager() -: ExternalSramManager(1) { } @@ -62,11 +50,13 @@ ExternalSramManager::~ExternalSramManager() size_t ExternalSramManager::availableMemory(BALibrary::MemSelect mem) { + if (!m_configured) { m_configure(); } return m_memConfig[mem].totalAvailable; } bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BALibrary::MemSelect mem, bool useDma) { + if (!m_configured) { m_configure(); } // 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, useDma); @@ -75,6 +65,8 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMillisecond bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALibrary::MemSelect mem, bool useDma) { + if (!m_configured) { m_configure(); } + if (m_memConfig[mem].totalAvailable >= sizeBytes) { Serial.println(String("Configuring a slot for mem ") + mem); // there is enough available memory for this request @@ -118,5 +110,20 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALi } } +void ExternalSramManager::m_configure(void) +{ + // Initialize the static memory configuration structs + if (!m_configured) { + for (unsigned i=0; i < NUM_MEM_SLOTS; i++) { + m_memConfig[i].size = BAHardwareConfig.getSpiMemSizeBytes(i); + m_memConfig[i].totalAvailable = BAHardwareConfig.getSpiMemSizeBytes(i); + m_memConfig[i].nextAvailable = 0; + + m_memConfig[i].m_spi = nullptr; + } + m_configured = true; + } +} + } diff --git a/src/effects/AudioEffectDelayExternal.cpp b/src/effects/AudioEffectDelayExternal.cpp index 1f1c215..f81e16a 100644 --- a/src/effects/AudioEffectDelayExternal.cpp +++ b/src/effects/AudioEffectDelayExternal.cpp @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#include "BAHardware.h" #include "BAAudioEffectDelayExternal.h" using namespace BALibrary; @@ -26,36 +26,26 @@ namespace BAEffects { #define SPISETTING SPISettings(20000000, MSBFIRST, SPI_MODE0) -struct MemSpiConfig { - unsigned mosiPin; - unsigned misoPin; - unsigned sckPin; - unsigned csPin; - unsigned memSize; -}; - -constexpr MemSpiConfig Mem0Config = {7, 8, 14, 15, 65536 }; -constexpr MemSpiConfig Mem1Config = {21, 5, 20, 31, 65536 }; - unsigned BAAudioEffectDelayExternal::m_usingSPICount[2] = {0,0}; BAAudioEffectDelayExternal::BAAudioEffectDelayExternal() : AudioStream(1, m_inputQueueArray) { - initialize(MemSelect::MEM0); + m_mem = MemSelect::MEM0; } BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(MemSelect mem) : AudioStream(1, m_inputQueueArray) { - initialize(mem); + m_mem = mem; } -BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(BALibrary::MemSelect type, float delayLengthMs) +BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(BALibrary::MemSelect mem, float delayLengthMs) : AudioStream(1, m_inputQueueArray) { unsigned delayLengthInt = (delayLengthMs*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f; - initialize(type, delayLengthInt); + m_mem = mem; + m_requestedDelayLength = delayLengthInt; } BAAudioEffectDelayExternal::~BAAudioEffectDelayExternal() @@ -65,6 +55,8 @@ BAAudioEffectDelayExternal::~BAAudioEffectDelayExternal() void BAAudioEffectDelayExternal::delay(uint8_t channel, float milliseconds) { + if (!m_configured) { initialize(); } + if (channel >= 8) return; if (milliseconds < 0.0) milliseconds = 0.0; uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f; @@ -78,6 +70,9 @@ void BAAudioEffectDelayExternal::delay(uint8_t channel, float milliseconds) { } void BAAudioEffectDelayExternal::disable(uint8_t channel) { + + if (!m_configured) { initialize(); } + if (channel >= 8) return; uint8_t mask = m_activeMask & ~(1<setMOSI(m_mosiPin); m_spi->setMISO(m_misoPin); @@ -175,13 +179,13 @@ void BAAudioEffectDelayExternal::initialize(MemSelect mem, unsigned delayLength) case MemSelect::MEM1 : { #if defined(__MK64FX512__) || defined(__MK66FX1M0__) - memsize = Mem1Config.memSize; + memsize = BAHardwareConfig.getSpiMemSizeBytes(m_mem) / sizeof(int16_t); m_spi = &SPI1; m_spiChannel = 1; - m_misoPin = Mem1Config.misoPin; - m_mosiPin = Mem1Config.mosiPin; - m_sckPin = Mem1Config.sckPin; - m_csPin = Mem1Config.csPin; + m_misoPin = SPI1_MISO_PIN; + m_mosiPin = SPI1_MOSI_PIN; + m_sckPin = SPI1_SCK_PIN; + m_csPin = SPI1_CS_PIN; m_spi->setMOSI(m_mosiPin); m_spi->setMISO(m_misoPin); @@ -196,14 +200,15 @@ void BAAudioEffectDelayExternal::initialize(MemSelect mem, unsigned delayLength) pinMode(m_csPin, OUTPUT); digitalWriteFast(m_csPin, HIGH); - avail = memsize - m_allocated[mem]; + avail = memsize - m_allocated[m_mem]; - if (delayLength > avail) samples = avail; - m_memoryStart = m_allocated[mem]; - m_allocated[mem] += samples; + if (m_requestedDelayLength > avail) samples = avail; + m_memoryStart = m_allocated[m_mem]; + m_allocated[m_mem] += samples; m_memoryLength = samples; zero(0, m_memoryLength); + m_configured = true; } diff --git a/src/peripherals/BAAudioControlWM8731.cpp b/src/peripherals/BAAudioControlWM8731.cpp index f2d635e..f822b13 100644 --- a/src/peripherals/BAAudioControlWM8731.cpp +++ b/src/peripherals/BAAudioControlWM8731.cpp @@ -19,6 +19,7 @@ */ #include +#include "BAHardware.h" #include "BAAudioControlWM8731.h" namespace BALibrary { @@ -132,9 +133,12 @@ BAAudioControlWM8731::~BAAudioControlWM8731() // Powerdown and disable the codec void BAAudioControlWM8731::disable(void) { - //Serial.println("Disabling codec"); - if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; } + if (m_wireStarted == false) { + Wire.begin(); + m_wireStarted = true; + } + setOutputStrength(); // set OUTPD to '1' (powerdown), which is bit 4 regArray[WM8731_REG_POWERDOWN] |= 0x10; @@ -155,9 +159,13 @@ void BAAudioControlWM8731::enable(void) disable(); // disable first in case it was already powered up //Serial.println("Enabling codec"); - if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; } - // Sequence from WAN0111.pdf + if (m_wireStarted == false) { + Wire.begin(); + m_wireStarted = true; + } + setOutputStrength(); + // Sequence from WAN0111.pdf // Begin configuring the codec resetCodec(); delay(100); // wait for reset @@ -199,9 +207,6 @@ void BAAudioControlWM8731::enable(void) regArray[WM8731_REG_POWERDOWN] = 0x02; delay(500); // wait for output to power up - //Serial.println("Done codec config"); - - delay(100); // wait for mute ramp } @@ -368,9 +373,9 @@ bool BAAudioControlWM8731::write(unsigned int reg, unsigned int val) Wire.beginTransmission(WM8731_I2C_ADDR); Wire.write((reg << 1) | ((val >> 8) & 1)); Wire.write(val & 0xFF); - if (byte error = Wire.endTransmission() ) { - (void)error; // supress warning about unused variable - //Serial.println(String("Wire::Error: ") + error + String(" retrying...")); + byte error = Wire.endTransmission(); + if (error) { + Serial.println(String("Wire::Error: ") + error + String(" retrying...")); } else { done = true; //Serial.println("Wire::SUCCESS!"); @@ -380,4 +385,17 @@ bool BAAudioControlWM8731::write(unsigned int reg, unsigned int val) return true; } +void BAAudioControlWM8731::setOutputStrength(void) +{ +#if defined(__IMXRT1062__) + // The T4 requires the pads be configured with correct pullups and drive strength + SCL_PAD_CTRL = SCL_SDA_PAD_CFG; + SDA_PAD_CTRL = SCL_SDA_PAD_CFG; + MCLK_PAD_CTRL = I2S_PAD_CFG; + BCLK_PAD_CTRL = I2S_PAD_CFG; + LRCLK_PAD_CTRL = I2S_PAD_CFG; + DAC_PAD_CTRL = I2S_PAD_CFG; +#endif +} + } /* namespace BALibrary */ diff --git a/src/peripherals/BAPhysicalControls.cpp b/src/peripherals/BAPhysicalControls.cpp index 5904455..e479ad3 100644 --- a/src/peripherals/BAPhysicalControls.cpp +++ b/src/peripherals/BAPhysicalControls.cpp @@ -57,7 +57,6 @@ unsigned BAPhysicalControls::addRotary(uint8_t pin1, uint8_t pin2, bool swapDire } unsigned BAPhysicalControls::addSwitch(uint8_t pin, unsigned long intervalMilliseconds) { - //m_switches.emplace_back(pin, intervalMilliseconds);' m_switches.emplace_back(); m_switches.back().attach(pin); m_switches.back().interval(10); @@ -240,23 +239,36 @@ void Potentiometer::setFeedbackFitlerValue(float fitlerValue) bool Potentiometer::getValue(float &value) { - bool newValue = true; + // Check if the minimum sampling time has elapsed + if (m_timerMs < m_samplingIntervalMs) { + return false; + } + m_timerMs = 0; // reset the sampling timer unsigned val = analogRead(m_pin); // read the raw value // constrain it within the calibration values, them map it to the desired range. val = constrain(val, m_minCalibration, m_maxCalibration); // Use an IIR filter to smooth out the noise in the pot readings - unsigned valFilter = static_cast( (1.0f - m_feedbackFitlerValue)*val + (m_feedbackFitlerValue*m_lastValue)); + unsigned valFilter = static_cast( (1.0f - m_feedbackFitlerValue)*val + (m_feedbackFitlerValue*m_lastValue)); + m_lastValue = valFilter; - if (valFilter == m_lastValue) { - newValue = false; + // Apply a hysteresis check + if (valFilter == m_lastValidValue) { // check if value hasn't changed + return false; } - m_lastValue = valFilter; + if (abs((int)valFilter - (int)m_lastValidValue) < m_changeThreshold) { + // The value has not exceeded the change threshold. Suppress the change only if it's not + // near the limits. This is necessary to ensure the limits can be reached. + if ( (valFilter < m_maxCalibrationThresholded) && (valFilter > m_minCalibrationThresholded)) { + return false; + } + } + m_lastValidValue = m_lastValue; - // - if (valFilter < m_minCalibrationThresholded) { value = 0.0f; } + // Convert the integer reading to a float value range 0.0 to 1.0f + if (valFilter < m_minCalibrationThresholded) { value = 0.0f; } else if (valFilter > m_maxCalibrationThresholded) { value = 1.0f; } else { value = static_cast(valFilter - m_minCalibrationThresholded) / static_cast(m_rangeThresholded); @@ -265,7 +277,8 @@ bool Potentiometer::getValue(float &value) { if (m_swapDirection) { value = 1.0f - value; } - return newValue; + + return true; } int Potentiometer::getRawValue() { @@ -293,6 +306,16 @@ void Potentiometer::setCalibrationValues(unsigned min, unsigned max, bool swapDi adjustCalibrationThreshold(m_thresholdFactor); } +void Potentiometer::setSamplingIntervalMs(unsigned intervalMs) +{ + m_samplingIntervalMs = intervalMs; +} + +void Potentiometer::setChangeThreshold(float changeThreshold) +{ + m_changeThreshold = changeThreshold; +} + Potentiometer::Calib Potentiometer::calibrate(uint8_t pin) { Calib calib; diff --git a/src/peripherals/BASpiMemory.cpp b/src/peripherals/BASpiMemory.cpp index a1fab91..143dda2 100644 --- a/src/peripherals/BASpiMemory.cpp +++ b/src/peripherals/BASpiMemory.cpp @@ -17,23 +17,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #include "Arduino.h" #include "BASpiMemory.h" namespace BALibrary { // MEM0 Settings -constexpr int SPI_CS_MEM0 = 15; -constexpr int SPI_MOSI_MEM0 = 7; -constexpr int SPI_MISO_MEM0 = 8; -constexpr int SPI_SCK_MEM0 = 14; +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 = 31; -constexpr int SPI_MOSI_MEM1 = 21; -constexpr int SPI_MISO_MEM1 = 5; -constexpr int SPI_SCK_MEM1 = 20; +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 // SPI Constants constexpr int SPI_WRITE_MODE_REG = 0x1; @@ -48,6 +49,7 @@ constexpr int SPI_ADDR_0_MASK = 0x0000FF; constexpr int CMD_ADDRESS_SIZE = 4; constexpr int MAX_DMA_XFER_SIZE = 0x4000; + BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId) { m_memDeviceId = memDeviceId; @@ -71,6 +73,7 @@ void BASpiMemory::begin() m_spi->setMISO(SPI_MISO_MEM0); m_spi->setSCK(SPI_SCK_MEM0); m_spi->begin(); + m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM0).DIE_BOUNDARY; break; #if defined(__MK64FX512__) || defined(__MK66FX1M0__) @@ -81,6 +84,7 @@ void BASpiMemory::begin() m_spi->setMISO(SPI_MISO_MEM1); m_spi->setSCK(SPI_SCK_MEM1); m_spi->begin(); + m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM1).DIE_BOUNDARY; break; #endif @@ -112,40 +116,28 @@ void BASpiMemory::write(size_t address, uint8_t data) digitalWrite(m_csPin, HIGH); } -// Single address write +// Sequential write void BASpiMemory::write(size_t address, uint8_t *src, size_t numBytes) { - uint8_t *dataPtr = src; - - 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)); - - for (size_t i=0; i < numBytes; i++) { - m_spi->transfer(*dataPtr++); - } - m_spi->endTransaction(); - digitalWrite(m_csPin, HIGH); + // Check if this burst will cross the die boundary + while (numBytes > 0) { + size_t bytesToWrite = m_bytesToXfer(address, numBytes); + m_rawWrite(address, src, bytesToWrite); + address += bytesToWrite; + numBytes -= bytesToWrite; + src += bytesToWrite; + } } - void BASpiMemory::zero(size_t address, size_t numBytes) { - 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)); - - for (size_t i=0; i < numBytes; i++) { - m_spi->transfer(0); - } - m_spi->endTransaction(); - digitalWrite(m_csPin, HIGH); + // Check if this burst will cross the die boundary + while (numBytes > 0) { + size_t bytesToWrite = m_bytesToXfer(address, numBytes); + m_rawZero(address, bytesToWrite); + address += bytesToWrite; + numBytes -= bytesToWrite; + } } void BASpiMemory::write16(size_t address, uint16_t data) @@ -161,35 +153,29 @@ void BASpiMemory::write16(size_t address, uint16_t data) void BASpiMemory::write16(size_t address, uint16_t *src, size_t numWords) { - uint16_t *dataPtr = src; - - m_spi->beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); - m_spi->transfer16(address & 0xFFFF); - - for (size_t i=0; itransfer16(*dataPtr++); - } - - m_spi->endTransaction(); - digitalWrite(m_csPin, HIGH); + // Check if this burst will cross the die boundary + size_t numBytes = numWords * sizeof(uint16_t); + while (numBytes > 0) { + size_t bytesToWrite = m_bytesToXfer(address, numBytes); + size_t wordsToWrite = bytesToWrite / sizeof(uint16_t); + m_rawWrite16(address, src, wordsToWrite); + address += bytesToWrite; + numBytes -= bytesToWrite; + src += wordsToWrite; + } } void BASpiMemory::zero16(size_t address, size_t numWords) { - m_spi->beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); - m_spi->transfer16(address & 0xFFFF); - - for (size_t i=0; itransfer16(0); - } - - m_spi->endTransaction(); - digitalWrite(m_csPin, HIGH); - Serial.println("DONE!"); + // Check if this burst will cross the die boundary + size_t numBytes = numWords * sizeof(uint16_t); + while (numBytes > 0) { + size_t bytesToWrite = m_bytesToXfer(address, numBytes); + size_t wordsToWrite = bytesToWrite / sizeof(uint16_t); + m_rawZero16(address, wordsToWrite); + address += bytesToWrite; + numBytes -= bytesToWrite; + } } // single address read @@ -209,24 +195,16 @@ uint8_t BASpiMemory::read(size_t address) return data; } - void BASpiMemory::read(size_t address, uint8_t *dest, size_t numBytes) { - uint8_t *dataPtr = dest; - - 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)); - - for (size_t i=0; itransfer(0); - } - - m_spi->endTransaction(); - digitalWrite(m_csPin, HIGH); + // Check if this burst will cross the die boundary + while (numBytes > 0) { + size_t bytesToRead = m_bytesToXfer(address, numBytes); + m_rawRead(address, dest, bytesToRead); + address += bytesToRead; + numBytes -= bytesToRead; + dest += bytesToRead; + } } uint16_t BASpiMemory::read16(size_t address) @@ -246,21 +224,136 @@ uint16_t BASpiMemory::read16(size_t address) void BASpiMemory::read16(size_t address, uint16_t *dest, size_t numWords) { + // Check if this burst will cross the die boundary + size_t numBytes = numWords * sizeof(uint16_t); + while (numBytes > 0) { + size_t bytesToRead = m_bytesToXfer(address, numBytes); + size_t wordsToRead = bytesToRead / sizeof(uint16_t); + m_rawRead16(address, dest, wordsToRead); + address += bytesToRead; + numBytes -= bytesToRead; + dest += wordsToRead; + } +} - uint16_t *dataPtr = dest; - m_spi->beginTransaction(m_settings); - digitalWrite(m_csPin, LOW); - m_spi->transfer16((SPI_READ_CMD << 8) | (address >> 16) ); - m_spi->transfer16(address & 0xFFFF); +// PRIVATE FUNCTIONS +size_t BASpiMemory::m_bytesToXfer(size_t address, size_t numBytes) +{ + // Check if this burst will cross the die boundary + size_t bytesToXfer = numBytes; + if (m_dieBoundary) { + if ((address < m_dieBoundary) && (address+numBytes > m_dieBoundary)) { + // split into two xfers + bytesToXfer = m_dieBoundary-address; + } + } + return bytesToXfer; +} - for (size_t i=0; itransfer16(0); - } +void BASpiMemory::m_rawWrite(size_t address, uint8_t *src, size_t numBytes) +{ + uint8_t *dataPtr = src; + + 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)); + + for (size_t i=0; i < numBytes; i++) { + m_spi->transfer(*dataPtr++); + } + m_spi->endTransaction(); + digitalWrite(m_csPin, HIGH); +} - m_spi->endTransaction(); - digitalWrite(m_csPin, HIGH); +void BASpiMemory::m_rawWrite16(size_t address, uint16_t *src, size_t numWords) +{ + uint16_t *dataPtr = src; + + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); + m_spi->transfer16(address & 0xFFFF); + + for (size_t i=0; itransfer16(*dataPtr++); + } + + m_spi->endTransaction(); + digitalWrite(m_csPin, HIGH); +} + +void BASpiMemory::m_rawZero(size_t address, size_t numBytes) +{ + 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)); + + for (size_t i=0; i < numBytes; i++) { + m_spi->transfer(0); + } + m_spi->endTransaction(); + digitalWrite(m_csPin, HIGH); +} + +void BASpiMemory::m_rawZero16(size_t address, size_t numWords) +{ + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) ); + m_spi->transfer16(address & 0xFFFF); + + for (size_t i=0; itransfer16(0); + } + + m_spi->endTransaction(); + digitalWrite(m_csPin, HIGH); +} + +void BASpiMemory::m_rawRead(size_t address, uint8_t *dest, size_t numBytes) +{ + uint8_t *dataPtr = dest; + + 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)); + + for (size_t i=0; itransfer(0); + } + + m_spi->endTransaction(); + digitalWrite(m_csPin, HIGH); } +void BASpiMemory::m_rawRead16(size_t address, uint16_t *dest, size_t numWords) +{ + uint16_t *dataPtr = dest; + m_spi->beginTransaction(m_settings); + digitalWrite(m_csPin, LOW); + m_spi->transfer16((SPI_READ_CMD << 8) | (address >> 16) ); + m_spi->transfer16(address & 0xFFFF); + + for (size_t i=0; itransfer16(0); + } + + m_spi->endTransaction(); + digitalWrite(m_csPin, HIGH); +} + +#if defined (__IMXRT1062__) +//#if 0 +#else ///////////////////////////////////////////////////////////////////////////// // BASpiMemoryDMA ///////////////////////////////////////////////////////////////////////////// @@ -342,8 +435,8 @@ void BASpiMemoryDMA::begin(void) m_spi->setMISO(SPI_MISO_MEM0); m_spi->setSCK(SPI_SCK_MEM0); m_spi->begin(); - //m_spiDma = &DMASPI0; m_spiDma = new DmaSpiGeneric(); + m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM0).DIE_BOUNDARY; break; #if defined(__MK66FX1M0__) // DMA on SPI1 is only supported on T3.6 @@ -355,7 +448,7 @@ void BASpiMemoryDMA::begin(void) m_spi->setSCK(SPI_SCK_MEM1); m_spi->begin(); m_spiDma = new DmaSpiGeneric(1); - //m_spiDma = &DMASPI1; + m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM1).DIE_BOUNDARY; break; #endif @@ -366,7 +459,6 @@ void BASpiMemoryDMA::begin(void) m_spiDma->begin(); m_spiDma->start(); - m_started = true; } @@ -380,14 +472,16 @@ void BASpiMemoryDMA::write(size_t address, uint8_t *src, size_t numBytes) size_t bytesRemaining = numBytes; uint8_t *srcPtr = src; size_t nextAddress = address; + while (bytesRemaining > 0) { - m_txXferCount = min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE)); - while ( m_txTransfer[1].busy()) {} // wait until not busy + m_txXferCount = m_bytesToXfer(nextAddress, min(bytesRemaining, static_cast(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]); - while ( m_txTransfer[0].busy()) {} // wait until not busy + while ( m_txTransfer[0].busy() || m_txTransfer[1].busy()) { yield(); } // 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; @@ -401,15 +495,23 @@ void BASpiMemoryDMA::zero(size_t address, size_t numBytes) { size_t bytesRemaining = numBytes; size_t nextAddress = address; + + /// TODO: Why can't the T4 zero the memory when a NULLPTR is passed? It seems to write a constant random value. + /// Perhaps there is somewhere we can set a fill value? + uint8_t zeroBuffer[MAX_DMA_XFER_SIZE]; + memset(zeroBuffer, 0, MAX_DMA_XFER_SIZE); + while (bytesRemaining > 0) { - m_txXferCount = min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE)); - while ( m_txTransfer[1].busy()) {} // wait until not busy + m_txXferCount = m_bytesToXfer(nextAddress, min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE))); // check for die boundary + + while ( m_txTransfer[1].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]); - 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); + while ( m_txTransfer[0].busy()) { yield(); } // wait until not busy + //m_txTransfer[0] = DmaSpi::Transfer(nullptr, m_txXferCount, nullptr, 0, m_cs, TransferType::NO_START_CS); + m_txTransfer[0] = DmaSpi::Transfer(zeroBuffer, m_txXferCount, nullptr, 0, m_cs, TransferType::NO_START_CS); m_spiDma->registerTransfer(m_txTransfer[0]); bytesRemaining -= m_txXferCount; nextAddress += m_txXferCount; @@ -434,14 +536,15 @@ void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes) uint8_t *destPtr = dest; size_t nextAddress = address; while (bytesRemaining > 0) { - m_setSpiCmdAddr(SPI_READ_CMD, nextAddress, m_rxCommandBuffer); + m_rxXferCount = m_bytesToXfer(nextAddress, min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE))); // check for die boundary - while ( m_rxTransfer[1].busy()) {} + 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]); - m_rxXferCount = min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE)); - while ( m_rxTransfer[0].busy()) {} + + 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); m_spiDma->registerTransfer(m_rxTransfer[0]); @@ -467,5 +570,6 @@ bool BASpiMemoryDMA::isReadBusy(void) const { return (m_rxTransfer[0].busy() or m_rxTransfer[1].busy()); } +#endif // BASpiMemoryDMA definition } /* namespace BALibrary */ diff --git a/src/peripherals/DmaSpi.cpp b/src/peripherals/DmaSpi.cpp index 2653f6f..f837ed3 100644 --- a/src/peripherals/DmaSpi.cpp +++ b/src/peripherals/DmaSpi.cpp @@ -1,6 +1,8 @@ #include "DmaSpi.h" -#if defined(KINETISK) +#if defined(__IMXRT1062__) // T4.0 +DmaSpi0 DMASPI0; +#elif defined(KINETISK) DmaSpi0 DMASPI0; #if defined(__MK66FX1M0__) DmaSpi1 DMASPI1;