/*****************************************************
Project : Velo Comp
Version : 1.0
Date    : 23.03.2010
Author  : 

Chip type           : ATmega8
Program type        : Application
Clock frequency     : 1 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 512
*****************************************************/

#include <mega8.h>

// SPI functions
#include <spi.h>
#include <delay.h>
#include <stdio.h>
#include <lcd.c>

// I2C Bus functions
#asm
   .equ __i2c_port=0x15 ;PORTC
   .equ __sda_bit=4
   .equ __scl_bit=5
#endasm
#include <i2c.h>
// DS1307 Real Time Clock functions
#include <ds1307.h>

// 1 Wire Bus functions
#asm
   .equ __w1_port=0x15 ;PORTC
   .equ __w1_bit=3
#endasm
#include <1wire.h>  
// DS1820 Temperature Sensor functions
#include <ds18b20.h>

#define length 220 // довжина колеса в кілометрах

// Declare your global variables here
bit disp_flag = 0;
unsigned char str [14], sec_count = 0;
char hour = 0,m1n = 0,sec = 0; // години,хвилини,секунди
int last_time_sec = 0, j = 0;
volatile unsigned long int distance = 0;
eeprom unsigned long int eep_all_distance = 0;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
    sec_count ++;
    last_time_sec ++;    
}

void DS1307_init (void)  
{
    unsigned char tmphour, tmpmin, tmpsec1, tmpsec2;

    rtc_init(0,1,0); // ініціалізація годинника (вихід 1 Гц)

    rtc_get_time(&tmphour, &tmpmin, &tmpsec1); // читаємо час
    delay_ms(1500); // чекаємо 1,5 с
    rtc_get_time(&tmphour, &tmpmin, &tmpsec2); // ще раз читаємо час

    if (tmpsec1 == tmpsec2) // якщо "годинник стоїть"        
    {
        rtc_set_time(00,00,00); // запускаємо внутрішній генератор біт 7 (CH)                                     
        rtc_set_date(01, 01, 10);
    }
}

void get_time (void)
{
    rtc_get_time(&hour,&m1n,&sec); // прочитати час   
    sprintf(str, "%02u:%02u",hour,m1n);
    lcd_gotoxy(0,0);
    lcd_putstr(str);
}

void get_speed (int count)
{
    if (count < 10)
    { 
        sprintf(str, "SPEED: %u km/h ", count);        
    }
    else
    {
        sprintf(str, "SPEED: %u km/h", count);
    }
    lcd_gotoxy(0,1);
    lcd_putstr(str);
}

void all_distance (int dist)
{
    eep_all_distance += dist;
    eep_all_distance /= 100000;
    sprintf(str, "%i km", eep_all_distance);
    lcd_center_putstr(5, str);   
}

void set_distance (float dist)
{
    distance=distance+dist;

    sprintf(str, "DIST: %u sm",distance);
 
    lcd_gotoxy(0,2);
    lcd_putstr(str);
    all_distance (dist); 
}

void last_time (int last_time_sec)
{ 
    sprintf(str, "TIME: %02u:%02u",last_time_sec/3600,last_time_sec/60); 
    lcd_gotoxy(0,3);
    lcd_putstr(str);
}

void get_temperature (void)
{
    int temperature = 0;
    temperature = ds18b20_temperature_10 (0);
    sprintf(str, "t:%i.%i",temperature/10,temperature%10); 
    lcd_gotoxy(48,0);
    lcd_putstr(str);
}

void main(void)
{
// Declare your local variables here
distance = 0;
eep_all_distance = 0;
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=Out Func2=Out Func1=In Func0=In 
// State7=P State6=P State5=0 State4=T State3=0 State2=0 State1=T State0=T 
PORTB=0xC0;
DDRB=0x2C;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2*250,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x50;
SPSR=0x01; 

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
GICR|=0x40;
MCUCR=0x03;
GIFR=0x40;

lcd_init();

delay_us (100);

lcd_clear();

sprintf(str, "Velo Comp");
lcd_center_putstr (1,str);
sprintf(str, "Made");
lcd_center_putstr (3,str);
sprintf(str, "in Ukraine");
lcd_center_putstr (4,str); 
delay_ms(1000);
lcd_clear();

// I2C Bus initialization
i2c_init();

// DS1307 Real Time Clock initialization
DS1307_init();

w1_init();
#asm("nop")
ds18b20_init(0,5,40,DS18B20_12BIT_RES); // налаштування датчика температури  

get_time(); // читаємо дату та час 

// Global enable interrupts
#asm("sei")
                 
while (1)
      {      
        if (!PINB.6)
        {
            distance = 0;
            last_time_sec = 0;
            set_distance(0);
            last_time(last_time_sec);
            disp_flag = 1;
        }
        
        if (sec_count == 1) // раз у 3 секунди 
        {
            sec_count = 0;
            get_speed(1);
            get_time();
            get_temperature();
           
            if (disp_flag)
            {
                last_time(last_time_sec);
                set_distance(210);
                sprintf(str, "%i counts", j++);
                lcd_center_putstr(4, str);            
            }
        }                    
      };
}