From f05df1f97b60293e90e14c5f8ac189e1c78e59c5 Mon Sep 17 00:00:00 2001 From: "kyle.hu.gz" Date: Thu, 11 Mar 2010 19:19:32 +0000 Subject: [PATCH] Fixed some major problem under CODEC_MASTER_MODE. Removed IIS interrupt mode code. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@480 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- bsp/stm32_radio/codec.c | 244 ++++++++++++++------------------- bsp/stm32_radio/codec.h | 17 +++ bsp/stm32_radio/stm32f10x_it.c | 42 ------ 3 files changed, 121 insertions(+), 182 deletions(-) diff --git a/bsp/stm32_radio/codec.c b/bsp/stm32_radio/codec.c index 0f62c1f964..233c577e97 100644 --- a/bsp/stm32_radio/codec.c +++ b/bsp/stm32_radio/codec.c @@ -79,19 +79,12 @@ struct codec_device }; struct codec_device codec; -static uint16_t r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV4; +static uint16_t r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8; static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; - /* SPI IRQ Channel configuration */ - NVIC_InitStructure.NVIC_IRQChannel = CODEC_I2S_IRQ; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - /* DMA IRQ Channel configuration */ NVIC_InitStructure.NVIC_IRQChannel = CODEC_I2S_DMA_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; @@ -117,7 +110,7 @@ static void GPIO_Configuration(void) GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; #if CODEC_MASTER_MODE - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; #else GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; #endif @@ -182,7 +175,7 @@ static void I2S_Configuration(void) /* I2S peripheral configuration */ I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; - I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16bextended; + I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k; I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; @@ -294,6 +287,33 @@ void vol(uint16_t v) codec_send(REG_ROUT2_VOL | SPKVU | v); } +void eq(codec_eq_args_t args) +{ + switch (args->channel) + { + case 1: + codec_send(REG_EQ1 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ3DMODE_DAC : EQ3DMODE_ADC)); + break; + + case 2: + codec_send(REG_EQ2 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ2BW_WIDE : EQ2BW_NARROW)); + break; + + case 3: + codec_send(REG_EQ3 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ3BW_WIDE : EQ3BW_NARROW)); + break; + + case 4: + codec_send(REG_EQ4 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ4BW_WIDE : EQ4BW_NARROW)); + break; + + case 5: + codec_send(REG_EQ5 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS)); + break; + } +} + +// TODO eq1() ~ eq5() are just for testing. To be removed. void eq1(uint8_t freq, uint8_t gain, uint8_t mode) { codec_send(REG_EQ1 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (mode ? EQ3DMODE_DAC : EQ3DMODE_ADC)); @@ -324,58 +344,58 @@ void eq3d(uint8_t depth) codec_send(REG_3D | ((depth & DEPTH3D_MASK) << DEPTH3D_POS)); } -rt_err_t sample_rate(uint8_t sr) +rt_err_t sample_rate(int sr) { uint16_t r07 = REG_ADDITIONAL; switch (sr) { - case 8: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV4 | (r06 & MS); + case 8000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV8 | (r06 & MS); r07 |= SR_8KHZ; break; - case 11: - r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV8 | BCLK_DIV4 | (r06 & MS); + case 11025: + r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV8 | BCLK_DIV8 | (r06 & MS); r07 |= SR_12KHZ; break; #if CODEC_MASTER_MODE - case 12: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV4 | (r06 & MS); + case 12000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS); r07 |= SR_12KHZ; break; #endif - case 16: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV4 | (r06 & MS); + case 16000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV8 | (r06 & MS); r07 |= SR_16KHZ; break; - case 22: - r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV4 | BCLK_DIV4 | (r06 & MS); + case 22050: + r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS); r07 |= SR_24KHZ; break; #if CODEC_MASTER_MODE - case 24: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV4 | (r06 & MS); + case 24000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS); r07 |= SR_24KHZ; break; #endif - case 32: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV4 | (r06 & MS); + case 32000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV8 | (r06 & MS); r07 |= SR_32KHZ; break; - case 44: - r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV4 | (r06 & MS); + case 44100: + r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS); r07 |= SR_48KHZ; break; - case 48: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV4 | (r06 & MS); + case 48000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV8 | (r06 & MS); r07 |= SR_48KHZ; break; @@ -408,45 +428,68 @@ static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag) static rt_err_t codec_close(rt_device_t dev) { - /* interrupt mode */ - if (dev->flag & RT_DEVICE_FLAG_INT_TX) - { #if CODEC_MASTER_MODE - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET); - - I2S_Cmd(CODEC_I2S_PORT, DISABLE); + if (r06 & MS) + { + CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); + CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; r06 &= ~MS; codec_send(r06); -#else - /* Disable the I2S2 */ - I2S_Cmd(CODEC_I2S_PORT, DISABLE); -#endif - } -#if CODEC_MASTER_MODE - else if ((dev->flag & RT_DEVICE_FLAG_DMA_TX) && (r06 & MS)) - { - DMA_Cmd(CODEC_I2S_DMA, DISABLE); - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET); + /* remove all data node */ + if (codec.parent.tx_complete != RT_NULL) + { + rt_base_t level = rt_hw_interrupt_disable(); - I2S_Cmd(CODEC_I2S_PORT, DISABLE); + do + { + codec.parent.tx_complete(&codec.parent, codec.data_list[codec.read_index].data_ptr); + codec.read_index++; + if (codec.read_index >= DATA_NODE_MAX) + { + codec.read_index = 0; + } + } + while (codec.read_index != codec.put_index); - r06 &= ~MS; - codec_send(r06); + rt_hw_interrupt_enable(level); + } } #endif - /* remove all data node */ - return RT_EOK; } static rt_err_t codec_control(rt_device_t dev, rt_uint8_t cmd, void *args) { - /* rate control */ + switch (cmd) + { + case CODEC_CMD_RESET: + codec_init(dev); + break; + + case CODEC_CMD_VOLUME: + vol(*((uint16_t*) args)); + break; + + case CODEC_CMD_SAMPLERATE: + sample_rate(*((int*) args)); + break; + + case CODEC_CMD_EQ: + eq((codec_eq_args_t) args); + break; + + case CODEC_CMD_3D: + eq3d(*((uint8_t*) args)); + break; + + default: + return RT_ERROR; + } return RT_EOK; } @@ -476,7 +519,6 @@ static rt_size_t codec_write(rt_device_t dev, rt_off_t pos, node = &device->data_list[device->put_index]; device->put_index = next_index; - // rt_kprintf("+\n"); /* set node attribute */ node->data_ptr = (rt_uint16_t*) buffer; node->data_size = size >> 1; /* size is byte unit, convert to half word unit */ @@ -488,22 +530,12 @@ static rt_size_t codec_write(rt_device_t dev, rt_off_t pos, /* check data list whether is empty */ if (next_index == device->put_index) { - if (dev->flag & RT_DEVICE_FLAG_INT_TX) - { - device->offset = 0; - /* enable I2S interrupt */ - SPI_I2S_ITConfig(CODEC_I2S_PORT, SPI_I2S_IT_TXE, ENABLE); - } - else if (dev->flag & RT_DEVICE_FLAG_DMA_TX) - { - DMA_Configuration((rt_uint32_t) node->data_ptr, node->data_size); - } + DMA_Configuration((rt_uint32_t) node->data_ptr, node->data_size); #if CODEC_MASTER_MODE if ((r06 & MS) == 0) { - I2S_Cmd(CODEC_I2S_PORT, ENABLE); - + CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; r06 |= MS; codec_send(r06); } @@ -549,71 +581,7 @@ rt_err_t codec_hw_init(void) return rt_device_register(&codec.parent, "snd", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX); } -void codec_isr() -{ - struct codec_data_node* node; - node = &codec.data_list[codec.read_index]; /* get current data node */ - - if (SPI_I2S_GetITStatus(CODEC_I2S_PORT, SPI_I2S_IT_TXE) == SET) - { -#if CODEC_MASTER_MODE - if ((r06 & MS) == 0) - { - I2S_Cmd(CODEC_I2S_PORT, ENABLE); - SPI_I2S_SendData(CODEC_I2S_PORT, node->data_ptr[codec.offset++]); - - r06 |= MS; - codec_send(r06); - } - else - { - SPI_I2S_SendData(CODEC_I2S_PORT, node->data_ptr[codec.offset++]); - } -#else - SPI_I2S_SendData(CODEC_I2S_PORT, node->data_ptr[codec.offset++]); -#endif - } - - if (codec.offset == node->data_size) - { - /* move to next node */ - rt_uint16_t next_index; - - next_index = codec.read_index + 1; - if (next_index >= DATA_NODE_MAX) - next_index = 0; - - /* notify transmitted complete. */ - if (codec.parent.tx_complete != RT_NULL) - { - codec.parent.tx_complete(&codec.parent, - codec.data_list[codec.read_index].data_ptr); - rt_kprintf("-\n"); - } - - codec.offset = 0; - codec.read_index = next_index; - if (next_index == codec.put_index) - { - /* no data on the list, disable I2S interrupt */ - SPI_I2S_ITConfig(CODEC_I2S_PORT, SPI_I2S_IT_TXE, DISABLE); - -#if CODEC_MASTER_MODE - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET); - - I2S_Cmd(CODEC_I2S_PORT, DISABLE); - - r06 &= ~MS; - codec_send(r06); -#endif - - rt_kprintf("*\n"); - } - } -} - -void codec_dma_isr() +void codec_dma_isr(void) { /* switch to next buffer */ rt_uint16_t next_index; @@ -635,8 +603,7 @@ void codec_dma_isr() #if CODEC_MASTER_MODE if ((r06 & MS) == 0) { - I2S_Cmd(CODEC_I2S_PORT, ENABLE); - + CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; r06 |= MS; codec_send(r06); } @@ -647,12 +614,10 @@ void codec_dma_isr() #if CODEC_MASTER_MODE if (r06 & MS) { - DMA_Cmd(CODEC_I2S_DMA, DISABLE); - - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); - while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET); - - I2S_Cmd(CODEC_I2S_PORT, DISABLE); + CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); + CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; r06 &= ~MS; codec_send(r06); @@ -666,6 +631,5 @@ void codec_dma_isr() if (codec.parent.tx_complete != RT_NULL) { codec.parent.tx_complete(&codec.parent, data_ptr); - // rt_kprintf("-\n"); } } diff --git a/bsp/stm32_radio/codec.h b/bsp/stm32_radio/codec.h index 877f9d6fae..f0ba49028a 100644 --- a/bsp/stm32_radio/codec.h +++ b/bsp/stm32_radio/codec.h @@ -625,4 +625,21 @@ #define RMIX2OUT4 (1 << 1) #define RDAC2OUT4 (1) + +/* Device Control Commands */ +#define CODEC_CMD_RESET 0 +#define CODEC_CMD_VOLUME 1 +#define CODEC_CMD_SAMPLERATE 2 +#define CODEC_CMD_EQ 3 +#define CODEC_CMD_3D 4 + +struct codec_eq_args +{ + uint8_t channel; + uint8_t frequency; + uint8_t gain; + uint8_t mode_bandwidth; +}; +typedef struct codec_eq_args* codec_eq_args_t; + #endif // #ifndef __CODEC_H__ diff --git a/bsp/stm32_radio/stm32f10x_it.c b/bsp/stm32_radio/stm32f10x_it.c index e3c64edf85..907fa8d4c5 100644 --- a/bsp/stm32_radio/stm32f10x_it.c +++ b/bsp/stm32_radio/stm32f10x_it.c @@ -425,26 +425,6 @@ void EXTI9_5_IRQHandler(void) #endif } -/******************************************************************************* -* Function Name : SPI2_IRQHandler -* Description : This function handles SPI2 global interrupt request. -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void SPI2_IRQHandler(void) -{ - extern void codec_isr(void); - - /* enter interrupt */ - rt_interrupt_enter(); - - codec_isr(); - - /* leave interrupt */ - rt_interrupt_leave(); -} - /******************************************************************************* * Function Name : USART1_IRQHandler * Description : This function handles USART1 global interrupt request. @@ -638,28 +618,6 @@ void SDIO_IRQHandler(void) #endif } -/******************************************************************************* -* Function Name : SPI3_IRQHandler -* Description : This function handles SPI3 global interrupt request. -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void SPI3_IRQHandler(void) -{ -#if CODEC_USE_SPI3 - extern void codec_isr(void); - - /* enter interrupt */ - rt_interrupt_enter(); - - codec_isr(); - - /* leave interrupt */ - rt_interrupt_leave(); -#endif -} - /******************************************************************************* * Function Name : DMA2_Channel2_IRQHandler * Description : This function handles DMA2 Channel 2 interrupt request.