diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 4d92db61..4155a4e1 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -29,8 +29,8 @@ sphinx: # fail_on_warning: true # Optionally build your docs in additional formats such as PDF and ePub -# formats: -# - pdf + formats: + - pdf # - epub # Optional but recommended, declare the Python requirements required diff --git a/cores/rp2040/AudioOutputBase.h b/cores/rp2040/AudioOutputBase.h new file mode 100644 index 00000000..a7250aca --- /dev/null +++ b/cores/rp2040/AudioOutputBase.h @@ -0,0 +1,21 @@ +// Abstract class for audio output devices to allow easy swapping between output devices + +#pragma once + +#include + +class AudioOutputBase : public Print { +public: + virtual ~AudioOutputBase() { } + virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) = 0; + virtual bool setBitsPerSample(int bps) = 0; + virtual bool setFrequency(int freq) = 0; + virtual bool setStereo(bool stereo = true) = 0; + virtual bool begin() = 0; + virtual bool end() = 0; + virtual bool getUnderflow() = 0; + virtual void onTransmit(void(*)(void *), void *) = 0; + // From Print + virtual size_t write(const uint8_t *buffer, size_t size) = 0; + virtual int availableForWrite() = 0; +}; diff --git a/libraries/AudioBufferManager/src/AudioBufferManager.h b/libraries/AudioBufferManager/src/AudioBufferManager.h index f90d62ff..a98c4270 100644 --- a/libraries/AudioBufferManager/src/AudioBufferManager.h +++ b/libraries/AudioBufferManager/src/AudioBufferManager.h @@ -87,7 +87,6 @@ class AudioBufferManager { delete ab; } - int _bitsPerSample; size_t _wordsPerBuffer; size_t _bufferCount; enum dma_channel_transfer_size _dmaSize; diff --git a/libraries/BluetoothAudio/src/A2DPSource.cpp b/libraries/BluetoothAudio/src/A2DPSource.cpp index 884eaa02..7f6dcf45 100644 --- a/libraries/BluetoothAudio/src/A2DPSource.cpp +++ b/libraries/BluetoothAudio/src/A2DPSource.cpp @@ -220,6 +220,8 @@ void A2DPSource::clearPairing() { size_t A2DPSource::write(const uint8_t *buffer, size_t size) { BluetoothLock b; + size = std::min((size_t)availableForWrite(), size); + size_t count = 0; size /= 2; @@ -260,6 +262,7 @@ int A2DPSource::availableForWrite() { } else { avail = _pcmBufferSize - _pcmWriter + _pcmReader - 1; } + avail /= sizeof(uint32_t); // availableForWrite always 32b sample pairs in this core... return avail; } diff --git a/libraries/BluetoothAudio/src/A2DPSource.h b/libraries/BluetoothAudio/src/A2DPSource.h index 07018c8e..0c5293c8 100644 --- a/libraries/BluetoothAudio/src/A2DPSource.h +++ b/libraries/BluetoothAudio/src/A2DPSource.h @@ -24,17 +24,20 @@ #include #include #include "BluetoothMediaConfigurationSBC.h" +#include #include #include #include -class A2DPSource : public Stream { +class A2DPSource : public Stream, public AudioOutputBase { public: A2DPSource() { } - bool setFrequency(uint32_t rate) { + virtual ~A2DPSource() { } + + virtual bool setFrequency(int rate) override { if (_running || ((rate != 44100) && (rate != 48000))) { return false; } @@ -51,7 +54,14 @@ class A2DPSource : public Stream { return true; } - void onTransmit(void (*cb)(void *), void *cbData = nullptr) { + virtual bool setBitsPerSample(int bps) override { + return bps == 16; + } + virtual bool setStereo(bool stereo = true) override { + return stereo; + } + + virtual void onTransmit(void (*cb)(void *), void *cbData = nullptr) override { _transmitCB = cb; _transmitData = cbData; } @@ -84,7 +94,11 @@ class A2DPSource : public Stream { return true; } - bool getUnderflow() { + virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override { + return setBufferSize(buffers * bufferWords * sizeof(int32_t)); + } + + virtual bool getUnderflow() override { BluetoothLock b; if (!_running) { return false; @@ -102,7 +116,10 @@ class A2DPSource : public Stream { } } - bool begin(); + virtual bool begin() override; + virtual bool end() override { + return false; // We can't actually stop bluetooth on this device + } std::vector scan(uint32_t mask = BluetoothHCI::speaker_cod, int scanTimeSec = 5, bool async = false) { return _hci.scan(mask, scanTimeSec, async); diff --git a/libraries/I2S/examples/SimpleTone/SimpleTone.ino b/libraries/I2S/examples/SimpleTone/SimpleTone.ino index f5d686cb..ed66ea65 100644 --- a/libraries/I2S/examples/SimpleTone/SimpleTone.ino +++ b/libraries/I2S/examples/SimpleTone/SimpleTone.ino @@ -19,14 +19,14 @@ #include -// Create the I2S port using a PIO state machine -I2S i2s(OUTPUT); - // GPIO pin numbers #define pBCLK 20 #define pWS (pBCLK+1) #define pDOUT 22 +// Create the I2S port using a PIO state machine +I2S i2s(OUTPUT, pBCLK, pDOUT); + const int frequency = 440; // frequency of square wave in Hz const int amplitude = 500; // amplitude of square wave const int sampleRate = 16000; // minimum for UDA1334A @@ -43,8 +43,6 @@ void setup() { Serial.begin(115200); Serial.println("I2S simple tone"); - i2s.setBCLK(pBCLK); - i2s.setDATA(pDOUT); i2s.setBitsPerSample(16); // start I2S at the sample rate with 16-bits per sample diff --git a/libraries/I2S/src/I2S.cpp b/libraries/I2S/src/I2S.cpp index 612775c5..d3387c3c 100644 --- a/libraries/I2S/src/I2S.cpp +++ b/libraries/I2S/src/I2S.cpp @@ -24,14 +24,14 @@ #include -I2S::I2S(PinMode direction) { +I2S::I2S(PinMode direction, pin_size_t bclk, pin_size_t data, pin_size_t mclk) { _running = false; _bps = 16; _writtenHalf = false; _isOutput = direction == OUTPUT; - _pinBCLK = 26; - _pinDOUT = 28; - _pinMCLK = 25; + _pinBCLK = bclk; + _pinDOUT = data; + _pinMCLK = mclk; _MCLKenabled = false; #ifdef PIN_I2S_BCLK _pinBCLK = PIN_I2S_BCLK; @@ -287,7 +287,7 @@ bool I2S::begin() { return true; } -void I2S::end() { +bool I2S::end() { if (_running) { if (_MCLKenabled) { pio_sm_set_enabled(_pioMCLK, _smMCLK, false); @@ -301,6 +301,7 @@ void I2S::end() { delete _i2s; _i2s = nullptr; } + return true; } int I2S::available() { diff --git a/libraries/I2S/src/I2S.h b/libraries/I2S/src/I2S.h index 3b4e613e..dfb62f97 100644 --- a/libraries/I2S/src/I2S.h +++ b/libraries/I2S/src/I2S.h @@ -21,19 +21,23 @@ #pragma once #include -#include "AudioBufferManager.h" +#include +#include -class I2S : public Stream { +class I2S : public Stream, public AudioOutputBase { public: - I2S(PinMode direction = OUTPUT); + I2S(PinMode direction = OUTPUT, pin_size_t bclk = 26, pin_size_t data = 28, pin_size_t mclk = 25); virtual ~I2S(); bool setBCLK(pin_size_t pin); bool setDATA(pin_size_t pin); bool setMCLK(pin_size_t pin); - bool setBitsPerSample(int bps); - bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0); - bool setFrequency(int newFreq); + virtual bool setBitsPerSample(int bps) override; + virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override; + virtual bool setFrequency(int newFreq) override; + virtual bool setStereo(bool stereo = true) override { + return stereo; + } bool setLSBJFormat(); bool setTDMFormat(); bool setTDMChannels(int channels); @@ -46,8 +50,11 @@ class I2S : public Stream { return begin(); } - bool begin(); - void end(); + virtual bool begin() override; + virtual bool end() override; + virtual bool getUnderflow() override { + return getOverUnderflow(); + } // from Stream virtual int available() override; diff --git a/libraries/PWMAudio/src/PWMAudio.cpp b/libraries/PWMAudio/src/PWMAudio.cpp index b0886b3c..e435b166 100644 --- a/libraries/PWMAudio/src/PWMAudio.cpp +++ b/libraries/PWMAudio/src/PWMAudio.cpp @@ -40,7 +40,8 @@ PWMAudio::~PWMAudio() { end(); } -bool PWMAudio::setBuffers(size_t buffers, size_t bufferWords) { +bool PWMAudio::setBuffers(size_t buffers, size_t bufferWords, int32_t silence) { + (void) silence; if (_running || (buffers < 3) || (bufferWords < 8)) { return false; } @@ -176,7 +177,7 @@ bool PWMAudio::begin() { return true; } -void PWMAudio::end() { +bool PWMAudio::end() { if (_running) { _running = false; pinMode(_pin, OUTPUT); @@ -189,6 +190,7 @@ void PWMAudio::end() { dma_timer_unclaim(_pacer); _pacer = -1; } + return true; } int PWMAudio::available() { diff --git a/libraries/PWMAudio/src/PWMAudio.h b/libraries/PWMAudio/src/PWMAudio.h index 8c5e35f3..98dfcf34 100644 --- a/libraries/PWMAudio/src/PWMAudio.h +++ b/libraries/PWMAudio/src/PWMAudio.h @@ -21,20 +21,24 @@ #pragma once #include -#include "AudioBufferManager.h" +#include +#include -class PWMAudio : public Stream { +class PWMAudio : public Stream, public AudioOutputBase { public: PWMAudio(pin_size_t pin = 0, bool stereo = false); virtual ~PWMAudio(); - bool setBuffers(size_t buffers, size_t bufferWords); + virtual bool setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample = 0) override; /*Sets the frequency of the PWM in hz*/ bool setPWMFrequency(int newFreq); /*Sets the sample rate frequency in hz*/ - bool setFrequency(int frequency); + virtual bool setFrequency(int frequency) override; bool setPin(pin_size_t pin); - bool setStereo(bool stereo = true); + virtual bool setStereo(bool stereo = true) override; + virtual bool setBitsPerSample(int bits) override { + return bits == 16; + } bool begin(long sampleRate) { _sampleRate = sampleRate; @@ -47,8 +51,8 @@ class PWMAudio : public Stream { return begin(); } - bool begin(); - void end(); + virtual bool begin() override; + virtual bool end() override; // from Stream virtual int available() override;