/*****************************************************
CodeWizardAVR V1.24.8b Professional

Chip type           : ATmega8
Program type        : Application
Clock frequency     : 8,000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega8.h>

#define SOLENOID_PORT PORTB.0 // вывод, к которому подключён светодиод 
#define PULSE_TIME 200 // длительность импульса соленоида в миллисекундах 

// объявляем счетчик как  и его состояние как глобальные переменные
volatile unsigned int meter_on_time; // время включения секундомера
volatile unsigned int pulse_time; // длительность импульса соленоида
volatile unsigned int ms_counter; // счётчик миллисекунд
volatile enum // состояния секундомера
{
    off,     // выключен
    must_on, // надо включить
    on,      // включён
    must_off // надо выключить
}meter_status;

// переменные для хранения часов, минут, секунд тоже как глобальные
unsigned char hour = 0;
unsigned char min = 0;
unsigned char sec = 0;

// время измерения будем хранить в энергонезависимой памяти
eeprom unsigned int meter_on_time_eeprom = 0; // какое было прошлый раз

// объявляем прототипы наших функций и обработчиков прерывний.
// а их самих сунем в конец файла (можно и вообще в другой файл)
// чтоб глаза не мозолили.
interrupt [TIM1_COMPA] void timer1_compa_isr(void);
interrupt [TIM2_COMP] void timer2_comp_isr(void);
void initPeripherals(void); // сюда засунем всю инициализацию
void timeDelayMs(unsigned int time_delay); // самопальная временная задержка 
void statusOffExecute(void); // функция обработки состояния "выключено"
void statusOnExecute(void); // функция обработки состояния "включено"
void timeDisplay(unsigned int on_time_display); // выводит на дисплей время

void main(void)
{

initPeripherals(); // инициализация нашего железа.

meter_on_time = meter_on_time_eeprom; // берём предыдущее значение из EEPROM
meter_status = off;
// Global enable interrupts
#asm("sei")


while (1)
    {
        //проверяем состояние нашей шарманки
        // в зависимости от этого вызываем соответствующую функцию
        switch(meter_status)
        {
            case off: // выключена
                statusOffExecute(); // вызываем функцию состояния "выключено"
                break;
            case on: // включена и тИкает...
                statusOnExecute(); // вызываем функцию состояния "выключено"
                break;

            default: // в прочих случаях ничего делать не надо.
                break;
         }
    };
}// конец главной программы
  
void timeDisplay(unsigned int on_time_display) // выводит на дисплей время 
{
hour = on_time_display/3600;
min = (on_time_display - 3600*(unsigned int)hour)/60;
sec = on_time_display - 3600*(unsigned int)hour - 60*(unsigned int)min;
// дальше вывести hour, min, sec на дисплей
// ...................................
}



void statusOffExecute(void) // функция обработки состояния "выключено"
{
// индикация установленного времени
timeDisplay(meter_on_time); // выводит на дисплей время
// установка времени


#asm("cli") // запрещаем все прерывания
meter_on_time = 3600*(unsigned int)hour + 60*(unsigned int)min + (unsigned int)sec;
// запись установленного времени в EEPROM
meter_on_time_eeprom = meter_on_time;
// запуск секундомера
meter_status = must_on;
#asm("sei") // разрешаем прерывания
}

void statusOnExecute(void) // функция обработки состояния "включено"
{
// индикация текущего времени (сколько осталось)
// принудительное выключение по нажатии кнопки

}

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
// сюда попадаем каждую секунду
// проверяем, была ли дана команда на включение?
if(meter_status == must_on)
{
    // да, была. включаем
    SOLENOID_PORT = 1;
    pulse_time = PULSE_TIME; // задаём длительность импульса соленоида
    // и изменям статус на включён
    meter_status = on;
}

if(meter_status == on)
{
    // время вышло?
    if(meter_on_time)
    {
        // нет, не вышло
        meter_on_time--; // уменьшили на секунду
    }
    else
    {
        // вышло! Выключаем нах!
        SOLENOID_PORT = 1;
        pulse_time = PULSE_TIME; // задаём длительность импульса соленоида
        // и изменям статус на выключен
        meter_status = off;
    }
}
}//interrupt [TIM1_COMPA] void timer1_compa_isr(void)


// Timer 2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
// сюда попадаем каждую миллисекунду
// проверяем, время импульса вышло ?
if(pulse_time)
{
    // нет, не вышло
    pulse_time--; // уменьшили на миллисекунду
}
else
{
    // вышло! Выключаем !
    SOLENOID_PORT = 0;
}
// проверяем счётчик для функции временной задержки 
if(ms_counter)
    ms_counter--; // 
}//interrupt [TIM2_COMP] void timer2_comp_isr(void)


void initPeripherals(void)
{
// Input/Output Ports initialization
// Port B initialization
// PB0, PB1, PB2, PB3 - на вывод 
PORTB=0x00;
DDRB=0x0F;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 31,250 kHz
// Mode: CTC top=OCR1A
// OC1A output: Toggle
// Compare A Match Interrupt: On

TCCR1A=0x40;
TCCR1B=0x0C;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x7A;
OCR1AL=0x12;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 250,000 kHz
// Mode: CTC top=OCR2
// OC2 output: Toggle on compare match
ASSR=0x00;
TCCR2=0x1B;
TCNT2=0x00;
OCR2=0xFA;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x90;

}

void timeDelayMs(unsigned int time_delay)  // самопальная временная задержка
{
    ms_counter = time_delay;
    while(ms_counter);
}
