Plays USB Audio packets through external DAC (Cirrus Logic CS4344). Simple demo code, don't expect a sophisticated I2S library. HW setup: mbed DIP 5 (I2STX_SDA) -> DAC SDIN (Serial Audio Data Input) mbed DIP 6 (I2STX_WS) -> DAC LRCK (Left Right Clock) mbed DIP 7 (I2STX_CLK) -> DAC SCLK (External Serial Clock Input) mbed DIP 30 (I2SRX_CLK) -> DAC MCLK (Master Clock) also needed an extra USB connector wired to mbed. Does not work with built-in USB. Code needs a bit of clean up.

Dependencies:   mbed

Revision:
0:bf9e7b99dda5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/I2S.cpp	Mon Apr 16 08:28:42 2012 +0000
@@ -0,0 +1,145 @@
+#include "I2S.h"
+#include "MODDMA.h"
+
+
+volatile uint32_t counter=0;
+
+DigitalOut led3(LED3);
+
+//Serial *global_out;
+MODDMA dma;
+MODDMA_Config *dmaconfig;
+
+void TC0_callback(void);
+void TC1_callback(void);
+void TC2_callback(void);
+
+#define BUFFER_SIZE 2048
+
+int16_t buffer[BUFFER_SIZE];
+
+int16_t transferSize;
+
+int16_t *bufferStart, *nextToPlay;
+volatile int16_t playing = 0;
+
+volatile int16_t moreToPlay=0;
+
+void setup(Serial *out) {
+
+global_out = out;
+
+    bufferStart = nextToPlay = (int16_t *)buffer;
+
+    LPC_SC->PCONP |= 1 <<27; // Enable I2S
+    LPC_SC->PCLKSEL1 |= 1 << 22; // Set Clock to CCLK
+    // Reset i2s
+    LPC_I2S->I2SDAO = (1 << 4);
+    LPC_I2S->I2SDAO = 0;
+
+    
+    
+    LPC_I2S->I2SDAO = 1 /* Number of bytes 16bit */ | 0xF << 6 /* Word select half perion - 1 */;// | 1 << 3 /* Stop bit */;
+    LPC_I2S->I2SDAI = 1 /* Number of bytes 16bit */ | 0xF << 6 /* Word select half perion - 1 */;// | 1 << 3 /* Stop bit */;
+    
+    
+    LPC_PINCON->PINSEL0 |= 01 << 14 /* I2STX_CLK */ | 01 << 16 /* I2STX_WS */ | 01 << 18 /* I2STX_SDA */;
+    LPC_PINCON->PINSEL0 |= 01 << 8 /* I2SRX_CLK */ | 01 << 10 /* I2SRX_WS */ | 01 << 12 /* I2SRX_SDA */;
+
+    // Set all to neither pull-up, nor pull-down
+    LPC_PINCON->PINMODE0 |= 2 << 14 /* I2STX_CLK */ | 2 << 16 /* I2STX_WS */ | 2 << 18 /* I2STX_SDA */;
+    LPC_PINCON->PINMODE0 |= 2 << 8 /* I2SRX_CLK */ | 2 << 10 /* I2SRX_WS */ | 2 << 12 /* I2SRX_SDA */;
+    
+    
+    // Cirrus Logic CS4344 specific frequency settings
+    LPC_I2S->I2STXRATE = 125 /* Y_divider */ | 4 << 8 /* X_divider */;
+    LPC_I2S->I2SRXRATE = 125 /* Y_divider */ | 32 << 8 /* X_divider */;
+    
+    int rxbitrate = 1;
+    LPC_I2S->I2STXBITRATE = 1;
+    LPC_I2S->I2SRXBITRATE = rxbitrate;
+    
+
+    LPC_I2S->I2STXMODE  = (0 << 0) | (1 << 3);
+    LPC_I2S->I2SRXMODE  = (0 << 0) | (1 << 3);
+  
+  
+    // Start trasnmit    
+    LPC_I2S->I2SDAO &= (~(1 << 3));
+    LPC_I2S->I2SDAI &= (~(1 << 3));
+
+    LPC_I2S->I2SDMA1 = (1 << 1) /* Enable transit */ | (0 << 16) /* Transmit FIFO level */;
+
+
+    out->printf("I2S Setup complete\n");
+        
+    dmaconfig = new MODDMA_Config;
+    dmaconfig
+     ->channelNum    ( MODDMA::Channel_0 )
+//     ->srcMemAddr    ( (uint32_t) &buffer1 )
+     ->dstMemAddr    ( 0 )
+     //->transferSize  ( 2500 )
+     ->transferType  ( MODDMA::m2p )
+     ->transferWidth ( 1 )
+     ->srcConn       ( 0 )
+     ->dstConn       ( MODDMA::I2S_Channel_0 )
+     ->dmaLLI        ( 0 )
+     ->attach_tc     ( &TC1_callback )
+    ;
+
+    out->printf("DMA Setup complete\n");
+
+}
+
+
+void play(int16_t *buf,int16_t length) {
+
+
+    moreToPlay = 1;
+    
+    if (nextToPlay - bufferStart + length >= BUFFER_SIZE) {
+        nextToPlay = bufferStart;
+    }  
+    
+    memcpy(nextToPlay,buf,length*sizeof(int16_t));
+    
+    transferSize=length;
+    
+    
+    // Wait for end of playing previous packet
+    while (playing) {};
+    
+    playing = 1;
+    moreToPlay = 0;
+
+    dmaconfig->srcMemAddr    ( (uint32_t) nextToPlay );
+    dmaconfig->transferSize  ( length / 2);
+    nextToPlay+=length*sizeof(int16_t);
+    
+
+    dma.Prepare(dmaconfig);
+    
+    
+}
+
+
+
+void TC1_callback(void) {
+    
+       // Get configuration pointer.
+    MODDMA_Config *config = dma.getConfig();
+    
+    // Finish the DMA cycle by shutting down the channel.
+    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+   
+
+    // Clear DMA IRQ flags.
+    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
+    
+    playing = 0;
+
+    if (!moreToPlay) {
+        LPC_I2S->I2STXFIFO = 0x0;
+        led3 = !led3;
+    }
+}