#ifndef __MAIN_H
#define __MAIN_H

#include <ioavr.h>
#include <intrinsics.h>
#include <stdint.h>
#include "twim.h"

#ifndef F_CPU
   #define F_CPU  8000000UL
#endif

/* Timers */
// T0 period 4 ms == 0x100 - (8000000 / 256 * 0.004) 
#define TIM0_PRESCALER  1<<CS02
#define TIM0_CNT        0x83

// T2 period 1 ms == 0x100 - (8000000 / 64 * 0.001)
#define TIM2_PRESCALER  1<<CS22
#define TIM2_CNT        0x83

/* LEDs */
#define LED_PORT        PORTC
#define LED_DDR         DDRC
#define LED_1           (1<<PC2)
#define LED_2           (1<<PC3)

#define LED_ON(led)     LED_PORT |= led
#define LED_OFF(led)    LED_PORT &= ~led
#define LED_TOGGLE(led) LED_PORT ^= led

/* 7-segment LED indikators */
#define INDCTR_NUMS                4

/**
 *   A
 * F   B
 *   G
 * E   C
 *   D   H
 */
#define INDCTR_SEGMENT_PORT        PORTB
#define INDCTR_SEGMENT_DDR         DDRB
#define INDCTR_SEGMENT_A           (1<<PB0)
#define INDCTR_SEGMENT_B           (1<<PB2)
#define INDCTR_SEGMENT_C           (1<<PB4)
#define INDCTR_SEGMENT_D           (1<<PB6)
#define INDCTR_SEGMENT_E           (1<<PB7)
#define INDCTR_SEGMENT_F           (1<<PB1)
#define INDCTR_SEGMENT_G           (1<<PB3)
#define INDCTR_SEGMENT_H           (1<<PB5)

#define INDCTR_COMMON_PORT         PORTD
#define INDCTR_COMMON_DDR          DDRD
#define INDCTR_COMMON_1            (1<<PD0)
#define INDCTR_COMMON_2            (1<<PD1)
#define INDCTR_COMMON_3            (1<<PD2)
#define INDCTR_COMMON_4            (1<<PD3)
#define INDCTR_COMMON_ALL          (INDCTR_COMMON_1 | INDCTR_COMMON_2 | INDCTR_COMMON_3 | INDCTR_COMMON_4)

#define INDCTR_COMMON_DOT          1

typedef enum {
  Sym_0 = 0xD7,
  Sym_1 = 0x14,
  Sym_2 = 0xCD,
  Sym_3 = 0x5D,
  Sym_4 = 0x1E,
  Sym_5 = 0x5B,
  Sym_6 = 0xDB,
  Sym_7 = 0x15,
  Sym_8 = 0xDF,
  Sym_9 = 0x5F,
  Sym_a = 0x9F,
  Sym_b = 0xDA,
  Sym_c = 0xC8,
  Sym_d = 0xDC,
  Sym_e = 0xCB,
  Sym_f = 0x8B,
  Sym_minus = INDCTR_SEGMENT_G,
  Sym_minus_t = INDCTR_SEGMENT_A,
  Sym_minus_b = INDCTR_SEGMENT_D,
  Sym_gradus = 0x0F,
  Sym_t = 0xCA,
  Sym_dot = INDCTR_SEGMENT_H,
  Sym_blank = 0x00
} indctr_sym_t;

/* Convert 0x0-0xF digit to 7-seg indicators symbol */
const indctr_sym_t IndctrNums[16] = {
  Sym_0, Sym_1, Sym_2, Sym_3,
  Sym_4, Sym_5, Sym_6, Sym_7,
  Sym_8, Sym_9, Sym_a, Sym_b,
  Sym_c, Sym_d, Sym_e, Sym_f
};


/* DS18B20 termometer */
#define DS18B20_CMD_CONVERTTEMP   0x44
#define DS18B20_CMD_RSCRATCHPAD   0xbe
#define DS18B20_CMD_WSCRATCHPAD   0x4e
#define DS18B20_CMD_CPYSCRATCHPAD 0x48
#define DS18B20_CMD_RECEEPROM     0xb8
#define DS18B20_CMD_RPWRSUPPLY    0xb4
#define DS18B20_CMD_SEARCHROM     0xf0
#define DS18B20_CMD_READROM       0x33
#define DS18B20_CMD_MATCHROM      0x55
#define DS18B20_CMD_SKIPROM       0xcc
#define DS18B20_CMD_ALARMSEARCH   0xec

#define DS18B20_PORT            PORTD
#define DS18B20_DDR             DDRD
#define DS18B20_PIN             PIND
#define DS18B20_PAD             PD7

#define DS18B20_INPUT_MODE      DS18B20_DDR&=~(1<<DS18B20_PAD)
#define DS18B20_OUTPUT_MODE     DS18B20_DDR|=(1<<DS18B20_PAD)
#define DS18B20_LOW             DS18B20_PORT&=~(1<<DS18B20_PAD)
#define DS18B20_HIGH            DS18B20_PORT|=(1<<DS18B20_PAD)
#define DS18B20_VALUE           (DS18B20_PIN & (1<<DS18B20_PAD))

__no_init int8_t Temperature @7;

static uint8_t ds18b20_Reset(void);
static void ds18b20_WriteBit(uint8_t bit);
static uint8_t ds18b20_ReadBit(void);
static uint8_t ds18b20_ReadByte(void);
static void ds18b20_WriteByte(uint8_t byte);
static void ds18b20_StartMeasure(void);
static void ds18b20_ReadTemperature(void);

#define TIM1_PRESCALER          (1<<CS11)

/* BTN */
#define BTN_LVL_NO              0xED
#define BTN_LVL_7               0xD8
#define BTN_LVL_6               0xD0
#define BTN_LVL_5               0xC5
#define BTN_LVL_4               0xB4
#define BTN_LVL_3               0x94
#define BTN_LVL_2               0x3F

typedef enum {
  btn_no = 0,
  btn_1,
  btn_2,
  btn_3,
  btn_4,
  btn_5,
  btn_6,
  btn_7
} btn_t;

/* DS1307 */
#define DS1307_ADR              0x68
#define DS1307_ADR_RD           0xD0
#define DS1307_ADR_WR           0xD1

typedef struct {
  uint8_t seconds;
  uint8_t minutes;
  uint8_t hours;
} time_t;

/* Global varaibles */
__no_init indctr_sym_t Indicator1 @15;
__no_init indctr_sym_t Indicator2 @14;
__no_init indctr_sym_t Indicator3 @13;
__no_init indctr_sym_t Indicator4 @12;
__no_init uint8_t resultADC @11;

__no_init struct {
  uint8_t newTime       : 1;
  uint8_t newTemp       : 1;
  uint8_t newBTN        : 1;
  uint8_t getTime       : 1;
  uint8_t startDS18B20  : 1;
  uint8_t readDS18B20   : 1;
  uint8_t               : 2;
} Flag @10;

__no_init struct {
  uint8_t needDot       : 1;
  uint8_t blinkIndktr   : 1;
  uint8_t waitIndktr    : 1;
  uint8_t               : 5;
} Flag2 @9;

typedef enum {
  show_None = 0,
  show_HHMM,
  show_MMSS,
  show_TEMP,
  set_TIME
} state_t;

__no_init state_t State @8;

static uint8_t twi_buf[5];
static time_t Clock;

#define PERIOD_ADC      100
#define PERIOD_TWI      500
#define PERIOD_SHT      5000
#define PERIOD_DS18B20s 10000
#define PERIOD_DS18B20r 750
volatile static uint8_t counterADC;
volatile static uint16_t counterTWI;
volatile static uint16_t counterShowTemp;
volatile static uint16_t counterDS18B20s;
volatile static uint16_t counterDS18B20r;


/* Functions prototypes */
static void showHHMM(void);
static void showMMSS(void);
static void showTEMP(void);
static btn_t getBTN(void);
static void setTime(void);
static void getTime(void);
static uint8_t bcd2bin(uint8_t bcd);
static uint8_t bin2bcd(uint8_t bin);

#endif // __MAIN_H
