#include "ds18b20.h"
extern TIM_HandleTypeDef htim17;
uint8_t flag,sign;
volatile float temperature;
uint8_t DS18B20Reset(void)
{
	//Pull Output line low and wait for 480uS
  output();//Output low for 480us   
  CONFIG_OUTPUT;//Configure as Output
	_delay_us(480);
	//Release line and wait for 60uS
  input(); //Configure as Input   
	_delay_us(60);
	//Store line value and wait until the completion of 480uS period
	uint8_t i;
	i=(READ_INPUT);
	_delay_us(420);
	return i;
	//Return the value read from the presence pulse (0=OK, 1=WRONG)
}
/*
For Write LSB first
----------------------------------------------------------
   | 8th | 7th | 6th | 5th | 4th | 3th | 2nd | 1st |
----------------------------------------------------------
*/
void DS18B20Write(uint8_t byte)
{
	for(uint8_t i=0;i<8;i++)
	{
	  //Pull line low for 2uS   
    output();  //Configure as Output  
    CONFIG_OUTPUT;//Output low 
		_delay_us(2);
		//If we want to write 1, release the line (if not will keep low)
		if(byte & 0x01)
    input(); //Configure as Input
		_delay_us(60);  
    input(); //Configure as Input
		_delay_us(1);
		byte=byte>>1;
	}
}
/*
For Read MSB first
----------------------------------------------------------
   | 1st | 2nd | 3rd | 4th | 5th | 6th | 7th | 8st |
----------------------------------------------------------
*/
uint8_t DS18B20Read()
{
	uint8_t byte=0x00;
	for(uint8_t i=0;i<8;i++)
	{
	  byte=byte>>1;
		//Pull line low for 1uS  
    output(); //Configure as Output
    CONFIG_OUTPUT; //Output low for 2us
		_delay_us(2);
		//Release line and wait for 14uS
    input();
		_delay_us(14); //Configure as Input
		if(READ_INPUT)
		byte|=0x80;
		_delay_us(45);
	}
	return byte;
}

uint8_t DS18B20ReadTemp()
{
  uint8_t ds18b20_scratchpad[8];
	uint8_t digit;
  uint8_t decimal;
	flag=DS18B20Reset();
	DS18B20Write(DS18B20_CMD_SKIPROM);
	DS18B20Write(DS18B20_CMD_CONVERTTEMP);
	//Wait until conversion is complete 0 complete 1 processing
	while(!DS18B20Read());
	flag=DS18B20Reset();
	DS18B20Write(DS18B20_CMD_SKIPROM);
	DS18B20Write(DS18B20_CMD_RSCRATCHPAD);
	for(uint8_t i=0;i<8;i++)
	ds18b20_scratchpad[i]=DS18B20Read();
	sign=ds18b20_scratchpad[1]&0xf0;//if not 0 value is negative
	if(sign)
	{
		ds18b20_scratchpad[0]=~ds18b20_scratchpad[0]; //inverse the bit
		ds18b20_scratchpad[1]=~ds18b20_scratchpad[1];
	}
	digit=ds18b20_scratchpad[0]>>4;
  digit|=(ds18b20_scratchpad[1]&0x7)<<4;
	decimal=ds18b20_scratchpad[0]&0xf;
	temperature=(float)digit+(decimal*THERM_DECIMAL_STEPS_12BIT);
	if(sign) temperature=-(temperature+THERM_DECIMAL_STEPS_12BIT);
	return digit;
}
void output(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = DS18B20_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(DS18B20_GPIO, &GPIO_InitStruct);
}
void input(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin =  DS18B20_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(DS18B20_GPIO, &GPIO_InitStruct);
}

void _delay_us(uint16_t delay)
{
HAL_TIM_Base_Start(&htim17);
__HAL_TIM_SET_COUNTER(&htim17,0);  // set the counter value a 0
while (__HAL_TIM_GET_COUNTER(&htim17) < delay);  // wait for the counter to reach the us input in the parameter
}