/*
 * Copyright (c) 2022 OpenLuat & AirM2M
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "user.h"

#define	SHT30_ADDR	  		(0x44)					//7位地址0x44

#define noACK 0                                 //用于判断是否结束通讯
#define ACK   1                                 //结束数据传输

//命令
#define SHT30_SINGLE_H_MEASURE_EN					0x2C06
#define SHT30_SINGLE_M_MEASURE_EN					0x2C0D
#define SHT30_SINGLE_L_MEASURE_EN					0x2C10
#define SHT30_SINGLE_H_MEASURE_DIS				0x2400
#define SHT30_SINGLE_M_MEASURE_DIS				0x240B
#define SHT30_SINGLE_L_MEASURE_DIS				0x2416

#define SHT30_PERIODOC_H_MEASURE_500MS		0x2032
#define SHT30_PERIODOC_M_MEASURE_500MS		0x2024
#define SHT30_PERIODOC_L_MEASURE_500MS		0x202F
#define SHT30_PERIODOC_H_MEASURE_1S				0x2130
#define SHT30_PERIODOC_M_MEASURE_1S				0x2126
#define SHT30_PERIODOC_L_MEASURE_1S				0x212D
#define SHT30_PERIODOC_H_MEASURE_2S				0x2236
#define SHT30_PERIODOC_M_MEASURE_2S				0x2220
#define SHT30_PERIODOC_L_MEASURE_2S				0x222B
#define SHT30_PERIODOC_H_MEASURE_4S				0x2334
#define SHT30_PERIODOC_M_MEASURE_4S				0x2322
#define SHT30_PERIODOC_L_MEASURE_4S				0x2329
#define SHT30_PERIODOC_H_MEASURE_10S			0x2737
#define SHT30_PERIODOC_M_MEASURE_10S			0x2721
#define SHT30_PERIODOC_L_MEASURE_10S			0x272A

#define SHT30_PERIODOC_MEASURE_READ			0xE000			//重复测量读取数据

#define	SHT30_SOFT_RESET									0x30A2			//软复位

#define SHT30_HEATER_EN										0x306D			//加热使能
#define SHT30_HEATER_DIS									0x3066			//加热关闭

#define SHT30_READ_STATUS									0xF32D			//读状态寄存器
#define SHT30_CLEAR_STATUS								0x3041			//清状态寄存器

// CRC
#define POLYNOMIAL  0x31 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001

void SHT30_Init(CBFuncEx_t CB, void *pParam)
{
	uint8_t Reg[2];
	uint8_t I2CID = I2C_ID0;
	GPIO_Iomux(GPIOE_06, 2);
	GPIO_Iomux(GPIOE_07, 2);
	I2C_MasterSetup(I2CID, 400000);
	BytesPutBe16(Reg, SHT30_SINGLE_M_MEASURE_EN);
	I2C_BlockWrite(I2CID, SHT30_ADDR, Reg, 2, 100, CB, pParam);
}

void SHT30_GetResult(CBFuncEx_t CB, void *pParam)
{
	uint8_t Reg[2];
	uint8_t Data[9];
	uint8_t I2CID = I2C_ID0;
	uint16_t T,H;
	uint8_t vTemSymbol, crc8;
	int32_t vTem, vHum;
	float vTemp = 0.00;

	Reg[0] = 0;
	if (!I2C_BlockRead(I2CID, SHT30_ADDR, Reg, Data, 6, 100, CB, pParam))
	{
		T = BytesGetBe16(Data);
		H = BytesGetBe16(Data + 3);
		crc8 = CRC8Cal(Data, 2, 0xff, POLYNOMIAL, 0);
		if (crc8 != Data[2])
		{
			DBG("t data check error %x %x", crc8, Data[2]);
			goto CHECK_NEXT;
		}
		crc8 = CRC8Cal(Data + 3, 2, 0xff, POLYNOMIAL, 0);
		if (crc8 != Data[5])
		{
			DBG("h data check error %x %x", crc8, Data[5]);
			goto CHECK_NEXT;
		}
		vTemp = 175.0*T/(65536-1);
		if (vTemp >= 45)
		{
			vTem = (vTemp - 45.0)*10.0;
		}
		else
		{
			vTem = (45.0 - vTemp)*10.0;
			vTem = -vTem;
		}
		vTemp = 100.0*H/(65536.0-1.0);
		vHum = (vTemp*10);
		DBG("温度 %d, 湿度 %d",vTem, vHum);
	}
	else
	{
		DBG("i2c fail!");
	}
CHECK_NEXT:
	BytesPutBe16(Reg, SHT30_SINGLE_M_MEASURE_EN);
	I2C_BlockWrite(I2CID, SHT30_ADDR, Reg, 2, 100, CB, pParam);
}
