/* ----------------------------------------------------------------P. S. O---
 *  FIRST UPDATE : 3. 6. 1991. all ok!
 *  LIB Ver      : 1.00
 * --------------------------------------------------------------------------
 * Fuse_su		      : 6432   52
 * Internal Security Fuse     : 1
 * ------------------------------------------------------------------------ */
declaration
  dataunit : bit
  ;
  functions
    Program
    Read
    Verify
    Blank_Check
    Security
    Erase
    Auto
  ;
  Manufacturers
    LATTICE
  ;
  Devices
    dGAL26CV12
  ;
		/*  ΥΝΝΝΝΈΥΝΝΝΝΈ        */
  chips = UP0,  /* [³ 1     28 ³] UP3   */
	 EDIT,  /* [³ 2     27 ³] OP10  */
	  P_V,  /* [³ 3     26 ³] OP9   */
	   PS,  /* [³ 4     25 ³] OP8   */
	  UP1,  /* [³ 5     24 ³] OP7   */
          CLR,  /* [³ 6     23 ³] OP6   */
	  VCC,  /* [³ 7     22 ³] OP5   */
	  UP2,  /* [³ 8     21 ³] GND   */
	   BE,  /* [³ 9     20 ³] OP4   */
	 ARCH,  /* [³ 10    19 ³] OP3   */
       AND_BE,  /* [³ 11    18 ³] OP2   */
	 SCLK,  /* [³ 12    17 ³] OP1   */
         SDIN,  /* [³ 13    16 ³] OP0   */
	  STR,  /* [³ 14    15 ³] SDOUT */

	  NC0,  /* [³          ³] NC3   */
          NC1,  /* [³          ³] NC2   */
		/*  ΤΝΝΝΝΝΝΝΝΝΝΎ        */
	NC2, NC3, SDOUT, OP0, OP1, OP2, OP3, OP4, GND, OP5, OP6, OP7, 
	OP8, OP9, OP10, UP3;

  $v2 = EDIT;
  $v1 = VCC;
endd

int	ALGO;                    	/* Programming Voltage */
int 	TPWP;				/* Programming pulse width */
int     data[17];			/* MES data buffer */

int 	arch[24] =
  {6345, 6344, 6347, 6346, 6349, 6348, 6351, 6350, 6353, 6352, 6355, 6354,
   6357, 6356, 6359, 6358, 6361, 6360, 6363, 6362, 6365, 6364, 6367, 6366};

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 ++;
  }
}
/* -----------------------------------------------------------------------
 * init() ---> inital processing
 * ----------------------------------------------------------------------- */
int enter(option)
int option;
{
  @Vout 1,      5.00; /* NULL */
  @Vout 2,      5.00;
  @Vout 3,	5.00;	

  @Delay 10, @Ms;
  @Out GND,	@G;
  @Out VCC,	@O;

  @Out UP[0..3],@W;
  @Out EDIT,    @W;  
  @Out P_V,  	@W;
  @Out PS,	@W;
  @Out CLR,	@W;
  @Out VCC,	@W;
  @Out BE,	@W;
  @Out ARCH,	@W;
  @Out AND_BE,	@W;
  @Out SCLK,	@W;
  @Out SDIN,	@W;
  @Out STR,	@W;
  @Out SDOUT,	@Z;
  @Out OP[0..10], @Z;  
  
  @Out UP[0..3],@L;
  @Out EDIT,    @L;  
  @Out P_V,  	@L;
  @Out PS,	@L;
  @Out CLR,	@L;
  @Out VCC,	@H;
  @Out BE,	@L;
  @Out ARCH,	@L;
  @Out AND_BE,	@L;
  @Out SCLK,	@L;
  @Out SDIN,	@L;
  @Out STR,	@H;

  if(option == 'r')    @Raising EDIT, 2.0, 12.00, 100;
  else {
    if     (ALGO == 0) @Raising EDIT, 2.0, 16.50, 100;
    else if(ALGO == 1) @Raising EDIT, 2.0, 15.75, 100;
    else if(ALGO == 2) @Raising EDIT, 2.0, 14.50, 100;
    else if(ALGO == 3) @Raising EDIT, 2.0, 14.00, 100;
  }
  @Delay 100, @us;

  @Out OP[0..10], @W;
  @Out OP[0..10], @L;
}
int exit(option)
int option;
{
  @Out OP[0..10], @Z;

  if(option == 'r')    @Falling EDIT, 12.00, 2.0, 100;
  else {
    if     (ALGO == 0) @Falling EDIT, 16.50, 2.0, 100;
    else if(ALGO == 1) @Falling EDIT, 15.75, 2.0, 100;
    else if(ALGO == 2) @Falling EDIT, 14.50, 2.0, 100;
    else if(ALGO == 3) @Falling EDIT, 14.00, 2.0, 100;
  }
  @Out EDIT, @F;
  @Out STR,  @L;
  @Out VCC,  @F;
}              
/* -----------------------------------------------------------------------
 * Out Clock
 * ----------------------------------------------------------------------- */
int clock()
{
    @Out SCLK,  @H;
    @Out SCLK,  @L;
}
/* -----------------------------------------------------------------------
 * Addressing
 * ----------------------------------------------------------------------- */
int addressing(RAG)
int RAG;
{
  int i;
  
  for(i=0; i<6; i++) {
    if((RAG >> i) & 1 == 1) @Out SDIN, @H;
    else                    @Out SDIN, @L;
    clock();
  }
  @Out SDIN, @L;
}
/* -----------------------------------------------------------------------
 * Out Program
 * ----------------------------------------------------------------------- */
int pgm_p()
{
  @Out P_V,  @H;
  @Out STR,  @L;
  @Delay TPWP, @Ms;
  @Out STR,  @H;
  @Out P_V,  @L;
}
/* -----------------------------------------------------------------------
 * Read | Verify | Blank_check device
 * ----------------------------------------------------------------------- */
int verifyf(address, data, option)
int address,
    data,
    option;
{
  int tmp;

  @Display 67, 9, address, @d;
  @Set 0, address;

  if     (option == 'r') @Load data;                    /* Read device */
  else if(option == 'v') {
    @Store tmp;
    if (tmp&1 != data&1) {exit('r');@Exit;}
  }
  else if(option == 'b' || option == 's') {
    if(option == 's' && address > 6367) return;
    if(data & 1 != 1)    {exit('r');@Exit;}
  }
}
/* -----------------------------------------------------------------------
 * Program, Read, Verify, Blank_check
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j, k;
  int r_data, tmp, end, addr;

  disp(option, 0);
  enter('r');

  addressing(0);

  for(i=0; i<53; i++) {
    @Out STR,	    @L;
    @Out STR,       @H;

    for(j=0; j<122; j++) {
      @In SDOUT, r_data;
      clock();
      if(i == 52) addr = 6368 + j;
      else        addr = j*52+i;
      verifyf(addr, r_data, option);
    }
    if(i == 52) break;
    addressing(i+1);
  }

  @Out ARCH, @H;
  @Out STR,  @L;
  @Out STR,  @H;
  for(i=0; i<24; i++) {
    @In SDOUT, r_data;
    clock();
    verifyf(arch[i], r_data, option);
  }
  @Out ARCH, @L;

  exit('r');
  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * Program data to device
 * ----------------------------------------------------------------------- */
int program_device()
{
  int i, j;
  int p_data, r_data, addr, addr1;

  disp('p', 0);
  enter('p');
  r_data = p_data = 0;

  for(j=0; j<122; j++) {
    @Set 0, j * 52;
    @Store p_data;
    if(p_data&1 == 1) @Out SDIN, @H;
    else              @Out SDIN, @L;
    clock();
  }
  addressing(0);

  for(i=0; i<53; i++) {
    pgm_p();
    if(i == 52) break;
    @Out STR,  @L;
    @Out STR,  @H;
    
    for(j=0; j<122; j++) {
      @In SDOUT, r_data;  			/* Verify */
      if(i == 51) addr = 6368+j;
      else  {
        addr = j*52+i+1;
        verifyf(addr-1, r_data, 'v');
      }

      @Set 0, addr;				/* Program data shift in */
      @Store p_data;
      if(p_data == 1) @Out SDIN, @H;
      else            @Out SDIN, @L;
      clock();
      @Out SDIN, @L;
    }  
    addressing(i+1);
  }
  @Out ARCH, @H;
  for(i=0; i<24; i++) {
    @Set 0, arch[i];
    @Store p_data;
    if(p_data == 1) @Out SDIN, @H;
    else            @Out SDIN, @L;
    clock();
    @Out SDIN, @L;
  }
  pgm_p();
  @Out ARCH, @L;

  exit('p');
  disp('p', 1);
}
/* -----------------------------------------------------------------------
 * MES Check
 * ----------------------------------------------------------------------- */
int ID_check()
{
  int  i, j;
  int  tmp;

  tmp = 0;

  for(i=0; i<17 ; i++) data[i] = 0;
  
  enter('r');
  addressing(58);
  @Out STR, @L;
  @Out STR, @H;
  for(i=0; i<122; i++) {
    @In SDOUT, tmp;
    data[i/8] |= tmp << (i%8);
    clock();
  }
  exit('r');

  if     (data[1] == 0) {ALGO = 0; TPWP = 10;}
  else if(data[1] == 1) {ALGO = 1; TPWP = 80;}
  else if(data[1] == 2) {ALGO = 2; TPWP = 40;}
  else if(data[1] == 3) {ALGO = 3; TPWP = 80;}
  else {
    ALGO = 3; TPWP = 80;
    @Display 26, 6, "Invalid ID !";
    @Exit;
  }

@Display 26, 6, "Algorithm Code  :"; @Display 44, 6, data[1];
@Display 26, 7, "Device Code     :"; @Display 44, 7, data[2];
@Display 26, 8, "Manufacture's ID:"; @Display 44, 8, data[3];
}
/* -----------------------------------------------------------------------
 * Erase & Security device
 * ----------------------------------------------------------------------- */
int erase_device()
{
  disp('e', 0);
  enter('p');
  
  @Out P_V,    @H;
  @Out AND_BE, @H;
  @Out ARCH,   @H;
  @Out PS,     @H;
  @Out BE,     @H;
  @Out CLR,    @H;
  @Out STR,    @L;
  @Delay 100, @Ms;
  @Out STR,    @H;
  @Out CLR,    @L;
  @Out BE,     @L;
  @Out AND_BE, @L;
  @Out ARCH,   @L;
  @Out PS,     @L;
  @Out P_V,    @L;

  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('e', 1);
}
int security_device()
{
  disp('s', 0);
  enter('p');
  
  addressing(61);
  pgm_p();

  disp_flag = 1;
  top('s');
  disp_flag = 0;
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 10;
  disp_flag = 0;
  
  ID_check();

  if     (FUNCTION == Program) {
    erase_device();				/* Erase device       */
    program_device();				/* 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();				/* Erase device       */
    program_device();				/* Program device     */
    top('v');					/* Verify device      */
    security_device();				/* Security device    */
  }
  else if(FUNCTION == Erase) {
    erase_device();				/* Erase device       */
  }
}
/* ------------------------------- End of program ------------------------ */
