// 1Wire   clock 4 meg

#include "main.h"

// изначально записываем "0" !!!
#define     PORTwire1   PORTC
#define     DDRwire1    DDRC
#define     PINwire1    PINC

#define     BITwire1    PC7  // бит DQ DS18B20

/*
SEARCH ROM [F0h]
READ ROM [33h]
MATCH ROM [55h]
SKIP ROM [CCh]
ALARM SEARCH [ECh]
Конвертировать температуру [44h]
Запись в память [4Eh]  +3 байта TH, TL, конфиг (0x7F)
Чтение памяти [BEh]  до 9 байт
Копирование ОЗУ В ПЗУ [48h]
Повторная загрузка [B8h]
Вид электропитания датчика [B4h]
    Если после подачи команды на шине присутствует логический «ноль» - это значит,
    что DS18B20 использует паразитное питание. Иначе DS18B20 использует внешнее питание (логическая единица).

*/

//**********1wire************

void init_1wire()
{
    DDRwire1 &= ~_BV(BITwire1);  // Вывод порта настраеваем как вход
    PORTwire1 &= ~_BV(BITwire1); // уровень порта = 0
}

// Функция сброса DS1820
uchar reset_1wire()
{
    uchar cResult = 1;
    cli();
    DDRwire1 |= _BV(BITwire1); // Вывод порта настраеваем как выход
    _delay_us(480);  // Устанавливаем 0 в теч. около 480 мкс

    DDRwire1 &= ~_BV(BITwire1);  // Вывод порта настраеваем как вход
    _delay_us(70); //60us  // Ожидание сигнала присутствия 70 мкс
    if( PINwire1 & _BV(BITwire1) )
    { // 1 - нет сигнала присутвия
        cResult = 0;
    }
    sei();
    //410 мкс
    _delay_us(410);  // Устанавливаем 0 в теч. около 480 мкс
    return cResult;
}

uchar readbit()
{
    cli();
    DDRwire1 |= _BV(BITwire1);//line down
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");//1.25us
    DDRwire1 &= ~_BV(BITwire1);//line up through 1.25us
    _delay_us(10); //10us
    uchar i = 0;
    if( PINwire1 & _BV(BITwire1) )
        i = 1;
    _delay_us(44); //44.5us
    sei();
    return i;
}

uchar read_1wire()
{
    uchar read_byte = 0;
    uchar r = 1;
    for(uchar i=0; i<8; i++)
    {
        if( readbit() )
            read_byte |= r;
        r <<= 1;
    }
    return read_byte;
}

void write_bit0(void)
{
    cli();
    DDRwire1 |= _BV(BITwire1);
    _delay_us(60); // 60us
    DDRwire1 &= ~_BV(BITwire1);
    sei();
}

void write_bit1(void)
{
    cli();
    DDRwire1 |= _BV(BITwire1);
    _delay_us(3); //3.2us
    DDRwire1 &= ~_BV(BITwire1);
    _delay_us(55); // 60us
    sei();
}

void write_1wire(uchar byte)
{
    for(uchar i=0; i<8; i++)
    {
        if( byte & 0x01 )
            write_bit1();
        else
            write_bit0();
        byte >>= 1;
    }
}

/*
//Функция считывания кода датчика
void search_ds1820_ROM(void)
{
reset_ds1820();             //Сброс датчика
send_ds1820_command(0xF0);  //Команда поиск ПЗУ
was_conflict=0;   //Сброс признака наличия конфликта
unsigned char bit_analizer=0; //Переменная анализа принятых битов
_delay_loop_2(250);
cli();
  for(j=0;j<8;j++) {      //Процедура получения номера датчика
   for(i=0;i<8;i++)
   {                      //Запрос на передачу бита
    DDRD|=_BV(6);
    _delay_loop_2(15);  //Задержка примерно на 6 мкс
    DDRD&=~_BV(6);
    _delay_loop_1(30);  //Задержка примерно на 9 мкс

     if (PIND & (1<<PIND6)) //Прием бита кода датчика
     {
     bit_analizer|=_BV(0);      //Запись лог. 1
     }
     else
     {
     bit_analizer&=~_BV(0);    //Запись лог. 0
     }
   _delay_loop_2(138);
                         //Запрос на передачу инверсного бита
    DDRD|=_BV(6);
    _delay_loop_2(15);  //Задержка примерно на 6 мкс
    DDRD&=~_BV(6);
    _delay_loop_1(30);  //Задержка примерно на 9 мкс
     if (PIND & (1<<PIND6)) //Прием инверсного бита кода датчика
     {
     bit_analizer|=_BV(1);      //Запись лог. 1
     }
     else
     {
     bit_analizer&=~_BV(1);    //Запись лог. 0
     }
     _delay_loop_2(138);
	 //Анализ принятых битов кода(прямого и инверсного)
	  switch(bit_analizer)
	   {
       case 0: //Произошел конфликт битов
	           was_conflict=1;
	           if(get_for_two==false) //Если для 1-го получаем
	                                    //по лог. 0
	            {
				ROM1[j]&=~_BV(i);
									  //Выдача лог. 0 на линию
                DDRD|=_BV(6);
                _delay_loop_2(150); //60 мкс
                DDRD&=~_BV(6);
                _delay_loop_2(25);  //10 мкс
				}
			   else //Если для 2-го получаем по лог. 1
			    {
				ROM2[j]|=_BV(i);
									 //Выдача лог.1 на линию
                DDRD|=_BV(6);
                _delay_loop_2(15);   //Задержка примерно на 6 мкс
                DDRD&=~_BV(6);
                _delay_loop_2(160);  //Задержка примерно на 64 мкс
				}
	           break;
	   case 1: if(get_for_two==false) //Прием лог.1
	            {
	           ROM1[j]|=_BV(i);
			    }
				else
				{
			   ROM2[j]|=_BV(i);
				}
               			//Выдача лог. 1 на линию
               DDRD|=_BV(6);
               _delay_loop_2(15);   //Задержка примерно на 6 мкс
               DDRD&=~_BV(6);
               _delay_loop_2(160);   //Задержка примерно на 64 мкс
			   break;
	   case 2: if(get_for_two==false)//Прием лог. 0
	           {
	           ROM1[j]&=~_BV(i);
			   }
			   else
			   {
			   ROM2[j]&=~_BV(i);
			   }
					 //Выдача лог.0 на линию
               DDRD|=_BV(6);
               _delay_loop_2(150);  //60 мкс
               DDRD&=~_BV(6);
               _delay_loop_2(25);  //10 мкс
			   break;
	   case 3:break;
	   };
	  }
	 }
if(get_for_two==false && was_conflict==1)
{
get_for_two=true;
}
else
{
get_for_two=false;
}
sei();
}
*/
/*
		writebyte(0xCC);//SKIP ROM [CCh]
		writebyte(0x4E);//WRITE SCRATCHPAD [4Eh]
		writebyte(t_otkl_in_ds);//	TH
		writebyte(0x77);//	TL
		writebyte(0x7F);//	Statys 12bit
		if (detectPresence()){// сохроняем в EEPROM
			writebyte(0xCC);//SKIP ROM [CCh]
			writebyte(0x48);//COPY SCRATCHPAD [48h]
			pullup_on();
			TCNT0=216;//10ms
			time_50ms=1;
			while(time_50ms);
			pullup_off();
			}
*/

// замер температуры
uchar Ask_DS18B20()
{
    if( !reset_1wire() )
        return 0;
    write_1wire(0xCC); // SKIP ROM [CCh]
    write_1wire(0x44); // Конвертировать температуру [44h]
    return 1;
//ждем 1 сек
}

// завершение замера температуры
uchar Check_DS18B20()
{
    DDRwire1 &= ~_BV(BITwire1);//line up through 1.25us
    _delay_us(10); //10us
    uchar i = 0;
    if( PINwire1 & _BV(BITwire1) )
        i = 1;
    return i;
}

// прочитать температуру. -99.9 - недостоверно
int Read_DS18B20()
{
    if( !reset_1wire() )
        return -999;
    write_1wire(0xCC);//SKIP ROM [CCh]
    write_1wire(0xBE);//READ SCRATCHPAD [BEh]
// читаем температуру
    int iValue = read_1wire();
    iValue |= (read_1wire() << 8);
// получили значение с датчика - расшифровываем
// мл. 4 бита - дробная часть
// b3  2(-1) = 0,5000
// b2  2(-2) = 0,2500
// b1  2(-3) = 0,1250
// b0  2(-4) = 0,0625
    unsigned int nDiv = 0;
    if( iValue & 0x08 ) nDiv += 5000;
    if( iValue & 0x04 ) nDiv += 2500;
    if( iValue & 0x02 ) nDiv += 1250;
    if( iValue & 0x01 ) nDiv +=  625;
    nDiv /= 1000; // оставили только 0,1 градус

// *10/16 = 5/8
    iValue >>= 4; // сбросили 4 бита
    iValue *= 10; // * 10 / 16
    iValue += nDiv; // добавили до 0,1 градуса
    return iValue;
}


