diff --git a/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino b/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino index 6127f2c..25fec18 100644 --- a/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino +++ b/examples/Delay/AnalogDelayDemo/AnalogDelayDemo.ino @@ -1,17 +1,17 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * This example demonstrates teh BAAudioEffectsAnalogDelay effect. It can * be controlled using USB MIDI. You can get a free USB MIDI Controller - * appliation at + * appliation at * http://www.blackaddr.com/downloads/BAMidiTester/ * or the source code at * https://github.com/Blackaddr/BAMidiTester - * + * * Even if you don't control the guitar effect with USB MIDI, you must set * the Arduino IDE USB-Type under Tools to "Serial + MIDI" */ @@ -76,14 +76,16 @@ elapsedMillis timer; void OnControlChange(byte channel, byte control, byte value) { analogDelay.processMidi(channel-1, control, value); #ifdef MIDI_DEBUG - Serial.print("Control Change, ch="); - Serial.print(channel, DEC); - Serial.print(", control="); - Serial.print(control, DEC); - Serial.print(", value="); - Serial.print(value, DEC); - Serial.println(); - #endif + if (Serial) { + Serial.print("Control Change, ch="); + Serial.print(channel, DEC); + Serial.print(", control="); + Serial.print(control, DEC); + Serial.print(", value="); + Serial.print(value, DEC); + Serial.println(); + } + #endif } void setup() { @@ -96,7 +98,7 @@ void setup() { //SPI_MEM0_4M(); // Older REVA and REVB boards came with 4M or 1M //SPI_MEM0_1M(); #endif - + delay(100); Serial.begin(57600); // Start the serial port @@ -107,18 +109,19 @@ void setup() { delay(5); // Enable the codec - Serial.println("Enabling codec...\n"); + if (Serial) { Serial.println("Enabling codec...\n"); } codec.enable(); delay(100); // If using external memory request request memory from the manager // for the slot #ifdef USE_EXT - Serial.println("Using EXTERNAL memory"); + if (Serial) { Serial.println("Using EXTERNAL memory"); } // We have to request memory be allocated to our slot. externalSram.requestMemory(&delaySlot, 500.0f, MemSelect::MEM0, true); + delaySlot.clear(); #else - Serial.println("Using INTERNAL memory"); + if (Serial) { Serial.println("Using INTERNAL memory"); } #endif // Setup MIDI @@ -126,7 +129,7 @@ void setup() { MIDI.setHandleControlChange(OnControlChange); usbMIDI.setHandleControlChange(OnControlChange); - + // Configure which MIDI CC's will control the effect parameters analogDelay.mapMidiControl(AudioEffectAnalogDelay::BYPASS,16); analogDelay.mapMidiControl(AudioEffectAnalogDelay::DELAY,20); @@ -136,7 +139,7 @@ void setup() { // Besure to enable the delay. When disabled, audio is is completely blocked // to minimize resources to nearly zero. - analogDelay.enable(); + analogDelay.enable(); // Set some default values. // These can be changed by sending MIDI CC messages over the USB using @@ -162,13 +165,15 @@ void setup() { void loop() { // usbMIDI.read() needs to be called rapidly from loop(). - + if (timer > 1000) { timer = 0; - Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); - Serial.print("% "); - Serial.print(" analogDelay: "); Serial.print(analogDelay.processorUsage()); - Serial.println("%"); + if (Serial) { + Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); + Serial.print("% "); + Serial.print(" analogDelay: "); Serial.print(analogDelay.processorUsage()); + Serial.println("%"); + } } MIDI.read(); diff --git a/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino b/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino index b12bb23..2a79b26 100644 --- a/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino +++ b/examples/Delay/AnalogDelayDemoExpansion/AnalogDelayDemoExpansion.ino @@ -1,24 +1,24 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * This example demonstrates teh BAAudioEffectsAnalogDelay effect. It can * be controlled using the Blackaddr Audio "Expansion Control Board". - * + * * POT1 (left) controls amount of delay * POT2 (right) controls amount of feedback * POT3 (center) controls the wet/dry mix * SW1 will enable/bypass the audio effect. LED1 will be on when effect is enabled. * SW2 will cycle through the 3 pre-programmed analog filters. LED2 will be on when SW2 is pressed. - * + * * !!! SET POTS TO REASONABLE VALUES BEFORE STARTING TO AVOID SCREECHING FEEDBACK!!!! * - set POT1 (delay) fully counter-clockwise then increase it slowly. * - set POT2 (feedback) fully counter-clockwise, then increase it slowly * - set POT3 (wet/dry mix) to half-way at the detent. - * + * * Using the Serial Montitor, send 'u' and 'd' characters to increase or decrease * the headphone volume between values of 0 and 9. */ @@ -79,7 +79,7 @@ AudioConnection rightOut(analogDelay,0, i2sOut, 1); // - LED2 (right) will illuminate when pressing SW2. ////////////////////////////////////////// // To get the calibration values for your particular board, first run the -// BAExpansionCalibrate.ino example and +// BAExpansionCalibrate.ino example and constexpr int potCalibMin = 1; constexpr int potCalibMax = 1018; constexpr bool potSwapDirection = true; @@ -100,27 +100,27 @@ void setup() { TGA_PRO_MKII_REV1(); // Declare the version of the TGA Pro you are using. //TGA_PRO_REVB(x); //TGA_PRO_REVA(x); - + #ifdef USE_EXT SPI_MEM0_64M(); // Optional 64Mbit SPI RAM //SPI_MEM0_4M(); // Older REVB and REVA boards offered 1M or 4M - //SPI_MEM0_1M(); + //SPI_MEM0_1M(); #endif - + delay(100); // wait a bit for serial to be available Serial.begin(57600); // Start the serial port delay(100); // Configure the hardware - + // 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 filterHandle = controls.addSwitch(BA_EXPAND_SW2_PIN); // will be used for stepping through filters // pots delayHandle = controls.addPot(BA_EXPAND_POT1_PIN, potCalibMin, potCalibMax, potSwapDirection); // control the amount of delay - feedbackHandle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); - mixHandle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); + feedbackHandle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); + mixHandle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); // leds led1Handle = controls.addOutput(BA_EXPAND_LED1_PIN); led2Handle = controls.addOutput(BA_EXPAND_LED2_PIN); // will illuminate when pressing SW2 @@ -130,28 +130,29 @@ void setup() { AudioMemory(128); // Enable and configure the codec - Serial.println("Enabling codec...\n"); + if (Serial) { Serial.println("Enabling codec...\n"); } codec.enable(); codec.setHeadphoneVolume(1.0f); // Max headphone volume // If using external memory request request memory from the manager // for the slot #ifdef USE_EXT - Serial.println("Using EXTERNAL memory"); + if (Serial) { Serial.println("Using EXTERNAL memory"); } // We have to request memory be allocated to our slot. externalSram.requestMemory(&delaySlot, 500.0f, MemSelect::MEM0, true); + delaySlot.clear(); #else - Serial.println("Using INTERNAL memory"); + if (Serial) { Serial.println("Using INTERNAL memory"); } #endif // Besure to enable the delay. When disabled, audio is is completely blocked by the effect // to minimize resource usage to nearly to nearly zero. - analogDelay.enable(); + analogDelay.enable(); // Set some default values. // These can be changed using the controls on the Blackaddr Audio Expansion Board analogDelay.bypass(false); - controls.setOutput(led1Handle, !analogDelay.isBypass()); // Set the LED when NOT bypassed + controls.setOutput(led1Handle, !analogDelay.isBypass()); // Set the LED when NOT bypassed analogDelay.mix(0.5f); analogDelay.feedback(0.0f); @@ -178,8 +179,8 @@ void loop() { bool bypass = analogDelay.isBypass(); // get the current state bypass = !bypass; // change it analogDelay.bypass(bypass); // set the new state - controls.setOutput(led1Handle, !bypass); // Set the LED when NOT bypassed - Serial.println(String("BYPASS is ") + bypass); + controls.setOutput(led1Handle, !bypass); // Set the LED when NOT bypassed + if (Serial) { Serial.println(String("BYPASS is ") + bypass); } } // Use SW2 to cycle through the filters @@ -188,27 +189,27 @@ void loop() { filterIndex = (filterIndex + 1) % 3; // update and potentionall roll the counter 0, 1, 2, 0, 1, 2, ... // cast the index between 0 to 2 to the enum class AudioEffectAnalogDelay::Filter analogDelay.setFilter(static_cast(filterIndex)); // will cycle through 0 to 2 - Serial.println(String("Filter set to ") + filterIndex); + if (Serial) { Serial.println(String("Filter set to ") + filterIndex); } } // Use POT1 (left) to control the delay setting if (controls.checkPotValue(delayHandle, potValue)) { // Pot has changed - Serial.println(String("New DELAY setting: ") + potValue); + if (Serial) { Serial.println(String("New DELAY setting: ") + potValue); } analogDelay.delayFractionMax(potValue); } // Use POT2 (right) to control the feedback setting if (controls.checkPotValue(feedbackHandle, potValue)) { // Pot has changed - Serial.println(String("New FEEDBACK setting: ") + potValue); + if (Serial) { Serial.println(String("New FEEDBACK setting: ") + potValue); } analogDelay.feedback(potValue); } // Use POT3 (centre) to control the mix setting if (controls.checkPotValue(mixHandle, potValue)) { // Pot has changed - Serial.println(String("New MIX setting: ") + potValue); + if (Serial) { Serial.println(String("New MIX setting: ") + potValue); } analogDelay.mix(potValue); } @@ -217,11 +218,11 @@ void loop() { if (Serial.available() > 0) { while (Serial.available()) { char key = Serial.read(); - if (key == 'u') { + if (key == 'u') { headphoneVolume = (headphoneVolume + 1) % MAX_HEADPHONE_VOL; Serial.println(String("Increasing HEADPHONE volume to ") + headphoneVolume); } - else if (key == 'd') { + else if (key == 'd') { headphoneVolume = (headphoneVolume - 1) % MAX_HEADPHONE_VOL; Serial.println(String("Decreasing HEADPHONE volume to ") + headphoneVolume); } @@ -231,13 +232,15 @@ void loop() { } delay(20); // Without some minimal delay here it will be difficult for the pots/switch changes to be detected. - + if (timer > 1000) { timer = 0; - Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); - Serial.print("% "); - Serial.print(" analogDelay: "); Serial.print(analogDelay.processorUsage()); - Serial.println("%"); + if (Serial) { + Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); + Serial.print("% "); + Serial.print(" analogDelay: "); Serial.print(analogDelay.processorUsage()); + Serial.println("%"); + } } } diff --git a/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino b/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino index 9640ba6..1db9812 100644 --- a/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino +++ b/examples/Delay/ExternalDelayDemo/ExternalDelayDemo.ino @@ -1,15 +1,15 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * This demo shows to use the BAAudioEffectDelayExternal audio class * to create long delays using external SPI RAM. - * + * * Eight delay taps are configured from a single SRAM device. - * + * */ #include #include "BALibrary.h" @@ -60,12 +60,12 @@ void setup() { Serial.begin(57600); delay(200); AudioMemory(64); - + delay(500); - Serial.println(String("Starting...\n")); + if (Serial) { Serial.println(String("Starting...\n")); } delay(100); - Serial.println("Enabling codec...\n"); + if (Serial) { Serial.println("Enabling codec...\n"); } codecControl.enable(); delay(100); @@ -90,12 +90,12 @@ void setup() { delayOutMixerB.gain(1, 0.05f); delayOutMixerB.gain(2, 0.025f); delayOutMixerB.gain(3, 0.0125f); - + // mix the original signal with the two delay mixers delayMixer.gain(0, 1.0f); delayMixer.gain(1, 1.0f); delayMixer.gain(2, 1.0f); - + } void loop() { diff --git a/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino b/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino index c025600..32eb236 100644 --- a/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino +++ b/examples/Delay/SoundOnSoundDemo/SoundOnSoundDemo.ino @@ -1,21 +1,21 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * THIS DEMO REQUIRES THE EXTERNAL SRAM MEM0 - * + * * This demo combines MIDI control with the BAAudioEffectSoundOnSound. You can use * the BAMidiTester to control the effect but it's best to use external MIDI footswitch * or the Blackaddr Audio Expansion Control Board. - * + * * User must set the Arduino IDE USB-Type to "Serial + MIDI" in the Tools menu. - * + * * Afters startup, the effect will spend about 5 seconds clearing the audio delay buffer to prevent * any startup pops or clicks from propagating. - * + * */ #include #include @@ -84,14 +84,16 @@ elapsedMillis timer; void OnControlChange(byte channel, byte control, byte value) { sos.processMidi(channel-1, control, value); #ifdef MIDI_DEBUG - Serial.print("Control Change, ch="); - Serial.print(channel, DEC); - Serial.print(", control="); - Serial.print(control, DEC); - Serial.print(", value="); - Serial.print(value, DEC); - Serial.println(); - #endif + if (Serial) { + Serial.print("Control Change, ch="); + Serial.print(channel, DEC); + Serial.print(", control="); + Serial.print(control, DEC); + Serial.print(", value="); + Serial.print(value, DEC); + Serial.println(); + } + #endif } void setup() { @@ -109,20 +111,17 @@ void setup() { // Disable the codec first codec.disable(); - delay(100); AudioMemory(128); - delay(5); SPI_MEM0_1M(); // Configure the SPI memory size // Enable the codec - Serial.println("Enabling codec...\n"); + if (Serial) { Serial.println("Enabling codec...\n"); } codec.enable(); - delay(100); // We have to request memory be allocated to our slot. externalSram.requestMemory(&delaySlot, BAHardwareConfig.getSpiMemSizeBytes(MemSelect::MEM0), MemSelect::MEM0, true); - //externalSram.requestMemory(&delaySlot, 50.0f, MemSelect::MEM0, true); + delaySlot.clear(); // Setup MIDI MIDI.begin(MIDI_CHANNEL_OMNI); @@ -131,7 +130,7 @@ void setup() { // Configure the LED to indicate the gate status sos.setGateLedGpio(USR_LED_ID); - + // Configure which MIDI CC's will control the effect parameters //sos.mapMidiControl(AudioEffectSOS::BYPASS,16); sos.mapMidiControl(AudioEffectSOS::GATE_TRIGGER,16); @@ -143,7 +142,7 @@ void setup() { // Besure to enable the delay. When disabled, audio is is completely blocked // to minimize resources to nearly zero. - sos.enable(); + sos.enable(); // Set some default values. // These can be changed by sending MIDI CC messages over the USB using @@ -170,7 +169,7 @@ void setup() { delay(1000); sos.clear(); - + } void loop() { @@ -178,10 +177,12 @@ void loop() { if (timer > 1000) { timer = 0; - Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); - Serial.print("% "); - Serial.print(" SOS: "); Serial.print(sos.processorUsage()); - Serial.println("%"); + if (Serial) { + Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); + Serial.print("% "); + Serial.print(" SOS: "); Serial.print(sos.processorUsage()); + Serial.println("%"); + } } MIDI.read(); diff --git a/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino b/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino index 0cc2dcd..2264ed9 100644 --- a/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino +++ b/examples/Delay/SoundOnSoundExpansionDemo/SoundOnSoundExpansionDemo.ino @@ -1,29 +1,29 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * THIS DEMO REQUIRES BOTH THE EXTERNAL SRAM AND EXPANSION BOARD ADD-ONS - * + * * This demo combines the Blackaddr Audio Expansion board with the BAAudioEffectSOS, - * which provides sound-on-sound. The pushbuttons control the opening of the effect + * which provides sound-on-sound. The pushbuttons control the opening of the effect * gate, as well as clearing the sound being held. - * + * * The pots control the feedback, as well as the gate opening and close times. - * + * * Afters startup, the effect will spend about 5 seconds clearing the audio delay buffer to prevent * any startup pops or clicks from propagating. - * + * * POT1 - Gate open time. Middle position (detent) is about 2100 ms. * POT2 - gate close time. Middle position (detent) is about 2100 ms. * POT3 - Effect volume. Controls the volume of the SOS effect separate from the normal volume * SW1 - Strum and hold a chord then push this button. Continue holding the button until the LED1 light goes out. * SW2 - Push this button to clear out the sound circulating in the delay. - * + * */ -#include +#include #include "BALibrary.h" #include "BAEffects.h" @@ -86,7 +86,7 @@ AudioConnection outputRight(mixer, 0, i2sOut, 1); // - LED2 (right) will illuminate when pressing SW2. ////////////////////////////////////////// // To get the calibration values for your particular board, first run the -// BAExpansionCalibrate.ino example and +// BAExpansionCalibrate.ino example and constexpr int potCalibMin = 1; constexpr int potCalibMax = 1018; constexpr bool potSwapDirection = true; @@ -114,7 +114,6 @@ void setup() { //SPI_MEM0_4M(); // Older REVB / REVA boards offered 1M or 4M //SPI_MEM0_1M(); - 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 @@ -125,8 +124,8 @@ void setup() { clearHandle = controls.addSwitch(BA_EXPAND_SW2_PIN); // will be used for stepping through filters // pots openHandle = controls.addPot(BA_EXPAND_POT1_PIN, potCalibMin, potCalibMax, potSwapDirection); // control the amount of delay - closeHandle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); - volumeHandle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); + closeHandle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); + volumeHandle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); // leds led1Handle = controls.addOutput(BA_EXPAND_LED1_PIN); led2Handle = controls.addOutput(BA_EXPAND_LED2_PIN); // will illuminate when pressing SW2 @@ -136,12 +135,13 @@ void setup() { AudioMemory(128); // Enable the codec - Serial.println("Enabling codec...\n"); + if (Serial) { 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, BAHardwareConfig.getSpiMemSizeBytes(MemSelect::MEM0), MemSelect::MEM0, true); + delaySlot.clear(); // Configure the LED to indicate the gate status, this is controlled directly by SOS effect, not by // by BAPhysicalControls @@ -149,7 +149,7 @@ void setup() { // Besure to enable the SOS. When disabled, audio is is completely blocked // to minimize resources to nearly zero. - sos.enable(); + sos.enable(); // Set some default values. // These can be changed by sending MIDI CC messages over the USB using @@ -176,7 +176,7 @@ void setup() { delay(1000); sos.clear(); - + } void loop() { @@ -186,35 +186,35 @@ void loop() { // Check if SW1 has been toggled (pushed) and trigger the gate // LED1 will be directly control by the SOS effect, not by BAPhysicalControls if (controls.isSwitchToggled(gateHandle)) { - sos.trigger(); - Serial.println("GATE OPEN is triggered"); + sos.trigger(); + if (Serial) { Serial.println("GATE OPEN is triggered"); } } // Use SW2 to clear out the SOS delayline controls.setOutput(led2Handle, controls.getSwitchValue(led2Handle)); if (controls.isSwitchToggled(clearHandle)) { sos.clear(); - Serial.println("GATE CLEAR is triggered"); + if (Serial) { Serial.println("GATE CLEAR is triggered"); } } // Use POT1 (left) to control the OPEN GATE time if (controls.checkPotValue(openHandle, potValue)) { // Pot has changed sos.gateOpenTime(potValue * MAX_GATE_TIME_MS); - Serial.println(String("New OPEN GATE setting (ms): ") + (potValue * MAX_GATE_TIME_MS)); + if (Serial) { Serial.println(String("New OPEN GATE setting (ms): ") + (potValue * MAX_GATE_TIME_MS)); } } // Use POT2 (right) to control the CLOSE GATE time if (controls.checkPotValue(closeHandle, potValue)) { // Pot has changed sos.gateCloseTime(potValue * MAX_GATE_TIME_MS); - Serial.println(String("New CLOSE GATE setting (ms): ") + (potValue * MAX_GATE_TIME_MS)); + if (Serial) { Serial.println(String("New CLOSE GATE setting (ms): ") + (potValue * MAX_GATE_TIME_MS)); } } // Use POT3 (centre) to control the sos effect volume if (controls.checkPotValue(volumeHandle, potValue)) { // Pot has changed - Serial.println(String("New SOS VOLUME setting: ") + potValue); + if (Serial) { Serial.println(String("New SOS VOLUME setting: ") + potValue); } sos.volume(potValue); } @@ -223,11 +223,11 @@ void loop() { if (Serial.available() > 0) { while (Serial.available()) { char key = Serial.read(); - if (key == 'u') { + if (key == 'u') { headphoneVolume = (headphoneVolume + 1) % MAX_HEADPHONE_VOL; Serial.println(String("Increasing HEADPHONE volume to ") + headphoneVolume); } - else if (key == 'd') { + else if (key == 'd') { headphoneVolume = (headphoneVolume - 1) % MAX_HEADPHONE_VOL; Serial.println(String("Decreasing HEADPHONE volume to ") + headphoneVolume); } @@ -235,14 +235,16 @@ void loop() { } } } - + delay(20); // Without some minimal delay here it will be difficult for the pots/switch changes to be detected. - + if (timer > 1000) { timer = 0; - Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); - Serial.print("% "); - Serial.print(" SOS: "); Serial.print(sos.processorUsage()); - Serial.println("%"); + if (Serial) { + Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); + Serial.print("% "); + Serial.print(" SOS: "); Serial.print(sos.processorUsage()); + Serial.println("%"); + } } } diff --git a/examples/Modulation/TemoloDemo/TemoloDemo.ino b/examples/Modulation/TemoloDemo/TemoloDemo.ino index a9f4097..810aea9 100644 --- a/examples/Modulation/TemoloDemo/TemoloDemo.ino +++ b/examples/Modulation/TemoloDemo/TemoloDemo.ino @@ -1,17 +1,17 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * This example demonstrates teh AudioEffectsTremolo effect. It can * be controlled using USB MIDI. You can get a free USB MIDI Controller - * appliation at + * appliation at * http://www.blackaddr.com/downloads/BAMidiTester/ * or the source code at * https://github.com/Blackaddr/BAMidiTester - * + * * Even if you don't control the guitar effect with USB MIDI, you must set * the Arduino IDE USB-Type under Tools to "Serial + MIDI" */ @@ -57,14 +57,16 @@ elapsedMillis timer; void OnControlChange(byte channel, byte control, byte value) { tremolo.processMidi(channel-1, control, value); #ifdef MIDI_DEBUG - Serial.print("Control Change, ch="); - Serial.print(channel, DEC); - Serial.print(", control="); - Serial.print(control, DEC); - Serial.print(", value="); - Serial.print(value, DEC); - Serial.println(); - #endif + if (Serial) { + Serial.print("Control Change, ch="); + Serial.print(channel, DEC); + Serial.print(", control="); + Serial.print(control, DEC); + Serial.print(", value="); + Serial.print(value, DEC); + Serial.println(); + } + #endif } void setup() { @@ -72,26 +74,24 @@ void setup() { TGA_PRO_MKII_REV1(); // Declare the version of the TGA Pro you are using. //TGA_PRO_REVB(x); //TGA_PRO_REVA(x); - + delay(100); Serial.begin(57600); // Start the serial port // Disable the codec first codec.disable(); - delay(100); AudioMemory(128); delay(5); // Enable the codec - Serial.println("Enabling codec...\n"); + if (Serial) { Serial.println("Enabling codec...\n"); } codec.enable(); - delay(100); // Setup MIDI MIDI.begin(MIDI_CHANNEL_OMNI); MIDI.setHandleControlChange(OnControlChange); usbMIDI.setHandleControlChange(OnControlChange); - + // Configure which MIDI CC's will control the effect parameters tremolo.mapMidiControl(AudioEffectTremolo::BYPASS,16); tremolo.mapMidiControl(AudioEffectTremolo::RATE,20); @@ -100,7 +100,7 @@ void setup() { // Besure to enable the tremolo. When disabled, audio is is completely blocked // to minimize resources to nearly zero. - tremolo.enable(); + tremolo.enable(); // Set some default values. // These can be changed by sending MIDI CC messages over the USB using @@ -121,10 +121,12 @@ void loop() { if (timer > 1000) { timer = 0; - Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); - Serial.print("% "); - Serial.print(" tremolo: "); Serial.print(tremolo.processorUsage()); - Serial.println("%"); + if (Serial) { + Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); + Serial.print("% "); + Serial.print(" tremolo: "); Serial.print(tremolo.processorUsage()); + Serial.println("%"); + } } MIDI.read(); diff --git a/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino b/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino index 3dcba7e..5915979 100644 --- a/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino +++ b/examples/Modulation/TremoloDemoExpansion/TremoloDemoExpansion.ino @@ -1,21 +1,21 @@ /************************************************************************* * This demo uses the BALibrary library to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * This example demonstrates teh BAAudioEffectsTremolo effect. It can * be controlled using the Blackaddr Audio "Expansion Control Board". - * + * * POT1 (left) controls the tremolo RATE * POT2 (right) controls the tremolo DEPTH * POT3 (center) controls the output VOLUME * SW1 will enable/bypass the audio effect. LED1 will be on when effect is enabled. * SW2 will cycle through the 3 pre-programmed waveforms. NOTE: any waveform other than Sine will cause * pops/clicks since the waveforms are not bandlimited. - * - * + * + * * Using the Serial Montitor, send 'u' and 'd' characters to increase or decrease * the headphone volume between values of 0 and 9. */ @@ -60,7 +60,7 @@ AudioConnection rightOut(tremolo,0, i2sOut, 1); // - LED2 (right) will illuminate when pressing SW2. ////////////////////////////////////////// // To get the calibration values for your particular board, first run the -// BAExpansionCalibrate.ino example and +// BAExpansionCalibrate.ino example and constexpr int potCalibMin = 1; constexpr int potCalibMax = 1018; constexpr bool potSwapDirection = true; @@ -82,7 +82,7 @@ void setup() { TGA_PRO_MKII_REV1(); // Declare the version of the TGA Pro you are using. //TGA_PRO_REVB(x); //TGA_PRO_REVA(x); - + delay(100); // wait a bit for serial to be available Serial.begin(57600); // Start the serial port delay(100); @@ -93,8 +93,8 @@ void setup() { waveformHandle = controls.addSwitch(BA_EXPAND_SW2_PIN); // will be used for stepping through filters // pots rateHandle = controls.addPot(BA_EXPAND_POT1_PIN, potCalibMin, potCalibMax, potSwapDirection); // control the amount of delay - depthHandle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); - volumeHandle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); + depthHandle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); + volumeHandle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); // leds led1Handle = controls.addOutput(BA_EXPAND_LED1_PIN); led2Handle = controls.addOutput(BA_EXPAND_LED2_PIN); // will illuminate when pressing SW2 @@ -104,18 +104,18 @@ void setup() { AudioMemory(128); // Enable and configure the codec - Serial.println("Enabling codec...\n"); + if (Serial) { Serial.println("Enabling codec...\n"); } codec.enable(); codec.setHeadphoneVolume(1.0f); // Max headphone volume - + // Besure to enable the tremolo. When disabled, audio is is completely blocked by the effect // to minimize resource usage to nearly to nearly zero. - tremolo.enable(); + tremolo.enable(); // Set some default values. // These can be changed using the controls on the Blackaddr Audio Expansion Board tremolo.bypass(false); - controls.setOutput(led1Handle, !tremolo.isBypass()); // Set the LED when NOT bypassed + controls.setOutput(led1Handle, !tremolo.isBypass()); // Set the LED when NOT bypassed tremolo.rate(0.0f); tremolo.depth(1.0f); @@ -140,8 +140,8 @@ void loop() { bool bypass = tremolo.isBypass(); // get the current state bypass = !bypass; // change it tremolo.bypass(bypass); // set the new state - controls.setOutput(led1Handle, !bypass); // Set the LED when NOT bypassed - Serial.println(String("BYPASS is ") + bypass); + controls.setOutput(led1Handle, !bypass); // Set the LED when NOT bypassed + if (Serial) { Serial.println(String("BYPASS is ") + bypass); } } // Use SW2 to cycle through the waveforms @@ -150,27 +150,27 @@ void loop() { waveformIndex = (waveformIndex + 1) % static_cast(Waveform::NUM_WAVEFORMS); // cast the index tremolo.setWaveform(static_cast(waveformIndex)); - Serial.println(String("Waveform set to ") + waveformIndex); + if (Serial) { Serial.println(String("Waveform set to ") + waveformIndex); } } // Use POT1 (left) to control the rate setting if (controls.checkPotValue(rateHandle, potValue)) { // Pot has changed - Serial.println(String("New RATE setting: ") + potValue); + if (Serial) { Serial.println(String("New RATE setting: ") + potValue); } tremolo.rate(potValue); } // Use POT2 (right) to control the depth setting if (controls.checkPotValue(depthHandle, potValue)) { // Pot has changed - Serial.println(String("New DEPTH setting: ") + potValue); + if (Serial) { Serial.println(String("New DEPTH setting: ") + potValue); } tremolo.depth(potValue); } // Use POT3 (centre) to control the volume setting if (controls.checkPotValue(volumeHandle, potValue)) { // Pot has changed - Serial.println(String("New VOLUME setting: ") + potValue); + if (Serial) { Serial.println(String("New VOLUME setting: ") + potValue); } tremolo.volume(potValue); } @@ -179,11 +179,11 @@ void loop() { if (Serial.available() > 0) { while (Serial.available()) { char key = Serial.read(); - if (key == 'u') { + if (key == 'u') { headphoneVolume = (headphoneVolume + 1) % MAX_HEADPHONE_VOL; Serial.println(String("Increasing HEADPHONE volume to ") + headphoneVolume); } - else if (key == 'd') { + else if (key == 'd') { headphoneVolume = (headphoneVolume - 1) % MAX_HEADPHONE_VOL; Serial.println(String("Decreasing HEADPHONE volume to ") + headphoneVolume); } @@ -193,13 +193,15 @@ void loop() { } delay(20); // Without some minimal delay here it will be difficult for the pots/switch changes to be detected. - + if (timer > 1000) { timer = 0; - Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); - Serial.print("% "); - Serial.print(" tremolo: "); Serial.print(tremolo.processorUsage()); - Serial.println("%"); + if (Serial) { + Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); + Serial.print("% "); + Serial.print(" tremolo: "); Serial.print(tremolo.processorUsage()); + Serial.println("%"); + } } } diff --git a/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino b/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino index 244a60e..6a2d6de 100644 --- a/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino +++ b/examples/Tests/DMA_MEM0_test/DMA_MEM0_test.ino @@ -72,7 +72,7 @@ void setup() { SPI_MEM0_1M(); SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(MemSelect::MEM0); - Serial.println("Enabling SPI, testing MEM0"); + Serial.printf("Enabling SPI, testing MEM0 up to addres %08X\n\r", SPI_MAX_ADDR); spiMem0.begin(); } diff --git a/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino b/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino index 17fc9ea..dac8d56 100644 --- a/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino +++ b/examples/Tests/DMA_MEM1_test/DMA_MEM1_test.ino @@ -1,16 +1,16 @@ /************************************************************************* * This demo uses the BALibrary to provide enhanced control of * the TGA Pro board. - * + * * The latest copy of the BALibrary can be obtained from * https://github.com/Blackaddr/BALibrary - * + * * This demo will perform a DMA memory test on MEM1 attached * to SPI1. - * + * * NOTE: SPI MEM1 can be used by a Teensy 3.5/3.6. * pins. - * + * */ #include #include "BALibrary.h" @@ -30,7 +30,6 @@ using namespace BALibrary; SPISettings memSettings(20000000, MSBFIRST, SPI_MODE0); const int cs0pin = SPI1_CS_PIN; -BAGpio gpio; // access to User LED BASpiMemoryDMA spiMem1(SpiDeviceId::SPI_DEVICE1); bool compareBuffers(uint8_t *a, uint8_t *b, size_t numBytes) @@ -61,37 +60,35 @@ void setup() { TGA_PRO_MKII_REV1(); // Declare the version of the TGA Pro you are using. //TGA_PRO_REVB(x); //TGA_PRO_REVA(x); - - gpio.begin(); Serial.begin(57600); while (!Serial) { yield(); } delay(5); - SPI_MEM1_1M(); + SPI_MEM1_64M(); SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(MemSelect::MEM1); - Serial.println("Enabling SPI, testing MEM1"); + Serial.printf("Enabling SPI, testing MEM1, max address %08X\n\r", SPI_MAX_ADDR); Serial.flush(); spiMem1.begin(); } bool spi8BitTest(void) { - + size_t spiAddress = 0; int spiPhase = 0; constexpr uint8_t MASK80 = 0xaa; constexpr uint8_t MASK81 = 0x55; - + uint8_t src8[DMA_SIZE]; uint8_t dest8[DMA_SIZE]; - + // Write to the memory using 8-bit transfers - Serial.println("\nStarting 8-bit test Write/Read"); + Serial.println("\nStarting 8-bit test Write/Read"); Serial.flush(); while (spiPhase < 4) { spiAddress = 0; while (spiAddress <= SPI_MAX_ADDR) { - + // fill the write data buffer switch (spiPhase) { case 0 : @@ -114,15 +111,15 @@ bool spi8BitTest(void) { src8[i] = ((spiAddress+i) & 0xff) ^ (!MASK81); } break; - } - + } + // Send the DMA transfer spiMem1.write(spiAddress, src8, DMA_SIZE); // wait until write is done while (spiMem1.isWriteBusy()) {} - spiAddress += DMA_SIZE; + spiAddress += DMA_SIZE; } - + // Read back the data using 8-bit transfers spiAddress = 0; while (spiAddress <= SPI_MAX_ADDR) { @@ -149,15 +146,15 @@ bool spi8BitTest(void) { } break; } - + // Read back the DMA data spiMem1.read(spiAddress, dest8, DMA_SIZE); // wait until read is done while (spiMem1.isReadBusy()) {} - if (!compareBuffers(src8, dest8, DMA_SIZE)) { + if (!compareBuffers(src8, dest8, DMA_SIZE)) { Serial.println(String("ERROR @") + spiAddress); - return false; } // stop the test - spiAddress += DMA_SIZE; + return false; } // stop the test + spiAddress += DMA_SIZE; } Serial.println(String("Phase ") + spiPhase + String(": 8-bit Write/Read test passed!")); spiPhase++; @@ -169,7 +166,7 @@ bool spi8BitTest(void) { } #endif - Serial.println("\nStarting 8-bit test Zero/Read"); + Serial.println("\nStarting 8-bit test Zero/Read"); Serial.flush(); // Clear the memory spiAddress = 0; memset(src8, 0, DMA_SIZE); @@ -178,7 +175,7 @@ bool spi8BitTest(void) { spiMem1.zero(spiAddress, DMA_SIZE); // wait until write is done while (spiMem1.isWriteBusy()) {} - spiAddress += DMA_SIZE; + spiAddress += DMA_SIZE; } // Check the memory is clear @@ -188,8 +185,8 @@ bool spi8BitTest(void) { spiMem1.read(spiAddress, dest8, DMA_SIZE); // wait until read is done while (spiMem1.isReadBusy()) {} - if (!compareBuffers(src8, dest8, DMA_SIZE)) { return false; } // stop the test - spiAddress += DMA_SIZE; + if (!compareBuffers(src8, dest8, DMA_SIZE)) { return false; } // stop the test + spiAddress += DMA_SIZE; } Serial.println(String(": 8-bit Zero/Read test passed!")); return true; @@ -201,16 +198,16 @@ bool spi16BitTest(void) { constexpr uint16_t MASK160 = 0xaaaa; constexpr uint16_t MASK161 = 0x5555; constexpr int NUM_DATA = DMA_SIZE / sizeof(uint16_t); - + uint16_t src16[NUM_DATA]; uint16_t dest16[NUM_DATA]; // Write to the memory using 16-bit transfers - Serial.println("\nStarting 16-bit test"); + Serial.println("\nStarting 16-bit test"); Serial.flush(); while (spiPhase < 4) { spiAddress = 0; while (spiAddress <= SPI_MAX_ADDR) { - + // fill the write data buffer switch (spiPhase) { case 0 : @@ -234,14 +231,14 @@ bool spi16BitTest(void) { } break; } - + // Send the DMA transfer spiMem1.write16(spiAddress, src16, NUM_DATA); // wait until write is done while (spiMem1.isWriteBusy()) {} - spiAddress += DMA_SIZE; + spiAddress += DMA_SIZE; } - + // Read back the data using 8-bit transfers spiAddress = 0; while (spiAddress <= SPI_MAX_ADDR) { @@ -268,15 +265,15 @@ bool spi16BitTest(void) { } break; } - + // Read back the DMA data spiMem1.read16(spiAddress, dest16, NUM_DATA); // wait until read is done while (spiMem1.isReadBusy()) {} - if (!compareBuffers16(src16, dest16, NUM_DATA)) { + if (!compareBuffers16(src16, dest16, NUM_DATA)) { Serial.print("ERROR @"); Serial.println(spiAddress, HEX); - return false; } // stop the test - spiAddress += DMA_SIZE; + return false; } // stop the test + spiAddress += DMA_SIZE; } Serial.println(String("Phase ") + spiPhase + String(": 16-bit test passed!")); spiPhase++; @@ -287,7 +284,7 @@ bool spi16BitTest(void) { } #endif - Serial.println("\nStarting 16-bit test Zero/Read"); + Serial.println("\nStarting 16-bit test Zero/Read"); Serial.flush(); // Clear the memory spiAddress = 0; memset(src16, 0, DMA_SIZE); @@ -296,7 +293,7 @@ bool spi16BitTest(void) { spiMem1.zero16(spiAddress, NUM_DATA); // wait until write is done while (spiMem1.isWriteBusy()) {} - spiAddress += DMA_SIZE; + spiAddress += DMA_SIZE; } // Check the memory is clear @@ -306,8 +303,8 @@ bool spi16BitTest(void) { spiMem1.read16(spiAddress, dest16, NUM_DATA); // wait until read is done while (spiMem1.isReadBusy()) {} - if (!compareBuffers16(src16, dest16, NUM_DATA)) { return false; } // stop the test - spiAddress += DMA_SIZE; + if (!compareBuffers16(src16, dest16, NUM_DATA)) { return false; } // stop the test + spiAddress += DMA_SIZE; } Serial.println(String(": 16-bit Zero/Read test passed!")); return true; diff --git a/examples/Tests/Multiverse_BasicDemo/DebugPrintf.h b/examples/Tests/Multiverse_BasicDemo/DebugPrintf.h new file mode 100644 index 0000000..59dfca9 --- /dev/null +++ b/examples/Tests/Multiverse_BasicDemo/DebugPrintf.h @@ -0,0 +1,9 @@ +#ifndef DEBUG_PRINTF_H_ +#define DEBUG_PRINTF_H_ + +// Make a safe call to Serial where it checks if the object is valid first. This allows your +// program to work even when no USB serial is connected. Printing to the Serial object when +// no valid connection is present will crash the CPU. +#define DEBUG_PRINT(x) {if (Serial) {x;}} + +#endif diff --git a/examples/Tests/Multiverse_BasicDemo/Multiverse_BasicDemo.ino b/examples/Tests/Multiverse_BasicDemo/Multiverse_BasicDemo.ino new file mode 100644 index 0000000..a57e523 --- /dev/null +++ b/examples/Tests/Multiverse_BasicDemo/Multiverse_BasicDemo.ino @@ -0,0 +1,285 @@ +/*********************************************************************************** + * MULTIVERSE DEMO + * + * This demo program shows how to use BALibrary to access the hardware + * features of the Aviate Audio Multiverse effects processor. + * + * The following are demonstrated in this programming using BALibrary: + * - WM8731 stereo audio codec in master mode (NOTE: not slave mode like TGA Pro + * - Interact with all physical controls + * - Control the 128x64 pixel OLED display (connected to SPI0) + * - Use the 8MB external SRAM (simple memory test) + * + * REQUIREMENTS: + * This demo for Multiverse uses its OLED display which requires several Arduino + * libraries be downloaded first. The SH1106 library is modifed to work with Teensy + * and must be downloaded from the AlgorhythmTechnologies github. + * + * Adafruit_BusIO : https://github.com/adafruit/Adafruit_BusIO + * Adafruit_GFX_Library : https://github.com/adafruit/Adafruit-GFX-Library + * Adafruit_SH1106 : https://github.com/AlgorhythmTechnologies/Adafruit_SH1106 + * + * + * USAGE INSTRUCTIONS + * - Use the 'Gain' knob to control the input gain on the codec. See checkPot(). + * - Use the 'Level' knob to control output volume with an AudioMixer4 object. + * - Stomp switches S1 and S2 will write status to display, and turn on LED + * - Encoder push-button switches will write status to display when pressed/released + * - Encoder rotary control will adjust a positive/negative count and update display + */ +#include +#include +#include "BALibrary.h" + +#include "DebugPrintf.h" +#include "PhysicalControls.h" + +using namespace BALibrary; + +// OLED display stuff +#include "Adafruit_SH1106.h" +#include "Adafruit_GFX.h" +#include "Fonts/FreeSansBold9pt7b.h" +constexpr unsigned SCREEN_WIDTH = 128; // OLED display width, in pixels +constexpr unsigned SCREEN_HEIGHT = 64; // OLED display height, in pixels +Adafruit_SH1106 display(37, 35, 10); + +// External SPI RAM +ExternalSramManager sramManager; +ExtMemSlot memSlot; +BASpiMemory spiMem1(SpiDeviceId::SPI_DEVICE1); +unsigned spiAddress = 0; +unsigned spiAddressMax; +unsigned sramStage = 0; // stage 0 is zero, 1 is write, 2 is read +volatile float sramCompletion = 0.0f; +volatile unsigned errorCount = 0; + +AudioInputI2Sslave i2sIn; +AudioOutputI2Sslave i2sOut; +AudioMixer4 volumeOut; + +// i2sIn --> volumeOut(Mixer) --> i2sOut +AudioConnection patchIn0(i2sIn, 0, volumeOut, 0); +AudioConnection patchIn1(i2sIn, 1, volumeOut, 1); +AudioConnection patchOut0(volumeOut,0, i2sOut, 0); +AudioConnection patchOut1(volumeOut,0, i2sOut, 1); + +BAAudioControlWM8731master codec; +elapsedMillis timer; + +// Create a control object using the number of switches, pots, encoders and outputs on the +// Multiverse pedal +BAPhysicalControls controls(6, 4, 4, 2); // (SW, POT, ENC, LED) + +unsigned loopCounter = 0; + +void drawProgressBar(float completion); // declaration + +void drawBlackaddrAudio() { + display.setCursor(0, 24); // (x,y) + display.printf(" Blackaddr"); + display.setCursor(0, 40); // (x,y) + display.printf(" Audio"); +} + +void setup() { + + codec.disable(); // this will reset the codec + + // wait up for the serial to appear for up to 1 second + Serial.begin(57600); + unsigned serialLoopCount = 10; + while (!Serial && (serialLoopCount > 0)) { + delay(100); + serialLoopCount--; + } + + MULTIVERSE(); // constants defined in BALibrary become valid only after this call + SPI_MEM1_64M(); // Declare the correct memory size + + // Init the display + display.begin(SH1106_SWITCHCAPVCC, SH1106_I2C_ADDRESS, true); + display.clearDisplay(); + display.display(); + display.setTextColor(WHITE); // Draw white text + display.setFont(&FreeSansBold9pt7b); + drawBlackaddrAudio(); + display.display(); + + configPhysicalControls(&controls, &codec); + + // Request a memory slot from the external RAM + size_t numBytes = BAHardwareConfig.getSpiMemSizeBytes(MemSelect::MEM1); + spiAddressMax = BAHardwareConfig.getSpiMemMaxAddr(1)/4; // test the first 25% of memory + bool success = sramManager.requestMemory(&memSlot, numBytes, MemSelect::MEM1, /* no DMA */ false); + if (!success && Serial) { printf("Request for memory slot failed\n\r"); } + + // Allocated audio buffers and enable codec + AudioMemory(64); + codec.enable(); + delay(100); + + // Mixer at full volume + volumeOut.gain(0,1.0f); + volumeOut.gain(1,1.0f); + + // flush the pot filters. The analog measurement of the analog pots is averaged (filtered) + // over time, so at startup you will see a bunch of false changes detected as the filter + // settles. We can force this with a few dozen repeated calls. + for (unsigned i=0; i < 50; i++) { + float potValue; + for (unsigned j=0; j < BA_EXPAND_NUM_POT; j++) { + controls.checkPotValue(j, potValue); + } + delay(10); + } +} + +void loop() { + + // Check all the physical controls for updates + checkPot(0); + checkPot(1); + checkPot(2); + checkPot(3); + + checkSwitch(0); + checkSwitch(1); + checkSwitch(2); + checkSwitch(3); + checkSwitch(4); + checkSwitch(5); + + checkEncoder(0); + checkEncoder(1); + checkEncoder(2); + checkEncoder(3); + + // If the SRAM test is not complete, run the next block + if (sramCompletion < 1.0f) { + nextSpiMemTestBlock(); + } + + // Adjusting one of the knobs/switches will result in its value being display for + // 2 seconds in the check*() functions. + if (timer > 2000) { + loopCounter++; + display.clearDisplay(); + drawBlackaddrAudio(); + drawSramProgress(sramCompletion); + display.display(); + } +} + +// This function will draw on the display which stage the memory test is in, and +// the percentage complete for that stage. +void drawSramProgress(float completion) +{ + if (errorCount > 0) { // If errors, print the error count + display.setCursor(0, SCREEN_HEIGHT-1); + display.printf("Errors: %d", errorCount); + return; + } + + // Draw the SRAM test progress at the bottom of the screen + display.setCursor(0, SCREEN_HEIGHT-1); + switch(sramStage) { + case 0 : display.printf("0 mem:"); break; + case 1 : display.printf("0 chk:"); break; + case 2 : display.printf("wr mem:"); break; + case 3 : display.printf("rd mem:"); break; + case 4 : // same as default + default: display.printf("Done"); break; + } + display.setCursor(SCREEN_WIDTH*0.63f, SCREEN_HEIGHT-1); // position to lower right corner + display.printf("%0.f%%", 100.0f * completion); +} + +// Create a predictable data pattern based on address. +constexpr int mask0 = 0x5555; +constexpr int mask1 = 0xaaaa; +int calcNextData(int spiAddress, int loopPhase, int maskPhase) +{ + int data; + + int phase = ((loopPhase << 1) + maskPhase) & 0x3; + switch(phase) + { + case 0 : + data = spiAddress ^ mask0; + break; + case 1: + data = spiAddress ^ mask1; + break; + case 2: + data = ~spiAddress ^ mask0; + break; + case 3: + data = ~spiAddress ^ mask1; + + } + return (data & 0xffff); +} + +// Process the next block of data in the memory test +void nextSpiMemTestBlock() +{ + constexpr unsigned BLOCK_SIZE_BYTES = 256; // transfer 256 bytes (arbitrary) per transaction + constexpr unsigned NUM_BLOCK_WORDS = BLOCK_SIZE_BYTES; + static uint8_t buffer[BLOCK_SIZE_BYTES]; + static int16_t buffer16a[NUM_BLOCK_WORDS]; + static int16_t buffer16b[NUM_BLOCK_WORDS]; + static int maskPhase = 0; + + if (sramStage == 0) { // Zero write + // zero the memory + while (spiMem1.isWriteBusy()) {} // wait for DMA write to complete + memSlot.zero(spiAddress, BLOCK_SIZE_BYTES); + spiAddress += BLOCK_SIZE_BYTES; + + } else if (sramStage == 1) { // Zero check + memSlot.read(spiAddress, buffer, BLOCK_SIZE_BYTES); + while (spiMem1.isReadBusy()) {} // wait for DMA read results + for (unsigned i=0; i < BLOCK_SIZE_BYTES; i++) { + if (buffer[i] != 0) { errorCount++; } + } + spiAddress += BLOCK_SIZE_BYTES; + + } + else if (sramStage == 2) { // write test + // Calculate the data for a block + for (unsigned i=0; i spiAddressMax && sramStage < 4) { + spiAddress = 0; sramStage++; sramCompletion = 0.0f; + return; + } + + sramCompletion = (float)spiAddress / (float)spiAddressMax ; +} diff --git a/examples/Tests/Multiverse_BasicDemo/PhysicalControls.cpp b/examples/Tests/Multiverse_BasicDemo/PhysicalControls.cpp new file mode 100644 index 0000000..887b806 --- /dev/null +++ b/examples/Tests/Multiverse_BasicDemo/PhysicalControls.cpp @@ -0,0 +1,222 @@ +#include +#include "Adafruit_SH1106.h" +#include "BALibrary.h" +#include "DebugPrintf.h" + +using namespace BALibrary; + +// Declare the externally shared variables from the main .ino +extern Adafruit_SH1106 display; +extern BAAudioControlWM8731master codec; +extern AudioMixer4 volumeOut; +extern elapsedMillis timer; + +constexpr int displayRow = 36; // Row to start OLED display updates on +constexpr int potCalibMin = 8; +constexpr int potCalibMax = 1016; +constexpr bool potSwapDirection = true; +constexpr bool encSwapDirection = true; +int pot1Handle= -1, pot2Handle = -1, pot3Handle = -1, pot4Handle = -1; +int sw1Handle = -1, sw2Handle = -1, sw3Handle = -1, sw4Handle = -1, sw5Handle = -1, sw6Handle = -1; +int enc1Handle = -1, enc2Handle = -1, enc3Handle = -1, enc4Handle = -1; +int led1Handle = -1, led2Handle = -1; + +BAAudioControlWM8731master *codecPtr = nullptr; +BAPhysicalControls *controlPtr = nullptr; + +// Configure and setup the physical controls +void configPhysicalControls(BAPhysicalControls* controls, BAAudioControlWM8731master* codec) +{ + // Setup the controls. The return value is the handle to use when checking for control changes, etc. + controlPtr = controls; + codecPtr = codec; + + if (!controlPtr) { DEBUG_PRINT(Serial.printf("ERROR: controlPtr is invalid\n\r")); return; } + if (!codecPtr) { DEBUG_PRINT(Serial.printf("ERROR: codecPtr is invalid\n\r")); return; } + + // pushbuttons + sw1Handle = controlPtr->addSwitch(BA_EXPAND_SW1_PIN); + sw2Handle = controlPtr->addSwitch(BA_EXPAND_SW2_PIN); + sw3Handle = controlPtr->addSwitch(BA_EXPAND_SW3_PIN); + sw4Handle = controlPtr->addSwitch(BA_EXPAND_SW4_PIN); + sw5Handle = controlPtr->addSwitch(BA_EXPAND_SW5_PIN); + sw6Handle = controlPtr->addSwitch(BA_EXPAND_SW6_PIN); + // pots + pot1Handle = controlPtr->addPot(BA_EXPAND_POT1_PIN, potCalibMin, potCalibMax, potSwapDirection); + pot2Handle = controlPtr->addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); + pot3Handle = controlPtr->addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); + pot4Handle = controlPtr->addPot(BA_EXPAND_POT4_PIN, potCalibMin, potCalibMax, potSwapDirection); + + // encoders + enc1Handle = controlPtr->addRotary(BA_EXPAND_ENC1_A_PIN, BA_EXPAND_ENC1_B_PIN, encSwapDirection); + enc2Handle = controlPtr->addRotary(BA_EXPAND_ENC2_A_PIN, BA_EXPAND_ENC2_B_PIN, encSwapDirection); + enc3Handle = controlPtr->addRotary(BA_EXPAND_ENC3_A_PIN, BA_EXPAND_ENC3_B_PIN, encSwapDirection); + enc4Handle = controlPtr->addRotary(BA_EXPAND_ENC4_A_PIN, BA_EXPAND_ENC4_B_PIN, encSwapDirection); + + // leds + led1Handle = controlPtr->addOutput(BA_EXPAND_LED1_PIN); + led2Handle = controlPtr->addOutput(BA_EXPAND_LED2_PIN); // will illuminate when pressing SW2 + +} + +void checkPot(unsigned id) +{ + float potValue; + unsigned handle; + switch(id) { + case 0 : + handle = pot1Handle; + break; + case 1 : + handle = pot2Handle; + break; + case 2 : + handle = pot3Handle; + break; + case 3 : + handle = pot4Handle; + break; + default : + handle = pot1Handle; + } + + if ((handle < 0) || (handle >= controlPtr->getNumPots())) { + DEBUG_PRINT(Serial.printf("ILLEGAL POT HANDLE: %d for id %d\n\r", handle, id)); + return; + } + + if (controlPtr->checkPotValue(handle, potValue)) { + // Pot has changed + DEBUG_PRINT(Serial.println(String("POT") + id + String(" value: ") + potValue)); + + timer = 0; + display.clearDisplay(); + display.setCursor(0,displayRow); + switch(id) { + case 0 : + { + display.printf("Gain: %0.f\n", potValue * 100.0f); + int gain = static_cast(std::roundf(31.0f * potValue)); + codecPtr->setLeftInputGain(gain); + codecPtr->setRightInputGain(gain); + yield(); // give time for i2C transfers to complete + break; + } + case 1 : + { + display.printf("Level: %0.f\n", potValue * 100.0f); + volumeOut.gain(0, potValue); + volumeOut.gain(1, potValue); + break; + } + case 2 : display.printf("Exp T: %0.f\n", potValue * 100.0f); break; + case 3 : display.printf("Exp R: %0.f\n", potValue * 100.0f); break; + } + display.display(); + } + +} + +int checkSwitch(unsigned id, bool getValueOnly=false) +{ + unsigned swHandle = -1; + unsigned ledHandle = -1; + switch(id) { + case 0 : + swHandle = sw1Handle; + ledHandle = led1Handle; + break; + case 1 : + swHandle = sw2Handle; + ledHandle = led2Handle; + break; + case 2 : + swHandle = sw3Handle; + break; + case 3 : + swHandle = sw4Handle; + break; + case 4 : + swHandle = sw5Handle; + break; + case 5 : + swHandle = sw6Handle; + break; + default : + swHandle = sw1Handle; + ledHandle = led1Handle; + } + + if ((swHandle < 0) || (swHandle >= controlPtr->getNumSwitches())) { + DEBUG_PRINT(Serial.printf("ILLEGAL SWITCH HANDLE: %d for id %d\n\r", swHandle, id); Serial.flush()); + return -1; + } + + bool switchValue; + bool changed = controlPtr->hasSwitchChanged(swHandle, switchValue); + if (getValueOnly) { return controlPtr->getSwitchValue(swHandle); } + + if (changed) { + DEBUG_PRINT(Serial.println(String("Button ") + id + String(" pressed"))); + timer = 0; + display.clearDisplay(); + display.setCursor(0, displayRow); + switch(id) { + case 0 : display.printf("S1: %d\n", switchValue); break; + case 1 : display.printf("S2: %d\n", switchValue); break; + case 2 : display.printf("EncSw A: %d\n", switchValue); break; + case 3 : display.printf("EncSw B: %d\n", switchValue); break; + case 4 : display.printf("EncSw C: %d\n", switchValue); break; + case 5 : display.printf("EncSw D: %d\n", switchValue); break; + } + display.display(); + } + + if (swHandle < 2) { // these SWs map to LEDs + bool pressed = controlPtr->isSwitchHeld(swHandle); + controlPtr->setOutput(ledHandle, pressed); + } + return controlPtr->getSwitchValue(swHandle); +} + +void checkEncoder(unsigned id) +{ + unsigned encHandle; + static int enc1 = 0, enc2 = 0, enc3 = 0, enc4 = 0; + switch(id) { + case 0 : + encHandle = enc1Handle; + break; + case 1 : + encHandle = enc2Handle; + break; + case 2 : + encHandle = enc3Handle; + break; + case 3 : + encHandle = enc4Handle; + break; + default : + encHandle = enc1Handle; + } + + if ((encHandle < 0) || (encHandle >= controlPtr->getNumRotary())) { + DEBUG_PRINT(Serial.printf("ILLEGAL ENCODER HANDLE: %d for id %d\n\r", encHandle, id); Serial.flush()); + return; + } + + int adj= controlPtr->getRotaryAdjustUnit(encHandle); + if (adj != 0) { + DEBUG_PRINT(Serial.printf("Enc %d: %d\n\r", id, adj); Serial.flush()); + display.clearDisplay(); + display.setCursor(0, displayRow); + switch(id) { + case 0 : enc1 += adj; display.printf("Enc A: %d", enc1); break; + case 1 : enc2 += adj; display.printf("Enc B: %d", enc2); break; + case 2 : enc3 += adj; display.printf("Enc C: %d", enc3); break; + case 3 : enc4 += adj; display.printf("Enc D: %d", enc4); break; + } + display.display(); + timer = 0; + } +} diff --git a/examples/Tests/Multiverse_BasicDemo/PhysicalControls.h b/examples/Tests/Multiverse_BasicDemo/PhysicalControls.h new file mode 100644 index 0000000..e496388 --- /dev/null +++ b/examples/Tests/Multiverse_BasicDemo/PhysicalControls.h @@ -0,0 +1,11 @@ +#ifndef PHYSICAL_CONTROLS_H_ +#define PHYSICAL_CONTROLS_H_ + +#include "BALibrary.h" + +void configPhysicalControls(BALibrary::BAPhysicalControls* controls, BALibrary::BAAudioControlWM8731master* codec); +void checkPot(unsigned id); +int checkSwitch(unsigned id, bool getValueOnly=false); +void checkEncoder(unsigned id); + +#endif diff --git a/examples/Tests/TGA_PRO_Basic_Test/PhysicalControls.cpp b/examples/Tests/TGA_PRO_Basic_Test/PhysicalControls.cpp index 913587a..c2a1506 100644 --- a/examples/Tests/TGA_PRO_Basic_Test/PhysicalControls.cpp +++ b/examples/Tests/TGA_PRO_Basic_Test/PhysicalControls.cpp @@ -12,14 +12,14 @@ BAPhysicalControls *controlPtr = nullptr; void configPhysicalControls(BAPhysicalControls &controls, BAAudioControlWM8731 &codec) { // Setup the controls. The return value is the handle to use when checking for control changes, etc. - + // pushbuttons sw1Handle = controls.addSwitch(BA_EXPAND_SW1_PIN); sw2Handle = controls.addSwitch(BA_EXPAND_SW2_PIN); // pots pot1Handle = controls.addPot(BA_EXPAND_POT1_PIN, potCalibMin, potCalibMax, potSwapDirection); - pot2Handle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); - pot3Handle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); + pot2Handle = controls.addPot(BA_EXPAND_POT2_PIN, potCalibMin, potCalibMax, potSwapDirection); + pot3Handle = controls.addPot(BA_EXPAND_POT3_PIN, potCalibMin, potCalibMax, potSwapDirection); // leds led1Handle = controls.addOutput(BA_EXPAND_LED1_PIN); led2Handle = controls.addOutput(BA_EXPAND_LED2_PIN); // will illuminate when pressing SW2 @@ -45,12 +45,12 @@ void checkPot(unsigned id) default : handle = pot1Handle; } - + if (controlPtr->checkPotValue(handle, potValue)) { // Pot has changed codecPtr->setHeadphoneVolume(potValue); - Serial.println(String("POT") + id + String(" value: ") + potValue); - } + if (Serial) { Serial.println(String("POT") + id + String(" value: ") + potValue); } + } } void checkSwitch(unsigned id) @@ -72,7 +72,7 @@ void checkSwitch(unsigned id) } if (controlPtr->isSwitchToggled(swHandle)) { - Serial.println(String("Button ") + id + String(" pressed")); + if (Serial) { Serial.println(String("Button ") + id + String(" pressed")); } } bool pressed = controlPtr->isSwitchHeld(swHandle); diff --git a/examples/Tests/TGA_PRO_Basic_Test/TGA_PRO_Basic_Test.ino b/examples/Tests/TGA_PRO_Basic_Test/TGA_PRO_Basic_Test.ino index 930ae28..f15469d 100644 --- a/examples/Tests/TGA_PRO_Basic_Test/TGA_PRO_Basic_Test.ino +++ b/examples/Tests/TGA_PRO_Basic_Test/TGA_PRO_Basic_Test.ino @@ -1,44 +1,44 @@ /************************************************************************* * This demo is used for manufacturing testing on the TGA Pro Expansion * Control Board. - * + * * This will test the following on the TGA Pro: - * + * * - Audio INPUT and OUTPUT JACKS * - Midi INPUT and Midi OUTPUT jacks * - MEM0 (if installed) * - User LED - * + * * This will also test the Expansion Control Board (if installed): - * + * * - three POT knobs * - two pushbutton SWitches * - two LEDs * - headphone output - * + * * SETUP INSTRUCTIONS: - * + * * 1) Connect an audio source to AUDIO INPUT. * 2) Connect AUDIO OUTPUT to amp, stereo, headphone amplifier, etc. * 3) if testing the MIDI ports, connect a MIDI cable between MIDI INPUT and MIDI OUTPUT * 4) comment out any tests you want to skip * 5) Compile and run the demo on your Teensy with TGA Pro. * 6) Launch the Arduino Serial Monitor to see results. - * + * * TESTING INSTRUCTIONS: - * + * * 1) Check the Serial Monitor for the results of the MIDI testing, and external memory testing. * 2) Confirm that the audio sent to the INPUT is coming out the OUTPUT. * 3) Confirm the User LED is blinking every 1 or 2 seconds - * + * * If using the Expansion Control Board: - * + * * 1) Try pushing the pushbuttons. When pushed, they should turn on their corresponding LED. * 2) Try turn each of the knobs one at a time. They should adjust the volume. - * + * * The latest copy of the BA Guitar library can be obtained from * https://github.com/Blackaddr/BALibrary - * + * */ //#define RUN_MIDI_TEST // Uncomment this line to run a MIDI test. You must connect a MIDI cable as a loopback between the MIDI input and output jacks. @@ -93,7 +93,6 @@ void setup() { gpio.begin(); Serial.begin(57600); - //while (!Serial) { yield(); } delay(500); // Disable the audio codec first @@ -104,20 +103,20 @@ void setup() { codec.setHeadphoneVolume(0.8f); // Set headphone volume #if defined(RUN_EXP_TEST) configPhysicalControls(controls, codec); - Serial.println("Now monitoring for input from Expansion Control Board"); + if (Serial) { Serial.println("Now monitoring for input from Expansion Control Board"); } #endif // Run the initial Midi connectivity and SPI memory tests. #if defined(RUN_MIDI_TEST) - if (uartTest()) { Serial.println("MIDI Ports testing PASSED!"); } + if (uartTest()) { if (Serial) Serial.println("MIDI Ports testing PASSED!"); } #endif #if defined(RUN_MEMO_TEST) SPI_MEM0_64M(); // declare the 64Mbit optional PSI memory //SPI_MEM0_4M(); // REVB and REVA came with 4M or 1M - // SPI_MEM0_1M(); + // SPI_MEM0_1M(); spiMem0.begin(); delay(10); - if (spiTest(&spiMem0, 0)) { Serial.println("SPI0 testing PASSED!");} + if (spiTest(&spiMem0, 0)) { if (Serial) Serial.println("SPI0 testing PASSED!");} #endif } @@ -132,7 +131,7 @@ void loop() { #endif delay(20); // Without some minimal delay here it will be difficult for the pots/switch changes to be detected. - + loopCounter++; if (timer > 1000) { timer = 0; diff --git a/examples/Tests/TGA_PRO_Basic_Test/UartTest.cpp b/examples/Tests/TGA_PRO_Basic_Test/UartTest.cpp index 3ae3953..023cbd0 100644 --- a/examples/Tests/TGA_PRO_Basic_Test/UartTest.cpp +++ b/examples/Tests/TGA_PRO_Basic_Test/UartTest.cpp @@ -4,7 +4,7 @@ using namespace BALibrary; constexpr unsigned MIDI_RATE = 31250; -constexpr unsigned HIGH_RATE = 230400; +constexpr unsigned HIGH_RATE = 230400; constexpr unsigned TEST_TIME = 5; // 5 second test each static unsigned baudRate = MIDI_RATE; // start with low speed @@ -19,14 +19,15 @@ bool uartTest(void) { Serial1.begin(baudRate, SERIAL_8N1); delay(100); - while(!Serial) {} + if (!Serial) { return false; } // skip uart test if Serial not connected + Serial.println(String("\nRunning MIDI Port speed test at ") + baudRate); // write the first data Serial1.write(writeData); while(!testFailed && !testDone) { - + if (loopCounter >= (baudRate/4)) { // the divisor determines how long the test runs for // next test switch (testPhase) { @@ -38,13 +39,13 @@ bool uartTest(void) } if (errorCount == 0) { Serial.println("TEST PASSED!"); } - else { + else { Serial.println("MIDI PORT TEST FAILED!"); } errorCount = 0; testPhase++; loopCounter = 0; - + if (!testDone) { Serial.println(String("\nRunning MIDI Port speed test at ") + baudRate); Serial1.begin(baudRate, SERIAL_8N1); @@ -53,24 +54,24 @@ bool uartTest(void) Serial.println("MIDI PORT TEST DONE!\n"); } } - + // Wait for read data - if (Serial1.available()) { + if (Serial1.available()) { uint8_t readData= Serial1.read(); if (readData != writeData) { Serial.println(String("MIDI ERROR: readData = ") + readData + String(" writeData = ") + writeData); errorCount++; } - + if ((loopCounter % (baudRate/64)) == 0) { // the divisor determines how often the period is printed Serial.print("."); Serial.flush(); } - + if (errorCount > 16) { Serial.println("Halting test"); testFailed = true; } - + loopCounter++; writeData++; Serial1.write(writeData); diff --git a/examples/Tests/TGA_PRO_Basic_Test/spiTest.cpp b/examples/Tests/TGA_PRO_Basic_Test/spiTest.cpp index cd6475d..dc7fb88 100644 --- a/examples/Tests/TGA_PRO_Basic_Test/spiTest.cpp +++ b/examples/Tests/TGA_PRO_Basic_Test/spiTest.cpp @@ -32,13 +32,14 @@ int calcData(int spiAddress, int loopPhase, int maskPhase) break; case 3: data = ~spiAddress ^ mask1; - + } return (data & 0xffff); } bool spiTest(BASpiMemory *mem, int id) { + if (!Serial) { return false; } // Skip test if Serial not connected int spiAddress = 0; int spiErrorCount = 0; @@ -47,7 +48,7 @@ bool spiTest(BASpiMemory *mem, int id) uint16_t memBlock[NUM_BLOCK_WORDS]; uint16_t goldData[NUM_BLOCK_WORDS]; - SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(0); // assume for this test both memories are the same size so use MEM0 + SPI_MAX_ADDR = BAHardwareConfig.getSpiMemMaxAddr(MemSelect::MEM0); // assume for this test both memories are the same size so use MEM0 const size_t SPI_MEM_SIZE_BYTES = BAHardwareConfig.getSpiMemSizeBytes(id); Serial.println(String("Starting SPI MEM Test of ") + SPI_MEM_SIZE_BYTES + String(" bytes")); @@ -55,9 +56,9 @@ bool spiTest(BASpiMemory *mem, int id) for (int cnt = 0; cnt < NUM_TESTS; cnt++) { // Zero check - mem->zero16(0, SPI_MEM_SIZE_BYTES / sizeof(uint16_t)); + mem->zero16(0, SPI_MEM_SIZE_BYTES / sizeof(uint16_t)); while (mem->isWriteBusy()) {} - + for (spiAddress = 0; spiAddress <= SPI_MAX_ADDR; spiAddress += NUM_BLOCK_WORDS*sizeof(uint16_t)) { mem->read16(spiAddress, memBlock, NUM_BLOCK_WORDS); while (mem->isReadBusy()) {} @@ -69,15 +70,20 @@ bool spiTest(BASpiMemory *mem, int id) } if (spiErrorCount >= 10) break; } - - //if (spiErrorCount == 0) { Serial.println(String("SPI MEMORY(") + cnt + String("): Zero test PASSED!")); } + + if (spiErrorCount == 0) { Serial.println(String("SPI MEMORY(") + cnt + String("): Zero test PASSED!")); } if (spiErrorCount == 0) { Serial.print("."); Serial.flush(); } - if (spiErrorCount > 0) { Serial.println(String("SPI MEMORY(") + cnt + String("): Zero test FAILED, error count = ") + spiErrorCount); return false;} - + if (spiErrorCount > 0) { + //Serial.println(String("SPI MEMORY(") + cnt + String("): Zero test FAILED, error count = ") + spiErrorCount); return false; + Serial.printf("SPI MEMORY: test %d Zero test FAILED, error count:%d, final address:0x%08X\n\r", + cnt, spiErrorCount, spiAddress); + return false; + } + // Write all test data to the memory maskPhase = 0; - for (spiAddress = 0; spiAddress <= SPI_MAX_ADDR; spiAddress += NUM_BLOCK_WORDS*sizeof(uint16_t)) { + for (spiAddress = 0; spiAddress <= SPI_MAX_ADDR; spiAddress += NUM_BLOCK_WORDS*sizeof(uint16_t)) { // Calculate the data for a block for (int i=0; iread16(spiAddress, memBlock, NUM_BLOCK_WORDS); + + mem->read16(spiAddress, memBlock, NUM_BLOCK_WORDS); // Calculate the golden data for a block for (int i=0; i 0) ) { // overflow - Serial.println("RingBuffer::push_back: overflow"); + if (Serial) { Serial.println("RingBuffer::push_back: overflow"); } return -1; } @@ -73,7 +73,7 @@ public: if (m_size == 0) { // buffer is empty - //Serial.println("RingBuffer::pop_front: buffer is empty\n"); + // if (Serial) { Serial.println("RingBuffer::pop_front: buffer is empty\n"); } return -1; } if (m_tail < m_maxSize-1) { @@ -82,7 +82,7 @@ public: m_tail = 0; } m_size--; - //Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size); + // if (Serial) { Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size); } return 0; } @@ -141,8 +141,10 @@ public: /// DEBUG: Prints the status of the Ringbuffer. NOte using this much printing will usually cause audio glitches void print() const { for (int idx=0; idxdata, HEX); + if (Serial) { + Serial.print(idx + String(" address: ")); Serial.print((uint32_t)m_buffer[idx], HEX); + Serial.print(" data: "); Serial.println((uint32_t)m_buffer[idx]->data, HEX); + } } } private: diff --git a/src/DmaSpi.h b/src/DmaSpi.h index e7b576e..d895976 100644 --- a/src/DmaSpi.h +++ b/src/DmaSpi.h @@ -58,8 +58,8 @@ class DummyChipSelect : public AbstractChipSelect **/ class DebugChipSelect : public AbstractChipSelect { - void select(TransferType transferType = TransferType::NORMAL) override {Serial.println("Debug CS: select()");} - void deselect(TransferType transferType = TransferType::NORMAL) override {Serial.println("Debug CS: deselect()");} + void select(TransferType transferType = TransferType::NORMAL) override { if (Serial) Serial.println("Debug CS: select()");} + void deselect(TransferType transferType = TransferType::NORMAL) override { if (Serial) Serial.println("Debug CS: deselect()");} }; /** \brief An active low chip select class. This also configures the given pin. @@ -114,7 +114,7 @@ class ActiveLowChipSelect : public AbstractChipSelect }; -#if defined(__MK66FX1M0__) +#if defined(__MK66FX1M0__) || (defined(__IMXRT1062__) && (defined(ARDUINO_TEENSY_MICROMOD) || defined(ARDUINO_TEENSY41))) class ActiveLowChipSelect1 : public AbstractChipSelect { public: @@ -154,12 +154,12 @@ class ActiveLowChipSelect1 : public AbstractChipSelect const SPISettings settings_; }; -#endif +#endif // defined(__MK66FX1M0__) || (defined(__IMXRT1062__) && defined(ARDUINO_TEENSY_MICROMOD)) #if defined(DEBUG_DMASPI) - #define DMASPI_PRINT(x) do {Serial.printf x ; Serial.flush();} while (0); + #define DMASPI_PRINT(x) do { if (Serial) { Serial.printf x ; Serial.flush();} } while (0); #else #define DMASPI_PRINT(x) do {} while (0); #endif @@ -712,15 +712,17 @@ typename AbstractDmaSpi::Transfer* volatile Ab template volatile uint8_t AbstractDmaSpi::m_devNull = 0; -//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(); -//} +// void dump_dma(DMAChannel *dmabc) +// { +// if (Serial) { +// 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 @@ -764,37 +766,8 @@ public: 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(); @@ -810,23 +783,76 @@ public: 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; + +#if (defined(__IMXRT1062__) && (defined(ARDUINO_TEENSY_MICROMOD) || defined (ARDUINO_TEENSY41))) +// On T4.X, SPI1 is LPSPI3 + +class DmaSpi1 : public AbstractDmaSpi +{ +public: + static void begin_setup_txChannel_impl() + { + txChannel_()->disable(); + txChannel_()->destination((volatile uint8_t&)IMXRT_LPSPI3_S.TDR); + txChannel_()->disableOnCompletion(); + txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI3_TX); + } + + static void begin_setup_rxChannel_impl() + { + rxChannel_()->disable(); + rxChannel_()->source((volatile uint8_t&)IMXRT_LPSPI3_S.RDR); // POPR is the receive fifo register for the SPI + rxChannel_()->disableOnCompletion(); + rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI3_RX); // The DMA RX id for MT66 is 14 + rxChannel_()->attachInterrupt(rxIsr_); + rxChannel_()->interruptAtCompletion(); + + } + + static void pre_cs_impl() + { + if (LPSPI3_SR & 0x1800) { + DMASPI_PRINT(("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ERROR SR reg is %08X\n\r", LPSPI3_SR)); + } + DMASPI_PRINT(("********************************************CHECK SR reg is %08X\n\r", LPSPI3_SR)); + + IMXRT_LPSPI3_S.TCR = (IMXRT_LPSPI3_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7); + IMXRT_LPSPI3_S.FCR = 0; + + IMXRT_LPSPI3_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_LPSPI3_S.DER = LPSPI_DER_TDDE | LPSPI_DER_RDDE; //enable DMA on both TX and RX + IMXRT_LPSPI3_S.SR = 0x3f00; // clear out all of the other status... + + } + + static void post_cs_impl() + { + rxChannel_()->enable(); + txChannel_()->enable(); + DMASPI_PRINT(("Done post_cs_impl()\n\r")); + } + + static void post_finishCurrentTransfer_impl() + { + IMXRT_LPSPI3_S.FCR = LPSPI_FCR_TXWATER(15); // _spi_fcr_save; // restore the FSR status... + IMXRT_LPSPI3_S.DER = 0; // DMA no longer doing TX (or RX) + + IMXRT_LPSPI3_S.CR = LPSPI_CR_MEN | LPSPI_CR_RRF | LPSPI_CR_RTF; // actually clear both... + IMXRT_LPSPI3_S.SR = 0x3f00; // clear out all of the other status... + } private: }; +extern DmaSpi1 DMASPI1; -extern DmaSpi0 DMASPI0; +#endif // (defined(__IMXRT1062__) && defined(ARDUINO_TEENSY_MICROMOD)) #elif defined(KINETISK) @@ -1050,7 +1076,7 @@ public: // { // DMASPI_PRINT(("%s: %x %x %x %x \n", sz, p[0], p[1], p[2], p[3])); // } - + static void post_cs_impl() { DMASPI_PRINT(("post_cs S C1 C2: %x %x %x\n", SPI1_S, SPI1_C1, SPI1_C2)); diff --git a/src/LibMemoryManagement.h b/src/LibMemoryManagement.h index 4d049b3..33ff7df 100644 --- a/src/LibMemoryManagement.h +++ b/src/LibMemoryManagement.h @@ -80,6 +80,55 @@ public: /// @returns the read position value size_t getReadPosition() const { return m_currentRdPosition-m_start; } + /* Byte-based transfers */ + + /// Write a block of zeros (8-bit) to the memory at the specified offset + /// @param offsetBytes offset in 8-bit bytes from start of slot + /// @param numBytes number of 8-bit bytes to transfer + /// @returns true on success, else false on error + bool zero(size_t offsetBytes, size_t numBytes); + + /// Write a block of 8-bit data to the memory at the specified offset + /// @param offsetBytes offset in 8-bit bytes from start of slot + /// @param src pointer to start of block of 16-bit data + /// @param numBytes number of 8-bit bytes to transfer + /// @returns true on success, else false on error + bool write(size_t offsetBytes, uint8_t *src, size_t numBytes); + + /// Read a block of 8-bit data from the memory at the specified location + /// @param offsetBytes offset in 8-bit bytes from start of slot + /// @param dest pointer to destination for the read data + /// @param numBytes number of 8-bit bytes to transfer + /// @returns true on success, else false on error + bool read(size_t offsetBytes, uint8_t *dest, size_t numBytes); + + /// Write a block of 16-bit data zeros in circular operation + /// @param numBytes number of 16-bit words to transfer + /// @returns true on success, else false on error + bool zeroAdvance(size_t numBytes); + + /// Write a single 16-bit data to the next location in circular operation + /// @param data the 16-bit word to transfer + /// @returns true on success, else false on error + bool writeAdvance(uint8_t data); // write just one data + + /// Write a block of 16-bit data from the specified location in circular operation + /// @param src pointer to the start of the block of data to write to memory + /// @param numBytes number of 16-bit words to transfer + /// @returns true on success, else false on error + bool writeAdvance(uint8_t *src, size_t numBytes); + + /// Read the next byte in memory during circular operation + /// @returns the next 8-bit data word in memory + uint8_t readAdvance(); + + /// Read the next block of numWords during circular operation + /// @details, dest is ignored when using DMA + /// @param dest pointer to the destination of the read. + /// @param numBytes number of 16-bit words to transfer + /// @returns true on success, else false on error + bool readAdvance(uint8_t *dest, size_t numBytes); + /// Write a block of 16-bit data to the memory at the specified offset /// @param offsetWords offset in 16-bit words from start of slot /// @param src pointer to start of block of 16-bit data @@ -100,11 +149,12 @@ public: /// @returns true on success, else false on error bool read16(size_t offsetWords, int16_t *dest, size_t numWords); + /* 16-bit data transfers */ + /// Read the next in memory during circular operation /// @returns the next 16-bit data word in memory uint16_t readAdvance16(); - /// Read the next block of numWords during circular operation /// @details, dest is ignored when using DMA /// @param dest pointer to the destination of the read. diff --git a/src/common/AudioDelay.cpp b/src/common/AudioDelay.cpp index b2e26b7..92aa3fe 100644 --- a/src/common/AudioDelay.cpp +++ b/src/common/AudioDelay.cpp @@ -76,7 +76,9 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block) } else { // EXTERNAL memory - if (!m_slot) { Serial.println("addBlock(): m_slot is not valid"); } + if (!m_slot) { + if (Serial) { Serial.println("addBlock(): m_slot is not valid"); } + } if (block) { @@ -128,7 +130,7 @@ bool AudioDelay::getSamples(int16_t *dest, size_t offsetSamples, size_t numSampl bool AudioDelay::m_getSamples(int16_t *dest, size_t offsetSamples, size_t numSamples) { if (!dest) { - Serial.println("getSamples(): dest is invalid"); + if (Serial) { Serial.println("getSamples(): dest is invalid"); } return false; } @@ -196,8 +198,8 @@ bool AudioDelay::m_getSamples(int16_t *dest, size_t offsetSamples, size_t numSam return true; } else { // numSamples is > than total slot size - Serial.println("getSamples(): ERROR numSamples > total slot size"); - Serial.println(numSamples + String(" > ") + m_slot->size()); + if (Serial) { Serial.println("getSamples(): ERROR numSamples > total slot size"); } + if (Serial) { Serial.println(numSamples + String(" > ") + m_slot->size()); } return false; } } diff --git a/src/common/BAHardware.cpp b/src/common/BAHardware.cpp index 0aea37d..4fece7f 100644 --- a/src/common/BAHardware.cpp +++ b/src/common/BAHardware.cpp @@ -40,6 +40,7 @@ uint8_t BA_EXPAND_POT3_PIN = A2; // 16_A2_RX4_SCL1 uint8_t BA_EXPAND_SW1_PIN = 2; // 2_OUT2 uint8_t BA_EXPAND_SW2_PIN = 3; // 3_LRCLK2 + uint8_t BA_EXPAND_LED1_PIN = 4; // 4_BLCK2 uint8_t BA_EXPAND_LED2_PIN = 5; // 5_IN2 @@ -66,6 +67,27 @@ uint8_t SPI1_CS_PIN = 38; uint8_t SPI1_MISO_PIN = 39; uint8_t SPI1_MOSI_PIN = 26; +// The following pins are only used on Multiverse +// They have dummy default values +uint8_t BA_EXPAND_POT4_PIN = A0; +uint8_t BA_EXPAND_POT5_PIN = A0; +uint8_t BA_EXPAND_POT6_PIN = A0; + +uint8_t BA_EXPAND_SW3_PIN = 0; +uint8_t BA_EXPAND_SW4_PIN = 0; +uint8_t BA_EXPAND_SW5_PIN = 0; +uint8_t BA_EXPAND_SW6_PIN = 0; + +uint8_t BA_EXPAND_ENC1_A_PIN = 0; +uint8_t BA_EXPAND_ENC1_B_PIN = 0; +uint8_t BA_EXPAND_ENC2_A_PIN = 0; +uint8_t BA_EXPAND_ENC2_B_PIN = 0; +uint8_t BA_EXPAND_ENC3_A_PIN = 0; +uint8_t BA_EXPAND_ENC3_B_PIN = 0; +uint8_t BA_EXPAND_ENC4_A_PIN = 0; +uint8_t BA_EXPAND_ENC4_B_PIN = 0; + + BAHardware::BAHardware() { #if defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY_MICROMOD) // T4.X @@ -88,6 +110,7 @@ void BAHardware::set(TgaBoard tgaBoard) if (tgaBoard == TgaBoard::MKII_REV1) { // No change from defaults } + return; #endif #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) // T3.6 or T3.5 or T3.2 @@ -126,6 +149,7 @@ void BAHardware::set(TgaBoard tgaBoard) SPI1_MISO_PIN = 5; SPI1_MOSI_PIN = 21; } + return; #endif //////////////////////////////////////////////////////////////////////////// @@ -162,6 +186,7 @@ void BAHardware::set(TgaBoard tgaBoard) SPI0_MISO_PIN = 12; SPI0_MOSI_PIN = 11; } + return; #endif #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) // T3.6 or T3.5 or T3.2 @@ -199,6 +224,7 @@ void BAHardware::set(TgaBoard tgaBoard) SPI1_MISO_PIN = 5; SPI1_MOSI_PIN = 21; } + return; #endif //////////////////////////////////////////////////////////////////////////// @@ -226,6 +252,7 @@ void BAHardware::set(TgaBoard tgaBoard) SPI0_MISO_PIN = 12; SPI0_MOSI_PIN = 11; } + return; #endif #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) // T3.6 or T3.5 or T3.2 @@ -255,32 +282,57 @@ void BAHardware::set(TgaBoard tgaBoard) SPI1_MISO_PIN = 5; SPI1_MOSI_PIN = 21; } + return; #endif //////////////////////////////////////////////////////////////////////////// - // Avalon // + // MULTIVERSE // //////////////////////////////////////////////////////////////////////////// -#if defined(ARDUINO_TEENSY41) // T4.X - if (tgaBoard == TgaBoard::AVALON) { - BA_EXPAND_NUM_POT = 2; +#if defined(ARDUINO_TEENSY_MICROMOD) + if (tgaBoard == TgaBoard::MULTIVERSE) { + BA_EXPAND_NUM_POT = 4; BA_EXPAND_NUM_SW = 6; BA_EXPAND_NUM_LED = 2; BA_EXPAND_NUM_ENC = 4; - BA_EXPAND_POT1_PIN = A0; - BA_EXPAND_POT2_PIN = A1; - BA_EXPAND_POT3_PIN = A13; + BA_EXPAND_POT1_PIN = A8; + BA_EXPAND_POT2_PIN = A0; + BA_EXPAND_POT3_PIN = A2; + BA_EXPAND_POT4_PIN = A3; + + BA_EXPAND_SW1_PIN = 6; + BA_EXPAND_SW2_PIN = 34; + BA_EXPAND_SW3_PIN = 45; + BA_EXPAND_SW4_PIN = 32; + BA_EXPAND_SW5_PIN = 41; + BA_EXPAND_SW6_PIN = 40; - BA_EXPAND_SW1_PIN = 17; - BA_EXPAND_SW2_PIN = 16; - BA_EXPAND_LED1_PIN = 22; - BA_EXPAND_LED2_PIN = 32; + BA_EXPAND_ENC1_A_PIN = 33; + BA_EXPAND_ENC1_B_PIN = 2; + + BA_EXPAND_ENC2_A_PIN = 31; + BA_EXPAND_ENC2_B_PIN = 36; + + BA_EXPAND_ENC3_A_PIN = 5; + BA_EXPAND_ENC3_B_PIN = 4; + + BA_EXPAND_ENC4_A_PIN = 3; + BA_EXPAND_ENC4_B_PIN = 30; + + BA_EXPAND_LED1_PIN = 9; + BA_EXPAND_LED2_PIN = 42; SPI0_SCK_PIN = 13; SPI0_CS_PIN = 10; SPI0_MISO_PIN = 12; SPI0_MOSI_PIN = 11; + + SPI1_SCK_PIN = 27; + SPI1_CS_PIN = 43; + SPI1_MISO_PIN = 1; + SPI1_MOSI_PIN = 26; } + return; #endif } diff --git a/src/common/ExtMemSlot.cpp b/src/common/ExtMemSlot.cpp index 1574126..1989751 100644 --- a/src/common/ExtMemSlot.cpp +++ b/src/common/ExtMemSlot.cpp @@ -31,7 +31,7 @@ namespace BALibrary { bool ExtMemSlot::clear() { if (!m_valid) { return false; } - m_spi->zero16(m_start, m_size); + m_spi->zero(m_start, m_size); return true; } @@ -43,13 +43,25 @@ bool ExtMemSlot::setWritePosition(size_t offsetBytes) } else { return false; } } -bool ExtMemSlot::write16(size_t offsetWords, int16_t *src, size_t numWords) +bool ExtMemSlot::setReadPosition(size_t offsetBytes) +{ + if (m_start + offsetBytes <= m_end) { + m_currentRdPosition = m_start + offsetBytes; + return true; + } else { + return false; + } +} + +///////////////////////////////////////////////////////////////////////// +// BYTE BASED TRANSFERS +///////////////////////////////////////////////////////////////////////// +bool ExtMemSlot::zero(size_t offsetBytes, size_t numBytes) { if (!m_valid) { return false; } - size_t writeStart = m_start + sizeof(int16_t)*offsetWords; // 2x because int16 is two bytes per data - size_t numBytes = sizeof(int16_t)*numWords; + size_t writeStart = m_start + offsetBytes; if ((writeStart + numBytes-1) <= m_end) { - m_spi->write16(writeStart, reinterpret_cast(src), numWords); // cast audio data to uint + m_spi->zero(writeStart, numBytes); // cast audio data to uint return true; } else { // this would go past the end of the memory slot, do not perform the write @@ -57,16 +69,138 @@ bool ExtMemSlot::write16(size_t offsetWords, int16_t *src, size_t numWords) } } -bool ExtMemSlot::setReadPosition(size_t offsetBytes) +bool ExtMemSlot::write(size_t offsetBytes, uint8_t *src, size_t numBytes) { - if (m_start + offsetBytes <= m_end) { - m_currentRdPosition = m_start + offsetBytes; + if (!m_valid) { return false; } + size_t writeStart = m_start + offsetBytes; + if ((writeStart + numBytes-1) <= m_end) { + m_spi->write(writeStart, src, numBytes); // cast audio data to uint + return true; + } else { + // this would go past the end of the memory slot, do not perform the write + return false; + } +} + +bool ExtMemSlot::read(size_t offsetBytes, uint8_t *dest, size_t numBytes) +{ + if (!dest) return false; // invalid destination + size_t readOffset = m_start + offsetBytes; + + if ((readOffset + numBytes-1) <= m_end) { + m_spi->read(readOffset, dest, numBytes); + return true; + } else { + // this would go past the end of the memory slot, do not perform the read + return false; + } +} + +bool ExtMemSlot::zeroAdvance(size_t numBytes) +{ + if (!m_valid) { return false; } + + if (m_currentWrPosition + numBytes-1 <= m_end) { + // entire block fits in memory slot without wrapping + m_spi->zero(m_currentWrPosition, numBytes); // cast audio data to uint. + m_currentWrPosition += numBytes; + + } else { + // this write will wrap the memory slot + size_t wrBytes = m_end - m_currentWrPosition + 1; + m_spi->zero(m_currentWrPosition, wrBytes); + size_t remainingBytes = numBytes - wrBytes; // calculate the remaining bytes + m_spi->zero(m_start, remainingBytes); // write remaining bytes are start + m_currentWrPosition = m_start + remainingBytes; + } + return true; +} + +bool ExtMemSlot::writeAdvance(uint8_t data) +{ + if (!m_valid) { return false; } + + m_spi->write(m_currentWrPosition, static_cast(data)); + if (m_currentWrPosition < m_end-1) { + m_currentWrPosition++; // wrote two bytes + } else { + m_currentWrPosition = m_start; + } + return true; +} + +bool ExtMemSlot::writeAdvance(uint8_t *src, size_t numBytes) +{ + if (!m_valid) { return false; } + + if (m_currentWrPosition + numBytes-1 <= m_end) { + // entire block fits in memory slot without wrapping + m_spi->write(m_currentWrPosition, reinterpret_cast(src), numBytes); // cast audio data to uint. + m_currentWrPosition += numBytes; + + } else { + // this write will wrap the memory slot + size_t wrBytes = m_end - m_currentWrPosition + 1; + m_spi->write(m_currentWrPosition, src, wrBytes); + size_t remainingData = numBytes - wrBytes; + m_spi->write(m_start, src + wrBytes, remainingData); // write remaining bytes are start + m_currentWrPosition = m_start + remainingData; + } + return true; +} + +/// Read the next in memory during circular operation +/// @returns the next 8-bit data word in memory +uint8_t ExtMemSlot::readAdvance() { + uint8_t val = m_spi->read(m_currentRdPosition); + if (m_currentRdPosition < m_end-1) { + m_currentRdPosition ++; // position is in bytes and we read two + } else { + m_currentRdPosition = m_start; + } + return val; +} + +bool ExtMemSlot::readAdvance(uint8_t *dest, size_t numBytes) +{ + if (!m_valid) { return false; } + + if (m_currentRdPosition + numBytes-1 <= m_end) { + // entire block fits in memory slot without wrapping + m_spi->read(m_currentRdPosition, dest, numBytes); // cast audio data to uint. + m_currentRdPosition += numBytes; + + } else { + // this read will wrap the memory slot + size_t rdBytes = m_end - m_currentRdPosition + 1; + m_spi->read(m_currentRdPosition, dest, rdBytes); + size_t remainingData = numBytes - rdBytes; + m_spi->read(m_start, (dest + rdBytes), remainingData); // write remaining bytes are start + m_currentRdPosition = m_start + remainingData; + } + return true; +} + +///////////////////////////////////////////////////////////////////////// +// 16-BIT BASED TRANSFERS +///////////////////////////////////////////////////////////////////////// + +bool ExtMemSlot::write16(size_t offsetWords, int16_t *src, size_t numWords) +{ + if (!m_valid) { return false; } + size_t writeStart = m_start + sizeof(int16_t)*offsetWords; // 2x because int16 is two bytes per data + size_t numBytes = sizeof(int16_t)*numWords; + if ((writeStart + numBytes-1) <= m_end) { + m_spi->write16(writeStart, reinterpret_cast(src), numWords); // cast audio data to uint return true; } else { + // this would go past the end of the memory slot, do not perform the write return false; } } + + bool ExtMemSlot::zero16(size_t offsetWords, size_t numWords) { if (!m_valid) { return false; } @@ -198,12 +332,12 @@ bool ExtMemSlot::writeAdvance16(int16_t data) bool ExtMemSlot::enable() const { if (m_spi) { - Serial.println("ExtMemSlot::enable()"); + if (Serial) { Serial.println("ExtMemSlot::enable()"); } m_spi->begin(); return true; } else { - Serial.println("ExtMemSlot m_spi is nullptr"); + if (Serial) { Serial.println("ExtMemSlot m_spi is nullptr"); } return false; } } @@ -231,10 +365,11 @@ bool ExtMemSlot::isReadBusy() const void ExtMemSlot::printStatus(void) const { - Serial.println(String("valid:") + m_valid + String(" m_start:") + m_start + \ + if (Serial) { Serial.println(String("valid:") + m_valid + String(" m_start:") + m_start + \ String(" m_end:") + m_end + String(" m_currentWrPosition: ") + m_currentWrPosition + \ String(" m_currentRdPosition: ") + m_currentRdPosition + \ String(" m_size:") + m_size); + } } } diff --git a/src/common/ExternalSramManager.cpp b/src/common/ExternalSramManager.cpp index 377f646..1de2500 100644 --- a/src/common/ExternalSramManager.cpp +++ b/src/common/ExternalSramManager.cpp @@ -68,7 +68,7 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALi if (!m_configured) { m_configure(); } if (m_memConfig[mem].totalAvailable >= sizeBytes) { - Serial.println(String("Configuring a slot for mem ") + mem); + if (Serial) Serial.printf("Configuring mem %d, for size %d, available %d\n\r", (unsigned)mem, sizeBytes, m_memConfig[mem].totalAvailable); // there is enough available memory for this request slot->m_start = m_memConfig[mem].nextAvailable; slot->m_end = slot->m_start + sizeBytes -1; @@ -78,15 +78,18 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALi if (!m_memConfig[mem].m_spi) { if (useDma) { + if (Serial) { Serial.printf("Creating S for id %d\n\r", (int)mem);} m_memConfig[mem].m_spi = new BALibrary::BASpiMemoryDMA(static_cast(mem)); slot->m_useDma = true; } else { + if (Serial) { Serial.printf("Creating BASpiMemory for id %d\n\r", (int)mem);} m_memConfig[mem].m_spi = new BALibrary::BASpiMemory(static_cast(mem)); slot->m_useDma = false; } if (!m_memConfig[mem].m_spi) { + if (Serial) { Serial.printf("Failed to create SPI for id %d\n\r", (int)mem);} } else { - Serial.println("Calling spi begin()"); + if (Serial) { Serial.println("Calling spi begin()"); } m_memConfig[mem].m_spi->begin(); } } @@ -97,15 +100,14 @@ bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALi m_memConfig[mem].totalAvailable -= sizeBytes; slot->m_valid = true; if (!slot->isEnabled()) { slot->enable(); } - Serial.println("Clear the memory\n"); Serial.flush(); - slot->clear(); - Serial.println("Done Request memory\n"); Serial.flush(); + // Note: we no longer auto-clear the slot (on purpose) + if (Serial) { Serial.println("Done Request memory\n"); Serial.flush(); } return true; } else { // there is not enough memory available for the request - Serial.println(String("ExternalSramManager::requestMemory(): Insufficient memory in slot, request/available: ") + if (Serial) { Serial.println(String("ExternalSramManager::requestMemory(): Insufficient memory in slot, request/available: ") + sizeBytes + String(" : ") - + m_memConfig[mem].totalAvailable); + + m_memConfig[mem].totalAvailable); } return false; } } diff --git a/src/common/ParameterAutomation.cpp b/src/common/ParameterAutomation.cpp index bc3e4d2..240472d 100644 --- a/src/common/ParameterAutomation.cpp +++ b/src/common/ParameterAutomation.cpp @@ -134,9 +134,9 @@ T ParameterAutomation::getNextValue() } else { returnValue = m_startValue - (m_scaleY*value); } -// Serial.println(String("Start/End values: ") + m_startValue + String(":") + m_endValue); - //Serial.print("Parameter m_currentValueX is "); Serial.println(m_currentValueX, 6); - //Serial.print("Parameter returnValue is "); Serial.println(returnValue, 6); + // if (Serial) { Serial.println(String("Start/End values: ") + m_startValue + String(":") + m_endValue); } + // if (Serial) { Serial.print("Parameter m_currentValueX is "); Serial.println(m_currentValueX, 6); } + // if (Serial) { Serial.print("Parameter returnValue is "); Serial.println(returnValue, 6); } return returnValue; } @@ -175,7 +175,7 @@ ParameterAutomationSequence::~ParameterAutomationSequence() template void ParameterAutomationSequence::setupParameter(int index, T startValue, T endValue, size_t durationSamples, typename ParameterAutomation::Function function) { - Serial.println(String("setupParameter() called with samples: ") + durationSamples); + if (Serial) { Serial.println(String("setupParameter() called with samples: ") + durationSamples); } m_paramArray[index]->reconfigure(startValue, endValue, durationSamples, function); m_currentIndex = 0; } @@ -183,7 +183,7 @@ void ParameterAutomationSequence::setupParameter(int index, T startValue, T e template void ParameterAutomationSequence::setupParameter(int index, T startValue, T endValue, float durationMilliseconds, typename ParameterAutomation::Function function) { - Serial.print(String("setupParameter() called with time: ")); Serial.println(durationMilliseconds, 6); + if (Serial) { Serial.print(String("setupParameter() called with time: ")); Serial.println(durationMilliseconds, 6); } m_paramArray[index]->reconfigure(startValue, endValue, durationMilliseconds, function); m_currentIndex = 0; } @@ -194,7 +194,7 @@ void ParameterAutomationSequence::trigger(void) m_currentIndex = 0; m_paramArray[0]->trigger(); m_running = true; - //Serial.println("ParameterAutomationSequence::trigger() called"); + // if (Serial) { Serial.println("ParameterAutomationSequence::trigger() called"); } } template @@ -204,17 +204,17 @@ T ParameterAutomationSequence::getNextValue() T nextValue = m_paramArray[m_currentIndex]->getNextValue(); if (m_running) { - //Serial.println(String("ParameterAutomationSequence::getNextValue() is ") + nextValue - // + String(" from stage ") + m_currentIndex); + // if (Serial) { Serial.println(String("ParameterAutomationSequence::getNextValue() is ") + nextValue + // + String(" from stage ") + m_currentIndex); } // If current stage is done, trigger the next if (m_paramArray[m_currentIndex]->isFinished()) { - Serial.println(String("Finished stage ") + m_currentIndex); + if (Serial) { Serial.println(String("Finished stage ") + m_currentIndex); } m_currentIndex++; if (m_currentIndex >= m_numStages) { // Last stage already finished - Serial.println("Last stage finished"); + if (Serial) { Serial.println("Last stage finished"); } m_running = false; m_currentIndex = 0; } else { diff --git a/src/effects/AudioEffectAnalogDelay.cpp b/src/effects/AudioEffectAnalogDelay.cpp index 914c705..6150aeb 100644 --- a/src/effects/AudioEffectAnalogDelay.cpp +++ b/src/effects/AudioEffectAnalogDelay.cpp @@ -3,7 +3,20 @@ * * Created on: Jan 7, 2018 * Author: slascos - */ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version.* + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ #include #include "AudioEffectAnalogDelayFilters.h" #include "AudioEffectAnalogDelay.h" @@ -166,22 +179,26 @@ void AudioEffectAnalogDelay::delay(float milliseconds) { size_t delaySamples = calcAudioSamples(milliseconds); - if (!m_memory) { Serial.println("delay(): m_memory is not valid"); return; } + if (!m_memory) { + if (Serial) { Serial.println("delay(): m_memory is not valid"); return; } + } if (!m_externalMemory) { // internal memory m_maxDelaySamples = m_memory->getMaxDelaySamples(); //QueuePosition queuePosition = calcQueuePosition(milliseconds); - //Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset); + // if (Serial) { Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset); } } else { // external memory ExtMemSlot *slot = m_memory->getSlot(); m_maxDelaySamples = (slot->size() / sizeof(int16_t))-AUDIO_BLOCK_SAMPLES; - if (!slot) { Serial.println("ERROR: slot ptr is not valid"); } + if (!slot) { + if (Serial) { Serial.println("ERROR: slot ptr is not valid"); } + } if (!slot->isEnabled()) { slot->enable(); - Serial.println("WEIRD: slot was not enabled"); + if (Serial) { Serial.println("WEIRD: slot was not enabled"); } } } @@ -194,16 +211,16 @@ void AudioEffectAnalogDelay::delay(float milliseconds) void AudioEffectAnalogDelay::delay(size_t delaySamples) { - if (!m_memory) { Serial.println("delay(): m_memory is not valid"); } + if (!m_memory) { if (Serial) Serial.println("delay(): m_memory is not valid"); } if (!m_externalMemory) { // internal memory m_maxDelaySamples = m_memory->getMaxDelaySamples(); //QueuePosition queuePosition = calcQueuePosition(delaySamples); - //Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset); + // if (Serial) { Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset); } } else { // external memory - //Serial.println(String("CONFIG: delay:") + delaySamples); + // if (Serial) { Serial.println(String("CONFIG: delay:") + delaySamples); } ExtMemSlot *slot = m_memory->getSlot(); m_maxDelaySamples = (slot->size() / sizeof(int16_t))-AUDIO_BLOCK_SAMPLES; if (!slot->isEnabled()) { @@ -222,16 +239,16 @@ void AudioEffectAnalogDelay::delayFractionMax(float delayFraction) { size_t delaySamples = static_cast(static_cast(m_memory->getMaxDelaySamples()) * delayFraction); - if (!m_memory) { Serial.println("delay(): m_memory is not valid"); } + if (!m_memory) { if (Serial) Serial.println("delay(): m_memory is not valid"); } if (!m_externalMemory) { // internal memory m_maxDelaySamples = m_memory->getMaxDelaySamples(); //QueuePosition queuePosition = calcQueuePosition(delaySamples); - //Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset); + // if (Serial) { Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset); } } else { // external memory - //Serial.println(String("CONFIG: delay:") + delaySamples); + // if (Serial) { Serial.println(String("CONFIG: delay:") + delaySamples); } ExtMemSlot *slot = m_memory->getSlot(); m_maxDelaySamples = (slot->size() / sizeof(int16_t))-AUDIO_BLOCK_SAMPLES; if (!slot->isEnabled()) { @@ -284,23 +301,23 @@ void AudioEffectAnalogDelay::processMidi(int channel, int control, int value) if (m_externalMemory) { m_maxDelaySamples = (m_memory->getSlot()->size() / sizeof(int16_t))-AUDIO_BLOCK_SAMPLES; } size_t delayVal = (size_t)(val * (float)(m_maxDelaySamples)); delay(delayVal); - Serial.println(String("AudioEffectAnalogDelay::delay (ms): ") + calcAudioTimeMs(delayVal) - + String(" (samples): ") + delayVal + String(" out of ") + m_maxDelaySamples); + if (Serial) { Serial.println(String("AudioEffectAnalogDelay::delay (ms): ") + calcAudioTimeMs(delayVal) + + String(" (samples): ") + delayVal + String(" out of ") + m_maxDelaySamples); } return; } if ((m_midiConfig[BYPASS][MIDI_CHANNEL] == channel) && (m_midiConfig[BYPASS][MIDI_CONTROL] == control)) { // Bypass - if (value >= 65) { bypass(false); Serial.println(String("AudioEffectAnalogDelay::not bypassed -> ON") + value); } - else { bypass(true); Serial.println(String("AudioEffectAnalogDelay::bypassed -> OFF") + value); } + if (value >= 65) { bypass(false); if (Serial) Serial.println(String("AudioEffectAnalogDelay::not bypassed -> ON") + value); } + else { bypass(true); if (Serial) Serial.println(String("AudioEffectAnalogDelay::bypassed -> OFF") + value); } return; } if ((m_midiConfig[FEEDBACK][MIDI_CHANNEL] == channel) && (m_midiConfig[FEEDBACK][MIDI_CONTROL] == control)) { // Feedback - Serial.println(String("AudioEffectAnalogDelay::feedback: ") + 100*val + String("%")); + if (Serial) { Serial.println(String("AudioEffectAnalogDelay::feedback: ") + 100*val + String("%")); } feedback(val); return; } @@ -308,7 +325,7 @@ void AudioEffectAnalogDelay::processMidi(int channel, int control, int value) if ((m_midiConfig[MIX][MIDI_CHANNEL] == channel) && (m_midiConfig[MIX][MIDI_CONTROL] == control)) { // Mix - Serial.println(String("AudioEffectAnalogDelay::mix: Dry: ") + 100*(1-val) + String("% Wet: ") + 100*val ); + if (Serial) { Serial.println(String("AudioEffectAnalogDelay::mix: Dry: ") + 100*(1-val) + String("% Wet: ") + 100*val ); } mix(val); return; } @@ -316,7 +333,7 @@ void AudioEffectAnalogDelay::processMidi(int channel, int control, int value) if ((m_midiConfig[VOLUME][MIDI_CHANNEL] == channel) && (m_midiConfig[VOLUME][MIDI_CONTROL] == control)) { // Volume - Serial.println(String("AudioEffectAnalogDelay::volume: ") + 100*val + String("%")); + if (Serial) { Serial.println(String("AudioEffectAnalogDelay::volume: ") + 100*val + String("%")); } volume(val); return; } diff --git a/src/effects/AudioEffectDelayExternal.cpp b/src/effects/AudioEffectDelayExternal.cpp index e21d947..4ee9b7c 100644 --- a/src/effects/AudioEffectDelayExternal.cpp +++ b/src/effects/AudioEffectDelayExternal.cpp @@ -67,7 +67,7 @@ void BAAudioEffectDelayExternal::delay(uint8_t channel, float milliseconds) { unsigned mask = m_activeMask; if (m_activeMask == 0) m_startUsingSPI(m_spiChannel); m_activeMask = mask | (1<. +*/ #include #include "BALibrary.h" #include "AudioEffectRmsMeasure.h" @@ -64,8 +77,7 @@ void AudioEffectRmsMeasure::update(void) for (int i=0; idata[i] * (int64_t)inputAudioBlock->data[i]); if (dotProduct < 0) { - Serial.println("DOT ERROR!"); - Serial.println(inputAudioBlock->data[i], HEX); + if (Serial) { Serial.println("DOT ERROR!"); Serial.println(inputAudioBlock->data[i], HEX); } } } m_sum += (int64_t)(dotProduct); @@ -80,11 +92,13 @@ void AudioEffectRmsMeasure::update(void) // dbfs = 20*log10(abs(rmsFigure)/32768.0f); m_dbfs = 20.0f * log10(m_rms/32768.0f); - Serial.print("Accumulator: "); Serial.println((int)(m_sum >> 32), HEX); - Serial.print("RAW RMS: "); Serial.println(m_rms); + if (Serial) { + Serial.print("Accumulator: "); Serial.println((int)(m_sum >> 32), HEX); + Serial.print("RAW RMS: "); Serial.println(m_rms); - Serial.print("AudioEffectRmsMeasure: the RMS figure is "); Serial.print(m_dbfs); - Serial.print(" dBFS over "); Serial.print(m_accumulatorCount); Serial.println(" audio blocks"); + Serial.print("AudioEffectRmsMeasure: the RMS figure is "); Serial.print(m_dbfs); + Serial.print(" dBFS over "); Serial.print(m_accumulatorCount); Serial.println(" audio blocks"); + } m_sum = 0; m_accumulatorCount = 0; diff --git a/src/effects/AudioEffectSOS.cpp b/src/effects/AudioEffectSOS.cpp index 61552b5..998f0df 100644 --- a/src/effects/AudioEffectSOS.cpp +++ b/src/effects/AudioEffectSOS.cpp @@ -3,7 +3,20 @@ * * Created on: Apr 14, 2018 * Author: blackaddr - */ + * + * 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 "AudioEffectSOS.h" #include "LibBasicFunctions.h" @@ -63,7 +76,7 @@ void AudioEffectSOS::enable(void) // Because we hold the previous output buffer for an update cycle, the maximum delay is actually // 1 audio block mess then the max delay returnable from the memory. m_maxDelaySamples = m_memory->getMaxDelaySamples() - AUDIO_BLOCK_SAMPLES; - Serial.println(String("SOS Enabled with delay length ") + m_maxDelaySamples + String(" samples")); + if (Serial) { Serial.println(String("SOS Enabled with delay length ") + m_maxDelaySamples + String(" samples")); } } m_delaySamples = m_maxDelaySamples; m_inputGateAuto.setupParameter(GATE_OPEN_STAGE, 0.0f, 1.0f, 1000.0f, ParameterAutomation::Function::EXPONENTIAL); @@ -126,8 +139,8 @@ void AudioEffectSOS::update(void) // get the data. If using external memory with DMA, this won't be filled until // later. m_memory->getSamples(blockToOutput, m_delaySamples); - //Serial.println(String("Delay samples:") + m_delaySamples); - //Serial.println(String("Use dma: ") + m_memory->getSlot()->isUseDma()); + // if (Serial) { Serial.println(String("Delay samples:") + m_delaySamples); } + // if (Serial) { Serial.println(String("Use dma: ") + m_memory->getSlot()->isUseDma()); } // If using DMA, we need something else to do while that read executes, so // move on to input preprocessing @@ -157,7 +170,7 @@ void AudioEffectSOS::update(void) m_previousBlock = blockToOutput; if (m_blockToRelease == m_previousBlock) { - Serial.println("ERROR: POINTER COLLISION"); + if (Serial) { Serial.println("ERROR: POINTER COLLISION"); } } if (m_blockToRelease) { release(m_blockToRelease); } @@ -190,7 +203,7 @@ void AudioEffectSOS::processMidi(int channel, int control, int value) (m_midiConfig[GATE_OPEN_TIME][MIDI_CONTROL] == control)) { // Gate Open Time gateOpenTime(val * MAX_GATE_OPEN_TIME_MS); - Serial.println(String("AudioEffectSOS::gate open time (ms): ") + m_openTimeMs); + if (Serial) { Serial.println(String("AudioEffectSOS::gate open time (ms): ") + m_openTimeMs); } return; } @@ -198,14 +211,14 @@ void AudioEffectSOS::processMidi(int channel, int control, int value) (m_midiConfig[GATE_CLOSE_TIME][MIDI_CONTROL] == control)) { // Gate Close Time gateCloseTime(val * MAX_GATE_CLOSE_TIME_MS); - Serial.println(String("AudioEffectSOS::gate close time (ms): ") + m_closeTimeMs); + if (Serial) { Serial.println(String("AudioEffectSOS::gate close time (ms): ") + m_closeTimeMs); } return; } if ((m_midiConfig[FEEDBACK][MIDI_CHANNEL] == channel) && (m_midiConfig[FEEDBACK][MIDI_CONTROL] == control)) { // Feedback - Serial.println(String("AudioEffectSOS::feedback: ") + 100*val + String("%")); + if (Serial) { Serial.println(String("AudioEffectSOS::feedback: ") + 100*val + String("%")); } feedback(val); return; } @@ -213,7 +226,7 @@ void AudioEffectSOS::processMidi(int channel, int control, int value) if ((m_midiConfig[VOLUME][MIDI_CHANNEL] == channel) && (m_midiConfig[VOLUME][MIDI_CONTROL] == control)) { // Volume - Serial.println(String("AudioEffectSOS::volume: ") + 100*val + String("%")); + if (Serial) { Serial.println(String("AudioEffectSOS::volume: ") + 100*val + String("%")); } volume(val); return; } @@ -221,15 +234,15 @@ void AudioEffectSOS::processMidi(int channel, int control, int value) if ((m_midiConfig[BYPASS][MIDI_CHANNEL] == channel) && (m_midiConfig[BYPASS][MIDI_CONTROL] == control)) { // Bypass - if (value >= 65) { bypass(false); Serial.println(String("AudioEffectSOS::not bypassed -> ON") + value); } - else { bypass(true); Serial.println(String("AudioEffectSOS::bypassed -> OFF") + value); } + if (value >= 65) { bypass(false); if (Serial) Serial.println(String("AudioEffectSOS::not bypassed -> ON") + value); } + else { bypass(true); if (Serial) Serial.println(String("AudioEffectSOS::bypassed -> OFF") + value); } return; } if ((m_midiConfig[GATE_TRIGGER][MIDI_CHANNEL] == channel) && (m_midiConfig[GATE_TRIGGER][MIDI_CONTROL] == control)) { // The gate is triggered by any value - Serial.println(String("AudioEffectSOS::Gate Triggered!")); + if (Serial) { Serial.println(String("AudioEffectSOS::Gate Triggered!")); } m_inputGateAuto.trigger(); return; } @@ -237,7 +250,7 @@ void AudioEffectSOS::processMidi(int channel, int control, int value) if ((m_midiConfig[CLEAR_FEEDBACK_TRIGGER][MIDI_CHANNEL] == channel) && (m_midiConfig[CLEAR_FEEDBACK_TRIGGER][MIDI_CONTROL] == control)) { // The gate is triggered by any value - Serial.println(String("AudioEffectSOS::Clear feedback Triggered!")); + if (Serial) { Serial.println(String("AudioEffectSOS::Clear feedback Triggered!")); } m_clearFeedbackAuto.trigger(); return; } diff --git a/src/effects/AudioEffectTremolo.cpp b/src/effects/AudioEffectTremolo.cpp index 212f3c3..6b6b714 100644 --- a/src/effects/AudioEffectTremolo.cpp +++ b/src/effects/AudioEffectTremolo.cpp @@ -3,7 +3,21 @@ * * Created on: Jan 7, 2018 * Author: slascos - */ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version.* + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + #include // std::roundf #include "AudioEffectTremolo.h" @@ -62,16 +76,6 @@ void AudioEffectTremolo::update(void) float sample = std::roundf(mod[i] * (float)inputAudioBlock->data[i]); inputAudioBlock->data[i] = (int16_t)sample; } - //Serial.println(String("mod: ") + mod[0]); - - - - //float mod = (m_osc.getNext()+1.0f)/2.0f; // value between -1.0 and +1.0f - //float modVolume = (1.0f - m_depth) + mod*m_depth; // value between 0 to depth - //float finalVolume = m_volume * modVolume; - - // Set the output volume - //gainAdjust(inputAudioBlock, inputAudioBlock, finalVolume, 1); transmit(inputAudioBlock); release(inputAudioBlock); @@ -97,8 +101,8 @@ void AudioEffectTremolo::processMidi(int channel, int control, int value) if ((m_midiConfig[BYPASS][MIDI_CHANNEL] == channel) && (m_midiConfig[BYPASS][MIDI_CONTROL] == control)) { // Bypass - if (value >= 65) { bypass(false); Serial.println(String("AudioEffectTremolo::not bypassed -> ON") + value); } - else { bypass(true); Serial.println(String("AudioEffectTremolo::bypassed -> OFF") + value); } + if (value >= 65) { bypass(false); if (Serial) Serial.println(String("AudioEffectTremolo::not bypassed -> ON") + value); } + else { bypass(true); if (Serial) Serial.println(String("AudioEffectTremolo::bypassed -> OFF") + value); } return; } @@ -106,7 +110,7 @@ void AudioEffectTremolo::processMidi(int channel, int control, int value) (m_midiConfig[RATE][MIDI_CONTROL] == control)) { // Rate rate(val); - Serial.println(String("AudioEffectTremolo::rate: ") + m_rate); + if (Serial) { Serial.println(String("AudioEffectTremolo::rate: ") + m_rate); } return; } @@ -114,7 +118,7 @@ void AudioEffectTremolo::processMidi(int channel, int control, int value) (m_midiConfig[DEPTH][MIDI_CONTROL] == control)) { // Depth depth(val); - Serial.println(String("AudioEffectTremolo::depth: ") + m_depth); + if (Serial) { Serial.println(String("AudioEffectTremolo::depth: ") + m_depth); } return; } @@ -133,14 +137,14 @@ void AudioEffectTremolo::processMidi(int channel, int control, int value) m_waveform = Waveform::RANDOM; } - Serial.println(String("AudioEffectTremolo::waveform: ") + static_cast(m_waveform)); + if (Serial) { Serial.println(String("AudioEffectTremolo::waveform: ") + static_cast(m_waveform)); } return; } if ((m_midiConfig[VOLUME][MIDI_CHANNEL] == channel) && (m_midiConfig[VOLUME][MIDI_CONTROL] == control)) { // Volume - Serial.println(String("AudioEffectTremolo::volume: ") + 100*val + String("%")); + if (Serial) { Serial.println(String("AudioEffectTremolo::volume: ") + 100*val + String("%")); } volume(val); return; } diff --git a/src/peripherals/BAAudioControlWM8731.cpp b/src/peripherals/BAAudioControlWM8731.cpp index b82b83b..e70686c 100644 --- a/src/peripherals/BAAudioControlWM8731.cpp +++ b/src/peripherals/BAAudioControlWM8731.cpp @@ -136,7 +136,7 @@ BAAudioControlWM8731::~BAAudioControlWM8731() // Powerdown and disable the codec void BAAudioControlWM8731::disable(void) { - //Serial.println("Disabling codec"); + // if (Serial) { Serial.println("Disabling codec"); } if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; @@ -161,7 +161,7 @@ void BAAudioControlWM8731::enable(void) disable(); // disable first in case it was already powered up - //Serial.println("Enabling codec"); + // if (Serial) { Serial.println("Enabling codec"); } if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; @@ -398,10 +398,9 @@ bool BAAudioControlWM8731::write(unsigned int reg, unsigned int val) Wire.write(val & 0xFF); byte error = Wire.endTransmission(); if (error) { - Serial.println(String("Wire::Error: ") + error + String(" retrying...")); + if (Serial) { Serial.println(String("Wire::Error: ") + error + String(" retrying...")); } } else { done = true; - //Serial.println("Wire::SUCCESS!"); } } @@ -427,7 +426,7 @@ void BAAudioControlWM8731master::enable(void) disable(); // disable first in case it was already powered up - //Serial.println("Enabling codec"); + // if (Serial) { Serial.println("Enabling codec"); } if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; diff --git a/src/peripherals/BAPhysicalControls.cpp b/src/peripherals/BAPhysicalControls.cpp index 32c16c3..8fc909a 100644 --- a/src/peripherals/BAPhysicalControls.cpp +++ b/src/peripherals/BAPhysicalControls.cpp @@ -22,11 +22,11 @@ // These calls must be define in order to get vector to work on arduino namespace std { void __throw_bad_alloc() { - Serial.println("Unable to allocate memory"); + if (Serial) { Serial.println("Unable to allocate memory"); } abort(); } void __throw_length_error( char const*e ) { - Serial.print("Length Error :"); Serial.println(e); + if (Serial) { Serial.print("Length Error :"); Serial.println(e); } abort(); } } @@ -56,6 +56,8 @@ unsigned BAPhysicalControls::addRotary(uint8_t pin1, uint8_t pin2, bool swapDire return m_encoders.size()-1; } +unsigned BAPhysicalControls::getNumRotary() { return m_encoders.size(); } + unsigned BAPhysicalControls::addSwitch(uint8_t pin, unsigned long intervalMilliseconds) { m_switches.emplace_back(); m_switches.back().attach(pin); @@ -64,6 +66,8 @@ unsigned BAPhysicalControls::addSwitch(uint8_t pin, unsigned long intervalMillis return m_switches.size()-1; } +unsigned BAPhysicalControls::getNumSwitches() { return m_switches.size(); } + unsigned BAPhysicalControls::addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration) { m_pots.emplace_back(pin, minCalibration, maxCalibration); pinMode(pin, INPUT); @@ -76,12 +80,16 @@ unsigned BAPhysicalControls::addPot(uint8_t pin, unsigned minCalibration, unsign return m_pots.size()-1; } +unsigned BAPhysicalControls::getNumPots() { return m_pots.size(); } + unsigned BAPhysicalControls::addOutput(uint8_t pin) { m_outputs.emplace_back(pin); pinMode(pin, OUTPUT); return m_outputs.size()-1; } +unsigned BAPhysicalControls::getNumOutputs() { return m_outputs.size(); } + void BAPhysicalControls::setOutput(unsigned handle, int val) { if (handle >= m_outputs.size()) { return; } m_outputs[handle].set(val); @@ -329,6 +337,8 @@ void Potentiometer::setChangeThreshold(float changeThreshold) Potentiometer::Calib Potentiometer::calibrate(uint8_t pin) { Calib calib; + if (!Serial) { return calib; } // this function REQUIRES Serial port connection + // Flush the serial port input buffer while (Serial.available() > 0) {} diff --git a/src/peripherals/BASpiMemory.cpp b/src/peripherals/BASpiMemory.cpp index 21b58df..44e16ee 100644 --- a/src/peripherals/BASpiMemory.cpp +++ b/src/peripherals/BASpiMemory.cpp @@ -24,20 +24,6 @@ namespace BALibrary { -//// MEM0 Settings -//int SPI_CS_MEM0 = SPI0_CS_PIN; -//int SPI_MOSI_MEM0 = SPI0_MOSI_PIN; -//int SPI_MISO_MEM0 = SPI0_MISO_PIN; -//int SPI_SCK_MEM0 = SPI0_SCK_PIN; -// -//#if defined(SPI1_AVAILABLE) -//// MEM1 Settings -//int SPI_CS_MEM1 = SPI1_CS_PIN; -//int SPI_MOSI_MEM1 = SPI1_MOSI_PIN; -//int SPI_MISO_MEM1 = SPI1_MISO_PIN; -//int SPI_SCK_MEM1 = SPI1_SCK_PIN; -//#endif - // SPI Constants constexpr int SPI_WRITE_MODE_REG = 0x1; constexpr int SPI_WRITE_CMD = 0x2; @@ -82,7 +68,7 @@ void BASpiMemory::begin() m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM0).DIE_BOUNDARY; break; -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) +#if defined(ARDUINO_TEENSY_MICROMOD) || defined(__MK64FX512__) || defined(__MK66FX1M0__) case SpiDeviceId::SPI_DEVICE1 : m_csPin = SPI1_CS_PIN; m_spi = &SPI1; @@ -401,7 +387,7 @@ void BASpiMemoryDMA::begin(void) cs = SPI0_CS_PIN; m_cs = new ActiveLowChipSelect(cs, m_settings); break; -#if defined(__MK66FX1M0__) +#if defined(ARDUINO_TEENSY_MICROMOD) || defined(__MK66FX1M0__) case SpiDeviceId::SPI_DEVICE1 : cs = SPI1_CS_PIN; m_cs = new ActiveLowChipSelect1(cs, m_settings); @@ -430,7 +416,7 @@ void BASpiMemoryDMA::begin(void) m_dieBoundary = BAHardwareConfig.getSpiMemoryDefinition(MemSelect::MEM0).DIE_BOUNDARY; break; -#if defined(__MK66FX1M0__) // DMA on SPI1 is only supported on T3.6 +#if defined(ARDUINO_TEENSY_MICROMOD) || defined(__MK66FX1M0__) // DMA on SPI1 is only supported on T3.6 or Micromod case SpiDeviceId::SPI_DEVICE1 : m_csPin = SPI1_CS_PIN; m_spi = &SPI1; diff --git a/src/peripherals/DmaSpi.cpp b/src/peripherals/DmaSpi.cpp index f837ed3..18bf164 100644 --- a/src/peripherals/DmaSpi.cpp +++ b/src/peripherals/DmaSpi.cpp @@ -1,15 +1,38 @@ +/* + * DmaSpi.cpp + * + * Created on: Jan 7, 2018 + * Author: slascos + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version.* + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ #include "DmaSpi.h" -#if defined(__IMXRT1062__) // T4.0 -DmaSpi0 DMASPI0; +#if defined(__IMXRT1062__) // T4.X + DmaSpi0 DMASPI0; + #if defined(ARDUINO_TEENSY_MICROMOD) || defined (ARDUINO_TEENSY41) + DmaSpi1 DMASPI1; + #endif + #elif defined(KINETISK) -DmaSpi0 DMASPI0; -#if defined(__MK66FX1M0__) -DmaSpi1 DMASPI1; -//DmaSpi2 DMASPI2; -#endif + DmaSpi0 DMASPI0; + #if defined(__MK66FX1M0__) + DmaSpi1 DMASPI1; + //DmaSpi2 DMASPI2; + #endif #elif defined (KINETISL) -DmaSpi0 DMASPI0; -DmaSpi1 DMASPI1; -#else + DmaSpi0 DMASPI0; + DmaSpi1 DMASPI1; +#else #endif // defined