/* --< 5 >---------------------------------------------------------P. S. O-
 *  FIRST UPDATE : Oct. 10. 1990
 *                 Dec.  6. 1990
 *                   1. 16. 1990   All ok !
 *  LIB Ver      : 1.00
 * -------------------------------------------------------------------------
 *  EP310
 *  ALTERA=EP310  INTEL=5C031
 *  PAL-like, 18 inputs (8 fb), 8 outputs (OLMC), 20 pins (DIP)
 *  Fuse_su		      : 2720     [36 * 75 others 20]
 *  Internal Security Fuse    : 1        [Verify available]
 * ------------------------------------------------------------------------
 *  EP320
 *  ALTERA=EP320  INTEL=5C032, 85C220
 *  18 inputs (8 fb), 8 outputs (OLMC), 20 pins (DIP)
 *  Fuse_su		      : 2916     [36 * 81]
 *  Internal Security Fuse    : 1        [Verify available]
 * ------------------------------------------------------------------------
 * SYMBOL |                            |    MIN   TYP   MAX  |  UNIT
 * -------+----------------------------+---------------------+-------------
 * VPP    | Programming supply voltage |  12.50 12.75 13.00  |   V
 * Vhh    | High-level control volotge |  12.50 12.75 13.00  |   V
 * VCC    | Operating supply voltage   |   4.70  5.00  5.20  |   V
 * VCC    | Programming supply voltage |   5.75  6.00  6.25  |   V
 * M      | Pulse limit count          |      -     -    25  |
 * N      | Pulse multlpller           |      3     -     -  |
 * P      | Retry limit                |      8     -     -  |
 * S      | Location count for retry   |      -     -    50  |
 * VPcnt  | Verify protect pluse count |     25     -     -  |
 * PPw    | Base program plse width    |   0.95   1.0  1.05  |   ms
 * T duty | Programming duty perlod    |      3     -     -  |   ms
 * T rise | Rise time for VPP          |      5     -    50  |   us
 * T fall | Fall time for VPP          |      5     -  2000  |   us
 * T ps1  | Setup time pin 1           |      -     2     -  |   us
 *---------------------------------------------------------------------- */
declaration
  dataunit : bit
  ;
  functions
    Program  
    Read
    Verify
    Blank_Check
    Security
    Auto
  ;
  Manufacturers
    ALTERA
    INTEL
  ;
  Devices
    dEP310   /* Altera */
    d5C031   /* Intel  */
    
    dEP320   /* Altera */
    d5C032   /* Intel  */
    d85C220  /* Intel  */
  ;
                /*  ΥΝΝΝΝΈΥΝΝΝΝΈ       */
  chips = PGM,  /* [³ 1     20 ³] VCC  */
          CA0,  /* [³ 2     19 ³] D0   */
          CA1,  /* [³ 3     18 ³] D1   */
          CA2,  /* [³ 4     17 ³] D2   */
          RA0,  /* [³ 5     16 ³] D3   */
          RA1,  /* [³ 6     15 ³] D4   */
          RA2,  /* [³ 7     14 ³] D5   */
          RA3,  /* [³ 8     13 ³] D6   */
          RA4,  /* [³ 9     12 ³] D7   */
          GND,  /* [³ 10    11 ³] VPP  */
                /*  ΤΝΝΝΝΝΝΝΝΝΝΎ       */
	  VPP,  D7,  D6,  D5,  D4,  D3,  D2,  D1,  D0, VCC;

  $v2 = PGM, VPP, RA4, CA2;
  $v3 = VCC;
endd

int addr_7 [10] = {2912, 2910, 2906, 2902, 2898, 2896, 2900, 2904, 2908};
int addr_0 [10] = {2914, 2882, 2886, 2890, 2894, 2892, 2888, 2884, 2880};
int filter;

  int index     = 6;
  int disp_flag = 0;
/* -----------------------------------------------------------------------
 * 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 == '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!";
    index ++;
  }
}
/* -----------------------------------------------------------------------
 * init() ---> inital processing
 * ----------------------------------------------------------------------- */
int init(option)
int option;
{
  @Vout 1,       5.00;
  @Vout 2,       5.00;
  if(option == 'p')  @Vout 3, 6.00;
  else               @Vout 3, 5.00;
  @Out  GND,     @G;
  @Delay 10, @Ms;
            
  @Out VCC,      @W;
  @Out CA[0..2], @W;
  @Out RA[0..4], @W;
  @Out D[0..7],  @Z;
  @Out PGM,	 @W;
  @Out VPP,      @W;

  @Out VCC,      @L;
  @Out CA[0..2], @L;
  @Out RA[0..4], @L;
  @Out PGM,      @H;
  @Out VPP,      @L;

  @Out VCC, 	 @O;
  @Delay 100, @Us;

  if(DEVICE == d85C220)
  		@Raising VPP, 5.00, 12.50, 100;
  else if(DEVICE == dEP320 || DEVICE == d5C032)
		@Raising VPP, 5.00, 12.75, 100;
  else @Vout 2, 12.75;
}
/* -----------------------------------------------------------------------
 * Read data from device
 * Blank check
 * Verify
 * ----------------------------------------------------------------------- */
int verifyf(address, data, shift, option)
int address, data, shift, option;
{
  int tmp;

  @Set 0, address;
  data >>= shift;
      
  if     (option == 'r') @Load data;		/* Read data	   */
  else if(option == 'b') {			/* Blank check     */
    if(data&1 != 0)      @Exit;
  }
  else if(option == 'v') {			/* Verify check    */
    @Store tmp;
    if (tmp&1 != data&1) @Exit;
  }
}
/* -----------------------------------------------------------------------
 * putdata() --> Write data to device
 * ----------------------------------------------------------------------- */
int putdata(address, shift)
int address, shift;
{
  int data;

  @Set 0, address;
  @Store data;
  data = (data & 1) << shift;
  return(data);
}
/* -----------------------------------------------------------------------
 * convert sub program function
 * ----------------------------------------------------------------------- */
int convert_sub(address, data, shift, option)
int  address,
     data,					/* Read data    */
     shift,
     option;    				/* Option       */
{
  int pgm_d;

  @Display 67, 9, address, @d;

  if(option == 'p')  pgm_d = putdata(address, shift);
  else               verifyf(address, data, shift, option);

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * data convert
 * ----------------------------------------------------------------------- */
int convert(ca, ra, read_d, option, arr_type)
int  ca, ra, read_d, option, arr_type;
{
  int i, pgm_d;
    
  pgm_d = 0;
  filter = 0xff;
      
if(arr_type == 0) {     
  if(ca < 9) {
    for(i=0; i<8; i++) {
      pgm_d |= convert_sub(ca*36 + i*324 + ra, read_d, i, option);
    }
  }
}
						/*  EP310, 5C031 */
  if(DEVICE <= d5C031) {
    if(ca == 9) {
      pgm_d |= convert_sub(2592 + ra, read_d, 0, option);
      pgm_d |= convert_sub(2628 + ra, read_d, 7, option);
      filter = 0x81;
    }
    else if(ca == 0x0b) {
      for(i=0; i<8; i++) pgm_d |= convert_sub(2664 + i*7 + (ra - 0x28), read_d, i, option);
    }
  }
						/* EP320, 5C032, 85C220 */
  else {
    if(arr_type == 0) {
      if(ca == 9) {
        for(i=0; i<8; i++) pgm_d |= convert_sub(2592 + i*36 + ra, read_d, i, option);
      }
    }
    else {
      pgm_d |= convert_sub(addr_0[ca] + ra, read_d, 0, option);
      pgm_d |= convert_sub(addr_7[ca] + ra, read_d, 7, option);
      filter = 0x81;
    }
  }

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * Sub program
 * ----------------------------------------------------------------------- */
int sub(ca, ra, option, arr_type)
int ca,						/* Column Address */
    ra,						/* Row Address    */
    option,					/* Function type  */
    arr_type;
{
  int 	i, tmp,
        pgm_d, read_d, final;

  read_d = final = 0;

  if(option == 'p') {				/* Program data convert */
    pgm_d = convert(ca, ra, 0, option, arr_type);
  }

  for(i=0; i<25; i++) {
    @Out CA[0..2], ca;				/* Column address 	*/
    if(DEVICE <= d5C031) tmp = ra;
    else {
      if(arr_type == 0) tmp = ra + 2;
      else              tmp = ra;	
    }
    @Out RA[0..4], tmp;				/* Row address 		*/
    if(ca  > 0x07) @Out CA2, @O;		/* MSB on 		*/
    if(tmp > 0x1f) @Out RA4, @O;		/* MSB on 		*/
    if(option == 'p') {   			/* Program byte 	*/
      if(DEVICE <= d5C031) @Out VPP, @O;    
      @Out D[0..7], @W;				/* Data Out direction	*/
      @Out D[0..7], pgm_d;			/* Out data 		*/
      @Out PGM,     @L;				/* PGM enable		*/
      if(final == 1)  @Delay 3*i, @Ms;		/* Final pulse          */
      else     	      @Delay 1, @Ms;	  	/* Program base pulse   */
      @Out PGM,     @H;				/* PGM disable 		*/
      @Out D[0..7], @Z;                         /* Data In direction 	*/
      if(DEVICE <= d5C031) @Out VPP, @F;
    }
    @Out PGM,      @O;
    @In  D[0..7],  read_d;			/* READ data		*/
    @Out PGM,      @F;				/* PGM off 		*/
    @Out CA2,      @F;				/* MSB off 		*/    
    @Out RA4,      @F;				/* MSB off 		*/

    if(option == 'p') {
      if(final == 1) break;			/* Program success 	*/
      if(i == 24) @Exit;
      if(pgm_d&filter == read_d&filter) final = 1;	/* Need final pulse */
    }
    else break;
  }

  if(option != 'p') convert(ca, ra, read_d, option, arr_type);
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j;

  disp(option, 0);  
  init(option);

  for(i=0; i<10; i++) {				/* Normal array */
    for(j=0; j<36; j++) {
      sub(i, j, option, 0);
    }
  }
   						/*  EP310, 5C031 */
  if(DEVICE <= d5C031) {
    for(j=0; j<7; j++) 				/* ARCH array */
      sub(0x0b, 0x28+j, option, 0);
  }
						/* EP320, 5C032, 85C220 */
  else {
    for(i=0; i<9; i++) 				/* ARCH array */
      for(j=0; j<2; j++) 
        sub(i, j, option, 1);
  }
  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * Security device for EP310, d5C031
 * ----------------------------------------------------------------------- */
int security_device1()
{
  int 	i,
        final, 
        read_d;

  final = read_d = 0;  
    
  disp('s', 0);
  init('p');

  for(i=0; i<25; i++) {
    @Out VPP,     @O;    
    @Out CA[0..2], 0x0b;			/* Column address 	*/
    @Out RA[0..4], 0x2f;			/* Row address 		*/
    @Out CA2, @O;
    @Out RA4, @O;				/* MSB on 		*/

    @Out D[0..7],  @W;				/* Data Write direction */
    @Out D[0..7],  0x40;			/* Out data 		*/
    @Out PGM,      @L;
    if(final == 1) @Delay 3*i, @Ms; 		/* Final pulse       */
    else           @Delay 1, @Ms;	  	/* Program base pulse   */
    @Out PGM,      @H;
    @Out D[0..7],  @Z; 	                        /* Data In direction 	*/
    @Out VPP,      @F;				/* VPP off 		*/

    @Out PGM,      @O;				/* PGM on 		*/
    @In  D[0..7],  read_d;			/* READ data 		*/
    @Out PGM,      @F;				/* PGM off 		*/
    @Out CA2,      @F;
    @Out RA4,      @F;				/* MSB off 		*/

    if(i == 24) @Exit;
    if(final == 1) break;
    if((read_d & 0x40) == 0x40) final = 1;
  }    
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * Security device for EP320, d5C032, d85C220
 * ----------------------------------------------------------------------- */
int security_device2()
{
  int i, 
      read_d, 
      final,
      limit;					/* limit of program X=25 */

  read_d = final = 0;

  disp('s', 0);
  init('p');

  for(i=0; i<2; i++) {
    for(limit=0; limit<25; limit++) {
      @Out CA[0..2], 9;				/* Column address */
      @Out RA[0..4], i;				/* Row address */
      @Out CA2,      @O;

      @Out D[0..7],  @W;			/* Data Write direction */
      @Out D[0..7],  1;				/* Out data 		*/
      @Out PGM,      @L;
      if(final == 1) @Delay 3*limit, @Ms; 	/* Final pulse */
      else           @Delay 1, @Ms;	  	/* Program base pulse   */
      @Out PGM,      @H;
      @Out D[0..7],  @Z; 	                /* Data In direction 	*/

      @Out PGM,      @O;			/* Verify 		*/
      @In  D[0..7],  read_d;			/* READ data 		*/
      @Out PGM,      @F;			/* PGM off 		*/
      @Out CA2,      @F;			/* MSB off 		*/

      if(final == 1) break;			/* Program success 	*/
      if(limit == 24) @Exit;
      if((read_d&1) == 1) final = 1;		/* Need final pulse 	*/
    }
    final = 0;
  }
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;

  if     (FUNCTION == Program) {
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
  }
  else if(FUNCTION == Security) {
    if(DEVICE <= d5C031) security_device1();
    else  	         security_device2();
  }
  else if(FUNCTION == Read) {           	/* Read device        */
    top('r');	
    @CheckSumOn;
  }
  else if(FUNCTION == Blank_Check) {		/* Blank check device */
    top('b');
  }
  else if(FUNCTION == Verify) {     		/* Verify device      */
    top('v');
  }
  else if(FUNCTION == Auto) {
    top('b');					/* Blank check        */
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
    if(DEVICE <= d5C031) security_device1();
    else	         security_device2();
  }
}
/* ------------------------------- End of program ------------------------ */
  