#include "DS18B20.h"

#define DS18B20_PORT GPIOC
#define DS18B20_PIN GPIO_PIN_1


void DS18B20_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_PORT, &GPIO_InitStruct);
}

void DS18B20_INPUT(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = DS18B20_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
}


void DS18B20_Reset(void) {
    DS18B20_OUTPUT();
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
    Delay_us(750);
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
    Delay_us(15);
}

uint8_t DS18B20_Check(void)
{
    uint8_t retry=0;
    DS18B20_INPUT();
    while ((HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN))&&retry<200)
    {
        retry++;
        Delay_us(1);
    };
    if(retry>=200) return 0;
    else retry=0;
    while (!(HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN))&&retry<240)
    {
        retry++;
        Delay_us(1);
    };
    Delay_us(480);
    if(retry>=300) return 0;

    return 1;
}

uint8_t DS18B20_Read_Bit(void) 			 // read one bit
{
    uint8_t data;
    DS18B20_OUTPUT();
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
    Delay_us(2);
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);

    DS18B20_INPUT();
    Delay_us(12);
    if((HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN))) data=1;
    else data=0;
    Delay_us(50);
    return data;
}

uint8_t DS18B20_ReadByte(void) {
    uint8_t byte = 0;
    uint8_t j=0;
    for (uint8_t i = 0; i < 8; i++) {
        j=DS18B20_Read_Bit();
        byte=(j<<7)|(byte>>1);
    }
    return byte;
}

void DS18B20_Write_Bit(uint8_t bit) {
    DS18B20_OUTPUT();
    if (bit == 1) {
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
        Delay_us(2);
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        Delay_us(60);
    }
    else {
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
        Delay_us(60);
        HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
        Delay_us(2);
    }
}

void DS18B20_WriteByte(uint8_t data) {
    DS18B20_OUTPUT();
    for (uint8_t i = 0; i < 8; i++)
    {
        if (data & 0x01)
        {
            HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
            Delay_us(2);
            HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
            Delay_us(60);
        }
        else
        {
            HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
            Delay_us(60);
            HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
            Delay_us(2);
        }
        data >>= 1;
    }
}

void DS18B20_Start(void)// ds1820 start convert
{
    DS18B20_Reset();
    DS18B20_Check();
    DS18B20_WriteByte(0xcc);// skip rom
    DS18B20_WriteByte(0x44);// convert
}

uint8_t DS18B20_Init()
{
    Delay_Init() ;

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOC_CLK_ENABLE();

    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_PORT, &GPIO_InitStruct);
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
    HAL_Delay(1000);

    DS18B20_Reset();
    return DS18B20_Check();
}
void DS18B20_Stop() {
    DS18B20_OUTPUT();
    HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
}

float DS18B20_GetTemperature() {
    uint8_t Hight_Byte = 0;
    uint8_t Low_Byte = 0;
    uint16_t value = 0;
    float temperture = 0;

    DS18B20_Start();

    DS18B20_Reset();
    uint8_t check = DS18B20_Check();
    // printf("check %d",check);
    DS18B20_WriteByte(0xCC);
    DS18B20_WriteByte(0xBE);

    Low_Byte = DS18B20_ReadByte();
    Hight_Byte = DS18B20_ReadByte();
    DS18B20_Stop();
    value = Hight_Byte;
    value = (value << 8) + Low_Byte;

    if ((value & 0xf800) == 0xf800) {
        value = (~value)+1;
        temperture = value*(-0.0625);
    }
    else {
        temperture = value*(0.0625);
    }
    // printf("Temperature 111: %.2f\n", temperture);
    return temperture;
}

//
// void DS18B20_SearchROM(uint8_t *roms, uint8_t *count) {
//     uint8_t bit_value, complement_bit;
//     uint8_t rom[8];
//     uint8_t last_discrepancy = 0;
//     uint8_t rom_index = 0;
//     uint8_t search_complete = 0;
//
//     *count = 0; // 设备数量清零
//     printf("Starting DS18B20 SearchROM...\n");
//
//     while (!search_complete) {
//         DS18B20_Reset();
//         // uint8_t aaa=DS18B20_Check();
//         if (!DS18B20_Check()) { // 复位总线，检测是否有设备存在
//             return; // 没有设备，直接返回
//         }
//
//         DS18B20_WriteByte(0xF0); // 发送 "搜索 ROM" 命令
//
//         uint8_t bit_position = 1;
//         uint8_t discrepancy_marker = 0; // 记录新的冲突位置
//
//         for (uint8_t i = 0; i < 64; i++) {
//             bit_value = DS18B20_Read_Bit();
//             complement_bit = DS18B20_Read_Bit();
//
//             if (bit_value == 1 && complement_bit == 1) {
//                 printf("No more devices found, stopping search.\n");
//                 return;
//             }
//
//             uint8_t chosen_bit;
//             if (bit_value == 0 && complement_bit == 0) {
//                 // **发生冲突，选择路径**
//                 if (bit_position < last_discrepancy) {
//                     // 沿用之前的选择
//                     chosen_bit = (rom[i / 8] >> (i % 8)) & 0x01;
//                 } else if (bit_position == last_discrepancy) {
//                     // 选择 1 继续遍历新路径
//                     chosen_bit = 1;
//                 } else {
//                     // 选择 0 并记录新的冲突
//                     chosen_bit = 0;
//                     discrepancy_marker = bit_position;
//                 }
//             } else {
//                 // 读取到 0 或 1，直接存储
//                 chosen_bit = bit_value;
//             }
//
//             if (chosen_bit) {
//                 rom[i / 8] |= (1 << (i % 8));
//             } else {
//                 rom[i / 8] &= ~(1 << (i % 8));
//             }
//
//             DS18B20_Write_Bit(chosen_bit);
//             bit_position++;
//         }
//
//         // 存储找到的ROM地址
//         for (uint8_t j = 0; j < 8; j++) {
//             roms[rom_index * 8 + j] = rom[j];
//         }
//         rom_index++;
//
//         // **搜索结束条件**
//         if (discrepancy_marker == 0) {
//             search_complete = 1;
//         }
//
//         last_discrepancy = discrepancy_marker;
//     }
//
//     *count = rom_index; // 返回找到的设备数量
// }
//
