//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// SSC32 4 bitu iejimu ispletimas  (3+3)  + 4  
// Kas suveike konkreciai, nes davikliai "persidengia",
// galima perpatikrinti su SSC32 roboto valdymo programa
// 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   //  kartais nesupranta
#define false 0   //  kartais 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 mdav1;    //
unsigned char mdav;
unsigned char mdav2=0b00001111;
unsigned char mdav3;
unsigned char idav;   //sroves davikliai
unsigned char Uzlaik; //timerio uzlaikymas
unsigned char davnr;
bit t1=0;  // taimeris 1   , jei =1 tai laiko tarpas praejo 
unsigned char tmp;
unsigned char  PORTBOLD;
unsigned char  kanalas;
unsigned char lygispr[]={5,10,15,25};    //adc suveikimo pradiniai lygiai  pagal konkrecius varikliu galingumus
unsigned char lygis[]={0,0,0,0};    //adc suveikimo lygiai  pagal konkrecius varikliu galingumus
unsigned int adcjautrumas;

// **************  Paprogramiu sarasas  *********************************************     
    static  void  delay_ns(unsigned char __count);
    void Uzlaikymas ();
    void adcnust();     //  infrared davikliu inicializacija
   void adcDavApkl();
   void Jautrumas();
   void adcSuveikes();     

//** 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;
    //  idav= 0x0F; 
    }                       
//##############################################################################################            
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=0xFF;
DDRD=0x00;
//****************  ADC  initialization
   adcnust();  //ADC nustatymas
    
 #asm("sei")
while (1)
 {  
      if (!t1)  {Uzlaikymas (); Jautrumas();  //taimerio reiksme      
         mdav= 0x0F; mdav3= 0x0F; mdav2= 0x0F; idav= 0x0F;                                           
         PORTB=0xFF;  }                    
                              
   tmp=(0xF0&(PINB));     //mech davikliu 0 apklausa                     
      if (((tmp)<0xF0)){    tmp=tmp>>4; mdav=(mdav&tmp)&0x0F;  }   
                                                                      
   tmp=(0x0F&(PIND));     //mech davikliu 2 apklausa                     
      if (((tmp)<0x0F)){  mdav2=(mdav2&tmp);}                                                    
                       
    tmp=(0xF0&(PIND));     //mech davikliu 3 apklausa                     
      if (((tmp)<0xF0)){   tmp=tmp>>4;  mdav3=(mdav3&tmp); }    
                                                               
     adcSuveikes();  //apkrovu tikrinimas 
    tmp= ((mdav)&(mdav2)&(mdav3))|0xF0; // 
   if  (((idav)<0x0F)){  tmp= ((idav)&(tmp)&(0b11110111))|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

//*********************  ADC inicializavimas ******************************
void adcnust (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
}         


//*********************  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

//*********************  IR davikliu apklausa ****************************************** 
void adcDavApkl(void)  //
{ADMUX=(ADC_VREF_TYPE & 20)|kanalas; //perjungiam i PC i-taji 
ADCSRA|=0x40;         //paleisti adc
while(ADC_complete!=1); //ar adc pabaige - laukiam
ADC_complete=0;		//numetam adc velevele

if (gADC_result>lygis[kanalas]){
//****kur virsyja srove****
 if (kanalas==0) idav= idav & 0b00001110;  
 if (kanalas==1) idav= idav & 0b00001101;  
 if (kanalas==2) idav= idav & 0b00001011;  
 if (kanalas==3) idav= idav & 0b00000111;  
 }
}

//*********************  adc jautrumas ******************************************
void Jautrumas (void)
{ADMUX=(ADC_VREF_TYPE & 20) | 04; //perjungiam adc i PC4
 ADCSRA|=0x40; 
while(ADC_complete!=1);
adcjautrumas=(gADC_result);// 
ADC_complete=0;		//numetam adc velevele
lygis[0]=lygispr[0]+adcjautrumas/128; //paskui reikes subalansuoti skaicius realiom apkrovom
lygis[1]=lygispr[1]+adcjautrumas/64; //paskui reikes subalabnuoti skaicius realiom apkrovom
lygis[2]=lygispr[2]+adcjautrumas/32 ; //paskui reikes subalansuoti skaicius realiom apkrovom
lygis[3]=lygispr[3]+ adcjautrumas/16; //paskui reikes subalansuoti skaicius realiom apkrovom
}

//********************* adc Suveikes **********************************************
void adcSuveikes (void)
 {
        davnr=0b00000001; kanalas=0;   
        adcDavApkl();
     if (! (idav) & (davnr))   ;          
        davnr=0b00000010; kanalas=1;           
        adcDavApkl();
     if (! (idav) & (davnr))   ;
       davnr=0b00000100;   kanalas =2;
        adcDavApkl();             
     if (! (idav) & (davnr))   ; 
        davnr=0b00001000; kanalas=3;  
        adcDavApkl();   
     if (! (idav) & (davnr))  ;                                                           
}


//*********************  Uzlaikymas ns 22vienetu~13us******************************************  
static  void  delay_ns(char __count)  
{#asm  volatile 
            ld r26,y;
 _zyme:     dec r26;
               nop;                
            brne  _zyme;   
#endasm              
__count=0;
}