///Copyright (c) 2022, 四川汇源光通信有限公司 
///All rights reserved. 
///@file        tmp75.C 
///@brief       tmp75驱动程序
///
///@details     
///@note        
///@author      lqc
///@date        2022/05/23 
///
///@version		v1.0 2022/05/23 初始版本

#include "tmp75.h"

/*
  @ brief  延时函数
  @ param  
  @ return
  @ note   2022-5-23
*/
static void delay_us(int us)
{
  for(int i = 0; i < us; i++ )
  {
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
  }  
}

/*
  @ brief  初始化tmp75芯片GPIO引脚
  @ param
  @ return
  @ note  2022-5-23 lqc
*/
void temp75_gpio_init()
{
  //配置引脚时钟
  rcu_periph_clock_enable(RCU_GPIOB);
  //设置引脚为输出模式:PB6
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
  
  //设置引脚PB7输出模式
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
  
  TMP75_SCL_HIGH;
  TMP75_SDA_HIGH;
}

/*
  @ brief  设置SDA引脚为输出模式
  @ param  
  @ return 
  @ note  2022-5-25 lqc
*/
static void tmp75_sda_output()
{
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
}

/*
  @ brief  设置SDA引脚为输入模式
  @ param  
  @ return 
  @ note   2022-5-25 lqc
*/
static void tmp75_sda_input()
{
  gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
//  gpio_output_options_set(GPIOB, GPIO_PUPD_NONE, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
}

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

/* 
  @ brief  I2C stop信号
  @ param
  @ return
  @ note  2022-05-25
*/
static void i2c_stop()
{
  TMP75_SDA_LOW;
  TMP75_SCL_HIGH;
  TMP75_SDA_HIGH;  
}

/*
  @ brief  写一个字节数据
  @ param 
  @ return 
  @ note   2022-05-25
*/
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
*/
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   2022-05-25
*/
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   2022-05-25
*/
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   2022-05-26
*/
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  2022-05-25
*/
float tmp75_read_temp(void)
{
  uint8_t tempH = 0;
  uint8_t tempL = 0;
  uint16_t tempCode = 0;
  float temp = 0;
  
  //起始信号
  i2c_start();
  //写tmp75地址
  tmp75_write_byte(TMP75_ADDRESS);
  //接收tmp75的ack信息
  tmp75_ack();
  //发送需读取数据的地址
  tmp75_write_byte(TEMP_REGISTER_ADDRESS);
  tmp75_ack();
  
  i2c_start();
  //写tmp75地址
  tmp75_write_byte(TMP75_ADDRESS + 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);
}


