瀏覽代碼

stm32_radio: Updates the initialization sequence of the WM8978 driver, and adds EQ/sample rate control.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@373 bbd45198-f89e-11dd-88c7-29a3b14d5316
kyle.hu.gz 15 年之前
父節點
當前提交
8d78b3743a
共有 4 個文件被更改,包括 1039 次插入296 次删除
  1. 405 285
      bsp/stm32_radio/codec.c
  2. 627 0
      bsp/stm32_radio/codec.h
  3. 3 7
      bsp/stm32_radio/startup.c
  4. 4 4
      bsp/stm32_radio/stm32f10x_it.c

+ 405 - 285
bsp/stm32_radio/codec.c

@@ -1,37 +1,55 @@
 #include <rthw.h>
 #include <rtthread.h>
 #include "stm32f10x.h"
-
+#include "codec.h"
 
 /*
 SCLK  PA5  SPI1_SCK
 SDIN  PA7  SPI1_MOSI
 CSB   PC5
 */
-#define wm_csb_0   GPIO_ResetBits(GPIOC,GPIO_Pin_5)
-#define wm_csb_1   GPIO_SetBits(GPIOC,GPIO_Pin_5)
+#define CODEC_CSB_PORT		GPIOC
+#define CODEC_CSB_PIN		GPIO_Pin_5
+#define codec_set_csb()		do { CODEC_CSB_PORT->BSRR = CODEC_CSB_PIN; } while (0)
+#define codec_reset_csb()	do { CODEC_CSB_PORT->BRR = CODEC_CSB_PIN; } while (0)
+
+void vol(uint16_t v);
 
 #define DATA_NODE_MAX 5
 /* data node for Tx Mode */
-struct wm8753_data_node
+struct codec_data_node
 {
     rt_uint16_t *data_ptr;
     rt_size_t  data_size;
 };
 
-struct wm8753_device
+struct codec_device
 {
     /* inherit from rt_device */
     struct rt_device parent;
 
     /* pcm data list */
-    struct wm8753_data_node data_list[DATA_NODE_MAX];
+    struct codec_data_node data_list[DATA_NODE_MAX];
     rt_uint16_t read_index, put_index;
 
     /* transmitted offset of current data node */
     rt_size_t offset;
 };
-struct wm8753_device wm8753;
+struct codec_device codec;
+
+struct pll_ratio
+{
+	uint8_t n;
+	uint8_t k1;
+	uint16_t k2;
+	uint16_t k3;
+};
+
+static void delay_ms(unsigned int dt)
+{
+	volatile unsigned int u;
+	for (u = 0; u < dt * 30; u++);
+}
 
 static void NVIC_Configuration(void)
 {
@@ -56,332 +74,434 @@ static void GPIO_Configuration(void)
 {
     GPIO_InitTypeDef GPIO_InitStructure;
 
-    /* Disable the JTAG interface and enable the SWJ interface */
-    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
-
-    /* PC5 CODEC CS */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_Init(GPIOC,&GPIO_InitStructure);
-
-    /* Configure SPI2 pins: CK, WS and SD */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-    GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-#if 0
-    /*    MCO    configure */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_Init(GPIOA,&GPIO_InitStructure);
-
-    RCC_MCOConfig(RCC_MCO_HSE);
+	/* Disable the JTAG interface and enable the SWJ interface */
+	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
+
+	/* PC5 CODEC CS */
+	GPIO_InitStructure.GPIO_Pin = CODEC_CSB_PIN;
+	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+	GPIO_Init(CODEC_CSB_PORT, &GPIO_InitStructure);
+
+	/* Configure SPI2 pins: CK, WS and SD */
+	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
+	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
+	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+	GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+#ifdef CODEC_USE_MCO
+	/*    MCO    configure */
+	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
+	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+	GPIO_Init(GPIOA,&GPIO_InitStructure);
+
+	RCC_MCOConfig(RCC_MCO_HSE);
 #endif
 }
 
-#define SPI2_DR_Address  0x4000380C
 static void DMA_Configuration(rt_uint32_t addr, rt_size_t size)
 {
-    DMA_InitTypeDef    DMA_InitStructure;
-
-    /* DMA1 Channel2 configuration ----------------------------------------------*/
-    DMA_Cmd(DMA1_Channel5, DISABLE);
-    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SPI2_DR_Address;
-    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)addr;
-    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
-    DMA_InitStructure.DMA_BufferSize = size;
-    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
-    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
-    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
-    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
-    DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
-    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
-    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
-    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
-
-    /* Enable SPI2 DMA Tx request */
-    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
-
-    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
-    DMA_Cmd(DMA1_Channel5, ENABLE);
+    DMA_InitTypeDef DMA_InitStructure;
+
+	/* DMA1 Channel2 configuration ----------------------------------------------*/
+	DMA_Cmd(DMA1_Channel5, DISABLE);
+	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI2->DR));
+	DMA_InitStructure.DMA_MemoryBaseAddr = (u32) addr;
+	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
+	DMA_InitStructure.DMA_BufferSize = size;
+	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
+	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
+	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
+	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
+	DMA_Init(DMA1_Channel5, &DMA_InitStructure);
+
+	/* Enable SPI2 DMA Tx request */
+	SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
+
+	DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
+	DMA_Cmd(DMA1_Channel5, ENABLE);
 }
 
 static void I2S_Configuration(void)
 {
-    I2S_InitTypeDef I2S_InitStructure;
-
-    /* I2S peripheral configuration */
-    I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
-    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_High;// I2S_CPOL_Low
-
-    /* I2S2 Master Transmitter to I2S3 Slave Receiver communication -----------*/
-    /* I2S2 configuration */
-    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;//I2S_Mode_MasterTx  I2S_Mode_SlaveTx
-    I2S_Init(SPI2, &I2S_InitStructure);
+	I2S_InitTypeDef I2S_InitStructure;
+
+	/* I2S peripheral configuration */
+	I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
+	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_High; // I2S_CPOL_Low
+
+	/* I2S2 Master Transmitter to I2S3 Slave Receiver communication -----------*/
+	/* I2S2 configuration */
+	I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; //I2S_Mode_MasterTx  I2S_Mode_SlaveTx
+	I2S_Init(SPI2, &I2S_InitStructure);
 }
 
-unsigned char SPI_WriteByte(unsigned char data)
+uint8_t SPI_WriteByte(unsigned char data)
 {
-    unsigned char Data = 0;
+	//Wait until the transmit buffer is empty
+	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
+	// Send the byte
+	SPI_I2S_SendData(SPI1, data);
+
+	//Wait until a data is received
+	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
+	// Get the received data
+	data = SPI_I2S_ReceiveData(SPI1);
+
+	// Return the shifted data
+	return data;
+}
 
-    //Wait until the transmit buffer is empty
-    while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);
-    // Send the byte
-    SPI_I2S_SendData(SPI1,data);
+static void codec_send(rt_uint16_t s_data)
+{
+	codec_reset_csb();
+	SPI_WriteByte((s_data >> 8) & 0xFF);
+	SPI_WriteByte(s_data & 0xFF);
+	codec_set_csb();
+}
 
-    //Wait until a data is received
-    while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET);
-    // Get the received data
-    Data = SPI_I2S_ReceiveData(SPI1);
+static rt_err_t codec_init(rt_device_t dev)
+{
+	codec_send(REG_SOFTWARE_RESET);
+
+	// 1.5x boost power up sequence.
+	// Mute all outputs.
+	codec_send(REG_LOUT1_VOL | LOUT1MUTE);
+	codec_send(REG_ROUT1_VOL | ROUT1MUTE);
+	codec_send(REG_LOUT2_VOL | LOUT2MUTE);
+	codec_send(REG_ROUT2_VOL | ROUT2MUTE);
+	// Enable unused output chosen from L/ROUT2, OUT3 or OUT4.
+	codec_send(REG_POWER_MANAGEMENT3 | OUT4EN);
+	// Set BUFDCOPEN=1 and BUFIOEN=1 in register R1
+	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN);
+	// Set SPKBOOST=1 in register R49.
+	codec_send(REG_OUTPUT | SPKBOOST);
+	// Set VMIDSEL[1:0] to required value in register R1.
+	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K);
+	// Wait for VMID supply to settle.
+	delay_ms(750);
+	// Set L/RMIXEN=1 and DACENL/R=1 in register R3.
+	codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR);
+	// Set BIASEN=1 in register R1.
+	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN);
+	// Set L/ROUT2EN=1 in register R3.
+	codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR | LOUT2EN | ROUT2EN);
+	// Enable other mixers as required.
+	// Enable other outputs as required.
+	codec_send(REG_POWER_MANAGEMENT2 | LOUT1EN | ROUT1EN | BOOSTENL | BOOSTENR | INPPGAENL | INPPGAENR);
+
+	// Digital inferface setup.
+	codec_send(REG_AUDIO_INTERFACE | BCP_NORMAL | LRP_NORMAL | WL_16BITS | FMT_I2S);
+
+	// PLL setup.
+	// fs = 44.1KHz / 256fs = 11.2896MHz
+	// F_PLL = 11.2896MHz * 4 * 2 = 90.3168MHz
+	// R = 90.3168MHz / 12.288MHz = 7.35
+	// PLL_N = 7
+	// PLL_K = 5872026
+	codec_send(REG_PLL_N | 7);
+	codec_send(REG_PLL_K1 | 0x16);
+	codec_send(REG_PLL_K2 | 0xCC);
+	codec_send(REG_PLL_K3 | 0x19A);
+	codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN | PLLEN);
+	codec_send(REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2);
+
+	// Enable DAC 128x oversampling.
+	codec_send(REG_DAC | DACOSR128);
+
+	// Set LOUT2/ROUT2 in BTL operation.
+	codec_send(REG_BEEP | INVROUT2);
+
+	// Set output volume to -22dB.
+	vol(35);
+
+	return RT_EOK;
+}
+
+// Exported functions
+#include <finsh.h>
 
-    // Return the shifted data
-    return Data;
+void vol(uint16_t v)
+{
+	v = (v & VOL_MASK) << VOL_POS;
+	codec_send(REG_LOUT1_VOL | v);
+	codec_send(REG_ROUT1_VOL | HPVU | v);
+	codec_send(REG_LOUT2_VOL | v);
+	codec_send(REG_ROUT2_VOL | SPKVU | v);
 }
 
-void wm8753_send(rt_uint16_t s_data)
+void eq1(uint8_t freq, uint8_t gain, uint8_t mode)
 {
-    wm_csb_0;
-    SPI_WriteByte( (s_data>>8)&0xFF );
-    SPI_WriteByte( s_data&0xFF );
-    wm_csb_1;
+	codec_send(REG_EQ1 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (mode ? EQ3DMODE_DAC : EQ3DMODE_ADC));
 }
 
-static rt_err_t wm8753_init (rt_device_t dev)
+void eq2(uint8_t freq, uint8_t gain, uint8_t bw)
 {
-    wm8753_send(0<<9 | 0xFF); // reset
-
-    /* POWER manager */
-    wm8753_send(1<<9 | (1<<8) | (0<<7) | (0<<6) | (0<<5) | (1<<4) | (1<<3) | (1<<2) | 2    );//电源设置
-    wm8753_send(2<<9 | (1<<8) | (1<<7) | (1<<5) | (1<<4) | (1<<3) | (1<<2) );                // 打开电源  耳机输出
-    wm8753_send(3<<9 | (0<<8) | (0<<7) | (1<<6) | (1<<5) | (1<<3) | (1<<2) | (1<<1) | 1 );   // 喇叭输出和DAC
-
-    /* IIS DAC test */
-    wm8753_send(4<<9 | (0<<7) | (2<<3) );//IIS 16BIT
-    // 12.288/3/8=512K
-    wm8753_send(6<<9  | (0<<5) | (3<<2)| 0);//0: slave 1: master  | (3<<5) | (3<<2)
-    wm8753_send(43<<9 | (1<<4) );//INVROUT2
-
-    /* 设置初始化音量 */
-    wm8753_send(52<<9 | (1<<8) | (1<<7) | 35 ); // LOUT1 0-57-63
-    wm8753_send(53<<9 | (1<<8) | (1<<7) | 35 ); // ROUT1 0-57-63
-    wm8753_send(54<<9 | (1<<8) | (1<<7) | 35 ); // LOUT2 0-57-63
-    wm8753_send(55<<9 | (1<<8) | (1<<7) | 35 ); // ROUT2 0-57-63
-
-#if 1
-    /* LINE IN test */
-    wm8753_send(47<<9 | (1<<8) | (1<<4) ); //L LINE_IN VOL (6:4)输入增益: 0-关 1-12DB 2-9DB 5-0db 7+6DB
-    wm8753_send(48<<9 | (1<<8) | (1<<4) ); //R LINE_IN VOL (6:4)输入增益: 0-关 1-12DB 2-9DB 5-0db 7+6DB
-    wm8753_send(50<<9 | (5<<2) | (1<<1) | (1<<0) );//打开左监听 (4:2)增益 0-关 1-12DB 2-9DB 5-0db 7+6DB
-    wm8753_send(51<<9 | (5<<2) | (1<<1) | (1<<0) );//打开右监听 (4:2)增益 0-关 1-12DB 2-9DB 5-0db 7+6DB
-
-    /* MIC test */
-    wm8753_send(44<<9 | (1<<8) | (1<<5) | (1<<4) | (0<<2) | (1<<1) | (1<<0) );//MIC输入选择
-    wm8753_send(45<<9 | 50);//16-0  63-35
-    wm8753_send(46<<9 | 50);//16-0  63-35
-#endif
+	codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ2BW_WIDE : EQ2BW_NARROW));
+}
 
-    return RT_EOK;
+void eq3(uint8_t freq, uint8_t gain, uint8_t bw)
+{
+	codec_send(REG_EQ3 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ3BW_WIDE : EQ3BW_NARROW));
 }
 
-#include <finsh.h>
-//0~57~63
-void vol(int v)
+void eq4(uint8_t freq, uint8_t gain, uint8_t bw)
 {
-    wm8753_send(52<<9 | (0<<8) | (1<<7) | v ); // LOUT1 0-57-63
-    wm8753_send(53<<9 | (1<<8) | (1<<7) | v ); // ROUT1 0-57-63
-    wm8753_send(54<<9 | (0<<8) | (1<<7) | v ); // LOUT2 0-57-63
-    wm8753_send(55<<9 | (1<<8) | (1<<7) | v ); // ROUT2 0-57-63
+	codec_send(REG_EQ4 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ4BW_WIDE : EQ4BW_NARROW));
 }
-FINSH_FUNCTION_EXPORT(vol, set volume)
 
-static rt_err_t wm8753_open(rt_device_t dev, rt_uint16_t oflag)
+void eq5(uint8_t freq, uint8_t gain)
 {
-    /* enable I2S */
-    I2S_Cmd(SPI2, ENABLE);
+	codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS));
+}
 
-    return RT_EOK;
+void eq3d(uint8_t depth)
+{
+	codec_send(REG_3D | ((depth & DEPTH3D_MASK) << DEPTH3D_POS));
 }
 
-static rt_err_t wm8753_close(rt_device_t dev)
+void sample_rate(uint8_t sr)
 {
-    /* interrupt mode */
-    if (dev->flag & RT_DEVICE_FLAG_INT_TX)
-    {
-        /* Disable the I2S2 */
-        I2S_Cmd(SPI2, DISABLE);
-    }
+	if (sr == 44)
+	{
+		codec_send(REG_ADDITIONAL | SR_48KHZ);
+		codec_send(REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2);
+	}
+	else
+	{
+		switch (sr)
+		{
+		case 8:
+			codec_send(REG_ADDITIONAL | SR_8KHZ);
+			break;
+
+		case 12:
+			codec_send(REG_ADDITIONAL | SR_12KHZ);
+			break;
+
+		case 16:
+			codec_send(REG_ADDITIONAL | SR_16KHZ);
+			break;
+
+		case 24:
+			codec_send(REG_ADDITIONAL | SR_24KHZ);
+			break;
+
+		case 32:
+			codec_send(REG_ADDITIONAL | SR_32KHZ);
+			break;
+
+		case 48:
+			codec_send(REG_ADDITIONAL | SR_48KHZ);
+			break;
+
+		default:
+			return;
+		}
+		codec_send(REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1);
+	}
+}
+
+FINSH_FUNCTION_EXPORT(vol, Set volume);
+FINSH_FUNCTION_EXPORT(eq1, Set EQ1(Cut-off, Gain, Mode));
+FINSH_FUNCTION_EXPORT(eq2, Set EQ2(Center, Gain, Bandwidth));
+FINSH_FUNCTION_EXPORT(eq3, Set EQ3(Center, Gain, Bandwidth));
+FINSH_FUNCTION_EXPORT(eq4, Set EQ4(Center, Gain, Bandwidth));
+FINSH_FUNCTION_EXPORT(eq5, Set EQ5(Cut-off, Gain));
+FINSH_FUNCTION_EXPORT(eq3d, Set 3D(Depth));
+FINSH_FUNCTION_EXPORT(sample_rate, Set sample rate);
 
-    /* remove all data node */
+static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag)
+{
+	/* enable I2S */
+	I2S_Cmd(SPI2, ENABLE);
 
-    return RT_EOK;
+	return RT_EOK;
 }
 
-static rt_err_t wm8753_control(rt_device_t dev, rt_uint8_t cmd, void *args)
+static rt_err_t codec_close(rt_device_t dev)
 {
-    /* rate control */
-    return RT_EOK;
+	/* interrupt mode */
+	if (dev->flag & RT_DEVICE_FLAG_INT_TX)
+	{
+		/* Disable the I2S2 */
+		I2S_Cmd(SPI2, DISABLE);
+	}
+
+	/* remove all data node */
+
+	return RT_EOK;
 }
 
-static rt_size_t wm8753_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+static rt_err_t codec_control(rt_device_t dev, rt_uint8_t cmd, void *args)
 {
-    struct wm8753_device* device;
-    struct wm8753_data_node* node;
-    rt_uint32_t level;
-    rt_uint16_t next_index;
-
-    device = (struct wm8753_device*)dev;
-    RT_ASSERT(device != RT_NULL);
-
-    next_index = device->put_index + 1;
-    if (next_index >= DATA_NODE_MAX) next_index = 0;
-
-    /* check data_list full */
-    if (next_index == device->read_index)
-    {
-        rt_set_errno(-RT_EFULL);
-        return 0;
-    }
-
-    level = rt_hw_interrupt_disable();
-    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 */
-
-    next_index = device->read_index + 1;
-    if (next_index >= DATA_NODE_MAX) next_index = 0;
-
-    /* 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(SPI2, 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);
-        }
-    }
-    rt_hw_interrupt_enable(level);
-
-    return size;
+	/* rate control */
+	return RT_EOK;
 }
 
-rt_err_t wm8753_hw_init(void)
+static rt_size_t codec_write(rt_device_t dev, rt_off_t pos,
+		const void* buffer, rt_size_t size)
 {
-    rt_device_t dev;
-
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
-    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
-    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
-
-    NVIC_Configuration();
-    GPIO_Configuration();
-    I2S_Configuration();
-
-    dev = (rt_device_t)&wm8753;
-    dev->type			= RT_Device_Class_Unknown;
-    dev->rx_indicate 	= RT_NULL;
-    dev->tx_complete 	= RT_NULL;
-    dev->init 			= wm8753_init;
-    dev->open			= wm8753_open;
-    dev->close			= wm8753_close;
-    dev->read 			= RT_NULL;
-    dev->write 			= wm8753_write;
-    dev->control 		= wm8753_control;
-    dev->private		= RT_NULL;
-
-    /* set read_index and put index to 0 */
-    wm8753.read_index	= 0;
-    wm8753.put_index 	= 0;
-
-    /* unselect */
-    wm_csb_1;
-
-    /* register the device */
-    return rt_device_register(&wm8753.parent, "snd",
-                              RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX);
+	struct codec_device* device;
+	struct codec_data_node* node;
+	rt_uint32_t level;
+	rt_uint16_t next_index;
+
+	device = (struct codec_device*) dev;
+	RT_ASSERT(device != RT_NULL);
+
+	next_index = device->put_index + 1;
+	if (next_index >= DATA_NODE_MAX)
+		next_index = 0;
+
+	/* check data_list full */
+	if (next_index == device->read_index)
+	{
+		rt_set_errno(-RT_EFULL);
+		return 0;
+	}
+
+	level = rt_hw_interrupt_disable();
+	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 */
+
+	next_index = device->read_index + 1;
+	if (next_index >= DATA_NODE_MAX)
+		next_index = 0;
+
+	/* 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(SPI2, 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);
+		}
+	}
+	rt_hw_interrupt_enable(level);
+
+	return size;
 }
 
-void wm8753_isr()
+rt_err_t codec_hw_init(void)
 {
-    struct wm8753_data_node* node;
-    node = &wm8753.data_list[wm8753.read_index]; /* get current data node */
-
-    if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_TXE) == SET)
-    {
-        SPI_I2S_SendData(SPI2, node->data_ptr[wm8753.offset++]);
-    }
-
-    if (wm8753.offset == node->data_size)
-    {
-        /* move to next node */
-        rt_uint16_t next_index;
-
-        next_index = wm8753.read_index + 1;
-        if (next_index >= DATA_NODE_MAX) next_index = 0;
-
-        /* notify transmitted complete. */
-        if (wm8753.parent.tx_complete != RT_NULL)
-        {
-            wm8753.parent.tx_complete (&wm8753.parent, wm8753.data_list[wm8753.read_index].data_ptr);
-            rt_kprintf("-\n");
-        }
-
-        wm8753.offset = 0;
-        wm8753.read_index = next_index;
-        if (next_index == wm8753.put_index)
-        {
-            /* no data on the list, disable I2S interrupt */
-            SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
-
-            rt_kprintf("*\n");
-        }
-    }
+	rt_device_t dev;
+
+	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
+	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
+	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
+
+	NVIC_Configuration();
+	GPIO_Configuration();
+	I2S_Configuration();
+
+	dev = (rt_device_t) &codec;
+	dev->type = RT_Device_Class_Unknown;
+	dev->rx_indicate = RT_NULL;
+	dev->tx_complete = RT_NULL;
+	dev->init = codec_init;
+	dev->open = codec_open;
+	dev->close = codec_close;
+	dev->read = RT_NULL;
+	dev->write = codec_write;
+	dev->control = codec_control;
+	dev->private = RT_NULL;
+
+	/* set read_index and put index to 0 */
+	codec.read_index = 0;
+	codec.put_index = 0;
+
+	/* unselect */
+	codec_set_csb();
+
+	/* register the device */
+	return rt_device_register(&codec.parent, "snd", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX);
 }
 
-void wm8753_dma_isr()
+void codec_isr()
 {
-    /* switch to next buffer */
-    rt_uint16_t next_index;
-    void* data_ptr;
-
-    next_index = wm8753.read_index + 1;
-    if (next_index >= DATA_NODE_MAX) next_index = 0;
-
-    /* save current data pointer */
-    data_ptr = wm8753.data_list[wm8753.read_index].data_ptr;
-
-    wm8753.read_index = next_index;
-    if (next_index != wm8753.put_index)
-    {
-        /* enable next dma request */
-        DMA_Configuration((rt_uint32_t)wm8753.data_list[wm8753.read_index].data_ptr,
-                          wm8753.data_list[wm8753.read_index].data_size);
-    }
-    else
-    {
-        rt_kprintf("*\n");
-    }
-
-    /* notify transmitted complete. */
-    if (wm8753.parent.tx_complete != RT_NULL)
-    {
-        wm8753.parent.tx_complete (&wm8753.parent, data_ptr);
-        // rt_kprintf("-\n");
-    }
+	struct codec_data_node* node;
+	node = &codec.data_list[codec.read_index]; /* get current data node */
+
+	if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_TXE) == SET)
+	{
+		SPI_I2S_SendData(SPI2, node->data_ptr[codec.offset++]);
+	}
+
+	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(SPI2, SPI_I2S_IT_TXE, DISABLE);
+
+			rt_kprintf("*\n");
+		}
+	}
 }
 
+void codec_dma_isr()
+{
+	/* switch to next buffer */
+	rt_uint16_t next_index;
+	void* data_ptr;
+
+	next_index = codec.read_index + 1;
+	if (next_index >= DATA_NODE_MAX)
+		next_index = 0;
+
+	/* save current data pointer */
+	data_ptr = codec.data_list[codec.read_index].data_ptr;
+
+	codec.read_index = next_index;
+	if (next_index != codec.put_index)
+	{
+		/* enable next dma request */
+		DMA_Configuration((rt_uint32_t) codec.data_list[codec.read_index].data_ptr, codec.data_list[codec.read_index].data_size);
+	}
+	else
+	{
+		rt_kprintf("*\n");
+	}
+
+	/* notify transmitted complete. */
+	if (codec.parent.tx_complete != RT_NULL)
+	{
+		codec.parent.tx_complete(&codec.parent, data_ptr);
+		// rt_kprintf("-\n");
+	}
+}

+ 627 - 0
bsp/stm32_radio/codec.h

@@ -0,0 +1,627 @@
+#ifndef __CODEC_H__
+#define __CODEC_H__
+
+#include <stdint.h>
+
+#define REG_SOFTWARE_RESET		((uint16_t)0)
+#define REG_POWER_MANAGEMENT1	((uint16_t)(1 << 9))
+#define REG_POWER_MANAGEMENT2	((uint16_t)(2 << 9))
+#define REG_POWER_MANAGEMENT3	((uint16_t)(3 << 9))
+#define REG_AUDIO_INTERFACE		((uint16_t)(4 << 9))
+#define REG_COMPANDING			((uint16_t)(5 << 9))
+#define REG_CLOCK_GEN			((uint16_t)(6 << 9))
+#define REG_ADDITIONAL			((uint16_t)(7 << 9))
+#define REG_GPIO				((uint16_t)(8 << 9))
+#define REG_JACK_DETECT1		((uint16_t)(9 << 9))
+#define REG_DAC					((uint16_t)(10 << 9))
+#define REG_LEFT_DAC_VOL		((uint16_t)(11 << 9))
+#define REG_RIGHT_DAC_VOL		((uint16_t)(12 << 9))
+#define REG_JACK_DETECT2		((uint16_t)(13 << 9))
+#define REG_ADC					((uint16_t)(14 << 9))
+#define REG_LEFT_ADC_VOL		((uint16_t)(15 << 9))
+#define REG_RIGHT_ADC_VOL		((uint16_t)(16 << 9))
+#define REG_EQ1					((uint16_t)(18 << 9))
+#define REG_EQ2					((uint16_t)(19 << 9))
+#define REG_EQ3					((uint16_t)(20 << 9))
+#define REG_EQ4					((uint16_t)(21 << 9))
+#define REG_EQ5					((uint16_t)(22 << 9))
+#define REG_DAC_LIMITER1		((uint16_t)(24 << 9))
+#define REG_DAC_LIMITER2		((uint16_t)(25 << 9))
+#define REG_NOTCH_FILTER1		((uint16_t)(27 << 9))
+#define REG_NOTCH_FILTER2		((uint16_t)(28 << 9))
+#define REG_NOTCH_FILTER3		((uint16_t)(29 << 9))
+#define REG_NOTCH_FILTER4		((uint16_t)(30 << 9))
+#define REG_ALC1				((uint16_t)(32 << 9))
+#define REG_ALC2				((uint16_t)(33 << 9))
+#define REG_ALC3				((uint16_t)(34 << 9))
+#define REG_NOISE_GATE			((uint16_t)(35 << 9))
+#define REG_PLL_N				((uint16_t)(36 << 9))
+#define REG_PLL_K1				((uint16_t)(37 << 9))
+#define REG_PLL_K2				((uint16_t)(38 << 9))
+#define REG_PLL_K3				((uint16_t)(39 << 9))
+#define REG_3D					((uint16_t)(41 << 9))
+#define REG_BEEP				((uint16_t)(43 << 9))
+#define REG_INPUT				((uint16_t)(44 << 9))
+#define REG_LEFT_PGA_GAIN		((uint16_t)(45 << 9))
+#define REG_RIGHT_PGA_GAIN		((uint16_t)(46 << 9))
+#define REG_LEFT_ADC_BOOST		((uint16_t)(47 << 9))
+#define REG_RIGHT_ADC_BOOST		((uint16_t)(48 << 9))
+#define REG_OUTPUT				((uint16_t)(49 << 9))
+#define REG_LEFT_MIXER			((uint16_t)(50 << 9))
+#define REG_RIGHT_MIXER			((uint16_t)(51 << 9))
+#define REG_LOUT1_VOL			((uint16_t)(52 << 9))
+#define REG_ROUT1_VOL			((uint16_t)(53 << 9))
+#define REG_LOUT2_VOL			((uint16_t)(54 << 9))
+#define REG_ROUT2_VOL			((uint16_t)(55 << 9))
+#define REG_OUT3_MIXER			((uint16_t)(56 << 9))
+#define REG_OUT4_MIXER			((uint16_t)(57 << 9))
+
+// R01 REG_POWER_MANAGEMENT1
+#define BUFDCOPEN				(1 << 8)
+#define OUT4MIXEN				(1 << 7)
+#define OUT3MIXEN				(1 << 6)
+#define PLLEN					(1 << 5)
+#define MICBEN					(1 << 4)
+#define BIASEN					(1 << 3)
+#define BUFIOEN					(1 << 2)
+#define VMIDSEL_OFF				(0)
+#define VMIDSEL_75K				(1)
+#define VMIDSEL_300K			(2)
+#define VMIDSEL_5K				(3)
+
+// R02 REG_POWER_MANAGEMENT2
+#define ROUT1EN					(1 << 8)
+#define LOUT1EN					(1 << 7)
+#define SLEEP					(1 << 6)
+#define BOOSTENR				(1 << 5)
+#define BOOSTENL				(1 << 4)
+#define INPPGAENR				(1 << 3)
+#define INPPGAENL				(1 << 2)
+#define ADCENR					(1 << 1)
+#define ADCENL					(1)
+
+// R03 REG_POWER_MANAGEMENT3
+#define OUT4EN					(1 << 8)
+#define OUT3EN					(1 << 7)
+#define LOUT2EN					(1 << 6)
+#define ROUT2EN					(1 << 5)
+#define RMIXEN					(1 << 3)
+#define LMIXEN					(1 << 2)
+#define DACENR					(1 << 1)
+#define DACENL					(1)
+
+// R04 REG_AUDIO_INTERFACE
+#define BCP_NORMAL				(0)
+#define BCP_INVERTED			(1 << 8)
+#define LRP_NORMAL				(0)
+#define LRP_INVERTED			(1 << 7)
+#define WL_16BITS				(0)
+#define WL_20BITS				(1 << 5)
+#define WL_24BITS				(2 << 5)	// Default value
+#define WL_32BITS				(3 << 5)
+#define FMT_RIGHT_JUSTIFIED		(0)
+#define FMT_LEFT_JUSTIFIED		(1 << 3)
+#define FMT_I2S					(2 << 3)	// Default value
+#define FMT_PCM					(3 << 3)
+#define DACLRSWAP				(1 << 2)
+#define ADCLRSWAP				(1 << 1)
+#define MONO					(1)
+
+// R05 REG_COMPANDING
+#define WL8						(1 << 5)
+#define DAC_COMP_OFF			(0)			// Default value
+#define DAC_COMP_ULAW			(2 << 3)
+#define DAC_COMP_ALAW			(3 << 3)
+#define ADC_COMP_OFF			(0)			// Default value
+#define ADC_COMP_ULAW			(2 << 1)
+#define ADC_COMP_ALAW			(3 << 1)
+#define LOOPBACK				(1)
+
+// R06 REG_CLOCK_GEN
+#define CLKSEL_MCLK				(0)
+#define CLKSEL_PLL				(1 << 8)	// Default value
+#define MCLK_DIV1				(0)
+#define MCLK_DIV1_5				(1 << 5)
+#define MCLK_DIV2				(2 << 5)	// Default value
+#define MCLK_DIV3				(3 << 5)
+#define MCLK_DIV4				(4 << 5)
+#define MCLK_DIV6				(5 << 5)
+#define MCLK_DIV8				(6 << 5)
+#define MCLK_DIV12				(7 << 5)
+#define BCLK_DIV1				(0)			// Default value
+#define BCLK_DIV2				(1 << 2)
+#define BCLK_DIV4				(2 << 2)
+#define BCLK_DIV8				(3 << 2)
+#define BCLK_DIV16				(4 << 2)
+#define BCLK_DIV32				(5 << 2)
+#define MS						(1)
+
+// R07 REG_ADDITIONAL
+#define SR_48KHZ				(0)			// Default value
+#define SR_32KHZ				(1 << 1)
+#define SR_24KHZ				(2 << 1)
+#define SR_16KHZ				(3 << 1)
+#define SR_12KHZ				(4 << 1)
+#define SR_8KHZ					(5 << 1)
+#define SLOWCLKEN				(1)
+
+// R08 REG_GPIO
+#define OPCLK_DIV1				(0)			// Default value
+#define OPCLK_DIV2				(1 << 4)
+#define OPCLK_DIV3				(2 << 4)
+#define OPCLK_DIV4				(3 << 4)
+#define GPIO1POL_NONINVERTED	(0)			// Default value
+#define GPIO1POL_INVERTED		(1 << 3)
+#define GPIO1SEL_INPUT			(0)			// Default value
+#define GPIO1SEL_TEMP_OK		(2)
+#define GPIO1SEL_AMUTE_ACTIVE	(3)
+#define GPIO1SEL_PLL_CLK_OP		(4)
+#define GPIO1SEL_PLL_LOCK		(5)
+#define GPIO1SEL_LOGIC1			(6)
+#define GPIO1SEL_LOGIC0			(7)
+
+// R09 REG_JACK_DETECT1
+#define JD_VMID_EN1				(1 << 8)
+#define JD_VMID_EN0				(1 << 7)
+#define JD_EN					(1 << 6)
+#define JD_SEL_GPIO1			(0 << 4)	// Default value
+#define JD_SEL_GPIO2			(1 << 4)
+#define JD_SEL_GPIO3			(2 << 4)
+
+// R10 REG_DAC
+#define SOFTMUTE				(1 << 6)
+#define DACOSR128				(1 << 3)
+#define AMUTE					(1 << 2)
+#define DACPOLR					(1 << 1)
+#define DACPOLL					(1)
+
+// R11 & R12 REG_LEFT_DAC_VOL & REG_RIGHT_DAC_VOL
+#define DACVU					(1 << 8)
+#define DACVOL_POS				(0)
+#define DACVOL_MASK				(0xFF)
+
+// R13 REG_JACK_DETECT2
+#define JD_OUT4_EN1				(1 << 7)
+#define JD_OUT3_EN1				(1 << 6)
+#define JD_OUT2_EN1				(1 << 5)
+#define JD_OUT1_EN1				(1 << 4)
+#define JD_OUT4_EN0				(1 << 3)
+#define JD_OUT3_EN0				(1 << 2)
+#define JD_OUT2_EN0				(1 << 1)
+#define JD_OUT1_EN0				(1)
+
+// R14 REG_ADC
+#define HPFEN					(1 << 8)
+#define HPFAPP					(1 << 7)
+#define HPFCUT_POS				(4)
+#define HPFCUT_MASK				(7)
+#define HPFCUT_0				(0)
+#define HPFCUT_1				(1 << 4)
+#define HPFCUT_2				(2 << 4)
+#define HPFCUT_3				(3 << 4)
+#define HPFCUT_4				(4 << 4)
+#define HPFCUT_5				(5 << 4)
+#define HPFCUT_6				(6 << 4)
+#define HPFCUT_7				(7 << 4)
+#define ADCOSR128				(1 << 3)
+#define ADCRPOL					(1 << 1)
+#define ADCLPOL					(1)
+
+// R15 & R16 REG_LEFT_ADC_VOL & REG_RIGHT_ADC_VOL
+#define ADCVU					(1 << 8)
+#define ADCVOL_POS				(0)
+#define ADCVOL_MASK				(0xFF)
+
+// R18 REG_EQ1
+#define EQ3DMODE_ADC			(0)
+#define EQ3DMODE_DAC			(1 << 8)	// Default value
+#define EQ1C_80HZ				(0)
+#define EQ1C_105HZ				(1 << 5)	// Default value
+#define EQ1C_135HZ				(2 << 5)
+#define EQ1C_175HZ				(3 << 5)
+
+// R19 REG_EQ2
+#define EQ2BW_NARROW			(0)			// Default value
+#define EQ2BW_WIDE				(1 << 8)
+#define EQ2C_230HZ				(0)
+#define EQ2C_300HZ				(1 << 5)	// Default value
+#define EQ2C_385HZ				(2 << 5)
+#define EQ2C_500HZ				(3 << 5)
+
+// R20 REG_EQ3
+#define EQ3BW_NARROW			(0)			// Default value
+#define EQ3BW_WIDE				(1 << 8)
+#define EQ3C_650HZ				(0)
+#define EQ3C_850HZ				(1 << 5)	// Default value
+#define EQ3C_1_1KHZ				(2 << 5)
+#define EQ3C_1_4KHZ				(3 << 5)
+
+// R21 REG_EQ4
+#define EQ4BW_NARROW			(0)			// Default value
+#define EQ4BW_WIDE				(1 << 8)
+#define EQ4C_1_8KHZ				(0)
+#define EQ4C_2_4KHZ				(1 << 5)	// Default value
+#define EQ4C_3_2KHZ				(2 << 5)
+#define EQ4C_4_1KHZ				(3 << 5)
+
+// R22 REG_EQ5
+#define EQ5C_5_3KHZ				(0)
+#define EQ5C_6_9KHZ				(1 << 5)	// Default value
+#define EQ5C_9KHZ				(2 << 5)
+#define EQ5C_11_7KHZ			(3 << 5)
+
+// R18 - R22
+#define EQC_POS					(5)
+#define EQC_MASK				(3)
+#define EQG_POS					(0)
+#define EQG_MASK				(31)
+
+// R24 REG_DAC_LIMITER1
+#define LIMEN					(1 << 8)
+#define LIMDCY_POS				(4)
+#define LIMDCY_MASK				(15)
+#define LIMDCY_750US			(0)
+#define LIMDCY_1_5MS			(1 << 4)
+#define LIMDCY_3MS				(2 << 4)
+#define LIMDCY_6MS				(3 << 4)	// Default value
+#define LIMDCY_12MS				(4 << 4)
+#define LIMDCY_24MS				(5 << 4)
+#define LIMDCY_48MS				(6 << 4)
+#define LIMDCY_96MS				(7 << 4)
+#define LIMDCY_192MS			(8 << 4)
+#define LIMDCY_384MS			(9 << 4)
+#define LIMDCY_768MS			(10 << 4)
+#define LIMATK_POS				(0)
+#define LIMATK_MASK				(15)
+#define LIMATK_94US				(0)
+#define LIMATK_188US			(1)
+#define LIMATK_375US			(2)			// Default value
+#define LIMATK_750US			(3)
+#define LIMATK_1_5MS			(4)
+#define LIMATK_3MS				(5)
+#define LIMATK_6MS				(6)
+#define LIMATK_12MS				(7)
+#define LIMATK_24MS				(8)
+#define LIMATK_48MS				(9)
+#define LIMATK_96MS				(10)
+#define LIMATK_192MS			(11)
+
+// R25 REG_DAC_LIMITER2
+#define LIMLVL_POS				(4)
+#define LIMLVL_MASK				(7)
+#define LIMLVL_N1DB				(0)			// Default value
+#define LIMLVL_N2DB				(1 << 4)
+#define LIMLVL_N3DB				(2 << 4)
+#define LIMLVL_N4DB				(3 << 4)
+#define LIMLVL_N5DB				(4 << 4)
+#define LIMLVL_N6DB				(5 << 4)
+#define LIMBOOST_POS			(0)
+#define LIMBOOST_MASK			(15)
+#define LIMBOOST_0DB			(0)
+#define LIMBOOST_1DB			(1)
+#define LIMBOOST_2DB			(2)
+#define LIMBOOST_3DB			(3)
+#define LIMBOOST_4DB			(4)
+#define LIMBOOST_5DB			(5)
+#define LIMBOOST_6DB			(6)
+#define LIMBOOST_7DB			(7)
+#define LIMBOOST_8DB			(8)
+#define LIMBOOST_9DB			(9)
+#define LIMBOOST_10DB			(10)
+#define LIMBOOST_11DB			(11)
+#define LIMBOOST_12DB			(12)
+
+// R27 - R30 REG_NOTCH_FILTER1 - REG_NOTCH_FILTER4
+#define NFU						(1 << 8)
+#define NFEN					(1 << 7)
+#define NFA_POS					(0)
+#define NFA_MASK				(127)
+
+// R32 REG_ALC1
+#define ALCSEL_OFF				(0)			// Default value
+#define ALCSEL_RIGHT_ONLY		(1 << 7)
+#define ALCSEL_LEFT_ONLY		(2 << 7)
+#define ALCSEL_BOTH_ON			(3 << 7)
+#define ALCMAXGAIN_POS			(3)
+#define ALCMAXGAIN_MASK			(7)
+#define ALCMAXGAIN_N6_75DB		(0)
+#define ALCMAXGAIN_N0_75DB		(1 << 3)
+#define ALCMAXGAIN_5_25DB		(2 << 3)
+#define ALCMAXGAIN_11_25DB		(3 << 3)
+#define ALCMAXGAIN_17_25DB		(4 << 3)
+#define ALCMAXGAIN_23_25DB		(5 << 3)
+#define ALCMAXGAIN_29_25DB		(6 << 3)
+#define ALCMAXGAIN_35_25DB		(7 << 3)	// Default value
+#define ALCMINGAIN_POS			(0)
+#define ALCMINGAIN_MASK			(7)
+#define ALCMINGAIN_N12DB		(0)			// Default value
+#define ALCMINGAIN_N6DB			(1)
+#define ALCMINGAIN_0DB			(2)
+#define ALCMINGAIN_6DB			(3)
+#define ALCMINGAIN_12DB			(4)
+#define ALCMINGAIN_18DB			(5)
+#define ALCMINGAIN_24DB			(6)
+#define ALCMINGAIN_30DB			(7)
+
+// R33 REG_ALC2
+#define ALCHLD_POS				(4)
+#define ALCHLD_MASK				(15)
+#define ALCHLD_0MS				(0)			// Default value
+#define ALCHLD_2_67MS			(1 << 4)
+#define ALCHLD_5_33MS			(2 << 4)
+#define ALCHLD_10_67MS			(3 << 4)
+#define ALCHLD_21_33MS			(4 << 4)
+#define ALCHLD_42_67MS			(5 << 4)
+#define ALCHLD_85_33MS			(6 << 4)
+#define ALCHLD_170_67MS			(7 << 4)
+#define ALCHLD_341_33MS			(8 << 4)
+#define ALCHLD_682_67MS			(9 << 4)
+#define ALCHLD_1_36S			(10 << 4)
+#define ALCLVL_POS				(0)
+#define ALCLVL_MASK				(15)
+#define ALCLVL_N22_5DBFS		(0)
+#define ALCLVL_N21DBFS			(1)
+#define ALCLVL_N19_5DBFS		(2)
+#define ALCLVL_N18DBFS			(3)
+#define ALCLVL_N16_5DBFS		(4)
+#define ALCLVL_N15DBFS			(5)
+#define ALCLVL_N13_5DBFS		(6)
+#define ALCLVL_N12DBFS			(7)
+#define ALCLVL_N10_5DBFS		(8)
+#define ALCLVL_N9DBFS			(9)
+#define ALCLVL_N7_5DBFS			(10)
+#define ALCLVL_N6DBFS			(11)		// Default value
+#define ALCLVL_N4_5DBFS			(12)
+#define ALCLVL_N3DBFS			(13)
+#define ALCLVL_N1_5DBFS			(14)
+
+// R34 REG_ALC3
+#define ALCMODE_ALC				(0)			// Default value
+#define ALCMODE_LIMITER			(1 << 8)
+#define ALCDCY_POS				(4)
+#define ALCDCY_MASK				(15)
+#define ALCDCY_0				(0)
+#define ALCDCY_1				(1 << 4)
+#define ALCDCY_2				(2 << 4)
+#define ALCDCY_3				(3 << 4)	// Default value
+#define ALCDCY_4				(4 << 4)
+#define ALCDCY_5				(5 << 4)
+#define ALCDCY_6				(6 << 4)
+#define ALCDCY_7				(7 << 4)
+#define ALCDCY_8				(8 << 4)
+#define ALCDCY_9				(9 << 4)
+#define ALCDCY_10				(10 << 4)
+#define ALCATK_POS				(0)
+#define ALCATK_MASK				(15)
+#define ALCATK_0				(0)
+#define ALCATK_1				(1)
+#define ALCATK_2				(2)			// Default value
+#define ALCATK_3				(3)
+#define ALCATK_4				(4)
+#define ALCATK_5				(5)
+#define ALCATK_6				(6)
+#define ALCATK_7				(7)
+#define ALCATK_8				(8)
+#define ALCATK_9				(9)
+#define ALCATK_10				(10)
+
+// R35 REG_NOISE_GATE
+#define NGEN					(1 << 3)
+#define NGTH_POS				(0)
+#define NGTH_MASK				(7)
+#define NGTH_N39DB				(0)			// Default value
+#define NGTH_N45DB				(1)
+#define NGTH_N51DB				(2)
+#define NGTH_N57DB				(3)
+#define NGTH_N63DB				(4)
+#define NGTH_N69DB				(5)
+#define NGTH_N75DB				(6)
+#define NGTH_N81DB				(7)
+
+// R36 REG_PLL_N
+#define PLLPRESCALE				(1 << 4)
+#define PLLN_POS				(0)
+#define PLLN_MASK				(15)
+
+// R37 - R39 REG_PLL_K1 - REG_PLL_K3
+#define PLLK1_POS				(0)
+#define PLLK1_MASK				(63)
+#define PLLK2_POS				(0)
+#define PLLK2_MASK				(511)
+#define PLLK3_POS				(0)
+#define PLLK3_MASK				(511)
+
+// R41 REG_3D
+#define DEPTH3D_POS				(0)
+#define DEPTH3D_MASK			(15)
+#define DEPTH3D_0				(0)			// Default value
+#define DEPTH3D_6_67			(1)
+#define DEPTH3D_13_33			(2)
+#define DEPTH3D_20				(3)
+#define DEPTH3D_26_67			(4)
+#define DEPTH3D_33_33			(5)
+#define DEPTH3D_40				(6)
+#define DEPTH3D_46_67			(7)
+#define DEPTH3D_53_33			(8)
+#define DEPTH3D_60				(9)
+#define DEPTH3D_66_67			(10)
+#define DEPTH3D_73_33			(11)
+#define DEPTH3D_80				(12)
+#define DEPTH3D_86_67			(13)
+#define DEPTH3D_93_33			(14)
+#define DEPTH3D_100				(15)
+
+// R43 REG_BEEP
+#define MUTERPGA2INV			(1 << 5)
+#define INVROUT2				(1 << 4)
+#define BEEPVOL_POS				(1)
+#define BEEPVOL_MASK			(7)
+#define BEEPVOL_N15DB			(0)
+#define BEEPVOL_N12DB			(1 << 1)
+#define BEEPVOL_N9DB			(2 << 1)
+#define BEEPVOL_N6DB			(3 << 1)
+#define BEEPVOL_N3DB			(4 << 1)
+#define BEEPVOL_0DB				(5 << 1)
+#define BEEPVOL_3DB				(6 << 1)
+#define BEEPVOL_6DB				(7 << 1)
+#define BEEPEN					(1)
+
+// R44 REG_INPUT
+#define MBVSEL_0_9AVDD			(0)			// Default value
+#define MBVSEL_0_65AVDD			(1 << 8)
+#define R2_2INPVGA				(1 << 6)
+#define RIN2INPVGA				(1 << 5)	// Default value
+#define RIP2INPVGA				(1 << 4)	// Default value
+#define L2_2INPVGA				(1 << 2)
+#define LIN2INPVGA				(1 << 1)	// Default value
+#define LIP2INPVGA				(1)			// Default value
+
+// R45 REG_LEFT_PGA_GAIN
+#define INPPGAUPDATE			(1 << 8)
+#define INPPGAZCL				(1 << 7)
+#define INPPGAMUTEL				(1 << 6)
+
+// R46 REG_RIGHT_PGA_GAIN
+#define INPPGAZCR				(1 << 7)
+#define INPPGAMUTER				(1 << 6)
+
+// R45 - R46
+#define INPPGAVOL_POS			(0)
+#define INPPGAVOL_MASK			(63)
+
+// R47 REG_LEFT_ADC_BOOST
+#define PGABOOSTL				(1 << 8)	// Default value
+#define L2_2BOOSTVOL_POS		(4)
+#define L2_2BOOSTVOL_MASK		(7)
+#define L2_2BOOSTVOL_DISABLED	(0)			// Default value
+#define L2_2BOOSTVOL_N12DB		(1 << 4)
+#define L2_2BOOSTVOL_N9DB		(2 << 4)
+#define L2_2BOOSTVOL_N6DB		(3 << 4)
+#define L2_2BOOSTVOL_N3DB		(4 << 4)
+#define L2_2BOOSTVOL_0DB		(5 << 4)
+#define L2_2BOOSTVOL_3DB		(6 << 4)
+#define L2_2BOOSTVOL_6DB		(7 << 4)
+#define AUXL2BOOSTVOL_POS		(0)
+#define AUXL2BOOSTVOL_MASK		(7)
+#define AUXL2BOOSTVOL_DISABLED	(0)			// Default value
+#define AUXL2BOOSTVOL_N12DB		(1)
+#define AUXL2BOOSTVOL_N9DB		(2)
+#define AUXL2BOOSTVOL_N6DB		(3)
+#define AUXL2BOOSTVOL_N3DB		(4)
+#define AUXL2BOOSTVOL_0DB		(5)
+#define AUXL2BOOSTVOL_3DB		(6)
+#define AUXL2BOOSTVOL_6DB		(7)
+
+// R48 REG_RIGHT_ADC_BOOST
+#define PGABOOSTR				(1 << 8)	// Default value
+#define R2_2BOOSTVOL_POS		(4)
+#define R2_2BOOSTVOL_MASK		(7)
+#define R2_2BOOSTVOL_DISABLED	(0)			// Default value
+#define R2_2BOOSTVOL_N12DB		(1 << 4)
+#define R2_2BOOSTVOL_N9DB		(2 << 4)
+#define R2_2BOOSTVOL_N6DB		(3 << 4)
+#define R2_2BOOSTVOL_N3DB		(4 << 4)
+#define R2_2BOOSTVOL_0DB		(5 << 4)
+#define R2_2BOOSTVOL_3DB		(6 << 4)
+#define R2_2BOOSTVOL_6DB		(7 << 4)
+#define AUXR2BOOSTVOL_POS		(0)
+#define AUXR2BOOSTVOL_MASK		(7)
+#define AUXR2BOOSTVOL_DISABLED	(0)			// Default value
+#define AUXR2BOOSTVOL_N12DB		(1)
+#define AUXR2BOOSTVOL_N9DB		(2)
+#define AUXR2BOOSTVOL_N6DB		(3)
+#define AUXR2BOOSTVOL_N3DB		(4)
+#define AUXR2BOOSTVOL_0DB		(5)
+#define AUXR2BOOSTVOL_3DB		(6)
+#define AUXR2BOOSTVOL_6DB		(7)
+
+// R49 REG_OUTPUT
+#define DACL2RMIX				(1 << 6)
+#define DACR2LMIX				(1 << 5)
+#define OUT4BOOST				(1 << 4)
+#define OUT3BOOST				(1 << 3)
+#define SPKBOOST				(1 << 2)
+#define TSDEN					(1 << 1)
+#define VROI					(1)
+
+// R50 REG_LEFT_MIXER
+#define AUXLMIXVOL_POS			(6)
+#define AUXLMIXVOL_MASK			(7)
+#define AUXLMIXVOL_N15DB		(0)			// Default value
+#define AUXLMIXVOL_N12DB		(1 << 6)
+#define AUXLMIXVOL_N9DB			(2 << 6)
+#define AUXLMIXVOL_N6DB			(3 << 6)
+#define AUXLMIXVOL_N3DB			(4 << 6)
+#define AUXLMIXVOL_0DB			(5 << 6)
+#define AUXLMIXVOL_3DB			(6 << 6)
+#define AUXLMIXVOL_6DB			(7 << 6)
+#define AUXL2LMIX				(1 << 5)
+#define BYPLMIXVOL_POS			(2)
+#define BYPLMIXVOL_MASK			(7)
+#define BYPLMIXVOL_N15DB		(0)			// Default value
+#define BYPLMIXVOL_N12DB		(1 << 2)
+#define BYPLMIXVOL_N9DB			(2 << 2)
+#define BYPLMIXVOL_N6DB			(3 << 2)
+#define BYPLMIXVOL_N3DB			(4 << 2)
+#define BYPLMIXVOL_0DB			(5 << 2)
+#define BYPLMIXVOL_3DB			(6 << 2)
+#define BYPLMIXVOL_6DB			(7 << 2)
+#define BYPL2LMIX				(1 << 1)
+#define DACL2LMIX				(1)
+
+// R51 REG_RIGHT_MIXER
+#define AUXRMIXVOL_POS			(6)
+#define AUXRMIXVOL_MASK			(7)
+#define AUXRMIXVOL_N15DB		(0)			// Default value
+#define AUXRMIXVOL_N12DB		(1 << 6)
+#define AUXRMIXVOL_N9DB			(2 << 6)
+#define AUXRMIXVOL_N6DB			(3 << 6)
+#define AUXRMIXVOL_N3DB			(4 << 6)
+#define AUXRMIXVOL_0DB			(5 << 6)
+#define AUXRMIXVOL_3DB			(6 << 6)
+#define AUXRMIXVOL_6DB			(7 << 6)
+#define AUXR2RMIX				(1 << 5)
+#define BYPRMIXVOL_POS			(2)
+#define BYPRMIXVOL_MASK			(7)
+#define BYPRMIXVOL_N15DB		(0)			// Default value
+#define BYPRMIXVOL_N12DB		(1 << 2)
+#define BYPRMIXVOL_N9DB			(2 << 2)
+#define BYPRMIXVOL_N6DB			(3 << 2)
+#define BYPRMIXVOL_N3DB			(4 << 2)
+#define BYPRMIXVOL_0DB			(5 << 2)
+#define BYPRMIXVOL_3DB			(6 << 2)
+#define BYPRMIXVOL_6DB			(7 << 2)
+#define BYPR2RMIX				(1 << 1)
+#define DACR2RMIX				(1)
+
+// R52 - R55 REG_LOUT1_VOL - REG_ROUT2_VOL
+#define HPVU					(1 << 8)
+#define SPKVU					(1 << 8)
+#define LOUT1ZC					(1 << 7)
+#define LOUT1MUTE				(1 << 6)
+#define ROUT1ZC					(1 << 7)
+#define ROUT1MUTE				(1 << 6)
+#define LOUT2ZC					(1 << 7)
+#define LOUT2MUTE				(1 << 6)
+#define ROUT2ZC					(1 << 7)
+#define ROUT2MUTE				(1 << 6)
+#define VOL_POS					(0)
+#define VOL_MASK				(63)
+
+// R56 REG_OUT3_MIXER
+#define OUT3MUTE				(1 << 6)
+#define OUT4_2OUT3				(1 << 3)
+#define BYPL2OUT3				(1 << 2)
+#define LMIX2OUT3				(1 << 1)
+#define LDAC2OUT3				(1)
+
+// R57 REG_OUT4_MIXER
+#define OUT4MUTE				(1 << 6)
+#define HALFSIG					(1 << 5)
+#define LMIX2OUT4				(1 << 4)
+#define LDAC2OUT4				(1 << 3)
+#define BYPR2OUT4				(1 << 2)
+#define RMIX2OUT4				(1 << 1)
+#define RDAC2OUT4				(1)
+
+#endif	// #ifndef __CODEC_H__

+ 3 - 7
bsp/stm32_radio/startup.c

@@ -44,8 +44,8 @@ extern void finsh_system_init(void);
 extern void finsh_set_device(const char* device);
 #endif
 extern int rt_application_init(void);
-extern rt_err_t wm8753_hw_init(void);
-extern rt_err_t wm8978_hw_init(void);
+extern rt_err_t codec_hw_init(void);
+extern rt_err_t codec_hw_init(void);
 #ifdef  DEBUG
 /*******************************************************************************
 * Function Name  : assert_failed
@@ -104,11 +104,7 @@ void rtthread_startup(void)
     /* init scheduler system */
     rt_system_scheduler_init();
 
-#if CODEC_VERSION == 1
-    wm8753_hw_init();
-#elif CODEC_VERSION == 2
-    wm8978_hw_init();
-#endif
+    codec_hw_init();
 
     /* init hardware serial device */
     rt_hw_usart_init();

+ 4 - 4
bsp/stm32_radio/stm32f10x_it.c

@@ -365,7 +365,7 @@ void DMA1_Channel4_IRQHandler(void)
 *******************************************************************************/
 void DMA1_Channel5_IRQHandler(void)
 {
-    extern void wm8753_dma_isr(void);
+    extern void codec_dma_isr(void);
 
     /* enter interrupt */
     rt_interrupt_enter();
@@ -377,7 +377,7 @@ void DMA1_Channel5_IRQHandler(void)
 
         // rt_kprintf("DMA\n");
         /* transmission complete, invoke serial dma tx isr */
-        wm8753_dma_isr();
+        codec_dma_isr();
     }
 
     /* leave interrupt */
@@ -446,12 +446,12 @@ void EXTI9_5_IRQHandler(void)
 *******************************************************************************/
 void SPI2_IRQHandler(void)
 {
-    extern void wm8753_isr(void);
+    extern void codec_isr(void);
 
     /* enter interrupt */
     rt_interrupt_enter();
 
-    wm8753_isr();
+    codec_isr();
 
     /* leave interrupt */
     rt_interrupt_leave();