Skip to content

Commit 26ff2d9

Browse files
committed
initial infrastructure
1 parent 72b1dc1 commit 26ff2d9

File tree

4 files changed

+332
-0
lines changed

4 files changed

+332
-0
lines changed

libraries/I2S/keywords.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#######################################
2+
# Syntax Coloring Map I2S
3+
#######################################
4+
5+
#######################################
6+
# Datatypes (KEYWORD1)
7+
#######################################
8+
9+
I2S KEYWORD1
10+
11+
#######################################
12+
# Methods and Functions (KEYWORD2)
13+
#######################################
14+
begin KEYWORD2
15+
end KEYWORD2
16+
17+
onReceive KEYWORD2
18+
onTransmit KEYWORD2
19+
20+
#######################################
21+
# Constants (LITERAL1)
22+
#######################################
23+
I2S_PHILIPS_MODE LITERAL1
24+
I2S_RIGHT_JUSTIFIED_MODE LITERAL1
25+
I2S_LEFT_JUSTIFIED_MODE LITERAL1
26+
I2S_DSP_MODE LITERAL1

libraries/I2S/library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=I2S
2+
version=1.0
3+
author=Arduino
4+
maintainer=Arduino <[email protected]>
5+
sentence=Enables the communication with devices that use the Inter-IC Sound (I2S) Bus. Specific implementation for Arduino Zero.
6+
paragraph=
7+
category=Communication
8+
url=http://www.arduino.cc/en/Reference/I2S
9+
architectures=samd

libraries/I2S/src/I2S.cpp

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
#include <Arduino.h>
2+
#include <wiring_private.h>
3+
4+
#include "I2S.h"
5+
6+
I2SClass::I2SClass(SERCOM *p_sercom, uint8_t uc_index, uint8_t uc_pinSD, uint8_t uc_pinSCK, uint8_t uc_pinFS) :
7+
_p_sercom(p_sercom),
8+
_uc_index(uc_index),
9+
_uc_sd(uc_pinSD),
10+
_uc_sck(uc_pinSCK),
11+
_uc_fs(uc_pinFS)
12+
{
13+
}
14+
15+
int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, int driveClock)
16+
{
17+
switch (bitsPerSample) {
18+
case 8:
19+
case 16:
20+
case 24:
21+
case 32:
22+
break;
23+
24+
default:
25+
return 1;
26+
}
27+
28+
PM->APBCMASK.reg |= PM_APBCMASK_I2S;
29+
30+
while (GCLK->STATUS.bit.SYNCBUSY);
31+
32+
GCLK->GENDIV.bit.ID = GCLK_CLKCTRL_GEN_GCLK3_Val;
33+
GCLK->GENDIV.bit.DIV = SystemCoreClock / (sampleRate * 2 * bitsPerSample);
34+
35+
Serial.println(GCLK->GENDIV.bit.DIV);
36+
37+
while (GCLK->STATUS.bit.SYNCBUSY);
38+
39+
GCLK->GENCTRL.bit.ID = GCLK_CLKCTRL_GEN_GCLK3_Val;
40+
GCLK->GENCTRL.bit.SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
41+
GCLK->GENCTRL.bit.IDC = 1;
42+
GCLK->GENCTRL.bit.GENEN = 1;
43+
44+
while (GCLK->STATUS.bit.SYNCBUSY);
45+
46+
GCLK->CLKCTRL.bit.ID = (_uc_index == 0) ? I2S_GCLK_ID_0 : I2S_GCLK_ID_1;
47+
GCLK->CLKCTRL.bit.GEN = GCLK_CLKCTRL_GEN_GCLK3_Val;
48+
GCLK->CLKCTRL.bit.CLKEN = 1;
49+
50+
while (GCLK->STATUS.bit.SYNCBUSY);
51+
52+
while(_i2s->SYNCBUSY.bit.ENABLE);
53+
54+
_i2s->CTRLA.bit.ENABLE = 0;
55+
56+
// TODO: change these based on mode
57+
_i2s->CLKCTRL[_uc_index].bit.MCKOUTINV = 0;
58+
_i2s->CLKCTRL[_uc_index].bit.SCKOUTINV = 0;
59+
_i2s->CLKCTRL[_uc_index].bit.FSOUTINV = 0;
60+
_i2s->CLKCTRL[_uc_index].bit.MCKEN = 0;
61+
_i2s->CLKCTRL[_uc_index].bit.MCKSEL = I2S_CLKCTRL_MCKSEL_GCLK_Val;
62+
_i2s->CLKCTRL[_uc_index].bit.SCKSEL = I2S_CLKCTRL_SCKSEL_MCKDIV_Val;
63+
_i2s->CLKCTRL[_uc_index].bit.FSINV = 0;
64+
_i2s->CLKCTRL[_uc_index].bit.FSSEL = I2S_CLKCTRL_FSSEL_SCKDIV_Val;
65+
_i2s->CLKCTRL[_uc_index].bit.BITDELAY = I2S_CLKCTRL_BITDELAY_I2S_Val;
66+
_i2s->CLKCTRL[_uc_index].bit.MCKOUTDIV = 0;
67+
_i2s->CLKCTRL[_uc_index].bit.MCKDIV = 0;
68+
_i2s->CLKCTRL[_uc_index].bit.NBSLOTS = 1;
69+
70+
switch (bitsPerSample) {
71+
case 32:
72+
_i2s->CLKCTRL[_uc_index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_32_Val;
73+
break;
74+
75+
case 24:
76+
_i2s->CLKCTRL[_uc_index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_24_Val;
77+
break;
78+
79+
case 16:
80+
_i2s->CLKCTRL[_uc_index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_16_Val;
81+
break;
82+
83+
case 8:
84+
_i2s->CLKCTRL[_uc_index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_8_Val;
85+
break;
86+
}
87+
88+
_i2s->CLKCTRL[_uc_index].bit.FSWIDTH = I2S_CLKCTRL_FSWIDTH_SLOT_Val;
89+
90+
pinPeripheral(_uc_sck, PIO_COM);
91+
pinPeripheral(_uc_fs, PIO_COM);
92+
93+
_i2s->SERCTRL[_uc_index].bit.RXLOOP = 0;
94+
_i2s->SERCTRL[_uc_index].bit.DMA = I2S_SERCTRL_DMA_SINGLE_Val;
95+
_i2s->SERCTRL[_uc_index].bit.MONO = I2S_SERCTRL_MONO_STEREO_Val;
96+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS0 = 0;
97+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS1 = 0;
98+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS2 = 0;
99+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS3 = 0;
100+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS4 = 0;
101+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS5 = 0;
102+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS6 = 0;
103+
_i2s->SERCTRL[_uc_index].bit.SLOTDIS7 = 0;
104+
_i2s->SERCTRL[_uc_index].bit.BITREV = I2S_SERCTRL_BITREV_MSBIT_Val;
105+
_i2s->SERCTRL[_uc_index].bit.WORDADJ = I2S_SERCTRL_WORDADJ_RIGHT_Val;
106+
_i2s->SERCTRL[_uc_index].bit.SLOTADJ = I2S_SERCTRL_SLOTADJ_RIGHT_Val;
107+
_i2s->SERCTRL[_uc_index].bit.TXSAME = I2S_SERCTRL_TXSAME_SAME_Val; //I2S_SERCTRL_TXSAME_ZERO_Val;
108+
_i2s->SERCTRL[_uc_index].bit.CLKSEL = (_uc_index == 0) ? I2S_SERCTRL_CLKSEL_CLK0_Val : I2S_SERCTRL_CLKSEL_CLK1_Val;
109+
_i2s->SERCTRL[_uc_index].bit.SERMODE = I2S_SERCTRL_SERMODE_TX_Val;
110+
_i2s->SERCTRL[_uc_index].bit.TXDEFAULT = I2S_SERCTRL_TXDEFAULT_ZERO_Val;
111+
112+
switch (bitsPerSample) {
113+
case 32:
114+
_i2s->SERCTRL[_uc_index].bit.DATASIZE = I2S_SERCTRL_DATASIZE_32_Val;
115+
break;
116+
117+
case 24:
118+
_i2s->SERCTRL[_uc_index].bit.DATASIZE = I2S_SERCTRL_DATASIZE_24_Val;
119+
break;
120+
121+
case 16:
122+
_i2s->SERCTRL[_uc_index].bit.DATASIZE = I2S_SERCTRL_DATASIZE_16_Val;
123+
break;
124+
125+
case 8:
126+
_i2s->SERCTRL[_uc_index].bit.DATASIZE = I2S_SERCTRL_DATASIZE_8_Val;
127+
break;
128+
}
129+
130+
_i2s->SERCTRL[_uc_index].bit.EXTEND = I2S_SERCTRL_EXTEND_ZERO_Val;
131+
132+
pinPeripheral(_uc_sd, PIO_COM);
133+
134+
while(_i2s->SYNCBUSY.bit.ENABLE);
135+
136+
_i2s->CTRLA.bit.ENABLE = 1;
137+
138+
if (_uc_index == 0) {
139+
while(_i2s->SYNCBUSY.bit.CKEN0);
140+
141+
_i2s->CTRLA.bit.CKEN0 = 1;
142+
143+
while(_i2s->SYNCBUSY.bit.SEREN0);
144+
145+
_i2s->CTRLA.bit.SEREN0 = 1;
146+
} else {
147+
while(_i2s->SYNCBUSY.bit.SEREN0);
148+
149+
_i2s->CTRLA.bit.CKEN1 = 1;
150+
151+
while(_i2s->SYNCBUSY.bit.SEREN1);
152+
153+
_i2s->CTRLA.bit.SEREN1 = 1;
154+
}
155+
156+
return 0;
157+
}
158+
159+
void I2SClass::end()
160+
{
161+
162+
}
163+
164+
int I2SClass::available()
165+
{
166+
return 0;
167+
}
168+
169+
int I2SClass::read()
170+
{
171+
return -1;
172+
}
173+
174+
int I2SClass::peek()
175+
{
176+
return -1;
177+
}
178+
179+
void I2SClass::flush()
180+
{
181+
}
182+
183+
size_t I2SClass::write(uint8_t data)
184+
{
185+
if (_uc_index == 0) {
186+
_i2s->INTFLAG.bit.TXUR0 = 1;
187+
188+
while (_i2s->INTFLAG.bit.TXRDY0);
189+
while (_i2s->SYNCBUSY.bit.DATA0);
190+
} else {
191+
_i2s->INTFLAG.bit.TXUR1 = 1;
192+
193+
while (_i2s->INTFLAG.bit.TXRDY1);
194+
while (_i2s->SYNCBUSY.bit.DATA1);
195+
}
196+
197+
_i2s->DATA[_uc_index].bit.DATA = data;
198+
199+
if (_uc_index == 0) {
200+
_i2s->INTFLAG.bit.TXRDY0 = 1;
201+
} else {
202+
_i2s->INTFLAG.bit.TXRDY1 = 1;
203+
}
204+
205+
return 0;
206+
}
207+
208+
size_t I2SClass::write(const uint8_t *buffer, size_t size)
209+
{
210+
return 0;
211+
}
212+
213+
size_t I2SClass::availableForWrite()
214+
{
215+
return 0;
216+
}
217+
218+
int I2SClass::read(int8_t data[], int size)
219+
{
220+
return 0;
221+
}
222+
223+
/*
224+
225+
+--------+--------------+-----------+-----------------+
226+
| I2S | Pad | Zero | MKR1000 |
227+
+--------+--------------+-----------+-----------------+
228+
| SD[0] | PA07 or PA19 | 9 or 12 | A6 or 10 (MISO) |
229+
| MCK[0] | PA09 or PB17 | 3 or ? | 12 (SCL) or ? |
230+
| SCK[0] | PA10 or PA20 | 1 or 6 | 2 or 6 |
231+
| FS[0] | PA11 or PA21 | 0 or ? | 3 or 7 |
232+
+--------+--------------------------+-----------------+
233+
| SD[1] | PA08 or PB16 | 4 or ? | 11 (SDA) or ? |
234+
| MCK[1] | PB10 | 23 (MOSI) | 4 |
235+
| SCK[1] | PB11 | 24 (SCK) | 5 |
236+
| FS[1] | PB12 | ? | ? |
237+
+--------+--------------+-----------+-----------------+
238+
*/
239+
240+
I2SClass I2S(&sercom2, 0, 9, 1, 0);

libraries/I2S/src/I2S.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#ifndef _I2S_H_INCLUDED
2+
#define _I2S_H_INCLUDED
3+
4+
#include <Arduino.h>
5+
6+
typedef enum {
7+
I2S_PHILIPS_MODE,
8+
I2S_RIGHT_JUSTIFIED_MODE,
9+
I2S_LEFT_JUSTIFIED_MODE,
10+
I2S_DSP_MODE
11+
} i2s_mode_t;
12+
13+
class I2SClass : public Stream
14+
{
15+
public:
16+
I2SClass(SERCOM *p_sercom, uint8_t uc_index, uint8_t uc_pinSD, uint8_t uc_pinSCK, uint8_t uc_pinFS);
17+
18+
int begin(int mode, long sampleRate, int bitsPerSample, int driveClock = 1);
19+
20+
void end();
21+
22+
virtual int available();
23+
virtual int read();
24+
virtual int peek();
25+
virtual void flush();
26+
27+
virtual size_t write(uint8_t);
28+
virtual size_t write(const uint8_t *buffer, size_t size);
29+
30+
virtual size_t availableForWrite();
31+
32+
int read(int8_t data[], int size);
33+
int read(int16_t data[], int size);
34+
int read(int32_t data[], int size);
35+
36+
int write(const int8_t data[], int size);
37+
int write(const int16_t data[], int size);
38+
int write(const int32_t data[], int size);
39+
40+
void onReceive(void(*)(int));
41+
void onTransmit(void(*)(void));
42+
43+
private:
44+
I2s *_i2s = I2S;
45+
46+
SERCOM *_p_sercom;
47+
uint8_t _uc_index;
48+
uint8_t _uc_sd;
49+
uint8_t _uc_sck;
50+
uint8_t _uc_fs;
51+
};
52+
53+
#undef I2S
54+
55+
extern I2SClass I2S;
56+
57+
#endif

0 commit comments

Comments
 (0)