/*************************************************
Copyright (c) 2025, 成都赛联科技有限责任公司
All rights reserved.
@file        tmp75.C
@brief       tmp75驱动程序

@details
@note
@author      dufresne
@date        2025/09/15

@version		v1.0 2025/09/15 初始版本
*************************************************/

#include "tmp75.h"

/*
  @ brief  设置SDA引脚为输出模式
  @ param
  @ return
  @ note  2025-09-15 
*/
static void tmp75_sda_output()
{
	gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I2C_SDA_PIN);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
}

/*
  @ brief  设置SDA引脚为输入模式
  @ param
  @ return
  @ note  2025-09-15 
*/
static void tmp75_sda_input()
{
	gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, I2C_SDA_PIN);
}

/*
  @ brief  I2C start信号
  @ param
  @ return
  @ note  2025-09-15 
*/
static void i2c_start()
{
  TMP75_SDA_HIGH;
  TMP75_SCL_HIGH;
  TMP75_SDA_LOW;
  delay_us(40);
}

/*
  @ brief  I2C stop信号
  @ param
  @ return
  @ note  2025-09-15 
*/
static void i2c_stop()
{
  TMP75_SDA_LOW;
  TMP75_SCL_HIGH;
  TMP75_SDA_HIGH;
}

/*
  @ brief  写一个字节数据
  @ param
  @ return
  @ note  2025-09-15 
*/
static void tmp75_write_byte(uint8_t byte)
{
  for (int i = 0; i < 8; i++)
  {
    TMP75_SCL_LOW;
    delay_us(4);
    if (byte & 0x80)
    {
      TMP75_SDA_HIGH;
    }
    else
    {
      TMP75_SDA_LOW;
    }
    byte <<= 1;
    TMP75_SCL_HIGH;
    delay_us(40);
  }
  TMP75_SCL_LOW;
}

/*
  @ brief  写入数据后，CPU接收TMP75返回的ACK信号
  @ param
  @ return
  @ note  2025-09-15 
*/
static void tmp75_ack()
{
  int i = 0;
  // 将sda设置为输入模式
  tmp75_sda_input();
  TMP75_SCL_HIGH;
  while ((TMP75_SDA_GET) && (i < 1000))
  {
    i++;
  }
  TMP75_SCL_LOW;
  // 将sda设置为输出模式
  tmp75_sda_output();
}

/*
  @ brief  读取数据
  @ param
  @ return  value:读取到的单字节数据
  @ note    2025-09-15 
*/
static uint8_t tmp75_read_byte()
{
  uint8_t value = 0;
  tmp75_sda_input();
  TMP75_SCL_LOW;

  for (int i = 0; i < 8; i++)
  {
    TMP75_SCL_HIGH;
    value <<= 1;
    delay_us(10);
    if (TMP75_SDA_GET)
    {
      value = value | 0x01;
    }
    TMP75_SCL_LOW;
    delay_us(10);
  }
  tmp75_sda_output();
  return value;
}

/*
  @ brief   读取数据，主机发送ack信号
  @ param
  @ return
  @ note  2025-09-15 
*/
static void master_ack()
{
  TMP75_SDA_LOW;
  delay_us(5);
  TMP75_SCL_HIGH;
  delay_us(5);
  TMP75_SCL_LOW;
  delay_us(5);
}

/*
  @ brief 读取数据完成，主机发送noack信号
  @ param
  @ return
  @ note  2025-09-15 
*/
static void master_noack()
{
  TMP75_SDA_HIGH;
  delay_us(5);
  TMP75_SCL_HIGH;
  delay_us(5);
  TMP75_SCL_LOW;
  delay_us(5);
}

/*
  @ brief  读取温度值
  @ param
  @ return
  @ note  2025-09-15 
*/
float tmp75_read_temp(void)
{
  static uint8_t tempH = 0;
  static uint8_t tempL = 0;
  static uint16_t tempCode = 0;
  static float temp = 0;

  // 起始信号
  i2c_start();
  // 写tmp75地址
  tmp75_write_byte(TMP75_ADDRESS << 1);//写 数据 设置
  // 接收tmp75的ack信息
  tmp75_ack();
  // 发送需读取数据的地址
  tmp75_write_byte(TEMP_REGISTER_ADDRESS);// 写地址 0x00
  tmp75_ack();

  i2c_start();
  // 写tmp75地址
  tmp75_write_byte((TMP75_ADDRESS << 1) + 1); // 读 数据 设置
  tmp75_ack();
  tempH = tmp75_read_byte();
  master_ack();
  tempL = tmp75_read_byte();
  master_noack();
  i2c_stop();

  tempCode = (tempH << 8) | tempL;
  tempCode = tempCode >> 6;
  if (tempCode & 0x200) // 负温度
  {
    tempCode &= 0x1ff;
    temp = ((float)tempCode - 512) / 4;
  }
  else
  {
    temp = (float)tempCode / 4;
  }
  TMP75_SDA_LOW;
  TMP75_SCL_LOW;
  return (temp);
}
