From 0a5f8363fe4e6b3c7d4f17fde61e00ab63e43bcb Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Mon, 21 Mar 2022 02:24:59 +0100 Subject: i2s stereo driver --- fw/fe310/eos/board.h | 8 +-- fw/fe310/eos/eos.c | 4 +- fw/fe310/eos/eve/eve.c | 10 +-- fw/fe310/eos/i2s.c | 52 +++++++++++---- fw/fe310/eos/trap_entry.S | 163 +++++++++++++++++++++++++++------------------- 5 files changed, 146 insertions(+), 91 deletions(-) (limited to 'fw/fe310/eos') diff --git a/fw/fe310/eos/board.h b/fw/fe310/eos/board.h index a695029..a18b58f 100644 --- a/fw/fe310/eos/board.h +++ b/fw/fe310/eos/board.h @@ -30,14 +30,14 @@ #define I2S_PIN_SD_IN 13 #define I2S_PIN_SD_OUT 12 -#define I2S_IRQ_WS_ID (INT_PWM2_BASE + 0) -#define I2S_IRQ_SD_ID (INT_PWM2_BASE + 3) +#define I2S_IRQ_WS_ID (INT_PWM1_BASE + 0) +#define I2S_IRQ_SD_ID (INT_PWM1_BASE + 3) #define I2S_CTRL_ADDR_CK PWM0_CTRL_ADDR #define I2S_CTRL_ADDR_WS_MIC PWM1_CTRL_ADDR #define I2S_CTRL_ADDR_WS_SPK PWM2_CTRL_ADDR -#define I2S_IDLE_CYCLES 8 +#define I2S_IDLE_CYCLES 1 #define CTP_PIN_INT 1 #define CTP_PIN_RST 19 @@ -46,5 +46,5 @@ #define EVE_GPIO_CAM 0 #define EVE_GPIO_LCD_EN 1 -#define EVE_GPIO_GAIN_SEL 2 +#define EVE_GPIO_GAIN 2 #define EVE_GPIO_HAPT 3 diff --git a/fw/fe310/eos/eos.c b/fw/fe310/eos/eos.c index bf0f0da..b52ed93 100644 --- a/fw/fe310/eos/eos.c +++ b/fw/fe310/eos/eos.c @@ -28,13 +28,13 @@ void eos_init(void) { int touch_calibrate = 0; int rv; - printf("INIT:%d\n", wakeup_cause); - eos_evtq_init(wakeup_cause); eos_intr_init(wakeup_cause); eos_timer_init(wakeup_cause); eos_uart_init(wakeup_cause); + printf("INIT:%d\n", wakeup_cause); + rv = eos_pwr_init(wakeup_cause); if (rv) printf("PWR INIT ERR:%d\n", rv); rv = eos_i2s_init(wakeup_cause); diff --git a/fw/fe310/eos/eve/eve.c b/fw/fe310/eos/eve/eve.c index 91458d8..e1191fc 100644 --- a/fw/fe310/eos/eve/eve.c +++ b/fw/fe310/eos/eve/eve.c @@ -458,27 +458,27 @@ void eve_brightness(uint8_t b) { int eve_gpio_get(int gpio) { uint16_t reg = eve_read16(REG_GPIOX); + return !!(reg & (1 << gpio)); } void eve_gpio_set(int gpio, int val) { uint16_t reg = eve_read16(REG_GPIOX); uint16_t reg_val = (1 << gpio); - if (val) { - reg |= reg_val; - } else { - reg &= ~reg_val; - } + + reg = val ? reg | reg_val : reg & ~reg_val; eve_write16(REG_GPIOX, reg); } uint8_t eve_gpio_get_dir(void) { uint16_t reg = eve_read16(REG_GPIOX_DIR); + return reg & 0x000f; } void eve_gpio_set_dir(uint8_t dir) { uint16_t reg = eve_read16(REG_GPIOX_DIR); + reg &= 0xfff0; reg |= dir & 0x0f; eve_write16(REG_GPIOX_DIR, reg); diff --git a/fw/fe310/eos/i2s.c b/fw/fe310/eos/i2s.c index 5e5eaa7..9cc32e0 100644 --- a/fw/fe310/eos/i2s.c +++ b/fw/fe310/eos/i2s.c @@ -28,6 +28,8 @@ EOSABuf _eos_i2s_mic_buf; EOSABuf _eos_i2s_spk_buf; uint32_t _eos_i2s_fmt = 0; +uint32_t _eos_i2s_mode = 0; +uint32_t _eos_i2s_sample = 0; uint32_t _eos_i2s_mic_wm = 0; uint32_t _eos_i2s_spk_wm = 0; uint32_t _eos_i2s_mic_evt_enable = 0; @@ -102,12 +104,14 @@ static void i2s_handle_evt(unsigned char type, unsigned char *buffer, uint16_t l _eos_i2s_mic_evt_enable = 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); break; + default: eos_evtq_bad_handler(type, buffer, len); break; @@ -125,12 +129,10 @@ static void _spk_vol_set(uint8_t vol) { 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; 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); } } @@ -140,6 +142,10 @@ 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); + I2S_REG_CK(PWM_CFG) = 0; + I2S_REG_WS_MIC(PWM_CFG) = 0; + I2S_REG_WS_SPK(PWM_CFG) = 0; + eos_i2s_init_mux(); GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_CK_SW); @@ -202,10 +208,10 @@ void eos_i2s_start(uint32_t sample_rate, unsigned char fmt) { _eos_i2s_mic_evt_enable = 1; _eos_i2s_spk_evt_enable = 1; + eos_intr_set_priority(I2S_IRQ_SD_ID, IRQ_PRIORITY_I2S_SD); 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_intr_enable(I2S_IRQ_SD_ID); + eos_intr_enable(I2S_IRQ_WS_ID); _eos_i2s_start_pwm(); /* @@ -214,9 +220,13 @@ void eos_i2s_start(uint32_t sample_rate, unsigned char fmt) { I2S_REG_WS_SPK(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; + GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_WS_MIC); + 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_CK_SR); + GPIO_REG(GPIO_IOF_SEL) |= I2S_PIN_PWM; + GPIO_REG(GPIO_IOF_EN) |= I2S_PIN_PWM; } void eos_i2s_stop(void) { @@ -229,8 +239,7 @@ void eos_i2s_stop(void) { _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); eos_intr_disable(I2S_IRQ_SD_ID); @@ -239,10 +248,13 @@ void eos_i2s_stop(void) { GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_WS_SPK); GPIO_REG(GPIO_IOF_EN) &= ~I2S_PIN_PWM; + + eos_i2s_mic_set_wm(0); + eos_i2s_spk_set_wm(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_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size) { @@ -291,16 +303,22 @@ 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; } @@ -364,16 +382,22 @@ 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; } diff --git a/fw/fe310/eos/trap_entry.S b/fw/fe310/eos/trap_entry.S index 96024cb..506683b 100644 --- a/fw/fe310/eos/trap_entry.S +++ b/fw/fe310/eos/trap_entry.S @@ -37,7 +37,7 @@ .global eos_trap_entry eos_trap_entry: - addi sp, sp, -8*REGBYTES + addi sp, sp, -10*REGBYTES STORE x8, 0*REGBYTES(sp) STORE x9, 1*REGBYTES(sp) STORE x18, 2*REGBYTES(sp) @@ -46,6 +46,8 @@ 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) csrr x8, mcause li x18, MCAUSE_EXT @@ -84,34 +86,62 @@ 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 + li x9, I2S_CTRL_ADDR_WS_MIC + lw x18, PWM_COUNT(x9) + lw x19, PWM_CMP1(x9) + lw x20, PWM_CMP2(x9) + lw x21, PWM_CMP3(x9) - # disable sd irq - li x18, PLIC_PRIORITY - sw x0, 4*I2S_IRQ_SD_ID(x18) + # exit if too early + bltu x18, x21, i2s_sd_exit + + # move CMPs for next channel and store parity to x25 + li x25, 0 + bltu x20, x19, 0f + li x25, 1 + neg x19, x19 + li x22, PLIC_PRIORITY + sw x0, 4*I2S_IRQ_SD_ID(x22) +0: + add x20, x20, x19 + add x21, x21, x19 + sw x20, PWM_CMP2(x9) + sw x21, PWM_CMP3(x9) la x9, _eos_i2s_fmt - lw x23, 0(x9) + lw x24, 0(x9) i2s_abuf_pop: - # pop from spk buf -> x8 + la x9, _eos_i2s_mode + lw x22, 0(x9) + and x22, x22, x25 + beqz x22, 0f + + la x9, _eos_i2s_sample + lw x8, 0(x9) + j i2s_sd_xchg + +0: mv x8, x0 + + # check for pop from spk buf + la x9, _eos_i2s_spk_wm + lw x22, 0(x9) + beqz x22, i2s_sd_xchg + + # pop from spk buf -> x8 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) - 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 x24, 0f lbu x8, 0(x21) addi x18, x18, 1 j 1f @@ -124,15 +154,13 @@ 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 + bgtu x18, x22, i2s_decode la x9, _eos_i2s_spk_evt_enable lw x18, 0(x9) @@ -146,7 +174,7 @@ i2s_abuf_pop: sb x18, MSGQ_ITEM_OFF_TYPE(x21) i2s_decode: - beqz x23, i2s_handle_sd_xchg + beqz x24, 3f # aLaw decode -> x8 xori x8, x8, 0x55 andi x9, x8, 0x80 @@ -181,10 +209,13 @@ 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: + la x9, _eos_i2s_sample + sw x8, 0(x9) -i2s_handle_sd_xchg: +i2s_sd_xchg: # read/write shift reg: x8 -> sr -> x8 li x18, GPIO_CTRL_ADDR li x19, (0x1 << I2S_PIN_SD_IN) @@ -234,17 +265,15 @@ i2s_handle_sd_xchg: xor x22, x22, x21 sw x22, GPIO_OUTPUT_VAL(x18) + addi x23, x23, -1 + bnez x23, 0b + # idle li x9, I2S_IDLE_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) xor x22, x22, x21 sw x22, GPIO_OUTPUT_VAL(x18) @@ -256,11 +285,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 x24, i2s_abuf_push # aLaw encode -> x8 li x18, 0x800 li x19, 7 @@ -292,6 +318,14 @@ i2s_encode: andi x8, x8, 0xff i2s_abuf_push: + # check parity + # bnez x25, i2s_sd_exit + + # check for push to mic buf + la x9, _eos_i2s_mic_wm + lw x22, 0(x9) + beqz x22, i2s_sd_exit + # push to mic buf la x9, _eos_i2s_mic_buf lhu x18, I2S_ABUF_OFF_IDXR(x9) @@ -301,13 +335,13 @@ i2s_abuf_push: 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 x24, 0f sb x8, 0(x21) addi x19, x19, 1 addi x18, x18, 1 @@ -321,24 +355,22 @@ 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 + bltu x18, x22, i2s_sd_exit la x9, _eos_i2s_mic_evt_enable lw x18, 0(x9) - beqz x18, i2s_handle_sd_exit + beqz x18, i2s_sd_exit sw x0, 0(x9) # push to event queue jal x22, evtq_push - beqz x21, i2s_handle_sd_exit + beqz x21, i2s_sd_exit li x18, (EOS_EVT_I2S | EOS_I2S_ETYPE_MIC) sb x18, MSGQ_ITEM_OFF_TYPE(x21) -i2s_handle_sd_exit: +i2s_sd_exit: # complete li x18, I2S_IRQ_SD_ID li x19, PLIC_CLAIM @@ -418,7 +450,9 @@ 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) + addi sp, sp, 10*REGBYTES mret @@ -431,7 +465,7 @@ handle_intr: .align 4 trap_entry_text: - addi sp, sp, -24*REGBYTES + addi sp, sp, -22*REGBYTES STORE x1, 0*REGBYTES(sp) STORE x2, 1*REGBYTES(sp) @@ -448,14 +482,12 @@ 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 x26, 15*REGBYTES(sp) + STORE x27, 16*REGBYTES(sp) + STORE x28, 17*REGBYTES(sp) + STORE x29, 18*REGBYTES(sp) + STORE x30, 19*REGBYTES(sp) + STORE x31, 20*REGBYTES(sp) li x18, MCAUSE_TIMER beq x8, x18, handle_timer @@ -473,7 +505,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 +526,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 x26, 15*REGBYTES(sp) + LOAD x27, 16*REGBYTES(sp) + LOAD x28, 17*REGBYTES(sp) + LOAD x29, 18*REGBYTES(sp) + LOAD x30, 19*REGBYTES(sp) + LOAD x31, 20*REGBYTES(sp) + + LOAD x8, 22*REGBYTES(sp) + LOAD x9, 23*REGBYTES(sp) + LOAD x18, 24*REGBYTES(sp) + LOAD x19, 25*REGBYTES(sp) + LOAD x20, 26*REGBYTES(sp) + LOAD x21, 27*REGBYTES(sp) + LOAD x22, 28*REGBYTES(sp) + LOAD x23, 29*REGBYTES(sp) + LOAD x24, 30*REGBYTES(sp) + LOAD x25, 31*REGBYTES(sp) addi sp, sp, 32*REGBYTES mret -- cgit v1.2.3