#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");
}