summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2019-10-16 13:15:11 +0200
committerUros Majstorovic <majstor@majstor.org>2019-10-16 13:15:11 +0200
commitb7a007eb9d3548e2bcd141681a91b8a748d3ce49 (patch)
tree44989cf767870a7a19e02796b29ab7e70bff4e24
parent68d4d71ca06654bfa35603fcc7fc090220d87693 (diff)
i2s has pcm 16bit audio format
-rw-r--r--code/fe310/eos/i2s.c57
-rw-r--r--code/fe310/eos/i2s.h10
-rw-r--r--code/fe310/eos/msgq_def.h10
-rw-r--r--code/fe310/eos/trap_entry.S44
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