2121#include < Arduino.h>
2222#include " I2S.h"
2323#include " pio_i2s.pio.h"
24+ #include < pico/stdlib.h>
2425
2526
2627I2S::I2S (PinMode direction) {
@@ -30,6 +31,8 @@ I2S::I2S(PinMode direction) {
3031 _isOutput = direction == OUTPUT;
3132 _pinBCLK = 26 ;
3233 _pinDOUT = 28 ;
34+ _pinMCLK = 25 ;
35+ _MCLKenabled = false ;
3336#ifdef PIN_I2S_BCLK
3437 _pinBCLK = PIN_I2S_BCLK;
3538#endif
@@ -53,6 +56,7 @@ I2S::I2S(PinMode direction) {
5356 _silenceSample = 0 ;
5457 _isLSBJ = false ;
5558 _swapClocks = false ;
59+ _multMCLK = 256 ;
5660}
5761
5862I2S::~I2S () {
@@ -67,6 +71,14 @@ bool I2S::setBCLK(pin_size_t pin) {
6771 return true ;
6872}
6973
74+
75+ bool I2S::setMCLK (pin_size_t pin) {
76+ if (_running || (pin > 28 )) {
77+ return false ;
78+ }
79+ _pinMCLK = pin;
80+ return true ;
81+ }
7082bool I2S::setDATA (pin_size_t pin) {
7183 if (_running || (pin > 29 )) {
7284 return false ;
@@ -96,12 +108,41 @@ bool I2S::setBuffers(size_t buffers, size_t bufferWords, int32_t silenceSample)
96108bool I2S::setFrequency (int newFreq) {
97109 _freq = newFreq;
98110 if (_running) {
99- float bitClk = _freq * _bps * 2.0 /* channels */ * 2.0 /* edges per clock */ ;
100- pio_sm_set_clkdiv (_pio, _sm, (float )clock_get_hz (clk_sys) / bitClk);
111+ if (_MCLKenabled) {
112+ int bitClk = _freq * _bps * 2.0 /* channels */ * 2.0 /* edges per clock */ ;
113+ pio_sm_set_clkdiv_int_frac (_pio, _sm, clock_get_hz (clk_sys) / bitClk, 0 );
114+ } else {
115+ float bitClk = _freq * _bps * 2.0 /* channels */ * 2.0 /* edges per clock */ ;
116+ pio_sm_set_clkdiv (_pio, _sm, (float )clock_get_hz (clk_sys) / bitClk);
117+ }
101118 }
102119 return true ;
103120}
104121
122+ bool I2S::setSysClk (int samplerate) { // optimise sys_clk for desired samplerate
123+ if (samplerate % 11025 == 0 ) {
124+ set_sys_clock_khz (I2SSYSCLK_44_1, false ); // 147.6 unsuccessful - no I2S no USB
125+ return true ;
126+ }
127+ if (samplerate % 8000 == 0 ) {
128+ set_sys_clock_khz (I2SSYSCLK_8, false );
129+ return true ;
130+ }
131+ return false ;
132+ }
133+
134+ bool I2S::setMCLKmult (int mult) {
135+ if (_running || !_isOutput) {
136+ return false ;
137+ }
138+ if ((mult % 64 ) == 0 ) {
139+ _MCLKenabled = true ;
140+ _multMCLK = mult;
141+ return true ;
142+ }
143+ return false ;
144+ }
145+
105146bool I2S::setLSBJFormat () {
106147 if (_running || !_isOutput) {
107148 return false ;
@@ -136,6 +177,16 @@ void I2S::onReceive(void(*fn)(void)) {
136177 }
137178}
138179
180+ void I2S::MCLKbegin () {
181+ int off = 0 ;
182+ _i2sMCLK = new PIOProgram (&pio_i2s_mclk_program);
183+ _i2sMCLK->prepare (&_pioMCLK, &_smMCLK, &off); // not sure how to use the same PIO
184+ pio_i2s_MCLK_program_init (_pioMCLK, _smMCLK, off, _pinMCLK);
185+ int mClk = _multMCLK * _freq * 2.0 /* edges per clock */ ;
186+ pio_sm_set_clkdiv_int_frac (_pioMCLK, _smMCLK, clock_get_hz (clk_sys) / mClk , 0 );
187+ pio_sm_set_enabled (_pioMCLK, _smMCLK, true );
188+ }
189+
139190bool I2S::begin () {
140191 _running = true ;
141192 _hasPeeked = false ;
@@ -162,6 +213,9 @@ bool I2S::begin() {
162213 pio_i2s_in_program_init (_pio, _sm, off, _pinDOUT, _pinBCLK, _bps, _swapClocks);
163214 }
164215 setFrequency (_freq);
216+ if (_MCLKenabled) {
217+ MCLKbegin ();
218+ }
165219 if (_bps == 8 ) {
166220 uint8_t a = _silenceSample & 0xff ;
167221 _silenceSample = (a << 24 ) | (a << 16 ) | (a << 8 ) | a;
@@ -189,6 +243,11 @@ bool I2S::begin() {
189243
190244void I2S::end () {
191245 if (_running) {
246+ if (_MCLKenabled) {
247+ pio_sm_set_enabled (_pioMCLK, _smMCLK, false );
248+ delete _i2sMCLK;
249+ _i2sMCLK = nullptr ;
250+ }
192251 pio_sm_set_enabled (_pio, _sm, false );
193252 _running = false ;
194253 delete _arb;
@@ -204,8 +263,13 @@ int I2S::available() {
204263 } else {
205264 auto avail = _arb->available ();
206265 avail *= 4 ; // 4 samples per 32-bits
207- if (_bps < 24 && !_isOutput) {
208- avail += _isHolding / 8 ;
266+ if (_bps < 24 ) {
267+ if (_isOutput) {
268+ // 16- and 8-bit can have holding bytes available
269+ avail += (32 - _isHolding) / 8 ;
270+ } else {
271+ avail += _isHolding / 8 ;
272+ }
209273 }
210274 return avail;
211275 }
0 commit comments