From 5fe913c88d8c1781de336cca3949142bd9fc370d Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Wed, 14 Mar 2018 19:08:00 +0100 Subject: i2s driver added; new amd trap entry vector added --- code/fe310/eos/i2s.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 code/fe310/eos/i2s.c (limited to 'code/fe310/eos/i2s.c') diff --git a/code/fe310/eos/i2s.c b/code/fe310/eos/i2s.c new file mode 100644 index 0000000..98e2ffa --- /dev/null +++ b/code/fe310/eos/i2s.c @@ -0,0 +1,211 @@ +#include + +#include "encoding.h" +#include "platform.h" + +#include "eos.h" +#include "interrupt.h" +#include "event.h" + +#include "i2s.h" +#include "i2s_def.h" + +#define I2S_PWM_REG_CK PWM1_REG +#define I2S_PWM_REG_WS PWM2_REG + +#define EOS_ABUF_IDX_MASK(IDX, SIZE) ((IDX) & ((SIZE) - 1)) + +EOSABuf _eos_i2s_mic_buf; +EOSABuf _eos_i2s_spk_buf; +uint16_t _eos_i2s_mic_wm; +uint16_t _eos_i2s_spk_wm; +uint32_t _eos_i2s_ck_period; +uint32_t _eos_i2s_mic_volume = 3; +static eos_evt_fptr_t evt_handler[I2S_MAX_HANDLER]; + +static void _abuf_init(EOSABuf *buf, uint8_t *array, uint16_t size) { + buf->idx_r = 0; + buf->idx_w = 0; + buf->size = size; + buf->array = array; +} + +static int _abuf_push(EOSABuf *buf, uint8_t sample) { + if (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; + buf->idx_w++; + return EOS_OK; +} + +static int _abuf_pop(EOSABuf *buf, uint8_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)]; + buf->idx_r++; + return EOS_OK; + } +} + +static uint16_t _abuf_read(EOSABuf *buf, uint8_t *sample, uint16_t ssize) { + uint16_t i; + + for (i=0; iidx_r == buf->idx_w) break; + sample[i] = buf->array[EOS_ABUF_IDX_MASK(buf->idx_r, buf->size)]; + buf->idx_r++; + } + return i; +} + +static uint16_t _abuf_write(EOSABuf *buf, uint8_t *sample, uint16_t ssize) { + uint16_t i; + + for (i=0; iidx_w - buf->idx_r == buf->size) break; + buf->array[EOS_ABUF_IDX_MASK(buf->idx_w, buf->size)] = sample[i]; + buf->idx_w++; + } + return i; +} + +static uint16_t _abuf_len(EOSABuf *buf) { + return buf->idx_w - buf->idx_r; +} + +static void audio_handler(unsigned char cmd, unsigned char *buffer, uint16_t len) { + if ((cmd & ~EOS_EVT_MASK) < I2S_MAX_HANDLER) { + evt_handler[cmd & ~EOS_EVT_MASK](cmd, buffer, len); + } else { + eos_evtq_bad_handler(cmd, buffer, len); + } +} + +void eos_i2s_init(void) { + int i; + unsigned long f = get_cpu_freq(); + + _eos_i2s_ck_period = 512; + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_LR); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_LR); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_LR); + + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_CK); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_CK); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_CK); + + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_WS); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_WS); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_WS); + + GPIO_REG(GPIO_INPUT_EN) |= (1 << I2S_PIN_SD); + GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_SD); + GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << I2S_PIN_SD); + + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_LR); + + I2S_PWM_REG_CK(PWM_CFG) = 0; + I2S_PWM_REG_CK(PWM_COUNT) = 0; + I2S_PWM_REG_CK(PWM_CMP0) = _eos_i2s_ck_period - 1; + I2S_PWM_REG_CK(PWM_CMP1) = I2S_PWM_REG_CK(PWM_CMP0) / 2; + I2S_PWM_REG_CK(PWM_CMP2) = I2S_PWM_REG_CK(PWM_CMP0) / 4; + + I2S_PWM_REG_WS(PWM_CFG) = 0; + I2S_PWM_REG_WS(PWM_COUNT) = 0; + I2S_PWM_REG_WS(PWM_CMP0) = _eos_i2s_ck_period * 64 - 1; + I2S_PWM_REG_WS(PWM_CMP1) = I2S_PWM_REG_WS(PWM_CMP0) / 2; + I2S_PWM_REG_WS(PWM_CMP2) = I2S_PWM_REG_WS(PWM_CMP0) - 1024; + + eos_intr_set(I2S_IRQ_SD_ID, I2S_IRQ_SD_PRIORITY, NULL); + eos_intr_set(I2S_IRQ_CK_ID, I2S_IRQ_CK_PRIORITY, NULL); + eos_intr_set(I2S_IRQ_WS_ID, I2S_IRQ_WS_PRIORITY, NULL); + eos_intr_set(I2S_IRQ_CI_ID, I2S_IRQ_CI_PRIORITY, NULL); + + for (i=0; i