// Program pro měření frekvence jako součást generátoru funkcí
// Používá 4 místný displej se spol. anodou a AT89C2051 na 24MHz
// 2001 Tranzistor electronic

#include <reg51.h>

#define RadHz  0
#define RadkHz 1
#define RadMHz 2

sbit Dig1 = P3 ^ 5;
sbit Dig2 = P3 ^ 3;
sbit Dig3 = P3 ^ 1;
sbit Dig4 = P3 ^ 0;
sbit Leds = P3 ^ 7;
sbit LoFrq =P3 ^ 4;

#define LED	P1

unsigned long Frekvence;
unsigned char AktZnak=0;
unsigned char Znak[4];
unsigned char Rad;

unsigned int TimeStatus;
unsigned char Count;

bit Cas1ms;

#define SegB 0xFE
#define SegF 0xFD
#define SegA 0xFB
#define SegE 0xF7
#define SegD 0xEF
#define SegG 0xDF
#define SegC 0xBF
#define SegH 0x7F

const char Znaky[10]={SegA&SegB&SegC&SegD&SegE&SegF,        // 0
                      SegB&SegC,                            // 1
                      SegA&SegB&SegD&SegE&SegG,             // 2
                      SegA&SegB&SegC&SegD&SegG,             // 3
                      SegB&SegC&SegF&SegG,                  // 4
                      SegA&SegC&SegD&SegF&SegG,             // 5
                      SegA&SegC&SegD&SegE&SegF&SegG,        // 6
                      SegA&SegB&SegC,                       // 7
                      SegA&SegB&SegC&SegD&SegE&SegF&SegG,   // 8
                      SegA&SegB&SegC&SegD&SegF&SegG};       // 9

void Timer0intr() interrupt 1
{
  Count++;
}

void Timer1intr() interrupt 3
{
  LED=0xFF;Leds=1;
  Dig1=1;Dig2=1;Dig3=1;Dig4=1;
  switch(AktZnak)
  {
    case 0:Dig1=0;break;
    case 1:Dig2=0;break;
    case 2:Dig3=0;break;
    case 3:Dig4=0;break;
  }
  LED=Znak[AktZnak];
  if(AktZnak++==Rad) Leds=0;
  if(AktZnak>3) AktZnak=0;
  if(!(--TimeStatus)) Cas1ms=1;
}

void NastavCislo()
{
  unsigned char DT,Ra;
  unsigned char VZnak[4];
  while(AktZnak) {};      // Počkej až se zobrazí celý displej
  if(Frekvence<10000)	  // Pokud je frekvence menší než 100Hz
  {
    DT=1;
    Ra=RadHz;
  } else 
  {
    Frekvence/=10;
    DT=2;
    Ra=RadHz;
    if(Frekvence>=10000)
    {
      Frekvence/=10;
      DT=0;
      Ra=RadkHz;
      if(Frekvence>=10000)
      {
        Frekvence/=10;
        DT=1;
        if(Frekvence>=10000)
        {
          Frekvence/=10;
          DT=2;
          if(Frekvence>=10000)
          {
            Frekvence/=10;
            DT=0;
            Ra=RadMHz;
          }
        }
      }
    }
  }
  VZnak[0]=Znaky[Frekvence/1000];
  VZnak[1]=Znaky[(Frekvence/100)%10];
  VZnak[2]=Znaky[(Frekvence/10)%10];
  VZnak[3]=Znaky[Frekvence%10];
  VZnak[DT]&=SegH;
  EA=0;                   // Zákaz přerušení
  Znak[0]=VZnak[0];
  Znak[1]=VZnak[1];
  Znak[2]=VZnak[2];
  Znak[3]=VZnak[3];
  Rad=Ra;
  EA=1;
}

void ZmerFrekvenci()
{
  unsigned int Pulses;
  TMOD=0x25;
  TR0=0;
  TL0=0;
  TH0=0;
  TF0=0;
  Count=0;
  TimeStatus=2;
  Cas1ms=0;
  IE=0x8A;
  while(!Cas1ms) {};
  TR0=1;
  TimeStatus=1000;
  Cas1ms=0;
  while(!Cas1ms) {};
  TR0=0;
  IE=0x88;
  Frekvence=TL0|(TH0*0x100)|(Count*0x10000);
  if(Frekvence>=1000)
  {
    Frekvence*=1000;
    return;
  }
  TR0=0;
  TL0=0;
  TH0=0;
  TF0=0;
  TMOD=0x21;
  Count=0;
  Pulses=0;
  if(LoFrq)
  {
    while(LoFrq) {};
    TR0=1;
    IE=0x8A;
    while(!Count)
    {
      while(!LoFrq) {};
      while(LoFrq) {};
      Pulses++;
    }
    TR0=0;
  }
  else
  {
    while(!LoFrq) {};
    TR0=1;
    IE=0x8A;
    while(!Count)
    {
      while(LoFrq) {};
      while(!LoFrq) {};
      Pulses++;
    }
    TR0=0;
  }
  IE=0x88;
  Frekvence=(TL0|(TH0*0x100)|(Count*0x10000))-7;
  if(Pulses<10) Frekvence=(200000000*Pulses)/Frekvence;
  else if(Pulses<100)Frekvence=((20000000*Pulses)/Frekvence)*10;
  else Frekvence=((2000000*Pulses)/Frekvence)*100;
}

void Main()
{
  // Inicializace
  Frekvence=0;
  AktZnak=0;
  TMOD=0x25;      // Časovač jedna mód 2
  TH1=56;         // Frekvence 10 kHz
  TCON=0x40;
  Znak[0]=SegG;
  Znak[1]=SegG;
  Znak[2]=SegG;
  Znak[3]=SegG;
  Rad=4;
  IP=0x00;
  IE=0x88;			// Povolit přerušení od časovače 1
  while(1)
  {
    ZmerFrekvenci();
    NastavCislo();
  }
}





