1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

add I2S core

This commit is contained in:
John Doe 2015-06-22 15:47:22 +03:00
parent ca8ebdbb97
commit 3a525e47cf
3 changed files with 534 additions and 3 deletions

View File

@ -0,0 +1,223 @@
/*
si2c.c - Software I2C library for esp8266
Code taken and reworked from espessif's I2S example
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h"
#include "osapi.h"
#include "ets_sys.h"
#include "i2s_reg.h"
#include "i2s.h"
extern void ets_wdt_enable(void);
extern void ets_wdt_disable(void);
#define SLC_BUF_CNT (8) //Number of buffers in the I2S circular buffer
#define SLC_BUF_LEN (64) //Length of one buffer, in 32-bit words.
//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.
struct slc_queue_item {
uint32 blocksize:12;
uint32 datalen:12;
uint32 unused:5;
uint32 sub_sof:1;
uint32 eof:1;
uint32 owner:1;
uint32 buf_ptr;
uint32 next_link_ptr;
};
static uint32_t i2s_slc_queue[SLC_BUF_CNT-1];
static uint8_t i2s_slc_queue_len;
static uint32_t *i2s_slc_buf_pntr[SLC_BUF_CNT]; //Pointer to the I2S DMA buffer data
static struct slc_queue_item i2s_slc_items[SLC_BUF_CNT]; //I2S DMA buffer descriptors
uint32_t ICACHE_FLASH_ATTR i2s_slc_queue_next_item(){ //pop the top off the queue
uint8_t i;
uint32_t item = i2s_slc_queue[0];
i2s_slc_queue_len--;
for(i=0;i<i2s_slc_queue_len;i++)
i2s_slc_queue[i] = i2s_slc_queue[i+1];
return item;
}
//This routine is called as soon as the DMA routine has something to tell us. All we
//handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
//descriptor has the 'EOF' field set to 1.
void ICACHE_FLASH_ATTR i2s_slc_isr(void) {
uint32_t slc_intr_status = SLCIS;
SLCIC = 0xFFFFFFFF;
if (slc_intr_status & SLCIRXEOF) {
ETS_SLC_INTR_DISABLE();
struct slc_queue_item *finished_item = (struct slc_queue_item*)SLCRXEDA;
if (i2s_slc_queue_len >= SLC_BUF_CNT-1) { //All buffers are empty. This means we have an underflow
i2s_slc_queue_next_item(); //free space for finished_item
}
i2s_slc_queue[i2s_slc_queue_len++] = finished_item->buf_ptr;
ETS_SLC_INTR_ENABLE();
}
}
void ICACHE_FLASH_ATTR i2s_slc_begin(){
i2s_slc_queue_len = 0;
int x, y;
for (x=0; x<SLC_BUF_CNT; x++) {
i2s_slc_buf_pntr[x] = malloc(SLC_BUF_LEN*4);
for (y=0; y<SLC_BUF_LEN; y++) i2s_slc_buf_pntr[x][y] = 0;
i2s_slc_items[x].unused = 0;
i2s_slc_items[x].owner = 1;
i2s_slc_items[x].eof = 1;
i2s_slc_items[x].sub_sof = 0;
i2s_slc_items[x].datalen = SLC_BUF_LEN*4;
i2s_slc_items[x].blocksize = SLC_BUF_LEN*4;
i2s_slc_items[x].buf_ptr = (uint32_t)&i2s_slc_buf_pntr[x][0];
i2s_slc_items[x].next_link_ptr = (int)((x<(SLC_BUF_CNT-1))?(&i2s_slc_items[x+1]):(&i2s_slc_items[0]));
}
ETS_SLC_INTR_DISABLE();
SLCC0 |= SLCRXLR | SLCTXLR;
SLCC0 &= ~(SLCRXLR | SLCTXLR);
SLCIC = 0xFFFFFFFF;
//Configure DMA
SLCC0 &= ~(SLCMM << SLCM); //clear DMA MODE
SLCC0 |= (1 << SLCM); //set DMA MODE to 1
SLCRXDC |= SLCBINR | SLCBTNR; //enable INFOR_NO_REPLACE and TOKEN_NO_REPLACE
SLCRXDC &= ~(SLCBRXFE | SLCBRXEM | SLCBRXFM); //disable RX_FILL, RX_EOF_MODE and RX_FILL_MODE
//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.
SLCTXL &= ~(SLCTXLAM << SLCTXLA); // clear TX descriptor address
SLCTXL |= (uint32)&i2s_slc_items[1] << SLCTXLA; //set TX descriptor address. any random desc is OK, we don't use TX but it needs to be valid
SLCRXL &= ~(SLCRXLAM << SLCRXLA); // clear RX descriptor address
SLCRXL |= (uint32)&i2s_slc_items[0] << SLCRXLA; //set RX descriptor address
ETS_SLC_INTR_ATTACH(i2s_slc_isr, NULL);
SLCIE = SLCIRXEOF; //Enable only for RX EOF interrupt
ETS_SLC_INTR_ENABLE();
//Start transmission
SLCTXL |= SLCTXLS;
SLCRXL |= SLCRXLS;
}
void ICACHE_FLASH_ATTR i2s_slc_end(){
ETS_SLC_INTR_DISABLE();
SLCIC = 0xFFFFFFFF;
SLCIE = 0;
SLCTXL &= ~(SLCTXLAM << SLCTXLA); // clear TX descriptor address
SLCRXL &= ~(SLCRXLAM << SLCRXLA); // clear RX descriptor address
}
//This routine pushes a single, 32-bit sample to the I2S buffers. Call this at (on average)
//at least the current sample rate. You can also call it quicker: it will suspend the calling
//thread if the buffer is full and resume when there's room again.
static uint32_t *i2s_curr_slc_buf=NULL;
static int i2s_curr_slc_buf_pos=0;
bool ICACHE_FLASH_ATTR i2s_write_sample(uint32_t sample) {
if (i2s_curr_slc_buf_pos==SLC_BUF_LEN || i2s_curr_slc_buf==NULL) {
if(i2s_slc_queue_len == 0){
while(1){
if(i2s_slc_queue_len > 0){
break;
} else {
ets_wdt_disable();
ets_wdt_enable();
}
}
}
ETS_SLC_INTR_DISABLE();
i2s_curr_slc_buf = (uint32_t *)i2s_slc_queue_next_item();
ETS_SLC_INTR_ENABLE();
i2s_curr_slc_buf_pos=0;
}
i2s_curr_slc_buf[i2s_curr_slc_buf_pos++]=sample;
return true;
}
bool ICACHE_FLASH_ATTR i2s_write_lr(int16_t left, int16_t right){
int sample = right & 0xFFFF;
sample = sample << 16;
sample |= left & 0xFFFF;
return i2s_write_sample(sample);
}
// END DMA
// =========
// START I2S
static uint32_t _i2s_sample_rate;
void ICACHE_FLASH_ATTR i2s_set_rate(uint32_t rate){ //Rate in HZ
if(rate == _i2s_sample_rate) return;
_i2s_sample_rate = rate;
uint32_t i2s_clock_div = (I2SBASEFREQ/(_i2s_sample_rate*32)) & I2SCDM;
uint8_t i2s_bck_div = (I2SBASEFREQ/(_i2s_sample_rate*i2s_clock_div*2)) & I2SBDM;
//os_printf("Rate %u Div %u Bck %u Frq %u\n", _i2s_sample_rate, i2s_clock_div, i2s_bck_div, I2SBASEFREQ/(i2s_clock_div*i2s_bck_div*2));
//!trans master, !bits mod, rece slave mod, rece msb shift, right first, msb right
I2SC &= ~(I2STSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD));
I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | ((i2s_bck_div-1) << I2SBD) | ((i2s_clock_div-1) << I2SCD);
}
void ICACHE_FLASH_ATTR i2s_begin(){
_i2s_sample_rate = 0;
i2s_slc_begin();
pinMode(2, FUNCTION_1); //I2SO_WS (LRCK)
pinMode(3, FUNCTION_1); //I2SO_DATA (SDIN)
pinMode(15, FUNCTION_1); //I2SO_BCK (SCLK)
I2S_CLK_ENABLE();
I2SIC = 0x3F;
I2SIE = 0;
//Reset I2S
I2SC &= ~(I2SRST);
I2SC |= I2SRST;
I2SC &= ~(I2SRST);
I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM) | (I2SRXFMM << I2SRXFM)); //Set RX/TX FIFO_MOD=0 and disable DMA (FIFO only)
I2SFC |= I2SDE; //Enable DMA
I2SCC &= ~((I2STXCMM << I2STXCM) | (I2SRXCMM << I2SRXCM)); //Set RX/TX CHAN_MOD=0
i2s_set_rate(44100);
I2SC |= I2STXS; //Start transmission
}
void ICACHE_FLASH_ATTR i2s_end(){
i2s_slc_end();
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(15, INPUT);
}

View File

@ -27,6 +27,11 @@
#define ESP8266_DREG(addr) *((volatile uint32_t *)(0x3FF00000+(addr))) #define ESP8266_DREG(addr) *((volatile uint32_t *)(0x3FF00000+(addr)))
#define ESP8266_CLOCK 80000000UL #define ESP8266_CLOCK 80000000UL
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) rom_i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb)
#define i2c_readReg_Mask_def(block, reg_add) i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
#define i2c_writeReg_Mask_def(block, reg_add, indata) i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
//CPU Register //CPU Register
#define CPU2X ESP8266_DREG(0x14) //when bit 0 is set, F_CPU = 160MHz #define CPU2X ESP8266_DREG(0x14) //when bit 0 is set, F_CPU = 160MHz
@ -77,9 +82,6 @@
#define GPCD 2 //DRIVER 0:normal,1:open drain #define GPCD 2 //DRIVER 0:normal,1:open drain
#define GPCS 0 //SOURCE 0:GPIO_DATA,1:SigmaDelta #define GPCS 0 //SOURCE 0:GPIO_DATA,1:SigmaDelta
extern uint8_t esp8266_gpioToFn[16];
#define GPF(p) ESP8266_REG(0x800 + esp8266_gpioToFn[(p & 0xF)])
#define GPMUX ESP8266_REG(0x800) #define GPMUX ESP8266_REG(0x800)
//GPIO (0-15) PIN Function Registers //GPIO (0-15) PIN Function Registers
#define GPF0 ESP8266_REG(0x834) #define GPF0 ESP8266_REG(0x834)
@ -99,6 +101,9 @@ extern uint8_t esp8266_gpioToFn[16];
#define GPF14 ESP8266_REG(0x80C) #define GPF14 ESP8266_REG(0x80C)
#define GPF15 ESP8266_REG(0x810) #define GPF15 ESP8266_REG(0x810)
extern uint8_t esp8266_gpioToFn[16];
#define GPF(p) ESP8266_REG(0x800 + esp8266_gpioToFn[(p & 0xF)])
//GPIO (0-15) PIN Function Bits //GPIO (0-15) PIN Function Bits
#define GPFSOE 0 //Sleep OE #define GPFSOE 0 //Sleep OE
#define GPFSS 1 //Sleep Sel #define GPFSS 1 //Sleep Sel
@ -579,4 +584,254 @@ extern uint8_t esp8266_gpioToFn[16];
#define SPIE2IHEN 0x3 //SPI_INT_HOLD_ENA #define SPIE2IHEN 0x3 //SPI_INT_HOLD_ENA
#define SPIE2IHEN_S 0 //SPI_INT_HOLD_ENA_S #define SPIE2IHEN_S 0 //SPI_INT_HOLD_ENA_S
//SLC (DMA) Registers
#define SLCC0 ESP8266_REG(0xB00) //SLC_CONF0
#define SLCIR ESP8266_REG(0xB04) //SLC_INT_RAW
#define SLCIS ESP8266_REG(0xB08) //SLC_INT_STATUS
#define SLCIE ESP8266_REG(0xB0C) //SLC_INT_ENA
#define SLCIC ESP8266_REG(0xB10) //SLC_INT_CLR
#define SLCRXS ESP8266_REG(0xB14) //SLC_RX_STATUS
#define SLCRXP ESP8266_REG(0xB18) //SLC_RX_FIFO_PUSH
#define SLCTXS ESP8266_REG(0xB1C) //SLC_TX_STATUS
#define SLCTXP ESP8266_REG(0xB20) //SLC_TX_FIFO_POP
#define SLCRXL ESP8266_REG(0xB24) //SLC_RX_LINK
#define SLCTXL ESP8266_REG(0xB28) //SLC_TX_LINK
#define SLCIVTH ESP8266_REG(0xB2C) //SLC_INTVEC_TOHOST
#define SLCT0 ESP8266_REG(0xB30) //SLC_TOKEN0
#define SLCT1 ESP8266_REG(0xB34) //SLC_TOKEN1
#define SLCC1 ESP8266_REG(0xB38) //SLC_CONF1
#define SLCS0 ESP8266_REG(0xB3C) //SLC_STATE0
#define SLCS1 ESP8266_REG(0xB40) //SLC_STATE1
#define SLCBC ESP8266_REG(0xB44) //SLC_BRIDGE_CONF
#define SLCRXEDA ESP8266_REG(0xB48) //SLC_RX_EOF_DES_ADDR
#define SLCTXEDA ESP8266_REG(0xB4C) //SLC_TX_EOF_DES_ADDR
#define SLCRXEBDA ESP8266_REG(0xB50) //SLC_RX_EOF_BFR_DES_ADDR
#define SLCAT ESP8266_REG(0xB54) //SLC_AHB_TEST
#define SLCSS ESP8266_REG(0xB58) //SLC_SDIO_ST
#define SLCRXDC ESP8266_REG(0xB5C) //SLC_RX_DSCR_CONF
#define SLCTXD ESP8266_REG(0xB60) //SLC_TXLINK_DSCR
#define SLCTXDB0 ESP8266_REG(0xB64) //SLC_TXLINK_DSCR_BF0
#define SLCTXDB1 ESP8266_REG(0xB68) //SLC_TXLINK_DSCR_BF1
#define SLCRXD ESP8266_REG(0xB6C) //SLC_RXLINK_DSCR
#define SLCRXDB0 ESP8266_REG(0xB70) //SLC_RXLINK_DSCR_BF0
#define SLCRXDB1 ESP8266_REG(0xB74) //SLC_RXLINK_DSCR_BF1
#define SLCDT ESP8266_REG(0xB78) //SLC_DATE
#define SLCID ESP8266_REG(0xB7C) //SLC_ID
#define SLCHIR ESP8266_REG(0xB88) //SLC_HOST_INTR_RAW
#define SLCHC0 ESP8266_REG(0xB94) //SLC_HOST_CONF_W0
#define SLCHC1 ESP8266_REG(0xB98) //SLC_HOST_CONF_W1
#define SLCHIS ESP8266_REG(0xB9C) //SLC_HOST_INTR_ST
#define SLCHC2 ESP8266_REG(0xBA0) //SLC_HOST_CONF_W2
#define SLCHC3 ESP8266_REG(0xBA4) //SLC_HOST_CONF_W3
#define SLCHC4 ESP8266_REG(0xBA8) //SLC_HOST_CONF_W4
#define SLCHIC ESP8266_REG(0xBB0) //SLC_HOST_INTR_CLR
#define SLCHIE ESP8266_REG(0xBB4) //SLC_HOST_INTR_ENA
#define SLCHC5 ESP8266_REG(0xBBC) //SLC_HOST_CONF_W5
//SLC (DMA) CONF0
#define SLCMM (0x3) //SLC_MODE
#define SLCM (12) //SLC_MODE_S
#define SLCDTBE (1 << 9) //SLC_DATA_BURST_EN
#define SLCDBE (1 << 8) //SLC_DSCR_BURST_EN
#define SLCRXNRC (1 << 7) //SLC_RX_NO_RESTART_CLR
#define SLCRXAW (1 << 6) //SLC_RX_AUTO_WRBACK
#define SLCRXLT (1 << 5) //SLC_RX_LOOP_TEST
#define SLCTXLT (1 << 4) //SLC_TX_LOOP_TEST
#define SLCAR (1 << 3) //SLC_AHBM_RST
#define SLCAFR (1 << 2) //SLC_AHBM_FIFO_RST
#define SLCRXLR (1 << 1) //SLC_RXLINK_RST
#define SLCTXLR (1 << 0) //SLC_TXLINK_RST
//SLC (DMA) INT
#define SLCITXDE (1 << 21) //SLC_TX_DSCR_EMPTY_INT
#define SLCIRXDER (1 << 20) //SLC_RX_DSCR_ERR_INT
#define SLCITXDER (1 << 19) //SLC_TX_DSCR_ERR_INT
#define SLCITH (1 << 18) //SLC_TOHOST_INT
#define SLCIRXEOF (1 << 17) //SLC_RX_EOF_INT
#define SLCIRXD (1 << 16) //SLC_RX_DONE_INT
#define SLCITXEOF (1 << 15) //SLC_TX_EOF_INT
#define SLCITXD (1 << 14) //SLC_TX_DONE_INT
#define SLCIT0 (1 << 13) //SLC_TOKEN1_1TO0_INT
#define SLCIT1 (1 << 12) //SLC_TOKEN0_1TO0_INT
#define SLCITXO (1 << 11) //SLC_TX_OVF_INT
#define SLCIRXU (1 << 10) //SLC_RX_UDF_INT
#define SLCITXS (1 << 9) //SLC_TX_START_INT
#define SLCIRXS (1 << 8) //SLC_RX_START_INT
#define SLCIFH7 (1 << 7) //SLC_FRHOST_BIT7_INT
#define SLCIFH6 (1 << 6) //SLC_FRHOST_BIT6_INT
#define SLCIFH5 (1 << 5) //SLC_FRHOST_BIT5_INT
#define SLCIFH4 (1 << 4) //SLC_FRHOST_BIT4_INT
#define SLCIFH3 (1 << 3) //SLC_FRHOST_BIT3_INT
#define SLCIFH2 (1 << 2) //SLC_FRHOST_BIT2_INT
#define SLCIFH1 (1 << 1) //SLC_FRHOST_BIT1_INT
#define SLCIFH0 (1 << 0) //SLC_FRHOST_BIT0_INT
//SLC (DMA) RX_STATUS
#define SLCRXE (1 << 1) //SLC_RX_EMPTY
#define SLCRXF (1 << 0) //SLC_RX_FULL
//SLC (DMA) TX_STATUS
#define SLCTXE (1 << 1) //SLC_TX_EMPTY
#define SLCTXF (1 << 0) //SLC_TX_FULL
//SLC (DMA) RX_FIFO_PUSH
#define SLCRXFP (1 << 16) //SLC_RXFIFO_PUSH
#define SLCRXWDM (0x1FF) //SLC_RXFIFO_WDATA
#define SLCRXWD (0) //SLC_RXFIFO_WDATA_S
//SLC (DMA) TX_FIFO_POP
#define SLCTXFP (1 << 16) //SLC_TXFIFO_POP
#define SLCTXRDM (0x7FF) //SLC_TXFIFO_RDATA
#define SLCTXRD (0) //SLC_TXFIFO_RDATA_S
//SLC (DMA) RX_LINK
#define SLCRXLP (1 << 31) //SLC_RXLINK_PARK
#define SLCRXLRS (1 << 30) //SLC_RXLINK_RESTART
#define SLCRXLS (1 << 29) //SLC_RXLINK_START
#define SLCRXLE (1 << 28) //SLC_RXLINK_STOP
#define SLCRXLAM (0xFFFF) //SLC_RXLINK_DESCADDR_MASK
#define SLCRXLA (0) //SLC_RXLINK_ADDR_S
//SLC (DMA) TX_LINK
#define SLCTXLP (1 << 31) //SLC_TXLINK_PARK
#define SLCTXLRS (1 << 30) //SLC_TXLINK_RESTART
#define SLCTXLS (1 << 29) //SLC_TXLINK_START
#define SLCTXLE (1 << 28) //SLC_TXLINK_STOP
#define SLCTXLAM (0xFFFF) //SLC_TXLINK_DESCADDR_MASK
#define SLCTXLA (0) //SLC_TXLINK_ADDR_S
//SLC (DMA) TOKENx
#define SLCTM (0xFFF) //SLC_TOKENx_MASK
#define SLCTT (16) //SLC_TOKENx_S
#define SLCTIM (1 << 14) //SLC_TOKENx_LOCAL_INC_MORE
#define SLCTI (1 << 13) //SLC_TOKENx_LOCAL_INC
#define SLCTW (1 << 12) //SLC_TOKENx_LOCAL_WR
#define SLCTDM (0xFFF) //SLC_TOKENx_LOCAL_WDATA
#define SLCTD (0) //SLC_TOKENx_LOCAL_WDATA_S
//SLC (DMA) BRIDGE_CONF
#define SLCBFMEM (0xF) //SLC_FIFO_MAP_ENA
#define SLCBFME (8) //SLC_FIFO_MAP_ENA_S
#define SLCBTEEM (0x3F) //SLC_TXEOF_ENA
#define SLCBTEE (0) //SLC_TXEOF_ENA_S
//SLC (DMA) AHB_TEST
#define SLCATAM (0x3) //SLC_AHB_TESTADDR
#define SLCATA (4) //SLC_AHB_TESTADDR_S
#define SLCATMM (0x7) //SLC_AHB_TESTMODE
#define SLCATM (0) //SLC_AHB_TESTMODE_S
//SLC (DMA) SDIO_ST
#define SLCSBM (0x7) //SLC_BUS_ST
#define SLCSB (12) //SLC_BUS_ST_S
#define SLCSW (1 << 8) //SLC_SDIO_WAKEUP
#define SLCSFM (0xF) //SLC_FUNC_ST
#define SLCSF (4) //SLC_FUNC_ST_S
#define SLCSCM (0x7) //SLC_CMD_ST
#define SLCSC (0) //SLC_CMD_ST_S
//SLC (DMA) RX_DSCR_CONF
#define SLCBRXFE (1 << 20) //SLC_RX_FILL_EN
#define SLCBRXEM (1 << 19) //SLC_RX_EOF_MODE
#define SLCBRXFM (1 << 18) //SLC_RX_FILL_MODE
#define SLCBINR (1 << 17) //SLC_INFOR_NO_REPLACE
#define SLCBTNR (1 << 16) //SLC_TOKEN_NO_REPLACE
#define SLCBPICM (0xFFFF) //SLC_POP_IDLE_CNT
#define SLCBPIC (0) //SLC_POP_IDLE_CNT_S
// I2S Registers
#define i2c_bbpll 0x67
#define i2c_bbpll_hostid 4
#define i2c_bbpll_en_audio_clock_out 4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define I2S_CLK_ENABLE() i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1)
#define I2SBASEFREQ (12000000L)
#define I2STXF ESP8266_REG(0xe00) //I2STXFIFO (32bit)
#define I2SRXF ESP8266_REG(0xe04) //I2SRXFIFO (32bit)
#define I2SC ESP8266_REG(0xe08) //I2SCONF
#define I2SIR ESP8266_REG(0xe0C) //I2SINT_RAW
#define I2SIS ESP8266_REG(0xe10) //I2SINT_ST
#define I2SIE ESP8266_REG(0xe14) //I2SINT_ENA
#define I2SIC ESP8266_REG(0xe18) //I2SINT_CLR
#define I2ST ESP8266_REG(0xe1C) //I2STIMING
#define I2SFC ESP8266_REG(0xe20) //I2S_FIFO_CONF
#define I2SRXEN ESP8266_REG(0xe24) //I2SRXEOF_NUM (32bit)
#define I2SCSD ESP8266_REG(0xe28) //I2SCONF_SIGLE_DATA (32bit)
#define I2SCC ESP8266_REG(0xe2C) //I2SCONF_CHAN
// I2S CONF
#define I2SBDM (0x3F) //I2S_BCK_DIV_NUM
#define I2SBD (22) //I2S_BCK_DIV_NUM_S
#define I2SCDM (0x3F) //I2S_CLKM_DIV_NUM
#define I2SCD (16) //I2S_CLKM_DIV_NUM_S
#define I2SBMM (0xF) //I2S_BITS_MOD
#define I2SBM (12) //I2S_BITS_MOD_S
#define I2SRMS (1 << 11) //I2S_RECE_MSB_SHIFT
#define I2STMS (1 << 10) //I2S_TRANS_MSB_SHIFT
#define I2SRXS (1 << 9) //I2S_I2S_RX_START
#define I2STXS (1 << 8) //I2S_I2S_TX_START
#define I2SMR (1 << 7) //I2S_MSB_RIGHT
#define I2SRF (1 << 6) //I2S_RIGHT_FIRST
#define I2SRSM (1 << 5) //I2S_RECE_SLAVE_MOD
#define I2STSM (1 << 4) //I2S_TRANS_SLAVE_MOD
#define I2SRXFR (1 << 3) //I2S_I2S_RX_FIFO_RESET
#define I2STXFR (1 << 2) //I2S_I2S_TX_FIFO_RESET
#define I2SRXR (1 << 1) //I2S_I2S_RX_RESET
#define I2STXR (1 << 0) //I2S_I2S_TX_RESET
#define I2SRST (0xF) //I2S_I2S_RESET_MASK
//I2S INT
#define I2SITXRE (1 << 5) //I2S_I2S_TX_REMPTY_INT
#define I2SITXWF (1 << 4) //I2S_I2S_TX_WFULL_INT
#define I2SIRXRE (1 << 3) //I2S_I2S_RX_REMPTY_INT
#define I2SIRXWF (1 << 2) //I2S_I2S_RX_WFULL_INT
#define I2SITXPD (1 << 1) //I2S_I2S_TX_PUT_DATA_INT
#define I2SIRXTD (1 << 0) //I2S_I2S_RX_TAKE_DATA_INT
//I2S TIMING
#define I2STBII (1 << 22) //I2S_TRANS_BCK_IN_INV
#define I2SRDS (1 << 21) //I2S_RECE_DSYNC_SW
#define I2STDS (1 << 20) //I2S_TRANS_DSYNC_SW
#define I2SRBODM (0x3) //I2S_RECE_BCK_OUT_DELAY
#define I2SRBOD (18) //I2S_RECE_BCK_OUT_DELAY_S
#define I2SRWODM (0x3) //I2S_RECE_WS_OUT_DELAY
#define I2SRWOD (16) //I2S_RECE_WS_OUT_DELAY_S
#define I2STSODM (0x3) //I2S_TRANS_SD_OUT_DELAY
#define I2STSOD (14) //I2S_TRANS_SD_OUT_DELAY_S
#define I2STWODM (0x3) //I2S_TRANS_WS_OUT_DELAY
#define I2STWOD (12) //I2S_TRANS_WS_OUT_DELAY_S
#define I2STBODM (0x3) //I2S_TRANS_BCK_OUT_DELAY
#define I2STBOD (10) //I2S_TRANS_BCK_OUT_DELAY_S
#define I2SRSIDM (0x3) //I2S_RECE_SD_IN_DELAY
#define I2SRSID (8) //I2S_RECE_SD_IN_DELAY_S
#define I2SRWIDM (0x3) //I2S_RECE_WS_IN_DELAY
#define I2SRWID (6) //I2S_RECE_WS_IN_DELAY_S
#define I2SRBIDM (0x3) //I2S_RECE_BCK_IN_DELAY
#define I2SRBID (4) //I2S_RECE_BCK_IN_DELAY_S
#define I2STWIDM (0x3) //I2S_TRANS_WS_IN_DELAY
#define I2STWID (2) //I2S_TRANS_WS_IN_DELAY_S
#define I2STBIDM (0x3) //I2S_TRANS_BCK_IN_DELAY
#define I2STBID (0) //I2S_TRANS_BCK_IN_DELAY_S
//I2S FIFO CONF
#define I2SRXFMM (0x7) //I2S_I2S_RX_FIFO_MOD
#define I2SRXFM (16) //I2S_I2S_RX_FIFO_MOD_S
#define I2STXFMM (0x7) //I2S_I2S_TX_FIFO_MOD
#define I2STXFM (13) //I2S_I2S_TX_FIFO_MOD_S
#define I2SDE (1 << 12) //I2S_I2S_DSCR_EN
#define I2STXDNM (0x3F) //I2S_I2S_TX_DATA_NUM
#define I2STXDN (6) //I2S_I2S_TX_DATA_NUM_S
#define I2SRXDNM (0x3F) //I2S_I2S_RX_DATA_NUM
#define I2SRXDN (0) //I2S_I2S_RX_DATA_NUM_S
//I2S CONF CHAN
#define I2SRXCMM (0x3) //I2S_RX_CHAN_MOD
#define I2SRXCM (3) //I2S_RX_CHAN_MOD_S
#define I2STXCMM (0x7) //I2S_TX_CHAN_MOD
#define I2STXCM (0) //I2S_TX_CHAN_MOD_S
#endif #endif

53
cores/esp8266/i2s.h Normal file
View File

@ -0,0 +1,53 @@
/*
i2s.h - Software I2C library for esp8266
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef I2S_h
#define I2S_h
/*
How does this work? Basically, to get sound, you need to:
- Connect an I2S codec to the I2S pins on the ESP.
- Start up a thread that's going to do the sound output
- Call i2s_begin()
- Call i2s_set_rate() with the sample rate you want.
- Generate sound and call i2s_write_sample() with 32-bit samples.
The 32bit samples basically are 2 16-bit signed values (the analog values for
the left and right channel) concatenated as (Rout<<16)+Lout
i2s_write_sample will block when you're sending data too quickly, so you can just
generate and push data as fast as you can and I2sPushSample will regulate the
speed.
*/
#ifdef __cplusplus
extern "C" {
#endif
void i2s_begin();
void i2s_end();
void i2s_set_rate(uint32_t rate);
bool i2s_write_sample(uint32_t sample);
bool i2s_write_lr(int16_t left, int16_t right);
#ifdef __cplusplus
}
#endif
#endif