// http://eugenemcu.ucoz.ru
#include               <inavr.h>
#include               <iom16.h>
#include           "dv16100.h"                                         // Драйвер символьного LCD-модуля DV16100.
#define                  LED        0
 
long                       SYS_FREQ = 1000000;                   // Тактовая частота.
unsigned char     Num1000;                                           // Разряд тысяч.
unsigned char     Num100;                                              // Разряд сотен.
unsigned char     Num10;                                                // Разряд десятков.
unsigned char     Num1;                                                  // Разряд единиц.
unsigned char     Num01;                                                // Разряд десятых.
double                  FrqHz;                                                   // Частота в герцах.
double                  FrqMn;                                                 // Частота в об/мин.
unsigned char     FreqOk=1;                                           // Признак «Получено новое значение частоты»
unsigned long     Period=0xFFFFFFF;                        // Длительность периода в тактах таймера.
union                     {unsigned int PRD0;  unsigned char PRD1[2];}   PRD; // Вспомогательное объединение.
               
 
void main (void)
{
    INI_LCD();                                                                       // Инициализировать LCD.
    DDRB |= (1<<LED);      
    MCUCR |= (1<<ISC00)|(1<<ISC01);                         // Прерывание  INT0 формировать по фронту сигнала.
    TCCR1B |= (1<<CS10)|(1<<CS11);                          // Тактировать T0 системной частотой.
    GICR |= (1<<INT0);                                                      // Разрешить прерывание INT0.
    GIFR |= (1<<INTF0);                                                    // Сбросить флаг INT0.
    SREG |= (1<<7);                                                            // Разрешить прерывания в программе.
    while (1)
                {
        if (FreqOk==1)                                                           // Если получено новое значение частоты…
        {
            FrqMn=(60/(Period*64e-6));         
            FrqHz=FrqMn/60;
            // Выделяем десятичные разряды числа.
            Num100=Num10=Num1=Num01=0;                                                                            
            while (FrqHz>=100)                                              {Num100++;  FrqHz -= 100;}
            while (FrqHz>=10)                                                {Num10++;   FrqHz -= 10;}
            while (FrqHz>=1)                                                   {Num1++;    FrqHz -= 1;}
            while (FrqHz>=0.1)                                               {Num01++;   FrqHz -= 0.1;}
            LCD_VIEW(7,'z');                                                    // Отображаем частоту на LCD.
            LCD_VIEW(6,'H');
            LCD_VIEW(4,(Num01+0x30));
            LCD_VIEW(3,'.');           
            LCD_VIEW(2,(Num1+0x30));
            LCD_VIEW(1,(Num10+0x30));
            LCD_VIEW(0,(Num100+0x30));
            
            Num1000=Num100=Num10=Num1=0;
            while (FrqMn>=1000)                                          {Num1000++; FrqMn -= 1000;}
            while (FrqMn>=100)                                             {Num100++;  FrqMn -= 100;}
            while (FrqMn>=10)                                               {Num10++;   FrqMn -= 10;}
            while (FrqMn>=1)                                                 {Num1++;    FrqMn -= 1;}
            LCD_VIEW(15,'M');
            LCD_VIEW(14,'p');
            LCD_VIEW(12,(Num1+0x30));
            LCD_VIEW(11,(Num10+0x30));
            LCD_VIEW(10,(Num100+0x30));           
            LCD_VIEW(9, (Num1000+0x30));           
            FreqOk=0;                                                              // Частота отображена. Ждать новой.
        }
        DELAY_MS (300);                                                     // Задержка для читаемости на LCD.
    }
}   
/*______________________________________________________
                              
 FUNCTIONS
______________________________________________________*/
 
void DELAY_MS (int Xms)                                               // Задержка на Xms миллисекунд .
{
                long   DELMS=(Xms*(SYS_FREQ/(10*1000))-65);
                while (DELMS!=0) DELMS--;
}
 
#pragma vector=INT0_vect
__interrupt  void INT0_INTPT()                                     // Прерывание INT0.
{
    PRD.PRD1[0]=TCNT1L;   
    PRD.PRD1[1]=TCNT1H;
    TCNT1H=0;
    TCNT1L=0;
    Period=PRD.PRD0;
    FreqOk=1;  
    PORTB ^= (1<<LED);
    GIFR |= (1<<INTF0);
}