diff options
author | Uros Majstorovic <majstor@majstor.org> | 2023-04-21 21:13:50 +0200 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2023-04-21 21:13:50 +0200 |
commit | a0059ab4365f41c84bb8bdf914477f5d4feeb985 (patch) | |
tree | 73baeb6706e44c8ccfe675fbf0001aa773af0a77 /fw/fe310/eos/soc | |
parent | 8c6001b298271bb52fa7142235ce7faa24b3e90e (diff) |
improved i2s driver
Diffstat (limited to 'fw/fe310/eos/soc')
-rw-r--r-- | fw/fe310/eos/soc/i2s.c | 109 | ||||
-rw-r--r-- | fw/fe310/eos/soc/i2s.h | 16 | ||||
-rw-r--r-- | fw/fe310/eos/soc/i2s_def.h | 5 | ||||
-rw-r--r-- | fw/fe310/eos/soc/trap_entry.S | 25 |
4 files changed, 98 insertions, 57 deletions
diff --git a/fw/fe310/eos/soc/i2s.c b/fw/fe310/eos/soc/i2s.c index 8416ec1..052efa2 100644 --- a/fw/fe310/eos/soc/i2s.c +++ b/fw/fe310/eos/soc/i2s.c @@ -192,9 +192,6 @@ void eos_i2s_start(uint32_t sample_rate) { I2S_REG_WS(PWM_COUNT) = 0; I2S_REG_SR_SEL(PWM_COUNT) = 0; - if (i2s_mic_handler) _eos_i2s_drvr[I2S_MIC_EVT] = 1; - if (i2s_spk_handler) _eos_i2s_drvr[I2S_SPK_EVT] = 1; - eos_eve_intr_disable(); eos_uart_disable(); eos_intr_set_priority(I2S_IRQ_SD_ID, IRQ_PRIORITY_I2S_SD); @@ -207,20 +204,11 @@ void eos_i2s_start(uint32_t sample_rate) { 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_SEL) |= I2S_PIN_PWM; GPIO_REG(GPIO_IOF_EN) |= iof_mask; _eos_i2s_start_pwm(); @@ -241,12 +229,6 @@ void eos_i2s_stop(void) { eos_intr_disable(I2S_IRQ_SD_ID); - 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); @@ -279,22 +261,32 @@ 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) { +void eos_i2s_mic_set_handler(eos_i2s_handler_t handler, uint16_t wm) { clear_csr(mstatus, MSTATUS_MIE); - _abuf_init(&_eos_i2s_mic_buf, mic_arr, mic_arr_size); + if ((i2s_mic_handler == NULL) && handler) _eos_i2s_drvr[I2S_MIC_EVT] = 1; + if (i2s_mic_handler && (handler == NULL)) _eos_i2s_drvr[I2S_MIC_EVT] = 0; + _eos_i2s_drvr[I2S_MIC_WM] = wm; + i2s_mic_handler = handler; set_csr(mstatus, MSTATUS_MIE); } -void eos_i2s_mic_set_handler(eos_i2s_handler_t wm_handler) { +void eos_i2s_mic_set_buf(uint8_t *mic_arr, uint16_t mic_arr_size) { + int run = eos_i2s_running(); + clear_csr(mstatus, MSTATUS_MIE); - i2s_mic_handler = wm_handler; + _abuf_init(&_eos_i2s_mic_buf, mic_arr, mic_arr_size); + if (run) { + if (mic_arr_size == 0) { + GPIO_REG(GPIO_IOF_EN) &= ~(1 << I2S_PIN_WS_MIC); + } else { + GPIO_REG(GPIO_IOF_EN) |= (1 << I2S_PIN_WS_MIC); + } + } set_csr(mstatus, MSTATUS_MIE); } -void eos_i2s_mic_set_wm(uint16_t wm) { - clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_drvr[I2S_MIC_WM] = wm; - set_csr(mstatus, MSTATUS_MIE); +uint8_t *eos_i2s_mic_get_buf(void) { + return _eos_i2s_mic_buf.array; } uint16_t eos_i2s_mic_len(void) { @@ -360,22 +352,32 @@ void eos_i2s_mic_set_vol(int vol) { set_csr(mstatus, MSTATUS_MIE); } -void eos_i2s_spk_init(uint8_t *spk_arr, uint16_t spk_arr_size) { +void eos_i2s_spk_set_handler(eos_i2s_handler_t handler, uint16_t wm) { clear_csr(mstatus, MSTATUS_MIE); - _abuf_init(&_eos_i2s_spk_buf, spk_arr, spk_arr_size); + if ((i2s_spk_handler == NULL) && handler) _eos_i2s_drvr[I2S_SPK_EVT] = 1; + if (i2s_spk_handler && (handler == NULL)) _eos_i2s_drvr[I2S_SPK_EVT] = 0; + _eos_i2s_drvr[I2S_SPK_WM] = wm; + i2s_spk_handler = handler; set_csr(mstatus, MSTATUS_MIE); } -void eos_i2s_spk_set_handler(eos_i2s_handler_t wm_handler) { +void eos_i2s_spk_set_buf(uint8_t *spk_arr, uint16_t spk_arr_size) { + int run = eos_i2s_running(); + clear_csr(mstatus, MSTATUS_MIE); - i2s_spk_handler = wm_handler; + _abuf_init(&_eos_i2s_spk_buf, spk_arr, spk_arr_size); + if (run) { + if (spk_arr_size == 0) { + GPIO_REG(GPIO_IOF_EN) &= ~(1 << I2S_PIN_WS_SPK); + } else { + GPIO_REG(GPIO_IOF_EN) |= (1 << I2S_PIN_WS_SPK); + } + } set_csr(mstatus, MSTATUS_MIE); } -void eos_i2s_spk_set_wm(uint16_t wm) { - clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_drvr[I2S_SPK_WM] = wm; - set_csr(mstatus, MSTATUS_MIE); +uint8_t *eos_i2s_spk_get_buf(void) { + return _eos_i2s_spk_buf.array; } uint16_t eos_i2s_spk_len(void) { @@ -388,23 +390,46 @@ uint16_t eos_i2s_spk_len(void) { return ret; } -uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize) { +uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize, uint8_t transform) { uint16_t i; - uint16_t _ssize = 0; + uint16_t abuf_free; + uint8_t transform_l, transform_r; clear_csr(mstatus, MSTATUS_MIE); - _ssize = MIN(ssize, _eos_i2s_spk_buf.size - _abuf_len(&_eos_i2s_spk_buf)); + abuf_free = _eos_i2s_spk_buf.size - _abuf_len(&_eos_i2s_spk_buf); + if (transform) abuf_free = abuf_free / 2; + ssize = MIN(ssize, abuf_free); set_csr(mstatus, MSTATUS_MIE); - for (i=0; i<_ssize; i++) { - _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i, _eos_i2s_spk_buf.size)] = sample[i]; + transform_l = (transform == EOS_I2S_TRANS_MONO2D) || (transform == EOS_I2S_TRANS_MONO2L); + transform_r = (transform == EOS_I2S_TRANS_MONO2D) || (transform == EOS_I2S_TRANS_MONO2R); + if (transform) { + if (_eos_i2s_drvr[I2S_FMT] == EOS_I2S_FMT_PCM16) { + for (i=0; i<ssize / 2; i++) { + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i * 4, _eos_i2s_spk_buf.size)] = transform_l ? sample[i * 2] : 0; + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i * 4 + 2, _eos_i2s_spk_buf.size)] = transform_r ? sample[i * 2] : 0; + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i * 4 + 1, _eos_i2s_spk_buf.size)] = transform_l ? sample[i * 2 + 1] : 0; + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i * 4 + 3, _eos_i2s_spk_buf.size)] = transform_r ? sample[i * 2 + 1] : 0; + } + } else { + for (i=0; i<ssize; i++) { + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i * 2, _eos_i2s_spk_buf.size)] = transform_l ? sample[i] : 0; + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i * 2 + 1, _eos_i2s_spk_buf.size)] = transform_r ? sample[i] : 0; + } + } + } else { + for (i=0; i<ssize; i++) { + _eos_i2s_spk_buf.array[EOS_ABUF_IDX_MASK(_eos_i2s_spk_buf.idx_w + i, _eos_i2s_spk_buf.size)] = sample[i]; + } } + if (transform) ssize *= 2; + clear_csr(mstatus, MSTATUS_MIE); - _eos_i2s_spk_buf.idx_w += _ssize; + _eos_i2s_spk_buf.idx_w += ssize; set_csr(mstatus, MSTATUS_MIE); - return _ssize; + return ssize; } int eos_i2s_spk_push8(uint8_t sample) { diff --git a/fw/fe310/eos/soc/i2s.h b/fw/fe310/eos/soc/i2s.h index a5a67df..c5e92b7 100644 --- a/fw/fe310/eos/soc/i2s.h +++ b/fw/fe310/eos/soc/i2s.h @@ -18,20 +18,22 @@ 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); + +void eos_i2s_mic_set_handler(eos_i2s_handler_t handler, uint16_t wm); +void eos_i2s_mic_set_buf(uint8_t *mic_arr, uint16_t mic_arr_size); +uint8_t *eos_i2s_mic_get_buf(void); 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_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); + +void eos_i2s_spk_set_handler(eos_i2s_handler_t handler, uint16_t wm); +void eos_i2s_spk_set_buf(uint8_t *spk_arr, uint16_t spk_arr_size); +uint8_t *eos_i2s_spk_get_buf(void); uint16_t eos_i2s_spk_len(void); -uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize); +uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize, uint8_t transform); int eos_i2s_spk_push8(uint8_t sample); int eos_i2s_spk_push16(uint16_t sample); int eos_i2s_spk_get_vol(void); diff --git a/fw/fe310/eos/soc/i2s_def.h b/fw/fe310/eos/soc/i2s_def.h index 3529be1..44eed25 100644 --- a/fw/fe310/eos/soc/i2s_def.h +++ b/fw/fe310/eos/soc/i2s_def.h @@ -6,3 +6,8 @@ #define EOS_I2S_ETYPE_MIC 1 #define EOS_I2S_ETYPE_SPK 2 + +#define EOS_I2S_TRANS_NONE 0 +#define EOS_I2S_TRANS_MONO2D 1 +#define EOS_I2S_TRANS_MONO2L 2 +#define EOS_I2S_TRANS_MONO2R 3
\ No newline at end of file diff --git a/fw/fe310/eos/soc/trap_entry.S b/fw/fe310/eos/soc/trap_entry.S index 7417254..1d3d1c2 100644 --- a/fw/fe310/eos/soc/trap_entry.S +++ b/fw/fe310/eos/soc/trap_entry.S @@ -99,12 +99,11 @@ i2s_handle_sd: # store channel bit to x25 li x18, I2S_CTRL_ADDR_WS lw x18, PWM_CFG(x18) + # 29th - pwmcmp1ip bit li x19, (1 << 29) and x25, x18, x19 srli x25, x25, 29 - bnez x25, i2s_sd_complete - la x27, _eos_i2s_drvr lw x26, I2S_FMT(x27) @@ -123,10 +122,12 @@ i2s_abuf_pop: lw x21, I2S_ABUF_OFF_ARRAY(x9) add x21, x21, x20 beqz x26, 0f + mv x22, x18 lbu x8, 0(x21) addi x18, x18, 1 j 1f 0: + srli x22, x18, 1 lb x8, 0(x21) lbu x20, 1(x21) slli x8, x8, 8 @@ -135,6 +136,13 @@ i2s_abuf_pop: 1: sh x18, I2S_ABUF_OFF_IDXR(x9) + # check for correct channel if mode is stereo + lw x21, I2S_MODE(x27) + bnez x21, 2f + andi x22, x22, 1 + xor x22, x22, x25 + beqz x22, i2s_abuf_pop + 2: li x21, 0xffff sub x18, x19, x18 @@ -194,13 +202,11 @@ i2s_decode: 3: 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_SR_CK) + li x19, (1 << I2S_PIN_SD_IN) + li x20, (1 << I2S_PIN_SD_OUT) + li x21, (1 << I2S_PIN_SR_CK) lw x22, GPIO_OUTPUT_VAL(x18) lw x9, GPIO_OUTPUT_EN(x18) @@ -272,6 +278,9 @@ i2s_sd_xchg: slli x8, x8, 16 srai x8, x8, 16 + # skip right channel + bnez x25, i2s_sd_complete + i2s_encode: beqz x26, i2s_abuf_push # aLaw encode -> x8 @@ -352,7 +361,7 @@ i2s_abuf_push: i2s_sd_complete: li x18, GPIO_CTRL_ADDR - li x19, (0x1 << I2S_PIN_INT) + li x19, (1 << I2S_PIN_INT) sw x19, GPIO_FALL_IP(x18) li x18, I2S_IRQ_SD_ID |