/////////////////////////////////////////////////////////////////
//
// ������ֻ��ѧϰʹ�ã�δ���������ɣ��������������κ���;
// STM32F103C8T6����	   
// by Pang
// �޸�����:2019/01/02
// �汾��V1.0
// ��Ȩ���У�����ؾ���
// All rights reserved
// ģ����߷�ʽ��PB10-I2C_SCL��PB11-I2C_SDA��PA4-nWAK
//
////////////////////////////////////////////////////////////////
#include "CCS811.h"
u8 CCS_BUF[12];
u8 Information[10];
u8 MeasureMode, Status, Error_ID;
u8 FlagGetId = 1;
u8 n         = 4;                                        // 3�ζ�ȡID������˵��û����
u8 CCS_temp      = 0x5a;
ccs811_measurement_t CCS;

#define STEP_DELAY 100

void CCS811_GPIO_Config()
{

	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //���˿�ʱ��

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;					 		 // CCS811-CS
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	     //�������
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	CCS811_CS_OFF();

	CCS811_I2C_GPIO_Config(); 													   //IIC GPIO Configure
}

void CCS811Init()
{
	u8 idCount = 0;               // count the correct times of id.
	CCS811_CS_ON(); 					   	//nWAKE pin is asserted at least 50��s before the transaction and kept asserted throughout,nWAKE pin is active low
	delay_ms(STEP_DELAY);
	// get CCS811 device id,when addr pin connect to GND and the id is 0x81(129)
	while( FlagGetId)
	{
		CCS811_ReadI2C(CCS811_Add, 0x20, Information, 1); //Read CCS's information  ,ID
		if(Information[0] == 0x81)
		{
			if(++idCount == n)
			{
				FlagGetId = 0;
			}
			else
			{
				//printf("id=%d,correct %d!\r\n", Information[0], idCount);
			}
		}
		else
		{
//printf("id=%d,incorrect,continuing...\r\n", Information[0]);
		}
		delay_ms(STEP_DELAY);
	}
//printf("id correct,initing...\r\n");
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0x23, &Information[1], 2);	  //FW_Boot_Version
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0x24, &Information[3], 2); 	//FW_App_Version
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0x00, &Status, 1);	          //Firstly the status register is read and the APP_VALID flag is checked.
	delay_ms(STEP_DELAY);
	// if there is valid application firmware loaded
	if(Status & 0x10)
	{

		while(!(Status & 0x80)) // if firmware not in application mode but boot mode.
		{
			CCS811_WriteI2C_byte(CCS811_Add, 0xF3, 0xF0);	      // Application Verify
		//	printf("trying to transition the CCS811 state from boot to application mode...\r\n");
			CCS811_MWriteI2C_byte(CCS811_Add, 0xF4, &CCS_temp, 0);	//Used to transition the CCS811 state from boot to application mode, a write with no data is required.
			delay_ms(STEP_DELAY);
			CCS811_ReadI2C(CCS811_Add, 0x00, &Status, 1);
			delay_ms(STEP_DELAY);

		}
		//printf("CCS811 is already in application mode!\r\n");
	}
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0x01, &MeasureMode, 1);
	delay_ms(STEP_DELAY);
	MeasureMode &= 0x70;                                       // get measure mode
	//if measure mode incorrect,and reset the measure mode.
	while(MeasureMode != DRIVE_MODE_1SEC)
	{
		CCS811_WriteI2C_byte(CCS811_Add, 0x01, DRIVE_MODE_1SEC); // Write Measure Mode Register,sensor measurement every second,no interrupt
		delay_ms(STEP_DELAY);
		CCS811_ReadI2C(CCS811_Add, 0x01, &MeasureMode, 1);
		MeasureMode &= 0x70;
	//	printf("trying to enter measure mode...\r\n");
		delay_ms(STEP_DELAY);
	}
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0x00, &Status, 1);
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0x01, &MeasureMode, 1);
	delay_ms(STEP_DELAY);
	CCS811_CS_OFF();
	delay_ms(STEP_DELAY);
	CCS811_ReadI2C(CCS811_Add, 0xE0, &Error_ID, 1);
	//printf("status=%d error_id=%d measureMode=%d \r\n", Status, Error_ID, MeasureMode);

}

void CCS811GetData()
{
	CCS811_CS_ON(); 	// nWAKE pin is asserted at least 50��s before the transaction and kept asserted throughout,nWAKE pin is active low
	delay_ms(10);
	CCS811_ReadI2C(CCS811_Add, 0x02, CCS_BUF, 8);
	delay_ms(10);
	CCS811_ReadI2C(CCS811_Add, 0x20, Information, 1); // Read CCS's information  ,ID
	delay_ms(10);
	CCS811_ReadI2C(CCS811_Add, 0xE0, &Error_ID, 1);
	CCS811_CS_OFF();
	CCS.eco2 = (u16)CCS_BUF[0] * 256 + CCS_BUF[1];
	CCS.tvoc = (u16)CCS_BUF[2] * 256 + CCS_BUF[3];
	CCS.device_id  = Information[0];
	CCS.error_id   = Error_ID;
	Error_ID       = 0;
	Information[0] = 0;
}

void CCS811ClearData()
{
	CCS.device_id = 0;
	CCS.eco2      = 0;
	CCS.status    = 0;
	CCS.tvoc      = 0;
	CCS.error_id  = 0;

}