#include "dht.h"
#include <avr/io.h>

// Флаг прерывания  
volatile unsigned char interrupt_flag = 1;  
bool dht_done = false;
int  dht_check_icp;

uint8_t dht_state, dht_last_state;
int T1time, dPos, dNum;
float temperature, humidity;  
float last_temperature, last_humidity;

unsigned char data[5];  
uint16_t  dt[48];
int  dtcnt;
bool dht_check_act = false;

// Таймер для задержки
volatile unsigned int timer_counter = 0;
int dht_en_timer = 0;

//----------------------------------------------------------------------------------------------------
// Установка таймера  
void setup_timer(void)  
{  
  // Настраиваем таймер 1 в режиме CTC  
  TCCR0B = 0b00000101;  
  // Устанавливаем значение сравнения для частоты 1 Гц  
  OCR0A = 250;  
  // Разрешаем прерывание сравнения A  
  TIMSK0 |= (1 << OCIE0A);  

  // Настраиваем таймер 1 в режиме CTC  
  TCCR1A = 0b00000000;
  TCCR1B = 0b00000000;  
  // Устанавливаем значение сравнения для частоты 1 Гц  
  OCR1A = 250;  
  // Разрешаем прерывание сравнения A  
  TIMSK1 = 0b00100010;  
}  
//----------------------------------------------------------------------------------------------------
bool dht_check( void )
{
  if (dht_check_act) {
    dht_check_act = false;
//-----[ 01. Старт, выжидание 18мс ]-----
    if ( interrupt_flag == 1)
    {
  //  Запускаем таймер на 18 мс посылка start на dht
      DHT_DDR |= (1 << DHT_BIT);    //  Пин как выход
      DHT_PORT &= ~(1 << DHT_BIT);  //  Выход ноль
      TCNT1 = 0;                    //  
      OCR1A = 288;                  //  
      TCCR1A = 0b00000000;          //  
      TIMSK1 = 0b00000010;
      TCCR1B = 0b00000101;
    }
//  Настройка таймера для захвата времени таймером T1
    if ( interrupt_flag == 2)
    {
      DHT_PORT |= (1 << DHT_BIT);   //  Пин в 1цу
      DHT_DDR  &= ~(1 << DHT_BIT);  //  Пин порта на вход
      TCNT1 = 0;                    //  Сброс значения счётчика таймера
      OCR1A = 10000;                
      TCCR1A = 0b00000000;          //
      TCCR1B = 0b10000001;          //  1<<ICNC1 Антидребезг, 1<<CS10 Делитель таймера 1:1, 
      TIFR1  = 0b00000000;          //  
      TIMSK1 = 0b00100010;          //  1<<ICF1  Прерывание по захвату, 1<<OCF1A Совпадение канал A
    }
  }
  return DHT_check_data();
}
//------------------------------------------------------------------------
float  dht_humidity()
{
  return humidity;
}
//------------------------------------------------------------------------
float  dht_temperature()
{
  return temperature;
}
//------------------------------------------------------------------------
void  DHT_get_bit(){
  dtcnt++;
  dt[ dtcnt ] =  ICR1; 
}
//------------------------------------------------------------------------
bool  DHT_check_data(){

  if ( dtcnt == 43 ){
    dtcnt   = 0;                    //
    dPos    = 7;                    //
    dNum    = 0;
/*
  Цикл анализа принятых данных dt[] и распределение бит по байтам data[]
*/
    for ( uint8_t i=4; i<44;i++){
      if ( dt[ i ]<1500 )           //  если время dt[i] < 1500 то data[dNum][dPos] = 0, иначе =1
      { 
        data[dNum] &= ~(1<<dPos); 
      } // 0
      else            
      {
         data[dNum] |=  (1<<dPos); 
      } // 1
      dPos--;
      if ( dPos < 0)                //  если прошли 8бит, то пишем в следующий байт
      {
         dPos=7; dNum++; 
      }
    }

    DHT_DDR  |= (1 << DHT_BIT);    //  Пин как выход
    DHT_PORT |= (1 << DHT_BIT);   //  Выход HIGH

    temperature = (data[3] * 0.1) + ((data[2] & 0b01111111) * 25.6);  
    if (data[2] & 0b10000000) temperature *= -1;  
    humidity = (data[1] * 0.1) + (data[0] * 25.6);

    return true;
  }
  return false;
}
//------------------------------------------------------------------------
void  T0_CA(){
  TCNT0 = 0;
  dht_en_timer++;
  if ( dht_en_timer >= 65)
  {
    dht_en_timer =0;
    dht_done = false;
    dtcnt=0;
    interrupt_flag = 1;
    dht_check_act = true;
    DHT_DDR  |= (1 << DHT_BIT);    //  Пин как выход
    DHT_PORT |= (1 << DHT_BIT);   //  Выход HIGH
  }
}
//------------------------------------------------------------------------
void  T1_CA(){
  TCNT1 = 0;
  dht_check_act = true;
  TCCR1B = 0b00000000;
  if ( interrupt_flag < 3 )
  {
    interrupt_flag++;
  }
}