diff options
author | Uros Majstorovic <majstor@majstor.org> | 2022-09-04 18:22:50 +0200 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2022-09-04 18:22:50 +0200 |
commit | 838c430635b146a545033bf4f4552c02958508f2 (patch) | |
tree | f305dbe0d6757453cdfd42b25de8097070787ff3 /fw | |
parent | 4c96cd2d5f7cb8de7d48b5dbd728af7fda572d9d (diff) |
new stereo audio driver
Diffstat (limited to 'fw')
-rw-r--r-- | fw/fe310/eos/soc/i2s.c | 293 | ||||
-rw-r--r-- | fw/fe310/eos/soc/i2s.h | 12 | ||||
-rw-r--r-- | fw/fe310/eos/soc/i2s_priv.h | 9 | ||||
-rw-r--r-- | fw/fe310/eos/soc/trap_entry.S | 224 |
4 files changed, 297 insertions, 241 deletions
diff --git a/fw/fe310/eos/soc/i2s.c b/fw/fe310/eos/soc/i2s.c index 5e5eaa7..c5b52bf 100644 --- a/fw/fe310/eos/soc/i2s.c +++ b/fw/fe310/eos/soc/i2s.c @@ -6,39 +6,54 @@ #include "prci_driver.h" #include "eos.h" -#include "interrupt.h" #include "event.h" +#include "interrupt.h" #include "board.h" +#include "dev/eve.h" + +#include "uart.h" + #include "i2s.h" #include "i2s_priv.h" #define I2S_REG_CK(o) _REG32(I2S_CTRL_ADDR_CK, o) -#define I2S_REG_WS_MIC(o) _REG32(I2S_CTRL_ADDR_WS_MIC, o) -#define I2S_REG_WS_SPK(o) _REG32(I2S_CTRL_ADDR_WS_SPK, o) +#define I2S_REG_WS(o) _REG32(I2S_CTRL_ADDR_WS, o) +#define I2S_REG_SR_SEL(o) _REG32(I2S_CTRL_ADDR_SR_SEL, o) -#define I2S_PIN_PWM ((1 << I2S_PIN_CK) | (1 << I2S_PIN_CK_SW) | (1 << I2S_PIN_WS_MIC) | (1 << I2S_PIN_WS_SPK)) +#define I2S_PIN_PWM ((1 << I2S_PIN_CK) | (1 << I2S_PIN_SR_SEL) | (1 << I2S_PIN_WS_MIC) | (1 << I2S_PIN_WS_SPK)) #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) #define EOS_ABUF_IDX_MASK(IDX, SIZE) ((IDX) & ((SIZE) - 1)) -EOSABuf _eos_i2s_mic_buf; -EOSABuf _eos_i2s_spk_buf; -uint32_t _eos_i2s_fmt = 0; -uint32_t _eos_i2s_mic_wm = 0; -uint32_t _eos_i2s_spk_wm = 0; -uint32_t _eos_i2s_mic_evt_enable = 0; -uint32_t _eos_i2s_spk_evt_enable = 0; - -static eos_i2s_handler_t i2s_spk_handler = NULL; static eos_i2s_handler_t i2s_mic_handler = NULL; +static eos_i2s_handler_t i2s_spk_handler = NULL; static uint32_t i2s_clk_period; static uint8_t i2s_mic_volume = 0; /* 0 - 8 */ static uint8_t i2s_spk_volume = 16; /* 0 - 16 */ +EOSABuf _eos_i2s_mic_buf; +EOSABuf _eos_i2s_spk_buf; + +uint32_t _eos_i2s_drvr[] = { + EOS_I2S_FMT_PCM16, /* I2S_FMT */ + EOS_I2S_MODE_STEREO, /* I2S_MODE */ + 0, /* I2S_MIC_WM */ + 0, /* I2S_SPK_WM */ + 0, /* I2S_MIC_EVT */ + 0, /* I2S_SPK_EVT */ + }; + +#define I2S_FMT 0 +#define I2S_MODE 1 +#define I2S_MIC_WM 2 +#define I2S_SPK_WM 3 +#define I2S_MIC_EVT 4 +#define I2S_SPK_EVT 5 + static void _abuf_init(EOSABuf *buf, uint8_t *array, uint16_t size) { buf->idx_r = 0; buf->idx_w = 0; @@ -84,7 +99,6 @@ static int _abuf_pop16(EOSABuf *buf, uint16_t *sample) { } } - static void _abuf_flush(EOSABuf *buf) { buf->idx_r = 0; buf->idx_w = 0; @@ -94,45 +108,48 @@ static uint16_t _abuf_len(EOSABuf *buf) { return buf->idx_w - buf->idx_r; } +__attribute__ ((section (".itim"))) static void i2s_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) { switch(type & ~EOS_EVT_MASK) { case EOS_I2S_ETYPE_MIC: - if (i2s_mic_handler) i2s_mic_handler(type); - clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_mic_evt_enable = 1; - set_csr(mstatus, MSTATUS_MIE); + if (i2s_mic_handler) { + i2s_mic_handler(type); + clear_csr(mstatus, MSTATUS_MIE); + _eos_i2s_drvr[I2S_MIC_EVT] = 1; + set_csr(mstatus, MSTATUS_MIE); + } break; + case EOS_I2S_ETYPE_SPK: - if (i2s_spk_handler) i2s_spk_handler(type); - clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_spk_evt_enable = 1; - set_csr(mstatus, MSTATUS_MIE); + if (i2s_spk_handler) { + i2s_spk_handler(type); + clear_csr(mstatus, MSTATUS_MIE); + _eos_i2s_drvr[I2S_SPK_EVT] = 1; + set_csr(mstatus, MSTATUS_MIE); + } break; + default: eos_evtq_bad_handler(type, buffer, len); break; } } -static void _mic_vol_set(uint8_t vol) { - I2S_REG_WS_MIC(PWM_CMP2) = i2s_clk_period * (vol + 1); - I2S_REG_WS_MIC(PWM_CMP3) = I2S_REG_WS_MIC(PWM_CMP2) + i2s_clk_period * 16; -} - -static void _spk_vol_set(uint8_t vol) { - int spk_cmp = vol + i2s_mic_volume - 16; +static void i2s_set_cmp(void) { + int spk_ws_offset = i2s_spk_volume - 16 + i2s_mic_volume; - if (spk_cmp <= 0) { - I2S_REG_WS_SPK(PWM_CMP1) = i2s_clk_period * (32 + spk_cmp); - I2S_REG_WS_SPK(PWM_CMP2) = i2s_clk_period * (64 + spk_cmp); - I2S_REG_WS_SPK(PWM_CMP3) = i2s_clk_period * 33; + /* adjust spk ws relative to mic ws */ + if (spk_ws_offset <= 0) { + spk_ws_offset += 32; GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_WS_SPK); } else { - I2S_REG_WS_SPK(PWM_CMP1) = i2s_clk_period * spk_cmp; - I2S_REG_WS_SPK(PWM_CMP2) = i2s_clk_period * (32 + spk_cmp); - I2S_REG_WS_SPK(PWM_CMP3) = i2s_clk_period * (33 + spk_cmp); - GPIO_REG(GPIO_OUTPUT_XOR) |= (1 << I2S_PIN_WS_SPK); + GPIO_REG(GPIO_OUTPUT_XOR) |= (1 << I2S_PIN_WS_SPK); } + I2S_REG_WS(PWM_CMP2) = spk_ws_offset * i2s_clk_period - i2s_clk_period / 2; + I2S_REG_WS(PWM_CMP3) = (32 + spk_ws_offset) * i2s_clk_period - i2s_clk_period / 2; + + I2S_REG_SR_SEL(PWM_CMP1) = (1 + i2s_mic_volume) * i2s_clk_period; + I2S_REG_SR_SEL(PWM_CMP2) = (17 + i2s_mic_volume) * i2s_clk_period - (i2s_clk_period / 4); } extern void _eos_i2s_start_pwm(void); @@ -140,109 +157,127 @@ extern void _eos_i2s_start_pwm(void); int eos_i2s_init(uint8_t wakeup_cause) { eos_evtq_set_handler(EOS_EVT_I2S, i2s_handle_evt); - eos_i2s_init_mux(); - - GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_CK_SW); - GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_CK_SR); - - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_CK_SW); - GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_CK_SW); - - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_CK_SR); - GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_CK_SR); - - return EOS_OK; -} - -void eos_i2s_init_mux(void) { - GPIO_REG(GPIO_OUTPUT_VAL) &= ~((1 << I2S_PIN_CK) | (1 << I2S_PIN_WS_MIC) | (1 << I2S_PIN_WS_SPK)); - - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_CK); - GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_CK); + I2S_REG_CK(PWM_CFG) = 0; + I2S_REG_WS(PWM_CFG) = 0; + I2S_REG_SR_SEL(PWM_CFG) = 0; - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_WS_MIC); - GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_WS_MIC); + GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_SR_SEL); + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_SR_CK); - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_WS_SPK); - GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_WS_SPK); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_SR_SEL); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_SR_CK); GPIO_REG(GPIO_INPUT_EN) |= (1 << I2S_PIN_SD_IN); - GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_SD_IN); - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_SD_OUT); - GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_SD_OUT); + return EOS_OK; } -void eos_i2s_start(uint32_t sample_rate, unsigned char fmt) { - i2s_clk_period = ((PRCI_get_cpu_freq() / (sample_rate * 64)) & ~I2S_PWM_SCALE_CK_MASK) + 1; - - GPIO_REG(GPIO_INPUT_EN) |= (1 << I2S_PIN_SD_IN); - GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_SD_IN); - - GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_SD_OUT); - GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_SD_OUT); +void eos_i2s_start(uint32_t sample_rate) { + uint32_t iof_mask; + i2s_clk_period = PRCI_get_cpu_freq() / (sample_rate * 64); + i2s_clk_period = (i2s_clk_period & ~I2S_PWM_SCALE_CK_MASK) + 1; I2S_REG_CK(PWM_CMP0) = i2s_clk_period >> I2S_PWM_SCALE_CK; I2S_REG_CK(PWM_CMP1) = I2S_REG_CK(PWM_CMP0) / 2; I2S_REG_CK(PWM_CMP2) = 0; I2S_REG_CK(PWM_CMP3) = 0; - I2S_REG_WS_MIC(PWM_CMP0) = i2s_clk_period * 64 - 1; - I2S_REG_WS_MIC(PWM_CMP1) = i2s_clk_period * 32; - _mic_vol_set(i2s_mic_volume); + I2S_REG_WS(PWM_CMP0) = i2s_clk_period * 64 - 1; + I2S_REG_WS(PWM_CMP1) = i2s_clk_period * 32; - I2S_REG_WS_SPK(PWM_CMP0) = i2s_clk_period * 64 - 1; - _spk_vol_set(i2s_spk_volume); + I2S_REG_SR_SEL(PWM_CMP0) = i2s_clk_period * 32 - 1; + I2S_REG_SR_SEL(PWM_CMP3) = 0; + i2s_set_cmp(); I2S_REG_CK(PWM_COUNT) = 0; - I2S_REG_WS_MIC(PWM_COUNT) = 0; - I2S_REG_WS_SPK(PWM_COUNT) = i2s_clk_period / 2; + I2S_REG_WS(PWM_COUNT) = 0; + I2S_REG_SR_SEL(PWM_COUNT) = 0; - _eos_i2s_fmt = fmt; - _eos_i2s_mic_evt_enable = 1; - _eos_i2s_spk_evt_enable = 1; + if (i2s_mic_handler) _eos_i2s_drvr[I2S_MIC_EVT] = 1; + if (i2s_spk_handler) _eos_i2s_drvr[I2S_SPK_EVT] = 1; - eos_intr_set_priority(I2S_IRQ_WS_ID, IRQ_PRIORITY_I2S_WS); - eos_intr_set_priority(I2S_IRQ_SD_ID, 0); - eos_intr_enable(I2S_IRQ_WS_ID); + eos_eve_intr_disable(); + eos_uart_disable(); + eos_intr_set_priority(I2S_IRQ_SD_ID, IRQ_PRIORITY_I2S_SD); eos_intr_enable(I2S_IRQ_SD_ID); + GPIO_REG(GPIO_INPUT_EN) |= (1 << I2S_PIN_INT); + GPIO_REG(GPIO_FALL_IE) |= (1 << I2S_PIN_INT); + GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_SR_CK); + + iof_mask = I2S_PIN_PWM; + if (_eos_i2s_mic_buf.size == 0) { + iof_mask &= ~(1 << I2S_PIN_WS_MIC); + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_WS_MIC); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_WS_MIC); + } else if (_eos_i2s_drvr[I2S_MIC_WM] == 0) { + _eos_i2s_drvr[I2S_MIC_WM] = _eos_i2s_mic_buf.size / 2; + } + if (_eos_i2s_spk_buf.size == 0) { + iof_mask &= ~(1 << I2S_PIN_WS_SPK); + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_SD_OUT); + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_WS_SPK); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_WS_SPK); + } else if (_eos_i2s_drvr[I2S_SPK_WM] == 0) { + _eos_i2s_drvr[I2S_SPK_WM] = _eos_i2s_spk_buf.size / 2; + } + GPIO_REG(GPIO_IOF_SEL) |= iof_mask; + GPIO_REG(GPIO_IOF_EN) |= iof_mask; + _eos_i2s_start_pwm(); /* I2S_REG_CK(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | I2S_PWM_SCALE_CK; - I2S_REG_WS_MIC(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | PWM_CFG_CMP2GANG; - I2S_REG_WS_SPK(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | PWM_CFG_CMP1GANG; + I2S_REG_WS(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | PWM_CFG_CMP2GANG; + I2S_REG_SR_SEL(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | PWM_CFG_CMP1GANG; */ - - GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_CK_SR); - GPIO_REG(GPIO_IOF_SEL) |= I2S_PIN_PWM; - GPIO_REG(GPIO_IOF_EN) |= I2S_PIN_PWM; } void eos_i2s_stop(void) { I2S_REG_CK(PWM_CFG) = 0; - I2S_REG_WS_MIC(PWM_CFG) = 0; - I2S_REG_WS_SPK(PWM_CFG) = 0; + I2S_REG_WS(PWM_CFG) = 0; + I2S_REG_SR_SEL(PWM_CFG) = 0; I2S_REG_CK(PWM_COUNT) = 0; - I2S_REG_WS_MIC(PWM_COUNT) = 0; - I2S_REG_WS_SPK(PWM_COUNT) = 0; - - _eos_i2s_mic_evt_enable = 0; - _eos_i2s_spk_evt_enable = 0; - eos_intr_set_priority(I2S_IRQ_WS_ID, 0); - eos_intr_set_priority(I2S_IRQ_SD_ID, 0); - eos_intr_disable(I2S_IRQ_WS_ID); + I2S_REG_WS(PWM_COUNT) = 0; + I2S_REG_SR_SEL(PWM_COUNT) = 0; + eos_intr_disable(I2S_IRQ_SD_ID); - GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_CK_SW); - GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_CK_SR); + if (!(GPIO_REG(GPIO_IOF_EN) & I2S_PIN_WS_MIC)) { + GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_WS_MIC); + } + if (!(GPIO_REG(GPIO_IOF_EN) & I2S_PIN_WS_SPK)) { + GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_WS_SPK); + } + GPIO_REG(GPIO_FALL_IE) &= ~(1 << I2S_PIN_INT); + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_INT); + GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_SR_SEL); + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_SR_CK); GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_WS_SPK); GPIO_REG(GPIO_IOF_EN) &= ~I2S_PIN_PWM; + eos_uart_enable(); + eos_eve_intr_enable(); + + _eos_i2s_drvr[I2S_MIC_EVT] = 0; + _eos_i2s_drvr[I2S_SPK_EVT] = 0; + _eos_i2s_drvr[I2S_MIC_WM] = 0; + _eos_i2s_drvr[I2S_SPK_WM] = 0; + i2s_mic_handler = NULL; + i2s_spk_handler = NULL; + _abuf_init(&_eos_i2s_mic_buf, NULL, 0); + _abuf_init(&_eos_i2s_spk_buf, NULL, 0); } int eos_i2s_running(void) { - return !!(GPIO_REG(GPIO_IOF_EN) & I2S_PIN_PWM); + return !!(GPIO_REG(GPIO_IOF_EN) & (1 << I2S_PIN_CK)); +} + +void eos_i2s_set_fmt(unsigned char fmt) { + _eos_i2s_drvr[I2S_FMT] = fmt; +} + +void eos_i2s_set_mode(unsigned char mode) { + _eos_i2s_drvr[I2S_MODE] = mode; } void eos_i2s_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size) { @@ -259,18 +294,22 @@ void eos_i2s_mic_set_handler(eos_i2s_handler_t wm_handler) { void eos_i2s_mic_set_wm(uint16_t wm) { clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_mic_wm = wm; + _eos_i2s_drvr[I2S_MIC_WM] = wm; set_csr(mstatus, MSTATUS_MIE); - } +__attribute__ ((section (".itim"))) uint16_t eos_i2s_mic_len(void) { + uint16_t ret; + clear_csr(mstatus, MSTATUS_MIE); - uint16_t ret = _abuf_len(&_eos_i2s_mic_buf); + ret = _abuf_len(&_eos_i2s_mic_buf); set_csr(mstatus, MSTATUS_MIE); + return ret; } +__attribute__ ((section (".itim"))) uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize) { uint16_t i; uint16_t _ssize = 0; @@ -291,31 +330,36 @@ uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize) { } int eos_i2s_mic_pop8(uint8_t *sample) { + int ret; + clear_csr(mstatus, MSTATUS_MIE); - int ret = _abuf_pop8(&_eos_i2s_mic_buf, sample); + ret = _abuf_pop8(&_eos_i2s_mic_buf, sample); set_csr(mstatus, MSTATUS_MIE); + return ret; } int eos_i2s_mic_pop16(uint16_t *sample) { + int ret; + clear_csr(mstatus, MSTATUS_MIE); - int ret = _abuf_pop16(&_eos_i2s_mic_buf, sample); + ret = _abuf_pop16(&_eos_i2s_mic_buf, sample); set_csr(mstatus, MSTATUS_MIE); + return ret; } -int eos_i2s_mic_vol_get(void) { +int eos_i2s_mic_get_vol(void) { return i2s_mic_volume; } -void eos_i2s_mic_vol_set(int vol) { +void eos_i2s_mic_set_vol(int vol) { if ((vol < 0) || (vol > 8)) return; i2s_mic_volume = vol; clear_csr(mstatus, MSTATUS_MIE); - _mic_vol_set(vol); - _spk_vol_set(i2s_spk_volume); + i2s_set_cmp(); set_csr(mstatus, MSTATUS_MIE); } @@ -333,17 +377,22 @@ void eos_i2s_spk_set_handler(eos_i2s_handler_t wm_handler) { void eos_i2s_spk_set_wm(uint16_t wm) { clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_spk_wm = wm; + _eos_i2s_drvr[I2S_SPK_WM] = wm; set_csr(mstatus, MSTATUS_MIE); } +__attribute__ ((section (".itim"))) uint16_t eos_i2s_spk_len(void) { + uint16_t ret; + clear_csr(mstatus, MSTATUS_MIE); - uint16_t ret = _abuf_len(&_eos_i2s_spk_buf); + ret = _abuf_len(&_eos_i2s_spk_buf); set_csr(mstatus, MSTATUS_MIE); + return ret; } +__attribute__ ((section (".itim"))) uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize) { uint16_t i; uint16_t _ssize = 0; @@ -364,29 +413,35 @@ uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize) { } int eos_i2s_spk_push8(uint8_t sample) { + int ret; + clear_csr(mstatus, MSTATUS_MIE); - int ret = _abuf_push8(&_eos_i2s_spk_buf, sample); + ret = _abuf_push8(&_eos_i2s_spk_buf, sample); set_csr(mstatus, MSTATUS_MIE); + return ret; } int eos_i2s_spk_push16(uint16_t sample) { + int ret; + clear_csr(mstatus, MSTATUS_MIE); - int ret = _abuf_push16(&_eos_i2s_spk_buf, sample); + ret = _abuf_push16(&_eos_i2s_spk_buf, sample); set_csr(mstatus, MSTATUS_MIE); + return ret; } -int eos_i2s_spk_vol_get(void) { +int eos_i2s_spk_get_vol(void) { return i2s_spk_volume; } -void eos_i2s_spk_vol_set(int vol) { +void eos_i2s_spk_set_vol(int vol) { if ((vol < 0) || (vol > 16)) return; i2s_spk_volume = vol; clear_csr(mstatus, MSTATUS_MIE); - _spk_vol_set(vol); + i2s_set_cmp(); set_csr(mstatus, MSTATUS_MIE); } diff --git a/fw/fe310/eos/soc/i2s.h b/fw/fe310/eos/soc/i2s.h index f53e183..a5a67df 100644 --- a/fw/fe310/eos/soc/i2s.h +++ b/fw/fe310/eos/soc/i2s.h @@ -13,9 +13,11 @@ typedef void (*eos_i2s_handler_t) (unsigned char); int eos_i2s_init(uint8_t wakeup_cause); void eos_i2s_init_mux(void); -void eos_i2s_start(uint32_t sample_rate, unsigned char fmt); +void eos_i2s_start(uint32_t sample_rate); void eos_i2s_stop(void); int eos_i2s_running(void); +void eos_i2s_set_fmt(unsigned char fmt); +void eos_i2s_set_mode(unsigned char mode); void eos_i2s_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size); void eos_i2s_mic_set_handler(eos_i2s_handler_t wm_handler); void eos_i2s_mic_set_wm(uint16_t wm); @@ -23,8 +25,8 @@ uint16_t eos_i2s_mic_len(void); uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize); int eos_i2s_mic_pop8(uint8_t *sample); int eos_i2s_mic_pop16(uint16_t *sample); -int eos_i2s_mic_vol_get(void); -void eos_i2s_mic_vol_set(int vol); +int eos_i2s_mic_get_vol(void); +void eos_i2s_mic_set_vol(int vol); void eos_i2s_spk_init(uint8_t *mic_arr, uint16_t mic_arr_size); void eos_i2s_spk_set_handler(eos_i2s_handler_t wm_handler); void eos_i2s_spk_set_wm(uint16_t wm); @@ -32,5 +34,5 @@ uint16_t eos_i2s_spk_len(void); uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize); int eos_i2s_spk_push8(uint8_t sample); int eos_i2s_spk_push16(uint16_t sample); -int eos_i2s_spk_vol_get(void); -void eos_i2s_spk_vol_set(int vol); +int eos_i2s_spk_get_vol(void); +void eos_i2s_spk_set_vol(int vol); diff --git a/fw/fe310/eos/soc/i2s_priv.h b/fw/fe310/eos/soc/i2s_priv.h index 25237c3..bc3cb1a 100644 --- a/fw/fe310/eos/soc/i2s_priv.h +++ b/fw/fe310/eos/soc/i2s_priv.h @@ -6,3 +6,12 @@ #define I2S_ABUF_OFF_IDXW 2 #define I2S_ABUF_OFF_SIZE 4 #define I2S_ABUF_OFF_ARRAY 8 + +#define I2S_IRQ_SD_ID INT_GPIO_BASE + I2S_PIN_INT + +#define I2S_CTRL_ADDR_CK PWM0_CTRL_ADDR +#define I2S_CTRL_ADDR_WS PWM1_CTRL_ADDR +#define I2S_CTRL_ADDR_SR_SEL PWM2_CTRL_ADDR + +#define I2S_IDLE1_CYCLES 4 +#define I2S_IDLE2_CYCLES 4 diff --git a/fw/fe310/eos/soc/trap_entry.S b/fw/fe310/eos/soc/trap_entry.S index 96024cb..7417254 100644 --- a/fw/fe310/eos/soc/trap_entry.S +++ b/fw/fe310/eos/soc/trap_entry.S @@ -8,6 +8,8 @@ #define PLIC_PRIORITY 0x0C000000 #define PLIC_THRESHOLD 0x0C200000 #define PLIC_CLAIM 0x0C200004 +#define PLIC_ENABLE1 0x0C002000 +#define PLIC_ENABLE2 0x0C002004 #define PWM0_CTRL_ADDR 0x10015000 #define PWM1_CTRL_ADDR 0x10025000 @@ -21,10 +23,18 @@ #define SPI1_CTRL_ADDR 0x10024000 #include "sifive/devices/spi.h" +#define INT_GPIO_BASE 8 #define INT_PWM0_BASE 40 #define INT_PWM1_BASE 44 #define INT_PWM2_BASE 48 +#define I2S_FMT (0*4) +#define I2S_MODE (1*4) +#define I2S_MIC_WM (2*4) +#define I2S_SPK_WM (3*4) +#define I2S_MIC_EVT (4*4) +#define I2S_SPK_EVT (5*4) + #include "board.h" #include "irq_def.h" #include "evt_def.h" @@ -32,12 +42,12 @@ #include "i2s_priv.h" #include "msgq_priv.h" - .section .data.entry + .section .itim.trap .align 4 -.global eos_trap_entry -eos_trap_entry: - addi sp, sp, -8*REGBYTES +.global eos_trap_vector +eos_trap_vector: + addi sp, sp, -12*REGBYTES STORE x8, 0*REGBYTES(sp) STORE x9, 1*REGBYTES(sp) STORE x18, 2*REGBYTES(sp) @@ -46,14 +56,16 @@ eos_trap_entry: STORE x21, 5*REGBYTES(sp) STORE x22, 6*REGBYTES(sp) STORE x23, 7*REGBYTES(sp) + STORE x24, 8*REGBYTES(sp) + STORE x25, 9*REGBYTES(sp) # channel: 0 - left; 1 - right + STORE x26, 10*REGBYTES(sp) # format: 0 - PCM16; 1 - ALAW + STORE x27, 11*REGBYTES(sp) # _eos_i2s_drvr addr csrr x8, mcause li x18, MCAUSE_EXT bne x8, x18, handle_intr li x18, PLIC_CLAIM lw x9, 0(x18) - li x18, I2S_IRQ_WS_ID - beq x9, x18, i2s_handle_ws li x18, I2S_IRQ_SD_ID beq x9, x18, i2s_handle_sd j handle_intr @@ -84,34 +96,33 @@ evtq_push: jalr x0, x21 i2s_handle_sd: - # exit if too early - li x18, I2S_CTRL_ADDR_WS_SPK - lw x8, PWM_COUNT(x18) - lw x9, PWM_CMP3(x18) - bltu x8, x9, i2s_handle_sd_exit + # store channel bit to x25 + li x18, I2S_CTRL_ADDR_WS + lw x18, PWM_CFG(x18) + li x19, (1 << 29) + and x25, x18, x19 + srli x25, x25, 29 - # disable sd irq - li x18, PLIC_PRIORITY - sw x0, 4*I2S_IRQ_SD_ID(x18) + bnez x25, i2s_sd_complete - la x9, _eos_i2s_fmt - lw x23, 0(x9) + la x27, _eos_i2s_drvr + lw x26, I2S_FMT(x27) i2s_abuf_pop: # pop from spk buf -> x8 - mv x8, x0 la x9, _eos_i2s_spk_buf lhu x18, I2S_ABUF_OFF_IDXR(x9) lhu x19, I2S_ABUF_OFF_IDXW(x9) lhu x20, I2S_ABUF_OFF_SIZE(x9) + beqz x20, i2s_sd_xchg - beq x18, x19, i2s_handle_sd_xchg + beq x18, x19, 2f addi x20, x20, -1 and x20, x20, x18 lw x21, I2S_ABUF_OFF_ARRAY(x9) add x21, x21, x20 - beqz x23, 0f + beqz x26, 0f lbu x8, 0(x21) addi x18, x18, 1 j 1f @@ -124,20 +135,18 @@ i2s_abuf_pop: 1: sh x18, I2S_ABUF_OFF_IDXR(x9) +2: li x21, 0xffff sub x18, x19, x18 and x18, x18, x21 # check for push to event queue - la x9, _eos_i2s_spk_wm - lw x20, 0(x9) - beqz x20, i2s_decode - bgtu x18, x20, i2s_decode + lw x9, I2S_SPK_WM(x27) + bgtu x18, x9, i2s_decode - la x9, _eos_i2s_spk_evt_enable - lw x18, 0(x9) - beqz x18, i2s_decode - sw x0, 0(x9) + lw x9, I2S_SPK_EVT(x27) + beqz x9, i2s_decode + sw x0, I2S_SPK_EVT(x27) # push to event queue jal x22, evtq_push @@ -146,13 +155,12 @@ i2s_abuf_pop: sb x18, MSGQ_ITEM_OFF_TYPE(x21) i2s_decode: - beqz x23, i2s_handle_sd_xchg + beqz x26, 3f # aLaw decode -> x8 xori x8, x8, 0x55 andi x9, x8, 0x80 beqz x9, 0f - li x9, 1 - slli x9, x9, 7 + li x9, (1 << 7) not x9, x9 and x8, x8, x9 li x9, -1 @@ -181,15 +189,18 @@ i2s_decode: slli x8, x8, 1 ori x8, x8, 1 2: - beqz x9, i2s_handle_sd_xchg + beqz x9, 3f mul x8, x8, x9 +3: -i2s_handle_sd_xchg: +i2s_sd_xchg: + # li x18, 0xa5a5 + # mv x8, x18 # read/write shift reg: x8 -> sr -> x8 li x18, GPIO_CTRL_ADDR li x19, (0x1 << I2S_PIN_SD_IN) li x20, (0x1 << I2S_PIN_SD_OUT) - li x21, (0x1 << I2S_PIN_CK_SR) + li x21, (0x1 << I2S_PIN_SR_CK) lw x22, GPIO_OUTPUT_VAL(x18) lw x9, GPIO_OUTPUT_EN(x18) @@ -202,8 +213,7 @@ i2s_handle_sd_xchg: li x23, 16 0: # write bit - li x9, 1 - slli x9, x9, 15 + li x9, (1 << 15) and x9, x8, x9 slli x8, x8, 1 #if I2S_PIN_SD_OUT > 15 @@ -214,38 +224,44 @@ i2s_handle_sd_xchg: and x22, x22, x20 or x22, x22, x9 +#if I2S_IDLE1_CYCLES + # idle + li x9, I2S_IDLE1_CYCLES +1: + addi x9, x9, -1 + bnez x9, 1b +#endif + # read bit lw x9, GPIO_INPUT_VAL(x18) and x9, x9, x19 srli x9, x9, I2S_PIN_SD_IN or x8, x8, x9 - # 74HC595 ck low (I2S_PIN_CK_SR high) + # 74HC595 ck low (I2S_PIN_SR_CK high) xor x22, x22, x21 sw x22, GPIO_OUTPUT_VAL(x18) # idle - li x9, I2S_IDLE_CYCLES + li x9, I2S_IDLE2_CYCLES 1: addi x9, x9, -1 bnez x9, 1b - # 74HC595 ck high (I2S_PIN_CK_SR low) + # 74HC595 ck high (I2S_PIN_SR_CK low) xor x22, x22, x21 sw x22, GPIO_OUTPUT_VAL(x18) + addi x23, x23, -1 + bnez x23, 0b + # idle - li x9, I2S_IDLE_CYCLES + li x9, I2S_IDLE2_CYCLES 1: addi x9, x9, -1 bnez x9, 1b - addi x23, x23, -1 - beqz x23, 2f - j 0b - -2: - # 74HC595 ck low (I2S_PIN_CK_SR high) + # 74HC595 ck low (I2S_PIN_SR_CK high) xor x22, x22, x21 sw x22, GPIO_OUTPUT_VAL(x18) @@ -256,11 +272,8 @@ i2s_handle_sd_xchg: slli x8, x8, 16 srai x8, x8, 16 - la x9, _eos_i2s_fmt - lw x23, 0(x9) - i2s_encode: - beqz x23, i2s_abuf_push + beqz x26, i2s_abuf_push # aLaw encode -> x8 li x18, 0x800 li x19, 7 @@ -297,17 +310,18 @@ i2s_abuf_push: lhu x18, I2S_ABUF_OFF_IDXR(x9) lhu x19, I2S_ABUF_OFF_IDXW(x9) lhu x20, I2S_ABUF_OFF_SIZE(x9) + beqz x20, i2s_sd_complete li x21, 0xffff sub x18, x19, x18 and x18, x18, x21 - beq x18, x20, i2s_handle_sd_exit + beq x18, x20, 2f addi x20, x20, -1 and x20, x20, x19 lw x21, I2S_ABUF_OFF_ARRAY(x9) add x21, x21, x20 - beqz x23, 0f + beqz x26, 0f sb x8, 0(x21) addi x19, x19, 1 addi x18, x18, 1 @@ -321,40 +335,27 @@ i2s_abuf_push: 1: sh x19, I2S_ABUF_OFF_IDXW(x9) +2: # check for push to event queue - la x9, _eos_i2s_mic_wm - lw x20, 0(x9) - beqz x20, i2s_handle_sd_exit - bltu x18, x20, i2s_handle_sd_exit + lw x9, I2S_MIC_WM(x27) + bltu x18, x9, i2s_sd_complete - la x9, _eos_i2s_mic_evt_enable - lw x18, 0(x9) - beqz x18, i2s_handle_sd_exit - sw x0, 0(x9) + lw x9, I2S_MIC_EVT(x27) + beqz x9, i2s_sd_complete + sw x0, I2S_MIC_EVT(x27) # push to event queue jal x22, evtq_push - beqz x21, i2s_handle_sd_exit + beqz x21, i2s_sd_complete li x18, (EOS_EVT_I2S | EOS_I2S_ETYPE_MIC) sb x18, MSGQ_ITEM_OFF_TYPE(x21) -i2s_handle_sd_exit: - # complete - li x18, I2S_IRQ_SD_ID - li x19, PLIC_CLAIM - sw x18, 0(x19) - - # exit - j trap_exit_data - -i2s_handle_ws: - # enable sd irq - li x18, PLIC_PRIORITY - li x19, IRQ_PRIORITY_I2S_SD - sw x19, 4*I2S_IRQ_SD_ID(x18) +i2s_sd_complete: + li x18, GPIO_CTRL_ADDR + li x19, (0x1 << I2S_PIN_INT) + sw x19, GPIO_FALL_IP(x18) - # complete - li x18, I2S_IRQ_WS_ID + li x18, I2S_IRQ_SD_ID li x19, PLIC_CLAIM sw x18, 0(x19) @@ -374,8 +375,8 @@ _eos_i2s_start_pwm: STORE x23, 7*REGBYTES(sp) li x18, I2S_CTRL_ADDR_CK - li x19, I2S_CTRL_ADDR_WS_MIC - li x20, I2S_CTRL_ADDR_WS_SPK + li x19, I2S_CTRL_ADDR_WS + li x20, I2S_CTRL_ADDR_SR_SEL li x21, PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | I2S_PWM_SCALE_CK li x22, PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | PWM_CFG_CMP2GANG li x23, PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP | PWM_CFG_CMP1GANG @@ -395,16 +396,6 @@ _eos_i2s_start_pwm: ret -.global _eos_flash_set -_eos_flash_set: - li a3, SPI0_CTRL_ADDR - sw x0, SPI_REG_FCTRL(a3) - sw a0, SPI_REG_SCKDIV(a3) - sw a1, SPI_REG_FFMT(a3) - li a0, 1 - sw a0, SPI_REG_FCTRL(a3) - ret - trap_exit_data: # Remain in M-mode after mret li x18, MSTATUS_MPP @@ -418,7 +409,11 @@ trap_exit_data: LOAD x21, 5*REGBYTES(sp) LOAD x22, 6*REGBYTES(sp) LOAD x23, 7*REGBYTES(sp) - addi sp, sp, 8*REGBYTES + LOAD x24, 8*REGBYTES(sp) + LOAD x25, 9*REGBYTES(sp) + LOAD x26, 10*REGBYTES(sp) + LOAD x27, 11*REGBYTES(sp) + addi sp, sp, 12*REGBYTES mret @@ -427,11 +422,11 @@ handle_intr: addi x18, x18, %lo(trap_entry_text) jalr x0, x18 - .section .text.entry + .section .text.trap .align 4 trap_entry_text: - addi sp, sp, -24*REGBYTES + addi sp, sp, -20*REGBYTES STORE x1, 0*REGBYTES(sp) STORE x2, 1*REGBYTES(sp) @@ -448,14 +443,10 @@ trap_entry_text: STORE x15, 12*REGBYTES(sp) STORE x16, 13*REGBYTES(sp) STORE x17, 14*REGBYTES(sp) - STORE x24, 15*REGBYTES(sp) - STORE x25, 16*REGBYTES(sp) - STORE x26, 17*REGBYTES(sp) - STORE x27, 18*REGBYTES(sp) - STORE x28, 19*REGBYTES(sp) - STORE x29, 20*REGBYTES(sp) - STORE x30, 21*REGBYTES(sp) - STORE x31, 22*REGBYTES(sp) + STORE x28, 15*REGBYTES(sp) + STORE x29, 16*REGBYTES(sp) + STORE x30, 17*REGBYTES(sp) + STORE x31, 18*REGBYTES(sp) li x18, MCAUSE_TIMER beq x8, x18, handle_timer @@ -473,7 +464,6 @@ handle_ext: call eos_intr_handle li x18, PLIC_CLAIM sw a0, 0(x18) - j trap_exit_text trap_exit_text: # Remain in M-mode after mret @@ -495,23 +485,23 @@ trap_exit_text: LOAD x15, 12*REGBYTES(sp) LOAD x16, 13*REGBYTES(sp) LOAD x17, 14*REGBYTES(sp) - LOAD x24, 15*REGBYTES(sp) - LOAD x25, 16*REGBYTES(sp) - LOAD x26, 17*REGBYTES(sp) - LOAD x27, 18*REGBYTES(sp) - LOAD x28, 19*REGBYTES(sp) - LOAD x29, 20*REGBYTES(sp) - LOAD x30, 21*REGBYTES(sp) - LOAD x31, 22*REGBYTES(sp) - - LOAD x8, 24*REGBYTES(sp) - LOAD x9, 25*REGBYTES(sp) - LOAD x18, 26*REGBYTES(sp) - LOAD x19, 27*REGBYTES(sp) - LOAD x20, 28*REGBYTES(sp) - LOAD x21, 29*REGBYTES(sp) - LOAD x22, 30*REGBYTES(sp) - LOAD x23, 31*REGBYTES(sp) + LOAD x28, 15*REGBYTES(sp) + LOAD x29, 16*REGBYTES(sp) + LOAD x30, 17*REGBYTES(sp) + LOAD x31, 18*REGBYTES(sp) + + LOAD x8, 20*REGBYTES(sp) + LOAD x9, 21*REGBYTES(sp) + LOAD x18, 22*REGBYTES(sp) + LOAD x19, 23*REGBYTES(sp) + LOAD x20, 24*REGBYTES(sp) + LOAD x21, 25*REGBYTES(sp) + LOAD x22, 26*REGBYTES(sp) + LOAD x23, 27*REGBYTES(sp) + LOAD x24, 28*REGBYTES(sp) + LOAD x25, 29*REGBYTES(sp) + LOAD x26, 30*REGBYTES(sp) + LOAD x27, 31*REGBYTES(sp) addi sp, sp, 32*REGBYTES mret |