Procházet zdrojové kódy

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

kyle.hu.gz před 15 roky
rodič
revize
f05df1f97b
3 změnil soubory, kde provedl 123 přidání a 184 odebrání
  1. 106 142
      bsp/stm32_radio/codec.c
  2. 17 0
      bsp/stm32_radio/codec.h
  3. 0 42
      bsp/stm32_radio/stm32f10x_it.c

+ 106 - 142
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);
-
-		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))
+	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);
+
+		/* 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
 
-	/* 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");
 	}
 }

+ 17 - 0
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__

+ 0 - 42
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.