/****************************************************************/
/*								*/
/* GAL.c - routines for reading and programming GALs		*/
/*								*/
/* 								*/
/****************************************************************/



#include <exec/types.h>
#include <intuition/intuition.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include <libraries/reqtools.h>
#include <proto/locale.h>
#include <proto/reqtools.h>

#include "GALer.h"
#include "Localize.h"



extern	struct AppString { LONG   as_ID;
		 	   STRPTR as_Str;
			 };

extern	struct AppString AppStrings[];

extern	char	path[];
extern	int	GALType, JedecSecurity, JedecGALType;
extern	struct	JedecStruct	Jedec;
extern	struct	Configuration	Config;
extern	struct	Catalog		*catalog;


int	MaxFuseAdr, SigAdr, RowSize, XORSize;

extern	long	prog_time, bulk_time;

struct	JedecStruct	Jedec2;


UBYTE	SignatureTxt[] = "Signature: $00 $00 $00 $00 $00 $00 $00 $00  :  XXXXXXXX";
UBYTE	PTTxt[]        = "PT: 0000000000000000000000000000000000000000000000000000000000000000";
UBYTE	ConTxt[]       = "XOR(n): 00000000    SYN: 0    AC0: 0";
UBYTE	AC1Txt[]       = "AC1(n): 00000000";
UBYTE   XOR10Txt[]     = "XOR(n): 0000000000";
UBYTE   SYN10Txt[]     = "SYN(n): 0000000000";


UBYTE *CmpText1, *CmpText2, *CmpText3, *CmpText4;




/*ProgramGAL
  read JEDEC file and program a GAL
  Syntax: ProgramGAL();
*/
void ProgramGAL(void)
{

  if (MyRequest(GALTYPE_REQ, AppStrings[MSG_GAL_PROG].as_Str)) {

    if (MyFileReq(AppStrings[MSG_LOADJED].as_Str, ".jed", YES, LOAD)) {

      if (!(GetJedec((UBYTE *)&path[0]))) {

        if (GALType != JedecGALType) {		/*überprüfen, ob der einge-*/
	  JedecError(25, NO);			/*stellte GAL-Typ zum Jedec-*/
	  return;				/*File paßt*/
        }

        if (ReadGALParameter(YES))		/*GAL-Parameter holen*/
	  return;				/*bei Fehler return*/

        if (!ProgJedecToGAL(PROGGAL)) {

	  if (JedecSecurity)			/*war im Jedec-File das Sec.*/
	    SetSecurity(NO);			/*gesetzt? */ 

	  MyRequest(INFO_REQ, AppStrings[MSG_GALPROGED].as_Str);
        }
        else
	  return;
      }
    }
  }
}



/* GAL kopieren
*/
void CopyGAL(void)
{
int	flag;

 if (MyRequest(GALTYPE_REQ, AppStrings[MSG_COPY_GAL].as_Str)) {

   if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
     return;					/*bei Fehler return*/

   PrintText(AppStrings[MSG_READING_GAL].as_Str, 1);

   ReadGALToJedec();

   PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);


   flag = 0;

   for (;;) {

     if (flag)
       if (!MyRequest(CONT_REQ, AppStrings[MSG_COPY_AGAIN].as_Str))
         break;

     flag = 1;

     MyRequest(INFO_REQ, AppStrings[MSG_INS_DEST_GAL].as_Str);
     if (!ReadGALParameter(YES))		/*GAL-Parameter holen*/
       ProgJedecToGAL(COPYGAL);			/*kein Fehler, dann prog.*/

   }
 }
}



/* überprüfe, ob GAL leer ist*/
void Leertest(void)
{
int result;

 if (MyRequest(GALTYPE_REQ, AppStrings[MSG_BLANK_TEST].as_Str)) {
   if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
     return;					/*bei Fehler return*/

   PrintText(AppStrings[MSG_EXE_BLANK_TEST].as_Str ,1);

   result = CheckGAL();

   PrintText(AppStrings[MSG_READY].as_Str, 0);

   if (result)
     MyRequest(INFO_REQ, AppStrings[MSG_NOT_BLANK].as_Str);
   else
     MyRequest(INFO_REQ, AppStrings[MSG_BLANK].as_Str);
  }
}




/* CheckGAL:   teste ob GAL leer ist
   Vor dem Aufruf von dieser Routine sollten mit ReadGALParameter(YES) die
   GAL-Parameter erfolgreich gelesen worden sein.
   Aufruf:   return=CheckGAL();
   Ergebnis: return = 0 : GAL ist leer
		      1 : Logik-Matrix ist nicht leer
		      2 : Logik-Matrix ist leer, aber Rest nicht
*/
int CheckGAL(void)
{
int	n, row;


 LED(ON);
 EditMode(VERIFY);				/*GAL in Verify-Mode*/

				    /*** Logik-Matrix lesen ***/
 for (row = 0; row <= MaxFuseAdr; row++) {

   SetRow(row);				/*Adresse anlegen*/
   STRImpuls(VERIFY_TIME);		/*Bits ins Schieberegister holen*/

   for (n = 0; n < RowSize; n++) {	/*seriell auslesen*/

     if (!SDOut()) {				/*SDOut-Ausgang lesen*/
       ExitEditMode();
       return(1);
     }

     Clock();					/*nächstes Bit an SDOut holen*/
   }
 }


 SetRow(SigAdr);	 		/*** Signatur auslesen ***/
 STRImpuls(VERIFY_TIME);

 for (n = 0; n < SIG_SIZE; n++) {

    if (!SDOut()) {
      ExitEditMode();
      return(2);
    }

    Clock();
  }
 

				        /*** ACW holen ***/
 if ((GALType == GAL16V8) || (GALType == GAL20V8)) {
   SetRow(ACW_ADR);				/*ACW adressieren*/
   STRImpuls(VERIFY_TIME);			/*Bits ins Schieberegister*/

   for (n = 0; n < ACW_SIZE; n++) {

     if (!SDOut()) {
       ExitEditMode();
       return(2);
     }

     Clock();

   }

 }
					/*** GAL22V10 ***/

 if (GALType == GAL22V10) {
   SetARCH(1);					/*ACW adressieren */
   STRImpuls(VERIFY_TIME);			/*Bits ins Schieberegister*/
   
   for (n = 0; n < 20; n++) {
     if (!SDOut()) {
       ExitEditMode();
       return(2);
     }
     Clock();
   }

 }

					/*** GAL20RA10 ***/
 if (GALType == GAL20RA10) {
   SetARCH(1);					/*ACW adressieren */
   STRImpuls(VERIFY_TIME);			/*Bits ins Schieberegister*/

   for (n = 0; n < 10; n++) {
     if (!SDOut()) {
       ExitEditMode();
       return(2);
     }
     Clock();
   }

 }


 ExitEditMode();
 return(0);					/*GAL ist leer*/
}






/*testen, ob Sicherungsbit gesetzt ist
  Das geht so (hoffe ich zumindest): Die Funktion CheckGAL gibt eine 0
  zurück, wenn das GAL leer ist; eine 1, wenn in der Logik-Matrix eine
  0 vorkommt und eine 2, wenn erst im ACW oder in der Signatur eine 0 vor-
  kommt. Wenn in der Logik-Matrix eine 0 vorkommt, kann das Security-Bit
  nicht gesetzt sein. Wenn in der Logik-Matrix nur 1 vorkommt und der Rest
  (Signatur...), der ja auch bei gesetztem Bit ausgelesen werden kann,
  eine 0 enthält, folgt daraus, daß das Secruity-Bit gesetzt ist.
*/
void TestSecurity(void)
{
int result;

 if (MyRequest(GALTYPE_REQ, AppStrings[MSG_SEC_TEST].as_Str)) {

   if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
     return;					/*bei Fehler return*/

   result = CheckGAL();

   if (result == 2)
     MyRequest(INFO_REQ, AppStrings[MSG_SEC_SET].as_Str);
   else
     if (result == 1)
       MyRequest(INFO_REQ, AppStrings[MSG_SEC_NOT_SET].as_Str);
     else
       MyRequest(INFO_REQ, AppStrings[MSG_BLANK].as_Str);
  }
}







/* Compare:  führt Vergleich durch zwischen GAL-GAL, GAL-Jedec, Jedec-GAL
   Aufruf:	 Compare();
   Ergebnis:	 ---
*/
void Compare(void)
{
int	n, row, cmptype, execute;
int	logic, acw, signature;
UBYTE	*text;


 if (!(cmptype = (int)rtEZRequestTags(AppStrings[MSG_CMPTYPE].as_Str,
				AppStrings[MSG_CMPS].as_Str, NULL, NULL,
				RT_ReqPos, REQPOS_CENTERSCR, TAG_END)))
   return;					/* Abbruch => zurück */


 if (cmptype == 1)					/*GAL mit GAL*/
   if (!MyRequest(GALTYPE_REQ, AppStrings[MSG_CMP_GALGAL].as_Str))
     return;

 if (cmptype == 2)					/*GAL mit Jedec*/
   if (!MyRequest(GALTYPE_REQ, AppStrings[MSG_CMP_GALJED].as_Str))
     return;

 if ((cmptype == 3) && (Config.GALTypeReq))		/*Jedec mit GAL*/
   if (!MyRequest(GALTYPE_REQ, AppStrings[MSG_CMP_JEDGAL].as_Str))
     return;



 if ((cmptype == 1) || (cmptype == 2)) {

   if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
     return;					/*bei Fehler return*/

   PrintText(AppStrings[MSG_READING_GAL].as_Str ,1);

   ReadGALToJedec();				/*Jedec-Struktur erstellen*/

   PrintText(AppStrings[MSG_LOWER_OK].as_Str ,0);
 }

 if (cmptype == 3) {

   if (MyFileReq(AppStrings[MSG_LOADJED].as_Str, ".jed", YES, LOAD)) {

     if (GetJedec((UBYTE *)&path[0]))		/*Jedec-File in Struktur*/
       return;

     if (GALType != JedecGALType) {		/*überprüfen, ob der einge-*/
       JedecError(25,NO);			/*stellte GAL-Typ zum Jedec-*/
       return;					/*File paßt*/
     }

   }
   else
     return;
 }


 for (n = 0; n < sizeof(Jedec2); n++)		/*Jedec-Struktur sichern*/
   Jedec2.GALLogic[n] = Jedec.GALLogic[n];


 for (;;) {

   execute = 1;

   if ((cmptype == 1) || (cmptype == 3)) {

     MyRequest(INFO_REQ, AppStrings[MSG_GAL_TO_CMP].as_Str);

     if (!ReadGALParameter(YES)) {		/*GAL-Parameter holen*/
       PrintText(AppStrings[MSG_READING_GAL].as_Str, 1);	/*o.k.? dann weiter*/

       ReadGALToJedec();

       PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);
     }
     else
       execute = 0;
   }


   if (cmptype == 2) {

     if (MyFileReq(AppStrings[MSG_LOADJED].as_Str, ".jed", YES, LOAD)) {

       if (GetJedec((UBYTE *)&path[0]))		/*Jedec-File in Struktur*/
	 execute = 0;

       if (GALType != JedecGALType) {		/*überprüfen, ob der einge-*/
	 JedecError(25,NO);			/*stellte GAL-Typ zum Jedec-*/
	 execute = 0;
       }

     }
     else
       execute = 0;
   }


   if (execute) {			/*** Compare ausführen ***/
     logic = acw = signature = 1;

						/*Logik-Matrizen vergleichen*/
     for (row = 0; row <= MaxFuseAdr; row++) {

       for (n = 0; n < RowSize; n++) {

         if (Jedec.GALLogic[row+(MaxFuseAdr+1)*n] != Jedec2.GALLogic[row+(MaxFuseAdr+1)*n]) {
	   logic = 0;
         }

         if (!logic) break;
       }

       if (!logic) break;
     }

						/* Signatur vergleichen */
     for (n = 0; n < SIG_SIZE; n++) {
       if (Jedec.GALSig[n] != Jedec2.GALSig[n])
	 signature = 0;
     }

						/* ACW vergleichen */
     if ((GALType == GAL16V8) || (GALType == GAL20V8)) {

       if (Jedec.GALSYN != Jedec2.GALSYN)
	 acw = 0;

       if (Jedec.GALAC0 != Jedec2.GALAC0)
	 acw = 0;

       for (n = 0; n < 8; n++)
	 if (Jedec.GALXOR[n] != Jedec2.GALXOR[n])
	   acw = 0;

       for (n = 0; n < 8; n++)
	 if (Jedec.GALAC1[n] != Jedec2.GALAC1[n])
	   acw = 0;

       for (n = 0; n < PT_SIZE; n++)
	 if (Jedec.GALPT[n] != Jedec2.GALPT[n])
	   acw = 0;

     }
     else {

       for (n = 0; n < 10; n++)
	 if (Jedec.GALXOR[n] != Jedec2.GALXOR[n])
	   acw = 0;

       if (GALType == GAL22V10)
	 for (n = 0; n < 10; n++)
	   if (Jedec.GALS1[n] != Jedec2.GALS1[n])
	     acw = 0;

     }

				/*** Ergebnis des Vergleichs ausgeben ***/

     if (logic && acw && signature)		/*völlig identisch?*/
       text = CmpText1;

     if (!logic || !acw)			/*NICHT identisch?*/
       text = CmpText2;

     if (logic && acw && !signature)		/*bis auf Sig. identisch?*/
       text = CmpText3;
   }
   else
     text = CmpText4;				/*Vergleich abgebrochen*/


   if (!MyRequest(CONT_REQ, text))
     return;					
 
 }
}




/****************************************************************/
/* Die nachfolgenden Routinen greifen direkt über das Modul	*/
/* "port.asm" auf das GAL zu.					*/
/****************************************************************/

/* PrintACW
   gibt das Architecture Control Word aus
   Aufruf: PrintACW
*/
void PrintACW(void)
{
BYTE	bit;
int	n, acw_num, xor_num, ac1_num ;

 acw_num = xor_num = ac1_num =0;

 if (MyRequest(GALTYPE_REQ, AppStrings[MSG_READ_ACW].as_Str)) {

   if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
     return;					/*bei Fehler return*/

   LED(ON);					/*LED anschalten*/
   EditMode(VERIFY);				/*GAL in Edit-Mode versetzen*/

					/*** 16V8, 20V8 ***/
   if ((GALType == GAL16V8) || (GALType == GAL20V8)) {

     SetRow(ACW_ADR);				/*ACW adressieren*/
     STRImpuls(VERIFY_TIME);			/*ACW ins Schiebereg. holen*/

     for (n = 0; n < ACW_SIZE; n++) {		/*ACW einlesen*/

       bit = (BYTE)SDOut();
       Clock();

					/*Standard-Typ (kein A-Typ)*/
       if (!GALAType()) {

	 if (n < 32) {				/*PT0-31 eintragen*/
           PTTxt[4+acw_num]=bit+'0';
	   acw_num++;
	 }

 	 if (n >= 50) {				/*PT32-63 eintragen*/
           PTTxt[4+acw_num]=bit+'0';
	   acw_num++;
	 }

	 if (n == 36) 				/*AC0-Bit*/
	   ConTxt[35]=bit+'0';

	 if (n == 45) 				/*SYN-Bit*/
	   ConTxt[25]=bit+'0';

	 if ((n >= 32) && (n <= 35)) { 		/*4 XOR-Bits*/
	   ConTxt[8+xor_num]=bit+'0';
	   xor_num++;
	 }

	 if ((n >= 46) && (n <= 49)) { 		/*4 XOR-Bits*/
	   ConTxt[8+xor_num]=bit+'0';
	   xor_num++;
	 }

	 if ((n >= 37) && (n <= 44)) {		/*AC1-Bits*/
	   AC1Txt[8+ac1_num]=bit+'0';
	   ac1_num++;
	 }

       }
       else {				/*A-Typ*/

	 if ((n >= 9) && (n <= 72)) {		/*PT0-63 eintragen*/
           PTTxt[4+acw_num]=bit+'0';
	   acw_num++;
	 }

	 if (n == 36) 				/*AC0-Bit*/
	   ConTxt[35]=bit+'0';

	 if (n == 77) 				/*SYN-Bit*/
	   ConTxt[25]=bit+'0';

	 if (n <= 3) { 				/*XOR-Bits*/
	   ConTxt[8+xor_num]=bit+'0';
	   xor_num++;
	 }

	 if (n >= 78) {	 			/*XOR-Bits*/
	   ConTxt[8+xor_num]=bit+'0';
	   xor_num++;
	 }

	 if ((n >= 5) && (n <= 8)) {		/*AC1-Bits*/
	   AC1Txt[8+ac1_num]=bit+'0';
	   ac1_num++;
	 }

	 if ((n >= 73) && (n <= 76)) {		/*AC1-Bits*/
	   AC1Txt[8+ac1_num]=bit+'0';
	   ac1_num++;
         }
       }
     }

     PrintText((UBYTE *)&PTTxt[0], 1);
     PrintText((UBYTE *)&ConTxt[0], 1);
     PrintText((UBYTE *)&AC1Txt[0], 1);
   }


				/*** GAL22V10 ***/
   if (GALType == GAL22V10) {
     SetARCH(1);			/*Architecture-Control-Word */
     STRImpuls(VERIFY_TIME);		/*ACW ins Schiebereg. holen*/

     for (n = 0; n < 10; n++) {
       SYN10Txt[8 + n] = SDOut() + '0';		/* S1 holen */
       Clock();

       XOR10Txt[8 + n] = SDOut() + '0';		/* XORs holen */
       Clock();
     }

     PrintText((UBYTE *)&XOR10Txt[0], 1);
     PrintText((UBYTE *)&SYN10Txt[0], 1);
   }


				/*** GAL20RA10 ***/
   if (GALType == GAL20RA10) {
     SetARCH(1);			/*Architecture-Control-Word */
     STRImpuls(VERIFY_TIME);		/*ACW ins Schiebereg. holen*/

     for (n = 0; n < 10; n++) {
       XOR10Txt[8 + n] = SDOut() + '0';		/* XORs holen */
       Clock();
     }

     PrintText((UBYTE *)&XOR10Txt[0], 1);
   }


   ExitEditMode();

  }
}



/* PrintSignature
   gibt Signatur im Textfeld aus
   Aufruf: PrintSignature();
*/
void PrintSignature(void)
{
UBYTE	strn[6];
BYTE	byte;
int	n;

 if (MyRequest(GALTYPE_REQ, AppStrings[MSG_READ_SIG].as_Str)) {

   if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
     return;					/*bei Fehler return*/

   LED(ON);					/*LED anschalten*/

   EditMode(VERIFY);				/*GAL in Edit-Mode versetzen*/

   SetRow(SigAdr);				/*Signatur adressieren*/

   STRImpuls(VERIFY_TIME);			/*Signatur ins Schiebereg. holen*/
					/*** Signatur einlesen ***/
   byte = 0;
   for (n = 0; n < SIG_SIZE; n++) {

     byte |= (BYTE)SDOut();			/*acht Bits zu einem Byte*/

     if (!((n+1)%8)) {				/*Text erstellen*/

       sprintf((char *)&strn[0], "%02x", (UWORD)byte);

       strncpy((char *)&SignatureTxt[12+4*((n+1)/8-1)], (char *)&strn[0], (size_t)2);

       if (isprint(byte))
         SignatureTxt[47+((n+1)/8-1)] = byte;
       else
         SignatureTxt[47+((n+1)/8-1)] = '.';

       byte = 0;
     }

     byte <<= 1;

     Clock();
   } 
   ExitEditMode();

   PrintText((UBYTE *)&SignatureTxt[0], 1);
 }
}




/* ProgJedecToGAL
   schreibt die Jedec-Struktur in das GAL
   (eigentliche Programmier-Routine)
   Aufruf:    result = ProgJedecToGAL(mode);
   Parameter: mode = COPYGAL: Aufruf erfolgt von GAL-Copy-Routine
		   = PROGGAL: Aufruf erfolgt von GAL-Programmier-Routine

   Ergebnis: 0: GAL erfolgreich programmiert
	     1: GAL wurde nicht programmiert, da es nicht leer ist
	     2: Verify ist fehlgeschlagen
*/
int ProgJedecToGAL(int mode)
{
int	n, i, row, bit;

					/*Leertest durchführen*/
  if (((mode == COPYGAL) && Config.CopyEmptyTest) || ((mode == PROGGAL) && Config.ProgEmptyTest)) {

    PrintText(AppStrings[MSG_EXE_BLANK_TEST].as_Str, 1);

    if (CheckGAL()) {
      PrintText(AppStrings[MSG_NOT_BLANK2].as_Str, 0);

      if (MyRequest(ERASE_REQ, AppStrings[MSG_NOT_BLNK_ERS].as_Str))
        EraseIt();
      else
        return(1);
    }
    else
      PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);

  }


  PrintText(AppStrings[MSG_PROGING_GAL].as_Str, 1);



  LED(ON);
  EditMode(PROG);
				/*** GAL16V8, GAL20V8 **/
 		
  if ((GALType == GAL16V8) || (GALType == GAL20V8)) {

				/*** Logik-Matrix schreiben ***/
    for (row = 0; row <= MaxFuseAdr; row++) {
      SetRow(row);

      for (n = 0; n < RowSize; n++) {
        SDIn((int)Jedec.GALLogic[row+(MaxFuseAdr+1)*n]); /*Bit an SDIn-Eingang anlegen*/
        Clock();			/*Bit in Schieberegister takten*/
      }

      SetPV(PROG);			/*P/V auf "programmieren"*/
      STRImpuls(prog_time);		/*Row (64 Bit) programmieren*/
      SetPV(VERIFY);			/*P/V wieder auf "lesen"*/
    }



    SetRow(SigAdr);		/*** Signatur schreiben ***/

    for (n = 0; n < SIG_SIZE; n++) {
      SDIn((int)Jedec.GALSig[n]);	/*Bit an SDIn-Eingang anlegen*/
      Clock();				/*Bit in Schieberegister takten*/
    }

    SetPV(PROG);				/*P/V auf "programmieren"*/
    STRImpuls(prog_time);			/*Daten programmieren*/
    SetPV(VERIFY);				/*P/V auf "lesen"*/



    SetRow(ACW_ADR);		/*** ACW schreiben ***/

    for (n = 0; n < ACW_SIZE; n++) {

      if (!GALAType()) {		/*** Standard-Typ (kein A-Typ) ***/

	if (n <= 31)				/*PT0-PT31*/
	  bit = Jedec.GALPT[n];

	if ((n >= 32) && (n <= 35))		/*4 XOR-Bits*/
	  bit = Jedec.GALXOR[n-32];

	if (n == 36)				/*AC0-Bit*/
	  bit = Jedec.GALAC0;

	if ((n >= 37) && (n <= 44)) 		/*AC1-Bits*/
	  bit = Jedec.GALAC1[n-37];

	if (n == 45) 				/*SYN-Bit*/
	  bit = Jedec.GALSYN;

	if ((n >= 46) && (n <= 49))		/*4 XOR-Bits*/
	  bit = Jedec.GALXOR[n-42];

	if ((n >= 50) && (n <= 81))		/*PT32-PT63*/
	  bit = Jedec.GALPT[n-18];

      }
      else {				/*** A-Typ ***/

	if (n <= 3)				/*4 XOR-Bits*/
	  bit = Jedec.GALXOR[n];

	if (n == 4)				/*AC0-Bit*/
	  bit = Jedec.GALAC0;

	if ((n >= 5) && (n <= 8))			/*AC1-Bits*/
	  bit = Jedec.GALAC1[n-5];

	if ((n >= 9) && (n <= 72))		/*PT0-PT63*/
	  bit = Jedec.GALPT[n-9];

	if ((n >= 73) && (n <= 76))		/*AC1-Bits*/
	  bit = Jedec.GALAC1[n-69];

	if (n == 77)				/*SYN-Bit*/
	  bit = Jedec.GALSYN;

	if (n >= 78)				/*XOR-Bits*/
	  bit = Jedec.GALXOR[n-74];

      }

      SDIn((int)bit);			/*Bit an SDIn-Eingang anlegen*/
      Clock();				/*Bit in Schieberegister takten*/
    }

    SetPV(PROG);				/*P/V auf "programmieren"*/
    STRImpuls(prog_time);			/*Daten programmieren*/
    SetPV(VERIFY);			/*P/V auf "lesen"*/

  }
  else {			/*** GAL20RA10, GAL22V10 ***/
				/*** Logik-Matrix schreiben ***/
    for (row = 0; row <= MaxFuseAdr; row++) {

      for (n = 0; n < RowSize; n++) {
        SDIn((int)Jedec.GALLogic[row+(MaxFuseAdr+1)*n]); /*Bit an SDIn-Eingang anlegen*/
        Clock();			/*Bit in Schieberegister takten*/
      }

      SetRow(row);
      SDIn(0);
      SetPV(PROG);			/*P/V auf "programmieren"*/
      STRImpuls(prog_time);		/*Row (64 Bit) programmieren*/
      SetPV(VERIFY);			/*P/V wieder auf "lesen"*/
    }

				/*** Signatur schreiben ***/
    for (n = 0; n < SIG_SIZE; n++) {
      SDIn((int)Jedec.GALSig[n]);	/*Bit an SDIn-Eingang anlegen*/
      Clock();				/*Bit in Schieberegister takten*/
    }

    for (n = 0; n < 132-SIG_SIZE; n++) { /*fehlende Bits reintakten*/
      SDIn(1);
      Clock();
    }

    SetRow(SigAdr);
    SDIn(0);
    SetPV(PROG);				/*P/V auf "programmieren"*/
    STRImpuls(prog_time);			/*Daten programmieren*/
    SetPV(VERIFY);				/*P/V auf "lesen"*/



				/*** ACW schreiben ***/
    SetARCH(1);					/* Architecture-Array */
    for (n = 0; n < 10; n++) {
      if (GALType == GAL22V10) {		/* bei 22V10 SYN zuerst */
	SDIn((int)Jedec.GALS1[n]);
	Clock();
      }

      SDIn((int)Jedec.GALXOR[n]);		/* XOR eintakten */
      Clock();
    }

    SDIn(0);
    SetPV(PROG);				/*P/V auf "programmieren"*/
    STRImpuls(prog_time);			/*Daten programmieren*/
    SetPV(VERIFY);				/*P/V auf "lesen"*/

  }

  ExitEditMode();


  PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);



				/*** Verify durchführen ***/

  if (((mode == COPYGAL) && Config.CopyVerify) || ((mode == PROGGAL) && Config.ProgVerify)) {

    PrintText(AppStrings[MSG_VERIFYING].as_Str, 1);

    for (n = 0; n < sizeof(Jedec2); n++)	/*Jedec-Struktur sichern*/
      Jedec2.GALLogic[n] = Jedec.GALLogic[n];

    ReadGALToJedec();			/*GAL nach Programmierung einlesen*/

    for (i = 0; i < sizeof(Jedec); i++) {	/*Jedec-Strukturen vergleichen*/
      if (Jedec.GALLogic[i] != Jedec2.GALLogic[i]) {
        MyRequest(ERR_REQ, AppStrings[MSG_VERFAILED].as_Str);

        PrintText(AppStrings[MSG_FAILED].as_Str, 0);

	for (i = 0; i < sizeof(Jedec2); i++)	/*Jedec-Struktur restaurieren*/
	  Jedec.GALLogic[i] = Jedec2.GALLogic[i];

	return(2);
      }
    }

    for (n = 0; n < sizeof(Jedec2); n++)	/*Jedec-Struktur restaurieren*/
      Jedec.GALLogic[n] = Jedec2.GALLogic[n];	/*wurde durch Verify überschrieben*/

    PrintText(AppStrings[MSG_LOWER_OK].as_Str, 0);
  }

  return(0);
}





/* ReadGALToJedec
   liest das GAL in die Jedec-Struktur
   (MaxFuseAdr, SigAdr, RowSize müssen initialisiert sein)
   Aufruf:  ReadGALToJedec()
*/
void ReadGALToJedec(void)
{
int	n, row;
BYTE	bit;


  LED(ON);
  EditMode(VERIFY);				/*GAL in Verify-Mode*/

					/*** Logik-Matrix lesen ***/
  for (row = 0; row <= MaxFuseAdr; row++) {
    SetRow(row);				/*Adresse anlegen*/

    STRImpuls(VERIFY_TIME);			/*Bits ins Schieberegister holen*/

    for (n = 0; n < RowSize; n++) {		/*seriell auslesen*/
      Jedec.GALLogic[row+(MaxFuseAdr+1)*n] = (BYTE)SDOut();
      Clock();					/*nächstes Bit an SDOut holen*/
    }
  }



  SetRow(SigAdr);	 		/*** Signatur auslesen ***/
  STRImpuls(VERIFY_TIME);

  for (n = 0; n < SIG_SIZE; n++) {
    Jedec.GALSig[n] = (BYTE)SDOut();
    Clock();
  }

				/*** Architecture Control Word (ACW) holen ***/

  if ((GALType == GAL16V8) || (GALType == GAL20V8)) {

    SetRow(ACW_ADR);
    STRImpuls(VERIFY_TIME);			/*Bits ins Schieberegister*/

    for (n = 0; n < ACW_SIZE; n++) {

      bit = (BYTE)SDOut();
      Clock();

      if (!GALAType()) {		   /*** kein A-Typ ***/

	if (n <= 31)
	  Jedec.GALPT[n] = bit;

	if ((n >= 32) && (n <= 35))		/*4 XOR-Bits*/
	  Jedec.GALXOR[n-32] = bit;

	if (n == 36)				/*AC0-Bit*/
	  Jedec.GALAC0 = bit;

	if ((n >= 37) && (n <= 44))		/*AC1-Bits*/
	  Jedec.GALAC1[n-37] = bit;

	if (n == 45) 				/*SYN-Bit*/
	  Jedec.GALSYN=bit;

	if ((n >= 46) && (n <= 49))		/*4 XOR-Bits*/
	  Jedec.GALXOR[n-42] = bit;

	if ((n >= 50) && (n <= 81))		/*PT32-PT63*/
	  Jedec.GALPT[n-18] = bit;

      }
      else {				/*** A-Typ ***/

	if (n <= 3)				/*4 XOR-Bits 19-16*/
	  Jedec.GALXOR[n] = bit;

	if (n == 4)				/*AC0-Bit*/
	  Jedec.GALAC0 = bit;

	if ((n >= 5) && (n <= 8))		/*AC1-Bits*/
	  Jedec.GALAC1[n-5] = bit;

	if ((n >= 9) && (n <= 72))		/*PT0-PT63*/
	  Jedec.GALPT[n-9] = bit;

	if (n == 77)				/*SYN-Bit*/
	  Jedec.GALSYN = bit;

	if ((n >= 73) && (n <= 76))		/*AC1-Bits*/
	  Jedec.GALAC1[n-69] = bit;

	if (n >= 78)				/*XOR-Bits*/
	  Jedec.GALXOR[n-74] = bit;
      }
    }

  }

					/*** 22V10 ***/
  if (GALType == GAL22V10) {
    SetARCH(1);					/* Architecture-Word lesen*/
    STRImpuls(VERIFY_TIME);			/* Bits ins Schieberegister*/

    for (n = 0; n < 10; n++) {
      Jedec.GALS1[n] = (BYTE)SDOut();		/* S1x holen */
      Clock();

      Jedec.GALXOR[n]  = (BYTE)SDOut();		/* XORx holen */
      Clock();
    }
  }

					/*** 20RA10 ***/
  if (GALType == GAL20RA10) {
    SetARCH(1);					/* Architecture-Word lesen */
    STRImpuls(VERIFY_TIME);			/* Bits ins Schieberegister*/

    for (n = 0; n < 10; n++) {
      Jedec.GALXOR[n] = (BYTE)SDOut();			/* XORx holen */
      Clock();
    }
  }


  ExitEditMode();
}





/* Sicherungsbit setzen
    flag = 0: Aufruf von der ProgramGAL-Routine aufgrund eines
	      gesetzten "JedecSecurity"-Flags
    flag = 1: Aufruf von einer anderen Routine als der ProgramGAL-Routine
*/
void SetSecurity(int flag)
{
int result;

  if (flag)
    result = MyRequest(GALTYPE_REQ, AppStrings[MSG_SET_SEC].as_Str);
  else
    result = MyRequest(CONT_REQ, AppStrings[MSG_SET_SEC].as_Str);

  if (result) {

    if (flag)
      if (ReadGALParameter(YES))		/*GAL-Parameter holen*/
        return;					/*bei Fehler return*/

    LED(ON);

    EditMode(PROG);

    SetRow(SECURITY_ADR);

    SetPV(PROG);				/*P/V-Pin auf "programmieren*/

    STRImpuls(prog_time);			/*STR-Impuls geben*/

    SetPV(VERIFY);				/*P/V wieder auf "lesen*/

    ExitEditMode();

    if (flag)
      MyRequest(INFO_REQ, AppStrings[MSG_SEC_IS_SET].as_Str);
  }
}





/* GAL löschen */
void Loeschen(void)
{
int result;

  if (MyRequest(GALTYPE_REQ, AppStrings[MSG_ERASE_GAL].as_Str)){
    if (ReadGALParameter(YES))			/*GAL-Parameter holen*/
      return;					/*bei Fehler return*/

    EraseIt();

    if (Config.EraseEmptyTest) {
      PrintText(AppStrings[MSG_GAL_ERASED].as_Str, 1);

      PrintText(AppStrings[MSG_EXE_BLANK_TEST].as_Str, 1);

      result = CheckGAL();

      PrintText(AppStrings[MSG_READY].as_Str, 0);

      if (result) {
        MyRequest(ERR_REQ, AppStrings[MSG_ERASE_FAILED].as_Str);
        return;
      }
    }

    MyRequest(INFO_REQ, AppStrings[MSG_ERASED].as_Str);
  }
}



/*GAL löschen.
  Vor dem Aufruf sollten die GAL-Parameter eingelesen worden sein (mit
  ReadGALParameter(YES);)
*/
void EraseIt(void)
{

   LED(ON);

   EditMode(PROG);


   if ((GALType == GAL16V8) || (GALType == GAL20V8)) {
     SetRow(ERASE_ADR);
     SDIn(1);
     SetPV(PROG);			/*P/V-Pin auf "programmieren"*/
     STRImpuls(bulk_time);		/*STR-Imputs geben*/
     SetPV(VERIFY);			/*und P/V wieder auf "lesen"*/
   }


   if (GALType == GAL22V10) {
     SDIn(1);
     SetPV(PROG);
     SetANDBE(1);
     SetARCH(1);
     SetBE(1);
     SetCLR(1);
     SetERASE(1);

     STRImpuls(bulk_time);

     SetPV(VERIFY);
     SetANDBE(0);
     SetARCH(0);
     SetBE(0);
     SetCLR(0);
     SetERASE(0);
   }


   if (GALType == GAL20RA10) {
     SDIn(1);
     SetPV(PROG);
     SetPESSAVE(1);
     SetARCH(1);
     SetBE(1);
     SetCLR(1);

     STRImpuls(bulk_time);		/* Architecture-Array löschen */

     SetARCH(0);

     STRImpuls(bulk_time);		/* AND-Array löschen */

     SetPV(VERIFY);
     SetPESSAVE(0);
     SetBE(0);
     SetCLR(0);
   }


   ExitEditMode();

}

