1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#include "embiosapp.h"


void main();
EMBIOS_APP_HEADER("Audiotest", 0x4000, main, 127)


struct dma_lli
{
    void* srcaddr;
    void* dstaddr;
    const struct dma_lli* nextlli;
    uint32_t control;
};
#define DMACINTSTS(d)       (*((uint32_t volatile*)(0x38200000 + 0x1700000 * (d))))
#define DMACINTTCSTS(d)     (*((uint32_t volatile*)(0x38200004 + 0x1700000 * (d))))
#define DMACINTTCCLR(d)     (*((uint32_t volatile*)(0x38200008 + 0x1700000 * (d))))
#define DMACINTERRSTS(d)    (*((uint32_t volatile*)(0x3820000c + 0x1700000 * (d))))
#define DMACINTERRCLR(d)    (*((uint32_t volatile*)(0x38200010 + 0x1700000 * (d))))
#define DMACRAWINTTCSTS(d)  (*((uint32_t volatile*)(0x38200014 + 0x1700000 * (d))))
#define DMACRAWINTERRSTS(d) (*((uint32_t volatile*)(0x38200018 + 0x1700000 * (d))))
#define DMACENABLEDCHANS(d) (*((uint32_t volatile*)(0x3820001c + 0x1700000 * (d))))
#define DMACSOFTBREQ(d)     (*((uint32_t volatile*)(0x38200020 + 0x1700000 * (d))))
#define DMACSOFTSREQ(d)     (*((uint32_t volatile*)(0x38200024 + 0x1700000 * (d))))
#define DMACSOFTLBREQ(d)    (*((uint32_t volatile*)(0x38200028 + 0x1700000 * (d))))
#define DMACSOFTLSREQ(d)    (*((uint32_t volatile*)(0x3820002c + 0x1700000 * (d))))
#define DMACCONFIG(d)       (*((uint32_t volatile*)(0x38200030 + 0x1700000 * (d))))
#define DMACSYNC(d)         (*((uint32_t volatile*)(0x38200034 + 0x1700000 * (d))))
#define DMACCLLI(d, c)      (*((struct dma_lli volatile*)(0x38200100 + 0x1700000 * (d) + 0x20 * (c))))
#define DMACCSRCADDR(d, c)  (*((const void* volatile*)(0x38200100 + 0x1700000 * (d) + 0x20 * (c))))
#define DMACCDESTADDR(d, c) (*((void* volatile*)(0x38200104 + 0x1700000 * (d) + 0x20 * (c))))
#define DMACCNEXTLLI(d, c)  (*((const void* volatile*)(0x38200108 + 0x1700000 * (d) + 0x20 * (c))))
#define DMACCCONTROL(d, c)  (*((uint32_t volatile*)(0x3820010c + 0x1700000 * (d) + 0x20 * (c))))
#define DMACCCONFIG(d, c)   (*((uint32_t volatile*)(0x38200110 + 0x1700000 * (d) + 0x20 * (c))))
#define DMAC0INTSTS         (*((uint32_t volatile*)(0x38200000)))
#define DMAC0INTTCSTS       (*((uint32_t volatile*)(0x38200004)))
#define DMAC0INTTCCLR       (*((uint32_t volatile*)(0x38200008)))
#define DMAC0INTERRSTS      (*((uint32_t volatile*)(0x3820000c)))
#define DMAC0INTERRCLR      (*((uint32_t volatile*)(0x38200010)))
#define DMAC0RAWINTTCSTS    (*((uint32_t volatile*)(0x38200014)))
#define DMAC0RAWINTERRSTS   (*((uint32_t volatile*)(0x38200018)))
#define DMAC0ENABLEDCHANS   (*((uint32_t volatile*)(0x3820001c)))
#define DMAC0SOFTBREQ       (*((uint32_t volatile*)(0x38200020)))
#define DMAC0SOFTSREQ       (*((uint32_t volatile*)(0x38200024)))
#define DMAC0SOFTLBREQ      (*((uint32_t volatile*)(0x38200028)))
#define DMAC0SOFTLSREQ      (*((uint32_t volatile*)(0x3820002c)))
#define DMAC0CONFIG         (*((uint32_t volatile*)(0x38200030)))
#define DMAC0SYNC           (*((uint32_t volatile*)(0x38200034)))
#define DMAC0CLLI(c)        (*((struct dma_lli volatile*)(0x38200100 + 0x20 * (c))))
#define DMAC0CSRCADDR(c)    (*((const void* volatile*)(0x38200100 + 0x20 * (c))))
#define DMAC0CDESTADDR(c)   (*((void* volatile*)(0x38200104 + 0x20 * (c))))
#define DMAC0CNEXTLLI(c)    (*((const void* volatile*)(0x38200108 + 0x20 * (c))))
#define DMAC0CCONTROL(c)    (*((uint32_t volatile*)(0x3820010c + 0x20 * (c))))
#define DMAC0CCONFIG(c)     (*((uint32_t volatile*)(0x38200110 + 0x20 * (c))))
#define DMAC0C0LLI          (*((struct dma_lli volatile*)(0x38200100)))
#define DMAC0C0SRCADDR      (*((const void* volatile*)(0x38200100)))
#define DMAC0C0DESTADDR     (*((void* volatile*)(0x38200104)))
#define DMAC0C0NEXTLLI      (*((const struct dma_lli* volatile*)(0x38200108)))
#define DMAC0C0CONTROL      (*((uint32_t volatile*)(0x3820010c)))
#define DMAC0C0CONFIG       (*((uint32_t volatile*)(0x38200110)))
#define DMAC0C1LLI          (*((struct dma_lli volatile*)(0x38200120)))
#define DMAC0C1SRCADDR      (*((const void* volatile*)(0x38200120)))
#define DMAC0C1DESTADDR     (*((void* volatile*)(0x38200124)))
#define DMAC0C1NEXTLLI      (*((const struct dma_lli* volatile*)(0x38200128)))
#define DMAC0C1CONTROL      (*((uint32_t volatile*)(0x3820012c)))
#define DMAC0C1CONFIG       (*((uint32_t volatile*)(0x38200130)))
#define DMAC0C2LLI          (*((struct dma_lli volatile*)(0x38200140)))
#define DMAC0C2SRCADDR      (*((const void* volatile*)(0x38200140)))
#define DMAC0C2DESTADDR     (*((void* volatile*)(0x38200144)))
#define DMAC0C2NEXTLLI      (*((const struct dma_lli* volatile*)(0x38200148)))
#define DMAC0C2CONTROL      (*((uint32_t volatile*)(0x3820014c)))
#define DMAC0C2CONFIG       (*((uint32_t volatile*)(0x38200150)))
#define DMAC0C3LLI          (*((struct dma_lli volatile*)(0x38200160)))
#define DMAC0C3SRCADDR      (*((const void* volatile*)(0x38200160)))
#define DMAC0C3DESTADDR     (*((void* volatile*)(0x38200164)))
#define DMAC0C3NEXTLLI      (*((const struct dma_lli* volatile*)(0x38200168)))
#define DMAC0C3CONTROL      (*((uint32_t volatile*)(0x3820016c)))
#define DMAC0C3CONFIG       (*((uint32_t volatile*)(0x38200170)))
#define DMAC0C4LLI          (*((struct dma_lli volatile*)(0x38200180)))
#define DMAC0C4SRCADDR      (*((const void* volatile*)(0x38200180)))
#define DMAC0C4DESTADDR     (*((void* volatile*)(0x38200184)))
#define DMAC0C4NEXTLLI      (*((const struct dma_lli* volatile*)(0x38200188)))
#define DMAC0C4CONTROL      (*((uint32_t volatile*)(0x3820018c)))
#define DMAC0C4CONFIG       (*((uint32_t volatile*)(0x38200190)))
#define DMAC0C5LLI          (*((struct dma_lli volatile*)(0x382001a0)))
#define DMAC0C5SRCADDR      (*((const void* volatile*)(0x382001a0)))
#define DMAC0C5DESTADDR     (*((void* volatile*)(0x382001a4)))
#define DMAC0C5NEXTLLI      (*((const struct dma_lli* volatile*)(0x382001a8)))
#define DMAC0C5CONTROL      (*((uint32_t volatile*)(0x382001ac)))
#define DMAC0C5CONFIG       (*((uint32_t volatile*)(0x382001b0)))
#define DMAC0C6LLI          (*((struct dma_lli volatile*)(0x382001c0)))
#define DMAC0C6SRCADDR      (*((const void* volatile*)(0x382001c0)))
#define DMAC0C6DESTADDR     (*((void* volatile*)(0x382001c4)))
#define DMAC0C6NEXTLLI      (*((const struct dma_lli* volatile*)(0x382001c8)))
#define DMAC0C6CONTROL      (*((uint32_t volatile*)(0x382001cc)))
#define DMAC0C6CONFIG       (*((uint32_t volatile*)(0x382001d0)))
#define DMAC0C7LLI          (*((struct dma_lli volatile*)(0x382001e0)))
#define DMAC0C7SRCADDR      (*((const void* volatile*)(0x382001e0)))
#define DMAC0C7DESTADDR     (*((void* volatile*)(0x382001e4)))
#define DMAC0C7NEXTLLI      (*((const struct dma_lli* volatile*)(0x382001e8)))
#define DMAC0C7CONTROL      (*((uint32_t volatile*)(0x382001ec)))
#define DMAC0C7CONFIG       (*((uint32_t volatile*)(0x382001f0)))
#define DMAC1INTSTS         (*((uint32_t volatile*)(0x39900000)))
#define DMAC1INTTCSTS       (*((uint32_t volatile*)(0x39900004)))
#define DMAC1INTTCCLR       (*((uint32_t volatile*)(0x39900008)))
#define DMAC1INTERRSTS      (*((uint32_t volatile*)(0x3990000c)))
#define DMAC1INTERRCLR      (*((uint32_t volatile*)(0x39900010)))
#define DMAC1RAWINTTCSTS    (*((uint32_t volatile*)(0x39900014)))
#define DMAC1RAWINTERRSTS   (*((uint32_t volatile*)(0x39900018)))
#define DMAC1ENABLEDCHANS   (*((uint32_t volatile*)(0x3990001c)))
#define DMAC1SOFTBREQ       (*((uint32_t volatile*)(0x39900020)))
#define DMAC1SOFTSREQ       (*((uint32_t volatile*)(0x39900024)))
#define DMAC1SOFTLBREQ      (*((uint32_t volatile*)(0x39900028)))
#define DMAC1SOFTLSREQ      (*((uint32_t volatile*)(0x3990002c)))
#define DMAC1CONFIG         (*((uint32_t volatile*)(0x39900030)))
#define DMAC1SYNC           (*((uint32_t volatile*)(0x39900034)))
#define DMAC1CLLI(c)        (*((struct dma_lli volatile*)(0x39900100 + 0x20 * (c))))
#define DMAC1CSRCADDR(c)    (*((const void* volatile*)(0x39900100 + 0x20 * (c))))
#define DMAC1CDESTADDR(c)   (*((void* volatile*)(0x39900104 + 0x20 * (c))))
#define DMAC1CNEXTLLI(c)    (*((const void* volatile*)(0x39900108 + 0x20 * (c))))
#define DMAC1CCONTROL(c)    (*((uint32_t volatile*)(0x3990010c + 0x20 * (c))))
#define DMAC1CCONFIG(c)     (*((uint32_t volatile*)(0x39900110 + 0x20 * (c))))
#define DMAC1C0LLI          (*((struct dma_lli volatile*)(0x39900100)))
#define DMAC1C0SRCADDR      (*((const void* volatile*)(0x39900100)))
#define DMAC1C0DESTADDR     (*((void* volatile*)(0x39900104)))
#define DMAC1C0NEXTLLI      (*((const struct dma_lli* volatile*)(0x39900108)))
#define DMAC1C0CONTROL      (*((uint32_t volatile*)(0x3990010c)))
#define DMAC1C0CONFIG       (*((uint32_t volatile*)(0x39900110)))
#define DMAC1C1LLI          (*((struct dma_lli volatile*)(0x39900120)))
#define DMAC1C1SRCADDR      (*((const void* volatile*)(0x39900120)))
#define DMAC1C1DESTADDR     (*((void* volatile*)(0x39900124)))
#define DMAC1C1NEXTLLI      (*((const struct dma_lli* volatile*)(0x39900128)))
#define DMAC1C1CONTROL      (*((uint32_t volatile*)(0x3990012c)))
#define DMAC1C1CONFIG       (*((uint32_t volatile*)(0x39900130)))
#define DMAC1C2LLI          (*((struct dma_lli volatile*)(0x39900140)))
#define DMAC1C2SRCADDR      (*((const void* volatile*)(0x39900140)))
#define DMAC1C2DESTADDR     (*((void* volatile*)(0x39900144)))
#define DMAC1C2NEXTLLI      (*((const struct dma_lli* volatile*)(0x39900148)))
#define DMAC1C2CONTROL      (*((uint32_t volatile*)(0x3990014c)))
#define DMAC1C2CONFIG       (*((uint32_t volatile*)(0x39900150)))
#define DMAC1C3LLI          (*((struct dma_lli volatile*)(0x39900160)))
#define DMAC1C3SRCADDR      (*((const void* volatile*)(0x39900160)))
#define DMAC1C3DESTADDR     (*((void* volatile*)(0x39900164)))
#define DMAC1C3NEXTLLI      (*((volatile void**)(0x39900168)))
#define DMAC1C3CONTROL      (*((uint32_t volatile*)(0x3990016c)))
#define DMAC1C3CONFIG       (*((uint32_t volatile*)(0x39900170)))
#define DMAC1C4LLI          (*((struct dma_lli volatile*)(0x39900180)))
#define DMAC1C4SRCADDR      (*((const void* volatile*)(0x39900180)))
#define DMAC1C4DESTADDR     (*((void* volatile*)(0x39900184)))
#define DMAC1C4NEXTLLI      (*((const struct dma_lli* volatile*)(0x39900188)))
#define DMAC1C4CONTROL      (*((uint32_t volatile*)(0x3990018c)))
#define DMAC1C4CONFIG       (*((uint32_t volatile*)(0x39900190)))
#define DMAC1C5LLI          (*((struct dma_lli volatile*)(0x399001a0)))
#define DMAC1C5SRCADDR      (*((const void* volatile*)(0x399001a0)))
#define DMAC1C5DESTADDR     (*((void* volatile*)(0x399001a4)))
#define DMAC1C5NEXTLLI      (*((const struct dma_lli* volatile*)(0x399001a8)))
#define DMAC1C5CONTROL      (*((uint32_t volatile*)(0x399001ac)))
#define DMAC1C5CONFIG       (*((uint32_t volatile*)(0x399001b0)))
#define DMAC1C6LLI          (*((struct dma_lli volatile*)(0x399001c0)))
#define DMAC1C6SRCADDR      (*((const void* volatile*)(0x399001c0)))
#define DMAC1C6DESTADDR     (*((void* volatile*)(0x399001c4)))
#define DMAC1C6NEXTLLI      (*((const struct dma_lli* volatile*)(0x399001c8)))
#define DMAC1C6CONTROL      (*((uint32_t volatile*)(0x399001cc)))
#define DMAC1C6CONFIG       (*((uint32_t volatile*)(0x399001d0)))
#define DMAC1C7LLI          (*((struct dma_lli volatile*)(0x399001e0)))
#define DMAC1C7SRCADDR      (*((const void* volatile*)(0x399001e0)))
#define DMAC1C7DESTADDR     (*((void* volatile*)(0x399001e4)))
#define DMAC1C7NEXTLLI      (*((const struct dma_lli* volatile*)(0x399001e8)))
#define DMAC1C7CONTROL      (*((uint32_t volatile*)(0x399001ec)))
#define DMAC1C7CONFIG       (*((uint32_t volatile*)(0x399001f0)))
#define I2SCLKCON           (*((volatile uint32_t*)(0x3CA00000)))
#define I2STXCON            (*((volatile uint32_t*)(0x3CA00004)))
#define I2STXCOM            (*((volatile uint32_t*)(0x3CA00008)))
#define I2STXDB0            (*((volatile uint32_t*)(0x3CA00010)))
#define I2SRXCON            (*((volatile uint32_t*)(0x3CA00030)))
#define I2SRXCOM            (*((volatile uint32_t*)(0x3CA00034)))
#define I2SRXDB             (*((volatile uint32_t*)(0x3CA00038)))
#define I2SSTATUS           (*((volatile uint32_t*)(0x3CA0003C)))
#define I2S40               (*((volatile uint32_t*)(0x3CA00040)))
#define CLKCON0C            (*((volatile uint32_t*)(0x3C50000C)))
#define PDAT(i)             (*((uint32_t volatile*)(0x3cf00004 + ((i) << 5))))


#define LLIMAX (2047)
#define CHUNKSIZE (4096)
#define WATERMARK (1024)
uint32_t dataptr;
uint32_t remaining;
uint32_t irqs;
bool running;
struct dma_lli lli[(CHUNKSIZE - WATERMARK + LLIMAX - 1) / LLIMAX + 1] __attribute__((aligned(16)));


void dmahandler()
{
    irqs++;
    DMAC0INTTCCLR = 1;
    if (!remaining)
    {
        int_dma_set_handler(0, NULL);
        running = false;
        return;
    }
    uint32_t lastsize = MIN(WATERMARK * 4, remaining);
    remaining -= lastsize;
    struct dma_lli* lastlli;
    if (remaining) lastlli = &lli[ARRAYLEN(lli) - 1];
    else lastlli = lli;
    uint32_t chunksize = MIN(CHUNKSIZE * 4 - lastsize, remaining);
    remaining -= chunksize;
    int i = 0;
    while (chunksize)
    {
        uint32_t thislli = MIN(LLIMAX * 4, chunksize);
        chunksize -= thislli;
        lli[i].srcaddr = (void*)dataptr;
        lli[i].dstaddr = (void*)((int)&I2STXDB0);
        lli[i].nextlli = chunksize ? &lli[i + 1] : lastlli;
        lli[i].control = ((chunksize || !remaining) ? 0x75249000 : 0xf5249000) | (thislli / 2);
        dataptr += thislli;
        i++;
    }
    lastlli->srcaddr = (void*)dataptr;
    lastlli->dstaddr = (void*)((int)&I2STXDB0);
    lastlli->nextlli = remaining ? lli : NULL;
    lastlli->control = (remaining ? 0x75249000 : 0xf5249000) | (lastsize / 2);
    dataptr += lastsize;
    clean_dcache();
}

void main()
{
    cputs(3, "Preparing...\n");
    dataptr = 0x08100000;
    remaining = 40135680;
    running = true;
    irqs = 0;
    CLKCON0C &= ~0xffff;
    clockgate_enable(4, true);
    clockgate_enable(39, true);
    I2S40 = 0x110;
    PDAT(3) &= ~8;
    sleep(10000);
    PDAT(3) |= 8;
    i2c_sendbyte(0, 0x94, 0x00, 0x99);
    i2c_sendbyte(0, 0x94, 0x2e, 0x30);
    i2c_sendbyte(0, 0x94, 0x32, 0x07);
    i2c_sendbyte(0, 0x94, 0x33, 0xff);
    i2c_sendbyte(0, 0x94, 0x34, 0xf8);
    i2c_sendbyte(0, 0x94, 0x35, 0xdc);
    i2c_sendbyte(0, 0x94, 0x36, 0xfc);
    i2c_sendbyte(0, 0x94, 0x37, 0xac);
    i2c_sendbyte(0, 0x94, 0x3a, 0xf8);
    i2c_sendbyte(0, 0x94, 0x3c, 0xd3);
    i2c_sendbyte(0, 0x94, 0x3d, 0x23);
    i2c_sendbyte(0, 0x94, 0x3e, 0x81);
    i2c_sendbyte(0, 0x94, 0x3f, 0x46);
    i2c_sendbyte(0, 0x94, 0x00, 0x00);
    i2c_sendbyte(0, 0x94, 0x03, 0xaa);
    i2c_sendbyte(0, 0x94, 0x04, 0x2e);
    i2c_sendbyte(0, 0x94, 0x05, 0x0b);
    i2c_sendbyte(0, 0x94, 0x07, 0x18);
    i2c_sendbyte(0, 0x94, 0x02, 0x01);
    i2c_sendbyte(0, 0x94, 0x0f, 0x80);
    i2c_sendbyte(0, 0x94, 0x0b, 0x00);
    i2c_sendbyte(0, 0x94, 0x0c, 0x00);
    i2c_sendbyte(0, 0x94, 0x1a, 0x80);
    i2c_sendbyte(0, 0x94, 0x1b, 0x80);
    i2c_sendbyte(0, 0x94, 0x1c, 0x80);
    i2c_sendbyte(0, 0x94, 0x1d, 0x80);
    i2c_sendbyte(0, 0x94, 0x02, 0x00);
    sleep(75000);
    i2c_sendbyte(0, 0x94, 0x1a, 0x00);
    i2c_sendbyte(0, 0x94, 0x1b, 0x00);
    i2c_sendbyte(0, 0x94, 0x1c, 0x00);
    i2c_sendbyte(0, 0x94, 0x1d, 0x00);
    i2c_sendbyte(0, 0x94, 0x06, 0x00);
    I2STXCON = 0xb100059;
    I2SCLKCON = 1;
    I2STXCOM = 0xe;
    int_dma_set_handler(0, dmahandler);
    dmahandler();
    DMAC0CONFIG |= 4;
    DMAC0C0LLI.srcaddr = lli[0].srcaddr;
    DMAC0C0LLI.dstaddr = lli[0].dstaddr;
    DMAC0C0LLI.nextlli = lli[0].nextlli;
    DMAC0C0LLI.control = lli[0].control;
    DMAC0C0CONFIG = 0x8a81;
    cputs(3, "Playing...\n");
}