
#include <stdint.h>

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include <tool.h>
#include <temp.h>

uint8_t ds18b20_reset() {
    uint8_t error;
    REG_SETDOWN_BIT(DS18B20_PORT, DS18B20_PB);
    REG_SETUP_BIT(DS18B20_DDR, DS18B20_PB);
    _delay_us(480);
    cli();
    REG_SETDOWN_BIT(DS18B20_DDR, DS18B20_PB);
    _delay_us(60);
    sei();
    error = REG_BIT_VALUE(DS18B20_PIN, DS18B20_PB);
    _delay_us(420);


    return error;
}

void ds18b20_write_bit(uint8_t bit) {
    cli();
    REG_SETDOWN_BIT(DS18B20_PORT, DS18B20_PB);
    REG_SETUP_BIT(DS18B20_DDR, DS18B20_PB);
    _delay_us(1);
    if (bit) {
        REG_SETDOWN_BIT(DS18B20_DDR, DS18B20_PB);
    }
    _delay_us(60);
    REG_SETDOWN_BIT(DS18B20_DDR, DS18B20_PB);
    sei();
}

uint8_t ds18b20_read_bit(void) {
    cli();
    uint8_t bit = 0x00;
    REG_SETDOWN_BIT(DS18B20_PORT, DS18B20_PB);
    REG_SETUP_BIT(DS18B20_DDR, DS18B20_PB);
    _delay_us(1);
    REG_SETDOWN_BIT(DS18B20_DDR, DS18B20_PB);
    _delay_us(14);
    if (REG_BIT_VALUE(DS18B20_PIN, DS18B20_PB)) {
        bit = 0x01;
    }
    _delay_us(45);
    sei();
    return bit;
}

void ds18b20_write_byte(uint8_t byte) {
    int i = 8;
    while (i--) {
        ds18b20_write_bit(byte & 0x01);
        byte >>= 1;
    }
}

uint8_t ds18b20_read_byte(void) {
    uint8_t i = 8, byte = 0;
    while (i--) {
        byte >>= 1;
        byte |= (ds18b20_read_bit() << 7);
    }
    return byte;
}

float ds18b20_get_temp() {
    uint8_t ltemp;
    uint8_t htemp;
    float temp = 0.0F;

    ds18b20_reset();
    ds18b20_write_byte(DS18B20_CMD_SKIPROM);
    ds18b20_write_byte(DS18B20_CMD_CONVERTTEMP);

    while (!ds18b20_read_bit());

    ds18b20_reset();
    ds18b20_write_byte(DS18B20_CMD_SKIPROM);
    ds18b20_write_byte(DS18B20_CMD_RSCRATCHPAD);

    ltemp = ds18b20_read_byte();
    htemp = ds18b20_read_byte();

    temp = ((htemp << 8) + ltemp) * 0.0625F;
    return temp;
}
