/**
******************************************************************************************************************************************************************************************
*@file                       user_mic_gpadc.c
*@author         
*@data                       
*@version                    v1.0
*@par Copyright(c):
*
*@par History:
*     version:author,date,desc
*     v1.0   :create this file
*
*******************************************************************************************************************************************************************************************
*/
#include "cpu.h"
#include "user_mic_gpadc.h"
#include "cpu_gpio.h"
#include "app_main.h"
#include "att_uuid.h"
#include "app.h"
#include "cpu_deepsleep.h"
#include "cpu_gpadc.h"
#include "app_config.h"

#if (USE_ADPCOM)
#define MAX_MTU      160
#define BUFF_LEN     1600
#else
#define MAX_MTU      100
#define BUFF_LEN     5000
#endif

typedef struct 
{
    uint8_t  data[BUFF_LEN];
    volatile uint16_t tx_save_pos;
    volatile uint16_t tx_send_pos;
}tx_buf_t;

typedef struct
{
    tx_buf_t        tx_buf;
    mic_adc_state_t state;
    volatile uint8_t         tx_credit;
}user_mic_env_t;

NO_REATION_RAM(user_mic_env_t mic_env);
void remout_control_adc_cbk(void);
void mic_state_set(mic_adc_state_t state)
{
    dbg_printf("set state=0x%x\r\n",state);
    mic_env.state = state;
    if(state == STATE_OPEN)
    {
        /* enable interrupt */
        user_mic_gpadc_cmd(ENABLE);
        
        
    }
    else
    {
        /* enable interrupt */
        user_mic_gpadc_cmd(DISABLE);
        
    }
}
 



void mic_tx_view(void)
{
    dbg_printf("tx_num=%d\r\n",tx_num);
}
void  gpadc_mic_init()
{

    memset(&mic_env, 0, sizeof(user_mic_env_t));
    mic_env.tx_credit = 5;

    /* initialise GPADC */
	user_mic_gpadc_init();
	gpadc_gpio ();

}

void user_mic_gpadc_init()
{
	gpadc_init_type_def gpadc_init_structure;
	/* open the gpadc door control */
	memset(&gpadc_init_structure, 0, sizeof(gpadc_init_structure));
	crm_cmd_periphclock(CRM_PeriphClock_QPADC,ENABLE);
	crm_reset_periph(CRM_PeriphReset_GPADC);
		
	/* analog register configuration */
	gpadc_init_structure.gapdc_ch_sel = GPADC_CH_GPIO;
	gpadc_init_structure.gpadc_in_mode = GPADC_SINGLE_IN;
	gpadc_init_structure.gpadc_gain = GPADC_Gain_1;
	gpadc_init_structure.gpadc_vcm_sel = GPADC_VCM_050;
	gpadc_init_structure.gpadc_sel1 = GPIOA_Pin0;
	gpadc_init_structure.gpadc_sel2 = GPIOA_Pin0;
	/* configure sampling rate */
	gpadc_init_structure.gpadc_sample_rate = GPADC_SAMPLERATE_8k;
	/* Multiple conversion */
	gpadc_init_structure.gpadc_write_in_mode = GPADC_MODE_CONTINU;
	/* FIFO threshold */
	gpadc_init_structure.gpadc_fifo_threshold = 8;
	gpadc_init_structure.gpadc_en = GPADC_OPEN;
	gpadc_init(&gpadc_init_structure);
	
	adc_register_handler(remout_control_adc_cbk);
	//WRITE_REG_FIELD_RANGE(*(uint32_t *)0x4000022C, 6, 7, 1);

}

void gpadc_gpio (void)
{
            
    /* gpadc reuse gpio  */
    gpio_init(GPIOA_Pin0, GPIO_Mode_Input);
    gpio_remap_config(GPIOA_Pin0, GPIO_Remap_ADC);
        
    /* P0.1(GPIOA.1) Control mic card upper and lower power*/
    gpio_remap_config(GPIOA_Pin0, GPIO_Remap_GPIO); 
    gpio_init(GPIOA_Pin1, GPIO_Mode_Output);
    gpio_reset(GPIOA_Pin1);
    
}

void gpadc_ctrl_upper_lower(functional_state_t new_state)
{
    if (new_state != ENABLE)
    {
        gpio_set(GPIOA_Pin1);
    }
    else
    {
        gpio_reset(GPIOA_Pin1);
    }
}

void user_mic_gpadc_cmd(functional_state_t new_state)
{
   gpadc_cmd(new_state);
		
	if (new_state != ENABLE)
	{
		/* NVIC disable interrupt */
		NVIC_DisableIRQ(GPADC_IRQn);
		gpadc_it_config(GPADC_IT_ALERT_EN,DISABLE);
	}
	else
	{
		/* NVIC enable interrupt */
		NVIC_EnableIRQ(GPADC_IRQn);
		gpadc_it_config(GPADC_IT_ALERT_EN,ENABLE);
	}

}

bool mic_adc_is_working(void)
{
    return mic_env.state;
}

/* GPADC interrupt operation function */
void remout_control_adc_cbk(void)
{
#if (USE_ADPCOM)
    int16_t *buf = (int16_t *)(mic_env.tx_buf.data+ mic_env.tx_buf.tx_save_pos);
#else
uint16_t *buf = (uint16_t *)(mic_env.tx_buf.data+ mic_env.tx_buf.tx_save_pos);
#endif
	uint32_t fifo_level = gpadc_receive_fifo_level();
//	uint16_t tmp;	
#if (USE_ADPCOM)
     if (fifo_level >= 8)
    {
        buf[0] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[1] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[2] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[3] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[4] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[5] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[6] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        buf[7] = (short)((int)(GPADC->GPADC_FIFODATA << 6) - 32768);
        /* the data is increased by 10 bytes,indicating the next array */
		mic_env.tx_buf.tx_save_pos += 16;

        mic_env.tx_buf.tx_save_pos = mic_env.tx_buf.tx_save_pos%(BUFF_LEN);
    }
#else
struct {
		int16_t b1:10;
		int16_t b26:6;
		
		int16_t b24:4;
		int16_t b3:10;
		int16_t b42:2;
	
		int16_t b48:8;
		int16_t b58:8;

		int16_t b52:2;
		int16_t b6:10;
		int16_t b74:4;

		int16_t b76:6;
		int16_t b8:10;
	} *adc_buf = (void *)buf;
	
	if (fifo_level >= 8)
	{
		/* read 8 timers */
		adc_buf->b1 = gpadc_receive_fifo_data();

		tmp = gpadc_receive_fifo_data();
		adc_buf->b26 = tmp;
		adc_buf->b24 = tmp >> 6;

		adc_buf->b3 = gpadc_receive_fifo_data();
	
		tmp = gpadc_receive_fifo_data();
		adc_buf->b42 = tmp;
		adc_buf->b48 = tmp >> 2;

		tmp = gpadc_receive_fifo_data();
		adc_buf->b58 = tmp;
		adc_buf->b52 = tmp >> 8;

		adc_buf->b6 = gpadc_receive_fifo_data();
	
		tmp = gpadc_receive_fifo_data();
		adc_buf->b74 = tmp;
		adc_buf->b76 = tmp >> 4;
		
		adc_buf->b8 = gpadc_receive_fifo_data();
		
		/* the data is increased by 10 bytes,indicating the next array */
		mic_env.tx_buf.tx_save_pos += 10;

        mic_env.tx_buf.tx_save_pos = mic_env.tx_buf.tx_save_pos%(BUFF_LEN);

	}
#endif
}
