Re: I2S for generating waveforms for ledpixel devices
Posted: Sun Aug 30, 2020 4:21 am
davydnorris wrote:Also, put up your questions about the registers - let's try to get some answers!!
Ok, hold on, this is what I got! (EDIT: grmbl, it ate all the whitespace!)
enum
{
DR_REG_I2S_BASE = 0x60000e00, // pretty trivial
};
enum
{
I2STXFIFO = DR_REG_I2S_BASE + 0x0000, // pretty trivial too
I2SRXFIFO = DR_REG_I2S_BASE + 0x0004, // note: no queue usage counter?
};
enum
{
I2SCONF = DR_REG_I2S_BASE + 0x0008,
I2S_BCK_DIV_NUM = 0x0000003f, // clock prescalers and dividers, not too complex, I only don't
I2S_BCK_DIV_NUM_S = 22, // understand how to assign the total scaling to both, there doesn't
// seem to be a general rule, other than some comments
I2S_CLKM_DIV_NUM = 0x0000003f,
I2S_CLKM_DIV_NUM_S = 16,
I2S_BITS_MOD = 0x0000000f, // undocumented; seems to relate to the amount of bit clocks
I2S_BITS_MOD_S = 12, // between a word or channel clock toggle?
I2S_RECE_MSB_SHIFT = 1 << 11, // ?
I2S_TRANS_MSB_SHIFT = 1 << 10, // ?
I2S_I2S_RX_START = 1 << 9, // clear
I2S_I2S_TX_START = 1 << 8, // clear
I2S_MSB_RIGHT = 1 << 7, // ? (although I do have a hunch...)
I2S_RIGHT_FIRST = 1 << 6, // ? similar
I2S_RECE_SLAVE_MOD = 1 << 5, // ?
I2S_TRANS_SLAVE_MOD = 1 << 4, // ?
I2S_I2S_RX_FIFO_RESET = 1 << 3, // clear
I2S_I2S_TX_FIFO_RESET = 1 << 2, // clear
I2S_I2S_RX_RESET = 1 << 1, // clear
I2S_I2S_TX_RESET = 1 << 0, // clear
};
enum
{
I2SINT_RAW = DR_REG_I2S_BASE + 0x000c, // all interrupts three times
I2S_I2S_TX_REMPTY_INT_RAW = 1 << 5, // I am not sure what the "raw" section does
I2S_I2S_TX_WFULL_INT_RAW = 1 << 4, (compared to the "enable" and "status" sections)
I2S_I2S_RX_REMPTY_INT_RAW = 1 << 3,
I2S_I2S_RX_WFULL_INT_RAW = 1 << 2,
I2S_I2S_TX_PUT_DATA_INT_RAW = 1 << 1,
I2S_I2S_RX_TAKE_DATA_INT_RAW = 1 << 0
};
enum
{
I2SINT_ST = DR_REG_I2S_BASE + 0x0010,
I2S_I2S_TX_REMPTY_INT_ST = 1 << 5, // transmit fifo empty
I2S_I2S_TX_WFULL_INT_ST = 1 << 4, // transmit fifo full
I2S_I2S_RX_REMPTY_INT_ST = 1 << 3, // receive fifo empty
I2S_I2S_RX_WFULL_INT_ST = 1 << 2, // receive fifo full
I2S_I2S_TX_PUT_DATA_INT_ST = 1 << 1, // one sample (word) stored in the fifo?
I2S_I2S_RX_TAKE_DATA_INT_ST = 1 << 0 // one sample (word) fetched from the fifo?
}; // these last two are not really useful I think?
enum
{
I2SINT_ENA = DR_REG_I2S_BASE + 0x0014, // same
I2S_I2S_TX_REMPTY_INT_ENA = 1 << 5,
I2S_I2S_TX_WFULL_INT_ENA = 1 << 4,
I2S_I2S_RX_REMPTY_INT_ENA = 1 << 3,
I2S_I2S_RX_WFULL_INT_ENA = 1 << 2,
I2S_I2S_TX_PUT_DATA_INT_ENA = 1 << 1,
I2S_I2S_RX_TAKE_DATA_INT_ENA = 1 << 0
};
enum
{
I2SINT_CLR = DR_REG_I2S_BASE + 0x0018, // same
I2S_I2S_TX_REMPTY_INT_CLR = 1 << 5,
I2S_I2S_TX_WFULL_INT_CLR = 1 << 4,
I2S_I2S_RX_REMPTY_INT_CLR = 1 << 3,
I2S_I2S_RX_WFULL_INT_CLR = 1 << 2,
I2S_I2S_PUT_DATA_INT_CLR = 1 << 1,
I2S_I2S_TAKE_DATA_INT_CLR = 1 << 0
};
enum
{
I2STIMING = DR_REG_I2S_BASE + 0x001c,
I2S_TRANS_BCK_IN_INV = 1 << 22, // inverted bit clock?
I2S_RECE_DSYNC_SW = 1 << 21, // no clue
I2S_TRANS_DSYNC_SW = 1 << 20, // no clue
I2S_RECE_BCK_OUT_DELAY = 0x00000003, // receiver bit clock output delay
I2S_RECE_BCK_OUT_DELAY_S = 18,
I2S_RECE_WS_OUT_DELAY = 0x00000003, // receiver word clock output delay
I2S_RECE_WS_OUT_DELAY_S = 16,
I2S_TRANS_SD_OUT_DELAY = 0x00000003, // transmitter sample clock output delay
I2S_TRANS_SD_OUT_DELAY_S = 14,
I2S_TRANS_WS_OUT_DELAY = 0x00000003, // transmitter work clock output delay
I2S_TRANS_WS_OUT_DELAY_S = 12,
I2S_TRANS_BCK_OUT_DELAY = 0x00000003, // transmitter bit clock output delay
I2S_TRANS_BCK_OUT_DELAY_S = 10,
I2S_RECE_SD_IN_DELAY = 0x00000003, // receiver sample clock input delay
I2S_RECE_SD_IN_DELAY_S = 8,
I2S_RECE_WS_IN_DELAY = 0x00000003, // receiver word clock input delay
I2S_RECE_WS_IN_DELAY_S = 6,
I2S_RECE_BCK_IN_DELAY = 0x00000003, // receiver bit clock input delay
I2S_RECE_BCK_IN_DELAY_S = 4,
I2S_TRANS_WS_IN_DELAY = 0x00000003, // transmitter work clock input delay
I2S_TRANS_WS_IN_DELAY_S = 2,
I2S_TRANS_BCK_IN_DELAY = 0x00000003, // receiver bit clock input delay
I2S_TRANS_BCK_IN_DELAY_S = 0
};
enum
{
I2S_FIFO_CONF = DR_REG_I2S_BASE + 0x0020,
I2S_I2S_RX_FIFO_MOD = 0x00000007, // receiver sample layout
I2S_I2S_RX_FIFO_MOD_S = 16,
I2S_I2S_TX_FIFO_MOD = 0x00000007, // transmitter sample layout
I2S_I2S_TX_FIFO_MOD_S = 13,
I2S_I2S_DSCR_EN = 1 << 12, // select DMA (SLC) or FIFO (PIO) mode
I2S_I2S_TX_DATA_NUM = 0x0000003f, // no clue, amount of bits per sample like 0-16? this is not the fifo length counter
I2S_I2S_TX_DATA_NUM_S = 6,
I2S_I2S_RX_DATA_NUM = 0x0000003f, // no clue, amount of bits per sample like 0-16? this is not the fifo length counter
I2S_I2S_RX_DATA_NUM_S = 0
};
enum
{
I2SRXEOF_NUM = DR_REG_I2S_BASE + 0x0024, // this has something to do with SLC/DMA
I2S_I2S_RX_EOF_NUM = 0xffffffff, // possibly the amount of times the DMA pointer wrapped around
I2S_I2S_RX_EOF_NUM_S = 0 // due to lack of timely input (either side)
};
enum
{
I2SCONF_SIGLE_DATA = DR_REG_I2S_BASE + 0x0028, // magic!
I2S_I2S_SIGLE_DATA = 0xffffffff,
I2S_I2S_SIGLE_DATA_S = 0
};
enum
{
I2SCONF_CHAN = DR_REG_I2S_BASE + 0x002c,
I2S_RX_CHAN_MOD = 0x00000003, // more data layout options
I2S_RX_CHAN_MOD_S = 3,
I2S_TX_CHAN_MOD = 0x00000007, // more data layout options
I2S_TX_CHAN_MOD_S = 0
};