#include "DS18B20.hpp"
#include "common.hpp"

QueueHandle_t xQueue;


#define MAX_TIMINGS 85

void ds18b20_init() {
    gpio_init(DS18B20_PIN);
    gpio_set_dir(DS18B20_PIN, GPIO_OUT);
    gpio_put(DS18B20_PIN, 1); // 上拉电阻
}

void ds18b20_write_bit(uint8_t bit) {
    gpio_set_dir(DS18B20_PIN, GPIO_OUT);
    gpio_put(DS18B20_PIN, 0);
    sleep_us(bit ? 10 : 60);
    gpio_put(DS18B20_PIN, 1);
    sleep_us(bit ? 55 : 5);
}

uint8_t ds18b20_read_bit() {
    uint8_t bit = 0;
    gpio_set_dir(DS18B20_PIN, GPIO_OUT);
    gpio_put(DS18B20_PIN, 0);
    sleep_us(3);
    gpio_set_dir(DS18B20_PIN, GPIO_IN);
    sleep_us(10);
    bit = gpio_get(DS18B20_PIN);
    sleep_us(50);
    return bit;
}

void ds18b20_write_byte(uint8_t byte) {
    for (int i = 0; i < 8; i++) {
        ds18b20_write_bit(byte & 0x01);
        byte >>= 1;
    }
}

uint8_t ds18b20_read_byte() {
    uint8_t byte = 0;
    for (int i = 0; i < 8; i++) {
        byte >>= 1;
        if (ds18b20_read_bit()) {
            byte |= 0x80;
        }
    }
    return byte;
}

int ds18b20_reset() {
    gpio_set_dir(DS18B20_PIN, GPIO_OUT);
    gpio_put(DS18B20_PIN, 0);
    sleep_us(480);
    gpio_put(DS18B20_PIN, 1);
    gpio_set_dir(DS18B20_PIN, GPIO_IN);
    sleep_us(70);
    int presence = !gpio_get(DS18B20_PIN);
    sleep_us(410);
    return presence;
}

float ds18b20_read_temperature() {
    if (!ds18b20_reset()) {
        printf("DS18B20 not found\n");
        return -1;
    }

    ds18b20_write_byte(0xCC); // 跳过ROM指令
    ds18b20_write_byte(0x44); // 启动温度转换

    sleep_ms(750); // 温度转换时间，具体时间请参考传感器数据手册

    if (!ds18b20_reset()) {
        printf("DS18B20 not found\n");
        return -1;
    }

    ds18b20_write_byte(0xCC); // 跳过ROM指令
    ds18b20_write_byte(0xBE); // 读取暂存器

    uint8_t lsb = ds18b20_read_byte();
    uint8_t msb = ds18b20_read_byte();
    int16_t temp = (msb << 8) | lsb;

    // 检查传感器数据有效性
    if (temp == 0xFFFF) {
        printf("Invalid temperature data\n");
        return -1;
    }

    return temp / 16.0; // 转换为摄氏度
}


// 温度传感器
void DS18B20(void *pvParameters)
{
    
    // One_wire 第三方库方法
    float TEMPERATURE = -1;

    One_wire one_wire(DS18B20_PIN);
    one_wire.init();
    rom_address_t address {
    };

    _printTaskStackHighWaterMark("DS18B20");

    while (1) {
        one_wire.single_device_read_rom(address);
        one_wire.convert_temperature(address, true, false);
        TEMPERATURE = one_wire.temperature(address);

        printf("Device Address: %02x%02x%02x%02x%02x%02x%02x%02x DS18B20 Temperature: %3.1f°C\n", address.rom[0], address.rom[1], address.rom[2], address.rom[3], address.rom[4], address.rom[5], address.rom[6], address.rom[7], one_wire.temperature(address));

        // 发送数据到队列
        xQueueSend(xQueue, &TEMPERATURE, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));

        //_printTaskStackHighWaterMark("DS18B20");
        watchdog_update();                  // 喂狗
        vTaskDelay(pdMS_TO_TICKS(3000));    // 非阻塞延时
    }
    
    /*
    ds18b20_init();

    while (1) {
        float temperature = ds18b20_read_temperature();
        if (temperature != -1) {
            printf("DS18B20 Temperature: %.2f°C\n", temperature);
        } else {
            printf("Failed to read temperature\n");
        }
        
        watchdog_update();                  // 喂狗
        vTaskDelay(pdMS_TO_TICKS(3000)); // 非阻塞延时
    }
    */
    return;
}
