diff --git a/libraries/I2S/src/I2S.cpp b/libraries/I2S/src/I2S.cpp index a62bc5114..5c165ce73 100644 --- a/libraries/I2S/src/I2S.cpp +++ b/libraries/I2S/src/I2S.cpp @@ -28,12 +28,14 @@ static I2SDevice_SAMD21G18x i2sd(*I2S); int I2SClass::_beginCount = 0; -I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, uint8_t sckPin, uint8_t fsPin) : +I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, uint8_t sckPin, uint8_t fsPin, uint8_t mckPin) : _deviceIndex(deviceIndex), _clockGenerator(clockGenerator), _sdPin(sdPin), _sckPin(sckPin), _fsPin(fsPin), + _mckPin(mckPin), + _mckFsMultiplier(0), _state(I2S_STATE_IDLE), _dmaChannel(-1), @@ -108,7 +110,16 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc if (driveClock) { // set up clock - enableClock(sampleRate * 2 * bitsPerSample); + int F_BCKL = sampleRate * 2 * bitsPerSample; // LRCLOCK + int F_MCKL = _mckFsMultiplier * sampleRate; // SYSCLK + + enableClock(_mckFsMultiplier ? F_MCKL : F_BCKL); + + if (_mckFsMultiplier) { + i2sd.enableMasterClock(_deviceIndex); + i2sd.setMasterClockDiv(_deviceIndex, F_MCKL / F_BCKL - 1); + pinPeripheral(_mckPin, PIO_COM); + } i2sd.setSerialClockSelectMasterClockDiv(_deviceIndex); i2sd.setFrameSyncSelectSerialClockDiv(_deviceIndex); @@ -168,6 +179,11 @@ void I2SClass::end() pinMode(_fsPin, INPUT); pinMode(_sckPin, INPUT); + if (_mckFsMultiplier) { + pinMode(_mckPin, INPUT); + _mckFsMultiplier = 0; + } + disableClock(); _beginCount--; @@ -401,9 +417,25 @@ void I2SClass::setBufferSize(int bufferSize) _doubleBuffer.setSize(bufferSize); } +void I2SClass::enableMasterClock(int mckFsMultiplier) +{ + switch (mckFsMultiplier) { + case 128: + case 192: + case 256: + case 384: + case 512: + _mckFsMultiplier = mckFsMultiplier; + return; + + default: + _mckFsMultiplier = 256; + } +} + void I2SClass::enableClock(int divider) { - int div = SystemCoreClock / divider; + int div = (float)SystemCoreClock / divider + 0.5f; int src = GCLK_GENCTRL_SRC_DFLL48M_Val; if (div > 255) { @@ -529,5 +561,5 @@ void I2SClass::onDmaTransferComplete(int channel) } #if I2S_INTERFACES_COUNT > 0 -I2SClass I2S(I2S_DEVICE, I2S_CLOCK_GENERATOR, PIN_I2S_SD, PIN_I2S_SCK, PIN_I2S_FS); +I2SClass I2S(I2S_DEVICE, I2S_CLOCK_GENERATOR, PIN_I2S_SD, PIN_I2S_SCK, PIN_I2S_FS, PIN_I2S_MCK); #endif diff --git a/libraries/I2S/src/I2S.h b/libraries/I2S/src/I2S.h index 7f78b7191..9e0f28103 100644 --- a/libraries/I2S/src/I2S.h +++ b/libraries/I2S/src/I2S.h @@ -24,6 +24,7 @@ #include "utility/I2SDoubleBuffer.h" #define I2S_HAS_SET_BUFFER_SIZE 1 +#define PIN_I2S_MCK PIN_WIRE_SCL //I2S_MCK[0] typedef enum { I2S_PHILIPS_MODE, @@ -35,11 +36,11 @@ class I2SClass : public Stream { public: // the device index and pins must map to the "COM" pads in Table 6-1 of the datasheet - I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, uint8_t sckPin, uint8_t fsPin); + I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, uint8_t sckPin, uint8_t fsPin, uint8_t mckPin); // the SCK and FS pins are driven as outputs using the sample rate int begin(int mode, long sampleRate, int bitsPerSample); - // the SCK and FS pins are inputs, other side controls sample rate + // the SCK and FS pins are inputs, other side controls the sample rate int begin(int mode, int bitsPerSample); void end(); @@ -65,6 +66,7 @@ class I2SClass : public Stream void onReceive(void(*)(void)); void setBufferSize(int bufferSize); + void enableMasterClock(int _mckFsMultiplier = 256); private: int begin(int mode, long sampleRate, int bitsPerSample, bool driveClock); @@ -94,6 +96,9 @@ class I2SClass : public Stream uint8_t _sckPin; uint8_t _fsPin; + uint8_t _mckPin; + int _mckFsMultiplier; + i2s_state_t _state; int _dmaChannel; int _bitsPerSample; diff --git a/libraries/I2S/src/utility/SAMD21_I2SDevice.h b/libraries/I2S/src/utility/SAMD21_I2SDevice.h index 261583921..25bac43e8 100644 --- a/libraries/I2S/src/utility/SAMD21_I2SDevice.h +++ b/libraries/I2S/src/utility/SAMD21_I2SDevice.h @@ -47,6 +47,14 @@ class I2SDevice_SAMD21G18x { return (index == 0) ? I2S_GCLK_ID_0 : I2S_GCLK_ID_1; } + inline void setMasterClockDiv(int index, int div) { + i2s.CLKCTRL[index].bit.MCKDIV = div; + } + + inline void enableMasterClock(int index) { + i2s.CLKCTRL[index].bit.MCKEN = 1; + } + inline void setSerialClockSelectMasterClockDiv(int index) { i2s.CLKCTRL[index].bit.SCKSEL = I2S_CLKCTRL_SCKSEL_MCKDIV_Val; }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: