//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// eProDas arba SSC32 iejimu ispletimas (ROBOTO BUFERIAI)
// Kas suveike konkreciai, nes davikliai "persidengia",
// ivesti papildomi isvadai TSOP, MDAV, paprasti IR davikliai
// gali buti nenaudojami, yra TSOP.
// 
// Autorius: Arnoldas Cerniakovas 2012m, Kaunas
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

#include <mega8.h> //Prijungti mk Atmega8 biblioteka
#include <delay.h>
#include <stdlib.h>
#define ADC_VREF_TYPE 0x20   //  ar  0x40
#define true 1   //  kitaip nesupranta
#define false 0   //  kitaip nesupranta

bit ADC_complete;     //analogas-kodas keitiklio busena kai ADC_complete==1, skaitine reiksme gADC_result jau yra...
unsigned int gADC_result;      // analogas-kodas keitiklio reiksme   
unsigned char irdiodas;     //infraredo daviklio nr. irdiodas==0-PORTD.0=1dav. sv diodas, PORTD.1=2dav.., PORTD.2=3dav.., PORTD.3=4dav.. kartu su vieno variklio fazem
unsigned char irdav;    //infraredo darbinio rezimo busenos kint. (i kuria puse judeti)
unsigned char mdav;
unsigned char tsopdav=0b00001111;
unsigned char irjautrumas;    //infraredo jautrumo kint.
unsigned char irkartai=6;   // kiek kartu turejo pasitikrinti ta pati davikli buvo 3
unsigned char Uzlaik;        //timerio uzlaikymas
bit t1=0;  // taimeris 1   , jei =1 tai laiko tarpas praejo 
unsigned int i; //tipo FOR ciklams
unsigned int delta;     // IR daviklio kintamasis, nusakantis atstuma iki objekto
unsigned char davnr;
unsigned char tmp;
unsigned char  PORTBOLD;
unsigned char D1;   // 1 optinio davikliio suveikimo kartai
unsigned char D2;   // 2 optinio davikliio suveikimo kartai
unsigned char D3;   //  3 optinio davikliio suveikimo kartai
unsigned char D4;  //   4 optinio davikliio suveikimo kartai
// **************  Paprogramiu sarasas  *********************************************     
    static  void  delay_ns(unsigned char __count);
    void Jautrumas ();
    void Uzlaikymas ();
    void IRdavnust();     //  infrared davikliu inicializacija
    void IrDavApkl();  // infrared davikliu apklausa     
    void IrSuveikes();
    void Tsop();
//** Taimerio [1] perpildymo pertraukimas
interrupt [TIM1_OVF] void timer1_ovf_isr(void){  //interrupt [TIM0_OVF] void timer0_ovf_isr(void)   //~3.4sek,kai TCNT0=0xFF; cik_sk=100;

      TIMSK=0x00;
    t1=false;

    }                       
//##############################################################################################            
void main(void)
{// Declare your local variables here
//****************   Port B initialization
PORTB=0xFF;
DDRB=0x0F;
//****************   Port C initialization
PORTC=0x00;
DDRC=0x00;
//****************   Port D initialization
PORTD=0b10000000;
DDRD=0x01111111;
//****************  ADC  initialization
   IRdavnust();  //ADC nustatymas
    
   // irdav=0x0F;   mdav=0x0F;    pradines 
  DDRD.1 = 1;  DDRD.2 =1 ; DDRD.3 = 1;  DDRD.4 = 1; DDRD.5 = 1;  DDRD.6 = 1; //  kad veiktu -> reikejo pakartoti krypti konkreciai siuos isvadus 
 #asm("sei")
while (1)
 {  
      if ((!t1))  {              //jei taimeris nepaleistas
       if  (PORTBOLD==0xFF)  {         
         PORTD.4=0;     // numesti, jei buvo  suveike mech davikliai                 
         PORTD.5=0; // numesti, jei buvo  suveike TSOP davikliai
         }
         Uzlaikymas ();  //taimerio reiksme is adc     
         mdav= 0x0F; irdav= 0x0F; tsopdav= 0x0F;         
         D1=0; D2=0; D3=0; D4=0;           
         }  
                        
      
   if (!(PIND.5||PIND.4)||!t1){  Jautrumas (); IrSuveikes();  } //(!(PIND.5||PIND.4)||t1) jei nebuvo  suveike mech davikliai ir  TSOP davikliai
   // delay_ms(1);  //kas tsop-ai nereaguotu
   if (!PIND.4){ Tsop();}    // jei nebuvo  suveike mech davikliai
    tmp=(0xF0&(PINB));     //mech davikliu apklausa                        
                            
      if (((tmp)<0xF0)){   
             tmp=tmp>>4;
             mdav=(mdav&tmp)&0x0F;                           
            PORTD.4=1; // patvirtinam sitam pine, kad suveike mech davikliai  
            irdav=0x0F; tsopdav=0x0F; // mech dav didesbis prioritetas numetam kitus          
          }
                                                                          
               
      if (irdav!=0x0F) { //jei kazka daviklis pries tai pamate- skanuojam filtruojam
         irdav=0x0F;                         
        for (i=1; i <= 10; i=i+1)  { IrSuveikes(); } // ciklas 10 daviklio patikrinimu  
                                                                               
                if (D1>irkartai) {irdav= 0b00001110 & irdav;}        //jei > nei irkartai kartus nustatyta kliutis                         
                if (D2>irkartai) {irdav= 0b00001101 & irdav;}        //jei > nei  irkartai kartus nustatyta kliutis
                if (D3>irkartai){irdav= 0b00001011 & irdav;}         //jei > nei  irkartai kartus nustatyta kliutis
                if (D4>irkartai){irdav= 0b00000111 & irdav;}         //jei > nei  irkartai kartus nustatyta kliutis    
      }
          
    tmp= ((irdav)&(mdav)&(tsopdav))|0xF0; //   
       if  (tmp!=PORTBOLD) { TIMSK=0x00;  // 
        TCCR1A=0x00;TCCR1B=0x00;  TCNT1L=0x0F; TCNT1H=0x0F;
        ICR1L=0x00;ICR1H=0x00; OCR1AL=0x00;OCR1AH=0x00; OCR1BL=0x00; OCR1BH=0x00;
        delay_ns(10);  //  gal ir nereikia  to viso vircuj jei netesti dar karta uzlaikyno
        t1=true;TCNT1H=Uzlaik;   TCCR1B=0x04; TIMSK=0x04;}    // PORTD.6=t1;
                                                                                                                                                 
      PORTB =  tmp;
      PORTBOLD = tmp; 
        
 } //while pabaiga
}  //main pabaiga

//*********************  IR davikliu inicializavimas ******************************
void IRdavnust (void)
{ACSR=0x80; SFIOR=0x00;
ADMUX=ADC_VREF_TYPE & 20;//ADC Voltage Reference: AVCC pin
ADCSRA=0x8F;  // 8000000/64=>0x8F 0x8C buvo //gale trys bitai:101 tai ADC_F=F/16 , 110 tai ADC_F=F/32 , 111 tai ADC_F=F/64(предделитель, ст бит - разрешение или запрешен  8B originale)
}

//*********************  ADC pertraukimo aptarnavimas ****************************************** 
interrupt [ADC_INT] void adc_isr(void) //ADC pertraukimas
{unsigned int adc_data;
adc_data=ADCW;
gADC_result=adc_data; //ADC reiksme
ADC_complete=1;// nustatom veliavele
}         

//*********************  IR davikliu apklausa ****************************************** 
void IrDavApkl(void)  //
{ADMUX=(ADC_VREF_TYPE & 20)|irdiodas; //perjungiam i PC i-taji 
PORTD=davnr|PORTD|0b10000000;            //leidimas sviesos diodams
delay_us(100);        //laukiam pakol nusistoves svietimas
ADCSRA|=0x40;         //paleisti adc
while(ADC_complete!=1); //ar adc pabaige - laukiam
delta=gADC_result;
ADC_complete=0;		//numetam adc velevele
PORTD=0xF0&PORTD|0b10000000;		//isjungti IR LED
delay_us(10);     //laukiam pakol nusistoves ...
ADCSRA|=0x40;    //paleisti adc
while(ADC_complete!=1);  //ar adc pabaige
delta=abs(gADC_result-delta);//;   skirtumas  tarp apsviesto ir tamsaus IR led
ADC_complete=0;		//numetam adc velevele

if (delta>irjautrumas){
//****judejimo krypties priskyrimas nuo optiniu davikliu****

 if (irdiodas==0) irdav= irdav & 0b00001110;  
 if (irdiodas==1) irdav= irdav & 0b00001101;  
 if (irdiodas==2) irdav= irdav & 0b00001011;  
 if (irdiodas==3) irdav= irdav & 0b00000111;  
 }
}

//*********************  irjautrumas ******************************************
void Jautrumas (void)
{ADMUX=(ADC_VREF_TYPE & 20) | 04; //perjungiam adc i PC4
 ADCSRA|=0x40; 
while(ADC_complete!=1);
irjautrumas=(unsigned char)(gADC_result>>5);// 
ADC_complete=0;		//numetam adc velevele
}

//*********************  Uzlaikymas ******************************************
void Uzlaikymas (void)
{ADMUX=(ADC_VREF_TYPE & 20)|05; //perjungiam adc i PA5
ADCSRA|=0x40;
while(ADC_complete!=1);
Uzlaik=(unsigned char)((gADC_result>>2));//
ADC_complete=0;	}	//numetam adc velevele
//********************* Filtras **********************************************
void IrSuveikes (void)
 {      davnr=0b00000001; irdiodas=0;
        IrDavApkl();
     if (! (irdav) & (davnr))  D1=D1+1  ;          
        davnr=0b00000010; irdiodas=1;           
        IrDavApkl();
     if (! (irdav) & (davnr))  D2=D2+1  ;
        davnr=0b00000100;   irdiodas=2;
        IrDavApkl();             
     if (! (irdav) & (davnr))  D3=D3+1  ; 
        davnr=0b00001000; irdiodas=3;  
        IrDavApkl();   
     if (! (irdav) & (davnr))  D4=D4+1  ;                                                           
}
//*********************  TSOP apklausa ******************************************
 void Tsop(void)
 {  delay_ms(1);  tmp=0;   
    // ciklas 30 siuntimu i TSOP-a 36KHz   priekis 1 dav  
   for (i=1; i <= 30; i=i+1)
    {    PORTD.0=1; // uzdegam priekini 1dav 
        #asm("nop");
        delay_ns(22);    //reikia 13.89 us  prie 22 ir 19 36585Hz
      if (!PIND.7) {  tmp=tmp+1; } //pakabinti abudu TSOP-ai ant vieno iejimo !!!!                           
        PORTD.0=0; //PORTD.1=0; gesinam priekinius PORTD.2=1; PORTD.3=1; 
        delay_ns(19); #asm("nop");} 
             
     if (tmp>15){tsopdav= 0b00001110&tsopdav;  irdav= 0x0F; PORTD.5=1;}                       
       
                                          
       delay_ms(1);   tmp=0;       
     // ciklas 30 siuntimu i TSOP-a 36KHz   priekis    2 dav
   for (i=1; i <= 30; i=i+1) 
    {PORTD.1=1; //PORTD.1=1; uzdegam priekinius PORTD.2=1; PORTD.3=1; 
         #asm("nop"); delay_ns(22);
      if (!PIND.7) { tmp=tmp+1; } //pakabinti abudu TSOP-ai ant vieno iejimo                   
         PORTD.1=0; //PORTD.1=0; gesinam priekinius PORTD.2=1; PORTD.3=1; 
        delay_ns(19);  #asm("nop");} 
           
       if (tmp>15) { tsopdav= 0b00001101&tsopdav;   irdav= 0x0F;  PORTD.5=1;}                       
          
                                     
      delay_ms(1);  tmp=0;    
     // ciklas 30 siuntimu i TSOP-a 38KHz    galas 1 dav
     for (i=1; i <= 30; i=i+1) 
      {  PORTD.2=1; //PORTD.3=1; uzdegam galinius PORTD.2=1; PORTD.3=1; 
        delay_ns(21);         //reikia 13.16 us
       if (!PIND.7) {  tmp=tmp+1;  } //pakabinti abudu TSOP-ai ant vieno iejimo
         PORTD.2=0; //PORTD.3=0; gesinam galinius PORTD.2=1; PORTD.3=1; 
         delay_ns(18); }       
  
       if (tmp>15) {tsopdav=  0b00001011&tsopdav;  irdav= 0x0F;PORTD.5=1;}            
         
                                       
        delay_ms(1);  tmp=0;
     // ciklas 30 siuntimu i TSOP-a 38KHz    galas 2 dav
    for (i=1; i <= 30; i=i+1) 
     {  PORTD.3=1; //PORTD.2=1; uzdegam galinius PORTD.2=1; PORTD.3=1; 
        delay_ns(21);  //37975Hz 21 ir 18
       if (!PIND.7) { tmp=tmp+1;} //pakabinti abudu TSOP-ai ant vieno iejimo           
         PORTD.3=0; // PORTD.2=0;gesinam galinius PORTD.2=1; PORTD.3=1; 
        delay_ns(18);}
           
       if (tmp>15) {tsopdav=  0b00000111&tsopdav;  irdav= 0x0F;PORTD.5=1;}            
                  
 }
//*********************  Uzlaikymas ns 22vienetu~13us******************************************  
static  void  delay_ns(char __count)  
{#asm  volatile 
            ld r26,y;
 _zyme:     dec r26;
               nop;                
            brne  _zyme;   
#endasm              
__count=0;
}