diff --git a/src/AudioEffectAnalogChorus.h b/src/AudioEffectAnalogChorus.h
index d0ee022..5dbd810 100644
--- a/src/AudioEffectAnalogChorus.h
+++ b/src/AudioEffectAnalogChorus.h
@@ -64,7 +64,6 @@ public:
/// Construct an analog chorus using external SPI via an ExtMemSlot. The chorus will have
/// the default average delay.
/// @param slot A pointer to the ExtMemSlot to use for the delay.
- AudioEffectAnalogChorus(BALibrary::ExtMemSlot *slot); // requires sufficiently sized pre-allocated memory
virtual ~AudioEffectAnalogChorus(); ///< Destructor
diff --git a/src/AudioEffectAnalogDelay.h b/src/AudioEffectAnalogDelay.h
deleted file mode 100644
index 86d4ea6..0000000
--- a/src/AudioEffectAnalogDelay.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * AudioEffectAnalogDelay is a class for simulating a classic BBD based delay
- * like the Boss DM-2. This class works with either internal RAM, or external
- * SPI RAM for longer delays. The exteranl ram uses DMA to minimize load on the
- * CPU.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BAEFFECTS_BAAUDIOEFFECTANALOGDELAY_H
-#define __BAEFFECTS_BAAUDIOEFFECTANALOGDELAY_H
-
-#include
-#include "LibBasicFunctions.h"
-
-namespace BAEffects {
-
-/**************************************************************************//**
- * AudioEffectAnalogDelay models BBD based analog delays. It provides controls
- * for delay, feedback (or regen), mix and output level. All parameters can be
- * controlled by MIDI. The class supports internal memory, or external SPI
- * memory by providing an ExtMemSlot. External memory access uses DMA to reduce
- * process load.
- *****************************************************************************/
-class AudioEffectAnalogDelay : public AudioStream {
-public:
-
- ///< List of AudioEffectAnalogDelay MIDI controllable parameters
- enum {
- BYPASS = 0, ///< controls effect bypass
- DELAY, ///< controls the amount of delay
- FEEDBACK, ///< controls the amount of echo feedback (regen)
- MIX, ///< controls the the mix of input and echo signals
- VOLUME, ///< controls the output volume level
- NUM_CONTROLS ///< this can be used as an alias for the number of MIDI controls
- };
-
- enum class Filter {
- DM3 = 0,
- WARM,
- DARK
- };
-
- // *** CONSTRUCTORS ***
- AudioEffectAnalogDelay() = delete;
-
- /// Construct an analog delay using internal memory by specifying the maximum
- /// delay in milliseconds.
- /// @param maxDelayMs maximum delay in milliseconds. Larger delays use more memory.
- AudioEffectAnalogDelay(float maxDelayMs);
-
- /// Construct an analog delay using internal memory by specifying the maximum
- /// delay in audio samples.
- /// @param numSamples maximum delay in audio samples. Larger delays use more memory.
- AudioEffectAnalogDelay(size_t numSamples);
-
- /// Construct an analog delay using external SPI via an ExtMemSlot. The amount of
- /// delay will be determined by the amount of memory in the slot.
- /// @param slot A pointer to the ExtMemSlot to use for the delay.
- AudioEffectAnalogDelay(BALibrary::ExtMemSlot *slot); // requires sufficiently sized pre-allocated memory
-
- virtual ~AudioEffectAnalogDelay(); ///< Destructor
-
- // *** PARAMETERS ***
-
- /// Set the delay in milliseconds.
- /// @param milliseconds the request delay in milliseconds. Must be less than max delay.
- void delay(float milliseconds);
-
- /// Set the delay in number of audio samples.
- /// @param delaySamples the request delay in audio samples. Must be less than max delay.
- void delay(size_t delaySamples);
-
- /// Set the delay as a fraction of the maximum delay.
- /// The value should be between 0.0f and 1.0f
- void delayFractionMax(float delayFraction);
-
- /// Bypass the effect.
- /// @param byp when true, bypass wil disable the effect, when false, effect is enabled.
- /// Note that audio still passes through when bypass is enabled.
- void bypass(bool byp) { m_bypass = byp; }
-
- /// Get if the effect is bypassed
- /// @returns true if bypassed, false if not bypassed
- bool isBypass() { return m_bypass; }
-
- /// Toggle the bypass effect
- void toggleBypass() { m_bypass = !m_bypass; }
-
- /// Set the amount of echo feedback (a.k.a regeneration).
- /// @param feedback a floating point number between 0.0 and 1.0.
- void feedback(float feedback) { m_feedback = feedback; }
-
- /// Set the amount of blending between dry and wet (echo) at the output.
- /// @param mix When 0.0, output is 100% dry, when 1.0, output is 100% wet. When
- /// 0.5, output is 50% Dry, 50% Wet.
- void mix(float mix) { m_mix = mix; }
-
- /// Set the output volume. This affect both the wet and dry signals.
- /// @details The default is 1.0.
- /// @param vol Sets the output volume between -1.0 and +1.0
- void volume(float vol) {m_volume = vol; }
-
- // ** ENABLE / DISABLE **
-
- /// Enables audio processing. Note: when not enabled, CPU load is nearly zero.
- void enable() { m_enable = true; }
-
- /// Disables audio process. When disabled, CPU load is nearly zero.
- void disable() { m_enable = false; }
-
- // ** MIDI **
-
- /// Sets whether MIDI OMNI channel is processig on or off. When on,
- /// all midi channels are used for matching CCs.
- /// @param isOmni when true, all channels are processed, when false, channel
- /// must match configured value.
- void setMidiOmni(bool isOmni) { m_isOmni = isOmni; }
-
- /// Configure an effect parameter to be controlled by a MIDI CC
- /// number on a particular channel.
- /// @param parameter one of the parameter names in the class enum
- /// @param midiCC the CC number from 0 to 127
- /// @param midiChannel the effect will only response to the CC on this channel
- /// when OMNI mode is off.
- void mapMidiControl(int parameter, int midiCC, int midiChannel = 0);
-
- /// process a MIDI Continous-Controller (CC) message
- /// @param channel the MIDI channel from 0 to 15)
- /// @param midiCC the CC number from 0 to 127
- /// @param value the CC value from 0 to 127
- void processMidi(int channel, int midiCC, int value);
-
- // ** FILTER COEFFICIENTS **
-
- /// Set the filter coefficients to one of the presets. See AudioEffectAnalogDelay::Filter
- /// for options.
- /// @details See AudioEffectAnalogDelayFIlters.h for more details.
- /// @param filter the preset filter. E.g. AudioEffectAnalogDelay::Filter::WARM
- void setFilter(Filter filter);
-
- /// Override the default coefficients with your own. The number of filters stages affects how
- /// much CPU is consumed.
- /// @details The effect uses the CMSIS-DSP library for biquads which requires coefficents.
- /// be in q31 format, which means they are 32-bit signed integers representing -1.0 to slightly
- /// less than +1.0. The coeffShift parameter effectively multiplies the coefficients by 2^shift.
- /// Example: If you really want +1.5, must instead use +0.75 * 2^1, thus 0.75 in q31 format is
- /// (0.75 * 2^31) = 1610612736 and coeffShift = 1.
- /// @param numStages the actual number of filter stages you want to use. Must be <= MAX_NUM_FILTER_STAGES.
- /// @param coeffs pointer to an integer array of coefficients in q31 format.
- /// @param coeffShift Coefficient scaling factor = 2^coeffShift.
- void setFilterCoeffs(int numStages, const int32_t *coeffs, int coeffShift);
-
- virtual void update(void); ///< update automatically called by the Teesny Audio Library
-
-private:
- audio_block_t *m_inputQueueArray[1];
- bool m_isOmni = false;
- bool m_bypass = true;
- bool m_enable = false;
- bool m_externalMemory = false;
- BALibrary::AudioDelay *m_memory = nullptr;
- size_t m_maxDelaySamples = 0;
- audio_block_t *m_previousBlock = nullptr;
- audio_block_t *m_blockToRelease = nullptr;
- BALibrary::IirBiQuadFilterHQ *m_iir = nullptr;
-
- // Controls
- int m_midiConfig[NUM_CONTROLS][2]; // stores the midi parameter mapping
- size_t m_delaySamples = 0;
- float m_feedback = 0.0f;
- float m_mix = 0.0f;
- float m_volume = 1.0f;
-
- void m_preProcessing(audio_block_t *out, audio_block_t *dry, audio_block_t *wet);
- void m_postProcessing(audio_block_t *out, audio_block_t *dry, audio_block_t *wet);
-
- // Coefficients
- void m_constructFilter(void);
-};
-
-}
-
-#endif /* __BAEFFECTS_BAAUDIOEFFECTANALOGDELAY_H */
diff --git a/src/AudioEffectSOS.h b/src/AudioEffectSOS.h
deleted file mode 100644
index 2ab7e8d..0000000
--- a/src/AudioEffectSOS.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * AudioEffectSOS is a class f
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BAEFFECTS_BAAUDIOEFFECTSOS_H
-#define __BAEFFECTS_BAAUDIOEFFECTSOS_H
-
-#include
-#include "LibBasicFunctions.h"
-
-namespace BAEffects {
-
-/**************************************************************************//**
- * AudioEffectSOS
- *****************************************************************************/
-class AudioEffectSOS : public AudioStream {
-public:
-
- ///< List of AudioEffectAnalogDelay MIDI controllable parameters
- enum {
- BYPASS = 0, ///< controls effect bypass
- GATE_TRIGGER, ///< begins the gate sequence
- GATE_OPEN_TIME, ///< controls how long it takes to open the gate
- //GATE_HOLD_TIME, ///< controls how long the gate stays open at unity
- GATE_CLOSE_TIME, ///< controls how long it takes to close the gate (release)
- CLEAR_FEEDBACK_TRIGGER, ///< begins the sequence to clear out the looping feedback
- FEEDBACK, ///< controls the amount of feedback, more gives longer SOS sustain
- VOLUME, ///< controls the output volume level
- NUM_CONTROLS ///< this can be used as an alias for the number of MIDI controls
- };
-
- // *** CONSTRUCTORS ***
- AudioEffectSOS() = delete;
- AudioEffectSOS(float maxDelayMs);
- AudioEffectSOS(size_t numSamples);
-
- /// Construct an analog delay using external SPI via an ExtMemSlot. The amount of
- /// delay will be determined by the amount of memory in the slot.
- /// @param slot A pointer to the ExtMemSlot to use for the delay.
- AudioEffectSOS(BALibrary::ExtMemSlot *slot); // requires sufficiently sized pre-allocated memory
-
- virtual ~AudioEffectSOS(); ///< Destructor
-
- void setGateLedGpio(int pinId);
-
- // *** PARAMETERS ***
- void gateOpenTime(float milliseconds);
-
- void gateCloseTime(float milliseconds);
-
- void feedback(float feedback) { m_feedback = feedback; }
-
- /// Bypass the effect.
- /// @param byp when true, bypass wil disable the effect, when false, effect is enabled.
- /// Note that audio still passes through when bypass is enabled.
- void bypass(bool byp) { m_bypass = byp; }
-
- /// Activate the gate automation. Input gate will open, then close.
- void trigger() { m_inputGateAuto.trigger(); }
-
- /// Activate the delay clearing automation. Input signal will mute, gate will open, then close.
- void clear() { m_clearFeedbackAuto.trigger(); }
-
- /// Set the output volume. This affect both the wet and dry signals.
- /// @details The default is 1.0.
- /// @param vol Sets the output volume between -1.0 and +1.0
- void volume(float vol) {m_volume = vol; }
-
- // ** ENABLE / DISABLE **
-
- /// Enables audio processing. Note: when not enabled, CPU load is nearly zero.
- void enable();
-
- /// Disables audio process. When disabled, CPU load is nearly zero.
- void disable() { m_enable = false; }
-
- // ** MIDI **
-
- /// Sets whether MIDI OMNI channel is processig on or off. When on,
- /// all midi channels are used for matching CCs.
- /// @param isOmni when true, all channels are processed, when false, channel
- /// must match configured value.
- void setMidiOmni(bool isOmni) { m_isOmni = isOmni; }
-
- /// Configure an effect parameter to be controlled by a MIDI CC
- /// number on a particular channel.
- /// @param parameter one of the parameter names in the class enum
- /// @param midiCC the CC number from 0 to 127
- /// @param midiChannel the effect will only response to the CC on this channel
- /// when OMNI mode is off.
- void mapMidiControl(int parameter, int midiCC, int midiChannel = 0);
-
- /// process a MIDI Continous-Controller (CC) message
- /// @param channel the MIDI channel from 0 to 15)
- /// @param midiCC the CC number from 0 to 127
- /// @param value the CC value from 0 to 127
- void processMidi(int channel, int midiCC, int value);
-
- virtual void update(void); ///< update automatically called by the Teesny Audio Library
-
-private:
- audio_block_t *m_inputQueueArray[1];
- bool m_isOmni = false;
- bool m_bypass = true;
- bool m_enable = false;
- BALibrary::AudioDelay *m_memory = nullptr;
- bool m_externalMemory = true;
- audio_block_t *m_previousBlock = nullptr;
- audio_block_t *m_blockToRelease = nullptr;
- size_t m_maxDelaySamples = 0;
- int m_gateLedPinId = -1;
-
- // Controls
- int m_midiConfig[NUM_CONTROLS][2]; // stores the midi parameter mapping
- size_t m_delaySamples = 0;
- float m_openTimeMs = 0.0f;
- float m_closeTimeMs = 0.0f;
- float m_feedback = 0.0f;
- float m_volume = 1.0f;
-
- // Automated Controls
- BALibrary::ParameterAutomationSequence m_inputGateAuto = BALibrary::ParameterAutomationSequence(3);
- BALibrary::ParameterAutomationSequence m_clearFeedbackAuto = BALibrary::ParameterAutomationSequence(3);
-
- // Private functions
- void m_preProcessing (audio_block_t *out, audio_block_t *input, audio_block_t *delayedSignal);
- void m_postProcessing(audio_block_t *out, audio_block_t *input);
-};
-
-}
-
-#endif /* __BAEFFECTS_BAAUDIOEFFECTSOS_H */
diff --git a/src/AudioEffectTremolo.h b/src/AudioEffectTremolo.h
deleted file mode 100644
index 58de0cd..0000000
--- a/src/AudioEffectTremolo.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * Tremolo is a classic volume modulate effect.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY__BAEFFECTS_AUDIOEFFECTDELAYEXTERNAL_H; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BAEFFECTS_AUDIOEFFECTTREMOLO_H
-#define __BAEFFECTS_AUDIOEFFECTTREMOLO_H
-
-#include
-#include "LibBasicFunctions.h"
-
-namespace BAEffects {
-
-/**************************************************************************//**
- * AudioEffectTremolo
- *****************************************************************************/
-class AudioEffectTremolo : public AudioStream {
-public:
-
- ///< List of AudioEffectTremolo MIDI controllable parameters
- enum {
- BYPASS = 0, ///< controls effect bypass
- RATE, ///< controls the rate of the modulation
- DEPTH, ///< controls the depth of the modulation
- WAVEFORM, ///< select the modulation waveform
- VOLUME, ///< controls the output volume level
- NUM_CONTROLS ///< this can be used as an alias for the number of MIDI controls
- };
-
- // *** CONSTRUCTORS ***
- AudioEffectTremolo();
-
- virtual ~AudioEffectTremolo(); ///< Destructor
-
- // *** PARAMETERS ***
- void rate(float rateValue);
-
- void depth(float depthValue) { m_depth = depthValue; }
-
- void setWaveform(BALibrary::Waveform waveform);
-
-
- /// Bypass the effect.
- /// @param byp when true, bypass wil disable the effect, when false, effect is enabled.
- /// Note that audio still passes through when bypass is enabled.
- void bypass(bool byp) { m_bypass = byp; }
-
- /// Get if the effect is bypassed
- /// @returns true if bypassed, false if not bypassed
- bool isBypass() { return m_bypass; }
-
- /// Toggle the bypass effect
- void toggleBypass() { m_bypass = !m_bypass; }
-
- /// Set the output volume. This affect both the wet and dry signals.
- /// @details The default is 1.0.
- /// @param vol Sets the output volume between -1.0 and +1.0
- void volume(float vol) {m_volume = vol; }
-
- // ** ENABLE / DISABLE **
-
- /// Enables audio processing. Note: when not enabled, CPU load is nearly zero.
- void enable() { m_enable = true; }
-
- /// Disables audio process. When disabled, CPU load is nearly zero.
- void disable() { m_enable = false; }
-
- // ** MIDI **
-
- /// Sets whether MIDI OMNI channel is processig on or off. When on,
- /// all midi channels are used for matching CCs.
- /// @param isOmni when true, all channels are processed, when false, channel
- /// must match configured value.
- void setMidiOmni(bool isOmni) { m_isOmni = isOmni; }
-
- /// Configure an effect parameter to be controlled by a MIDI CC
- /// number on a particular channel.
- /// @param parameter one of the parameter names in the class enum
- /// @param midiCC the CC number from 0 to 127
- /// @param midiChannel the effect will only response to the CC on this channel
- /// when OMNI mode is off.
- void mapMidiControl(int parameter, int midiCC, int midiChannel = 0);
-
- /// process a MIDI Continous-Controller (CC) message
- /// @param channel the MIDI channel from 0 to 15)
- /// @param midiCC the CC number from 0 to 127
- /// @param value the CC value from 0 to 127
- void processMidi(int channel, int midiCC, int value);
-
-
- virtual void update(void); ///< update automatically called by the Teesny Audio Library
-
-private:
- audio_block_t *m_inputQueueArray[1];
- BALibrary::LowFrequencyOscillatorVector m_osc;
- int m_midiConfig[NUM_CONTROLS][2]; // stores the midi parameter mapping
- bool m_isOmni = false;
- bool m_bypass = true;
- bool m_enable = false;
-
- float m_rate = 0.0f;
- float m_depth = 0.0f;
- BALibrary::Waveform m_waveform = BALibrary::Waveform::SINE;
- float m_volume = 1.0f;
-
-};
-
-}
-
-#endif /* __BAEFFECTS_AUDIOEFFECTTREMOLO_H */
diff --git a/src/BAAudioControlWM8731.h b/src/BAAudioControlWM8731.h
deleted file mode 100644
index f0e5d6c..0000000
--- a/src/BAAudioControlWM8731.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * BAAudioContromWM8731 is a class for controlling a WM8731 Codec via I2C.
- * @details The Codec power ups in a silent state, with non-optimal
- * configuration. This class will enable codec and set some initial gain levels.
- * The user can than use the API to changing settings for their specific needs.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BALIBRARY_BAAUDIOCONTROLWM8731_H
-#define __BALIBRARY_BAAUDIOCONTROLWM8731_H
-
-namespace BALibrary {
-
-constexpr int WM8731_NUM_REGS = 10; // Number of registers in the internal shadow array
-
-/**************************************************************************//**
- * BAAudioControlWM8731 provides an API for configuring the internal registers
- * of the WM8731 codec.
- * @details Not every single command is provided, please ask if you need something
- * added that is not already present. You can also directly write any register
- * you wish with the writeI2C() method.
- *****************************************************************************/
-class BAAudioControlWM8731 {
-public:
- BAAudioControlWM8731();
- virtual ~BAAudioControlWM8731();
-
- /// Mute and power down the codec.
- void disable(void);
-
- /// First disable, then cleanly power up and unmute the codec.
- void enable(void);
-
- /// Set the input gain of the codec's PGA for the left (TRS Tip) channel.
- /// @param val an interger value from 31 = +12dB . . 1.5dB steps down to 0 = -34.5dB
- void setLeftInputGain(int val);
-
- /// Set the input gain of the codec's PGA for the right (TRS Ring) channel.
- /// @param val an interger value from 31 = +12dB . . 1.5dB steps down to 0 = -34.5dB
- void setRightInputGain(int val);
-
- /// Mute/unmute the Left (TRS Tip) channel at the ADC input.
- /// @param val when true, channel is muted, when false, channel is unmuted
- void setLeftInMute(bool val);
-
- /// Mute/unmute the Right (TRS Ring) channel at the ADC input.
- /// @param val when true, channel is muted, when false, channel is unmuted
- void setRightInMute(bool val);
-
- /// Links the Left/Right channel contols for mute and input gain.
- /// @details when true, changing either the left or right gain/mute controls will
- /// affect both channels.
- /// @param val when true, channels are linked, when false, they are controlled separately
- void setLinkLeftRightIn(bool val);
- /// Swaps the left and right channels in the codec.
- ///param val when true, channels are swapped, else normal.
- void setLeftRightSwap(bool val);
-
- /// Set the volume for the codec's built-in headphone amp
- /// @param volume the input volume level from 0.0f to 1.0f;
- void setHeadphoneVolume(float volume);
-
- /// Mute/unmute the output DAC, affects both Left and Right output channels.
- /// @param when true, output DAC is muted, when false, unmuted.
- void setDacMute(bool val);
-
- /// Control when the DAC is feeding the output analog circuitry.
- /// @param val when true, the DAC output is connected to the analog output. When
- /// false, the DAC is disconnected.
- void setDacSelect(bool val);
-
- /// ADC Bypass control.
- /// @details This permits the analog audio from the Codec's PGA to bypass the ADC
- /// and go directly to the analog output of the codec, bypassing the digital domain
- /// entirely.
- /// @param val when true, analog ADC input is fed directly to codec analog otuput.
- void setAdcBypass(bool val);
-
- /// Digital High Pass Filter disable. RECOMMENDED ALWAYS TRUE!
- /// @details this controls a HPF in the codec that attempts to remove the lowest
- /// frequency (i.e. < 10 Hz) to improve headroom by dynamically measuring DC level.
- /// In most cases, it introduces noise components by modulating the filter. This
- /// is not suitable for applications where the audio is used for output, but might
- /// be useful for applications like tuning, pitch detection, whre the noise components
- /// can be tolerated.
- /// @param val when true (recommended) the dynamic HPF is disabled, otherwise enabled.
- void setHPFDisable(bool val);
-
- /// Activates the I2S interface on the codec.
- /// @param val when true, I2S interface is active, when false it is disabled.
- void setActivate(bool val);
-
- /// Soft-reset the codec.
- /// @details This will cause the codec to reset its internal registers to default values.
- void resetCodec(void);
-
- /// Write a custom command to the codec via I2C control interface.
- /// @details See WM8731 datasheet for register map details.
- /// @param addr The register address you wish to write to, range 0 to 15.
- /// @param val the 9-bit data value you wish to write at the address specifed.
- bool writeI2C(unsigned int addr, unsigned int val);
-
-protected:
- // A shadow array for the registers on the codec since the interface is write-only.
- int regArray[WM8731_NUM_REGS];
-
-private:
- // low-level write command
- bool write(unsigned int reg, unsigned int val);
- // resets the internal shadow register array
- void resetInternalReg(void);
-
- bool m_wireStarted = false;
-
-};
-
-} /* namespace BALibrary */
-
-#endif /* __BALIBRARY_BAAUDIOCONTROLWM8731_H */
diff --git a/src/BAAudioEffectDelayExternal.h b/src/BAAudioEffectDelayExternal.h
deleted file mode 100644
index 9e88b21..0000000
--- a/src/BAAudioEffectDelayExternal.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * BAAudioEffectDelayExternal is a class for using an external SPI SRAM chip
- * as an audio delay line. The external memory can be shared among several
- * different instances of BAAudioEffectDelayExternal by specifying the max delay
- * length during construction.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BAEFFECTS_BAAUDIOEFFECTDELAYEXTERNAL_H
-#define __BAEFFECTS_BAAUDIOEFFECTDELAYEXTERNAL_H
-
-#include
-#include "AudioStream.h"
-
-#include "BAHardware.h"
-
-namespace BAEffects {
-
-/**************************************************************************//**
- * BAAudioEffectDelayExternal can use external SPI RAM for delay rather than
- * the limited RAM available on the Teensy itself.
- *****************************************************************************/
-class BAAudioEffectDelayExternal : public AudioStream
-{
-public:
-
- /// Default constructor will use all memory available in MEM0
- BAAudioEffectDelayExternal();
-
- /// Specifiy which external memory to use
- /// @param type specify which memory to use
- BAAudioEffectDelayExternal(BALibrary::MemSelect type);
-
- /// Specify external memory, and how much of the memory to use
- /// @param type specify which memory to use
- /// @param delayLengthMs maximum delay length in milliseconds
- BAAudioEffectDelayExternal(BALibrary::MemSelect type, float delayLengthMs);
- virtual ~BAAudioEffectDelayExternal();
-
- /// set the actual amount of delay on a given delay tap
- /// @param channel specify channel tap 1-8
- /// @param milliseconds specify how much delay for the specified tap
- void delay(uint8_t channel, float milliseconds);
-
- /// Disable a delay channel tap
- /// @param channel specify channel tap 1-8
- void disable(uint8_t channel);
-
- virtual void update(void);
-
- static unsigned m_usingSPICount[2]; // internal use for all instances
-
-private:
- void initialize(BALibrary::MemSelect mem, unsigned delayLength = 1e6);
- void read(uint32_t address, uint32_t count, int16_t *data);
- void write(uint32_t address, uint32_t count, const int16_t *data);
- void zero(uint32_t address, uint32_t count);
- unsigned m_memoryStart; // the first address in the memory we're using
- unsigned m_memoryLength; // the amount of memory we're using
- unsigned m_headOffset; // head index (incoming) data into external memory
- unsigned m_channelDelayLength[8]; // # of sample delay for each channel (128 = no delay)
- unsigned m_activeMask; // which output channels are active
- static unsigned m_allocated[2];
- audio_block_t *m_inputQueueArray[1];
-
- BALibrary::MemSelect m_mem;
- SPIClass *m_spi = nullptr;
- int m_spiChannel = 0;
- int m_misoPin = 0;
- int m_mosiPin = 0;
- int m_sckPin = 0;
- int m_csPin = 0;
-
- void m_startUsingSPI(int spiBus);
- void m_stopUsingSPI(int spiBus);
-};
-
-
-} /* namespace BAEffects */
-
-#endif /* __BAEFFECTS_BAAUDIOEFFECTDELAYEXTERNAL_H */
diff --git a/src/BAEffects.h b/src/BAEffects.h
index c331137..f40eded 100644
--- a/src/BAEffects.h
+++ b/src/BAEffects.h
@@ -22,10 +22,6 @@
#include "BALibrary.h" // contains the Blackaddr hardware board definitions
-#include "BAAudioEffectDelayExternal.h"
-#include "AudioEffectAnalogDelay.h"
-#include "AudioEffectSOS.h"
-#include "AudioEffectTremolo.h"
#include "AudioEffectAnalogChorus.h"
#endif /* __BAEFFECTS_H */
diff --git a/src/BAGpio.h b/src/BAGpio.h
deleted file mode 100644
index f7766af..0000000
--- a/src/BAGpio.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * BAGPio is convenience class for accessing the the various GPIOs available
- * on the Teensy Guitar Audio series boards.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BALIBRARY_BAGPIO_H
-#define __BALIBRARY_BAGPIO_H
-
-#include "BAHardware.h"
-
-namespace BALibrary {
-
-/**************************************************************************//**
- * BAGpio provides a convince class to easily control the direction and state
- * of the GPIO pins available on the TGA headers.
- * @details you can always control this directly with Arduino commands like
- * digitalWrite(), etc.
- *****************************************************************************/
-class BAGpio {
-public:
- /// Construct a GPIO object for controlling the various GPIO and user pins
- BAGpio();
- virtual ~BAGpio();
-
- /// Set the direction of the specified GPIO pin.
- /// @param gpioId Specify a GPIO pin such as GPIO::GPIO0
- /// @param specify direction as INPUT or OUTPUT which are Arduino constants
- void setGPIODirection(GPIO gpioId, int direction);
-
- /// Set the state of the specified GPIO to high
- /// @param gpioId gpioId Specify a GPIO pin such as GPIO::GPIO0
- void setGPIO(GPIO gpioId);
-
- /// Clear the state of the specified GPIO pin.
- /// @param gpioId gpioId Specify a GPIO pin such as GPIO::GPIO0
- void clearGPIO(GPIO gpioId);
-
- /// Toggle the state of the specified GPIO pin. Only works if configured as output.
- /// @param gpioId gpioId Specify a GPIO pin such as GPIO::GPIO0
- /// @returns the new state of the pin
- int toggleGPIO(GPIO gpioId);
-
- /// Turn on the user LED
- void setLed();
-
- /// Turn off the user LED
- void clearLed();
-
- /// Toggle the stage of the user LED
- /// @returns the new stage of the user LED.
- int toggleLed();
-
-private:
- uint8_t m_ledState;
-};
-
-} /* namespace BALibrary */
-
-#endif /* __BALIBRARY_BAGPIO_H */
diff --git a/src/BAHardware.h b/src/BAHardware.h
deleted file mode 100644
index 68e77db..0000000
--- a/src/BAHardware.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * This file contains specific definitions for each Blackaddr Audio hardware
- * board.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BALIBRARY_BAHARDWARE_H
-#define __BALIBRARY_BAHARDWARE_H
-
-#include
-#include
-#include
-
-/**************************************************************************//**
- * BALibrary is a namespace/Library for Guitar processing from Blackaddr Audio.
- *****************************************************************************/
-namespace BALibrary {
-
-// uncomment the line that corresponds to your hardware
-//#define TGA_PRO_REVA
-#if (!defined(TGA_PRO_REVA) && !defined(TGA_PRO_REVB))
-#define TGA_PRO_REVA
-#endif
-
-#if defined(TGA_PRO_REVA) || defined(TGA_PRO_REVB)
-
-constexpr uint8_t USR_LED_ID = 16; ///< Teensy IO number for the user LED.
-
-/**************************************************************************//**
- * GPIOs and Testpoints are accessed via enumerated class constants.
- *****************************************************************************/
-enum class GPIO : uint8_t {
- GPIO0 = 2,
- GPIO1 = 3,
- GPIO2 = 4,
- GPIO3 = 6,
-
- GPIO4 = 12,
- GPIO5 = 32,
- GPIO6 = 27,
- GPIO7 = 28,
-
- TP1 = 34,
- TP2 = 33
-};
-
-/**************************************************************************//**
- * Optionally installed SPI RAM
- *****************************************************************************/
-constexpr unsigned NUM_MEM_SLOTS = 2;
-enum MemSelect : unsigned {
- MEM0 = 0, ///< SPI RAM MEM0
- MEM1 = 1 ///< SPI RAM MEM1
-};
-
-/**************************************************************************//**
- * Set the maximum address (byte-based) in the external SPI memories
- *****************************************************************************/
-constexpr size_t MEM_MAX_ADDR[NUM_MEM_SLOTS] = { 131071, 131071 };
-
-
-/**************************************************************************//**
- * General Purpose SPI Interfaces
- *****************************************************************************/
-enum class SpiDeviceId : unsigned {
- SPI_DEVICE0 = 0, ///< Arduino SPI device
- SPI_DEVICE1 = 1 ///< Arduino SPI1 device
-};
-constexpr int SPI_MAX_ADDR = 131071; ///< Max address size per chip
-constexpr size_t SPI_MEM0_SIZE_BYTES = 131072;
-constexpr size_t SPI_MEM0_MAX_AUDIO_SAMPLES = SPI_MEM0_SIZE_BYTES/sizeof(int16_t);
-
-constexpr size_t SPI_MEM1_SIZE_BYTES = 131072;
-constexpr size_t SPI_MEM1_MAX_AUDIO_SAMPLES = SPI_MEM1_SIZE_BYTES/sizeof(int16_t);
-
-
-
-#else
-
-#error "No hardware declared"
-
-#endif
-
-#if defined (TGA_PRO_EXPAND_REV2)
-/**************************************************************************//**
- * Blackaddr Audio Expansion Board
- *****************************************************************************/
-constexpr unsigned BA_EXPAND_NUM_POT = 3;
-constexpr unsigned BA_EXPAND_NUM_SW = 2;
-constexpr unsigned BA_EXPAND_NUM_LED = 2;
-constexpr unsigned BA_EXPAND_NUM_ENC = 0;
-
-constexpr uint8_t BA_EXPAND_POT1_PIN = A16; // 35_A16_PWM
-constexpr uint8_t BA_EXPAND_POT2_PIN = A17; // 36_A17_PWM
-constexpr uint8_t BA_EXPAND_POT3_PIN = A18; // 37_SCL1_A18_PWM
-constexpr uint8_t BA_EXPAND_SW1_PIN = 2; // 2)PWM
-constexpr uint8_t BA_EXPAND_SW2_PIN = 3; // 3_SCL2_PWM
-constexpr uint8_t BA_EXPAND_LED1_PIN = 4; // 4_SDA2_PWM
-constexpr uint8_t BA_EXPAND_LED2_PIN = 6; // 6_PWM
-#endif
-
-} // namespace BALibrary
-
-
-#endif /* __BALIBRARY_BAHARDWARE_H */
diff --git a/src/BALibrary.h b/src/BALibrary.h
index 9a0a3d3..456253c 100644
--- a/src/BALibrary.h
+++ b/src/BALibrary.h
@@ -20,15 +20,7 @@
#ifndef __BALIBRARY_H
#define __BALIBRARY_H
-#include "BAHardware.h" // contains the Blackaddr hardware board definitions
-
#include "BATypes.h"
#include "LibBasicFunctions.h"
-#include "LibMemoryManagement.h"
-
-#include "BAAudioControlWM8731.h" // Codec Control
-#include "BASpiMemory.h"
-#include "BAGpio.h"
-#include "BAPhysicalControls.h"
#endif /* __BALIBRARY_H */
diff --git a/src/BAPhysicalControls.h b/src/BAPhysicalControls.h
deleted file mode 100644
index 859d698..0000000
--- a/src/BAPhysicalControls.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * BAPhysicalControls is a general purpose class for handling an array of
- * pots, switches, rotary encoders and outputs (for LEDs or relays).
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-#ifndef __BAPHYSICALCONTROLS_H
-#define __BAPHYSICALCONTROLS_H
-
-#include
-#include
-#include
-
-namespace BALibrary {
-
-constexpr bool SWAP_DIRECTION = true; ///< Use when specifying direction should be swapped
-constexpr bool NOSWAP_DIRECTION = false; ///< Use when specifying direction should not be swapped
-
-/// Convenience class for handling a digital output with regard to setting and toggling stage
-class DigitalOutput {
-public:
- DigitalOutput() = delete; // delete the default constructor
-
- /// Construct an object to control the specified pin
- /// @param pin the "Logical Arduino" pin number (not the physical pin number
- DigitalOutput(uint8_t pin) : m_pin(pin) {}
-
- /// Set the output value
- /// @param val when zero output is low, otherwise output his high
- void set(int val);
-
- /// Toggle the output value current state
- void toggle(void);
-
-private:
- uint8_t m_pin; ///< store the pin associated with this output
- int m_val = 0; ///< store the value to support toggling
-};
-
-/// Convenience class for handling digital inputs. This wraps Bounce with the abilty
-/// to invert the polarity of the pin.
-class DigitalInput : public Bounce {
-public:
- /// Create an input where digital low is return true. Most switches ground when pressed.
- DigitalInput() : m_isPolarityInverted(true) {}
-
- /// Create an input and specify if input polarity is inverted.
- /// @param isPolarityInverted when false, a high voltage on the pin returns true, 0V returns false.
- DigitalInput(bool isPolarityInverted) : m_isPolarityInverted(isPolarityInverted) {}
-
- /// Read the state of the pin according to the polarity
- /// @returns true when the input should be interpreted as the switch is closed, else false.
- bool read() { return Bounce::read() != m_isPolarityInverted; } // logical XOR to conditionally invert polarity
-
- /// Set whether the input pin polarity
- /// @param polarity when true, a low voltage on the pin is considered true by read(), else false.
- void setPolarityInverted(bool polarity) { m_isPolarityInverted = polarity; }
-
- /// Check if input has toggled from low to high to low by looking for falling edges
- /// @returns true if the switch has toggled
- bool hasInputToggled();
-
- /// Check if the input is asserted
- /// @returns true if the switch is held
- bool isInputAssert();
-
- /// Get the raw input value (ignores polarity inversion)
- /// @returns returns true is physical pin is high, else false
- bool getPinInputValue();
-
- /// Store the current switch state and return true if it has changed.
- /// @param switchState variable to store switch state in
- /// @returns true when switch stage has changed since last check
- bool hasInputChanged(bool &switchState);
-
-private:
- bool m_isPolarityInverted;
- bool m_isPushed;
-};
-
-/// Convenience class for handling an analog pot as a control. When calibrated,
-/// returns a float between 0.0 and 1.0.
-class Potentiometer {
-public:
- /// Calibration data for a pot includes it's min and max value, as well as whether
- /// direction should be swapped. Swapping depends on the physical orientation of the
- /// pot.
- struct Calib {
- unsigned min; ///< The value from analogRead() when the pot is fully counter-clockwise (normal orientation)
- unsigned max; ///< The value from analogRead() when the pot is fully clockwise (normal orientation)
- bool swap; ///< when orientation is such that fully clockwise would give max reading, swap changes it to the min
- };
-
- Potentiometer() = delete; // delete the default constructor
-
- /// Construction requires the Arduino analog pin number, as well as calibration values.
- /// @param analogPin The analog Arduino pin literal. This the number on the Teensy pinout preceeeded by an A in the local pin name. E.g. "A17".
- /// @param minCalibration See Potentiometer::calibrate()
- /// @param maxCalibration See Potentiometer::calibrate()
- /// @param swapDirection Optional param. See Potentiometer::calibrate()
- Potentiometer(uint8_t analogPin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection = false);
-
- /// Get new value from the pot.
- /// @param value reference to a float, the new value will be written here. Value is between 0.0 and 1.0f.
- /// @returns true if the value has changed, false if it has not
- bool getValue(float &value);
-
- /// Get the raw int value directly from analogRead()
- /// @returns an integer between 0 and 1023.
- int getRawValue();
-
- /// Adjust the calibrate threshold. This is a factor that shrinks the calibration range slightly to
- /// ensure the full range from 0.0f to 1.0f can be obtained.
- /// @details temperature change can slightly alter the calibration values. This factor causes the value
- /// to hit min or max just before the end of the pots travel to compensate.
- /// @param thresholdFactor typical value is 0.01f to 0.05f
- void adjustCalibrationThreshold(float thresholdFactor);
-
- /// Set the amount of feedback in the IIR filter used to smooth the pot readings
- /// @details actual filter reponse deptnds on the rate you call getValue()
- /// @param filterValue typical values are 0.80f to 0.95f
- void setFeedbackFitlerValue(float fitlerValue);
-
- void setCalibrationValues(unsigned min, unsigned max, bool swapDirection);
-
- /// Call this static function before creating the object to obtain calibration data. The sequence
- /// involves prompts over the Serial port.
- /// @details E.g. call Potentiometer::calibrate(PIN). See BAExpansionCalibrate.ino in the library examples.
- /// @param analogPin the Arduino analog pin number connected to the pot you wish to calibraate.
- /// @returns populated Potentiometer::Calib structure
- static Calib calibrate(uint8_t analogPin);
-
-private:
- uint8_t m_pin; ///< store the Arduino pin literal, e.g. A17
- bool m_swapDirection; ///< swap when pot orientation is upside down
- unsigned m_minCalibration; ///< stores the min pot value
- unsigned m_maxCalibration; ///< stores the max pot value
- unsigned m_lastValue = 0; ///< stores previous value
- float m_feedbackFitlerValue = 0.9f; ///< feedback value for POT filter
- float m_thresholdFactor = 0.05f; ///< threshold factor causes values pot to saturate faster at the limits, default is 5%
- unsigned m_minCalibrationThresholded; ///< stores the min pot value after thresholding
- unsigned m_maxCalibrationThresholded; ///< stores the max pot value after thresholding
- unsigned m_rangeThresholded; ///< stores the range of max - min after thresholding
-};
-
-/// Convenience class for rotary (quadrature) encoders. Uses Arduino Encoder under the hood.
-class RotaryEncoder : public Encoder {
-public:
- RotaryEncoder() = delete; // delete default constructor
-
- /// Constructor an encoder with the specified pins. Optionally swap direction and divide down the number of encoder ticks
- /// @param pin1 the Arduino logical pin number for the 'A' on the encoder.
- /// @param pin2 the Arduino logical pin number for the 'B' on the encoder.
- /// @param swapDirection (OPTIONAL) set to true or false to obtain clockwise increments the counter-clockwise decrements
- /// @param divider (OPTIONAL) controls the sensitivity of the divider. Use powers of 2. E.g. 1, 2, 4, 8, etc.
- RotaryEncoder(uint8_t pin1, uint8_t pin2, bool swapDirection = false, int divider = 1) : Encoder(pin1,pin2), m_swapDirection(swapDirection), m_divider(divider) {}
-
- /// Get the delta (as a positive or negative number) since last call
- /// @returns an integer representing the net change since last call
- int getChange();
-
- /// Set the divider on the internal counter. High resolution encoders without detents can be overly sensitive.
- /// This will helf reduce sensisitive by increasing the divider. Default = 1.
- /// @pram divider controls the sensitivity of the divider. Use powers of 2. E.g. 1, 2, 4, 8, etc.
- void setDivider(int divider);
-
-private:
- bool m_swapDirection; ///< specifies if increment/decrement should be swapped
- int32_t m_lastPosition = 0; ///< store the last recorded position
- int32_t m_divider; ///< divides down the magnitude of change read by the encoder.
-};
-
-/// Specifies the type of control
-enum class ControlType : unsigned {
- SWITCH_MOMENTARY = 0, ///< a momentary switch, which is only on when pressed.
- SWITCH_LATCHING = 1, ///< a latching switch, which toggles between on and off with each press and release
- ROTARY_KNOB = 2, ///< a rotary encoder knob
- POT = 3, ///< an analog potentiometer
- UNDEFINED = 255 ///< undefined or uninitialized
-};
-
-/// Tjis class provides convenient interface for combinary an arbitrary number of controls of different types into
-/// one object. Supports switches, pots, encoders and digital outputs (useful for LEDs, relays).
-class BAPhysicalControls {
-public:
- BAPhysicalControls() = delete;
-
- /// Construct an object and reserve memory for the specified number of controls. Encoders and outptus are optional params.
- /// @param numSwitches the number of switches or buttons
- /// @param numPots the number of analog potentiometers
- /// @param numEncoders the number of quadrature encoders
- /// @param numOutputs the number of digital outputs. E.g. LEDs, relays, etc.
- BAPhysicalControls(unsigned numSwitches, unsigned numPots, unsigned numEncoders = 0, unsigned numOutputs = 0);
- ~BAPhysicalControls() {}
-
- /// add a rotary encoders to the controls
- /// @param pin1 the pin number corresponding to 'A' on the encoder
- /// @param pin2 the pin number corresponding to 'B' on the encoder
- /// @param swapDirection When true, reverses which rotation direction is positive, and which is negative
- /// @param divider optional, for encoders with high resolution this divides down the rotation measurement.
- /// @returns the index in the encoder vector the new encoder was placed at.
- unsigned addRotary(uint8_t pin1, uint8_t pin2, bool swapDirection = false, int divider = 1);
-
- /// add a switch to the controls
- /// @param pin the pin number connected to the switch
- /// @param intervalMilliseconds, optional, specifies the filtering time to debounce a switch
- /// @returns the index in the switch vector the new switch was placed at.
- unsigned addSwitch(uint8_t pin, unsigned long intervalMilliseconds = 10);
-
- /// add a pot to the controls
- /// @param pin the pin number connected to the wiper of the pot
- /// @param minCalibration the value corresponding to lowest pot setting
- /// @param maxCalibration the value corresponding to the highest pot setting
- unsigned addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration);
-
- /// add a pot to the controls
- /// @param pin the pin number connected to the wiper of the pot
- /// @param minCalibration the value corresponding to lowest pot setting
- /// @param maxCalibration the value corresponding to the highest pot setting
- /// @param swapDirection reverses the which direction is considered pot minimum value
- /// @param range the pot raw value will be mapped into a range of 0 to range
- unsigned addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection);
-
- /// add an output to the controls
- /// @param pin the pin number connected to the Arduino output
- /// @returns a handle (unsigned) to the added output. Use this to access the output.
- unsigned addOutput(uint8_t pin);
-
- /// Set the output specified by the provided handle
- /// @param handle the handle that was provided previously by calling addOutput()
- /// @param val the value to set the output. 0 is low, not zero is high.
- void setOutput(unsigned handle, int val);
-
- /// Set the output specified by the provided handle
- /// @param handle the handle that was provided previously by calling addOutput()
- /// @param val the value to set the output. True is high, false is low.
- void setOutput(unsigned handle, bool val);
-
- /// Toggle the output specified by the provided handle
- /// @param handle the handle that was provided previously by calling addOutput()
- void toggleOutput(unsigned handle);
-
- /// Retrieve the change in position on the specified rotary encoder
- /// @param handle the handle that was provided previously by calling addRotary()
- /// @returns an integer value. Positive is clockwise, negative is counter-clockwise rotation.
- int getRotaryAdjustUnit(unsigned handle);
-
- /// Check if the pot specified by the handle has been updated.
- /// @param handle the handle that was provided previously by calling addPot()
- /// @param value a reference to a float, the pot value will be written to this variable.
- /// @returns true if the pot value has changed since previous check, otherwise false
- bool checkPotValue(unsigned handle, float &value);
-
- /// Get the raw uncalibrated value from the pot
- /// @returns uncalibrated pot value
- int getPotRawValue(unsigned handle);
-
- /// Override the calibration values with new values
- /// @param handle handle the handle that was provided previously by calling addPot()
- /// @param min the min raw value for the pot
- /// @param max the max raw value for the pot
- /// @param swapDirection when true, max raw value will mean min control value
- /// @returns false when handle is out of range
- bool setCalibrationValues(unsigned handle, unsigned min, unsigned max, bool swapDirection);
-
- /// Check if the switch has been toggled since last call
- /// @param handle the handle that was provided previously by calling addSwitch()
- /// @returns true if the switch changed state, otherwise false
- bool isSwitchToggled(unsigned handle);
-
- /// Check if the switch is currently being pressed (held)
- /// @param handle the handle that was provided previously by calling addSwitch()
- /// @returns true if the switch is held in a pressed or closed state
- bool isSwitchHeld(unsigned handle);
-
- /// Get the value of the switch
- /// @param handle the handle that was provided previously by calling addSwitch()
- /// @returns the value at the switch pin, either 0 or 1.
- bool getSwitchValue(unsigned handle);
-
- /// Determine if a switch has changed value
- /// @param handle the handle that was provided previously by calling addSwitch()
- /// @param switchValue a boolean to store the new switch value
- /// @returns true if the switch has changed
- bool hasSwitchChanged(unsigned handle, bool &switchValue);
-
-private:
- std::vector m_pots; ///< a vector of all added pots
- std::vector m_encoders; ///< a vector of all added encoders
- std::vector m_switches; ///< a vector of all added switches
- std::vector m_outputs; ///< a vector of all added outputs
-};
-
-
-} // BALibrary
-
-
-#endif /* __BAPHYSICALCONTROLS_H */
diff --git a/src/BASpiMemory.h b/src/BASpiMemory.h
deleted file mode 100644
index 92e83fc..0000000
--- a/src/BASpiMemory.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * BASpiMemory is convenience class for accessing the optional SPI RAMs on
- * the GTA Series boards. BASpiMemoryDma works the same but uses DMA to reduce
- * load on the processor.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-#ifndef __BALIBRARY_BASPIMEMORY_H
-#define __BALIBRARY_BASPIMEMORY_H
-
-#include
-#include
-
-#include "BATypes.h"
-#include "BAHardware.h"
-
-namespace BALibrary {
-
-/**************************************************************************//**
- * This wrapper class uses the Arduino SPI (Wire) library to access the SPI ram.
- * @details The purpose of this class is primilary for functional testing since
- * it currently support single-word access. High performance access should be
- * done using DMA techniques in the Teensy library.
- *****************************************************************************/
-class BASpiMemory {
-public:
- BASpiMemory() = delete;
- /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2).
- /// @details default is 20 Mhz
- /// @param memDeviceId specify which MEM to control with SpiDeviceId.
- BASpiMemory(SpiDeviceId memDeviceId);
- /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2)
- /// @param memDeviceId specify which MEM to control with SpiDeviceId.
- /// @param speedHz specify the desired speed in Hz.
- BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz);
- virtual ~BASpiMemory();
-
- /// initialize and configure the SPI peripheral
- virtual void begin();
-
- /// write a single 8-bit word to the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param data the value to write
- void write(size_t address, uint8_t data);
-
- /// Write a block of 8-bit data to the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param src pointer to the source data block
- /// @param numBytes size of the data block in bytes
- virtual void write(size_t address, uint8_t *src, size_t numBytes);
-
- /// Write a block of zeros to the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param numBytes size of the data block in bytes
- virtual void zero(size_t address, size_t numBytes);
-
- /// write a single 16-bit word to the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param data the value to write
- void write16(size_t address, uint16_t data);
-
- /// Write a block of 16-bit data to the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param src pointer to the source data block
- /// @param numWords size of the data block in 16-bit words
- virtual void write16(size_t address, uint16_t *src, size_t numWords);
-
- /// Write a block of 16-bit zeros to the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param numWords size of the data block in 16-bit words
- virtual void zero16(size_t address, size_t numWords);
-
- /// read a single 8-bit data word from the specified address
- /// @param address the address in the SPI RAM to read from
- /// @return the data that was read
- uint8_t read(size_t address);
-
- /// Read a block of 8-bit data from the specified address
- /// @param address the address in the SPI RAM to write to
- /// @param dest pointer to the destination
- /// @param numBytes size of the data block in bytes
- virtual void read(size_t address, uint8_t *dest, size_t numBytes);
-
- /// read a single 16-bit data word from the specified address
- /// @param address the address in the SPI RAM to read from
- /// @return the data that was read
- uint16_t read16(size_t address);
-
- /// read a block 16-bit data word from the specified address
- /// @param address the address in the SPI RAM to read from
- /// @param dest the pointer to the destination
- /// @param numWords the number of 16-bit words to transfer
- virtual void read16(size_t address, uint16_t *dest, size_t numWords);
-
- /// Check if the class has been configured by a previous begin() call
- /// @returns true if initialized, false if not yet initialized
- bool isStarted() const { return m_started; }
-
-protected:
- SPIClass *m_spi = nullptr;
- SpiDeviceId m_memDeviceId; // the MEM device being control with this instance
- uint8_t m_csPin; // the IO pin number for the CS on the controlled SPI device
- SPISettings m_settings; // the Wire settings for this SPI port
- bool m_started = false;
-
-};
-
-
-class BASpiMemoryDMA : public BASpiMemory {
-public:
- BASpiMemoryDMA() = delete;
-
- /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2).
- /// @details default is 20 Mhz
- /// @param memDeviceId specify which MEM to control with SpiDeviceId.
- BASpiMemoryDMA(SpiDeviceId memDeviceId);
-
- /// Create an object to control either MEM0 (via SPI1) or MEM1 (via SPI2)
- /// @param memDeviceId specify which MEM to control with SpiDeviceId.
- /// @param speedHz specify the desired speed in Hz.
- BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz);
- virtual ~BASpiMemoryDMA();
-
- /// initialize and configure the SPI peripheral
- void begin() override;
-
- /// Write a block of 8-bit data to the specified address. Be check
- /// isWriteBusy() before sending the next DMA transfer.
- /// @param address the address in the SPI RAM to write to
- /// @param src pointer to the source data block
- /// @param numBytes size of the data block in bytes
- void write(size_t address, uint8_t *src, size_t numBytes) override;
-
- /// Write a block of zeros to the specified address. Be check
- /// isWriteBusy() before sending the next DMA transfer.
- /// @param address the address in the SPI RAM to write to
- /// @param numBytes size of the data block in bytes
- void zero(size_t address, size_t numBytes) override;
-
- /// Write a block of 16-bit data to the specified address. Be check
- /// isWriteBusy() before sending the next DMA transfer.
- /// @param address the address in the SPI RAM to write to
- /// @param src pointer to the source data block
- /// @param numWords size of the data block in 16-bit words
- void write16(size_t address, uint16_t *src, size_t numWords) override;
-
- /// Write a block of 16-bit zeros to the specified address. Be check
- /// isWriteBusy() before sending the next DMA transfer.
- /// @param address the address in the SPI RAM to write to
- /// @param numWords size of the data block in 16-bit words
- void zero16(size_t address, size_t numWords) override;
-
- /// Read a block of 8-bit data from the specified address. Be check
- /// isReadBusy() before sending the next DMA transfer.
- /// @param address the address in the SPI RAM to write to
- /// @param dest pointer to the destination
- /// @param numBytes size of the data block in bytes
- void read(size_t address, uint8_t *dest, size_t numBytes) override;
-
- /// read a block 16-bit data word from the specified address. Be check
- /// isReadBusy() before sending the next DMA transfer.
- /// @param address the address in the SPI RAM to read from
- /// @param dest the pointer to the destination
- /// @param numWords the number of 16-bit words to transfer
- void read16(size_t address, uint16_t *dest, size_t numWords) override;
-
- /// Check if a DMA write is in progress
- /// @returns true if a write DMA is in progress, else false
- bool isWriteBusy() const;
-
- /// Check if a DMA read is in progress
- /// @returns true if a read DMA is in progress, else false
- bool isReadBusy() const;
-
- /// Readout the 8-bit contents of the DMA storage buffer to the specified destination
- /// @param dest pointer to the destination
- /// @param numBytes number of bytes to read out
- /// @param byteOffset, offset from the start of the DMA buffer in bytes to begin reading
- void readBufferContents(uint8_t *dest, size_t numBytes, size_t byteOffset = 0);
-
- /// Readout the 8-bit contents of the DMA storage buffer to the specified destination
- /// @param dest pointer to the destination
- /// @param numWords number of 16-bit words to read out
- /// @param wordOffset, offset from the start of the DMA buffer in words to begin reading
- void readBufferContents(uint16_t *dest, size_t numWords, size_t wordOffset = 0);
-
-private:
-
- DmaSpiGeneric *m_spiDma = nullptr;
- AbstractChipSelect *m_cs = nullptr;
-
- uint8_t *m_txCommandBuffer = nullptr;
- DmaSpi::Transfer *m_txTransfer;
- uint8_t *m_rxCommandBuffer = nullptr;
- DmaSpi::Transfer *m_rxTransfer;
-
- uint16_t m_txXferCount;
- uint16_t m_rxXferCount;
-
- void m_setSpiCmdAddr(int command, size_t address, uint8_t *dest);
-};
-
-
-} /* namespace BALibrary */
-
-#endif /* __BALIBRARY_BASPIMEMORY_H */
diff --git a/src/DmaSpi.h b/src/DmaSpi.h
deleted file mode 100644
index 9f57c25..0000000
--- a/src/DmaSpi.h
+++ /dev/null
@@ -1,1024 +0,0 @@
-#ifndef DMASPI_H
-#define DMASPI_H
-
-#include
-#include
-
-#if(!defined(__arm__) && defined(TEENSYDUINO))
- #error This library is for teensyduino 1.21 on Teensy 3.0, 3.1 and Teensy LC only.
-#endif
-
-#include
-#include "DMAChannel.h"
-#include
-
-
-/** \brief Specifies the desired CS suppression
-**/
-enum TransferType
-{
- NORMAL, //*< The transfer will use CS at beginning and end **/
- NO_START_CS, //*< Skip the CS activation at the start **/
- NO_END_CS //*< SKip the CS deactivation at the end **/
-};
-
-/** \brief An abstract base class that provides an interface for chip select classes.
-**/
-class AbstractChipSelect
-{
- public:
- /** \brief Called to select a chip. The implementing class can do other things as well.
- **/
- virtual void select(TransferType transferType = TransferType::NORMAL) = 0;
-
- /** \brief Called to deselect a chip. The implementing class can do other things as well.
- **/
- virtual void deselect(TransferType transferType = TransferType::NORMAL) = 0;
-
- /** \brief the virtual destructor needed to inherit from this class **/
- virtual ~AbstractChipSelect() {}
-};
-
-
-/** \brief "do nothing" chip select class **/
-class DummyChipSelect : public AbstractChipSelect
-{
- void select(TransferType transferType = TransferType::NORMAL) override {}
-
- void deselect(TransferType transferType = TransferType::NORMAL) override {}
-};
-
-/** \brief "do nothing" chip select class that
- * outputs a message through Serial when something happens
-**/
-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()");}
-};
-
-/** \brief An active low chip select class. This also configures the given pin.
- * Warning: This class is hardcoded to manage a transaction on SPI (SPI0, that is).
- * If you want to use SPI1: Use AbstractChipSelect1 (see below)
- * If you want to use SPI2: Create AbstractChipSelect2 (adapt the implementation accordingly).
- * Something more flexible is on the way.
-**/
-class ActiveLowChipSelect : public AbstractChipSelect
-{
- public:
- /** Configures a chip select pin for OUTPUT mode,
- * manages the chip selection and a corresponding SPI transaction
- *
- * The chip select pin is asserted \e after the SPI settings are applied
- * and deasserted before the SPI transaction ends.
- * \param pin the CS pin to use
- * \param settings which SPI settings to apply when the chip is selected
- **/
- ActiveLowChipSelect(const unsigned int& pin, const SPISettings& settings)
- : pin_(pin),
- settings_(settings)
- {
- pinMode(pin, OUTPUT);
- digitalWriteFast(pin, 1);
- }
-
- /** \brief begins an SPI transaction selects the chip (sets the pin to low) and
- **/
- void select(TransferType transferType = TransferType::NORMAL) override
- {
- SPI.beginTransaction(settings_);
- if (transferType == TransferType::NO_START_CS) {
- return;
- }
- digitalWriteFast(pin_, 0);
- }
-
- /** \brief deselects the chip (sets the pin to high) and ends the SPI transaction
- **/
- void deselect(TransferType transferType = TransferType::NORMAL) override
- {
- if (transferType == TransferType::NO_END_CS) {
- } else {
- digitalWriteFast(pin_, 1);
- }
- SPI.endTransaction();
- }
- private:
- const unsigned int pin_;
- const SPISettings settings_;
-
-};
-
-#if defined(__MK66FX1M0__)
-class ActiveLowChipSelect1 : public AbstractChipSelect
-{
- public:
- /** Equivalent to AbstractChipSelect, but for SPI1.
- **/
- ActiveLowChipSelect1(const unsigned int& pin, const SPISettings& settings)
- : pin_(pin),
- settings_(settings)
- {
- pinMode(pin, OUTPUT);
- digitalWriteFast(pin, 1);
- }
-
- /** \brief begins an SPI transaction selects the chip (sets the pin to low) and
- **/
- void select(TransferType transferType = TransferType::NORMAL) override
- {
- SPI1.beginTransaction(settings_);
- if (transferType == TransferType::NO_START_CS) {
- return;
- }
- digitalWriteFast(pin_, 0);
- }
-
- /** \brief deselects the chip (sets the pin to high) and ends the SPI transaction
- **/
- void deselect(TransferType transferType = TransferType::NORMAL) override
- {
- if (transferType == TransferType::NO_END_CS) {
- } else {
- digitalWriteFast(pin_, 1);
- }
- SPI1.endTransaction();
- }
- private:
- const unsigned int pin_;
- const SPISettings settings_;
-
-};
-#endif
-
-
-//#define DEBUG_DMASPI 1
-
-#if defined(DEBUG_DMASPI)
- #define DMASPI_PRINT(x) do {Serial.printf x ; Serial.flush();} while (0);
-#else
- #define DMASPI_PRINT(x) do {} while (0);
-#endif
-
-namespace DmaSpi
-{
- /** \brief describes an SPI transfer
- *
- * Transfers are kept in a queue (intrusive linked list) until they are processed by the DmaSpi driver.
- *
- **/
- class Transfer
- {
- public:
- /** \brief The Transfer's current state.
- *
- **/
- enum State
- {
- idle, /**< The Transfer is idle, the DmaSpi has not seen it yet. **/
- eDone, /**< The Transfer is done. **/
- pending, /**< Queued, but not handled yet. **/
- inProgress, /**< The DmaSpi driver is currently busy executing this Transfer. **/
- error /**< An error occured. **/
- };
-
- /** \brief Creates a Transfer object.
- * \param pSource pointer to the data source. If this is nullptr, the fill value is used instead.
- * \param transferCount the number of SPI transfers to perform.
- * \param pDest pointer to the data sink. If this is nullptr, data received from the slave will be discarded.
- * \param fill if pSource is nullptr, this value is sent to the slave instead.
- * \param cs pointer to a chip select object.
- * If not nullptr, cs->select() is called when the Transfer is started and cs->deselect() is called when the Transfer is finished.
- **/
- Transfer(const uint8_t* pSource = nullptr,
- const uint16_t& transferCount = 0,
- volatile uint8_t* pDest = nullptr,
- const uint8_t& fill = 0,
- AbstractChipSelect* cs = nullptr,
- TransferType transferType = TransferType::NORMAL
- ) : m_state(State::idle),
- m_pSource(pSource),
- m_transferCount(transferCount),
- m_pDest(pDest),
- m_fill(fill),
- m_pNext(nullptr),
- m_pSelect(cs),
- m_transferType(transferType)
- {
- DMASPI_PRINT(("Transfer @ %p\n", this));
- };
-
- /** \brief Check if the Transfer is busy, i.e. may not be modified.
- **/
- bool busy() const {return ((m_state == State::pending) || (m_state == State::inProgress) || (m_state == State::error));}
-
- /** \brief Check if the Transfer is done.
- **/
- bool done() const {return (m_state == State::eDone);}
-
-// private:
- volatile State m_state;
- const uint8_t* m_pSource;
- uint16_t m_transferCount;
- volatile uint8_t* m_pDest;
- uint8_t m_fill;
- Transfer* m_pNext;
- AbstractChipSelect* m_pSelect;
- TransferType m_transferType;
- };
-} // namespace DmaSpi
-
-
-template
-class AbstractDmaSpi
-{
- public:
- using Transfer = DmaSpi::Transfer;
-
- /** \brief arduino-style initialization.
- *
- * During initialization, two DMA channels are allocated. If that fails, this function returns false.
- * If the channels could be allocated, those DMA channel fields that don't change during DMA SPI operation
- * are initialized to the values they will have at runtime.
- *
- * \return true if initialization was successful; false otherwise.
- * \see end()
- **/
- static bool begin()
- {
- if(init_count_ > 0)
- {
- return true; // this is not particularly bad, so we can return true
- }
- init_count_++;
- DMASPI_PRINT(("DmaSpi::begin() : "));
- // create DMA channels, might fail
- if (!createDmaChannels())
- {
- DMASPI_PRINT(("could not create DMA channels\n"));
- return false;
- }
- state_ = eStopped;
- // tx: known destination (SPI), no interrupt, finish silently
- begin_setup_txChannel();
- if (txChannel_()->error())
- {
- destroyDmaChannels();
- DMASPI_PRINT(("tx channel error\n"));
- return false;
- }
-
- // rx: known source (SPI), interrupt on completion
- begin_setup_rxChannel();
- if (rxChannel_()->error())
- {
- destroyDmaChannels();
- DMASPI_PRINT(("rx channel error\n"));
- return false;
- }
-
- return true;
- }
-
- static void begin_setup_txChannel() {DMASPI_INSTANCE::begin_setup_txChannel_impl();}
- static void begin_setup_rxChannel() {DMASPI_INSTANCE::begin_setup_rxChannel_impl();}
-
- /** \brief Allow the DMA SPI to start handling Transfers. This must be called after begin().
- * \see running()
- * \see busy()
- * \see stop()
- * \see stopping()
- * \see stopped()
- **/
- static void start()
- {
- DMASPI_PRINT(("DmaSpi::start() : state_ = "));
- switch(state_)
- {
- case eStopped:
- DMASPI_PRINT(("eStopped\n"));
- state_ = eRunning;
- beginPendingTransfer();
- break;
-
- case eRunning:
- DMASPI_PRINT(("eRunning\n"));
- break;
-
- case eStopping:
- DMASPI_PRINT(("eStopping\n"));
- state_ = eRunning;
- break;
-
- default:
- DMASPI_PRINT(("unknown\n"));
- state_ = eError;
- break;
- }
- }
-
- /** \brief check if the DMA SPI is in running state.
- * \return true if the DMA SPI is in running state, false otherwise.
- * \see start()
- * \see busy()
- * \see stop()
- * \see stopping()
- * \see stopped()
- **/
- static bool running() {return state_ == eRunning;}
-
- /** \brief register a Transfer to be handled by the DMA SPI.
- * \return false if the Transfer had an invalid transfer count (zero or greater than 32767), true otherwise.
- * \post the Transfer state is Transfer::State::pending, or Transfer::State::error if the transfer count was invalid.
- **/
- static bool registerTransfer(Transfer& transfer)
- {
- DMASPI_PRINT(("DmaSpi::registerTransfer(%p)\n", &transfer));
- if ((transfer.busy())
- || (transfer.m_transferCount == 0) // no zero length transfers allowed
- || (transfer.m_transferCount >= 0x8000)) // max CITER/BITER count with ELINK = 0 is 0x7FFF, so reject
- {
- DMASPI_PRINT((" Transfer is busy or invalid, dropped\n"));
- transfer.m_state = Transfer::State::error;
- return false;
- }
- addTransferToQueue(transfer);
- if ((state_ == eRunning) && (!busy()))
- {
- DMASPI_PRINT((" starting transfer\n"));
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- beginPendingTransfer();
- }
- }
- return true;
- }
-
-
- /** \brief Check if the DMA SPI is busy, which means that it is currently handling a Transfer.
- \return true if a Transfer is being handled.
- * \see start()
- * \see running()
- * \see stop()
- * \see stopping()
- * \see stopped()
- **/
- static bool busy()
- {
- return (m_pCurrentTransfer != nullptr);
- }
-
- /** \brief Request the DMA SPI to stop handling Transfers.
- *
- * The stopping driver may finish a current Transfer, but it will then not start a new, pending one.
- * \see start()
- * \see running()
- * \see busy()
- * \see stopping()
- * \see stopped()
- **/
- static void stop()
- {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- switch(state_)
- {
- case eStopped:
- break;
- case eRunning:
- if (busy())
- {
- state_ = eStopping;
- }
- else
- {
- // this means that the DMA SPI simply has nothing to do
- state_ = eStopped;
- }
- break;
- case eStopping:
- break;
- default:
- state_ = eError;
- break;
- }
- }
- }
-
- /** \brief See if the DMA SPI is currently switching from running to stopped state
- * \return true if the DMA SPI is switching from running to stopped state
- * \see start()
- * \see running()
- * \see busy()
- * \see stop()
- * \see stopped()
- **/
- static bool stopping() { return (state_ == eStopping); }
-
- /** \brief See if the DMA SPI is stopped
- * \return true if the DMA SPI is in stopped state, i.e. not handling pending Transfers
- * \see start()
- * \see running()
- * \see busy()
- * \see stop()
- * \see stopping()
- **/
- static bool stopped() { return (state_ == eStopped); }
-
- /** \brief Shut down the DMA SPI
- *
- * Deallocates DMA channels and sets the internal state to error (this might not be an intelligent name for that)
- * \see begin()
- **/
- static void end()
- {
- if (init_count_ == 0)
- {
- state_ = eError;
- return;
- }
- if (init_count_ == 1)
- {
- init_count_--;
- destroyDmaChannels();
- state_ = eError;
- return;
- }
- else
- {
- init_count_--;
- return;
- }
- }
-
- /** \brief get the last value that was read from a slave, but discarded because the Transfer didn't specify a sink
- **/
- static uint8_t devNull()
- {
- return m_devNull;
- }
-
- protected:
- enum EState
- {
- eStopped,
- eRunning,
- eStopping,
- eError
- };
-
- static void addTransferToQueue(Transfer& transfer)
- {
- transfer.m_state = Transfer::State::pending;
- transfer.m_pNext = nullptr;
- DMASPI_PRINT((" DmaSpi::addTransferToQueue() : queueing transfer\n"));
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
- {
- if (m_pNextTransfer == nullptr)
- {
- m_pNextTransfer = &transfer;
- }
- else
- {
- m_pLastTransfer->m_pNext = &transfer;
- }
- m_pLastTransfer = &transfer;
- }
- }
-
- static void post_finishCurrentTransfer() {DMASPI_INSTANCE::post_finishCurrentTransfer_impl();}
-
- static void finishCurrentTransfer()
- {
- if (m_pCurrentTransfer->m_pSelect != nullptr)
- {
- m_pCurrentTransfer->m_pSelect->deselect(m_pCurrentTransfer->m_transferType);
- }
- else
- {
- m_Spi.endTransaction();
- }
- m_pCurrentTransfer->m_state = Transfer::State::eDone;
- DMASPI_PRINT((" finishCurrentTransfer() @ %p\n", m_pCurrentTransfer));
- m_pCurrentTransfer = nullptr;
- post_finishCurrentTransfer();
- }
-
- static bool createDmaChannels()
- {
- if (txChannel_() == nullptr)
- {
- return false;
- }
- if (rxChannel_() == nullptr)
- {
- delete txChannel_();
- return false;
- }
- return true;
- }
-
- static void destroyDmaChannels()
- {
- if (rxChannel_() != nullptr)
- {
- delete rxChannel_();
- }
- if (txChannel_() != nullptr)
- {
- delete txChannel_();
- }
- }
-
- static DMAChannel* rxChannel_()
- {
- static DMAChannel* pChannel = new DMAChannel();
- return pChannel;
- }
-
- static DMAChannel* txChannel_()
- {
- static DMAChannel* pChannel = new DMAChannel();
- return pChannel;
- }
-
- static void rxIsr_()
- {
- DMASPI_PRINT(("DmaSpi::rxIsr_()\n"));
- rxChannel_()->clearInterrupt();
- // end current transfer: deselect and mark as done
- finishCurrentTransfer();
-
- DMASPI_PRINT((" state = "));
- switch(state_)
- {
- case eStopped: // this should not happen!
- DMASPI_PRINT(("eStopped\n"));
- state_ = eError;
- break;
- case eRunning:
- DMASPI_PRINT(("eRunning\n"));
- beginPendingTransfer();
- break;
- case eStopping:
- DMASPI_PRINT(("eStopping\n"));
- state_ = eStopped;
- break;
- case eError:
- DMASPI_PRINT(("eError\n"));
- break;
- default:
- DMASPI_PRINT(("eUnknown\n"));
- state_ = eError;
- break;
- }
- }
-
- static void pre_cs() {DMASPI_INSTANCE::pre_cs_impl();}
- static void post_cs() {DMASPI_INSTANCE::post_cs_impl();}
-
- static void beginPendingTransfer()
- {
- if (m_pNextTransfer == nullptr)
- {
- DMASPI_PRINT(("DmaSpi::beginNextTransfer: no pending transfer\n"));
- return;
- }
-
- m_pCurrentTransfer = m_pNextTransfer;
- DMASPI_PRINT(("DmaSpi::beginNextTransfer: starting transfer @ %p\n", m_pCurrentTransfer));
- m_pCurrentTransfer->m_state = Transfer::State::inProgress;
- m_pNextTransfer = m_pNextTransfer->m_pNext;
- if (m_pNextTransfer == nullptr)
- {
- DMASPI_PRINT((" this was the last in the queue\n"));
- m_pLastTransfer = nullptr;
- }
-
- // configure Rx DMA
- if (m_pCurrentTransfer->m_pDest != nullptr)
- {
- // real data sink
- DMASPI_PRINT((" real sink\n"));
- rxChannel_()->destinationBuffer(m_pCurrentTransfer->m_pDest,
- m_pCurrentTransfer->m_transferCount);
- }
- else
- {
- // dummy data sink
- DMASPI_PRINT((" dummy sink\n"));
- rxChannel_()->destination(m_devNull);
- rxChannel_()->transferCount(m_pCurrentTransfer->m_transferCount);
- }
-
- // configure Tx DMA
- if (m_pCurrentTransfer->m_pSource != nullptr)
- {
- // real data source
- DMASPI_PRINT((" real source\n"));
- txChannel_()->sourceBuffer(m_pCurrentTransfer->m_pSource,
- m_pCurrentTransfer->m_transferCount);
- }
- else
- {
- // dummy data source
- DMASPI_PRINT((" dummy source\n"));
- txChannel_()->source(m_pCurrentTransfer->m_fill);
- txChannel_()->transferCount(m_pCurrentTransfer->m_transferCount);
- }
-
- pre_cs();
-
- // Select Chip
- if (m_pCurrentTransfer->m_pSelect != nullptr)
- {
- m_pCurrentTransfer->m_pSelect->select(m_pCurrentTransfer->m_transferType);
- }
- else
- {
- m_Spi.beginTransaction(SPISettings());
- }
-
- post_cs();
- }
-
- static size_t init_count_;
- static volatile EState state_;
- static Transfer* volatile m_pCurrentTransfer;
- static Transfer* volatile m_pNextTransfer;
- static Transfer* volatile m_pLastTransfer;
- static volatile uint8_t m_devNull;
- //static SPICLASS& m_Spi;
-};
-
-template
-size_t AbstractDmaSpi::init_count_ = 0;
-
-template
-volatile typename AbstractDmaSpi::EState AbstractDmaSpi::state_ = eError;
-
-template
-typename AbstractDmaSpi::Transfer* volatile AbstractDmaSpi::m_pNextTransfer = nullptr;
-
-template
-typename AbstractDmaSpi::Transfer* volatile AbstractDmaSpi::m_pCurrentTransfer = nullptr;
-
-template
-typename AbstractDmaSpi::Transfer* volatile AbstractDmaSpi::m_pLastTransfer = nullptr;
-
-template
-volatile uint8_t AbstractDmaSpi::m_devNull = 0;
-
-#if defined(KINETISK)
-
-class DmaSpi0 : public AbstractDmaSpi
-{
-public:
- static void begin_setup_txChannel_impl()
- {
- txChannel_()->disable();
- txChannel_()->destination((volatile uint8_t&)SPI0_PUSHR);
- txChannel_()->disableOnCompletion();
- txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX);
- }
-
- static void begin_setup_rxChannel_impl()
- {
- rxChannel_()->disable();
- rxChannel_()->source((volatile uint8_t&)SPI0_POPR);
- rxChannel_()->disableOnCompletion();
- rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_RX);
- rxChannel_()->attachInterrupt(rxIsr_);
- rxChannel_()->interruptAtCompletion();
- }
-
- static void pre_cs_impl()
- {
- SPI0_SR = 0xFF0F0000;
- SPI0_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
- }
-
- static void post_cs_impl()
- {
- rxChannel_()->enable();
- txChannel_()->enable();
- }
-
- static void post_finishCurrentTransfer_impl()
- {
- SPI0_RSER = 0;
- SPI0_SR = 0xFF0F0000;
- }
-
-private:
-};
-
-extern DmaSpi0 DMASPI0;
-
-#if defined(__MK66FX1M0__)
-
-class DmaSpi1 : public AbstractDmaSpi
-{
-public:
- static void begin_setup_txChannel_impl()
- {
- txChannel_()->disable();
- txChannel_()->destination((volatile uint8_t&)SPI1_PUSHR);
- txChannel_()->disableOnCompletion();
- txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI1_TX);
- }
-
- static void begin_setup_rxChannel_impl()
- {
- rxChannel_()->disable();
- rxChannel_()->source((volatile uint8_t&)SPI1_POPR);
- rxChannel_()->disableOnCompletion();
- rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI1_RX);
- rxChannel_()->attachInterrupt(rxIsr_);
- rxChannel_()->interruptAtCompletion();
- }
-
- static void pre_cs_impl()
- {
- SPI1_SR = 0xFF0F0000;
- SPI1_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
- }
-
- static void post_cs_impl()
- {
- rxChannel_()->enable();
- txChannel_()->enable();
- }
-
- static void post_finishCurrentTransfer_impl()
- {
- SPI1_RSER = 0;
- SPI1_SR = 0xFF0F0000;
- }
-
-private:
-};
-
-/*
-class DmaSpi2 : public AbstractDmaSpi
-{
-public:
- static void begin_setup_txChannel_impl()
- {
- txChannel_()->disable();
- txChannel_()->destination((volatile uint8_t&)SPI2_PUSHR);
- txChannel_()->disableOnCompletion();
- txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI2_TX);
- }
-
- static void begin_setup_rxChannel_impl()
- {
- rxChannel_()->disable();
- rxChannel_()->source((volatile uint8_t&)SPI2_POPR);
- rxChannel_()->disableOnCompletion();
- rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI2_RX);
- rxChannel_()->attachInterrupt(rxIsr_);
- rxChannel_()->interruptAtCompletion();
- }
-
- static void pre_cs_impl()
- {
- SPI2_SR = 0xFF0F0000;
- SPI2_RSER = SPI_RSER_RFDF_RE | SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS;
- }
-
- static void post_cs_impl()
- {
- rxChannel_()->enable();
- txChannel_()->enable();
- }
-
- static void post_finishCurrentTransfer_impl()
- {
- SPI2_RSER = 0;
- SPI2_SR = 0xFF0F0000;
- }
-
-private:
-};
-*/
-
-extern DmaSpi1 DMASPI1;
-//extern DmaSpi2 DMASPI2;
-#endif // defined(__MK66FX1M0__)
-
-#elif defined(KINETISL)
-class DmaSpi0 : public AbstractDmaSpi
-{
-public:
- static void begin_setup_txChannel_impl()
- {
- txChannel_()->disable();
- txChannel_()->destination((volatile uint8_t&)SPI0_DL);
- txChannel_()->disableOnCompletion();
- txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX);
- }
-
- static void begin_setup_rxChannel_impl()
- {
- rxChannel_()->disable();
- rxChannel_()->source((volatile uint8_t&)SPI0_DL);
- rxChannel_()->disableOnCompletion();
- rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_RX);
- rxChannel_()->attachInterrupt(rxIsr_);
- rxChannel_()->interruptAtCompletion();
- }
-
- static void pre_cs_impl()
- {
- // disable SPI and enable SPI DMA requests
- SPI0_C1 &= ~(SPI_C1_SPE);
- SPI0_C2 |= SPI_C2_TXDMAE | SPI_C2_RXDMAE;
- }
-
- static void post_cs_impl()
- {
- rxChannel_()->enable();
- txChannel_()->enable();
- }
-
- static void post_finishCurrentTransfer_impl()
- {
- SPI0_C2 = 0;
- txChannel_()->clearComplete();
- rxChannel_()->clearComplete();
- }
-
-private:
-};
-
-class DmaSpi1 : public AbstractDmaSpi
-{
-public:
- static void begin_setup_txChannel_impl()
- {
- txChannel_()->disable();
- txChannel_()->destination((volatile uint8_t&)SPI1_DL);
- txChannel_()->disableOnCompletion();
- txChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI1_TX);
- }
-
- static void begin_setup_rxChannel_impl()
- {
- rxChannel_()->disable();
- rxChannel_()->source((volatile uint8_t&)SPI1_DL);
- rxChannel_()->disableOnCompletion();
- rxChannel_()->triggerAtHardwareEvent(DMAMUX_SOURCE_SPI1_RX);
- rxChannel_()->attachInterrupt(rxIsr_);
- rxChannel_()->interruptAtCompletion();
- }
-
- static void pre_cs_impl()
- {
- // disable SPI and enable SPI DMA requests
- SPI1_C1 &= ~(SPI_C1_SPE);
- SPI1_C2 |= SPI_C2_TXDMAE | SPI_C2_RXDMAE;
- }
-
-// static void dumpCFG(const char *sz, uint32_t* p)
-// {
-// 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));
-// dumpCFG("RX", (uint32_t*)(void*)rxChannel_()->CFG);
-// dumpCFG("TX", (uint32_t*)(void*)txChannel_()->CFG);
- rxChannel_()->enable();
- txChannel_()->enable();
- }
-
- static void post_finishCurrentTransfer_impl()
- {
- SPI1_C2 = 0;
- txChannel_()->clearComplete();
- rxChannel_()->clearComplete();
- }
-private:
-};
-
-extern DmaSpi0 DMASPI0;
-extern DmaSpi1 DMASPI1;
-
-#else
-
-#error Unknown chip
-
-#endif // KINETISK else KINETISL
-
-class DmaSpiGeneric
-{
-public:
- using Transfer = DmaSpi::Transfer;
-
- DmaSpiGeneric() {
- m_spiDma0 = &DMASPI0;
-#if defined(__MK66FX1M0__)
- m_spiDma1 = &DMASPI1;
-#endif
- }
- DmaSpiGeneric(int spiId) : DmaSpiGeneric() {
- m_spiSelect = spiId;
- }
-
- bool begin () {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->begin();
- default :
- return m_spiDma0->begin();
- }
- }
-
- void start () {
- switch(m_spiSelect) {
- case 1 : m_spiDma1->start(); return;
- default :
- m_spiDma0->start(); return;
- }
- }
-
- bool running () {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->running();
- default :
- return m_spiDma0->running();
- }
- }
-
- bool registerTransfer (Transfer& transfer) {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->registerTransfer(transfer);
- default :
- return m_spiDma0->registerTransfer(transfer);
- }
- }
-
-
- bool busy () {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->busy();
- default :
- return m_spiDma0->busy();
- }
- }
-
- void stop () {
- switch(m_spiSelect) {
- case 1 : m_spiDma1->stop(); return;
- default :
- m_spiDma0->stop(); return;
- }
- }
-
- bool stopping () {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->stopping();
- default :
- return m_spiDma0->stopping();
- }
- }
-
- bool stopped () {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->stopped();
- default :
- return m_spiDma0->stopped();
- }
- }
-
- void end () {
- switch(m_spiSelect) {
- case 1 : m_spiDma1->end(); return;
- default :
- m_spiDma0->end(); return;
- }
- }
-
- uint8_t devNull () {
- switch(m_spiSelect) {
- case 1 : return m_spiDma1->devNull();
- default :
- return m_spiDma0->devNull();
- }
- }
-
-private:
- int m_spiSelect = 0;
- DmaSpi0 *m_spiDma0 = nullptr;
-#if defined(__MK66FX1M0__)
- DmaSpi1 *m_spiDma1 = nullptr;
-#else
- // just make it Spi0 so it compiles atleast
- DmaSpi0 *m_spiDma1 = nullptr;
-#endif
-
-};
-
-
-#endif // DMASPI_H
diff --git a/src/LibBasicFunctions.h b/src/LibBasicFunctions.h
index 407e5c5..3cf80b5 100644
--- a/src/LibBasicFunctions.h
+++ b/src/LibBasicFunctions.h
@@ -29,7 +29,6 @@
#include "Audio.h"
#include "BATypes.h"
-#include "LibMemoryManagement.h"
#ifndef __BALIBRARY_LIBBASICFUNCTIONS_H
#define __BALIBRARY_LIBBASICFUNCTIONS_H
@@ -137,7 +136,6 @@ public:
/// Construct an audio buffer using a slot configured with the BALibrary::ExternalSramManager
/// @param slot a pointer to the slot representing the memory you wish to use for the buffer.
- AudioDelay(ExtMemSlot *slot);
~AudioDelay();
@@ -208,8 +206,6 @@ public:
/// When using EXTERNAL memory, this function can return a pointer to the underlying ExtMemSlot object associated
/// with the buffer.
/// @returns pointer to the underlying ExtMemSlot.
- ExtMemSlot *getSlot() const { return m_slot; }
-
/// Ween using INTERNAL memory, thsi function can return a pointer to the underlying RingBuffer that contains
@@ -227,7 +223,6 @@ private:
MemType m_type; ///< when 0, INTERNAL memory, when 1, external MEMORY.
RingBuffer *m_ringBuffer = nullptr; ///< When using INTERNAL memory, a RingBuffer will be created.
- ExtMemSlot *m_slot = nullptr; ///< When using EXTERNAL memory, an ExtMemSlot must be provided.
size_t m_maxDelaySamples = 0; ///< stores the number of audio samples in the AudioDelay.
bool m_getSamples(int16_t *dest, size_t offsetSamples, size_t numSamples); ///< operates directly on int16_y buffers
};
diff --git a/src/LibMemoryManagement.h b/src/LibMemoryManagement.h
deleted file mode 100644
index 288e581..0000000
--- a/src/LibMemoryManagement.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * LibMemoryManagment is a class for providing access to external SPI based
- * SRAM with the optional convience of breaking it up into 'slots' which are smaller
- * memory entities.
- * @details This class treats an external memory as a pool from which the user requests
- * a block. When using that block, the user need not be concerned with where the pool
- * it came from, they only deal with offsets from the start of their memory block. Ie.
- * Your particular slot of memory appears to you to start at 0 and end at whatever size
- * was requested.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef __BALIBRARY_LIBMEMORYMANAGEMENT_H
-#define __BALIBRARY_LIBMEMORYMANAGEMENT_H
-
-#include
-
-#include "BAHardware.h"
-#include "BASpiMemory.h"
-
-namespace BALibrary {
-
-/**************************************************************************//**
- * MemConfig contains the configuration information associated with a particular
- * SPI interface.
- *****************************************************************************/
-struct MemConfig {
- size_t size; ///< the total size of the external SPI memory
- size_t totalAvailable; ///< the number of bytes available (remaining)
- size_t nextAvailable; ///< the starting point for the next available slot
- BASpiMemory *m_spi = nullptr; ///< handle to the SPI interface
-};
-
-class ExternalSramManager; // forward declare so ExtMemSlot can declared friendship with it
-
-/**************************************************************************//**
- * ExtMemSlot provides a convenient interface to a particular slot of an
- * external memory.
- * @details the memory can be access randomly, as a single word, as a block of
- * data, or as circular queue.
- *****************************************************************************/
-class ExtMemSlot {
-public:
-
- /// clear the entire contents of the slot by writing zeros
- /// @returns true on success
- bool clear();
-
- /// set a new write position (in bytes) for circular operation
- /// @param offsetBytes moves the write pointer to the specified offset from the slot start
- /// @returns true on success, else false if offset is beyond slot boundaries.
- bool setWritePosition(size_t offsetBytes);
-
- /// returns the currently set write pointer pointer
- /// @returns the write position value
- size_t getWritePosition() const { return m_currentWrPosition-m_start; }
-
- /// set a new read position (in bytes) for circular operation
- /// @param offsetBytes moves the read pointer to the specified offset from the slot start
- /// @returns true on success, else false if offset is beyond slot boundaries.
- bool setReadPosition(size_t offsetBytes);
-
- /// returns the currently set read pointer pointer
- /// @returns the read position value
- size_t getReadPosition() const { return m_currentRdPosition-m_start; }
-
- /// Write a block of 16-bit data to the memory at the specified offset
- /// @param offsetWords offset in 16-bit words from start of slot
- /// @param src pointer to start of block of 16-bit data
- /// @param numWords number of 16-bit words to transfer
- /// @returns true on success, else false on error
- bool write16(size_t offsetWords, int16_t *src, size_t numWords);
-
- /// Write a block of zeros (16-bit) to the memory at the specified offset
- /// @param offsetWords offset in 16-bit words from start of slot
- /// @param numWords number of 16-bit words to transfer
- /// @returns true on success, else false on error
- bool zero16(size_t offsetWords, size_t numWords);
-
- /// Read a block of 16-bit data from the memory at the specified location
- /// @param offsetWords offset in 16-bit words from start of slot
- /// @param dest pointer to destination for the read data
- /// @param numWords number of 16-bit words to transfer
- /// @returns true on success, else false on error
- bool read16(size_t offsetWords, int16_t *dest, size_t numWords);
-
- /// 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.
- /// @param numWords number of 16-bit words to transfer
- /// @returns true on success, else false on error
- bool readAdvance16(int16_t *dest, size_t numWords);
-
- /// Write a block of 16-bit data from the specified location in circular operation
- /// @param src pointer to the start of the block of data to write to memory
- /// @param numWords number of 16-bit words to transfer
- /// @returns true on success, else false on error
- bool writeAdvance16(int16_t *src, size_t numWords);
-
- /// Write a single 16-bit data to the next location in circular operation
- /// @param data the 16-bit word to transfer
- /// @returns true on success, else false on error
- bool writeAdvance16(int16_t data); // write just one data
-
- /// Write a block of 16-bit data zeros in circular operation
- /// @param numWords number of 16-bit words to transfer
- /// @returns true on success, else false on error
- bool zeroAdvance16(size_t numWords);
-
- /// Get the size of the memory slot
- /// @returns size of the slot in bytes
- size_t size() const { return m_size; }
-
- /// Ensures the underlying SPI interface is enabled
- /// @returns true on success, false on error
- bool enable() const;
-
- /// Checks whether underlying SPI interface is enabled
- /// @returns true if enabled, false if not enabled
- bool isEnabled() const;
-
- bool isUseDma() const { return m_useDma; }
-
- bool isWriteBusy() const;
-
- bool isReadBusy() const;
-
- /// DEBUG USE: prints out the slot member variables
- void printStatus(void) const;
-
-private:
- friend ExternalSramManager; ///< gives the manager access to the private variables
- bool m_valid = false; ///< After a slot is successfully configured by the manager it becomes valid
- size_t m_start = 0; ///< the external memory address in bytes where this slot starts
- size_t m_end = 0; ///< the external memory address in bytes where this slot ends (inclusive)
- size_t m_currentWrPosition = 0; ///< current write pointer for circular operation
- size_t m_currentRdPosition = 0; ///< current read pointer for circular operation
- size_t m_size = 0; ///< size of this slot in bytes
- bool m_useDma = false; ///< when TRUE, BASpiMemoryDMA will be used.
- SpiDeviceId m_spiId; ///< the SPI Device ID
- BASpiMemory *m_spi = nullptr; ///< pointer to an instance of the BASpiMemory interface class
-};
-
-
-/**************************************************************************//**
- * ExternalSramManager provides a class to handle dividing an external SPI RAM
- * into independent slots for general use.
- * @details the class does not support deallocated memory because this would cause
- * fragmentation.
- *****************************************************************************/
-class ExternalSramManager final {
-public:
- ExternalSramManager();
-
- /// The manager is constructed by specifying how many external memories to handle allocations for
- /// @param numMemories the number of external memories
- ExternalSramManager(unsigned numMemories);
- virtual ~ExternalSramManager();
-
- /// Query the amount of available (unallocated) memory
- /// @details note that currently, memory cannot be allocated.
- /// @param mem specifies which memory to query, default is memory 0
- /// @returns the available memory in bytes
- size_t availableMemory(BALibrary::MemSelect mem = BALibrary::MemSelect::MEM0);
-
- /// Request memory be allocated for the provided slot
- /// @param slot a pointer to the global slot object to which memory will be allocated
- /// @param delayMilliseconds request the amount of memory based on required time for audio samples, rather than number of bytes.
- /// @param mem specify which external memory to allocate from
- /// @param useDma when true, DMA is used for SPI port, else transfers block until complete
- /// @returns true on success, otherwise false on error
- bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BALibrary::MemSelect mem = BALibrary::MemSelect::MEM0, bool useDma = false);
-
- /// Request memory be allocated for the provided slot
- /// @param slot a pointer to the global slot object to which memory will be allocated
- /// @param sizeBytes request the amount of memory in bytes to request
- /// @param mem specify which external memory to allocate from
- /// @param useDma when true, DMA is used for SPI port, else transfers block until complete
- /// @returns true on success, otherwise false on error
- bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALibrary::MemSelect mem = BALibrary::MemSelect::MEM0, bool useDma = false);
-
-private:
- static bool m_configured; ///< there should only be one instance of ExternalSramManager in the whole project
- static MemConfig m_memConfig[BALibrary::NUM_MEM_SLOTS]; ///< store the configuration information for each external memory
-
-};
-
-
-} // BALibrary
-
-#endif /* __BALIBRARY_LIBMEMORYMANAGEMENT_H */
diff --git a/src/common/AudioDelay.cpp b/src/common/AudioDelay.cpp
index 7b30c5f..fccd8fa 100644
--- a/src/common/AudioDelay.cpp
+++ b/src/common/AudioDelay.cpp
@@ -28,7 +28,6 @@ namespace BALibrary {
// AudioDelay
////////////////////////////////////////////////////
AudioDelay::AudioDelay(size_t maxSamples)
-: m_slot(nullptr)
{
m_type = (MemType::MEM_INTERNAL);
@@ -44,13 +43,6 @@ AudioDelay::AudioDelay(float maxDelayTimeMs)
}
-AudioDelay::AudioDelay(ExtMemSlot *slot)
-{
- m_type = (MemType::MEM_EXTERNAL);
- m_slot = slot;
- m_maxDelaySamples = (slot->size() / sizeof(int16_t)) - AUDIO_BLOCK_SAMPLES;
-}
-
AudioDelay::~AudioDelay()
{
if (m_ringBuffer) delete m_ringBuffer;
@@ -74,16 +66,7 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block)
m_ringBuffer->push_back(block);
return blockToRelease;
- } else {
- // EXTERNAL memory
- if (!m_slot) { Serial.println("addBlock(): m_slot is not valid"); }
-
- if (block) {
- // this causes pops
- m_slot->writeAdvance16(block->data, AUDIO_BLOCK_SAMPLES);
- }
- blockToRelease = block;
- }
+ }
return blockToRelease;
}
@@ -98,10 +81,6 @@ audio_block_t* AudioDelay::getBlock(size_t index)
size_t AudioDelay::getMaxDelaySamples()
{
- if (m_type == MemType::MEM_EXTERNAL) {
- // update the max delay sample size
- m_maxDelaySamples = (m_slot->size() / sizeof(int16_t)) - AUDIO_BLOCK_SAMPLES;
- }
return m_maxDelaySamples;
}
@@ -160,37 +139,9 @@ bool AudioDelay::m_getSamples(int16_t *dest, size_t offsetSamples, size_t numSam
memcpy(static_cast(destStart), static_cast(srcStart), numData * sizeof(int16_t));
return true;
-
- } else {
- // EXTERNAL Memory
- if (numSamples*sizeof(int16_t) <= m_slot->size() ) { // check for overflow
- // current position is considered the write position subtracted by the number of samples we're going
- // to read since this is the smallest delay we can get without reading past the write position into
- // the "future".
- int currentPositionBytes = (int)m_slot->getWritePosition() - (int)(numSamples*sizeof(int16_t));
- size_t offsetBytes = offsetSamples * sizeof(int16_t);
-
- if ((int)offsetBytes <= currentPositionBytes) {
- // when we back up to read, we won't wrap over the beginning of the slot
- m_slot->setReadPosition(currentPositionBytes - offsetBytes);
- } else {
- // It's going to wrap around to the from the beginning to the end of the slot.
- int readPosition = (int)m_slot->size() + currentPositionBytes - offsetBytes;
- m_slot->setReadPosition((size_t)readPosition);
- }
-
- // Read the number of samples
- m_slot->readAdvance16(dest, numSamples);
-
- return true;
- } else {
- // numSamples is > than total slot size
- Serial.println("getSamples(): ERROR numSamples > total slot size");
- Serial.println(numSamples + String(" > ") + m_slot->size());
- return false;
- }
}
+ return false;
}
bool AudioDelay::interpolateDelay(int16_t *extendedSourceBuffer, int16_t *destBuffer, float fraction, size_t numSamples)
@@ -203,28 +154,12 @@ bool AudioDelay::interpolateDelay(int16_t *extendedSourceBuffer, int16_t *destBu
}
/// @todo optimize this later
- for (int i=0; i> 16) + ((frac2*extendedSourceBuffer[i+1]) >> 16);
}
return true;
}
-bool AudioDelay::interpolateDelayVector(int16_t *extendedSourceBuffer, int16_t *destBuffer, float *fractionVector, size_t numSamples)
-{
- int16_t frac1Vec[numSamples];
- int16_t frac2Vec[numSamples];
-
- for (int i=0; i(32767.0f * fractionVector[i]);
- frac1Vec[i] = fracAsInt;
- frac2Vec[i] = 32767-frac1Vec[i];
-
- destBuffer[i] = (( frac1Vec[i] * extendedSourceBuffer[i]) >> 16) + ((frac2Vec[i] * extendedSourceBuffer[i+1]) >> 16);
- }
-
- return true;
-}
-
}
diff --git a/src/common/ExtMemSlot.cpp b/src/common/ExtMemSlot.cpp
deleted file mode 100644
index c857cbe..0000000
--- a/src/common/ExtMemSlot.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * ExtMemSlot.cpp
- *
- * Created on: Jan 19, 2018
- * Author: slascos
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-#include
-#include
-
-#include "Audio.h"
-#include "LibMemoryManagement.h"
-
-namespace BALibrary {
-
-/////////////////////////////////////////////////////////////////////////////
-// MEM SLOT
-/////////////////////////////////////////////////////////////////////////////
-bool ExtMemSlot::clear()
-{
- if (!m_valid) { return false; }
- m_spi->zero16(m_start, m_size);
- return true;
-}
-
-bool ExtMemSlot::setWritePosition(size_t offsetBytes)
-{
- if (m_start + offsetBytes <= m_end) {
- m_currentWrPosition = m_start + offsetBytes;
- return true;
- } else { return false; }
-}
-
-bool ExtMemSlot::write16(size_t 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::setReadPosition(size_t offsetBytes)
-{
- if (m_start + offsetBytes <= m_end) {
- m_currentRdPosition = m_start + offsetBytes;
- return true;
- } else {
- return false;
- }
-}
-
-bool ExtMemSlot::zero16(size_t offsetWords, size_t numWords)
-{
- if (!m_valid) { return false; }
- size_t writeStart = m_start + sizeof(int16_t)*offsetWords;
- size_t numBytes = sizeof(int16_t)*numWords;
- if ((writeStart + numBytes-1) <= m_end) {
- m_spi->zero16(writeStart, numWords); // cast audio data to uint
- return true;
- } else {
- // this would go past the end of the memory slot, do not perform the write
- return false;
- }
-}
-
-bool ExtMemSlot::read16(size_t offsetWords, int16_t *dest, size_t numWords)
-{
- if (!dest) return false; // invalid destination
- size_t readOffset = m_start + sizeof(int16_t)*offsetWords;
- size_t numBytes = sizeof(int16_t)*numWords;
-
- if ((readOffset + numBytes-1) <= m_end) {
- m_spi->read16(readOffset, reinterpret_cast(dest), numWords);
- return true;
- } else {
- // this would go past the end of the memory slot, do not perform the read
- return false;
- }
-}
-
-uint16_t ExtMemSlot::readAdvance16()
-{
- uint16_t val = m_spi->read16(m_currentRdPosition);
- if (m_currentRdPosition < m_end-1) {
- m_currentRdPosition +=2; // position is in bytes and we read two
- } else {
- m_currentRdPosition = m_start;
- }
- return val;
-}
-
-bool ExtMemSlot::readAdvance16(int16_t *dest, size_t numWords)
-{
- if (!m_valid) { return false; }
- size_t numBytes = sizeof(int16_t)*numWords;
-
- if (m_currentRdPosition + numBytes-1 <= m_end) {
- // entire block fits in memory slot without wrapping
- m_spi->read16(m_currentRdPosition, reinterpret_cast(dest), numWords); // cast audio data to uint.
- m_currentRdPosition += numBytes;
-
- } else {
- // this read will wrap the memory slot
- size_t rdBytes = m_end - m_currentRdPosition + 1;
- size_t rdDataNum = rdBytes >> 1; // divide by two to get the number of data
- m_spi->read16(m_currentRdPosition, reinterpret_cast(dest), rdDataNum);
- size_t remainingData = numWords - rdDataNum;
- m_spi->read16(m_start, reinterpret_cast(dest + rdDataNum), remainingData); // write remaining bytes are start
- m_currentRdPosition = m_start + (remainingData*sizeof(int16_t));
- }
- return true;
-}
-
-
-bool ExtMemSlot::writeAdvance16(int16_t *src, size_t numWords)
-{
- if (!m_valid) { return false; }
- size_t numBytes = sizeof(int16_t)*numWords;
-
- if (m_currentWrPosition + numBytes-1 <= m_end) {
- // entire block fits in memory slot without wrapping
- m_spi->write16(m_currentWrPosition, reinterpret_cast(src), numWords); // cast audio data to uint.
- m_currentWrPosition += numBytes;
-
- } else {
- // this write will wrap the memory slot
- size_t wrBytes = m_end - m_currentWrPosition + 1;
- size_t wrDataNum = wrBytes >> 1; // divide by two to get the number of data
- m_spi->write16(m_currentWrPosition, reinterpret_cast(src), wrDataNum);
- size_t remainingData = numWords - wrDataNum;
- m_spi->write16(m_start, reinterpret_cast(src + wrDataNum), remainingData); // write remaining bytes are start
- m_currentWrPosition = m_start + (remainingData*sizeof(int16_t));
- }
- return true;
-}
-
-
-bool ExtMemSlot::zeroAdvance16(size_t numWords)
-{
- if (!m_valid) { return false; }
- size_t numBytes = 2*numWords;
- if (m_currentWrPosition + numBytes-1 <= m_end) {
- // entire block fits in memory slot without wrapping
- m_spi->zero16(m_currentWrPosition, numWords); // cast audio data to uint.
- m_currentWrPosition += numBytes;
-
- } else {
- // this write will wrap the memory slot
- size_t wrBytes = m_end - m_currentWrPosition + 1;
- size_t wrDataNum = wrBytes >> 1;
- m_spi->zero16(m_currentWrPosition, wrDataNum);
- size_t remainingWords = numWords - wrDataNum; // calculate the remaining bytes
- m_spi->zero16(m_start, remainingWords); // write remaining bytes are start
- m_currentWrPosition = m_start + remainingWords*sizeof(int16_t);
- }
- return true;
-}
-
-
-bool ExtMemSlot::writeAdvance16(int16_t data)
-{
- if (!m_valid) { return false; }
-
- m_spi->write16(m_currentWrPosition, static_cast(data));
- if (m_currentWrPosition < m_end-1) {
- m_currentWrPosition+=2; // wrote two bytes
- } else {
- m_currentWrPosition = m_start;
- }
- return true;
-}
-
-
-bool ExtMemSlot::enable() const
-{
- if (m_spi) {
- Serial.println("ExtMemSlot::enable()");
- m_spi->begin();
- return true;
- }
- else {
- Serial.println("ExtMemSlot m_spi is nullptr");
- return false;
- }
-}
-
-bool ExtMemSlot::isEnabled() const
-{
- if (m_spi) { return m_spi->isStarted(); }
- else return false;
-}
-
-bool ExtMemSlot::isWriteBusy() const
-{
- if (m_useDma) {
- return (static_cast(m_spi))->isWriteBusy();
- } else { return false; }
-}
-
-bool ExtMemSlot::isReadBusy() const
-{
- if (m_useDma) {
- return (static_cast(m_spi))->isReadBusy();
- } else { return false; }
-}
-
-
-void ExtMemSlot::printStatus(void) const
-{
- Serial.println(String("valid:") + m_valid + String(" m_start:") + m_start + \
- String(" m_end:") + m_end + String(" m_currentWrPosition: ") + m_currentWrPosition + \
- String(" m_currentRdPosition: ") + m_currentRdPosition + \
- String(" m_size:") + m_size);
-}
-
-}
-
diff --git a/src/common/ExternalSramManager.cpp b/src/common/ExternalSramManager.cpp
deleted file mode 100644
index 7083e0c..0000000
--- a/src/common/ExternalSramManager.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * LibMemoryManagement.cpp
- *
- * Created on: Jan 19, 2018
- * Author: slascos
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-#include
-#include
-
-#include "Audio.h"
-#include "LibMemoryManagement.h"
-
-namespace BALibrary {
-
-/////////////////////////////////////////////////////////////////////////////
-// EXTERNAL SRAM MANAGER
-/////////////////////////////////////////////////////////////////////////////
-bool ExternalSramManager::m_configured = false;
-MemConfig ExternalSramManager::m_memConfig[BALibrary::NUM_MEM_SLOTS];
-
-
-ExternalSramManager::ExternalSramManager(unsigned numMemories)
-{
- // Initialize the static memory configuration structs
- if (!m_configured) {
- for (unsigned i=0; i < NUM_MEM_SLOTS; i++) {
- m_memConfig[i].size = MEM_MAX_ADDR[i]+1;
- m_memConfig[i].totalAvailable = MEM_MAX_ADDR[i]+1;
- m_memConfig[i].nextAvailable = 0;
-
- m_memConfig[i].m_spi = nullptr;
- }
- m_configured = true;
- }
-}
-
-ExternalSramManager::ExternalSramManager()
-: ExternalSramManager(1)
-{
-
-}
-
-ExternalSramManager::~ExternalSramManager()
-{
- for (unsigned i=0; i < NUM_MEM_SLOTS; i++) {
- if (m_memConfig[i].m_spi) { delete m_memConfig[i].m_spi; }
- }
-}
-
-size_t ExternalSramManager::availableMemory(BALibrary::MemSelect mem)
-{
- return m_memConfig[mem].totalAvailable;
-}
-
-bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BALibrary::MemSelect mem, bool useDma)
-{
- // convert the time to numer of samples
- size_t delayLengthInt = (size_t)((delayMilliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f);
- return requestMemory(slot, delayLengthInt * sizeof(int16_t), mem, useDma);
-}
-
-bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BALibrary::MemSelect mem, bool useDma)
-{
-
- if (m_memConfig[mem].totalAvailable >= sizeBytes) {
- Serial.println(String("Configuring a slot for mem ") + mem);
- // there is enough available memory for this request
- slot->m_start = m_memConfig[mem].nextAvailable;
- slot->m_end = slot->m_start + sizeBytes -1;
- slot->m_currentWrPosition = slot->m_start; // init to start of slot
- slot->m_currentRdPosition = slot->m_start; // init to start of slot
- slot->m_size = sizeBytes;
-
- if (!m_memConfig[mem].m_spi) {
- if (useDma) {
- m_memConfig[mem].m_spi = new BALibrary::BASpiMemoryDMA(static_cast(mem));
- slot->m_useDma = true;
- } else {
- m_memConfig[mem].m_spi = new BALibrary::BASpiMemory(static_cast(mem));
- slot->m_useDma = false;
- }
- if (!m_memConfig[mem].m_spi) {
- } else {
- Serial.println("Calling spi begin()");
- m_memConfig[mem].m_spi->begin();
- }
- }
- slot->m_spi = m_memConfig[mem].m_spi;
-
- // Update the mem config
- m_memConfig[mem].nextAvailable = slot->m_end+1;
- 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();
- return true;
- } else {
- // there is not enough memory available for the request
- Serial.println(String("ExternalSramManager::requestMemory(): Insufficient memory in slot, request/available: ")
- + sizeBytes + String(" : ")
- + m_memConfig[mem].totalAvailable);
- return false;
- }
-}
-
-}
-
diff --git a/src/effects/AudioEffectAnalogChorus.cpp b/src/effects/AudioEffectAnalogChorus.cpp
index 81b559d..74c77a9 100644
--- a/src/effects/AudioEffectAnalogChorus.cpp
+++ b/src/effects/AudioEffectAnalogChorus.cpp
@@ -31,21 +31,6 @@ AudioEffectAnalogChorus::AudioEffectAnalogChorus()
m_lfo.setRateAudio(4.0f); // Default to 4 Hz
}
-// requires preallocated memory large enough
-AudioEffectAnalogChorus::AudioEffectAnalogChorus(ExtMemSlot *slot)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(slot);
- m_maxDelaySamples = (slot->size() / sizeof(int16_t));
- m_averageDelaySamples = static_cast(calcAudioSamples(m_DEFAULT_AVERAGE_DELAY_MS));
- m_delayRange = static_cast(calcAudioSamples(m_DELAY_RANGE));
-
- m_externalMemory = true;
- m_constructFilter();
- m_lfo.setWaveform(Waveform::TRIANGLE);
- m_lfo.setRateAudio(4.0f); // Default to 4 Hz
-}
-
AudioEffectAnalogChorus::~AudioEffectAnalogChorus()
{
if (m_memory) delete m_memory;
@@ -179,12 +164,6 @@ void AudioEffectAnalogChorus::update(void)
// BACK TO OUTPUT PROCESSING
- // Check if external DMA, if so, we need to be sure the read is completed
- if (m_externalMemory && m_memory->getSlot()->isUseDma()) {
- // Using DMA so we have to busy-wait here until DMA is done
- while (m_memory->getSlot()->isReadBusy()) {}
- }
-
double bufferIndexFloat;
int delayIndex;
for (int i=0, j=AUDIO_BLOCK_SAMPLES-1; igetSlot();
-
- if (!slot) { Serial.println("ERROR: slot ptr is not valid"); }
- if (!slot->isEnabled()) {
- slot->enable();
- Serial.println("WEIRD: slot was not enabled");
- }
- }
}
void AudioEffectAnalogChorus::rate(float rate)
diff --git a/src/effects/AudioEffectAnalogDelay.cpp b/src/effects/AudioEffectAnalogDelay.cpp
deleted file mode 100644
index f64f172..0000000
--- a/src/effects/AudioEffectAnalogDelay.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * AudioEffectAnalogDelay.cpp
- *
- * Created on: Jan 7, 2018
- * Author: slascos
- */
-#include
-#include "AudioEffectAnalogDelayFilters.h"
-#include "AudioEffectAnalogDelay.h"
-
-using namespace BALibrary;
-
-namespace BAEffects {
-
-constexpr int MIDI_CHANNEL = 0;
-constexpr int MIDI_CONTROL = 1;
-
-AudioEffectAnalogDelay::AudioEffectAnalogDelay(float maxDelayMs)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(maxDelayMs);
- m_maxDelaySamples = calcAudioSamples(maxDelayMs);
- m_constructFilter();
-}
-
-AudioEffectAnalogDelay::AudioEffectAnalogDelay(size_t numSamples)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(numSamples);
- m_maxDelaySamples = numSamples;
- m_constructFilter();
-}
-
-// requires preallocated memory large enough
-AudioEffectAnalogDelay::AudioEffectAnalogDelay(ExtMemSlot *slot)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(slot);
- m_maxDelaySamples = (slot->size() / sizeof(int16_t));
- m_externalMemory = true;
- m_constructFilter();
-}
-
-AudioEffectAnalogDelay::~AudioEffectAnalogDelay()
-{
- if (m_memory) delete m_memory;
- if (m_iir) delete m_iir;
-}
-
-// This function just sets up the default filter and coefficients
-void AudioEffectAnalogDelay::m_constructFilter(void)
-{
- // Use DM3 coefficients by default
- m_iir = new IirBiQuadFilterHQ(DM3_NUM_STAGES, reinterpret_cast(&DM3), DM3_COEFF_SHIFT);
-}
-
-void AudioEffectAnalogDelay::setFilterCoeffs(int numStages, const int32_t *coeffs, int coeffShift)
-{
- m_iir->changeFilterCoeffs(numStages, coeffs, coeffShift);
-}
-
-void AudioEffectAnalogDelay::setFilter(Filter filter)
-{
- switch(filter) {
- case Filter::WARM :
- m_iir->changeFilterCoeffs(WARM_NUM_STAGES, reinterpret_cast(&WARM), WARM_COEFF_SHIFT);
- break;
- case Filter::DARK :
- m_iir->changeFilterCoeffs(DARK_NUM_STAGES, reinterpret_cast(&DARK), DARK_COEFF_SHIFT);
- break;
- case Filter::DM3 :
- default:
- m_iir->changeFilterCoeffs(DM3_NUM_STAGES, reinterpret_cast(&DM3), DM3_COEFF_SHIFT);
- break;
- }
-}
-
-void AudioEffectAnalogDelay::update(void)
-{
- audio_block_t *inputAudioBlock = receiveReadOnly(); // get the next block of input samples
-
- // Check is block is disabled
- if (m_enable == false) {
- // do not transmit or process any audio, return as quickly as possible.
- if (inputAudioBlock) release(inputAudioBlock);
-
- // release all held memory resources
- if (m_previousBlock) {
- release(m_previousBlock); m_previousBlock = nullptr;
- }
- if (!m_externalMemory) {
- // when using internal memory we have to release all references in the ring buffer
- while (m_memory->getRingBuffer()->size() > 0) {
- audio_block_t *releaseBlock = m_memory->getRingBuffer()->front();
- m_memory->getRingBuffer()->pop_front();
- if (releaseBlock) release(releaseBlock);
- }
- }
- return;
- }
-
- // Check is block is bypassed, if so either transmit input directly or create silence
- if (m_bypass == true) {
- // transmit the input directly
- if (!inputAudioBlock) {
- // create silence
- inputAudioBlock = allocate();
- if (!inputAudioBlock) { return; } // failed to allocate
- else {
- clearAudioBlock(inputAudioBlock);
- }
- }
- transmit(inputAudioBlock, 0);
- release(inputAudioBlock);
- return;
- }
-
- // Otherwise perform normal processing
- // In order to make use of the SPI DMA, we need to request the read from memory first,
- // then do other processing while it fills in the back.
- audio_block_t *blockToOutput = nullptr; // this will hold the output audio
- blockToOutput = allocate();
- if (!blockToOutput) return; // skip this update cycle due to failure
-
- // get the data. If using external memory with DMA, this won't be filled until
- // later.
- m_memory->getSamples(blockToOutput, m_delaySamples);
-
- // If using DMA, we need something else to do while that read executes, so
- // move on to input preprocessing
-
- // Preprocessing
- audio_block_t *preProcessed = allocate();
- // mix the input with the feedback path in the pre-processing stage
- m_preProcessing(preProcessed, inputAudioBlock, m_previousBlock);
-
- // consider doing the BBD post processing here to use up more time while waiting
- // for the read data to come back
- audio_block_t *blockToRelease = m_memory->addBlock(preProcessed);
-
-
- // BACK TO OUTPUT PROCESSING
- // Check if external DMA, if so, we need to be sure the read is completed
- if (m_externalMemory && m_memory->getSlot()->isUseDma()) {
- // Using DMA
- while (m_memory->getSlot()->isReadBusy()) {}
- }
-
- // perform the wet/dry mix mix
- m_postProcessing(blockToOutput, inputAudioBlock, blockToOutput);
- transmit(blockToOutput);
-
- release(inputAudioBlock);
- release(m_previousBlock);
- m_previousBlock = blockToOutput;
-
- if (m_blockToRelease) release(m_blockToRelease);
- m_blockToRelease = blockToRelease;
-}
-
-void AudioEffectAnalogDelay::delay(float milliseconds)
-{
- size_t delaySamples = calcAudioSamples(milliseconds);
-
- if (delaySamples > m_memory->getMaxDelaySamples()) {
- // this exceeds max delay value, limit it.
- delaySamples = m_memory->getMaxDelaySamples();
- }
-
- if (!m_memory) { Serial.println("delay(): m_memory is not valid"); }
-
- if (!m_externalMemory) {
- // internal memory
- //QueuePosition queuePosition = calcQueuePosition(milliseconds);
- //Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
- } else {
- // external memory
- //Serial.println(String("CONFIG: delay:") + delaySamples);
- ExtMemSlot *slot = m_memory->getSlot();
-
- if (!slot) { Serial.println("ERROR: slot ptr is not valid"); }
- if (!slot->isEnabled()) {
- slot->enable();
- Serial.println("WEIRD: slot was not enabled");
- }
- }
-
- m_delaySamples = delaySamples;
-}
-
-void AudioEffectAnalogDelay::delay(size_t delaySamples)
-{
- if (!m_memory) { Serial.println("delay(): m_memory is not valid"); }
-
- if (!m_externalMemory) {
- // internal memory
- //QueuePosition queuePosition = calcQueuePosition(delaySamples);
- //Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
- } else {
- // external memory
- //Serial.println(String("CONFIG: delay:") + delaySamples);
- ExtMemSlot *slot = m_memory->getSlot();
- if (!slot->isEnabled()) {
- slot->enable();
- }
- }
- m_delaySamples = delaySamples;
-}
-
-void AudioEffectAnalogDelay::delayFractionMax(float delayFraction)
-{
- size_t delaySamples = static_cast(static_cast(m_memory->getMaxDelaySamples()) * delayFraction);
-
- if (delaySamples > m_memory->getMaxDelaySamples()) {
- // this exceeds max delay value, limit it.
- delaySamples = m_memory->getMaxDelaySamples();
- }
-
- if (!m_memory) { Serial.println("delay(): m_memory is not valid"); }
-
- if (!m_externalMemory) {
- // internal memory
- //QueuePosition queuePosition = calcQueuePosition(delaySamples);
- //Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
- } else {
- // external memory
- //Serial.println(String("CONFIG: delay:") + delaySamples);
- ExtMemSlot *slot = m_memory->getSlot();
- if (!slot->isEnabled()) {
- slot->enable();
- }
- }
- m_delaySamples = delaySamples;
-}
-
-void AudioEffectAnalogDelay::m_preProcessing(audio_block_t *out, audio_block_t *dry, audio_block_t *wet)
-{
- if ( out && dry && wet) {
- alphaBlend(out, dry, wet, m_feedback);
- m_iir->process(out->data, out->data, AUDIO_BLOCK_SAMPLES);
- } else if (dry) {
- memcpy(out->data, dry->data, sizeof(int16_t) * AUDIO_BLOCK_SAMPLES);
- }
-}
-
-void AudioEffectAnalogDelay::m_postProcessing(audio_block_t *out, audio_block_t *dry, audio_block_t *wet)
-{
- if (!out) return; // no valid output buffer
-
- if ( out && dry && wet) {
- // Simulate the LPF IIR nature of the analog systems
- //m_iir->process(wet->data, wet->data, AUDIO_BLOCK_SAMPLES);
- alphaBlend(out, dry, wet, m_mix);
- } else if (dry) {
- memcpy(out->data, dry->data, sizeof(int16_t) * AUDIO_BLOCK_SAMPLES);
- }
- // Set the output volume
- gainAdjust(out, out, m_volume, 1);
-
-}
-
-
-void AudioEffectAnalogDelay::processMidi(int channel, int control, int value)
-{
-
- float val = (float)value / 127.0f;
-
- if ((m_midiConfig[DELAY][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[DELAY][MIDI_CONTROL] == control)) {
- // Delay
- if (m_externalMemory) { m_maxDelaySamples = m_memory->getSlot()->size() / sizeof(int16_t); }
- 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);
- 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); }
- return;
- }
-
- if ((m_midiConfig[FEEDBACK][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[FEEDBACK][MIDI_CONTROL] == control)) {
- // Feedback
- Serial.println(String("AudioEffectAnalogDelay::feedback: ") + 100*val + String("%"));
- feedback(val);
- return;
- }
-
- 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 );
- mix(val);
- return;
- }
-
- if ((m_midiConfig[VOLUME][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[VOLUME][MIDI_CONTROL] == control)) {
- // Volume
- Serial.println(String("AudioEffectAnalogDelay::volume: ") + 100*val + String("%"));
- volume(val);
- return;
- }
-
-}
-
-void AudioEffectAnalogDelay::mapMidiControl(int parameter, int midiCC, int midiChannel)
-{
- if (parameter >= NUM_CONTROLS) {
- return ; // Invalid midi parameter
- }
- m_midiConfig[parameter][MIDI_CHANNEL] = midiChannel;
- m_midiConfig[parameter][MIDI_CONTROL] = midiCC;
-}
-
-}
-
-
diff --git a/src/effects/AudioEffectAnalogDelayFilters.h b/src/effects/AudioEffectAnalogDelayFilters.h
deleted file mode 100644
index 473f9cd..0000000
--- a/src/effects/AudioEffectAnalogDelayFilters.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/**************************************************************************//**
- * @file
- * @author Steve Lascos
- * @company Blackaddr Audio
- *
- * This file constains precomputed co-efficients for the AudioEffectAnalogDelay
- * class.
- *
- * @copyright This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.*
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-#include
-
-namespace BAEffects {
-
-// The number of stages in the analog-response Biquad filter
-constexpr unsigned MAX_NUM_FILTER_STAGES = 4;
-constexpr unsigned NUM_COEFFS_PER_STAGE = 5;
-
-// Matlab/Octave can be helpful to design a filter. Once you have the IIR filter (bz,az) coefficients
-// in the z-domain, they can be converted to second-order-sections. AudioEffectAnalogDelay is designed
-// to accept up to a maximum of an 8th order filter, broken into four, 2nd order stages.
-//
-// Second order sections can be created with:
-// [sos] = tf2sos(bz,az);
-// The results coefficents must be converted the Q31 format required by the ARM CMSIS-DSP library. This means
-// all coefficients must lie between -1.0 and +0.9999. If your (bz,az) coefficients exceed this, you must divide
-// them down by a power of 2. For example, if your largest magnitude coefficient is -3.5, you must divide by
-// 2^shift where 4=2^2 and thus shift = 2. You must then mutliply by 2^31 to get a 32-bit signed integer value
-// that represents the required Q31 coefficient.
-
-// BOSS DM-3 Filters
-// b(z) = 1.0e-03 * (0.0032 0.0257 0.0900 0.1800 0.2250 0.1800 0.0900 0.0257 0.0032)
-// a(z) = 1.0000 -5.7677 14.6935 -21.3811 19.1491 -10.5202 3.2584 -0.4244 -0.0067
-constexpr unsigned DM3_NUM_STAGES = 4;
-constexpr unsigned DM3_COEFF_SHIFT = 2;
-constexpr int32_t DM3[5*MAX_NUM_FILTER_STAGES] = {
- 536870912, 988616936, 455608573, 834606945, -482959709,
- 536870912, 1031466345, 498793368, 965834205, -467402235,
- 536870912, 1105821939, 573646688, 928470657, -448083489,
- 2339, 5093, 2776, 302068995, 4412722
-};
-
-
-// Blackaddr WARM Filter
-// Butterworth, 8th order, cutoff = 2000 Hz
-// Matlab/Octave command: [bz, az] = butter(8, 2000/44100/2);
-// b(z) = 1.0e-05 * (0.0086 0.0689 0.2411 0.4821 0.6027 0.4821 0.2411 0.0689 0.0086_
-// a(z) = 1.0000 -6.5399 18.8246 -31.1340 32.3473 -21.6114 9.0643 -2.1815 0.2306
-constexpr unsigned WARM_NUM_STAGES = 4;
-constexpr unsigned WARM_COEFF_SHIFT = 2;
-constexpr int32_t WARM[5*MAX_NUM_FILTER_STAGES] = {
- 536870912,1060309346,523602393,976869875,-481046241,
- 536870912,1073413910,536711084,891250612,-391829326,
- 536870912,1087173998,550475248,835222426,-333446881,
- 46,92,46,807741349,-304811072
-};
-
-// Blackaddr DARK Filter
-// Chebychev Type II, 8th order, stopband = 60db, cutoff = 1000 Hz
-// Matlab command: [bz, az] = cheby2(8, 60, 1000/44100/2);
-// b(z) = 0.0009 -0.0066 0.0219 -0.0423 0.0522 -0.0423 0.0219 -0.0066 0.0009
-// a(z) = 1.0000 -7.4618 24.3762 -45.5356 53.1991 -39.8032 18.6245 -4.9829 0.5836
-constexpr unsigned DARK_NUM_STAGES = 4;
-constexpr unsigned DARK_COEFF_SHIFT = 1;
-constexpr int32_t DARK[5*MAX_NUM_FILTER_STAGES] = {
- 1073741824,-2124867808,1073741824,2107780229,-1043948409,
- 1073741824,-2116080466,1073741824,2042553796,-979786242,
- 1073741824,-2077777790,1073741824,1964779896,-904264933,
- 957356,-1462833,957356,1896884898,-838694612
-};
-
-};
diff --git a/src/effects/AudioEffectDelayExternal.cpp b/src/effects/AudioEffectDelayExternal.cpp
deleted file mode 100644
index 1f1c215..0000000
--- a/src/effects/AudioEffectDelayExternal.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * BAAudioEffectDelayExternal.cpp
- *
- * Created on: November 1, 2017
- * 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 "BAAudioEffectDelayExternal.h"
-
-using namespace BALibrary;
-
-namespace BAEffects {
-
-#define SPISETTING SPISettings(20000000, MSBFIRST, SPI_MODE0)
-
-struct MemSpiConfig {
- unsigned mosiPin;
- unsigned misoPin;
- unsigned sckPin;
- unsigned csPin;
- unsigned memSize;
-};
-
-constexpr MemSpiConfig Mem0Config = {7, 8, 14, 15, 65536 };
-constexpr MemSpiConfig Mem1Config = {21, 5, 20, 31, 65536 };
-
-unsigned BAAudioEffectDelayExternal::m_usingSPICount[2] = {0,0};
-
-BAAudioEffectDelayExternal::BAAudioEffectDelayExternal()
-: AudioStream(1, m_inputQueueArray)
-{
- initialize(MemSelect::MEM0);
-}
-
-BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(MemSelect mem)
-: AudioStream(1, m_inputQueueArray)
-{
- initialize(mem);
-}
-
-BAAudioEffectDelayExternal::BAAudioEffectDelayExternal(BALibrary::MemSelect type, float delayLengthMs)
-: AudioStream(1, m_inputQueueArray)
-{
- unsigned delayLengthInt = (delayLengthMs*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f;
- initialize(type, delayLengthInt);
-}
-
-BAAudioEffectDelayExternal::~BAAudioEffectDelayExternal()
-{
- if (m_spi) delete m_spi;
-}
-
-void BAAudioEffectDelayExternal::delay(uint8_t channel, float milliseconds) {
-
- if (channel >= 8) return;
- if (milliseconds < 0.0) milliseconds = 0.0;
- uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f;
- n += AUDIO_BLOCK_SAMPLES;
- if (n > m_memoryLength - AUDIO_BLOCK_SAMPLES)
- n = m_memoryLength - AUDIO_BLOCK_SAMPLES;
- m_channelDelayLength[channel] = n;
- unsigned mask = m_activeMask;
- if (m_activeMask == 0) m_startUsingSPI(m_spiChannel);
- m_activeMask = mask | (1<= 8) return;
- uint8_t mask = m_activeMask & ~(1<data);
- m_headOffset += AUDIO_BLOCK_SAMPLES;
- } else {
- // write wraps across end-of-memory
- n = m_memoryLength - m_headOffset;
- write(m_headOffset, n, block->data);
- m_headOffset = AUDIO_BLOCK_SAMPLES - n;
- write(0, m_headOffset, block->data + n);
- }
- release(block);
- } else {
- // if no input, store zeros, so later playback will
- // not be random garbage previously stored in memory
- if (m_headOffset + AUDIO_BLOCK_SAMPLES <= m_memoryLength) {
- zero(m_headOffset, AUDIO_BLOCK_SAMPLES);
- m_headOffset += AUDIO_BLOCK_SAMPLES;
- } else {
- n = m_memoryLength - m_headOffset;
- zero(m_headOffset, n);
- m_headOffset = AUDIO_BLOCK_SAMPLES - n;
- zero(0, m_headOffset);
- }
- }
-
- // transmit the delayed outputs
- for (channel = 0; channel < 8; channel++) {
- if (!(m_activeMask & (1<data);
- } else {
- // read wraps across end-of-memory
- n = m_memoryLength - read_offset;
- read(read_offset, n, block->data);
- read(0, AUDIO_BLOCK_SAMPLES - n, block->data + n);
- }
- transmit(block, channel);
- release(block);
- }
-}
-
-unsigned BAAudioEffectDelayExternal::m_allocated[2] = {0, 0};
-
-void BAAudioEffectDelayExternal::initialize(MemSelect mem, unsigned delayLength)
-{
- unsigned samples = 0;
- unsigned memsize, avail;
-
- m_activeMask = 0;
- m_headOffset = 0;
- m_mem = mem;
-
- switch (mem) {
- case MemSelect::MEM0 :
- {
- memsize = Mem0Config.memSize;
- m_spi = &SPI;
- m_spiChannel = 0;
- m_misoPin = Mem0Config.misoPin;
- m_mosiPin = Mem0Config.mosiPin;
- m_sckPin = Mem0Config.sckPin;
- m_csPin = Mem0Config.csPin;
-
- m_spi->setMOSI(m_mosiPin);
- m_spi->setMISO(m_misoPin);
- m_spi->setSCK(m_sckPin);
- m_spi->begin();
- break;
- }
- case MemSelect::MEM1 :
- {
-#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
- memsize = Mem1Config.memSize;
- m_spi = &SPI1;
- m_spiChannel = 1;
- m_misoPin = Mem1Config.misoPin;
- m_mosiPin = Mem1Config.mosiPin;
- m_sckPin = Mem1Config.sckPin;
- m_csPin = Mem1Config.csPin;
-
- m_spi->setMOSI(m_mosiPin);
- m_spi->setMISO(m_misoPin);
- m_spi->setSCK(m_sckPin);
- m_spi->begin();
-#endif
- break;
- }
-
- }
-
- pinMode(m_csPin, OUTPUT);
- digitalWriteFast(m_csPin, HIGH);
-
- avail = memsize - m_allocated[mem];
-
- if (delayLength > avail) samples = avail;
- m_memoryStart = m_allocated[mem];
- m_allocated[mem] += samples;
- m_memoryLength = samples;
-
- zero(0, m_memoryLength);
-
-}
-
-
-void BAAudioEffectDelayExternal::read(uint32_t offset, uint32_t count, int16_t *data)
-{
- uint32_t addr = m_memoryStart + offset;
- addr *= 2;
-
- m_spi->beginTransaction(SPISETTING);
- digitalWriteFast(m_csPin, LOW);
- m_spi->transfer16((0x03 << 8) | (addr >> 16));
- m_spi->transfer16(addr & 0xFFFF);
-
- while (count) {
- *data++ = (int16_t)(m_spi->transfer16(0));
- count--;
- }
- digitalWriteFast(m_csPin, HIGH);
- m_spi->endTransaction();
-
-}
-
-void BAAudioEffectDelayExternal::write(uint32_t offset, uint32_t count, const int16_t *data)
-{
- uint32_t addr = m_memoryStart + offset;
-
- addr *= 2;
- m_spi->beginTransaction(SPISETTING);
- digitalWriteFast(m_csPin, LOW);
- m_spi->transfer16((0x02 << 8) | (addr >> 16));
- m_spi->transfer16(addr & 0xFFFF);
- while (count) {
- int16_t w = 0;
- if (data) w = *data++;
- m_spi->transfer16(w);
- count--;
- }
- digitalWriteFast(m_csPin, HIGH);
- m_spi->endTransaction();
-
-}
-
-///////////////////////////////////////////////////////////////////
-// PRIVATE METHODS
-///////////////////////////////////////////////////////////////////
-void BAAudioEffectDelayExternal::zero(uint32_t address, uint32_t count) {
- write(address, count, NULL);
-}
-
-#ifdef SPI_HAS_NOTUSINGINTERRUPT
-inline void BAAudioEffectDelayExternal::m_startUsingSPI(int spiBus) {
- if (spiBus == 0) {
- m_spi->usingInterrupt(IRQ_SOFTWARE);
- } else if (spiBus == 1) {
- m_spi->usingInterrupt(IRQ_SOFTWARE);
- }
- m_usingSPICount[spiBus]++;
-}
-
-inline void BAAudioEffectDelayExternal::m_stopUsingSPI(int spiBus) {
- if (m_usingSPICount[spiBus] == 0 || --m_usingSPICount[spiBus] == 0)
- {
- if (spiBus == 0) {
- m_spi->notUsingInterrupt(IRQ_SOFTWARE);
- } else if (spiBus == 1) {
- m_spi->notUsingInterrupt(IRQ_SOFTWARE);
- }
-
- }
-}
-
-#else
-inline void BAAudioEffectDelayExternal::m_startUsingSPI(int spiBus) {
- if (spiBus == 0) {
- m_spi->usingInterrupt(IRQ_SOFTWARE);
- } else if (spiBus == 1) {
- m_spi->usingInterrupt(IRQ_SOFTWARE);
- }
-
-}
-inline void BAAudioEffectDelayExternal::m_stopUsingSPI(int spiBus) {
-}
-
-#endif
-
-
-} /* namespace BAEffects */
diff --git a/src/effects/AudioEffectSOS.cpp b/src/effects/AudioEffectSOS.cpp
deleted file mode 100644
index 2512261..0000000
--- a/src/effects/AudioEffectSOS.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * AudioEffectSOS.cpp
- *
- * Created on: Apr 14, 2018
- * Author: blackaddr
- */
-
-#include "AudioEffectSOS.h"
-#include "LibBasicFunctions.h"
-
-using namespace BALibrary;
-
-namespace BAEffects {
-
-constexpr int MIDI_CHANNEL = 0;
-constexpr int MIDI_CONTROL = 1;
-
-constexpr float MAX_GATE_OPEN_TIME_MS = 3000.0f;
-constexpr float MAX_GATE_CLOSE_TIME_MS = 1000.0f;
-
-constexpr int GATE_OPEN_STAGE = 0;
-constexpr int GATE_HOLD_STAGE = 1;
-constexpr int GATE_CLOSE_STAGE = 2;
-
-AudioEffectSOS::AudioEffectSOS(float maxDelayMs)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(maxDelayMs);
- m_maxDelaySamples = calcAudioSamples(maxDelayMs);
- m_externalMemory = false;
-}
-
-AudioEffectSOS::AudioEffectSOS(size_t numSamples)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(numSamples);
- m_maxDelaySamples = numSamples;
- m_externalMemory = false;
-}
-
-AudioEffectSOS::AudioEffectSOS(ExtMemSlot *slot)
-: AudioStream(1, m_inputQueueArray)
-{
- m_memory = new AudioDelay(slot);
- m_externalMemory = true;
-}
-
-AudioEffectSOS::~AudioEffectSOS()
-{
- if (m_memory) delete m_memory;
-}
-
-void AudioEffectSOS::setGateLedGpio(int pinId)
-{
- m_gateLedPinId = pinId;
- pinMode(static_cast(m_gateLedPinId), OUTPUT);
-}
-
-void AudioEffectSOS::enable(void)
-{
- m_enable = true;
- if (m_externalMemory) {
- // 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();
- 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);
- m_inputGateAuto.setupParameter(GATE_HOLD_STAGE, 1.0f, 1.0f, m_maxDelaySamples, ParameterAutomation::Function::HOLD);
- m_inputGateAuto.setupParameter(GATE_CLOSE_STAGE, 1.0f, 0.0f, 1000.0f, ParameterAutomation::Function::EXPONENTIAL);
-
- m_clearFeedbackAuto.setupParameter(GATE_OPEN_STAGE, 1.0f, 0.0f, 1000.0f, ParameterAutomation::Function::EXPONENTIAL);
- m_clearFeedbackAuto.setupParameter(GATE_HOLD_STAGE, 0.0f, 0.0f, m_maxDelaySamples, ParameterAutomation::Function::HOLD);
- m_clearFeedbackAuto.setupParameter(GATE_CLOSE_STAGE, 0.0f, 1.0f, 1000.0f, ParameterAutomation::Function::EXPONENTIAL);
-}
-
-void AudioEffectSOS::update(void)
-{
- audio_block_t *inputAudioBlock = receiveReadOnly(); // get the next block of input samples
-
- // Check is block is disabled
- if (m_enable == false) {
- // do not transmit or process any audio, return as quickly as possible.
- if (inputAudioBlock) release(inputAudioBlock);
-
- // release all held memory resources
- if (m_previousBlock) {
- release(m_previousBlock); m_previousBlock = nullptr;
- }
- if (!m_externalMemory) {
- // when using internal memory we have to release all references in the ring buffer
- while (m_memory->getRingBuffer()->size() > 0) {
- audio_block_t *releaseBlock = m_memory->getRingBuffer()->front();
- m_memory->getRingBuffer()->pop_front();
- if (releaseBlock) release(releaseBlock);
- }
- }
- return;
- }
-
- // Check is block is bypassed, if so either transmit input directly or create silence
- if ( (m_bypass == true) || (!inputAudioBlock) ) {
- // transmit the input directly
- if (!inputAudioBlock) {
- // create silence
- inputAudioBlock = allocate();
- if (!inputAudioBlock) { return; } // failed to allocate
- else {
- clearAudioBlock(inputAudioBlock);
- }
- }
- transmit(inputAudioBlock, 0);
- release(inputAudioBlock);
- return;
- }
-
- if (!inputAudioBlock) return;
-
- // Otherwise perform normal processing
- // In order to make use of the SPI DMA, we need to request the read from memory first,
- // then do other processing while it fills in the back.
- audio_block_t *blockToOutput = nullptr; // this will hold the output audio
- blockToOutput = allocate();
- if (!blockToOutput) return; // skip this update cycle due to failure
-
- // 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 using DMA, we need something else to do while that read executes, so
- // move on to input preprocessing
-
- // Preprocessing
- audio_block_t *preProcessed = allocate();
- // mix the input with the feedback path in the pre-processing stage
- m_preProcessing(preProcessed, inputAudioBlock, m_previousBlock);
-
- // consider doing the BBD post processing here to use up more time while waiting
- // for the read data to come back
- audio_block_t *blockToRelease = m_memory->addBlock(preProcessed);
- //audio_block_t *blockToRelease = m_memory->addBlock(inputAudioBlock);
- //Serial.println("Done adding new block");
-
-
- // BACK TO OUTPUT PROCESSING
- // Check if external DMA, if so, we need to be sure the read is completed
- if (m_externalMemory && m_memory->getSlot()->isUseDma()) {
- // Using DMA
- while (m_memory->getSlot()->isReadBusy()) {}
- }
-
- // perform the wet/dry mix mix
- m_postProcessing(blockToOutput, blockToOutput);
- transmit(blockToOutput);
-
- release(inputAudioBlock);
-
- if (m_previousBlock)
- release(m_previousBlock);
- m_previousBlock = blockToOutput;
-
- if (m_blockToRelease == m_previousBlock) {
- Serial.println("ERROR: POINTER COLLISION");
- }
-
- if (m_blockToRelease) release(m_blockToRelease);
- m_blockToRelease = blockToRelease;
-}
-
-
-void AudioEffectSOS::gateOpenTime(float milliseconds)
-{
- // TODO - change the paramter automation to an automation sequence
- m_openTimeMs = milliseconds;
- m_inputGateAuto.setupParameter(GATE_OPEN_STAGE, 0.0f, 1.0f, m_openTimeMs, ParameterAutomation::Function::EXPONENTIAL);
- //m_clearFeedbackAuto.setupParameter(GATE_OPEN_STAGE, 1.0f, 0.0f, m_openTimeMs, ParameterAutomation::Function::EXPONENTIAL);
-}
-
-void AudioEffectSOS::gateCloseTime(float milliseconds)
-{
- m_closeTimeMs = milliseconds;
- m_inputGateAuto.setupParameter(GATE_CLOSE_STAGE, 1.0f, 0.0f, m_closeTimeMs, ParameterAutomation::Function::EXPONENTIAL);
- //m_clearFeedbackAuto.setupParameter(GATE_CLOSE_STAGE, 0.0f, 1.0f, m_closeTimeMs, ParameterAutomation::Function::EXPONENTIAL);
-}
-
-////////////////////////////////////////////////////////////////////////
-// MIDI PROCESSING
-////////////////////////////////////////////////////////////////////////
-void AudioEffectSOS::processMidi(int channel, int control, int value)
-{
-
- float val = (float)value / 127.0f;
-
- if ((m_midiConfig[GATE_OPEN_TIME][MIDI_CHANNEL] == channel) &&
- (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);
- return;
- }
-
- if ((m_midiConfig[GATE_CLOSE_TIME][MIDI_CHANNEL] == channel) &&
- (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);
- return;
- }
-
- if ((m_midiConfig[FEEDBACK][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[FEEDBACK][MIDI_CONTROL] == control)) {
- // Feedback
- Serial.println(String("AudioEffectSOS::feedback: ") + 100*val + String("%"));
- feedback(val);
- return;
- }
-
- if ((m_midiConfig[VOLUME][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[VOLUME][MIDI_CONTROL] == control)) {
- // Volume
- Serial.println(String("AudioEffectSOS::volume: ") + 100*val + String("%"));
- volume(val);
- return;
- }
-
- 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); }
- 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!"));
- m_inputGateAuto.trigger();
- return;
- }
-
- 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!"));
- m_clearFeedbackAuto.trigger();
- return;
- }
-}
-
-void AudioEffectSOS::mapMidiControl(int parameter, int midiCC, int midiChannel)
-{
- if (parameter >= NUM_CONTROLS) {
- return ; // Invalid midi parameter
- }
- m_midiConfig[parameter][MIDI_CHANNEL] = midiChannel;
- m_midiConfig[parameter][MIDI_CONTROL] = midiCC;
-}
-
-//////////////////////////////////////////////////////////////////////
-// PRIVATE FUNCTIONS
-//////////////////////////////////////////////////////////////////////
-void AudioEffectSOS::m_preProcessing (audio_block_t *out, audio_block_t *input, audio_block_t *delayedSignal)
-{
- if ( out && input && delayedSignal) {
- // Multiply the input signal by the automated gate value
- // Multiply the delayed signal by the user set feedback value
- // Then combine the two
-
- float gateVol = m_inputGateAuto.getNextValue();
- float feedbackAdjust = m_clearFeedbackAuto.getNextValue();
- audio_block_t tempAudioBuffer;
-
- gainAdjust(out, input, gateVol, 0); // last paremeter is coeff shift, 0 bits
- gainAdjust(&tempAudioBuffer, delayedSignal, m_feedback*feedbackAdjust, 0); // last parameter is coeff shift, 0 bits
- combine(out, out, &tempAudioBuffer);
-
- } else if (input) {
- memcpy(out->data, input->data, sizeof(int16_t) * AUDIO_BLOCK_SAMPLES);
- }
-
- // Update the gate LED
- if (m_gateLedPinId >= 0) {
- if (m_inputGateAuto.isFinished() && m_clearFeedbackAuto.isFinished()) {
- digitalWriteFast(m_gateLedPinId, 0x0);
- } else {
- digitalWriteFast(m_gateLedPinId, 0x1);
- }
- }
-}
-
-void AudioEffectSOS::m_postProcessing(audio_block_t *out, audio_block_t *in)
-{
- gainAdjust(out, out, m_volume, 0);
-}
-
-
-} // namespace BAEffects
-
-
-
diff --git a/src/effects/AudioEffectTremolo.cpp b/src/effects/AudioEffectTremolo.cpp
deleted file mode 100644
index 0bb4d67..0000000
--- a/src/effects/AudioEffectTremolo.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * AudioEffectTremolo.cpp
- *
- * Created on: Jan 7, 2018
- * Author: slascos
- */
-#include // std::roundf
-#include "AudioEffectTremolo.h"
-
-using namespace BALibrary;
-
-namespace BAEffects {
-
-constexpr int MIDI_CHANNEL = 0;
-constexpr int MIDI_CONTROL = 1;
-
-constexpr float MAX_RATE_HZ = 20.0f;
-
-AudioEffectTremolo::AudioEffectTremolo()
-: AudioStream(1, m_inputQueueArray)
-{
- m_osc.setWaveform(m_waveform);
-}
-
-AudioEffectTremolo::~AudioEffectTremolo()
-{
-}
-
-void AudioEffectTremolo::update(void)
-{
- audio_block_t *inputAudioBlock = receiveWritable(); // get the next block of input samples
-
- // Check is block is disabled
- if (m_enable == false) {
- // do not transmit or process any audio, return as quickly as possible.
- if (inputAudioBlock) release(inputAudioBlock);
- return;
- }
-
- // Check is block is bypassed, if so either transmit input directly or create silence
- if (m_bypass == true) {
- // transmit the input directly
- if (!inputAudioBlock) {
- // create silence
- inputAudioBlock = allocate();
- if (!inputAudioBlock) { return; } // failed to allocate
- else {
- clearAudioBlock(inputAudioBlock);
- }
- }
- transmit(inputAudioBlock, 0);
- release(inputAudioBlock);
- return;
- }
-
- // DO PROCESSING
- // apply modulation wave
- float *mod = m_osc.getNextVector();
- for (auto i=0; idata[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);
-}
-
-void AudioEffectTremolo::rate(float rateValue)
-{
- float rateAudioBlock = rateValue * MAX_RATE_HZ;
- m_osc.setRateAudio(rateAudioBlock);
-}
-
-void AudioEffectTremolo::setWaveform(Waveform waveform)
-{
- m_waveform = waveform;
- m_osc.setWaveform(waveform);
-}
-
-void AudioEffectTremolo::processMidi(int channel, int control, int value)
-{
-
- float val = (float)value / 127.0f;
-
- 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); }
- return;
- }
-
- if ((m_midiConfig[RATE][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[RATE][MIDI_CONTROL] == control)) {
- // Rate
- rate(val);
- Serial.println(String("AudioEffectTremolo::rate: ") + m_rate);
- return;
- }
-
- if ((m_midiConfig[DEPTH][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[DEPTH][MIDI_CONTROL] == control)) {
- // Depth
- depth(val);
- Serial.println(String("AudioEffectTremolo::depth: ") + m_depth);
- return;
- }
-
- if ((m_midiConfig[WAVEFORM][MIDI_CHANNEL] == channel) &&
- (m_midiConfig[WAVEFORM][MIDI_CONTROL] == control)) {
- // Waveform
- if (value < 16) {
- m_waveform = Waveform::SINE;
- } else if (value < 32) {
- m_waveform = Waveform::TRIANGLE;
- } else if (value < 48) {
- m_waveform = Waveform::SQUARE;
- } else if (value < 64) {
- m_waveform = Waveform::SAWTOOTH;
- } else if (value < 80) {
- m_waveform = Waveform::RANDOM;
- }
-
- 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("%"));
- volume(val);
- return;
- }
-
-}
-
-void AudioEffectTremolo::mapMidiControl(int parameter, int midiCC, int midiChannel)
-{
- if (parameter >= NUM_CONTROLS) {
- return ; // Invalid midi parameter
- }
- m_midiConfig[parameter][MIDI_CHANNEL] = midiChannel;
- m_midiConfig[parameter][MIDI_CONTROL] = midiCC;
-}
-
-}
-
-
-
diff --git a/src/peripherals/BAAudioControlWM8731.cpp b/src/peripherals/BAAudioControlWM8731.cpp
deleted file mode 100644
index f2d635e..0000000
--- a/src/peripherals/BAAudioControlWM8731.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * BAAudioControlWM8731.cpp
- *
- * Created on: May 22, 2017
- * 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 "BAAudioControlWM8731.h"
-
-namespace BALibrary {
-
-// use const instead of define for proper scoping
-constexpr int WM8731_I2C_ADDR = 0x1A;
-
-// The WM8731 register map
-constexpr int WM8731_REG_LLINEIN = 0;
-constexpr int WM8731_REG_RLINEIN = 1;
-constexpr int WM8731_REG_LHEADOUT = 2;
-constexpr int WM8731_REG_RHEADOUT = 3;
-constexpr int WM8731_REG_ANALOG =4;
-constexpr int WM8731_REG_DIGITAL = 5;
-constexpr int WM8731_REG_POWERDOWN = 6;
-constexpr int WM8731_REG_INTERFACE = 7;
-constexpr int WM8731_REG_SAMPLING = 8;
-constexpr int WM8731_REG_ACTIVE = 9;
-constexpr int WM8731_REG_RESET = 15;
-
-// Register Masks and Shifts
-// Register 0
-constexpr int WM8731_LEFT_INPUT_GAIN_ADDR = 0;
-constexpr int WM8731_LEFT_INPUT_GAIN_MASK = 0x1F;
-constexpr int WM8731_LEFT_INPUT_GAIN_SHIFT = 0;
-constexpr int WM8731_LEFT_INPUT_MUTE_ADDR = 0;
-constexpr int WM8731_LEFT_INPUT_MUTE_MASK = 0x80;
-constexpr int WM8731_LEFT_INPUT_MUTE_SHIFT = 7;
-constexpr int WM8731_LINK_LEFT_RIGHT_IN_ADDR = 0;
-constexpr int WM8731_LINK_LEFT_RIGHT_IN_MASK = 0x100;
-constexpr int WM8731_LINK_LEFT_RIGHT_IN_SHIFT = 8;
-// Register 1
-constexpr int WM8731_RIGHT_INPUT_GAIN_ADDR = 1;
-constexpr int WM8731_RIGHT_INPUT_GAIN_MASK = 0x1F;
-constexpr int WM8731_RIGHT_INPUT_GAIN_SHIFT = 0;
-constexpr int WM8731_RIGHT_INPUT_MUTE_ADDR = 1;
-constexpr int WM8731_RIGHT_INPUT_MUTE_MASK = 0x80;
-constexpr int WM8731_RIGHT_INPUT_MUTE_SHIFT = 7;
-constexpr int WM8731_LINK_RIGHT_LEFT_IN_ADDR = 1;
-constexpr int WM8731_LINK_RIGHT_LEFT_IN_MASK = 0x100;
-constexpr int WM8731_LINK_RIGHT_LEFT_IN_SHIFT = 8;
-// Register 2
-constexpr int WM8731_LEFT_HEADPHONE_VOL_ADDR = 2;
-constexpr int WM8731_LEFT_HEADPHONE_VOL_MASK = 0x7F;
-constexpr int WM8731_LEFT_HEADPHONE_VOL_SHIFT = 0;
-constexpr int WM8731_LEFT_HEADPHONE_ZCD_ADDR = 2;
-constexpr int WM8731_LEFT_HEADPHONE_ZCD_MASK = 0x80;
-constexpr int WM8731_LEFT_HEADPHONE_ZCD_SHIFT = 7;
-constexpr int WM8731_LEFT_HEADPHONE_LINK_ADDR = 2;
-constexpr int WM8731_LEFT_HEADPHONE_LINK_MASK = 0x100;
-constexpr int WM8731_LEFT_HEADPHONE_LINK_SHIFT = 8;
-// Register 3
-constexpr int WM8731_RIGHT_HEADPHONE_VOL_ADDR = 3;
-constexpr int WM8731_RIGHT_HEADPHONE_VOL_MASK = 0x7F;
-constexpr int WM8731_RIGHT_HEADPHONE_VOL_SHIFT = 0;
-constexpr int WM8731_RIGHT_HEADPHONE_ZCD_ADDR = 3;
-constexpr int WM8731_RIGHT_HEADPHONE_ZCD_MASK = 0x80;
-constexpr int WM8731_RIGHT_HEADPHONE_ZCD_SHIFT = 7;
-constexpr int WM8731_RIGHT_HEADPHONE_LINK_ADDR = 3;
-constexpr int WM8731_RIGHT_HEADPHONE_LINK_MASK = 0x100;
-constexpr int WM8731_RIGHT_HEADPHONE_LINK_SHIFT = 8;
-// Register 4
-constexpr int WM8731_ADC_BYPASS_ADDR = 4;
-constexpr int WM8731_ADC_BYPASS_MASK = 0x8;
-constexpr int WM8731_ADC_BYPASS_SHIFT = 3;
-constexpr int WM8731_DAC_SELECT_ADDR = 4;
-constexpr int WM8731_DAC_SELECT_MASK = 0x10;
-constexpr int WM8731_DAC_SELECT_SHIFT = 4;
-// Register 5
-constexpr int WM8731_DAC_MUTE_ADDR = 5;
-constexpr int WM8731_DAC_MUTE_MASK = 0x8;
-constexpr int WM8731_DAC_MUTE_SHIFT = 3;
-constexpr int WM8731_HPF_DISABLE_ADDR = 5;
-constexpr int WM8731_HPF_DISABLE_MASK = 0x1;
-constexpr int WM8731_HPF_DISABLE_SHIFT = 0;
-// Register 7
-constexpr int WM8731_LRSWAP_ADDR = 5;
-constexpr int WM8731_LRSWAP_MASK = 0x20;
-constexpr int WM8731_LRSWAPE_SHIFT = 5;
-
-// Register 9
-constexpr int WM8731_ACTIVATE_ADDR = 9;
-constexpr int WM8731_ACTIVATE_MASK = 0x1;
-
-
-// Reset the internal shadow register array to match
-// the reset state of the codec.
-void BAAudioControlWM8731::resetInternalReg(void) {
- // Set to reset state
- regArray[0] = 0x97;
- regArray[1] = 0x97;
- regArray[2] = 0x79;
- regArray[3] = 0x79;
- regArray[4] = 0x0a;
- regArray[5] = 0x8;
- regArray[6] = 0x9f;
- regArray[7] = 0xa;
- regArray[8] = 0;
- regArray[9] = 0;
-}
-
-BAAudioControlWM8731::BAAudioControlWM8731()
-{
- resetInternalReg();
-}
-
-BAAudioControlWM8731::~BAAudioControlWM8731()
-{
-}
-
-// Powerdown and disable the codec
-void BAAudioControlWM8731::disable(void)
-{
-
- //Serial.println("Disabling codec");
- if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; }
-
- // set OUTPD to '1' (powerdown), which is bit 4
- regArray[WM8731_REG_POWERDOWN] |= 0x10;
- write(WM8731_REG_POWERDOWN, regArray[WM8731_REG_POWERDOWN]);
- delay(100); // wait for power down
-
- // power down the rest of the supplies
- write(WM8731_REG_POWERDOWN, 0x9f); // complete codec powerdown
- delay(100);
-
- resetCodec();
-}
-
-// Powerup and unmute the codec
-void BAAudioControlWM8731::enable(void)
-{
-
- disable(); // disable first in case it was already powered up
-
- //Serial.println("Enabling codec");
- if (m_wireStarted == false) { Wire.begin(); m_wireStarted = true; }
- // Sequence from WAN0111.pdf
-
- // Begin configuring the codec
- resetCodec();
- delay(100); // wait for reset
-
- // Power up all domains except OUTPD and microphone
- regArray[WM8731_REG_POWERDOWN] = 0x12;
- write(WM8731_REG_POWERDOWN, regArray[WM8731_REG_POWERDOWN]);
- delay(100); // wait for codec powerup
-
-
- setAdcBypass(false); // causes a slight click
- setDacSelect(true);
- setHPFDisable(true);
- setLeftInputGain(0x17); // default input gain
- setRightInputGain(0x17);
- setLeftInMute(false); // no input mute
- setRightInMute(false);
- setDacMute(false); // unmute the DAC
-
- // link, but mute the headphone outputs
- regArray[WM8731_REG_LHEADOUT] = WM8731_LEFT_HEADPHONE_LINK_MASK;
- write(WM8731_REG_LHEADOUT, regArray[WM8731_REG_LHEADOUT]); // volume off
- regArray[WM8731_REG_RHEADOUT] = WM8731_RIGHT_HEADPHONE_LINK_MASK;
- write(WM8731_REG_RHEADOUT, regArray[WM8731_REG_RHEADOUT]);
-
- /// Configure the audio interface
- write(WM8731_REG_INTERFACE, 0x02); // I2S, 16 bit, MCLK slave
- regArray[WM8731_REG_INTERFACE] = 0x2;
-
- write(WM8731_REG_SAMPLING, 0x20); // 256*Fs, 44.1 kHz, MCLK/1
- regArray[WM8731_REG_SAMPLING] = 0x20;
- delay(100); // wait for interface config
-
- // Activate the audio interface
- setActivate(true);
- delay(100);
-
- write(WM8731_REG_POWERDOWN, 0x02); // power up outputs
- regArray[WM8731_REG_POWERDOWN] = 0x02;
- delay(500); // wait for output to power up
-
- //Serial.println("Done codec config");
-
-
- delay(100); // wait for mute ramp
-
-}
-
-// Set the PGA gain on the Left channel
-void BAAudioControlWM8731::setLeftInputGain(int val)
-{
- regArray[WM8731_LEFT_INPUT_GAIN_ADDR] &= ~WM8731_LEFT_INPUT_GAIN_MASK;
- regArray[WM8731_LEFT_INPUT_GAIN_ADDR] |=
- ((val << WM8731_LEFT_INPUT_GAIN_SHIFT) & WM8731_LEFT_INPUT_GAIN_MASK);
- write(WM8731_LEFT_INPUT_GAIN_ADDR, regArray[WM8731_LEFT_INPUT_GAIN_ADDR]);
-}
-
-// Mute control on the ADC Left channel
-void BAAudioControlWM8731::setLeftInMute(bool val)
-{
- if (val) {
- regArray[WM8731_LEFT_INPUT_MUTE_ADDR] |= WM8731_LEFT_INPUT_MUTE_MASK;
- } else {
- regArray[WM8731_LEFT_INPUT_MUTE_ADDR] &= ~WM8731_LEFT_INPUT_MUTE_MASK;
- }
- write(WM8731_LEFT_INPUT_MUTE_ADDR, regArray[WM8731_LEFT_INPUT_MUTE_ADDR]);
-}
-
-// Link the gain/mute controls for Left and Right channels
-void BAAudioControlWM8731::setLinkLeftRightIn(bool val)
-{
- if (val) {
- regArray[WM8731_LINK_LEFT_RIGHT_IN_ADDR] |= WM8731_LINK_LEFT_RIGHT_IN_MASK;
- regArray[WM8731_LINK_RIGHT_LEFT_IN_ADDR] |= WM8731_LINK_RIGHT_LEFT_IN_MASK;
- } else {
- regArray[WM8731_LINK_LEFT_RIGHT_IN_ADDR] &= ~WM8731_LINK_LEFT_RIGHT_IN_MASK;
- regArray[WM8731_LINK_RIGHT_LEFT_IN_ADDR] &= ~WM8731_LINK_RIGHT_LEFT_IN_MASK;
- }
- write(WM8731_LINK_LEFT_RIGHT_IN_ADDR, regArray[WM8731_LINK_LEFT_RIGHT_IN_ADDR]);
- write(WM8731_LINK_RIGHT_LEFT_IN_ADDR, regArray[WM8731_LINK_RIGHT_LEFT_IN_ADDR]);
-}
-
-// Set the PGA input gain on the Right channel
-void BAAudioControlWM8731::setRightInputGain(int val)
-{
- regArray[WM8731_RIGHT_INPUT_GAIN_ADDR] &= ~WM8731_RIGHT_INPUT_GAIN_MASK;
- regArray[WM8731_RIGHT_INPUT_GAIN_ADDR] |=
- ((val << WM8731_RIGHT_INPUT_GAIN_SHIFT) & WM8731_RIGHT_INPUT_GAIN_MASK);
- write(WM8731_RIGHT_INPUT_GAIN_ADDR, regArray[WM8731_RIGHT_INPUT_GAIN_ADDR]);
-}
-
-// Mute control on the input ADC right channel
-void BAAudioControlWM8731::setRightInMute(bool val)
-{
- if (val) {
- regArray[WM8731_RIGHT_INPUT_MUTE_ADDR] |= WM8731_RIGHT_INPUT_MUTE_MASK;
- } else {
- regArray[WM8731_RIGHT_INPUT_MUTE_ADDR] &= ~WM8731_RIGHT_INPUT_MUTE_MASK;
- }
- write(WM8731_RIGHT_INPUT_MUTE_ADDR, regArray[WM8731_RIGHT_INPUT_MUTE_ADDR]);
-}
-
-// Left/right swap control
-void BAAudioControlWM8731::setLeftRightSwap(bool val)
-{
- if (val) {
- regArray[WM8731_LRSWAP_ADDR] |= WM8731_LRSWAP_MASK;
- } else {
- regArray[WM8731_LRSWAP_ADDR] &= ~WM8731_LRSWAP_MASK;
- }
- write(WM8731_LRSWAP_ADDR, regArray[WM8731_LRSWAP_ADDR]);
-}
-
-void BAAudioControlWM8731::setHeadphoneVolume(float volume)
-{
- // the codec volume goes from 0x30 to 0x7F. Anything below 0x30 is mute.
- // 0dB gain is 0x79. Total range is 0x50 (80) possible values.
- unsigned vol;
- constexpr unsigned RANGE = 80.0f;
- if (volume < 0.0f) {
- vol = 0;
- } else if (volume > 1.0f) {
- vol = 0x7f;
- } else {
- vol = 0x2f + static_cast(volume * RANGE);
- }
- regArray[WM8731_LEFT_HEADPHONE_VOL_ADDR] &= ~WM8731_LEFT_HEADPHONE_VOL_MASK; // clear the volume first
- regArray[WM8731_LEFT_HEADPHONE_VOL_ADDR] |=
- ((vol << WM8731_LEFT_HEADPHONE_VOL_SHIFT) & WM8731_LEFT_HEADPHONE_VOL_MASK);
- write(WM8731_LEFT_HEADPHONE_VOL_ADDR, regArray[WM8731_LEFT_HEADPHONE_VOL_ADDR]);
-}
-
-// Dac output mute control
-void BAAudioControlWM8731::setDacMute(bool val)
-{
- if (val) {
- regArray[WM8731_DAC_MUTE_ADDR] |= WM8731_DAC_MUTE_MASK;
- } else {
- regArray[WM8731_DAC_MUTE_ADDR] &= ~WM8731_DAC_MUTE_MASK;
- }
- write(WM8731_DAC_MUTE_ADDR, regArray[WM8731_DAC_MUTE_ADDR]);
-}
-
-// Switches the DAC audio in/out of the output path
-void BAAudioControlWM8731::setDacSelect(bool val)
-{
- if (val) {
- regArray[WM8731_DAC_SELECT_ADDR] |= WM8731_DAC_SELECT_MASK;
- } else {
- regArray[WM8731_DAC_SELECT_ADDR] &= ~WM8731_DAC_SELECT_MASK;
- }
- write(WM8731_DAC_SELECT_ADDR, regArray[WM8731_DAC_SELECT_ADDR]);
-}
-
-// Bypass sends the ADC input audio (analog) directly to analog output stage
-// bypassing all digital processing
-void BAAudioControlWM8731::setAdcBypass(bool val)
-{
- if (val) {
- regArray[WM8731_ADC_BYPASS_ADDR] |= WM8731_ADC_BYPASS_MASK;
- } else {
- regArray[WM8731_ADC_BYPASS_ADDR] &= ~WM8731_ADC_BYPASS_MASK;
- }
- write(WM8731_ADC_BYPASS_ADDR, regArray[WM8731_ADC_BYPASS_ADDR]);
-}
-
-// Enable/disable the dynamic HPF (recommended, it creates noise)
-void BAAudioControlWM8731::setHPFDisable(bool val)
-{
- if (val) {
- regArray[WM8731_HPF_DISABLE_ADDR] |= WM8731_HPF_DISABLE_MASK;
- } else {
- regArray[WM8731_HPF_DISABLE_ADDR] &= ~WM8731_HPF_DISABLE_MASK;
- }
- write(WM8731_HPF_DISABLE_ADDR, regArray[WM8731_HPF_DISABLE_ADDR]);
-}
-
-// Activate/deactive the I2S audio interface
-void BAAudioControlWM8731::setActivate(bool val)
-{
- if (val) {
- write(WM8731_ACTIVATE_ADDR, WM8731_ACTIVATE_MASK);
- } else {
- write(WM8731_ACTIVATE_ADDR, 0);
- }
-
-}
-
-// Trigger the on-chip codec reset
-void BAAudioControlWM8731::resetCodec(void)
-{
- write(WM8731_REG_RESET, 0x0);
- resetInternalReg();
-}
-
-// Direct write control to the codec
-bool BAAudioControlWM8731::writeI2C(unsigned int addr, unsigned int val)
-{
- return write(addr, val);
-}
-
-// Low level write control for the codec via the Teensy I2C interface
-bool BAAudioControlWM8731::write(unsigned int reg, unsigned int val)
-{
- bool done = false;
-
- while (!done) {
- Wire.beginTransmission(WM8731_I2C_ADDR);
- Wire.write((reg << 1) | ((val >> 8) & 1));
- Wire.write(val & 0xFF);
- if (byte error = Wire.endTransmission() ) {
- (void)error; // supress warning about unused variable
- //Serial.println(String("Wire::Error: ") + error + String(" retrying..."));
- } else {
- done = true;
- //Serial.println("Wire::SUCCESS!");
- }
- }
-
- return true;
-}
-
-} /* namespace BALibrary */
diff --git a/src/peripherals/BAGpio.cpp b/src/peripherals/BAGpio.cpp
deleted file mode 100644
index e2d3c79..0000000
--- a/src/peripherals/BAGpio.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * BAGpio.cpp
- *
- * Created on: November 1, 2017
- * 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 "Arduino.h"
-#include "BAGpio.h"
-
-namespace BALibrary {
-
-BAGpio::BAGpio()
-{
- // Set all GPIOs to input
- pinMode(static_cast(GPIO::GPIO0), INPUT);
- pinMode(static_cast(GPIO::GPIO1), INPUT);
- pinMode(static_cast(GPIO::GPIO2), INPUT);
- pinMode(static_cast(GPIO::GPIO3), INPUT);
- pinMode(static_cast(GPIO::GPIO4), INPUT);
- pinMode(static_cast(GPIO::GPIO5), INPUT);
- pinMode(static_cast(GPIO::GPIO6), INPUT);
- pinMode(static_cast(GPIO::GPIO7), INPUT);
- pinMode(static_cast(GPIO::TP1), INPUT);
- pinMode(static_cast(GPIO::TP2), INPUT);
-
- // Set the LED ot ouput
- pinMode(USR_LED_ID, OUTPUT);
- clearLed(); // turn off the LED
-
-}
-
-BAGpio::~BAGpio()
-{
-}
-
-void BAGpio::setGPIODirection(GPIO gpioId, int direction)
-{
- pinMode(static_cast(gpioId), direction);
-}
-void BAGpio::setGPIO(GPIO gpioId)
-{
- digitalWrite(static_cast(gpioId), 0x1);
-}
-void BAGpio::clearGPIO(GPIO gpioId)
-{
- digitalWrite(static_cast(gpioId), 0);
-
-}
-int BAGpio::toggleGPIO(GPIO gpioId)
-{
- int data = digitalRead(static_cast(gpioId));
- digitalWrite(static_cast(gpioId), ~data);
- return ~data;
-}
-
-void BAGpio::setLed()
-{
- digitalWrite(USR_LED_ID, 0x1);
- m_ledState = 1;
-}
-void BAGpio::clearLed()
-{
- digitalWrite(USR_LED_ID, 0);
- m_ledState = 0;
-}
-int BAGpio::toggleLed()
-{
- m_ledState = ~m_ledState;
- digitalWrite(USR_LED_ID, m_ledState);
- return m_ledState;
-}
-
-
-} /* namespace BALibrary */
diff --git a/src/peripherals/BAPhysicalControls.cpp b/src/peripherals/BAPhysicalControls.cpp
deleted file mode 100644
index 5904455..0000000
--- a/src/peripherals/BAPhysicalControls.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * BAPhysicalControls.cpp
- *
- * This file provides a class for handling physical controls such as
- * switches, pots and rotary encoders.
- *
- * 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 "BAPhysicalControls.h"
-
-// 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");
- abort();
-}
-void __throw_length_error( char const*e ) {
- Serial.print("Length Error :"); Serial.println(e);
- abort();
-}
-}
-
-namespace BALibrary {
-
-BAPhysicalControls::BAPhysicalControls(unsigned numSwitches, unsigned numPots, unsigned numEncoders, unsigned numOutputs) {
- if (numSwitches > 0) {
- m_switches.reserve(numSwitches);
- }
- if (numPots > 0) {
- m_pots.reserve(numPots);
- }
- if (numEncoders > 0) {
- m_encoders.reserve(numEncoders);
- }
- if (numOutputs > 0) {
- m_outputs.reserve(numOutputs);
- }
-
-}
-
-unsigned BAPhysicalControls::addRotary(uint8_t pin1, uint8_t pin2, bool swapDirection, int divider) {
- m_encoders.emplace_back(pin1, pin2, swapDirection, divider);
- pinMode(pin1, INPUT);
- pinMode(pin2, INPUT);
- return m_encoders.size()-1;
-}
-
-unsigned BAPhysicalControls::addSwitch(uint8_t pin, unsigned long intervalMilliseconds) {
- //m_switches.emplace_back(pin, intervalMilliseconds);'
- m_switches.emplace_back();
- m_switches.back().attach(pin);
- m_switches.back().interval(10);
- pinMode(pin, INPUT);
- return m_switches.size()-1;
-}
-
-unsigned BAPhysicalControls::addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration) {
- m_pots.emplace_back(pin, minCalibration, maxCalibration);
- pinMode(pin, INPUT);
- return m_pots.size()-1;
-}
-
-unsigned BAPhysicalControls::addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection) {
- m_pots.emplace_back(pin, minCalibration, maxCalibration, swapDirection);
- pinMode(pin, INPUT);
- return m_pots.size()-1;
-}
-
-unsigned BAPhysicalControls::addOutput(uint8_t pin) {
- m_outputs.emplace_back(pin);
- pinMode(pin, OUTPUT);
- return m_outputs.size()-1;
-}
-
-void BAPhysicalControls::setOutput(unsigned handle, int val) {
- if (handle >= m_outputs.size()) { return; }
- m_outputs[handle].set(val);
-}
-
-void BAPhysicalControls::setOutput(unsigned handle, bool val) {
- if (handle >= m_outputs.size()) { return; }
- unsigned value = val ? 1 : 0;
- m_outputs[handle].set(value);
-}
-
-void BAPhysicalControls::toggleOutput(unsigned handle) {
- if (handle >= m_outputs.size()) { return; }
- m_outputs[handle].toggle();
-}
-
-
-int BAPhysicalControls::getRotaryAdjustUnit(unsigned handle) {
- if (handle >= m_encoders.size()) { return 0; } // handle is greater than number of encoders
-
- int encoderAdjust = m_encoders[handle].getChange();
- if (encoderAdjust != 0) {
- // clip the adjust to maximum abs value of 1.
- int encoderAdjust = (encoderAdjust > 0) ? 1 : -1;
- }
-
- return encoderAdjust;
-}
-
-bool BAPhysicalControls::checkPotValue(unsigned handle, float &value) {
- if (handle >= m_pots.size()) { return false;} // handle is greater than number of pots
- return m_pots[handle].getValue(value);
-}
-
-int BAPhysicalControls::getPotRawValue(unsigned handle)
-{
- if (handle >= m_pots.size()) { return false;} // handle is greater than number of pots
- return m_pots[handle].getRawValue();
-}
-
-bool BAPhysicalControls::setCalibrationValues(unsigned handle, unsigned min, unsigned max, bool swapDirection)
-{
- if (handle >= m_pots.size()) { return false;} // handle is greater than number of pots
- m_pots[handle].setCalibrationValues(min, max, swapDirection);
- return true;
-}
-
-bool BAPhysicalControls::isSwitchToggled(unsigned handle) {
- if (handle >= m_switches.size()) { return 0; } // handle is greater than number of switches
- DigitalInput &sw = m_switches[handle];
-
- return sw.hasInputToggled();
-}
-
-bool BAPhysicalControls::isSwitchHeld(unsigned handle)
-{
- if (handle >= m_switches.size()) { return 0; } // handle is greater than number of switches
- DigitalInput &sw = m_switches[handle];
-
- return sw.isInputAssert();
-}
-
-bool BAPhysicalControls::getSwitchValue(unsigned handle)
-{
- if (handle >= m_switches.size()) { return 0; } // handle is greater than number of switches
- DigitalInput &sw = m_switches[handle];
-
- return sw.read();
-}
-
-bool BAPhysicalControls::hasSwitchChanged(unsigned handle, bool &switchValue)
-{
- if (handle >= m_switches.size()) { return 0; } // handle is greater than number of switches
- DigitalInput &sw = m_switches[handle];
-
- return sw.hasInputChanged(switchValue);
-}
-
-///////////////////////////
-// DigitalInput
-///////////////////////////
-bool DigitalInput::hasInputToggled() {
-
- update();
- if (fell() && (m_isPolarityInverted == false)) {
- // switch fell and polarity is not inverted
- return true;
- } else if (rose() && (m_isPolarityInverted == true)) {
- // switch rose and polarity is inveretd
- return true;
- } else {
- return false;
- }
-}
-
-bool DigitalInput::isInputAssert()
-{
- update();
- // if polarity is inverted, return the opposite state
- bool retValue = Bounce::read() ^ m_isPolarityInverted;
- return retValue;
-}
-
-bool DigitalInput::getPinInputValue()
-{
- update();
- return Bounce::read();
-}
-
-bool DigitalInput::hasInputChanged(bool &switchState)
-{
- update();
- if (rose()) {
- // return true if not inverted
- switchState = m_isPolarityInverted ? false : true;
- return true;
- } else if (fell()) {
- // return false if not inverted
- switchState = m_isPolarityInverted ? true : false;
- return true;
- } else {
- // return current value
- switchState = Bounce::read() != m_isPolarityInverted;
- return false;
- }
-}
-
-///////////////////////////
-// DigitalOutput
-///////////////////////////
-void DigitalOutput::set(int val) {
- m_val = val;
- digitalWriteFast(m_pin, m_val);
-}
-
-void DigitalOutput::toggle(void) {
- m_val = !m_val;
- digitalWriteFast(m_pin, m_val);
-}
-
-///////////////////////////
-// Potentiometer
-///////////////////////////
-Potentiometer::Potentiometer(uint8_t analogPin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection)
- : m_pin(analogPin), m_swapDirection(swapDirection), m_minCalibration(minCalibration), m_maxCalibration(maxCalibration)
-{
- adjustCalibrationThreshold(m_thresholdFactor); // Calculate the thresholded values
-}
-
-
-void Potentiometer::setFeedbackFitlerValue(float fitlerValue)
-{
- m_feedbackFitlerValue = fitlerValue;
-}
-
-bool Potentiometer::getValue(float &value) {
-
- bool newValue = true;
-
- unsigned val = analogRead(m_pin); // read the raw value
-
- // constrain it within the calibration values, them map it to the desired range.
- val = constrain(val, m_minCalibration, m_maxCalibration);
-
- // Use an IIR filter to smooth out the noise in the pot readings
- unsigned valFilter = static_cast( (1.0f - m_feedbackFitlerValue)*val + (m_feedbackFitlerValue*m_lastValue));
-
- if (valFilter == m_lastValue) {
- newValue = false;
- }
- m_lastValue = valFilter;
-
- //
- if (valFilter < m_minCalibrationThresholded) { value = 0.0f; }
- else if (valFilter > m_maxCalibrationThresholded) { value = 1.0f; }
- else {
- value = static_cast(valFilter - m_minCalibrationThresholded) / static_cast(m_rangeThresholded);
- }
-
- if (m_swapDirection) {
- value = 1.0f - value;
- }
- return newValue;
-}
-
-int Potentiometer::getRawValue() {
- return analogRead(m_pin);
-}
-
-// Recalculate thresholded limits based on thresholdFactor
-void Potentiometer::adjustCalibrationThreshold(float thresholdFactor)
-{
- m_thresholdFactor = thresholdFactor;
- // the threshold is specificed as a fraction of the min/max range.
- unsigned threshold = static_cast((m_maxCalibration - m_minCalibration) * thresholdFactor);
-
- // Update the thresholded values
- m_minCalibrationThresholded = m_minCalibration + threshold;
- m_maxCalibrationThresholded = m_maxCalibration - threshold;
- m_rangeThresholded = m_maxCalibrationThresholded - m_minCalibrationThresholded;
-}
-
-void Potentiometer::setCalibrationValues(unsigned min, unsigned max, bool swapDirection)
-{
- m_minCalibration = min;
- m_maxCalibration = max;
- m_swapDirection = swapDirection;
- adjustCalibrationThreshold(m_thresholdFactor);
-}
-
-Potentiometer::Calib Potentiometer::calibrate(uint8_t pin) {
- Calib calib;
-
- Serial.print("Calibration pin "); Serial.println(pin);
- Serial.println("Move the pot fully counter-clockwise to the minimum setting and press any key then ENTER");
- while (true) {
- delay(100);
- if (Serial.available() > 0) {
- calib.min = analogRead(pin);
- while (Serial.available()) { Serial.read(); }
- break;
- }
- }
-
- Serial.println("Move the pot fully clockwise to the maximum setting and press any key then ENTER");
- while (true) {
- delay(100);
- if (Serial.available() > 0) {
- calib.max = analogRead(pin);
- while (Serial.available()) { Serial.read(); }
- break;
- }
- }
-
- if (calib.min > calib.max) {
- unsigned tmp = calib.max;
- calib.max = calib.min;
- calib.min = tmp;
- calib.swap = true;
- }
-
- Serial.print("The calibration for pin "); Serial.print(pin);
- Serial.print(" is min:"); Serial.print(calib.min);
- Serial.print(" max:"); Serial.print(calib.max);
- Serial.print(" swap: "); Serial.println(calib.swap);
-
- return calib;
-}
-
-
-int RotaryEncoder::getChange() {
- int32_t newPosition = read();
- int delta = newPosition - m_lastPosition;
- m_lastPosition = newPosition;
- if (m_swapDirection) { delta = -delta; }
- return delta/m_divider;
-}
-
-void RotaryEncoder::setDivider(int divider) {
- m_divider = divider;
-}
-
-} // BALibrary
-
-
-
-
diff --git a/src/peripherals/BASpiMemory.cpp b/src/peripherals/BASpiMemory.cpp
deleted file mode 100644
index a1fab91..0000000
--- a/src/peripherals/BASpiMemory.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * BASpiMemory.cpp
- *
- * Created on: May 22, 2017
- * 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 "Arduino.h"
-#include "BASpiMemory.h"
-
-namespace BALibrary {
-
-// MEM0 Settings
-constexpr int SPI_CS_MEM0 = 15;
-constexpr int SPI_MOSI_MEM0 = 7;
-constexpr int SPI_MISO_MEM0 = 8;
-constexpr int SPI_SCK_MEM0 = 14;
-
-// MEM1 Settings
-constexpr int SPI_CS_MEM1 = 31;
-constexpr int SPI_MOSI_MEM1 = 21;
-constexpr int SPI_MISO_MEM1 = 5;
-constexpr int SPI_SCK_MEM1 = 20;
-
-// SPI Constants
-constexpr int SPI_WRITE_MODE_REG = 0x1;
-constexpr int SPI_WRITE_CMD = 0x2;
-constexpr int SPI_READ_CMD = 0x3;
-constexpr int SPI_ADDR_2_MASK = 0xFF0000;
-constexpr int SPI_ADDR_2_SHIFT = 16;
-constexpr int SPI_ADDR_1_MASK = 0x00FF00;
-constexpr int SPI_ADDR_1_SHIFT = 8;
-constexpr int SPI_ADDR_0_MASK = 0x0000FF;
-
-constexpr int CMD_ADDRESS_SIZE = 4;
-constexpr int MAX_DMA_XFER_SIZE = 0x4000;
-
-BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId)
-{
- m_memDeviceId = memDeviceId;
- m_settings = {20000000, MSBFIRST, SPI_MODE0};
-}
-
-BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz)
-{
- m_memDeviceId = memDeviceId;
- m_settings = {speedHz, MSBFIRST, SPI_MODE0};
-}
-
-// Intitialize the correct Arduino SPI interface
-void BASpiMemory::begin()
-{
- switch (m_memDeviceId) {
- case SpiDeviceId::SPI_DEVICE0 :
- m_csPin = SPI_CS_MEM0;
- m_spi = &SPI;
- m_spi->setMOSI(SPI_MOSI_MEM0);
- m_spi->setMISO(SPI_MISO_MEM0);
- m_spi->setSCK(SPI_SCK_MEM0);
- m_spi->begin();
- break;
-
-#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
- case SpiDeviceId::SPI_DEVICE1 :
- m_csPin = SPI_CS_MEM1;
- m_spi = &SPI1;
- m_spi->setMOSI(SPI_MOSI_MEM1);
- m_spi->setMISO(SPI_MISO_MEM1);
- m_spi->setSCK(SPI_SCK_MEM1);
- m_spi->begin();
- break;
-#endif
-
- default :
- // unreachable since memDeviceId is an enumerated class
- return;
- }
-
- pinMode(m_csPin, OUTPUT);
- digitalWrite(m_csPin, HIGH);
- m_started = true;
-
-}
-
-BASpiMemory::~BASpiMemory() {
-}
-
-// Single address write
-void BASpiMemory::write(size_t address, uint8_t data)
-{
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer(SPI_WRITE_CMD);
- m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
- m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
- m_spi->transfer((address & SPI_ADDR_0_MASK));
- m_spi->transfer(data);
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-// Single address write
-void BASpiMemory::write(size_t address, uint8_t *src, size_t numBytes)
-{
- uint8_t *dataPtr = src;
-
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer(SPI_WRITE_CMD);
- m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
- m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
- m_spi->transfer((address & SPI_ADDR_0_MASK));
-
- for (size_t i=0; i < numBytes; i++) {
- m_spi->transfer(*dataPtr++);
- }
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-
-void BASpiMemory::zero(size_t address, size_t numBytes)
-{
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer(SPI_WRITE_CMD);
- m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
- m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
- m_spi->transfer((address & SPI_ADDR_0_MASK));
-
- for (size_t i=0; i < numBytes; i++) {
- m_spi->transfer(0);
- }
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-void BASpiMemory::write16(size_t address, uint16_t data)
-{
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) );
- m_spi->transfer16(address & 0xFFFF);
- m_spi->transfer16(data);
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-void BASpiMemory::write16(size_t address, uint16_t *src, size_t numWords)
-{
- uint16_t *dataPtr = src;
-
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) );
- m_spi->transfer16(address & 0xFFFF);
-
- for (size_t i=0; itransfer16(*dataPtr++);
- }
-
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-void BASpiMemory::zero16(size_t address, size_t numWords)
-{
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer16((SPI_WRITE_CMD << 8) | (address >> 16) );
- m_spi->transfer16(address & 0xFFFF);
-
- for (size_t i=0; itransfer16(0);
- }
-
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
- Serial.println("DONE!");
-}
-
-// single address read
-uint8_t BASpiMemory::read(size_t address)
-{
- int data;
-
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer(SPI_READ_CMD);
- m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
- m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
- m_spi->transfer((address & SPI_ADDR_0_MASK));
- data = m_spi->transfer(0);
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
- return data;
-}
-
-
-void BASpiMemory::read(size_t address, uint8_t *dest, size_t numBytes)
-{
- uint8_t *dataPtr = dest;
-
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer(SPI_READ_CMD);
- m_spi->transfer((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
- m_spi->transfer((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
- m_spi->transfer((address & SPI_ADDR_0_MASK));
-
- for (size_t i=0; itransfer(0);
- }
-
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-uint16_t BASpiMemory::read16(size_t address)
-{
-
- uint16_t data;
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer16((SPI_READ_CMD << 8) | (address >> 16) );
- m_spi->transfer16(address & 0xFFFF);
- data = m_spi->transfer16(0);
- m_spi->endTransaction();
-
- digitalWrite(m_csPin, HIGH);
- return data;
-}
-
-void BASpiMemory::read16(size_t address, uint16_t *dest, size_t numWords)
-{
-
- uint16_t *dataPtr = dest;
- m_spi->beginTransaction(m_settings);
- digitalWrite(m_csPin, LOW);
- m_spi->transfer16((SPI_READ_CMD << 8) | (address >> 16) );
- m_spi->transfer16(address & 0xFFFF);
-
- for (size_t i=0; itransfer16(0);
- }
-
- m_spi->endTransaction();
- digitalWrite(m_csPin, HIGH);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// BASpiMemoryDMA
-/////////////////////////////////////////////////////////////////////////////
-BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId)
-: BASpiMemory(memDeviceId)
-{
- int cs;
- switch (memDeviceId) {
- case SpiDeviceId::SPI_DEVICE0 :
- cs = SPI_CS_MEM0;
- m_cs = new ActiveLowChipSelect(cs, m_settings);
- break;
-#if defined(__MK66FX1M0__)
- case SpiDeviceId::SPI_DEVICE1 :
- cs = SPI_CS_MEM1;
- m_cs = new ActiveLowChipSelect1(cs, m_settings);
- break;
-#endif
- default :
- cs = SPI_CS_MEM0;
- }
-
- // add 4 bytes to buffer for SPI CMD and 3 bytes of address
- m_txCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
- m_rxCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
- m_txTransfer = new DmaSpi::Transfer[2];
- m_rxTransfer = new DmaSpi::Transfer[2];
-}
-
-BASpiMemoryDMA::BASpiMemoryDMA(SpiDeviceId memDeviceId, uint32_t speedHz)
-: BASpiMemory(memDeviceId, speedHz)
-{
- int cs;
- switch (memDeviceId) {
- case SpiDeviceId::SPI_DEVICE0 :
- cs = SPI_CS_MEM0;
- m_cs = new ActiveLowChipSelect(cs, m_settings);
- break;
-#if defined(__MK66FX1M0__)
- case SpiDeviceId::SPI_DEVICE1 :
- cs = SPI_CS_MEM1;
- m_cs = new ActiveLowChipSelect1(cs, m_settings);
- break;
-#endif
- default :
- cs = SPI_CS_MEM0;
- }
-
- m_txCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
- m_rxCommandBuffer = new uint8_t[CMD_ADDRESS_SIZE];
- m_txTransfer = new DmaSpi::Transfer[2];
- m_rxTransfer = new DmaSpi::Transfer[2];
-}
-
-BASpiMemoryDMA::~BASpiMemoryDMA()
-{
- delete m_cs;
- if (m_txTransfer) delete [] m_txTransfer;
- if (m_rxTransfer) delete [] m_rxTransfer;
- if (m_txCommandBuffer) delete [] m_txCommandBuffer;
- if (m_rxCommandBuffer) delete [] m_txCommandBuffer;
-}
-
-void BASpiMemoryDMA::m_setSpiCmdAddr(int command, size_t address, uint8_t *dest)
-{
- dest[0] = command;
- dest[1] = ((address & SPI_ADDR_2_MASK) >> SPI_ADDR_2_SHIFT);
- dest[2] = ((address & SPI_ADDR_1_MASK) >> SPI_ADDR_1_SHIFT);
- dest[3] = ((address & SPI_ADDR_0_MASK));
-}
-
-void BASpiMemoryDMA::begin(void)
-{
- switch (m_memDeviceId) {
- case SpiDeviceId::SPI_DEVICE0 :
- m_csPin = SPI_CS_MEM0;
- m_spi = &SPI;
- m_spi->setMOSI(SPI_MOSI_MEM0);
- m_spi->setMISO(SPI_MISO_MEM0);
- m_spi->setSCK(SPI_SCK_MEM0);
- m_spi->begin();
- //m_spiDma = &DMASPI0;
- m_spiDma = new DmaSpiGeneric();
- break;
-
-#if defined(__MK66FX1M0__) // DMA on SPI1 is only supported on T3.6
- case SpiDeviceId::SPI_DEVICE1 :
- m_csPin = SPI_CS_MEM1;
- m_spi = &SPI1;
- m_spi->setMOSI(SPI_MOSI_MEM1);
- m_spi->setMISO(SPI_MISO_MEM1);
- m_spi->setSCK(SPI_SCK_MEM1);
- m_spi->begin();
- m_spiDma = new DmaSpiGeneric(1);
- //m_spiDma = &DMASPI1;
- break;
-#endif
-
- default :
- // unreachable since memDeviceId is an enumerated class
- return;
- }
-
- m_spiDma->begin();
- m_spiDma->start();
-
- m_started = true;
-}
-
-
-
-// SPI must build up a payload that starts the teh CMD/Address first. It will cycle
-// through the payloads in a circular buffer and use the transfer objects to check if they
-// are done before continuing.
-void BASpiMemoryDMA::write(size_t address, uint8_t *src, size_t numBytes)
-{
- size_t bytesRemaining = numBytes;
- uint8_t *srcPtr = src;
- size_t nextAddress = address;
- while (bytesRemaining > 0) {
- m_txXferCount = min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE));
- while ( m_txTransfer[1].busy()) {} // wait until not busy
- m_setSpiCmdAddr(SPI_WRITE_CMD, nextAddress, m_txCommandBuffer);
- m_txTransfer[1] = DmaSpi::Transfer(m_txCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
- m_spiDma->registerTransfer(m_txTransfer[1]);
-
- while ( m_txTransfer[0].busy()) {} // wait until not busy
- m_txTransfer[0] = DmaSpi::Transfer(srcPtr, m_txXferCount, nullptr, 0, m_cs, TransferType::NO_START_CS);
- m_spiDma->registerTransfer(m_txTransfer[0]);
- bytesRemaining -= m_txXferCount;
- srcPtr += m_txXferCount;
- nextAddress += m_txXferCount;
- }
-}
-
-
-void BASpiMemoryDMA::zero(size_t address, size_t numBytes)
-{
- size_t bytesRemaining = numBytes;
- size_t nextAddress = address;
- while (bytesRemaining > 0) {
- m_txXferCount = min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE));
- while ( m_txTransfer[1].busy()) {} // wait until not busy
- m_setSpiCmdAddr(SPI_WRITE_CMD, nextAddress, m_txCommandBuffer);
- m_txTransfer[1] = DmaSpi::Transfer(m_txCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
- m_spiDma->registerTransfer(m_txTransfer[1]);
-
- while ( m_txTransfer[0].busy()) {} // wait until not busy
- m_txTransfer[0] = DmaSpi::Transfer(nullptr, m_txXferCount, nullptr, 0, m_cs, TransferType::NO_START_CS);
- m_spiDma->registerTransfer(m_txTransfer[0]);
- bytesRemaining -= m_txXferCount;
- nextAddress += m_txXferCount;
- }
-}
-
-
-void BASpiMemoryDMA::write16(size_t address, uint16_t *src, size_t numWords)
-{
- write(address, reinterpret_cast(src), sizeof(uint16_t)*numWords);
-}
-
-void BASpiMemoryDMA::zero16(size_t address, size_t numWords)
-{
- zero(address, sizeof(uint16_t)*numWords);
-}
-
-
-void BASpiMemoryDMA::read(size_t address, uint8_t *dest, size_t numBytes)
-{
- size_t bytesRemaining = numBytes;
- uint8_t *destPtr = dest;
- size_t nextAddress = address;
- while (bytesRemaining > 0) {
- m_setSpiCmdAddr(SPI_READ_CMD, nextAddress, m_rxCommandBuffer);
-
- while ( m_rxTransfer[1].busy()) {}
- m_rxTransfer[1] = DmaSpi::Transfer(m_rxCommandBuffer, CMD_ADDRESS_SIZE, nullptr, 0, m_cs, TransferType::NO_END_CS);
- m_spiDma->registerTransfer(m_rxTransfer[1]);
-
- m_rxXferCount = min(bytesRemaining, static_cast(MAX_DMA_XFER_SIZE));
- while ( m_rxTransfer[0].busy()) {}
- m_rxTransfer[0] = DmaSpi::Transfer(nullptr, m_rxXferCount, destPtr, 0, m_cs, TransferType::NO_START_CS);
- m_spiDma->registerTransfer(m_rxTransfer[0]);
-
- bytesRemaining -= m_rxXferCount;
- destPtr += m_rxXferCount;
- nextAddress += m_rxXferCount;
- }
-}
-
-
-void BASpiMemoryDMA::read16(size_t address, uint16_t *dest, size_t numWords)
-{
- read(address, reinterpret_cast(dest), sizeof(uint16_t)*numWords);
-}
-
-
-bool BASpiMemoryDMA::isWriteBusy(void) const
-{
- return (m_txTransfer[0].busy() or m_txTransfer[1].busy());
-}
-
-bool BASpiMemoryDMA::isReadBusy(void) const
-{
- return (m_rxTransfer[0].busy() or m_rxTransfer[1].busy());
-}
-
-} /* namespace BALibrary */
diff --git a/src/peripherals/DmaSpi.cpp b/src/peripherals/DmaSpi.cpp
deleted file mode 100644
index 2653f6f..0000000
--- a/src/peripherals/DmaSpi.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "DmaSpi.h"
-
-#if defined(KINETISK)
-DmaSpi0 DMASPI0;
-#if defined(__MK66FX1M0__)
-DmaSpi1 DMASPI1;
-//DmaSpi2 DMASPI2;
-#endif
-#elif defined (KINETISL)
-DmaSpi0 DMASPI0;
-DmaSpi1 DMASPI1;
-#else
-#endif // defined