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.
I2S.cpp
00001 #include "I2S.h" 00002 #include "MODDMA.h" 00003 00004 00005 volatile uint32_t counter=0; 00006 00007 DigitalOut led3(LED3); 00008 00009 //Serial *global_out; 00010 MODDMA dma; 00011 MODDMA_Config *dmaconfig; 00012 00013 void TC0_callback(void); 00014 void TC1_callback(void); 00015 void TC2_callback(void); 00016 00017 #define BUFFER_SIZE 2048 00018 00019 int16_t buffer[BUFFER_SIZE]; 00020 00021 int16_t transferSize; 00022 00023 int16_t *bufferStart, *nextToPlay; 00024 volatile int16_t playing = 0; 00025 00026 volatile int16_t moreToPlay=0; 00027 00028 void setup(Serial *out) { 00029 00030 global_out = out; 00031 00032 bufferStart = nextToPlay = (int16_t *)buffer; 00033 00034 LPC_SC->PCONP |= 1 <<27; // Enable I2S 00035 LPC_SC->PCLKSEL1 |= 1 << 22; // Set Clock to CCLK 00036 // Reset i2s 00037 LPC_I2S->I2SDAO = (1 << 4); 00038 LPC_I2S->I2SDAO = 0; 00039 00040 00041 00042 LPC_I2S->I2SDAO = 1 /* Number of bytes 16bit */ | 0xF << 6 /* Word select half perion - 1 */;// | 1 << 3 /* Stop bit */; 00043 LPC_I2S->I2SDAI = 1 /* Number of bytes 16bit */ | 0xF << 6 /* Word select half perion - 1 */;// | 1 << 3 /* Stop bit */; 00044 00045 00046 LPC_PINCON->PINSEL0 |= 01 << 14 /* I2STX_CLK */ | 01 << 16 /* I2STX_WS */ | 01 << 18 /* I2STX_SDA */; 00047 LPC_PINCON->PINSEL0 |= 01 << 8 /* I2SRX_CLK */ | 01 << 10 /* I2SRX_WS */ | 01 << 12 /* I2SRX_SDA */; 00048 00049 // Set all to neither pull-up, nor pull-down 00050 LPC_PINCON->PINMODE0 |= 2 << 14 /* I2STX_CLK */ | 2 << 16 /* I2STX_WS */ | 2 << 18 /* I2STX_SDA */; 00051 LPC_PINCON->PINMODE0 |= 2 << 8 /* I2SRX_CLK */ | 2 << 10 /* I2SRX_WS */ | 2 << 12 /* I2SRX_SDA */; 00052 00053 00054 // Cirrus Logic CS4344 specific frequency settings 00055 LPC_I2S->I2STXRATE = 125 /* Y_divider */ | 4 << 8 /* X_divider */; 00056 LPC_I2S->I2SRXRATE = 125 /* Y_divider */ | 32 << 8 /* X_divider */; 00057 00058 int rxbitrate = 1; 00059 LPC_I2S->I2STXBITRATE = 1; 00060 LPC_I2S->I2SRXBITRATE = rxbitrate; 00061 00062 00063 LPC_I2S->I2STXMODE = (0 << 0) | (1 << 3); 00064 LPC_I2S->I2SRXMODE = (0 << 0) | (1 << 3); 00065 00066 00067 // Start trasnmit 00068 LPC_I2S->I2SDAO &= (~(1 << 3)); 00069 LPC_I2S->I2SDAI &= (~(1 << 3)); 00070 00071 LPC_I2S->I2SDMA1 = (1 << 1) /* Enable transit */ | (0 << 16) /* Transmit FIFO level */; 00072 00073 00074 out->printf("I2S Setup complete\n"); 00075 00076 dmaconfig = new MODDMA_Config; 00077 dmaconfig 00078 ->channelNum ( MODDMA::Channel_0 ) 00079 // ->srcMemAddr ( (uint32_t) &buffer1 ) 00080 ->dstMemAddr ( 0 ) 00081 //->transferSize ( 2500 ) 00082 ->transferType ( MODDMA::m2p ) 00083 ->transferWidth ( 1 ) 00084 ->srcConn ( 0 ) 00085 ->dstConn ( MODDMA::I2S_Channel_0 ) 00086 ->dmaLLI ( 0 ) 00087 ->attach_tc ( &TC1_callback ) 00088 ; 00089 00090 out->printf("DMA Setup complete\n"); 00091 00092 } 00093 00094 00095 void play(int16_t *buf,int16_t length) { 00096 00097 00098 moreToPlay = 1; 00099 00100 if (nextToPlay - bufferStart + length >= BUFFER_SIZE) { 00101 nextToPlay = bufferStart; 00102 } 00103 00104 memcpy(nextToPlay,buf,length*sizeof(int16_t)); 00105 00106 transferSize=length; 00107 00108 00109 // Wait for end of playing previous packet 00110 while (playing) {}; 00111 00112 playing = 1; 00113 moreToPlay = 0; 00114 00115 dmaconfig->srcMemAddr ( (uint32_t) nextToPlay ); 00116 dmaconfig->transferSize ( length / 2); 00117 nextToPlay+=length*sizeof(int16_t); 00118 00119 00120 dma.Prepare(dmaconfig); 00121 00122 00123 } 00124 00125 00126 00127 void TC1_callback(void) { 00128 00129 // Get configuration pointer. 00130 MODDMA_Config *config = dma.getConfig(); 00131 00132 // Finish the DMA cycle by shutting down the channel. 00133 dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); 00134 00135 00136 // Clear DMA IRQ flags. 00137 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 00138 00139 playing = 0; 00140 00141 if (!moreToPlay) { 00142 LPC_I2S->I2STXFIFO = 0x0; 00143 led3 = !led3; 00144 } 00145 }
Generated on Sat Aug 27 2022 10:07:19 by 1.7.2