// avrdude -pt13 -cusbtiny -Pusb -e -U lfuse:w:0x7a:m -U hfuse:w:0xff:m -U flash:w:C:\arduino\ATTINY13_termostat.cpp.hex:i -B 50

//                       +-\/-+
//      A0   (D5)  PB5  1|    |8   VCC
//      A3   (D3)  PB3  2| AT |7   PB2  (D2)  INT0  A1
//      A2   (D4)  PB4  3| 13 |6   PB1  (D1)        pwm1
//                 GND  4|    |5   PB0  (D0)        pwm0
//                       +----+


#define F_CPU 9600000  // 9.6MHz clock
//#define BAUD_RATE 115200

#include <avr/io.h>
#include <util/delay.h>
#include <BasicSerial.h>
#include <avr/pgmspace.h>


#define DS_BIT          2 // pin 7 ATTINY13 onewire pin
#define RC_BIT1         0 // pin 5 ATTINY13 switch output
//pin 6 ATTINY = serial monitor
//#define LEDBIT        5 // pin 1 ATTINY13 switch output

prog_char Message0[] PROGMEM  = {
  "by OK5AZ"}; 


// Serial monitor
void serOut(const char* str)
{
  while (*str) TxByte (*str++);
}


// Print mesaages from PROGMEM variables
void SerPrintMessage(prog_char Message[]) {
  char buf[2];
  byte b = 0;
  while(1){
    buf[0] = pgm_read_byte_near(&(Message[b]));
    buf[1] = '\0';
    if(buf[0] == 'Q')break;
    serOut(buf);
    b++;
  }
}

// Serial monitor - CR
void serCR()
{
  serOut("\n");
}


// Onewire reset
void OneWireReset() 
{
  PORTB &= ~_BV(DS_BIT);
  DDRB |= _BV(DS_BIT);
  _delay_us(500);
  DDRB &= ~_BV(DS_BIT);
  _delay_us(500);
}


// Onewire write
void OneWireOutByte(uint8_t d) 
{
  uint8_t n;

  for(n=8; n!=0; n--)
  {
    if ((d & 0x01) == 1) 
    {

      PORTB &= ~_BV(DS_BIT);
      DDRB |= _BV(DS_BIT);
      _delay_us(5);
      DDRB &= ~_BV(DS_BIT);
      _delay_us(60);
    }
    else
    {
      PORTB &= ~_BV(DS_BIT);
      DDRB |= _BV(DS_BIT);
      _delay_us(60);
      DDRB &= ~_BV(DS_BIT);
    }
    d=d>>1; 
  }
}


uint8_t OneWireInByte() 
{
  uint8_t d, n,b;

  for (n=0; n<8; n++)
  {
    PORTB &= ~_BV(DS_BIT);
    DDRB |= _BV(DS_BIT);
    _delay_us(5);
    DDRB &= ~_BV(DS_BIT);
    _delay_us(5);
    b = ((PINB & _BV(DS_BIT)) != 0);
    _delay_us(50);
    d = (d >> 1) | (b<<7);
  }
  return(d);
}



// Main
int main() {

  volatile const uint8_t adc2 = (1<<ADLAR) | 2; // ADC2 input
  volatile const uint8_t adc3 = (1<<ADLAR) | 3; // ADC3 input
  boolean heating = false;
  uint8_t delay_counter=0;

  DDRB |= _BV(DS_BIT);
  PORTB &= ~_BV(DS_BIT);
  DDRB &= ~_BV(DS_BIT);

  // nastaveni portu switche + LEDky
  DDRB |= (1 << RC_BIT1);
  //DDRB |= (1 << RC_BIT2);

  int16_t  adc2_in, adc3_in;
  int16_t TempSet; // nastavena teplota 2400 = 24.00 stupnu Celsia
  int16_t hystereze; // hystereze 200 = 2.00 stupnu Celsia

  // serial monitor
  char TReadingCh[5], TempSetCh[5], hysterezeCh[5];

  // ADC reference souce = internal
  ADMUX |= (1 << REFS0);
  // Set the prescaler to clock/128 & enable ADC
  // At 9.6 MHz this is 75 kHz.
  // See ATtiny13 datasheet, Table 14.4.
  ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);

  while( 1 ){          
    uint8_t SignBit;
    uint8_t DSdata[2];

    // cteni ADC2 = nastaveni hystereze
    // ADC-8bit  0-255 = 0-5deg * 100 = 255 * 2
    // Start the conversion
    ADMUX = adc2;
    ADCSRA |= (1 << ADSC);
    // Wait for it to finish
    while (ADCSRA & (1 << ADSC));
    adc2_in = ADCH;
    hystereze = (adc2_in * 2);


    // cteni ADC3 = nastaveni teploty
    // ADC-8bit 0-255 = 0-51deg * 100 = 255 * 20 
    // Start the conversion
    ADMUX = adc3;
    ADCSRA |= (1 << ADSC);
    // Wait for it to finish
    while (ADCSRA & (1 << ADSC));
    adc3_in = ADCH;
    TempSet = (adc3_in * 20);


    // onewire
    OneWireReset();
    OneWireOutByte(0xcc);
    OneWireOutByte(0x44);

    PORTB |= _BV(DS_BIT);
    DDRB |= _BV(DS_BIT);
    _delay_ms(1000);
    DDRB &= ~_BV(DS_BIT);
    PORTB &= ~_BV(DS_BIT);

    OneWireReset();
    OneWireOutByte(0xcc);
    OneWireOutByte(0xbe);

    DSdata[0] = OneWireInByte(); 
    DSdata[1] = OneWireInByte();

    int16_t TReading = (int)(DSdata[1] << 8) + DSdata[0];

    SignBit = TReading & 0x8000; 
    if (SignBit) TReading = (TReading ^ 0xffff) + 1;

    // vypocet teploty
    TReading = (((6 * TReading) + TReading / 4)); // 2345 = 23.45 stupnu Celsia


    // spodni limit termostatu
    if (TReading < 0) { 
      TReading = 1; 
    }

    // horni limit termostatu
    if (TReading > 9900) { 
      TReading = 9900; 
    }

    // osetreni odpojeni/chyby termocidla
    if (TReading == 0) { 
      TReading = 9900; 
    }

    // zapinani a vypinani topeni
    if (TReading < (TempSet - hystereze)) {
      PORTB |= (1 << RC_BIT1);      // topeni zapnuto = HIGH level
      //PORTB |= (1 << RC_BIT2);      // LEDon
      heating = true;  
    }
    if (TReading > (TempSet + hystereze)) {
      PORTB &= ~(1 << RC_BIT1);     // topeni vypnuto = LOW level
      //PORTB &= ~(1 << RC_BIT2);     // LEDoff
      heating = false;  
    } 


    // serial monitor ~300bytes 
    itoa(TReading,TReadingCh,10);
    itoa(TempSet,TempSetCh,10);
    itoa(hystereze,hysterezeCh,10);

    //SerPrintMessage(Message0);
    
    serOut("T=");
    serOut(TReadingCh);
    serCR();

    serOut("Ts=");
    //serOut(Message1);

    serOut(TempSetCh);
    serCR();

    serOut("Hs=");
    //serOut(Message2);

    serOut(hysterezeCh);
    serCR();
    //serOut(Message3);

    if (heating == true) { 
      serOut("ON");
      //serOut(Message4);
      serCR();  
    } 
    if (heating == false) { 
      serOut("OFF");
      //serOut(Message5);
      serCR();
    }
    //serOut(Message7);
    serCR();


    _delay_ms(1000); // pauza 1s = opakovani cyklu
    TReading = 0;
  }
}





