//Initialize I2S subsystem for DMA circular buffer use void ICACHE_FLASH_ATTR i2sInit() { int x, y; underrunCnt=0; //First, take care of the DMA buffers. for (y=0; y<I2SDMABUFCNT; y++) { //Allocate memory for this DMA sample buffer. i2sBuf[y]=malloc(I2SDMABUFLEN*4); //Clear sample buffer. We don't want noise. for (x=0; x<I2SDMABUFLEN; x++) { i2sBuf[y][x]=0; } } //Reset DMA SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST|SLC_TXLINK_RST); CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST|SLC_TXLINK_RST); //Clear DMA int flags SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); //Enable and configure DMA CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE); CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE); //Initialize DMA buffer descriptors in such a way that they will form a circular //buffer. for (x=0; x<I2SDMABUFCNT; x++) { i2sBufDesc[x].owner=1; i2sBufDesc[x].eof=1; i2sBufDesc[x].sub_sof=0; i2sBufDesc[x].datalen=I2SDMABUFLEN*4; i2sBufDesc[x].blocksize=I2SDMABUFLEN*4; i2sBufDesc[x].buf_ptr=(uint32_t)&i2sBuf[x][0]; i2sBufDesc[x].unused=0; i2sBufDesc[x].next_link_ptr=(int)((x<(I2SDMABUFCNT-1))?(&i2sBufDesc[x+1]):(&i2sBufDesc[0])); } //Feed dma the 1st buffer desc addr //To send data to the I2S subsystem, counter-intuitively we use the RXLINK part, not the TXLINK as you might //expect. The TXLINK part still needs a valid DMA descriptor, even if it's unused: the DMA engine will throw //an error at us otherwise. Just feed it any random descriptor. CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDesc[1]) & SLC_TXLINK_DESCADDR_MASK); //any random desc is OK, we don't use TX but it needs something valid CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDesc[0]) & SLC_RXLINK_DESCADDR_MASK); //Attach the DMA interrupt _xt_isr_attach(ETS_SLC_INUM, (_xt_isr)slc_isr, NULL); //Enable DMA operation intr WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA); //clear any interrupt flags that are set WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff); ///enable DMA intr in cpu _xt_isr_unmask(1<<ETS_SLC_INUM); //We use a queue to keep track of the DMA buffers that are empty. The ISR will push buffers to the back of the queue, //the mp3 decode will pull them from the front and fill them. For ease, the queue will contain *pointers* to the DMA //buffers, not the data itself. The queue depth is one smaller than the amount of buffers we have, because there's //always a buffer that is being used by the DMA subsystem *right now* and we don't want to be able to write to that //simultaneously. dmaQueue=xQueueCreate(I2SDMABUFCNT-1, sizeof(int*)); //Start transmission SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START); SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); //---- //Init pins to i2s functions PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS); #ifndef USE_ESP01_MODULE PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK); #else GPIO_AS_INPUT(1<<15); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); #endif //Enable clock to i2s subsystem i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1); //Reset I2S subsystem CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); //Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only) CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S)); //Enable DMA in i2s subsystem SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN); //tx/rx binaureal CLEAR_PERI_REG_MASK(I2SCONF_CHAN, (I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)|(I2S_RX_CHAN_MOD<<I2S_RX_CHAN_MOD_S)); //Clear int SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR| I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR| I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); //trans master&rece slave,MSB shift,right_first,msb right CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD| (I2S_BITS_MOD<<I2S_BITS_MOD_S)| (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)| (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S)); SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD| I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT| ((16&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| ((7&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)); //No idea if ints are needed... //clear int SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR| I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_TX_REMPTY_INT_CLR|I2S_I2S_TX_WFULL_INT_CLR| I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); //enable int SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_TX_REMPTY_INT_ENA|I2S_I2S_TX_WFULL_INT_ENA| I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_TX_PUT_DATA_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA); //Start transmission SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START); }
void ws2812_dma(sdio_queue_t *i2s_pixels_queue) { // Reset DMA SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST); //|SLC_TXLINK_RST); CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST); //|SLC_TXLINK_RST); // Clear DMA int flags SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); // Enable and configure DMA CLEAR_PERI_REG_MASK(SLC_CONF0,(SLC_MODE<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE); CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE); // configure DMA descriptor CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)i2s_pixels_queue) & SLC_RXLINK_DESCADDR_MASK); #if WS2812_USE_INTERRUPT == 1 // Attach the DMA interrupt ets_isr_attach(ETS_SLC_INUM, (int_handler_t)ws2812_isr , (void *)0); //Enable DMA operation intr // WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA); //clear any interrupt flags that are set WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff); ///enable DMA intr in cpu ets_isr_unmask(1<<ETS_SLC_INUM); #endif //Start transmission SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); //Init pins to i2s functions PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA); //Enable clock to i2s subsystem i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1); //Reset I2S subsystem CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); //Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only) CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S)); //Enable DMA in i2s subsystem SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN); //trans master&rece slave,MSB shift,right_first,msb right CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD| (I2S_BITS_MOD<<I2S_BITS_MOD_S)| (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)| (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S)); SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD| I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT| (((WS_I2S_BCK-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| (((WS_I2S_DIV-1)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)); #if WS2812_USE_INTERRUPT == 1 //clear int SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); //enable int SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA); #endif //Start transmission SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START); }
//Initialize I2S subsystem for DMA circular buffer use void ICACHE_FLASH_ATTR ws2812_init() { int x, y; //Reset DMA SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST); CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST); //Clear DMA int flags SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); //Enable and configure DMA CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE); CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE); i2sBufDescOut.owner = 1; i2sBufDescOut.eof = 1; i2sBufDescOut.sub_sof = 0; i2sBufDescOut.datalen = WS_BLOCKSIZE; //Size (in bytes) i2sBufDescOut.blocksize = WS_BLOCKSIZE; //Size (in bytes) i2sBufDescOut.buf_ptr=(uint32_t)&i2sBlock[0]; i2sBufDescOut.unused=0; i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer. i2sBufDescZeroes.owner = 1; i2sBufDescZeroes.eof = 1; i2sBufDescZeroes.sub_sof = 0; i2sBufDescZeroes.datalen = 32; i2sBufDescZeroes.blocksize = 32; i2sBufDescZeroes.buf_ptr=(uint32_t)&i2sZeroes[0]; i2sBufDescZeroes.unused=0; i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut; for( x = 0; x < 32; x++ ) { i2sZeroes[x] = 0x00; } for( x = 0; x < WS_BLOCKSIZE/4; x++ ) { i2sBlock[x] = 0x00000000;//(x == 0 || x == 999)?0xaa:0x00; /* uint16_t * tt = (uint16_t*)&i2sBlock[x]; (*(tt+0)) = 0xA0F0; (*(tt+1)) = 0xC0E0;*/ } // CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK); // SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDescZeroes) & SLC_TXLINK_DESCADDR_MASK); //any random desc is OK, we don't use TX but it needs something valid CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK); #ifdef USE_2812_INTERRUPTS //Attach the DMA interrupt ets_isr_attach(ETS_SLC_INUM, slc_isr); //Enable DMA operation intr WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA); //clear any interrupt flags that are set WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff); ///enable DMA intr in cpu ets_isr_unmask(1<<ETS_SLC_INUM); #endif //Start transmission // SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START); SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); //---- //Init pins to i2s functions PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA); // PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS); // PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK); //Enable clock to i2s subsystem i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1); //Reset I2S subsystem CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK); //Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only) CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S)); //Enable DMA in i2s subsystem SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN); //tx/rx binaureal // CLEAR_PERI_REG_MASK(I2SCONF_CHAN, (I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)|(I2S_RX_CHAN_MOD<<I2S_RX_CHAN_MOD_S)); #ifdef USE_2812_INTERRUPTS //Clear int SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); #endif //trans master&rece slave,MSB shift,right_first,msb right CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD| (I2S_BITS_MOD<<I2S_BITS_MOD_S)| (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)| (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S)); SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD| I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT| (((WS_I2S_BCK-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| (((WS_I2S_DIV-1)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)); //No idea if ints are needed... //clear int SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); //enable int SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA); //Start transmission SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START); }
C3WireOutput::C3WireOutput( unsigned int nLength, unsigned int nBck, unsigned int nDiv, I3WireEncoder *pEncoder) : COutput(nLength) { // Final clock frequency is: // 160 / MAX(2, nBck) / MAX(2, nDiv) // // Example: // For the WS2811 800khz clock, // one bit should take 1.25usec or 1250nanosec // 1sec/1250nanosec = 800khz // Assuming we need 4 bits to encode each bit, we'd need a clock of // 4 * 800khz = 3.2mhz // So we need to find 160 / nBck / nDiv = 3.2 // 160 / 3.2 = 50 // So we need nBck * nDiv = 50, where nBck>=2 and nDiv>=2 // We should use 5 and 10, or 2 and 25, etc m_pEncoder = pEncoder; m_nBufferLength = m_pEncoder->getMaxLength(m_nLength); m_pBuffer = new uint32_t[m_nBufferLength]; memset(&m_qBuffer, 0, sizeof(m_qBuffer)); memset(&m_qZeroes, 0, sizeof(m_qZeroes)); memset(m_pZeroes, 0, sizeof(m_pZeroes)); // DMA buffer structure. // Buffer points to actual data, zeroes points to zeroes // Both buffer and zeroes point to zeroes as "next buffer" m_qBuffer.owner = m_qZeroes.owner = 1; m_qBuffer.eof = m_qZeroes.eof = 1; m_qBuffer.sub_sof = m_qZeroes.sub_sof = 0; m_qBuffer.datalen = m_qBuffer.blocksize = m_nBufferLength * sizeof(uint32_t); m_qZeroes.datalen = m_qZeroes.blocksize = sizeof(m_pZeroes); m_qBuffer.buf_ptr = (uint32_t)m_pBuffer; m_qZeroes.buf_ptr = (uint32_t)m_pZeroes; m_qBuffer.unused = m_qZeroes.unused = 0; m_qBuffer.next_link_ptr = m_qZeroes.next_link_ptr = (uint32_t)&m_qZeroes; // Pin func select PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA); // We don't really care about anything other than data, // But you might want to un-comment these while debugging. // PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS); // PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK); //Reset DMA SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST); CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST); //Clear DMA int flags SET_PERI_REG_MASK(SLC_INT_CLR, 0xFFFFFFFF); CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xFFFFFFFF); //Enable and configure DMA CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE << SLC_MODE_S)); SET_PERI_REG_MASK(SLC_CONF0, (1<<SLC_MODE_S)); SET_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE); CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE|SLC_RX_FILL_MODE); CLEAR_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32_t)&m_qZeroes) & SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); //Clock provider? i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1); // Reset I2S subsystem CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_RESET_MASK); SET_PERI_REG_MASK(I2SCONF, I2S_I2S_RESET_MASK); CLEAR_PERI_REG_MASK(I2SCONF, I2S_I2S_RESET_MASK); CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S)); SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN); //Trans master & rece slave? CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD| (I2S_BITS_MOD<<I2S_BITS_MOD_S)| (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)| (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S)); SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD| I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT| (((nBck)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| (((nDiv)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)); //No idea if ints are needed... //clear int SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR); //enable int SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA); //Start transmission SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START); }