提交 f05df1f9 编写于 作者: K kyle.hu.gz

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
上级 873d9e9b
...@@ -79,19 +79,12 @@ struct codec_device ...@@ -79,19 +79,12 @@ struct codec_device
}; };
struct codec_device codec; 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) static void NVIC_Configuration(void)
{ {
NVIC_InitTypeDef NVIC_InitStructure; 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 */ /* DMA IRQ Channel configuration */
NVIC_InitStructure.NVIC_IRQChannel = CODEC_I2S_DMA_IRQ; NVIC_InitStructure.NVIC_IRQChannel = CODEC_I2S_DMA_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
...@@ -117,7 +110,7 @@ static void GPIO_Configuration(void) ...@@ -117,7 +110,7 @@ static void GPIO_Configuration(void)
GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN; GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
#else #else
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
#endif #endif
...@@ -182,7 +175,7 @@ static void I2S_Configuration(void) ...@@ -182,7 +175,7 @@ static void I2S_Configuration(void)
/* I2S peripheral configuration */ /* I2S peripheral configuration */
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; 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_MCLKOutput = I2S_MCLKOutput_Disable;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k; I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
...@@ -294,6 +287,33 @@ void vol(uint16_t v) ...@@ -294,6 +287,33 @@ void vol(uint16_t v)
codec_send(REG_ROUT2_VOL | SPKVU | 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) 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)); 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) ...@@ -324,58 +344,58 @@ void eq3d(uint8_t depth)
codec_send(REG_3D | ((depth & DEPTH3D_MASK) << DEPTH3D_POS)); 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; uint16_t r07 = REG_ADDITIONAL;
switch (sr) switch (sr)
{ {
case 8: case 8000:
r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_8KHZ; r07 |= SR_8KHZ;
break; break;
case 11: case 11025:
r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV8 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV8 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_12KHZ; r07 |= SR_12KHZ;
break; break;
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
case 12: case 12000:
r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_12KHZ; r07 |= SR_12KHZ;
break; break;
#endif #endif
case 16: case 16000:
r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_16KHZ; r07 |= SR_16KHZ;
break; break;
case 22: case 22050:
r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV4 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_24KHZ; r07 |= SR_24KHZ;
break; break;
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
case 24: case 24000:
r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_24KHZ; r07 |= SR_24KHZ;
break; break;
#endif #endif
case 32: case 32000:
r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_32KHZ; r07 |= SR_32KHZ;
break; break;
case 44: case 44100:
r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_48KHZ; r07 |= SR_48KHZ;
break; break;
case 48: case 48000:
r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV4 | (r06 & MS); r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV8 | (r06 & MS);
r07 |= SR_48KHZ; r07 |= SR_48KHZ;
break; break;
...@@ -408,45 +428,68 @@ static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag) ...@@ -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) static rt_err_t codec_close(rt_device_t dev)
{ {
/* interrupt mode */
if (dev->flag & RT_DEVICE_FLAG_INT_TX)
{
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); if (r06 & MS)
while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET);
I2S_Cmd(CODEC_I2S_PORT, DISABLE);
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); CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN;
while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0);
while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0);
while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET); CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE;
I2S_Cmd(CODEC_I2S_PORT, DISABLE);
r06 &= ~MS; r06 &= ~MS;
codec_send(r06); codec_send(r06);
/* remove all data node */
if (codec.parent.tx_complete != RT_NULL)
{
rt_base_t level = rt_hw_interrupt_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);
rt_hw_interrupt_enable(level);
}
} }
#endif #endif
/* remove all data node */
return RT_EOK; return RT_EOK;
} }
static rt_err_t codec_control(rt_device_t dev, rt_uint8_t cmd, void *args) 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; return RT_EOK;
} }
...@@ -476,7 +519,6 @@ static rt_size_t codec_write(rt_device_t dev, rt_off_t pos, ...@@ -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]; node = &device->data_list[device->put_index];
device->put_index = next_index; device->put_index = next_index;
// rt_kprintf("+\n");
/* set node attribute */ /* set node attribute */
node->data_ptr = (rt_uint16_t*) buffer; node->data_ptr = (rt_uint16_t*) buffer;
node->data_size = size >> 1; /* size is byte unit, convert to half word unit */ 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, ...@@ -488,22 +530,12 @@ static rt_size_t codec_write(rt_device_t dev, rt_off_t pos,
/* check data list whether is empty */ /* check data list whether is empty */
if (next_index == device->put_index) if (next_index == device->put_index)
{ {
if (dev->flag & RT_DEVICE_FLAG_INT_TX) DMA_Configuration((rt_uint32_t) node->data_ptr, node->data_size);
{
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);
}
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
if ((r06 & MS) == 0) if ((r06 & MS) == 0)
{ {
I2S_Cmd(CODEC_I2S_PORT, ENABLE); CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE;
r06 |= MS; r06 |= MS;
codec_send(r06); codec_send(r06);
} }
...@@ -549,71 +581,7 @@ rt_err_t codec_hw_init(void) ...@@ -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); return rt_device_register(&codec.parent, "snd", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX);
} }
void codec_isr() void codec_dma_isr(void)
{
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()
{ {
/* switch to next buffer */ /* switch to next buffer */
rt_uint16_t next_index; rt_uint16_t next_index;
...@@ -635,8 +603,7 @@ void codec_dma_isr() ...@@ -635,8 +603,7 @@ void codec_dma_isr()
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
if ((r06 & MS) == 0) if ((r06 & MS) == 0)
{ {
I2S_Cmd(CODEC_I2S_PORT, ENABLE); CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE;
r06 |= MS; r06 |= MS;
codec_send(r06); codec_send(r06);
} }
...@@ -647,12 +614,10 @@ void codec_dma_isr() ...@@ -647,12 +614,10 @@ void codec_dma_isr()
#if CODEC_MASTER_MODE #if CODEC_MASTER_MODE
if (r06 & MS) if (r06 & MS)
{ {
DMA_Cmd(CODEC_I2S_DMA, DISABLE); CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN;
while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0);
while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_TXE) == RESET); while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0);
while (SPI_I2S_GetFlagStatus(CODEC_I2S_PORT, SPI_I2S_FLAG_BSY) == SET); CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE;
I2S_Cmd(CODEC_I2S_PORT, DISABLE);
r06 &= ~MS; r06 &= ~MS;
codec_send(r06); codec_send(r06);
...@@ -666,6 +631,5 @@ void codec_dma_isr() ...@@ -666,6 +631,5 @@ void codec_dma_isr()
if (codec.parent.tx_complete != RT_NULL) if (codec.parent.tx_complete != RT_NULL)
{ {
codec.parent.tx_complete(&codec.parent, data_ptr); codec.parent.tx_complete(&codec.parent, data_ptr);
// rt_kprintf("-\n");
} }
} }
...@@ -625,4 +625,21 @@ ...@@ -625,4 +625,21 @@
#define RMIX2OUT4 (1 << 1) #define RMIX2OUT4 (1 << 1)
#define RDAC2OUT4 (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__ #endif // #ifndef __CODEC_H__
...@@ -425,26 +425,6 @@ void EXTI9_5_IRQHandler(void) ...@@ -425,26 +425,6 @@ void EXTI9_5_IRQHandler(void)
#endif #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 * Function Name : USART1_IRQHandler
* Description : This function handles USART1 global interrupt request. * Description : This function handles USART1 global interrupt request.
...@@ -638,28 +618,6 @@ void SDIO_IRQHandler(void) ...@@ -638,28 +618,6 @@ void SDIO_IRQHandler(void)
#endif #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 * Function Name : DMA2_Channel2_IRQHandler
* Description : This function handles DMA2 Channel 2 interrupt request. * Description : This function handles DMA2 Channel 2 interrupt request.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册