#include "user_driver.h"
#include "Drv_adc.h"

#include "system.h"
#include "yc11xx_bt_interface.h"
#include "att.h"
#include "core_cm0.h"
#include "yc11xx_pwm.h"
#include "user_driver.h"
#include "Drv_adc.h"
#include "yc11xx_gpio.h"
#include "yc11xx_qspi.h"
#include "LH_TaskManager.h"

/*
@file��user_driver.c
@author: LiuHao 
Creation Date��2021/07/27
Function: Add related drivers
*/

void PWM_Config(GPIO_NUM gpio, PWM_ChxTypeDef pwm_channel, uint16_t pcnt,uint16_t ncnt, PWM_ClkdivDef clk_div,START_TypeDef LEVEL, PWM_SwitchDef SWITCH);
void PWM_Config(GPIO_NUM gpio, PWM_ChxTypeDef pwm_channel, uint16_t pcnt,uint16_t ncnt, PWM_ClkdivDef clk_div,START_TypeDef LEVEL, PWM_SwitchDef SWITCH)
{
	PWM_InitTypeDef PWM_InitStruct;
	PWM_InitStruct.pwm_gpio = gpio;
	PWM_InitStruct.PWM_Channel = pwm_channel;
	PWM_InitStruct.HighLevelPeriod = pcnt;
	PWM_InitStruct.LowLevelPeriod = ncnt;
	PWM_InitStruct.pwm_ctrl.clk_div = clk_div;
	PWM_InitStruct.pwm_ctrl.StartLevel = LEVEL;
	PWM_InitStruct.pwm_ctrl.pwm_switch = SWITCH;
	PWM_Init(&PWM_InitStruct);
}
uint8_t Hal_Timer_CheckTimerClock(uint32_t frequency)
{
    uint8_t div;
    if(frequency >= HAL_MIN_48M_MIN_FREQUENCY   && frequency <= HAL_MAX_48M_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_0;
    }
    else if(frequency >= HAL_MIN_24M_MIN_FREQUENCY   && frequency <= HAL_MAX_24M_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_1;
    }
    else if(frequency >= HAL_MIN_12M_MIN_FREQUENCY   && frequency <= HAL_MAX_12M_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_2;
    }
    else if(frequency >= HAL_MIN_6M_MIN_FREQUENCY    && frequency <= HAL_MAX_6M_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_3;
    }
    else if(frequency >= HAL_MIN_3M_MIN_FREQUENCY    && frequency <= HAL_MAX_3M_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_4;
    }
    else if(frequency >= HAL_MIN_1500K_MIN_FREQUENCY && frequency <= HAL_MAX_1500K_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_5;
    }
    else if(frequency >= HAL_MIN_750K_MIN_FREQUENCY  && frequency <= HAL_MAX_750K_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_6;
    }
    else if(frequency >= HAL_MIN_375K_MIN_FREQUENCY  && frequency <= HAL_MAX_375K_MAX_FREQUENCY)
    {
        div = FREQUENCY_DIVISION_7;
    }

    return div;
}
/**
#define FREQUENCY_48M_1US 48
#define FREQUENCY_24M_1US 24
#define FREQUENCY_12M_1US 12
#define FREQUENCY_6M_1US 6
#define FREQUENCY_3M_1US 3
#define FREQUENCY_1500K_3US 2
#define FREQUENCY_750K_3US 4
#define FREQUENCY_375K_3US 8
*/
uint16_t Hal_Timer_GetOneCycleCount(uint32_t frequency,uint8_t clock)
{
    uint32_t count;
    switch (clock)
    {
    case FREQUENCY_DIVISION_0: //48M
        count = 48000000 / frequency;
        break;
    case FREQUENCY_DIVISION_1:
        count = 24000000 / frequency;
        break;
    case FREQUENCY_DIVISION_2:
        count = 12000000 / frequency;
        break;
    case FREQUENCY_DIVISION_3:
        count = 6000000 / frequency;
        break;
    case FREQUENCY_DIVISION_4:
        count = 3000000 / frequency;
        break;
    case FREQUENCY_DIVISION_5:
        // count = 2000000 / (3*frequency);
        count = 1500000 / (frequency);
        break;
    case FREQUENCY_DIVISION_6:
        count = 750000 / (frequency);
        break;
    case FREQUENCY_DIVISION_7:
        count = 375000 / (frequency);
        break;
    default:
			  break;
    }
    
    return count;
}
void UserSet_OutPWM(GPIO_NUM gpio, PWM_ChxTypeDef pwm_channel,uint32_t frequecy,uint32_t percent){
	 
	if(percent>=100)
	{
	   GPIO_SetOut(gpio,OUT_HIGH);
	}
	else if(percent==0)
	{
	  GPIO_SetOut(gpio,OUT_LOW);
	}
	else
	{
   uint8_t divClk=0;
	 uint32_t count=0;uint32_t pCnt=0,nCnt,temp=0;
	 divClk = Hal_Timer_CheckTimerClock(frequecy*2); //��Ƶ�� 
   temp = Hal_Timer_GetOneCycleCount(frequecy*2, divClk); //�������ڼ���ֵ 
#ifdef DEBUG_PWM
	MyPrintf("DivClk=%x,temp=%x\r\n",divClk,temp);
#endif
   
	 pCnt = (uint32_t)((float)(temp * percent * 100)/10000.0); 
		if(!(temp > pCnt))//error
		{
			#ifdef DEBUG_PWM
			 MyPrintf("\r\nerror\r\n",pCnt,nCnt);
			#endif
			 return;
		}
	nCnt = temp - pCnt;
		#ifdef DEBUG_PWM
	MyPrintf("\r\ntemp=%d,pCnt=%d,nCnt=%d\r\n",temp,pCnt,nCnt);
		#endif
	PWM_Config(gpio,pwm_channel,pCnt,nCnt,divClk,OutputLow,PWM_ENABLE);//no��Ƶ 
	}
}

/*���´���ADC��ش���*/
void ADC_Configuration(void);
/**
  * @brief  ADC initialization function.
  * @param  None
  * @retval None
  */
void ADC_Configuration(void)
{
	GPIO_SetGpioMultFunction(ADC_GET_GPIOx,GPCFG_NO_IE);
	
	ADC_InitTypeDef ADCInitStruct;
	ADCInitStruct.ADC_Channel = ADC_CHANNEL_5;
	ADCInitStruct.ADC_Mode = ADC_GPIO;
#ifdef hvin_test
	ADCInitStruct.ADC_Mode = ADC_HVIN;
#endif
	ADC_Init(&ADCInitStruct);
#ifdef DEBUG_ADC
//	printf("adc_init suc, gpio mode test 0-1.2V!\n");
	MyPrintf("testing channel %d\n",ADCInitStruct.ADC_Channel);
#endif
}

#include "yc11xx_gpio.h"
#include "Drv_mic.h"
#include <stdlib.h>
#include <math.h>
extern MIC_CUR_VARIABLE sMicCurVariable;
/*
 * @method Audio_sampling_init
 * @brief  mic adc init
 * @retval None
 */
void Audio_sampling_init()
{
	DRV_Mic_Init();
	DRV_Mic_Enable();
}
/*
 * @method Audio_get_buffer_len
 * @brief  Get adc dma buf unread data length.
 * @retval None
 */
int Audio_get_buffer_len()
{
	int audioWPtr = HREADW(CORE_ADCD_ADDR) ;
	int audioRPtr = TO_16BIT_ADDR(sMicCurVariable.mReadPtr) ;
	int audioBufferLen = (int)(sMicCurVariable.mEndPtr - sMicCurVariable.mReadBufPtr);
	if(audioRPtr <= audioWPtr)
	{
		return (audioWPtr - audioRPtr);
	}
	else
	{
		return (audioBufferLen - (audioRPtr - audioWPtr));
	}
}
/*
 * @method Audio_to_uart_start
 * @brief  read mic adc data for adc_dma_buf, and send  mic adc data by uart.
 * @retval None
 */
//short testPtr=NULL;
//void Audio_to_uart_start()
//{
//	uint8_t audioVal=0;
//	if (sMicCurVariable.mMicEnable == MIC_DISABLE)
//		return;
//	int audioWPtr = HREADW(CORE_ADCD_ADDR) ;
//	int bufferLen = Audio_get_buffer_len();
//		
//	if (bufferLen != 0 && bufferLen >= ENCODE_INPUT_LEN)
//	{
//		//Original sound sampling(pcm)
//		for(int indexL = 0; indexL < ENCODE_INPUT_LEN; indexL++)
//		{
//			 audioVal = *(sMicCurVariable.mReadPtr + indexL);
//				printfsend(&audioVal,1);
//			//MyPrintf("n:%d  v:%d\r\n",indexL,*(sMicCurVariable.mReadPtr + indexL));
//		}
//		sMicCurVariable.mReadPtr += ENCODE_INPUT_LEN;	
//		if (sMicCurVariable.mReadPtr == sMicCurVariable.mEndPtr)
//			sMicCurVariable.mReadPtr = sMicCurVariable.mReadBufPtr;
//	}

//}


/*
 * @method Audio_to_uart_start
 * @brief  read mic adc data for adc_dma_buf, and send  mic adc data by uart.
 * @retval None
 */
short * testPtr=NULL;
short Audio_Buffer[ENCODE_INPUT_LEN]={0};

//����Ϊ���ݣ���������
//����ֵΪ�ֱ�
#define VOLUMEMAX   32767
int SimpleCalculate_DB(short* pcmData, int sample)
{
    signed short ret = 0;
    if (sample > 0){
        long sum = 0;
        signed short* pos = (signed short *)pcmData;
        for (int i = 0; i < sample; i++){
            sum += abs(*pos);
            pos++;
        }
        ret = sum * 500.0 / (sample * VOLUMEMAX);
        if (ret >= 100){
            ret = 100;
        }
   }
   return ret;
}

//�����������RMS�� ������ֵ
static const float kMaxSquaredLevel = 32768 * 32768;
const float kMinLevel = 30.f;
int Process(const int16_t* data, size_t length) 
{
    float sum_square_ = 0;
    size_t sample_count_ = 0;
    for (size_t i = 0; i < length; ++i) {
        sum_square_ += data[i] * data[i];
    }
    sample_count_ += length;
    float rms = sum_square_ / (sample_count_ * kMaxSquaredLevel);
    //20log_10(x^0.5) = 10log_10(x)
    rms = 10 * log10(rms);
    if (rms < -kMinLevel)
        rms = -kMinLevel;
    rms = -rms;
    return (rms + 0.5);
}


static unsigned long long AudioSumVal=0;//
static unsigned int AudioCntIdx=0;
static unsigned char AudioDbVal=0;//�ֱ�ֵ
static  int AudioValMin=0;
static  int AudioValMax=0;

void Audio_to_uart_start()
{
//	char audioVal=0;
	 	short audioVal=0;
	  int indexL=0;
	  if (sMicCurVariable.mMicEnable == MIC_DISABLE)
		return;
	int audioWPtr = HREADW(CORE_ADCD_ADDR) ;
	int bufferLen = Audio_get_buffer_len();
		
	if (bufferLen != 0 && bufferLen >= ENCODE_INPUT_LEN)
	{

		//Original sound sampling(pcm)
		testPtr = (short *)sMicCurVariable.mReadPtr;
		for( indexL = 0; indexL < (ENCODE_INPUT_LEN>>1); indexL++)
		{
//			   audioVal = *(testPtr+ indexL)/100; //������ʾ������
//			   printfsend((uint8_t*)&audioVal,1);
			   
			   audioVal = *(testPtr+ indexL);
			   if(audioVal<AudioValMin)
				 {
				   AudioValMin = audioVal;
				 }
				 	if(audioVal>AudioValMax)
				 {
				   AudioValMax = audioVal;
				 }
				 
			  if(AudioCntIdx<ENCODE_INPUT_LEN*100)
				{
								AudioSumVal+=abs(*(testPtr+ indexL));
								AudioCntIdx++;
				}else
		    {
					    AudioDbVal = (int)(10.0*log10(AudioSumVal));  
						 AudioSumVal=0;
						AudioCntIdx=0;
						MyPrintf("sys:%d val:%ddb AudioValMax:%d AudioValMin:%d SumVal:%d\r\n",sys_time_handle.get_run_tickms(),AudioDbVal,AudioValMax,AudioValMin,AudioSumVal);//����ֱ�ֵ��ӡ
					// MyPrintf("val:%ddb \r\n",AudioDbVal); 
					  AudioValMin=0;AudioValMax=0;
				}

				//MyPrintf("%c",*(sMicCurVariable.mReadPtr + indexL));
			  //MyPrintf("%d\r\n",*(testPtr+ indexL)/10);
		}
		
	//	MyPrintf("val:%ddb\r\n",SimpleCalculate_DB(Audio_Buffer,ENCODE_INPUT_LEN));//����ֱ�ֵ��ӡ 
		sMicCurVariable.mReadPtr += ENCODE_INPUT_LEN;	
		if (sMicCurVariable.mReadPtr == sMicCurVariable.mEndPtr)
			sMicCurVariable.mReadPtr = sMicCurVariable.mReadBufPtr;
	}

}


void u_ble_data_send(uint8_t *send_data, uint8_t send_len) /*ʵ�ַ���ble���ݰ����ܺ���*/
{
  Bt_SndBleData(BLE_SEND_HANDLE,send_data,send_len);
}

uint32_t HW_Get_Native_Clk_Avoid_Race(void) //����ϵͳ����ʱ�������
{
     uint32_t native_clk=0;
     native_clk = sys_time_handle.get_run_tickms();
     return native_clk;
}
//ʵ�ֶ�flash�IJ��� api
void flash_erase_sector(uint32_t address)
{
    QSPI_SectorEraseFlash(address); 
}
void flash_read_data (uint8_t *buffer, uint32_t address, uint32_t len)
{
  QSPI_ReadFlashData(address,len,buffer);
}
void flash_write_data (uint8_t *buffer, uint32_t address, uint32_t len)
{
  QSPI_WriteFlashData(address,len,buffer);
}