From 3456c9e10432dd70cd1ec2f82a6a3cc19f009a15 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 13 Sep 2014 15:43:46 +0200 Subject: Some I2S interface cleaning up. --- firmware/drivers/i2s.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) (limited to 'firmware/drivers/i2s.h') diff --git a/firmware/drivers/i2s.h b/firmware/drivers/i2s.h index 6e3acf2..386476e 100644 --- a/firmware/drivers/i2s.h +++ b/firmware/drivers/i2s.h @@ -29,8 +29,180 @@ #include +/** + * Set power of I²S circuit. + * @param power Integer value 0 is off, nonzero values are on. + */ +void i2s_set_power(int power); + +/** + * Clock selection mode. See table 41, pg. 57. + */ +typedef enum { + I2S_CCLK_4 = 0b00, ///< PCLK_peripheral = CCLK/4 + I2S_CCLK = 0b01, ///< PCLK_peripheral = CCLK + I2S_CCLK_2 = 0b10, ///< PCLK_peripheral = CCLK/2 + I2S_CCLK_8 = 0b11, ///< PCLK_peripheral = CCLK/8 +} i2s_clksel_t; + +#define I2S_CCLK_6 ((i2s_clksel_t)0b11) ///< For CAN1, CAN2, and CAN filtering when 0b11 selects = CCLK/6. + +/** + * Set clock selection for I²S circuit. + * @param sel Clock selection mode. + */ +void i2s_set_clksel(i2s_clksel_t sel); + +/** + * Set pin selection for I²S circuit. + * RX: + * - P0.4: I2SRX_CLK + * - P0.5: I2SRX_WS + * - P0.6: I2SRX_SDA + * - P?.?: RX_MCLK (currently not set) + * TX: + * - P0.7: I2STX_CLK + * - P0.8: I2STX_WS + * - P0.9: I2STX_SDA + * - P4.28: TX_MCLK + */ +void i2s_set_pinsel(); + +typedef enum { + WW_8_BIT = 0b00, // 8-bit data + WW_16_BIT = 0b01, // 16-bit data + // WW_RESERVED = 0b10, // Reserved, do not use this setting + WW_32_BIT = 0b11, // 32-bit data +} wordwidth_t; + +typedef enum { + CH_MONO = 0b1, // Data is mono format + CH_STEREO = 0b0, // Data is stereo format +} channels_t; + +/** + * Sets DAO register values and stops/resets the bus. + * @param ww Word width of pcm values. + * @param ch Number of channels (mono/stereo) + */ +void i2s_set_dao_register(wordwidth_t ww, channels_t ch); + +/** + * Sets DAI register values and stops/resets the bus. + * @param ww Word width of pcm values. + * @param ch Number of channels (mono/stereo) + */ +void i2s_set_dai_register(wordwidth_t ww, channels_t ch); + +/** + * Set clock transmit rate as PCLK_I2S * (X/Y) / 2 + * @param y_div I²S transmit MCLK rate denominator. This value is used to + * divide PCLK to produce the transmit MCLK. Eight bits of fractional divide + * supports a wide range of possibilities. A value of 0 stops the clock. + * @param x_div I²S transmit MCLK rate numerator. This value is used to + * multiply PCLK by to produce the transmit MCLK. A value of 0 stops the clock. + * Eight bits of fractional divide supports a wide range of possibilities. + * Note: the resulting ratio X/Y is divided by 2. + */ +void i2s_set_tx_rate(uint8_t y_div, uint8_t x_div); + +/** + * Set clock receive rate as PCLK_I2S * (X/Y) / 2 + * @param y_div I²S receive MCLK rate denominator. This value is used to divide + * PCLK to produce the receive MCLK. Eight bits of fractional divide supports + * a wide range of possibilities. A value of 0 stops the clock. + * @param x_div I²S receive MCLK rate numerator. This value is used to multiply + * PCLK by to produce the receive MCLK. A value of 0 stops the clock. Eight + * bits of fractional divide supports a wide range of possibilities. + * Note: the resulting ratio X/Y is divided by 2. + */ +void i2s_set_rx_rate(uint8_t y_div, uint8_t x_div); + +/** + * I²S transmit bit rate. + * @param bitrate This value plus one is used to divide TX_MCLK to produce the + * transmit bit clock. + */ +void i2s_set_tx_clock_bitrate(uint8_t bitrate); + +/** + * I²S receive bit rate. + * @param bitrate This value plus one is used to divide RX_MCLK to produce the + * receive bit clock. + */ +void i2s_set_rx_clock_bitrate(uint8_t bitrate); + +typedef enum { + CLK_TX_SRC = 0b00, ///< Select the TX fractional rate divider clock output as the source + CLK_RX_MCLK = 0b10, ///< Select the RX_MCLK signal as the TX_MCLK clock source +} clksel_t; + +/** + * + */ +void i2s_set_tx_mode_control(clksel_t c, int _4pin, int mcena); + +/** + * + */ +void i2s_set_rx_mode_control(clksel_t c, int _4pin, int mcena); + +void i2s_tx_reset(); +void i2s_tx_stop(); +void i2s_tx_start(); + +void i2s_rx_reset(); +void i2s_rx_stop(); +void i2s_rx_start(); + +/* + * A data sample in the FIFO consists of: + * - 1×32 bits in 8-bit or 16-bit stereo modes. + * - 1×32 bits in mono modes. + * - 2×32 bits, first left data, second right data, in 32-bit stereo modes. + * + * I2STXFIFO: 0x400A 8008 - 8 x 32 bit (see table 407, pg 477) + * I2SRXFIFO: 0x400A 800C - 8 x 32 bit (see table 408, pg 478) + * + * See figure 113, pg. 489, for examples. + */ + +/** + * Write to TXFIFO + * I2STXFIFO: 0x400A 8008 - 8 x 32 bit (see table 407, pg 477) + */ +#define TF(t, n) t *n = (t*)0x400A8008 +inline void i2s_write_pcm_8_mono(int8_t s) { TF(int8_t, t); t[0] = s; } +inline void i2s_write_pcm_16_mono(int16_t s) { TF(int16_t, t); t[0] = s; } +inline void i2s_write_pcm_32_mono(int32_t s) { TF(int32_t, t); t[0] = s; } +inline void i2s_write_pcm_8_stereo(int8_t l, int8_t r) +{ TF(int8_t, t); t[0] = l; t[1] = r; } +inline void i2s_write_pcm_16_stereo(int16_t l, int16_t r) +{ TF(int16_t, t); t[0] = l; t[1] = r; } +inline void i2s_write_pcm_32_stereo(int32_t l, int32_t r) +{ TF(int32_t, t); t[0] = l; t[1] = r; } + +/** + * Read from RXFIFO + * I2SRXFIFO: 0x400A 800C - 8 x 32 bit (see table 408, pg 478) + */ +#define RF(t, n) t *n = (t*)0x400A800C +inline void i2s_read_pcm_8_mono(int8_t *s) { RF(int8_t, t); *s = t[0]; } +inline void i2s_read_pcm_16_mono(int16_t *s) { RF(int16_t, t); *s = t[0]; } +inline void i2s_read_pcm_32_mono(int32_t *s) { RF(int32_t, t); *s = t[0]; } +inline void i2s_read_pcm_8_stereo(int8_t *l, int8_t *r) +{ RF(int8_t, t); *l = t[0]; *r = t[1]; } +inline void i2s_read_pcm_16_stereo(int16_t *l, int16_t *r) +{ RF(int16_t, t); *l = t[0]; *r = t[1]; } +inline void i2s_read_pcm_32_stereo(int32_t *l, int32_t *r) +{ RF(int32_t, t); *l = t[0]; *r = t[1]; } + +/** + * Convenience function for power, pin, clock and register configuration. + */ void i2s_init(); + /** * Enables accesses on FIFOs, places the transmit channel in unmute mode. */ -- cgit v1.2.3