/* ----------------------------------------------------------------P. S. O---
 *  FIRST UPDATE : 1. 11. 91
 *                 1. 23. 91  all ok !
 *                 1. 31. 91  (p, r, v, b, s, a, v_test ok!)
 *  LIB Ver      : 1.00
 * --------------------------------------------------------------------------
 * Fuse_su		      : 8294    117/2 (57)
 * Internal Security Fuse     : 1
 * ------------------------------------------------------------------------- */
declaration
  dataunit : bit 
  ;
  functions
    Program
    Read
    Verify
    Blank_Check
    Security
    Erase
    Auto
  ;
  Manufacturers
    LATTICE
    NS
    SGS
  ;
  Devices
    GAL6001
  ;
		/*  ΥΝΝΝΝΈΥΝΝΝΝΈ        */
  chips = UP0,  /* [³ 1     24 ³] VCC   */
         EDIT,  /* [³ 2     23 ³] PV    */
	  UP1,  /* [³ 3     12 ³] OP7   */
	  UP2,  /* [³ 4     21 ³] OP6   */
	  AND,  /* [³ 5     20 ³] OP5   */
           OR,  /* [³ 6     19 ³] OP4   */
	 ARCH,  /* [³ 7     18 ³] OP3   */
	  CLR,  /* [³ 8     17 ³] OP2   */
	   BE,  /* [³ 9     16 ³] OP1   */
	 SCLK,  /* [³ 10    15 ³] OP0   */
	 SDIN,  /* [³ 11    14 ³] SDOUT */
	  GND,  /* [³ 12    13 ³] STR   */
		/*  ΤΝΝΝΝΝΝΝΝΝΝΎ        */
	STR, SDOUT, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7, PV, VCC;

  $v2 = EDIT;
  $v3 = VCC;
endd

int	ALGO;                    	/* Programming Voltage */	
int 	TPWP;				/* Programming pulse width */
int     MES_data[10];			/* MES data buffer */

int xor[20] =
       { 8216, 8217, 8212, 8213, 8208, 8209, 8204, 8205, 8200, 8201,
	 8196, 8197, 8192, 8193, 8188, 8189, 8184, 8185, 8180, 8181};

int index, disp_flag;

/* -----------------------------------------------------------------------
 * Display processing
 * ----------------------------------------------------------------------- */
int disp(option, p)
int option, p;
{
  if(disp_flag == 1) return(p);
  if(p == 0) {             
    if     (option == 'p') @Display 26, index, "Programming ...";    
    else if(option == 'r') @Display 26, index, "Reading ...";      
    else if(option == 'b') @Display 26, index, "Blank checking ...";
    else if(option == 'v') @Display 26, index, "Verifying ...   ";
    else if(option == 's') @Display 26, index, "Securing ...";
    else if(option == 'e') @Display 26, index, "Eraseing ...";
  }
  else {
    if     (option == 'p') @Display 26, index, "Program OK!    ";
    else if(option == 'r') @Display 26, index, "Read OK!   ";
    else if(option == 'b') @Display 26, index, "Blank check OK!   ";
    else if(option == 'v') @Display 26, index, "Verification OK!";
    else if(option == 's') @Display 26, index, "Security OK!";
    else if(option == 'e') @Display 26, index, "Erase OK!   ";
    index ++;
  }
}
/* -----------------------------------------------------------------------
 * enter() ---> inital processing
 * ----------------------------------------------------------------------- */
int enter(option)
int option;
{
  @Out  GND, 	@G;
  @Vout 1,      5.00;	/* NULL */
  @Vout 2,	5.00;
  @Vout 3, 	5.00;
  @Delay 10, @Ms;

  @Out UP[0..2],@W;
  @Out OP[0..7],@Z;
  @Out EDIT,    @W;
  @Out AND, 	@W;
  @Out OR, 	@W;
  @Out ARCH,	@W;
  @Out CLR,	@W;
  @Out BE,	@W;
  @Out SCLK,	@W;
  @Out SDIN,	@W;
  @Out STR,	@W;
  @Out SDOUT,	@Z;
  @Out PV,	@Z;
  @Out VCC,	@W;

  @Out UP[0..2],@L;
  @Out EDIT,	@L;
  @Out AND,	@L;
  @Out OR, 	@L;
  @Out ARCH,	@L;
  @Out CLR,	@L;
  @Out BE,	@L;
  @Out SCLK,	@L;
  @Out SDIN,	@L;
  @Out STR,	@L;
  @Out VCC,	@H;

  @Out VCC, 	@O;
  @Delay 100, @us;   
  @Out STR,     @H;

  if(option == 'r')    @Raising EDIT, 2.0, 12.00, 100;
  else {
    if     (ALGO == 0) @Raising EDIT, 2.0, 15.75, 100;
    else if(ALGO == 1) @Raising EDIT, 2.0, 16.50, 100;
  }

  @Out PV,	@W;  
  @Out OP[0..7],@W;
  @Out PV,	@L;
  @Out OP[0..7],@L;
}
/* -----------------------------------------------------------------------
 * exit() ---> quit processing
 * ----------------------------------------------------------------------- */
int exit(option)
int option;
{
  @Out PV,	@Z;
  @Out AND,	@L;
  @Out OR, 	@L;
  @Out ARCH,	@L;
  @Out SDIN,	@L;

  if(option == 'r')    @Falling EDIT, 12.00, 2.00, 100;
  else {
    if     (ALGO == 0) @Falling EDIT, 15.75, 2.00, 100;
    else if(ALGO == 1) @Falling EDIT, 16.50, 2.00, 100;
  }
  @Out EDIT,    @F;
  @Out STR,	@L;
  @Out VCC,	@F;
}
int clock()
{
  @Out SCLK, @H;
  @Out SCLK, @L;
}
/* -----------------------------------------------------------------------
 * Verify function 
 * ----------------------------------------------------------------------- */
int verifyf(address, data, option)
int address,
    data,
    option;
{
  int tmp;

  @Set 0, address;

  if     (option == 'r') @Load data;		/* Read device */
  else if(option == 'v') {
    @Store tmp;
    if (tmp&1 != data&1) {			/* Verify error */
      exit('r');
      @Exit;
    }
  }
  else if(option == 'b') { 		       	/* Blank check error */
    if(address > 8221) return; 
    if(data&1 != 1) {
      exit('r');
      @Exit;
    }
  }
}
/* -----------------------------------------------------------------------
 * putdata() --> Write data to device
 * ----------------------------------------------------------------------- */
int putdata(address)
int address;
{
  int data;

  data = 0;
  @Set 0, address;
  @Store data;
  return(data);
}
/* -----------------------------------------------------------------------
 * convert sub program function
 * ----------------------------------------------------------------------- */
int convert_sub(address, data, option)
int  address, 
     data,					/* Read data    */
     option;    				/* Option       */
{
  int pgm_d;

  @Display 67, 9, address, @d;
  
  if(option == 'p')  pgm_d = putdata(address);
  else               verifyf(address, data, option);
  return(pgm_d);
}  
/* -----------------------------------------------------------------------
 * convert function
 * ----------------------------------------------------------------------- */
int convert(i, j, data, arr_type, option)
int  i, j, 
     data,					/* Read data    */
     arr_type,  				/* Array type   */
     option;    				/* Option       */
{
  int pgm_d, tmp;
  
  pgm_d = 0;

  if(arr_type == 0) {				/* i=0 to 77 NORMAL */
    if     (j>19 && j<30) pgm_d = convert_sub(7296+(j-20)*78+i, data, option);
    else if(j == 30)      pgm_d = convert_sub(8076+i, data, option);
    else if(j>30 && j<95) pgm_d = convert_sub((j-31)*114+i, data, option);
  }
  else if(arr_type == 1) {			/* i=97  UES */
    if(j>19 && j<92) pgm_d = convert_sub(8222+j-20, data, option);
  }
  else if(arr_type == 2) {			/* i=96  MES */
    if(j>19 && j<95) {
      if(option == 'p') pgm_d = (MES_data[(j-20)/8] >> ((j-20)%8)) & 1;
      else if(option == 's') return(0);
      else              MES_data[(j-20)/8] |= data << ((j-20)%8);
    }
  }
  else if(arr_type == 3) {			/* OR */
    if     (j < 20)  pgm_d = convert_sub(7338-i*114-78+j, data, option);
    else if(j > 102) pgm_d = convert_sub(7378-i*114-98+j-103, data, option);
  }
  else if(arr_type == 4) {			/* ARCH */
    if     (j==0) 	   pgm_d = convert_sub(8221, data, option);
    else if(j==1)	   pgm_d = convert_sub(8220, data, option);         
    else if(j>1  && j<12)  pgm_d = convert_sub(8179+(j- 2)*4, data, option);
    else if(j>11 && j<22)  pgm_d = convert_sub(8214-(j-12)*4, data, option);
    else if(j>21 && j<42)  pgm_d = convert_sub(xor[j-22], data, option);
    else if(j>41 && j<50)  pgm_d = convert_sub(8156+(j-42)*3, data, option);
    else if(j>49 && j<58)  pgm_d = convert_sub(8154+(j-50)*3, data, option);
    else if(j>57 && j<66)  pgm_d = convert_sub(8176-(j-58)*3, data, option);
    else if(j==66)         pgm_d = convert_sub(8218, data, option);
    else if(j==67)         pgm_d = convert_sub(8219, data, option);
  }

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * AND array data process
 * ----------------------------------------------------------------------- */
int normal_sub(i, arr_type, option)		/* for AND, OR, MES, UES Array */
int  i, arr_type, option;
{
  int 	j, data;

  for(j=0; j<119; j++) {
    data = 0;
    if(option == 'p' || option == 's') data = convert(i, j, 0, arr_type, option);
    
    if(arr_type < 3) {				/* for AND, MES, UES Array*/
      if     (j == 95)       data = 1;
      else if(j>95 && j<103) data = (i >> (j-96)) & 1;
    }
    else {					/* for OR Array */
      if(j>30 && j<95) {if(j != 94-i) data = 1;}
    }

    if(data == 1) @Out SDIN, @H;
    else          @Out SDIN, @L;
    clock();
  }  
  
  if(option == 'p' || option == 's') {
    @Out PV,	@H;
    @Out STR,	@L;
    @Delay TPWP, @Ms;
    @Out STR, 	@H;
    @Out PV, 	@L;
  }
  else {
    @Out STR,	@L;
    @Out STR,   @H;
    for(j=0; j<119; j++) {
      @In  SDOUT, data;
      clock();
      convert(i, j, data, arr_type, option);
    }
  }
}
/* -----------------------------------------------------------------------
 * ARCH array data process
 * ----------------------------------------------------------------------- */
int arch_sub(arr_type, option)		/* for ARCH Array */
int arr_type, option;
{
  int 	j, data;

  @Out ARCH, @H;
  for(j=0; j<68; j++) {
    data = 0;
    if(option == 'p') data = convert(0, j, 0, arr_type, option);
    
    if(data == 1) @Out SDIN, @H;
    else          @Out SDIN, @L;
    clock();
  }  
  
  if(option == 'p') {
    @Out PV,	@H;
    @Out STR,	@L;
    @Delay TPWP, @Ms;
    @Out STR, 	@H;
    @Out PV, 	@L;
  }
  else {
    @Out STR,	@L;
    @Out STR,   @H;
    for(j=0; j<68; j++) {
      @In  SDOUT, data;
      clock();
      convert(0, j, data, arr_type, option);
    }
  }
}
/* -----------------------------------------------------------------------
 * program main process
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i;
  
  disp(option, 0);
  if(option == 'p') enter('p');
  else              enter('r');

  for(i=0; i<78; i++) normal_sub(i, 0, option);		/* AND */
  normal_sub(97, 1, option);				/* UES */
  for(i=0; i<64; i++) normal_sub(i, 3, option);		/* OR  */
  arch_sub(4, option);					/* ARCH */

  if(option == 'p') exit('p');
  else              exit('r');

  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * MES Check function
 * ----------------------------------------------------------------------- */
int ID_check()
{
  int i;

  for(i=0; i<10; i++) MES_data[i] = 0;
  enter('r');
  normal_sub(96, 2, 'r');				/* MES */
  exit('r');

  if     (MES_data[1]&0x7f == 1) {ALGO = 0; /*VIE = 15.75;*/ TPWP = 80;}
  else if(MES_data[1]&0x7f == 2) {ALGO = 1; /*VIE = 16.50;*/ TPWP = 10;}
  else {
    @Display 26, 6, "Invalid ID !";
    @Exit;
  }

@Display 26, 5, "Cycle count     :"; @Display 44, 5, MES_data[0]&0x7f;  
@Display 26, 6, "Algorithm Code  :"; @Display 44, 6, MES_data[1];
@Display 26, 7, "Device Code     :"; @Display 44, 7, MES_data[2];
@Display 26, 8, "Manufacture's ID:"; @Display 44, 8, MES_data[3];
}
/* -----------------------------------------------------------------------
 * Erase device function
 * ----------------------------------------------------------------------- */
int erase_device()
{
  disp('e', 0);
  enter('p');
  
  @Out CLR,	@H; 
  @Out BE,	@H;
  @Out AND,	@H;
  @Out OR,	@H;
  @Out ARCH,	@H; 
  @Out PV,      @H;
  @Out STR,	@L;
  @Delay 50, @Ms;
  @Out STR,	@H;
  @Out PV,      @L;
  @Out CLR,	@L; 
  @Out BE,	@L;
  @Out AND,	@L;
  @Out OR,	@L;
  @Out ARCH,	@L; 
  exit('p');

  disp_flag = 1;
  top('b');
  disp_flag = 0;
  if(MES_data[0] & 0x7f < 0x7f) MES_data[0] ++;
  enter('p');
  normal_sub(96, 2, 'p');
  exit('p');
  disp('e', 1);
}
/* -----------------------------------------------------------------------
 * Security device function
 * ----------------------------------------------------------------------- */
int security_device()
{
  disp('s', 0);
  enter('p');
  normal_sub(98, 2, 's');  
  exit('p');

  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('s', 1);         
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 10;
  disp_flag = 0;

  ID_check();
  
  if     (FUNCTION == Program) {
    erase_device();				/* Erase device       */  
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
  }
  else if(FUNCTION == Security) {
    security_device();				/* Security device    */
  }
  else if(FUNCTION == Read) {           	/* Read device        */
    top('r');	
    @CheckSumOn;
  }
  else if(FUNCTION == Blank_Check) top('b');	/* Blank check device */
  else if(FUNCTION == Verify)      top('v');	/* Verify device      */
  else if(FUNCTION == Auto) {
    erase_device('e');				/* Erase device       */
    top('b');					/* Blank check        */
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
    security_device();				/* Security device    */
  }
  else if(FUNCTION == Erase) {
    erase_device();				/* Erase device       */
  }
}
/* ------------------------------- End of program ------------------------ */
  