summaryrefslogtreecommitdiff
path: root/fw/fe310/eos
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2022-09-04 18:22:50 +0200
committerUros Majstorovic <majstor@majstor.org>2022-09-04 18:22:50 +0200
commit838c430635b146a545033bf4f4552c02958508f2 (patch)
treef305dbe0d6757453cdfd42b25de8097070787ff3 /fw/fe310/eos
parent4c96cd2d5f7cb8de7d48b5dbd728af7fda572d9d (diff)
new stereo audio driver
Diffstat (limited to 'fw/fe310/eos')
-rw-r--r--fw/fe310/eos/soc/i2s.c293
-rw-r--r--fw/fe310/eos/soc/i2s.h12
-rw-r--r--fw/fe310/eos/soc/i2s_priv.h9
-rw-r--r--fw/fe310/eos/soc/trap_entry.S224
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