Skip to content

Commit 46d9f8f

Browse files
committed
initial receiver mode support
1 parent d049e1d commit 46d9f8f

File tree

3 files changed

+110
-14
lines changed

3 files changed

+110
-14
lines changed

libraries/I2S/src/I2S.cpp

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, u
3535
_sckPin(sckPin),
3636
_fsPin(fsPin),
3737

38+
_state(I2S_STATE_IDLE),
3839
_dmaChannel(-1),
40+
_bitsPerSample(0),
3941
_dmaTransferInProgress(false),
4042

4143
_onTransmit(NULL)
@@ -44,6 +46,10 @@ I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, u
4446

4547
int I2SClass::begin(int mode, long sampleRate, int bitsPerSample)
4648
{
49+
if (_state != I2S_STATE_IDLE) {
50+
return 1;
51+
}
52+
4753
switch (mode) {
4854
case I2S_PHILIPS_MODE:
4955
break;
@@ -56,6 +62,7 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample)
5662
case 8:
5763
case 16:
5864
case 32:
65+
_bitsPerSample = bitsPerSample;
5966
break;
6067

6168
default:
@@ -92,18 +99,10 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample)
9299

93100
i2sd.setSlotAdjustedLeft(_deviceIndex);
94101
i2sd.setClockUnit(_deviceIndex);
95-
i2sd.setTxMode(_deviceIndex);
96102

97103
pinPeripheral(_sdPin, PIO_COM);
98104

99105
i2sd.enable();
100-
i2sd.enableClockUnit(_deviceIndex);
101-
i2sd.enableSerializer(_deviceIndex);
102-
103-
DMA.incSrc(_dmaChannel);
104-
DMA.onTransferComplete(_dmaChannel, I2SClass::onDmaTransferComplete);
105-
DMA.setTriggerSource(_dmaChannel, i2sd.dmaTriggerSource(_deviceIndex));
106-
DMA.setTransferWidth(_dmaChannel, bitsPerSample);
107106

108107
_doubleBuffer.reset();
109108

@@ -116,6 +115,7 @@ void I2SClass::end()
116115
DMA.freeChannel(_dmaChannel);
117116
}
118117

118+
_state = I2S_STATE_IDLE;
119119
_dmaTransferInProgress = false;
120120

121121
i2sd.disableSerializer(_deviceIndex);
@@ -139,12 +139,26 @@ void I2SClass::end()
139139

140140
int I2SClass::available()
141141
{
142-
return 0;
142+
if (_state != I2S_STATE_RECEIVER) {
143+
enableReceiver();
144+
}
145+
146+
return (_bitsPerSample / 8);
143147
}
144148

145149
int I2SClass::read()
146150
{
147-
return 0;
151+
if (_state != I2S_STATE_RECEIVER) {
152+
enableReceiver();
153+
}
154+
155+
while(!i2sd.rxReady(_deviceIndex));
156+
157+
int sample = i2sd.readData(_deviceIndex);
158+
159+
i2sd.clearRxReady(_deviceIndex);
160+
161+
return sample;
148162
}
149163

150164
int I2SClass::peek()
@@ -168,6 +182,10 @@ size_t I2SClass::write(const uint8_t *buffer, size_t size)
168182

169183
size_t I2SClass::availableForWrite()
170184
{
185+
if (_state != I2S_STATE_TRANSMITTER) {
186+
enableTransmitter();
187+
}
188+
171189
uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0);
172190
size_t space;
173191

@@ -191,6 +209,10 @@ size_t I2SClass::write(int sample)
191209

192210
size_t I2SClass::write(int32_t sample)
193211
{
212+
if (_state != I2S_STATE_TRANSMITTER) {
213+
enableTransmitter();
214+
}
215+
194216
while(!i2sd.txReady(_deviceIndex));
195217

196218
i2sd.writeData(_deviceIndex, sample);
@@ -202,6 +224,10 @@ size_t I2SClass::write(int32_t sample)
202224

203225
size_t I2SClass::write(const void *buffer, size_t size)
204226
{
227+
if (_state != I2S_STATE_TRANSMITTER) {
228+
enableTransmitter();
229+
}
230+
205231
uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0);
206232
size_t written;
207233

@@ -231,7 +257,8 @@ void I2SClass::onTransmit(void(*function)(void))
231257
_onTransmit = function;
232258
}
233259

234-
void I2SClass::enableClock(int divider) {
260+
void I2SClass::enableClock(int divider)
261+
{
235262
while (GCLK->STATUS.bit.SYNCBUSY);
236263
GCLK->GENDIV.bit.ID = _clockGenerator;
237264
GCLK->GENDIV.bit.DIV = SystemCoreClock / divider;
@@ -250,7 +277,8 @@ void I2SClass::enableClock(int divider) {
250277
while (GCLK->STATUS.bit.SYNCBUSY);
251278
}
252279

253-
void I2SClass::disableClock() {
280+
void I2SClass::disableClock()
281+
{
254282
while (GCLK->STATUS.bit.SYNCBUSY);
255283
GCLK->GENCTRL.bit.ID = _clockGenerator;
256284
GCLK->GENCTRL.bit.SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
@@ -265,6 +293,34 @@ void I2SClass::disableClock() {
265293
while (GCLK->STATUS.bit.SYNCBUSY);
266294
}
267295

296+
void I2SClass::enableTransmitter()
297+
{
298+
i2sd.setTxMode(_deviceIndex);
299+
i2sd.enableClockUnit(_deviceIndex);
300+
i2sd.enableSerializer(_deviceIndex);
301+
302+
DMA.incSrc(_dmaChannel);
303+
DMA.onTransferComplete(_dmaChannel, I2SClass::onDmaTransferComplete);
304+
DMA.setTriggerSource(_dmaChannel, i2sd.dmaTriggerSource(_deviceIndex));
305+
DMA.setTransferWidth(_dmaChannel, _bitsPerSample);
306+
307+
_state = I2S_STATE_TRANSMITTER;
308+
}
309+
310+
void I2SClass::enableReceiver()
311+
{
312+
i2sd.setRxMode(_deviceIndex);
313+
i2sd.enableClockUnit(_deviceIndex);
314+
i2sd.enableSerializer(_deviceIndex);
315+
316+
DMA.incSrc(_dmaChannel);
317+
DMA.onTransferComplete(_dmaChannel, I2SClass::onDmaTransferComplete);
318+
DMA.setTriggerSource(_dmaChannel, i2sd.dmaTriggerSource(_deviceIndex));
319+
DMA.setTransferWidth(_dmaChannel, _bitsPerSample);
320+
321+
_state = I2S_STATE_RECEIVER;
322+
}
323+
268324
void I2SClass::onTransferComplete(void)
269325
{
270326
if (_doubleBuffer.available()) {

libraries/I2S/src/I2S.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ typedef enum {
2727
I2S_PHILIPS_MODE
2828
} i2s_mode_t;
2929

30-
3130
class I2SClass : public Stream
3231
{
3332
public:
@@ -58,11 +57,20 @@ class I2SClass : public Stream
5857
void enableClock(int divider);
5958
void disableClock();
6059

60+
void enableTransmitter();
61+
void enableReceiver();
62+
6163
void onTransferComplete(void);
6264

6365
static void onDmaTransferComplete(int);
6466

6567
private:
68+
typedef enum {
69+
I2S_STATE_IDLE,
70+
I2S_STATE_TRANSMITTER,
71+
I2S_STATE_RECEIVER
72+
} i2s_state_t;
73+
6674
static int _beginCount;
6775

6876
uint8_t _deviceIndex;
@@ -71,7 +79,9 @@ class I2SClass : public Stream
7179
uint8_t _sckPin;
7280
uint8_t _fsPin;
7381

82+
i2s_state_t _state;
7483
int _dmaChannel;
84+
int _bitsPerSample;
7585

7686
volatile bool _dmaTransferInProgress;
7787
I2SDoubleBuffer _doubleBuffer;

libraries/I2S/src/utility/SAMD21_I2SDevice.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class I2SDevice_SAMD21G18x {
9191
i2s.SERCTRL[index].bit.SERMODE = I2S_SERCTRL_SERMODE_TX_Val;
9292
}
9393

94+
inline void setRxMode(int index) {
95+
i2s.SERCTRL[index].bit.SERMODE = I2S_SERCTRL_SERMODE_RX_Val;
96+
}
97+
9498
inline void enableClockUnit(int index) {
9599
if (index == 0) {
96100
while(i2s.SYNCBUSY.bit.CKEN0);
@@ -132,7 +136,11 @@ class I2SDevice_SAMD21G18x {
132136
}
133137

134138
inline int dmaTriggerSource(int index) {
135-
return (index == 0) ? I2S_DMAC_ID_TX_0 : I2S_DMAC_ID_TX_1;
139+
if (i2s.SERCTRL[index].bit.SERMODE == I2S_SERCTRL_SERMODE_TX_Val) {
140+
return (index == 0) ? I2S_DMAC_ID_TX_0 : I2S_DMAC_ID_TX_1;
141+
} else {
142+
return (index == 0) ? I2S_DMAC_ID_RX_0 : I2S_DMAC_ID_RX_1;
143+
}
136144
}
137145

138146
inline int txReady(int index) {
@@ -157,6 +165,28 @@ class I2SDevice_SAMD21G18x {
157165
}
158166
}
159167

168+
inline int rxReady(int index) {
169+
return (index == 0) ? i2s.INTFLAG.bit.RXRDY0 :i2s.INTFLAG.bit.RXRDY1;
170+
}
171+
172+
inline int32_t readData(int index) {
173+
if (index == 0) {
174+
while (i2s.SYNCBUSY.bit.DATA0);
175+
} else {
176+
while (i2s.SYNCBUSY.bit.DATA1);
177+
}
178+
179+
return i2s.DATA[index].bit.DATA;
180+
}
181+
182+
inline void clearRxReady(int index) {
183+
if (index == 0) {
184+
i2s.INTFLAG.bit.RXRDY0 = 1;
185+
} else {
186+
i2s.INTFLAG.bit.RXRDY1 = 1;
187+
}
188+
}
189+
160190
inline void* data(int index) {
161191
return (void*)&i2s.DATA[index].reg;
162192
}

0 commit comments

Comments
 (0)