/*! * \file pga_adc.c * * \brief Target pga adc implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #include "pga_adc.h" #include "adc.h" #include "ringbuffer.h" #include "xc6xxx_hal_adc.h" #include "xc6xxx_hal_uart.h" /*------------------------------------------------------------------------------------ Macros -------------------------------------------------------------------------------------*/ #define USER_NOISE_EN 0 /*------------------------------------------------------------------------------------ Global Variables -------------------------------------------------------------------------------------*/ Mic_sampling_cb m_sampling_cb; extern void UART_SendByte(UART_TypeDef *UARTx, uint8_t Byte); extern uint8_t adc_ch_buff[1000]; extern uint32_t adc_val_buff[500]; extern uint16_t adc_con; /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ /** **************************************************************************************** * @brief * * @param[in] * @param[in] * @return[out] * **************************************************************************************** */ void adc_uart_init(void) { // uint8_t rxbuff[26]; GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Mux = GPIO_Mux0; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Int = NOT_INT; GPIO_InitStruct.Pin = GPIO_3; GPIO_InitStruct.Dir = GPIO_DIR_OUTPUT; GPIO_InitStruct.FunSel = UART1_TX; GPIO_Init(&GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_2; GPIO_InitStruct.Dir = GPIO_DIR_INPUT; GPIO_InitStruct.FunSel = UART1_RX; GPIO_Init(&GPIO_InitStruct); UART_InitTypeDef UART_InitStruct = {0}; UART_InitStruct.Parity = UART_PARITY_DISABLE; UART_InitStruct.StopBits = UART_STOP_1_BITS; UART_InitStruct.WordLength = UART_UARTx_TCR_CLS_8BITS; UART_InitStruct.BaudRate = UART_BAUDRATE_1M; UART_InitStruct.HardwareFlowControl = UART_UARTx_MCR_AFCE_DISABLE; UART_Init(XC_UART1, &UART_InitStruct); UART_Enable_RxIT(XC_UART1); NVIC_EnableIRQ(UART1_IRQn); } void uart_seed_data(uint8_t data) { UART_SendByte(XC_UART1, data); } void uart_seed_buff(uint8_t *Data, uint16_t len) { UART_SendData(XC_UART1, Data, len); } // extern unsigned int filter_data(unsigned int data); // 对采样到的ADC值进行处理 void pga_adc_rx_event_handler(uint16_t pga_adc_val) { #if USER_NOISE_EN static uint8_t delay_con = 0; static uint32_t voice_data_bk = 0; #endif static uint8_t freq_con = 0; short voice_data = 0; freq_con++; if (freq_con < m_sampling_cb.freq_con) return; freq_con = 0; #if SAMPLING_DEBUG if (m_sampling_cb.rx_flag) return; m_sampling_cb.pga_adc_rx_con++; #endif #if REC_TEST_EN || SAMPLING_DEBUG if (!m_sampling_cb.rec_len_time) { #if SAMPLING_DEBUG m_sampling_cb.rx_flag = 1; #endif // SAMPLING_DEBUG return; } #endif // REC_TEST_EN || SAMPLING_DEBUG // voice_data = pga_adc_val; // if (pga_adc_val > 50) pga_adc_val = pga_adc_val - 50;//平移 voice_data = pga_adc_val; #if USER_NOISE_EN if (pga_adc_val > 2100 || pga_adc_val < 1900) { delay_con = 0; } else { delay_con++; if (delay_con >= 50) { delay_con = 50; pga_adc_val = (voice_data_bk + pga_adc_val) / 2; pga_adc_val = 1024 + pga_adc_val / 2; } } voice_data_bk = voice_data = pga_adc_val; #endif // USER_NOISE_EN if (voice_data > 2047) { voice_data = (((uint32_t)voice_data - 2047) * 0x7fff / 2048); voice_data &= ~0x8000; } else { voice_data = (((uint32_t)2047 - voice_data) * 0x7fff / 2048); voice_data = 0x7fff - voice_data; voice_data |= 0x8000; } m_sampling_cb.mic_adc_buff[m_sampling_cb.save_buf_index] [m_sampling_cb.pga_adc_rx_index] = voice_data; m_sampling_cb.pga_adc_rx_index++; if (m_sampling_cb.pga_adc_rx_index >= MIC_SAMPLING_MAX_LEN) { m_sampling_cb.pga_adc_rx_index = 0; m_sampling_cb.save_buf_index = !m_sampling_cb.save_buf_index; m_sampling_cb.buf_full_flag = 1; } } #if (USE_XIP == 1) /** * @brief mic_pga_adc_sampling_set * @details * @param void * @retval void */ void mic_pga_adc_sampling_set(void) { CLOCK_HighFreq_In_Typedef uclock_freq = CLOCK_HighFreq_Get(); #if (SAMPLING_TYPE == MIC_SAMPLING_8K) #if (ADC_FREQ_CLOCK == ADC_CLK_DIV_2) if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 32; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 24; } else { m_sampling_cb.freq_con = 19; } #else //===========ADC时钟为2/4M的时候 if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 32; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 21; } else { m_sampling_cb.freq_con = 15; } #endif //(ADC_FREQ_CLOCK == ADC_CLK_DIV_2) #else // 16k采样 #if (ADC_FREQ_CLOCK == ADC_CLK_DIV_2) if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 18; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 12; } else { m_sampling_cb.freq_con = 9; } #elif (ADC_FREQ_CLOCK == ADC_CLK_DIV_4) if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 13; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 8; } else { m_sampling_cb.freq_con = 7; } #else //===========ADC时钟为2的时候 if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 16; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 9; } else { m_sampling_cb.freq_con = 5; } #endif //(ADC_FREQ_CLOCK == ADC_CLK_DIV_2) #endif //(SAMPLING_TYPE == MIC_SAMPLING_8K) } #else /** * @brief mic_pga_adc_sampling_set * @details * @param void * @retval void */ void mic_pga_adc_sampling_set(void) { CLOCK_HighFreq_In_Typedef uclock_freq = CLOCK_HighFreq_Get(); #if (SAMPLING_TYPE == MIC_SAMPLING_8K) if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 32; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 24; } else { m_sampling_cb.freq_con = 20; } //===========ADC采样率为2/4M的时候 if (uclock_freq == CLOCK_HFCLK_IN_96M) // { // m_sampling_cb.freq_con = 32; // } // else if (uclock_freq == CLOCK_HFCLK_IN_64M) // { // m_sampling_cb.freq_con = 21; // } // else // { // m_sampling_cb.freq_con = 20; // } #else if (uclock_freq == CLOCK_HFCLK_IN_96M) { m_sampling_cb.freq_con = 16; } else if (uclock_freq == CLOCK_HFCLK_IN_64M) { m_sampling_cb.freq_con = 12; } else { m_sampling_cb.freq_con = 10; } //===========ADC采样率为2/4M的时候 // if (uclock_freq == CLOCK_HFCLK_IN_96M) // { // m_sampling_cb.freq_con = 16; // } // else if (uclock_freq == CLOCK_HFCLK_IN_64M) // { // m_sampling_cb.freq_con = 9; // } // else // { // m_sampling_cb.freq_con = 7; // } #endif // (SAMPLING_TYPE == MIC_SAMPLING_8K) } #endif // USE_XIP == 1 /** * @brief mic_pga_adc_sampling_set * @details * @param void * @retval void */ uint32_t pga_adc_data_uart_byte_delay(void) { uint32_t delay = 0; CLOCK_HighFreq_In_Typedef uclock_freq = CLOCK_HighFreq_Get(); #if (ADC_FREQ_CLOCK == ADC_CLK_DIV_2) if (uclock_freq == CLOCK_HFCLK_IN_64M) { delay = 210; } else { delay = 75; } #else if (uclock_freq == CLOCK_HFCLK_IN_64M) { delay = 210; } else { delay = 86; } #endif return delay; } /** * @brief pga_init * @details * @param void * @retval void */ void pga_init(void) { uint32_t adc_reg = 0; DEBUG("audio_adc_ctrl_reg0 = %x\n", *((volatile unsigned int *)(0x400001BC))); // for(int i=0; i<0x100000; i++); //delay adc_reg = *((volatile unsigned int *)(0x400001BC)); adc_reg &= ~(1 << 28); adc_reg |= (1 << 28); // opa第1级增益 +20DB adc_reg &= ~(0x0f << 24); adc_reg |= (0x0a << 24); // opa第2级增益 +16DB //主要修改增益处(<24-27>) adc_reg &= ~(0x7 << 21); adc_reg |= (0x7 << 21); // BIT21-23电流大小控制,最大为000,最小为111 adc_reg &= ~(0x0F << 0); // bias寄存器 控制电流 adc_reg &= ~(0x1 << 4); // opa pd信号 adc_reg &= ~(1 << 12); // open pdbias adc_reg |= (0x1 << 5); // 差分 adc_reg &= ~(1 << 7); // open pdbias pga第1级增益, *((volatile unsigned int *)(0x400001BC)) = adc_reg; DEBUG("after audio_adc_ctrl_reg0 = %x\n", *((volatile unsigned int *)(0x400001BC))); } /** * @brief mic_pga_adc_demo * @details * @param void * @retval void */ void mic_pga_adc_demo(void) { // DEBUG("__MIC_PGA_ADC_DEMO__\r"); adc_uart_init(); // uint16_t adc_val = 0; adc_cfg adc_cfg; GPIO_InitTypeDef GPIO_InitCfg = {0}; GPIO_InitCfg.Mux = GPIO_Mux0; GPIO_InitCfg.FunSel = GPIO_Dx; GPIO_InitCfg.Pull = GPIO_NOPULL; // Board Led1 Initialization GPIO_InitCfg.Dir = GPIO_DIR_INPUT; GPIO_InitCfg.Int = NOT_INT; GPIO_InitCfg.Pin = 6; GPIO_Init(&GPIO_InitCfg); // GPIO_InitCfg.Pin = 8; // GPIO_Init(&GPIO_InitCfg); // // GPIO_InitCfg.Pin = 9; // GPIO_Init(&GPIO_InitCfg); #if SAMPLING_DEBUG || REC_TEST_EN TIMER_BaseInitTypeDef Timer_Init; Timer_Init.src_clk = TIMER_CLK_SRC_32M_DIV; Timer_Init.mode = TIMER_MODE_CYCLE_COUNT; Timer_Init.div_clk = TIMER_DIV_CLK_1MHzOr1K; // Timer0 Config & Start TIMER_Base_Init(XC_TIMER1, &Timer_Init); TIMER_SetUs(XC_TIMER1, 1000000); // 测试采样到的时候改成1秒,录音测试改成5秒或者其他 #endif // pga初始化 pga_init(); /*----- Special Pin -----*/ /*< SWD 和 SWCK 引脚也可以作为 ADC 使用, 注意 PIN 脚的功能重映射 >*/ // GPIO_MuxCtl(12,GPIO_Mux1); // GPIO_MuxCtl(13,GPIO_Mux1); /*-----------------------*/ adc_cfg.Freq = ADC_FREQ_4M; adc_cfg.RefVol = ADC_REF_VOL_3_3V; adc_cfg.SampEdge = ADC_SAMPEDGE_FALL; adc_cfg.ExtDataMode = ADC_DATA_MODE_32BIT; adc_cfg.ExtEdgeSel = ADC_EXT_EDGE_SEL_INTER; // ADC_EXT_EDGE_SEL_EXTERN_RISE // // ADC_EXT_EDGE_SEL_EXTERN_BOTH adc_cfg.ExtSampleNum = ADC_SAMPLE_NUM_16; adc_cfg.ExtTriggerSel = ADC_TRIGGER_SEL_PWM0; ADC_Init(XC_ADC, &adc_cfg); // 采样率设置 mic_pga_adc_sampling_set(); // ADC改动跟着改动 __ADC_ChannelSet(XC_ADC, ADC_CHANNEL13_PIN6); __ADC_FIFO_ReqIntLenthSet(XC_ADC); __ADC_FIFO_Flush(XC_ADC); __ADC_Clear_IT_Flag(XC_ADC); //=============中断======================= ADC_Enable_IT(XC_ADC, ADC_INT_EN_READ_REQ_EN_ENABLE | ADC_INT_EN_FIFO_ERROR_EN_ENABLE); NVIC_EnableIRQ(GADC_IRQn); __ADC_Enable(XC_ADC); #if SAMPLING_DEBUG || REC_TEST_EN TIMER_Start_IT(XC_TIMER1); m_sampling_cb.rec_len_time = 5; // 秒 uint8_t rec_time; rec_time = m_sampling_cb.rec_len_time; #endif DEBUG("start adc\n"); short voice_data = 0; uint16_t voice_adc_rx_index = 0; uint32_t uart_byte_delay = pga_adc_data_uart_byte_delay(); while (1) { #if SAMPLING_DEBUG if (m_sampling_cb.rx_flag) { Delay_Ms(500); DEBUG("sampling: %d.%dKhz\n", (m_sampling_cb.pga_adc_rx_con / rec_time) / 1000, (m_sampling_cb.pga_adc_rx_con / rec_time) % 1000); } #endif // ADC_MIC_StartGetValue(XC_ADC, ADC_CHANNEL13_PIN6,&adc_val); //轮询 if (m_sampling_cb.buf_full_flag) { m_sampling_cb.buf_full_flag = 0; voice_adc_rx_index = 0; while (voice_adc_rx_index < MIC_SAMPLING_MAX_LEN) { voice_data = m_sampling_cb.mic_adc_buff[!m_sampling_cb.save_buf_index] [voice_adc_rx_index]; // DEBUG("%d\n",voice_data); uart_seed_data(voice_data & 0xff); for (uint16_t i = 0; i < uart_byte_delay; i++) ; // 64M延时 uart_seed_data((voice_data >> 8) & 0xff); for (uint16_t i = 0; i < uart_byte_delay; i++) ; // 64M延时 voice_adc_rx_index++; } // m_sampling_cb.save_buf_index = !m_sampling_cb.save_buf_index; } } } void Timer1_Callback(void *context) { (void)context; #if SAMPLING_DEBUG // m_sampling_cb.rx_flag = 1; #endif #if REC_TEST_EN if (m_sampling_cb.rec_len_time) { // DEBUG("m_sampling_cb.rec_len_time\n"); m_sampling_cb.rec_len_time--; } #endif } //=========================================PGA+ADC相关的========================================= void ADC_MIC_StartGetValue(ADC_TypeDef *ADCx, ADC_ChannelTypeDef Channel, uint16_t *adc_val) { uint32_t val; ADC_FIFO_TypeDef *fifo_val = NULL; if (__ADC_ChannelGet(XC_ADC) != Channel) { __ADC_Disable(ADCx); __ADC_ChannelSet(ADCx, Channel); __ADC_FIFO_ReqIntLenthSet(ADCx); __ADC_FIFO_Flush(ADCx); __ADC_Clear_IT_Flag(ADCx); __ADC_Enable(ADCx); } val = ADCx->INT_RAW; if (((val & ADC_INT_READ_REQ_INT_Msk) != ADC_INT_READ_REQ_INT_Msk)) { return; } __ADC_Clear_IT_Flag(ADCx); fifo_val = (ADC_FIFO_TypeDef *)&val; for (int t = 0; t < ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8; t++) { val = ADCx->FIFO; if (fifo_val->chanel_1 != fifo_val->chanel_2) { // DEBUG("channel error :%d\n",t); continue; } if (fifo_val->chanel_1 != Channel) { // DEBUG("channel error :%d\n",t); continue; } pga_adc_rx_event_handler(fifo_val->value_1); pga_adc_rx_event_handler(fifo_val->value_2); } *adc_val = fifo_val->value_1; __ADC_FIFO_Flush(ADCx); // __ADC_Disable(ADCx); // __ADC_ChannelSet(ADCx, Channel); // __ADC_Clear_IT_Flag(XC_ADC); // __ADC_Enable(XC_ADC); } //================================================================================= void PGA_ADC_Intr_Callback(void) { uint32_t adc_int; uint32_t val; ADC_FIFO_TypeDef *fifo_val = NULL; adc_int = XC_ADC->INT; if (!(adc_int & (ADC_INT_READ_REQ_INT_Msk | ADC_INT_FIFO_ERROR_INT_Msk))) { return; } // 开关ADC会影响采样率,需要重新调整 //__ADC_Disable(XC_ADC); fifo_val = (ADC_FIFO_TypeDef *)&val; for (int t = 0; t < ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8; t++) { val = XC_ADC->FIFO; if (fifo_val->chanel_1 == ADC_CHANNEL13_PIN6) { pga_adc_rx_event_handler(fifo_val->value_1); } if (fifo_val->chanel_2 == ADC_CHANNEL13_PIN6) { pga_adc_rx_event_handler(fifo_val->value_2); } // if (t==7) // __ADC_Enable(XC_ADC); } // __ADC_Enable(XC_ADC); __ADC_FIFO_Flush(XC_ADC); } void ADC_Intr_Callback(void) { ADC_channelswitch_hw_Intr_Callback(); // adc硬件切换 // ADC_channelswitch_sw_Intr_Callback();//adc软件切换 // PGA_ADC_Intr_Callback(); //录音pga }