/*************************** (C) COPYRIGHT 2017 Vcare ***************************
 * File Name          : main.c
 * Author             : hu
 * Version            : v1.0
 * Date               : 2019-03-18
 * Description        : VC31 demo file
 *
 * HISTORY:
 * Date        | Modification                                	| Author
 * 18/03/2019  | Initial Revision                            	| hu
 *
 ********************************************************************************
 * THIS FILE IS ONLY AN EXAMPLE OF HOW TO USE DRIVER AND ALGORITHM OF VC31.
 * IT IS NOT EXECUTABLE CODE.
 * USERS SHOULD CODING EXECUTABLE FILE YOURSELF BASED ON THE DOMMENTS IN THIS FILE.
 *******************************************************************************/

#include "VC31Hci.h"    //Head file of VC31 Driver
#include "algo.h"       //Head file of VC31 Algorithm

#define HR_MODE         CONTINUOUS_MEASURE

accRaw_t            axes;
VC31_t              VC31;
AlgoInputData_t		algoInputData;
AlgoOutputData_t	algoOutputData;


bool VC31IRQFlag = false;
uint16_t            VC31SampleRate = 10;
uint32_t    		mcuOscData = 32768;
uint16_t            SwitchFlag = 0;//0-default，1-Static to Dynamic,2-Dynamic to Static.

extern int16_t VC31HeartRateValue;

void VC31PhyInit(void);

uint16_t ppgData[VC31SampleRate];
uint16_t envData[VC31SampleRate];
int16_t xData[VC31SampleRate];
int16_t yData[VC31SampleRate];
int16_t zData[VC31SampleRate];
int16_t timerData[11];// = VC31SampleRate + 1


void main()
{
    static uint8_t VC31SampleCnt = 0;
    int heartRate = 0;
    
/***************************************************************************//**
* Initial necessarily hardware and software, including VC31 and Accelerometer.
******************************************************************************/
    
/*-----------INSERT BOARD HARDWARE AND SOFTWARE INITIAL FUNCTION------------*/
    accInit();          //Accelerometer initial
	VC31PhyInit();      //VC31 board initial
	VC31Init(&VC31,VC31Mode_NormalWork);    //VC31 chip initial
	Algo_Init();        //VC31 algorithm initial
    
#if (HR_MODE == CONTINUOUS_MEASURE)
  //If continuous heart rate monitor is needed, insert VC31StartSample() here.
    VC31StartSample(&VC31);
#endif

/***************************************************************************//**
* Every sample period, the MCU need to read data from VC31,
* and send simulataneously accelerometer data to algorithm.
* MCU can use GPIO interrupt with Pin INT of VC31 (recommended),
* or use MCU timer to read data.
******************************************************************************/

/***************************************************************************//**
* ATTENTION: 
* The accelerometer direction:
*                          X         --------|
*                          ^        /        |
*                          |       /         |
*           |--------------|------/          |
*           | ARM    Y<----.Z         HAND   |
*           |---------------------\          |
*                                  \         |
*                                   \        |
*                                    --------|
* If the accelerometer direction is not the same,
* send accelerometer data as this required order.
*
* Accelerometer range is +/- 8G, and resolution is 4mg/LSB.
*
* Users should read current accelerometer data rather than using FIFO of it,
* because simulataneously accelerometer data is required of algorithm.
* 
* When other algorithm also need accelerometer data, and required another
* required smaple rate with VC31, users should set a least common multiple
* number of these rates as sample rate, and downsample accelerometer data as
* necessery. Meanwhile, make sure accelerometer data is synchronous with VC31.
* For example, VC31 needs 10Hz accelerometer data, while step calculation
* algorithm needs 50Hz. Users can set sample rate of accelerometer as 50Hz, and
* take one data every five sample data as input of VC31.
******************************************************************************/
    
    while(1)
    {
        
        if (VC31IRQFlag)
        {
            VC31IRQFlag = false;
			
                if(!VC31OscCheck(mcuOscData,&VC31,VC31SampleRate))
                {
                    return;
                }

                //timerData[VC31SampleRate] = VC31GetTimeIntervalFromInterval();
                //if（timerData[VC31SampleRate] < 15）
                //{
                //    return;
                //}
                if(VC31Ret_unWearToIsWear == VC31GetSampleValues(&VC31))
                {
                    Algo_Init();
                    VC31SampleCnt = 0;
                }
				getAxesData(&axes);
                if (VC31.wearStatus == wearST_isWear)
                {
                    
                    ppgData[VC31SampleCnt] = VC31.sampleData.ppgValue;
                    envData[VC31SampleCnt] = VC31.sampleData.envValue;
                    xData[VC31SampleCnt] = axes.x>>5;
                    yData[VC31SampleCnt] = axes.y>>5;
                    zData[VC31SampleCnt] = axes.z>>5;
                    //timerData[VC31SampleCnt] = timerData[VC31SampleRate];
                    
                    //Algo_Input(&AlgoInputData_t,100);
                    //Use Algo_Output every fs(10) sample period to get heart rate.
                    if (++VC31SampleCnt >= VC31SampleRate)
                    {
                        for(uint8_t i = 0; i < VC31SampleRate; i++)
                        {
                            algoInputData.ppgSample = ppgData[i];
                            algoInputData.envSample = envData[i];
                            algoInputData.axes.x = xData[i];//The direction vertical with ARM.
                            algoInputData.axes.y = yData[i];//The direction parallel with ARM.
                            algoInputData.axes.z = zData[i];//The direction upside.
                            
                            Algo_Input(&algoInputData,100);//timerData[i]);
                        }
                        VC31SampleCnt = 0;
                        Algo_Output(&algoOutputData);
                        VC31HeartRateValue = algoOutputData.hrData;
                    	if(VC31HeartRateValue == -1)
						{
							Algo_Init();
						}	
					}
                }
                else
                {
                    VC31SampleCnt = 0;
					green_led_off_state_gsensor_abs_sum_diff_func(axes.x, axes.y, axes.z); 

                	VC31HeartRateValue = -2;  //Wrist band is not wear.

                }                
			
        }
    }
}

#if (HR_MODE == DISCONTINUOUS_MEASURE)
//If discontinuous heart rate monioter is needed, insert VC31StartSample()
//when it is needed, and insert VC31StopSample() at property place.
//The following example is starting heart rate measure triggered by button,
//and stop heart rate measure after 1 minute.
void buttonInterruptHandle(event)
{
  if(event == buttonPress)
  {
    setTimerOnce(60);
    VC31StartSample(&VC31);
  }
}

void timerTrigger()
{
  VC31StopSample(&VC31);
}
#endif


void NormalWork()
{
    VC31StopSample(&VC31);
    VC31Init(&VC31,VC31Mode_NormalWork);
    Algo_Init();   
    VC31StartSample(&VC31);
//    SwitchFlag = 0;
}

void CrossTalkTest()
{
    VC31StopSample(&VC31);
    VC31Init(&VC31,VC31Mode_CrossTalkTest);
    VC31StartSample(&VC31);
//    SwitchFlag = 0;
}

void VC31IRQHandler()
{
    GPIO_IntClear(1 << VC31_INT_PIN);
    VC31IRQFlag = true;
    GPIO_IntEnable(1 << VC31_INT_PIN);
}

void VC31PhyInit(void)
{
/***************************************************************************//**
* If Reset Pin of VC31 is connected to MCU, Initial it;
* If I2C and SPI is selected by software (Mode Pin is connected), Initial it
*       according to which interface is used (0 for SPI and 1 for I2C);
*       otherwise, ignore that;
* If I2C is selected, and I2C address is controlled by MCU, Initial these two
*       pins; otherwise, ignore that;
* If interrupt is enabled, Initial interrupt pin, configurate interrupt pin,
        interrupt edge;
* If interrupt is enabled, clear IRQ, set priority and enable interrupt;
* Initial communication interface selected.
******************************************************************************/

/*------------------INSERT YOUR CODE HERE-----------------*/

}

/***************************************************************************//**
* @brief
*   Write Registers to VC31. This function needs to be implemented
*   according to the MCU.
* @param
*       startAddress    VC31 register address
*       *pRegisters     pointer of register storing data write to VC31
*       len             register length needing to be writen
* @retval
*       VC31Ret_t       VC31 return status
******************************************************************************/
VC31Ret_t VC31WriteRegisters(uint8_t startAddress, uint8_t *pRegisters, uint8_t len)
{
/***************************************************************************//**
* When SPI is used, write WRITE command to VC31 FIRSTLY,
* then write len byte data to register(s) start from startAddress
* to register(s) pointed by pRegisters.
*
* When I2C is used, write Slave Address and write flag to VC31 firstly,
* then write len byte data to register(s) start from startAddress
* to register(s) pointed by pRegisters.
******************************************************************************/


/*------------------INSERT YOUR CODE HERE-----------------*/

	return VC31Ret_isOK;
}

/***************************************************************************//**
* @brief
*   Read Registers from VC31. This function needs to be implemented
*   according to the MCU.
* @param
*       startAddress    VC31 register address
*       *pRegisters     pointer of register storing data read from VC31
*       len             register length needing to be read
* @retval
*       VC31Ret_t     VC31 return status
******************************************************************************/
VC31Ret_t VC31ReadRegisters(uint8_t startAddress, uint8_t *pRegisters, uint8_t len)
{
/***************************************************************************//**
* When SPI is used, write READ command to VC31 FIRSTLY,
* then read len byte data from register(s) start from startAddress
* to register(s) pointed by pRegisters.
*
* When I2C is used, write Slave Address and read flag to VC31 firstly,
* then read len byte data from register(s) start from startAddress
* to register(s) pointed by pRegisters.
******************************************************************************/


/*------------------INSERT YOUR CODE HERE-----------------*/

	return VC31Ret_isOK;
}

static uint32_t timeVec[2] = {0,0};
uint32_t VC31GetTimeIntervalFromMCU(void)
{
/***************************************************************************//**
* Get the time difference between two interrupts.
******************************************************************************/

/*------------------INSERT YOUR CODE HERE-----------------*/
/*------------------THE CODE FOR 51822-----------------*/
		uint32_t timeDiff;
		timeVec[1] = timeVec[0];
		timeVec[0] = app_timer_cnt_get();
		//app_timer_cnt_diff_compute(timeVec[0], timeVec[1], &timeDiff);
        timeDiff = ((timeVec[0] - timeVec[1])& 0x00FFFFFF);
		return timeDiff;

}

static uint32_t time_interval[2] = {0,0};
uint32_t VC31GetTimeIntervalFromInterval(void)
{
/***************************************************************************//**
* Get the time difference between two interrupts.
******************************************************************************/

/*------------------INSERT YOUR CODE HERE-----------------*/
/*------------------THE CODE FOR 51822-----------------*/
/*      uint32_t timeDiff;
        time_interval[1] = time_interval[0];
        time_interval[0] = app_timer_cnt_get();
        //app_timer_cnt_diff_compute(time_interval[0], time_interval[1], &timeDiff);
        timeDiff = ((timeVec[0] - timeVec[1])& 0x00FFFFFF);
        timeDiff = timeDiff*1000/mcuOscData;
        return timeDiff;
*/
}

