/****************************************************************/
/*								*/
/* Pruefer - legt Prüfmuster an die Eingänge des GALs und	*/
/* gibt Auskunft über den Zustand der Ausänge			*/
/*								*/
/* compilieren: cc Pruefer.c					*/
/****************************************************************/


#include "intuition/intuition.h"
#include "GALer.h"


extern	int	pruef_mode;
extern	int	GALType;
extern	int	gal_type;
extern	int	outIC3;
extern	int	outIC4;
extern	int	outIC5;
extern	int	pinnameflag;
extern	int	num_of_pins;

extern	UBYTE	PinNames[24][10];

extern  struct	Window		*window;
extern	struct	Rastport	*rp;
extern	struct	Border		Border1;
extern	struct	Border		Border2;

extern	struct	Menu		Menu1;
extern	struct	Menu		MenuP;

extern	struct	Gadget		Gadget1;
extern	struct	Gadget		Gadget4;
extern	struct	Gadget		Gadget20;
extern	struct	Gadget		Gadget21;
extern	struct	Gadget		Gadget23;
extern	struct	Gadget		Gadget25;
extern	struct	Gadget		Gadget27;
extern	struct	Gadget		Gadget29;
extern	struct	Gadget		Gadget31;
extern	struct	Gadget		Gadget33;
extern	struct	Gadget		Gadget35;



struct	in_con	  { int IC16V8;
		    int Pin16V8;
	  	    int IC20V8;
		    int Pin20V8;
		    int EA;
		    int Pegel; };

struct	out_con	  { int IC16V8;
		    int Bit16V8;
		    int IC20V8;
		    int Bit20V8;
		    struct Gadget *Gad; };


/*Aufbau der nachfolgenden Struktur: 
 für GAL16V8:
 1. Eintrag: IC, das für den Zugriff auf den Pin mit der GadID zuständig ist
 2. Eintrag: Bit des ICs
 für GAL20V8:
 3. Eintrag: IC, das für den Zugriff auf den Pin mit der GadId zuständig ist
 4. Eintrag: Bit des ICs
 allgemein:
 5. Eintrag: Pin als Ein- bzw. Ausgang definiert
 6. Eintrag: wenn Pin Eingang ist, dann gibt dieser Eintrag den Pegel an
*/
struct in_con  in_bit[22] = { {IC4,0x04,IC4,0x04,EINGANG,LOW},
			      {IC4,0x08,IC4,0x08,EINGANG,LOW},
			      {IC4,0x10,IC4,0x10,EINGANG,LOW},
			      {IC4,0x20,IC4,0x20,EINGANG,LOW},
			      {IC4,0x40,IC4,0x40,EINGANG,LOW},
			      {IC4,0x80,IC4,0x80,EINGANG,LOW},
			      {IC5,0x01,IC5,0x01,EINGANG,LOW},
			      {IC5,0x02,IC5,0x02,EINGANG,LOW},
			      {IC5,0x04,IC5,0x04,EINGANG,LOW},
			      {IC5,0x08,IC5,0x08,EINGANG,LOW},
			      {IC4,0x00,IC4,0x01,EINGANG,LOW},
			      {IC3,0x00,IC3,0x80,EINGANG,LOW},
			      {IC4,0x00,IC4,0x02,EINGANG,LOW},
			      {IC5,0x00,IC5,0x10,EINGANG,LOW},
			      {IC5,0x10,IC5,0x20,AUSGANG,LOW},
			      {IC5,0x20,IC3,0x01,AUSGANG,LOW},
			      {IC3,0x01,IC3,0x02,AUSGANG,LOW},
			      {IC3,0x02,IC3,0x04,AUSGANG,LOW},
			      {IC3,0x04,IC3,0x08,AUSGANG,LOW},
			      {IC3,0x08,IC3,0x10,AUSGANG,LOW},
			      {IC3,0x10,IC3,0x20,AUSGANG,LOW},
			      {IC3,0x20,IC3,0x40,AUSGANG,LOW}  };


/*Aufbau der nachfolgenden Struktur: 
 für GAL16V8:
 1. Eintrag: IC, das den Pin mit der GadID ausliest
 2. Eintrag: Bit des ICs
 für GAL20V8:
 1. Eintrag: IC, das den Pin mit der GadID ausliest
 4. Eintrag: Bit des ICs
*/
struct out_con out_bit[8] = { {IC7,0x01,IC7,0x02,&Gadget35},
			      {IC7,0x02,IC7,0x04,&Gadget33},
			      {IC7,0x04,IC7,0x08,&Gadget31},
			      {IC7,0x08,IC7,0x10,&Gadget29},
			      {IC7,0x10,IC7,0x20,&Gadget27},
			      {IC7,0x20,IC7,0x40,&Gadget25},
			      {IC7,0x40,IC7,0x80,&Gadget23},
			      {IC7,0x80,IC6,0x01,&Gadget21}  };




Pruefer(gad,gadID)
struct	Gadget	*gad;
USHORT	gadID;
{
UBYTE	c;

 c=(UBYTE)*gad->GadgetText->IText;
					    /*Eingabe-Gadgets*/
 if ((gadID>=1)&&(gadID<=22)) {
   if (gad->GadgetRender!=(APTR)&Border2) {
     if (c=='L') {
       c='H';
       in_bit[gadID-1].Pegel=HIGH;
       SetPegel(gadID,HIGH);
      }
     else {
       c='L';
       in_bit[gadID-1].Pegel=LOW;
       SetPegel(gadID,LOW);
      }
    }
  }
					    /*Ein- u. Ausgabe-Gadgets (A/E)*/
 if ((gadID>=30)&&(gadID<=37)) {
   if (c=='A') {
     c='E';
     gad->NextGadget->GadgetRender=(APTR)&Border1;
     *gad->NextGadget->GadgetText->IText='L';
     SetPegel(gadID-16,LOW);
     in_bit[gadID-16].EA=EINGANG;
    }
   else {
     c='A';
     gad->NextGadget->GadgetRender=(APTR)&Border2;
     in_bit[gadID-16].EA=AUSGANG;
     SetPegel(gadID-16,LOW);
     CheckOutput();
    }
  }

 CheckOutput();

 *gad->GadgetText->IText=c;
 RefreshGList(gad->NextGadget,window,NULL,1L);
 RefreshGList(gad,window,NULL,1L);

}




/*setze den Pin mit der "gadID" auf "Pegel" (=HIGH oder LOW)*/
SetPegel(gadID,Pegel)
USHORT	gadID;
int	Pegel;
{
int	bits,ICnum,outIC;

 if (GALType==GAL16V8) {
   ICnum=in_bit[gadID-1].IC16V8;
   bits =in_bit[gadID-1].Pin16V8;
  }
 else {
   ICnum=in_bit[gadID-1].IC20V8;
   bits =in_bit[gadID-1].Pin20V8;
  }

 if (ICnum==IC3) outIC=outIC3;
 if (ICnum==IC4) outIC=outIC4;
 if (ICnum==IC5) outIC=outIC5;
 
 bits^=0xFF;				/*invertieren*/
 outIC&=bits;				/*Bit für Pin löschen*/
 if (Pegel==HIGH) {			/*falls HIGH-Pegel, Bit wieder setzen*/
   bits^=0xFF;
   outIC|=bits;
  }

 WriteByte(outIC,ICnum);		/*Pin auf Pegel setzen*/
}



/*Ausgänge auf HIGH, LOW, hochohmig (Z) prüfen
  Aufruf: Ausgänge müssen über ihre Widerstände auf LOW geschalten sein
*/
CheckOutput()
{
struct	Gadget	*gad;

int	n,in_bits,out_bits,pin_pegel,
	inICnum,outICnum,outIC,byte;


 for(n=14; n<=21; n++) {		/*mögliche Ausgänge:gadID15-22*/ 
   if (in_bit[n].EA==AUSGANG) {
     if (GALType==GAL16V8) {
       outICnum=in_bit[n].IC16V8;
       out_bits=in_bit[n].Pin16V8;
       inICnum =out_bit[n-14].IC16V8;
       in_bits =out_bit[n-14].Bit16V8;
      }
     else {
       outICnum=in_bit[n].IC20V8;
       out_bits=in_bit[n].Pin20V8;
       inICnum =out_bit[n-14].IC20V8;
       in_bits =out_bit[n-14].Bit20V8;
      }
     if (outICnum==IC3) outIC=outIC3;
     if (outICnum==IC4) outIC=outIC4;
     if (outICnum==IC5) outIC=outIC5;

     byte=ReadByte(inICnum);		/*Pegel der Ausgänge holen*/
     if (byte&in_bits) pin_pegel=HIGH;	/*Pegel des Pins "berechnen"*/
     else  pin_pegel=LOW;

     outIC|=out_bits;			/*Ausgang über Widerstand auf HIGH*/
     WriteByte(outIC,outICnum);

     byte=ReadByte(inICnum);		/*Pegel der Ausgänge holen*/

     gad=out_bit[n-14].Gad;
     if (pin_pegel!=(1&&(byte&in_bits))) {	/*Ausgang widerspricht nicht->Z*/
       *gad->GadgetText->IText='Z';
       RefreshGList(gad,window,NULL,1L);
      }
     else
       if (pin_pegel==LOW) {
         *gad->GadgetText->IText='L';
         RefreshGList(gad,window,NULL,1L);
        }
       else {
         *gad->GadgetText->IText='H';
         RefreshGList(gad,window,NULL,1L);
        }

     outIC&=(out_bits^0xFF);		/*Ausgang wieder auf "LOW schalten"*/
     WriteByte(outIC,outICnum);
    }
  }
}




/*Prüfer an- bzw. ausschalten*/
TogglePruefer()
{
int	n;
struct	Gadget	*gad;


 if (pruef_mode) {
   LED(OFF);
   DisableVcc();

   pruef_mode=OFF;				/*Prüfer verlassen*/
   gad=&Gadget4;				/*Gadget-Text initialisieren*/
   while(gad!=NULL) {
     if (*gad->GadgetText->IText=='E') {
       *gad->GadgetText->IText='A';
       gad->NextGadget->GadgetRender=(APTR)&Border2;
      }
     if (*gad->GadgetText->IText=='H') *gad->GadgetText->IText='L';
     if (*gad->GadgetText->IText=='Z') *gad->GadgetText->IText='L';
     gad=gad->NextGadget; }
  
   RefreshGList(&Gadget4,window,NULL,-1L);
   for (n=0; n<22; n++) {			/*in_bit initialisieren*/
      in_bit[n].Pegel=LOW;
      if (n>=14) in_bit[n].EA=AUSGANG;
     }
   MyRequest(INFO_REQ,(UBYTE *)"GAL kann wieder entfernt werden");
   ClearMenuStrip(window);
   SetMenuStrip(window,&Menu1);
 }
 else {
   if (MyRequest(ASK_REQ,(UBYTE *)"Bitte GAL einsetzen")) {
     LED(ON);
     EnableVcc();
     pruef_mode=ON;				/*Prüfer initialisieren*/
     CheckOutput();				/*Ausgänge untersuchen*/
     ClearMenuStrip(window);
     SetMenuStrip(window,&MenuP);
    }
  }
}




/*GAL zeichnen*/
DrawGAL(type)
int type;
{
int	pins,n,gadypos;
long	ypos,ic_hight;
char	pinnum[2];				/*Pin-Nummer in ASCII*/
struct	Gadget	*gad;


 ClearPinNames();

 SetAPen(rp,0L);
 RectFill(rp,240L,19L,400L,150L);
 SetAPen(rp,1L);

 if (window->FirstGadget==NULL)			/*Gadgetlist in Window*/
   window->FirstGadget=&Gadget4;

 if (type==GAL16V8) {
   RemoveGList(window,&Gadget1,4L);
   gad = &Gadget20;
   gadypos = 50;
   for (n=0; n<8; n++) {			/*y-Koord. für Ausgänge*/
     gad->TopEdge=gadypos;
     gad=gad->NextGadget;
     gad->TopEdge=gadypos;
     gad=gad->NextGadget;
     gadypos+=10; }
   pins=20;
   ypos=50L;
   ic_hight=100L; }
 else {
   gad = &Gadget20;
   gadypos = 40;
   for (n=0; n<8; n++) {			/*y-Koord. für Ausgänge*/
     gad->TopEdge=gadypos;
     gad=gad->NextGadget;
     gad->TopEdge=gadypos;
     gad=gad->NextGadget;
     gadypos+=10; }
   AddGList(window,&Gadget1,-1L);		/*Gadgets für Pin1,2,14,23*/
   pins=24;
   ypos=30L;
   ic_hight=120L; }

 RefreshGadgets(&Gadget4,window,NULL);

 Move(rp,280L,ypos-2L);				/*IC zeichnen*/
 Draw(rp,360L,ypos-2L);
 Draw(rp,360L,ypos+ic_hight);
 Draw(rp,280L,ypos+ic_hight);
 Draw(rp,280L,ypos-2L);

 Move(rp,312L,ypos-2L);				/*Markierung zeichnen*/
 Draw(rp,312L,ypos+3L);
 Draw(rp,326L,ypos+3L);
 Draw(rp,326L,ypos-2L);


 SetDrMd(rp,JAM1);				/*Pins zeichnen*/
 for(n=1; n<=pins; n++) {
   sprintf(&pinnum,"%2d",n);
   if (n<pins/2) {
     DrawLeftPin(280L,ypos);
     Move(rp,264L,ypos+7L);
     Text(rp,(UBYTE *)pinnum,2L);
     Move(rp,285L,ypos+7L);
     Text(rp,(UBYTE *)"E",1L);
     ypos+=10L; }
   if (n==pins/2) {
     DrawLeftPin(280L,ypos);
     Move(rp,264L,ypos+7L);
     Text(rp,(UBYTE *)pinnum,2L); }
   if (n>pins/2) {
     DrawRightPin(360L,ypos);
     Move(rp,361L,ypos+7L);
     Text(rp,(UBYTE *)pinnum,2L);
     if (n==pins/2+1) {
       Move(rp,348L,ypos+7L);
       Text(rp,(UBYTE *)"E",1L); }
     if ((n==14)&&(GALType==GAL20V8)) {
       Move(rp,348L,ypos+7L);
       Text(rp,(UBYTE *)"E",1L); }
     if ((n==23)&&(GALType==GAL20V8)) {
       Move(rp,348L,ypos+7L);
       Text(rp,(UBYTE *)"E",1L); }
     ypos-=10L; }
   }
 SetDrMd(rp,JAM2);

}


DrawLeftPin(x,y)
long x,y;
{
 Move(rp,x,y);
 Draw(rp,x-18L,y);
 Draw(rp,x-18L,y+8L);
 Draw(rp,x,y+8L);
}

DrawRightPin(x,y)
long x,y;
{
 Move(rp,x,y);
 Draw(rp,x+18L,y);
 Draw(rp,x+18L,y+8L);
 Draw(rp,x,y+8L);
}





/*Pinname an die Pins des GALs einstellen*/
PrintPinNames()
{
int	n;
long	ypos;

 if (pinnameflag) {				/*sind Pinnamen gültig?*/
   if (gal_type == GALType) {			/*stimmt der eing. GAL-Typ?*/
     ClearPinNames();
     if (GALType == GAL16V8)
       ypos = 50L;
     else
       ypos = 30L;

     for (n=1; n<=num_of_pins; n++) {
       if (n < num_of_pins/2) {
	 Move(rp,234L-8L*(long)strlen(&PinNames[n-1][0]),ypos+7L);
	 ypos += 10;
        }
       if (n == num_of_pins/2) {
	 Move(rp,234L-8L*(long)strlen(&PinNames[n-1][0]),ypos+7L);
        }
       if (n > num_of_pins/2) {
	 Move(rp,406L,ypos+7L);
	  ypos -= 10;
	 }
       Text(rp,&PinNames[n-1][0],(long)strlen(&PinNames[n-1][0]));
      }

    }
   else {
     ErrorReq(9);				/*falsches GAL eingestellt*/
    }
  }
 else {
   ErrorReq(7);					/*keine Pinnamen*/
  }
}


/*Pinnamen an den Pins des GALs löschen*/
ClearPinNames()
{
int	n;
long	ypos;

 ypos = 30L;

 for (n=1; n<=24; n++) {
   if (n < 24/2) {
     Move(rp,154L,ypos+7L);
     ypos += 10;
    }
   if (n == 24/2) {
     Move(rp,154L,ypos+7L);
    }
   if (n > 24/2) {
     Move(rp,406L,ypos+7L);
     ypos -= 10;
    }
   Text(rp,(UBYTE *)"          ",10L);
  }
}

