diff options
author | Uros Majstorovic <majstor@majstor.org> | 2019-10-16 13:15:11 +0200 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2019-10-16 13:15:11 +0200 |
commit | b7a007eb9d3548e2bcd141681a91b8a748d3ce49 (patch) | |
tree | 44989cf767870a7a19e02796b29ab7e70bff4e24 /code/fe310/eos | |
parent | 68d4d71ca06654bfa35603fcc7fc090220d87693 (diff) |
i2s has pcm 16bit audio format
Diffstat (limited to 'code/fe310/eos')
-rw-r--r-- | code/fe310/eos/i2s.c | 57 | ||||
-rw-r--r-- | code/fe310/eos/i2s.h | 10 | ||||
-rw-r--r-- | code/fe310/eos/msgq_def.h | 10 | ||||
-rw-r--r-- | code/fe310/eos/trap_entry.S | 44 |
4 files changed, 97 insertions, 24 deletions
diff --git a/code/fe310/eos/i2s.c b/code/fe310/eos/i2s.c index 0eb5353..0bd818a 100644 --- a/code/fe310/eos/i2s.c +++ b/code/fe310/eos/i2s.c @@ -22,6 +22,7 @@ EOSABuf _eos_i2s_mic_buf; EOSABuf _eos_i2s_spk_buf; +uint32_t _eos_i2s_fmt = 0; uint32_t _eos_i2s_ck_period = 0; uint32_t _eos_i2s_mic_volume = 0; uint32_t _eos_i2s_spk_volume = 0; @@ -40,7 +41,7 @@ static void _abuf_init(EOSABuf *buf, uint8_t *array, uint16_t size) { buf->array = array; } -static int _abuf_push(EOSABuf *buf, uint8_t sample) { +static int _abuf_push8(EOSABuf *buf, uint8_t sample) { if ((uint16_t)(buf->idx_w - buf->idx_r) == buf->size) return EOS_ERR_Q_FULL; buf->array[EOS_ABUF_IDX_MASK(buf->idx_w, buf->size)] = sample; @@ -48,7 +49,16 @@ static int _abuf_push(EOSABuf *buf, uint8_t sample) { return EOS_OK; } -static int _abuf_pop(EOSABuf *buf, uint8_t *sample) { +static int _abuf_push16(EOSABuf *buf, uint16_t sample) { + if ((uint16_t)(buf->idx_w - buf->idx_r) == buf->size) return EOS_ERR_Q_FULL; + + buf->array[EOS_ABUF_IDX_MASK(buf->idx_w, buf->size)] = sample >> 8; + buf->array[EOS_ABUF_IDX_MASK(buf->idx_w + 1, buf->size)] = sample & 0xFF; + buf->idx_w += 2; + return EOS_OK; +} + +static int _abuf_pop8(EOSABuf *buf, uint8_t *sample) { if (buf->idx_r == buf->idx_w) { return EOS_ERR_Q_EMPTY; } else { @@ -58,6 +68,18 @@ static int _abuf_pop(EOSABuf *buf, uint8_t *sample) { } } +static int _abuf_pop16(EOSABuf *buf, uint16_t *sample) { + if (buf->idx_r == buf->idx_w) { + return EOS_ERR_Q_EMPTY; + } else { + *sample = buf->array[EOS_ABUF_IDX_MASK(buf->idx_r, buf->size)] << 8; + *sample |= buf->array[EOS_ABUF_IDX_MASK(buf->idx_r + 1, buf->size)]; + buf->idx_r += 2; + return EOS_OK; + } +} + + static void _abuf_flush(EOSABuf *buf) { buf->idx_r = 0; buf->idx_w = 0; @@ -218,6 +240,14 @@ void eos_i2s_stop(void) { GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << I2S_PIN_CK_SW); } +void eos_i2s_set_fmt(unsigned char fmt) { + clear_csr(mstatus, MSTATUS_MIE); + _eos_i2s_fmt = fmt; + _abuf_flush(&_eos_i2s_mic_buf); + _abuf_flush(&_eos_i2s_spk_buf); + set_csr(mstatus, MSTATUS_MIE); +} + void eos_i2s_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size) { clear_csr(mstatus, MSTATUS_MIE); _abuf_init(&_eos_i2s_mic_buf, mic_arr, mic_arr_size); @@ -263,9 +293,16 @@ uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize) { return _ssize; } -int eos_i2s_mic_pop(uint8_t *sample) { +int eos_i2s_mic_pop8(uint8_t *sample) { + clear_csr(mstatus, MSTATUS_MIE); + int ret = _abuf_pop8(&_eos_i2s_mic_buf, sample); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + +int eos_i2s_mic_pop16(uint16_t *sample) { clear_csr(mstatus, MSTATUS_MIE); - int ret = _abuf_pop(&_eos_i2s_mic_buf, sample); + int ret = _abuf_pop16(&_eos_i2s_mic_buf, sample); set_csr(mstatus, MSTATUS_MIE); return ret; } @@ -314,9 +351,17 @@ uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize) { return _ssize; } -int eos_i2s_spk_push(uint8_t sample) { +int eos_i2s_spk_push8(uint8_t sample) { clear_csr(mstatus, MSTATUS_MIE); - int ret = _abuf_push(&_eos_i2s_spk_buf, sample); + int ret = _abuf_push8(&_eos_i2s_spk_buf, sample); set_csr(mstatus, MSTATUS_MIE); return ret; } + +int eos_i2s_spk_push16(uint16_t sample) { + clear_csr(mstatus, MSTATUS_MIE); + int ret = _abuf_push16(&_eos_i2s_spk_buf, sample); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + diff --git a/code/fe310/eos/i2s.h b/code/fe310/eos/i2s.h index b9f2e02..09b9228 100644 --- a/code/fe310/eos/i2s.h +++ b/code/fe310/eos/i2s.h @@ -1,5 +1,8 @@ #include <stdint.h> +#define EOS_I2S_FMT_ALAW 0 +#define EOS_I2S_FMT_PCM16 1 + typedef struct EOSABuf { uint16_t idx_r; uint16_t idx_w; @@ -12,15 +15,18 @@ typedef void (*eos_i2s_fptr_t) (unsigned char); void eos_i2s_init(uint32_t sample_rate); void eos_i2s_start(void); void eos_i2s_stop(void); +void eos_i2s_set_fmt(unsigned char fmt); void eos_i2s_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size); void eos_i2s_mic_set_handler(eos_i2s_fptr_t wm_handler); void eos_i2s_mic_set_wm(uint16_t wm); uint16_t eos_i2s_mic_len(void); uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize); -int eos_i2s_mic_pop(uint8_t *sample); +int eos_i2s_mic_pop8(uint8_t *sample); +int eos_i2s_mic_pop16(uint16_t *sample); void eos_i2s_spk_init(uint8_t *mic_arr, uint16_t mic_arr_size); void eos_i2s_spk_set_handler(eos_i2s_fptr_t wm_handler); void eos_i2s_spk_set_wm(uint16_t wm); uint16_t eos_i2s_spk_len(void); uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize); -int eos_i2s_spk_push(uint8_t sample); +int eos_i2s_spk_push8(uint8_t sample); +int eos_i2s_spk_push16(uint16_t sample); diff --git a/code/fe310/eos/msgq_def.h b/code/fe310/eos/msgq_def.h index 53d71f2..2ad5fc5 100644 --- a/code/fe310/eos/msgq_def.h +++ b/code/fe310/eos/msgq_def.h @@ -1,10 +1,10 @@ /* asm */ -#define MSGQ_OFF_IDXR 0 -#define MSGQ_OFF_IDXW 1 -#define MSGQ_OFF_SIZE 2 -#define MSGQ_OFF_ARRAY 4 -#define MSGQ_ITEM_SIZE 12 +#define MSGQ_OFF_IDXR 0 +#define MSGQ_OFF_IDXW 1 +#define MSGQ_OFF_SIZE 2 +#define MSGQ_OFF_ARRAY 4 #define MSGQ_ITEM_OFF_TYPE 0 #define MSGQ_ITEM_OFF_BUF 4 #define MSGQ_ITEM_OFF_SIZE 8 +#define MSGQ_ITEM_SIZE 12 diff --git a/code/fe310/eos/trap_entry.S b/code/fe310/eos/trap_entry.S index 650c45b..c3b7104 100644 --- a/code/fe310/eos/trap_entry.S +++ b/code/fe310/eos/trap_entry.S @@ -76,7 +76,7 @@ evtq_push: lbu x18, MSGQ_OFF_IDXR(x9) lbu x19, MSGQ_OFF_IDXW(x9) lbu x20, MSGQ_OFF_SIZE(x9) - + sub x18, x19, x18 andi x18, x18, 0xff beq x18, x20, 0f @@ -107,8 +107,11 @@ i2s_handler_sd: li x18, PLIC_PRIORITY sw x0, 4*I2S_IRQ_SD_ID(x18) + la x9, _eos_i2s_fmt + lw x23, 0(x9) + +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) @@ -121,14 +124,20 @@ i2s_handler_sd: lw x21, I2S_ABUF_OFF_ARRAY(x9) add x21, x21, x20 lbu x8, 0(x21) - addi x18, x18, 1 + beqz x23, 0f + slli x8, x8, 8 + lbu x22, 1(x21) + or x8, x8, x22 + addi x18, x18, 1 + +0: sh x18, I2S_ABUF_OFF_IDXR(x9) - + 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) @@ -145,7 +154,9 @@ i2s_handler_sd: beqz x21, i2s_decode li x18, (EOS_EVT_AUDIO | I2S_ETYPE_SPK) sb x18, MSGQ_ITEM_OFF_TYPE(x21) - + + bnez x23, i2s_handler_sd_xchg + i2s_decode: # aLaw decode -> x8 xori x8, x8, 0x55 @@ -255,6 +266,10 @@ i2s_handler_sd_xchg: and x9, x9, x20 sw x9, GPIO_OUTPUT_EN(x18) + la x9, _eos_i2s_fmt + lw x23, 0(x9) + bnez x23, i2s_abuf_push + i2s_encode: # aLaw encode -> x8 li x18, 0x800 @@ -286,6 +301,7 @@ i2s_encode: xori x8, x8, 0x55 andi x8, x8, 0xff +i2s_abuf_push: # push to mic buf la x9, _eos_i2s_mic_buf lhu x18, I2S_ABUF_OFF_IDXR(x9) @@ -300,13 +316,19 @@ i2s_encode: addi x20, x20, -1 and x20, x20, x19 lw x21, I2S_ABUF_OFF_ARRAY(x9) - add x20, x21, x20 - + add x21, x21, x20 + add x21, x21, x23 + sb x8, 0(x21) addi x19, x19, 1 - sh x19, I2S_ABUF_OFF_IDXW(x9) - - sb x8, 0(x20) addi x18, x18, 1 + beqz x23, 0f + srli x8, x8, 8 + sb x8, -1(x21) + addi x19, x19, 1 + addi x18, x18, 1 + +0: + sh x19, I2S_ABUF_OFF_IDXW(x9) # check for push to event queue la x9, _eos_i2s_mic_wm |