Erased error messages and added some comments

This commit is contained in:
jvramallo 2019-02-04 19:46:48 +01:00
parent 354e636bb0
commit 1b88629942
3 changed files with 83 additions and 69 deletions

View file

@ -170,6 +170,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
pinPeripheral(_sdPin, PIO_COM);
#endif
/*
// Test what pins are being used
Serial.println("_sdPin: " + String(_sdPin));
Serial.println("_sckPin: " + String(_sckPin));
Serial.println("_fsPin: " + String(_fsPin));
@ -339,7 +340,7 @@ int I2SClass::availableForWrite()
return space;
}
/*/ ---
// New, just for testing, blocking read
void I2SClass::read(int32_t *left, int32_t *right)
{
if (_state != I2S_STATE_RECEIVER)
@ -347,13 +348,14 @@ void I2SClass::read(int32_t *left, int32_t *right)
i2sd.read(left, right);
}
// ---*/
//
int I2SClass::read(void* buffer, size_t size)
{
if (_state != I2S_STATE_RECEIVER) {
enableReceiver();
}
// Testing registers if they match AdafruitZeroI2S configuration
// i2sd.printRegisters();
// while(true);
@ -445,12 +447,12 @@ void I2SClass::onReceive(void(*function)(void))
_onReceive = function;
}
void I2SClass::enableClock(int divider)
void I2SClass::enableClock(int divider/*, int mck_mult*/)
{
#if defined(__SAMD51__)
// divider = sampleRate * numChannels * _bitsPerSample (44100 * 2 * 32)
uint32_t mckFreq = (divider / 2 / _bitsPerSample) * 256; // (fs_freq * mck_mult)
uint32_t mckFreq = (divider / 2 / _bitsPerSample) * 256; // (fs_freq * mck_mult), assumes 2 channels and mck_mult = 256
uint32_t sckFreq = divider; // (fs_freq * I2S_NUM_SLOTS * bitsPerSample)
uint32_t gclkval = GCLK_PCHCTRL_GEN_GCLK1_Val;
@ -465,11 +467,13 @@ void I2SClass::enableClock(int divider)
gclkFreq = 12000000; // 120Mhz
}
/*
Serial.println ("divider: " + String(divider));
Serial.println ("divider: " + String(divider));
Serial.println ("mckoutdiv: " + String(mckoutdiv));
Serial.println ("mckdiv: " + String(mckdiv));
Serial.println ("mckdiv: " + String(mckdiv));
*/
//while (GCLK->SYNCBUSY.reg);
// if this is not configured I2S won't work at all.
GCLK->PCHCTRL[I2S_GCLK_ID_0].reg = gclkval | GCLK_PCHCTRL_CHEN;
GCLK->PCHCTRL[I2S_GCLK_ID_1].reg = gclkval | GCLK_PCHCTRL_CHEN;
@ -480,54 +484,55 @@ Serial.println ("divider: " + String(divider));
#else // SAMD21
int div = SystemCoreClock / divider;
int src = GCLK_GENCTRL_SRC_DFLL48M_Val; // <--- ERROR SAMD51
int src = GCLK_GENCTRL_SRC_DFLL48M_Val;
if (div > 255) {
// divider is too big, use 8 MHz oscillator instead
div = 8000000 / divider;
src = GCLK_GENCTRL_SRC_OSC8M_Val; // <--- ERROR SAMD51
src = GCLK_GENCTRL_SRC_OSC8M_Val;
}
// configure the clock divider
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
GCLK->GENDIV.bit.ID = _clockGenerator; // <--- ERROR SAMD51
GCLK->GENDIV.bit.DIV = div; // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
GCLK->GENDIV.bit.ID = _clockGenerator;
GCLK->GENDIV.bit.DIV = div;
// use the DFLL as the source
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
GCLK->GENCTRL.bit.ID = _clockGenerator; // <--- ERROR SAMD51
GCLK->GENCTRL.bit.SRC = src; // <--- ERROR SAMD51
GCLK->GENCTRL.bit.IDC = 1; // <--- ERROR SAMD51
GCLK->GENCTRL.bit.GENEN = 1; // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
GCLK->GENCTRL.bit.ID = _clockGenerator;
GCLK->GENCTRL.bit.SRC = src;
GCLK->GENCTRL.bit.IDC = 1;
GCLK->GENCTRL.bit.GENEN = 1;
// enable
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
GCLK->CLKCTRL.bit.ID = i2sd.glckId(_deviceIndex); // <--- ERROR SAMD51
GCLK->CLKCTRL.bit.GEN = _clockGenerator; // <--- ERROR SAMD51
GCLK->CLKCTRL.bit.CLKEN = 1; // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
GCLK->CLKCTRL.bit.ID = i2sd.glckId(_deviceIndex);
GCLK->CLKCTRL.bit.GEN = _clockGenerator;
GCLK->CLKCTRL.bit.CLKEN = 1;
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
#endif
}
void I2SClass::disableClock()
{
#if defined(__SAMD51__)
// Need to be tested if works
//GCLK->PCHCTRL[I2S_GCLK_ID_0].reg = GCLK_PCHCTRL_RESETVALUE;
//GCLK->PCHCTRL[I2S_GCLK_ID_1].reg = GCLK_PCHCTRL_RESETVALUE;
#else // SAMD21
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
GCLK->GENCTRL.bit.ID = _clockGenerator; // <--- ERROR SAMD51
GCLK->GENCTRL.bit.SRC = GCLK_GENCTRL_SRC_DFLL48M_Val; // <--- ERROR SAMD51
GCLK->GENCTRL.bit.IDC = 1; // <--- ERROR SAMD51
GCLK->GENCTRL.bit.GENEN = 0; // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
GCLK->GENCTRL.bit.ID = _clockGenerator;
GCLK->GENCTRL.bit.SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
GCLK->GENCTRL.bit.IDC = 1;
GCLK->GENCTRL.bit.GENEN = 0;
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
GCLK->CLKCTRL.bit.ID = i2sd.glckId(_deviceIndex); // <--- ERROR SAMD51
GCLK->CLKCTRL.bit.GEN = _clockGenerator; // <--- ERROR SAMD51
GCLK->CLKCTRL.bit.CLKEN = 0; // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
GCLK->CLKCTRL.bit.ID = i2sd.glckId(_deviceIndex);
GCLK->CLKCTRL.bit.GEN = _clockGenerator;
GCLK->CLKCTRL.bit.CLKEN = 0;
while (GCLK->STATUS.bit.SYNCBUSY); // <--- ERROR SAMD51
while (GCLK->STATUS.bit.SYNCBUSY);
#endif
}
@ -628,7 +633,8 @@ void I2SClass::onDmaTransferComplete(int channel)
#if defined(__SAMD51__)
// If you want to use this class as output on SAMD51, you can redefine this on arduino's setup function as:
// I2S = I2SClass(I2S_DEVICE, I2S_CLOCK_GENERATOR, PIN_I2S_SDO, PIN_I2S_SCK, PIN_I2S_FS);
#if I2S_INTERFACES_COUNT > 0
I2SClass I2S(I2S_DEVICE, I2S_CLOCK_GENERATOR, PIN_I2S_SDI, PIN_I2S_SCK, PIN_I2S_FS);
#endif

View file

@ -53,7 +53,7 @@ public:
virtual int availableForWrite();
//void read(int32_t *left, int32_t *right);
void read(int32_t *left, int32_t *right); // this function is NOT available on Standard Arduino's I2S API, just for testing
int read(void* buffer, size_t size);
size_t write(int);

View file

@ -20,8 +20,6 @@
#include <Arduino.h>
//void printRegisters ();
class I2SDevice_SAMD51 {
public:
@ -50,7 +48,7 @@ public:
inline int glckId(int index) {
return (index == 0) ? I2S_GCLK_ID_0 : I2S_GCLK_ID_1;
}
// New for SAMD51, taken from Adafrui Zero I2S Library ----
// --- New for SAMD51, taken from Adafrui Zero I2S Library ----
inline void setMasterClockOutputDivisionFactor(int index, uint8_t mckoutdiv) {
// printRegisters();
// Serial.println ("index: " + String(index));
@ -75,29 +73,30 @@ public:
i2s.CLKCTRL[index].reg |= I2S_CLKCTRL_FSWIDTH(fswidth);
}
inline void setTxMode(int index, int bitsPersample) {
//while(i2s.SYNCBUSY.reg); // wait for sync
// added bitsPerSample parameter
inline void setTxMode(int index, int bitsPerSample) {
// Previously used here:
//i2s.RXCTRL.bit.SERMODE = 0x01;
//i2s.TXCTRL.reg &= ~(0x03); //TODO: why is this not in CMSIS...
//i2s.TXCTRL.reg &= ~(0x03); //TODO: why is this not in CMSIS... <- I think Atmel's datasheet has an errata, it has no sense to set this serializer as RX
//i2s.TXCTRL.reg |= 0x01;
uint8_t wordSize = 0;
switch (bitsPersample)
{
case 8:
wordSize = I2S_TXCTRL_DATASIZE_8_Val;
break;
case 16:
wordSize = I2S_TXCTRL_DATASIZE_16_Val;
break;
case 24:
wordSize = I2S_TXCTRL_DATASIZE_24_Val;
break;
case 32:
wordSize = I2S_TXCTRL_DATASIZE_32_Val;
break;
}
switch (bitsPerSample)
{
case 8:
wordSize = I2S_TXCTRL_DATASIZE_8_Val;
break;
case 16:
wordSize = I2S_TXCTRL_DATASIZE_16_Val;
break;
case 24:
wordSize = I2S_TXCTRL_DATASIZE_24_Val;
break;
case 32:
wordSize = I2S_TXCTRL_DATASIZE_32_Val;
break;
}
i2s.TXCTRL.reg &= I2S_TXCTRL_RESETVALUE;
i2s.TXCTRL.reg = I2S_TXCTRL_DMA_SINGLE |
@ -112,15 +111,16 @@ public:
// printRegisters();
// while(true);
}
// added bitsPerSample parameter
inline void setRxMode(int index, int bitsPerSample) {
inline void setRxMode(int index, int bitsPersample) {
//i2s.RXCTRL.bit.SERMODE = 0x00;
//i2s.TXCTRL.reg &= ~(0x03); //TODO: why is this not in CMSIS...
//i2s.TXCTRL.reg |= 0x00;
//i2s.RXCTRL.bit.SERMODE = 0x00;
//i2s.TXCTRL.reg &= ~(0x03); //TODO: why is this not in CMSIS...
//i2s.TXCTRL.reg |= 0x00;
uint8_t wordSize = 0;
switch (bitsPersample)
switch (bitsPerSample)
{
case 8:
wordSize = I2S_RXCTRL_DATASIZE_8_Val;
@ -136,20 +136,23 @@ public:
break;
}
//while(i2s.SYNCBUSY.reg); // wait for sync
i2s.RXCTRL.reg &= I2S_RXCTRL_RESETVALUE;
i2s.RXCTRL.reg = I2S_RXCTRL_DMA_SINGLE | //I2S_RXCTRL_DMA_MULTIPLE | <- CASCA
i2s.RXCTRL.reg = I2S_RXCTRL_DMA_SINGLE | //I2S_RXCTRL_DMA_MULTIPLE | <- IT HANGS
I2S_RXCTRL_MONO_STEREO |
I2S_RXCTRL_BITREV_MSBIT |
I2S_RXCTRL_EXTEND_ZERO |
I2S_RXCTRL_EXTEND_ZERO | // ZERO fills with ONEs and ONE fills with ZEROs, CMSIS errata?
I2S_RXCTRL_WORDADJ_RIGHT |
I2S_RXCTRL_DATASIZE(wordSize) |
I2S_RXCTRL_SLOTADJ_RIGHT |
I2S_RXCTRL_CLKSEL_CLK0 |
I2S_RXCTRL_SERMODE_RX;
// printRegisters();
// while(true);
}
// end new-----
// -----
inline void setSerialClockSelectMasterClockDiv(int index) {
i2s.CLKCTRL[index].bit.SCKSEL = I2S_CLKCTRL_SCKSEL_MCKDIV_Val;
}
@ -268,16 +271,19 @@ public:
}
}
// this should be explitted or filtered with "bool txrx"
inline void enableSerializer(int index) {
i2s.CTRLA.bit.RXEN = 1;
i2s.CTRLA.bit.TXEN = 1;
}
// this should be explitted or filtered with "bool txrx"
inline void disableSerializer(int index) {
i2s.CTRLA.bit.RXEN = 0;
i2s.CTRLA.bit.TXEN = 0;
i2s.CTRLA.bit.TXEN = 0;
}
// this is also new, dmaTriggerSource also depends on serializer furthermore clock source index
// rx = 0, tx = 1
inline int dmaTriggerSource(int index, bool txrx = 0) {
if (txrx) {
@ -317,7 +323,7 @@ public:
inline int rxReady(int index) {
return (index == 0) ? i2s.INTFLAG.bit.RXRDY0 :i2s.INTFLAG.bit.RXRDY1;
}
// ---
// for blocking read ---
inline void read(int32_t *left, int32_t *right) {
// printRegisters ();
while( (!i2s.INTFLAG.bit.RXRDY0) || i2s.SYNCBUSY.bit.RXDATA );
@ -355,8 +361,10 @@ public:
return (void*)&i2s.RXDATA.reg;
}
// BOOOM, This is my arduino's embeded debugger xD
inline void printRegisters()
{
{
// MCLK_APBAMASK
Serial.println ("SAMD51_MCLK Main Clock (APBA Mask)");
Serial.println ("(32-bit) MCLK->APBAMASK: 0x" + String(MCLK->APBAMASK.reg, HEX) + "\t, 0b" + String(MCLK->APBAMASK.reg, BIN));