Skip to content

Commit 4fae4dd

Browse files
committed
CurieI2S initial commit
- Minimal functional version
1 parent 953479a commit 4fae4dd

File tree

4 files changed

+514
-0
lines changed

4 files changed

+514
-0
lines changed

libraries/CurieI2S/library.properties

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name=CurieI2S
2+
version=1.0
3+
author=Intel
4+
maintainer=Intel
5+
email=dino.tinitigan@intel.com
6+
sentence=Curie I2S Library
7+
paragraph=
8+
url=http://makers.intel.com
9+
architectures=arc32
10+
core-dependencies=arduino (>=1.6.3)

libraries/CurieI2S/src/CurieI2S.cpp

Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
//CurieI2S.cpp
2+
3+
#include "CurieI2S.h"
4+
#include <interrupt.h>
5+
6+
Curie_I2S CurieI2S;
7+
8+
static uint32_t _i2s_dma_Rx_Buffer[DMA_BUFFER_SIZE];
9+
static uint32_t _i2s_dma_Tx_Buffer[DMA_BUFFER_SIZE];
10+
11+
static void i2sInterruptHandler(void)
12+
{
13+
//TODO: Make interrupt handling more atomic
14+
noInterrupts();
15+
16+
//tx FIFO full
17+
if(*I2S_STAT & 0x00000400)
18+
{
19+
//Serial.println("tx full");
20+
21+
//disable TFIFO_FULL interrupts
22+
*I2S_CID_CTRL = *I2S_CID_CTRL & 0xFBFFFFFF;
23+
24+
//start transmit data in FIFO
25+
*I2S_CTRL = *I2S_CTRL | 0x02000000;
26+
delayTicks(3200);
27+
28+
//clear flags
29+
*I2S_STAT = *I2S_CTRL & 0xFFFFF3FF;
30+
31+
32+
//enable TFIFO_EMPTY interrupt
33+
*I2S_CID_CTRL = *I2S_CID_CTRL | 0x01000000;
34+
35+
return;
36+
}
37+
38+
//tx FIFO empty
39+
if(*I2S_STAT & 0x00000100)
40+
{
41+
//Serial.println("tx empty");
42+
43+
//disable TFIFO_EMPTY interrupt
44+
*I2S_CID_CTRL = *I2S_CID_CTRL & 0xFEFFFFFF;
45+
46+
//stop transmission
47+
*I2S_CTRL = *I2S_CTRL & 0xFDFFFFFF;
48+
49+
//clear flags
50+
*I2S_STAT = *I2S_STAT & 0xFFFFFCFF;
51+
52+
//enable TFIFO_FULL interrupt
53+
*I2S_CID_CTRL = *I2S_CID_CTRL | 0x04000000;
54+
55+
return;
56+
}
57+
58+
//tx FIFO almost empty
59+
{
60+
//fill up FIFO from buffer if available;
61+
}
62+
63+
//overrun and underrun
64+
65+
interrupts();
66+
}
67+
68+
Curie_I2S::Curie_I2S()
69+
{
70+
71+
}
72+
73+
void Curie_I2S::begin(uint32_t sampleRate, uint32_t resolution)
74+
{
75+
init();
76+
setSampleRate(sampleRate);
77+
setResolution(resolution);
78+
}
79+
void Curie_I2S::end()
80+
{
81+
//disable I2S PCLK Clock Gate
82+
}
83+
void Curie_I2S::startRX()
84+
{
85+
enableRXChannel(1);
86+
syncRX(1);
87+
}
88+
89+
void Curie_I2S::startTX()
90+
{
91+
syncTX(1);
92+
delayTicks(800); //add frame delay to prevent sending emptyFrame
93+
muxTX(1);
94+
}
95+
96+
void Curie_I2S::stopRX()
97+
{
98+
syncRX(0);
99+
enableRXChannel(0);
100+
}
101+
102+
void Curie_I2S::stopTX()
103+
{
104+
//delayTicks(160);
105+
//muxTX(0);
106+
delayTicks(320);
107+
syncTX(0);
108+
//delayTicks(320);
109+
muxTX(0);
110+
//enableTXChannel(0);
111+
}
112+
113+
void Curie_I2S::setI2SMode(uint32_t mode)
114+
{
115+
*I2S_DEV_CONF = mode;
116+
uint32_t dev_conf = *I2S_DEV_CONF;
117+
dev_conf &= 0xFFFFF800;
118+
dev_conf |= mode;
119+
*I2S_DEV_CONF = dev_conf;
120+
}
121+
122+
void Curie_I2S::setSampleRate(uint32_t dividerValue)
123+
{
124+
uint32_t i2s_srr = *I2S_SRR;
125+
i2s_srr &= I2S_SAMPLERATE_MASK;
126+
i2s_srr |= dividerValue;
127+
*I2S_SRR = i2s_srr;
128+
}
129+
130+
void Curie_I2S::setResolution(uint32_t resolution)
131+
{
132+
switch(resolution)
133+
{
134+
case 32:
135+
resolution = I2S_32bit;
136+
break;
137+
case 24:
138+
resolution = I2S_24bit;
139+
break;
140+
case 16:
141+
resolution = I2S_16bit;
142+
break;
143+
default:
144+
break;
145+
}
146+
uint32_t i2s_srr = *I2S_SRR;
147+
i2s_srr &= I2S_RESOLUTION_MASK;
148+
i2s_srr |= resolution;
149+
*I2S_SRR = i2s_srr;
150+
}
151+
152+
//*************************************************************************************//
153+
154+
void Curie_I2S::init()
155+
{
156+
//enable I2S PCLK Clock Gate and I2S Clock
157+
uint32_t clk_gate_ctl = *(uint32_t *)0xB0800018;
158+
clk_gate_ctl |= 0x200200;
159+
*(uint32_t *)0xB0800018 = clk_gate_ctl;
160+
161+
//configure I2S_CTRL register and set TX as master and RX as slave
162+
uint32_t i2s_ctrl = *I2S_CTRL;
163+
i2s_ctrl &= 0xF9FFFCFC;
164+
i2s_ctrl |= 0x08B00100;
165+
*I2S_CTRL = i2s_ctrl;
166+
167+
//enable interrupts
168+
//ToDo: Use DMA instead of relying on interrupts
169+
enableInterrupts();
170+
}
171+
172+
void Curie_I2S::muxRX(bool enable)
173+
{
174+
int mux_mode = GPIO_MUX_MODE;
175+
if(enable)
176+
{
177+
mux_mode = 1;
178+
}
179+
180+
/* Set SoC pin mux configuration */
181+
SET_PIN_MODE(49, mux_mode); //I2S_RXD
182+
SET_PIN_MODE(51, mux_mode); //I2S_RWS
183+
SET_PIN_MODE(50, mux_mode); //I2S_RSCK
184+
g_APinDescription[I2S_RXD].ulPinMode = mux_mode;
185+
g_APinDescription[I2S_RWS].ulPinMode = mux_mode;
186+
g_APinDescription[I2S_RSCK].ulPinMode = mux_mode;
187+
}
188+
189+
void Curie_I2S::muxTX(bool enable)
190+
{
191+
int mux_mode = GPIO_MUX_MODE;
192+
if(enable)
193+
{
194+
mux_mode = I2S_MUX_MODE;
195+
}
196+
197+
/* Set SoC pin mux configuration */
198+
SET_PIN_MODE(g_APinDescription[I2S_TXD].ulSocPin, mux_mode);
199+
SET_PIN_MODE(g_APinDescription[I2S_TWS].ulSocPin, mux_mode);
200+
SET_PIN_MODE(g_APinDescription[I2S_TSCK].ulSocPin, mux_mode);
201+
g_APinDescription[I2S_TXD].ulPinMode = mux_mode;
202+
g_APinDescription[I2S_TWS].ulPinMode = mux_mode;
203+
g_APinDescription[I2S_TSCK].ulPinMode = mux_mode;
204+
}
205+
206+
void Curie_I2S::initRX()
207+
{
208+
muxRX(1);
209+
resetRXFIFO();
210+
}
211+
212+
void Curie_I2S::initTX()
213+
{
214+
muxTX(1);
215+
resetTXFIFO();
216+
enableTXChannel(1);
217+
}
218+
219+
void Curie_I2S::enableRXChannel(bool enable)
220+
{
221+
uint32_t i2s_ctrl = *I2S_CTRL;
222+
if(enable)
223+
{
224+
i2s_ctrl |= 0x00000002;
225+
*I2S_CTRL = i2s_ctrl;
226+
}
227+
else
228+
{
229+
i2s_ctrl &= 0xFFFFFFFD;
230+
*I2S_CTRL = i2s_ctrl;
231+
}
232+
}
233+
234+
void Curie_I2S::enableTXChannel(bool enable)
235+
{
236+
uint32_t i2s_ctrl = *I2S_CTRL;
237+
if(enable)
238+
{
239+
i2s_ctrl |= 0x00000001;
240+
*I2S_CTRL = i2s_ctrl;
241+
}
242+
else
243+
{
244+
i2s_ctrl &= 0xFFFFFFFE;
245+
*I2S_CTRL = i2s_ctrl;
246+
}
247+
}
248+
249+
void Curie_I2S::syncTX(bool sync)
250+
{
251+
uint32_t i2s_ctrl = *I2S_CTRL;
252+
if(sync)
253+
{
254+
i2s_ctrl |= 0x02000000;
255+
*I2S_CTRL = i2s_ctrl;
256+
}
257+
else
258+
{
259+
i2s_ctrl &= 0xFDFFFFFF;
260+
*I2S_CTRL = i2s_ctrl;
261+
}
262+
}
263+
264+
void Curie_I2S::syncRX(bool sync)
265+
{
266+
uint32_t i2s_ctrl = *I2S_CTRL;
267+
if(sync)
268+
{
269+
i2s_ctrl |= 0x04000000;
270+
*I2S_CTRL = i2s_ctrl;
271+
}
272+
else
273+
{
274+
i2s_ctrl &= 0xFBFFFFFF;
275+
*I2S_CTRL = i2s_ctrl;
276+
}
277+
}
278+
279+
void Curie_I2S::resetRXFIFO()
280+
{
281+
uint32_t i2s_ctrl = *I2S_CTRL;
282+
i2s_ctrl &= 0xFEFFFFFF;
283+
}
284+
285+
void Curie_I2S::resetTXFIFO()
286+
{
287+
uint32_t i2s_ctrl = *I2S_CTRL;
288+
i2s_ctrl &= 0xFF7FFFFF;
289+
}
290+
291+
void Curie_I2S::enableInterrupts()
292+
{
293+
//Serial.println("enabling interrupts");
294+
uint32_t int_i2s_mask = *INT_I2S_MASK;
295+
int_i2s_mask &= 0xFFFFFEFF;
296+
*INT_I2S_MASK = int_i2s_mask;
297+
298+
uint32_t i2s_cid_ctrl = *I2S_CID_CTRL;
299+
i2s_cid_ctrl |= 0x05008000;
300+
*I2S_CID_CTRL = i2s_cid_ctrl;
301+
302+
interrupt_disable(IRQ_I2S_INTR);
303+
interrupt_connect(IRQ_I2S_INTR , &i2sInterruptHandler);
304+
interrupt_enable(IRQ_I2S_INTR);
305+
}
306+
307+
void Curie_I2S::transmitFIFO()
308+
{
309+
if(getTxFIFOLength())
310+
{
311+
startTX();
312+
while(getTxFIFOLength());
313+
stopTX();
314+
}
315+
}
316+
317+
void Curie_I2S::transmitFrame()
318+
{
319+
320+
}
321+
322+
void Curie_I2S::pushData(uint32_t data)
323+
{
324+
if(getTxFIFOLength() < 4)
325+
{
326+
*I2S_DATA_REG = data;
327+
}
328+
}
329+
330+
void Curie_I2S::fastPushData(uint32_t data)
331+
{
332+
*I2S_DATA_REG = data;
333+
}
334+
335+
uint32_t Curie_I2S::pullData()
336+
{
337+
uint32_t data = *I2S_DATA_REG;
338+
return data;
339+
}
340+
341+
void Curie_I2S::pushDataFrame(uint32_t leftChData, uint32_t rightChData)
342+
{
343+
int fifoLength = getTxFIFOLength();
344+
if(!(fifoLength%2) && (fifoLength < 4))
345+
{
346+
pushData(leftChData);
347+
pushData(rightChData);
348+
}
349+
}
350+
351+
uint8_t Curie_I2S::getTxFIFOLength()
352+
{
353+
uint8_t fifolength = *I2S_TFIFO_STAT & 0x000000FF;
354+
delayTicks(640);
355+
return fifolength;
356+
}
357+
358+
uint8_t Curie_I2S::getRxFIFOLength()
359+
{
360+
uint8_t fifolength = *I2S_RFIFO_STAT & 0x000000FF;
361+
delayTicks(640);
362+
return fifolength;
363+
}

0 commit comments

Comments
 (0)