#include <mega16.h>
#include <Delay.h>

//definice GPIB bitů
#define SRQout PORTC.7	// Service Request
#define SRQin PINC.7
#define ATNout PORTC.6	// Attention
#define ATNin PINC.6
#define EOIout PORTC.5	// End Or Identity
#define EOIin PINC.5
#define DAVout PORTC.4	// Data Valid
#define DAVin PINC.4
#define NRFDout PORTC.3	// Not Ready For Data
#define NRFDin PINC.3
#define NDACout PORTC.2	// Not Data Accepted
#define NDACin PINC.2
#define IFCout PORTC.1 	// Interface Clear
#define IFCin PINC.1
#define RENout PORTC.0	// Remote Enable
#define RENin PINC.0

//definice GPIB interface
#define TE PORTB.0
#define PE PORTB.3
#define DC PORTB.1
#define SC PORTB.2

//pomocné definice
#define H 1
#define L 0
#define ADRESA_POSLUCHAC 0x27	//X0100111
#define ADRESA_MLUVCI 0x47	//X1000111
#define NEPOSLOUCHEJ 0x3F	//X0111111
#define NEMLUV 0x5F		//X1011111
#define SPE 0x18		//X0011000
#define SPD 0x19		//X0011001
#define PPC 0x05		//X0000101
#define PPU 0x15		//X0010101
#define PPE 0x60		//X110Ippp

void NastavVysilac(void)// nastavení parametrů pro vysílání dat
{
	TE = H;
	PE = H;
	DC = L;
	SC = H;
	DDRA=0xFF;	//PORT A jako výstupní
	DDRC=0x73;	//01110011 - nastavení vybraných pinů zda jsou výst. nebo vst.
}

void NastavPrijimac(void)// nastavení parametrů pro příjem dat
{
	TE = L;
	PE = H;
	DC = H;
	SC = L;
	DDRA=0x00;	//PORT A jako vstupni
	DDRC=0x8C;	//10001100 - nastavení vybraných pinů zda jsou výst. nebo vst.
}

int prijmi(void)		//funkce pro přijetí dat z GPIB
{
	int data_prijate;
		
        NDACout = L;
        NRFDout = H;		//připraven přijmout data
	
	while (DAVin)		//čekej, dokud nebudou data validní (DAV=L)	
	{	
		if (DAVin==L) {break;}
	}
	 
	NRFDout = L;
	data_prijate =~ PINA;	
	
	NDACout = H;		//přijal data
	while (!DAVin)		//DAVin = L
	{	
		if (DAVin==H) {break;}
	}
	
	NDACout = L;       	//mohu přijímat další
	
	return data_prijate;

}

int vysli(int data_vyslane)	//funkce pro odeslání dat na GPIB
{
	NastavVysilac();
	ATNout = H;
	IFCout = H;
	DAVout = H;
	
	while(NDACin && NRFDin) {}	//čeká na posluchače
	PORTA =~ data_vyslane;
	
	while (!NRFDin)	       		//testujeme, jeli NRFD v high 
	{	
		
		if (NRFDin==H) {break;}
	}
	
	DAVout = L;
	
	while (!NDACin)			//testujeme, jeli NDAC v high
	{	
		
		if (NDACin==H) {break;}
	}
	
	DAVout = H;
	//ATNout=1; 
		
	return 0;	
}

void OtocVpravo(int krok)	//funkce pro otočení krokového motoru o stanovený počet kroků
{     
	int i;
   	PORTD.4=1;	//ENB
      	PORTD.7=1;	//RESET
      	PORTD.6=1;	//smer
      	PORTD.0=1;	//signalizace
      	for (i=0; i<=krok; i++)
      	{
      		delay_ms(30);
      		PORTD.5=1;
      		delay_ms(30);
      		PORTD.5=0; 
	}
	PORTD.0=0;	//signalizace
}

void OtocVlevo(int krok)	//funkce pro otočení krokového motoru o stanovený počet kroků
{     
	int i;
   	PORTD.4=1;	//ENB
      	PORTD.7=1;	//RESET
      	PORTD.6=0;	//smer
      	PORTD.0=1;	//signalizace
      	for (i=0; i<=krok; i++)
      	{
      		delay_ms(30);
      		PORTD.5=1;
      		delay_ms(30);
      		PORTD.5=0; 
	}
	PORTD.0=0;	//signalizace
}



//--------------------HLAVNI PROGRAM---------------------
void main(void)
{

//potřebné proměnné
int adresa;
int SRQ_flag =0;
int stavovy_registr = 0x40;
int dataa;
int flag_mluvci = 0;
int flag_posluchac = 0;
int flag_r = 0;
cislo_rozsahu = 0;

//proměnné paralel pool
int PP_linka = 0x01;
int adresa_PP;
int PP_flag = 0;

//inicializace portů jako vstupní(přijímací, high Z)
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;

//inicializace pinů portu D jako výstupní;
DDRD=0xFF;


// inicializace funkcí procesoru
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
TCCR2=0x00;
ASSR=0x00;
TCNT2=0x00;
OCR2=0x00;
GICR=0x00;
MCUCR=0x00;
MCUCSR=0x00;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;

//implicitni nastaveni jako prijimac
NRFDout = L;
NDACout = L;
NastavPrijimac();
// má adresa je 7: 00111

while (1)
      {
      NastavPrijimac();
      delay_ms(2);	//zpoždění, kvůli pomalé změně ATN a EOI
      
      if (ATNin == L && EOIin == H)	//ATN je v 1 a EOI je v 0 - přišla adresa, nebo vícevodičová zpráva
      {
      	adresa = prijmi();
      	if (adresa == 0x55) {goto konec;}	//X1010101
      	adresa = adresa & 0x7F;			//maskování kvůli nevyužívanému 8 bitu
      	adresa_PP = adresa & 0x70;		//maskování kvůli PP
      	      	
      	if (adresa == ADRESA_POSLUCHAC)
      	{
      		flag_posluchac = 1;
      		flag_mluvci = 0;
      		goto konec;
     	}
     	if (adresa == ADRESA_MLUVCI)
      	{       
      		if (SRQ_flag == 1)
      		{
      			vysli(stavovy_registr);
     			
      		}
      		else 
      		{
      			flag_mluvci = 1;
      			flag_posluchac = 0;
      			goto konec;
       		}
     	}
     	if (adresa == NEPOSLOUCHEJ)
      	{
 		flag_posluchac = 0;
 		goto konec;
     	}
     	if (adresa == NEMLUV)
      	{
		flag_mluvci = 0;
		goto konec;
     	}
     	if (adresa == SPE)
     	{
     		
     		SRQ_flag = 1;
	}
     	if (adresa == SPD)
     	{       
     		SRQout =~ 0;
     		SRQ_flag = 0;
	}
     	if (adresa == PPC)
     	{       
     		PP_flag = 1;
	}
     	if (adresa == PPU)
     	{       
     		PP_flag = 0;
     	}
     	if (adresa_PP == PPE && PP_flag == 1)
     	{
     		PP_linka = adresa & 0x07 ;
     	}
      }

      if (ATNin == H && flag_posluchac == 1) //data
      { 
      	flag_mluvci = 0;
      	dataa = prijmi();
     	if (dataa == 0x0A) {goto konec; flag_posluchac = 0;}	//LF 1010
     	if (dataa == 0x61) {OtocVpravo(50);}
     	if (dataa == 0x62) {OtocVlevo(50);}
     	if (dataa == 0x52) {flag_r=1;}
     	if (dataa == 0x72) {flag_r=1;}
     	if (dataa == 0x31) {cislo_rozsahu=1;}
     	if (dataa == 0x32) {cislo_rozsahu=2;}
     	if (dataa == 0x33) {cislo_rozsahu=3;}
     	if (dataa == 0x34) {cislo_rozsahu=4;}
     	if (dataa == 0x35) {cislo_rozsahu=5;}
     	if (dataa == 0x36) {cislo_rozsahu=6;}
     	if (dataa == 0x37) {cislo_rozsahu=7;}
     	if (dataa == 0x38) {cislo_rozsahu=8;}		
      }
      
      if (ATNin == H && flag_mluvci == 1) //data
      { 
      	flag_posluchac = 0;
      	NastavVysilac();
      	vysli(0x62);

      }
      
      if (flag_r == 1)	//přepnutí rozsahu
      {
      	if (cislo_rozsahu == 1)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 2)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 3)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 4)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 5)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 6)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 7)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      	if (cislo_rozsahu == 8)	{}//zde příjde zdrojový kód natočení v závislosti na výstupu snímačů
      }
		
      if (ATNin == L && EOIin == L) //parallel pool
      {
      	PORTA =~ PP_linka;
      }			
          
      if (IFCin == L)		//interface clear
      {
      	flag_mluvci = 0;
      	flag_posluchac = 0;
      	SRQ_flag = 0;   	
      }
      
konec: 
    
      }
}
