/* ----------------------------------------------------------------P. S. O---
 *  FIRST UPDATE : Oct. 10. 1990
 *                 Dec.  5. 1990  
 *                   1. 17. 1991  (p, r, b, v, s, e, v_test ok!)
 *  LIB Ver      : 1.00
 * --------------------------------------------------------------------------
 * Fuse_su		      : 2194     [32 * ]
 * Internal Security Fuse     : 1
 * ==========================================================================
 * MANUFACTURER : AMD
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vccp   | VCC During Programming       |   4.75  5.00  5.25  |   V
	  |                              |                     |
 * Vpp    | Programming Voltage 1000 0000|  13.25 13.50 13.75  |   V
 * Vpp    | Programming Voltage 0000 0010|   9.00  9.25  9.50  |   V
	  |				 |		       |
 * VHH    | Input Super Voltage 1000 0001|  10.25 10.50 10.75  |   V
 * VHH    | Input Super Voltage 0000 0010|   9.00  9.25  9.50  |   V
	  |				 |		       |
 * VCCL   | During Low Vcc Verify        |   4.5   4.6   4.7   |   V
 * VCCH   | During High VCC Verify       |   5.3   5.4   5.5   |   V
 * VIHP   | Input High Voltage           |   2.4   5.0   Vcc   |   V
 * VILP   | Input Low Voltage            |   0.0   0.2   0.5   |   V
 * VOH    | Output Higt Voltage          |   2.4   3.0   4.0   |   V
 * VOL    | Output Low Voltage           |   0.1   0.2   0.5   |   V
 * IPP    | Programming Supply Current   |   3.0   4.0   5.0   |   mA
 * TPROG  | Programming Pulse width      |  49.9  50.0  50.1   |   ms
 * TERASE | Erase pulse width            |  99.9 100.0 100.1   |   ms
 * TD     | Delay time                   |   0.9   1.0   5.0   |   us
 * TR     | Rise time of Vpp             |  35.0  40.0  45.0   |   us
 * TF     | Fall time of Vpp             |  35.0  40.0  45.0   |   us
 * ======================================================================== */

declaration
  dataunit : bit
  ;
  functions
    Program
    Read
    Verify
    Blank_Check
    Security
    Auto
    Erase
  ;
  Manufacturers
    AMD
  ;
  Devices
    dRAL10H8     	/*  0 */
    dRAL10L8            /*  1 */
    dRAL10P8            /*  2 */
    dRAL12H6            /*  3 */
    dRAL12L6            /*  4 */
    dRAL12P6            /*  5 */
    dRAL14H4            /*  6 */
    dRAL14L4            /*  7 */
    dRAL14P4            /*  8 */
    dRAL16H2            /*  9 */
    dRAL16L2            /* 10 */
    dRAL16P2            /* 11 */
    dRAL16H8            /* 12 */
    dRAL16L8            /* 13 */
    dRAL16P8            /* 14 */
    dRAL16R4            /* 15 */
    dRAL16R6            /* 16 */
    dRAL16R8            /* 17 */
    dRAL16RP4           /* 18 */
    dRAL16RP6           /* 19 */
    dRAL16RP8           /* 20 */
    dPALCE16V8
  ;
                /*  ΥΝΝΝΝΈΥΝΝΝΝΈ        */
  chips = CLK,  /* [³ 1     20 ³] VCC   */
         SDIN,  /* [³ 2     19 ³] D7    */
          VPP,  /* [³ 3     18 ³] D6    */
        MODE0,  /* [³ 4     17 ³] D5    */
        MODE1,  /* [³ 5     16 ³] D4    */
        MODE2,  /* [³ 6     15 ³] D3    */
        MODE3,  /* [³ 7     14 ³] D2    */
          PGM,  /* [³ 8     13 ³] D1    */
          NC0,  /* [³ 9     12 ³] D0    */
          GND,  /* [³ 10    11 ³] NC1   */
                /*  ΤΝΝΝΝΝΝΝΝΝΝΎ        */
	  NC1, D0, D1, D2, D3, D4, D5, D6, D7, VCC;

  $v2 = VPP;
  $v3 = VCC;
endd

char arch_con[378] =
 {1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0, 1,0,	/* 10H8  */
  0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,	/* 10L8  */
  2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0, 1,0,	/* 10P8  */
  1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,1, 1,0,	/* 12H6  */
  0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,1, 1,0,	/* 12L6  */
  0,2,2,2,2,2,2,0, 1,0,0,0,0,0,0,1, 1,0,	/* 12P6  */
  1,1,1,1,1,1,1,1, 1,1,0,0,0,0,1,1, 1,0,	/* 14H4  */
  0,0,0,0,0,0,0,0, 1,1,0,0,0,0,1,1, 1,0,	/* 14L4  */
  0,0,2,2,2,2,0,0, 1,1,0,0,0,0,1,1, 1,0,	/* 14P4  */   
  1,1,1,1,1,1,1,1, 1,1,1,0,0,1,1,1, 1,0,	/* 16H2  */
  0,0,0,0,0,0,0,0, 1,1,1,0,0,1,1,1, 1,0,	/* 16L2  */
  0,0,0,2,2,0,0,0, 1,1,1,0,0,1,1,1, 1,0,	/* 16P2  */
  1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,	/* 16H8  */
  0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1, 1,1,	/* 16L8  */
  0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1, 1,1,	/* 16P8  */
  0,0,0,0,0,0,0,0, 1,1,0,0,0,0,1,1, 0,1,	/* 16R4  */
  0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,1, 0,1,	/* 16R6  */
  0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,1,	/* 16R8  */
  2,2,2,2,2,2,2,2, 1,1,0,0,0,0,1,1, 0,1,	/* 16RP4 */
  2,2,2,2,2,2,2,2, 1,0,0,0,0,0,0,1, 0,1,	/* 16RP6 */
  2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0, 0,1};	/* 16RP8 */
char pt_d[168] = 
 {0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
  0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
  0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
  0x00,0x0f,0x03,0x03,0x03,0x03,0x0f,0x00,
  0x00,0x0f,0x03,0x03,0x03,0x03,0x0f,0x00,
  0x00,0x0f,0x03,0x03,0x03,0x03,0x0f,0x00,
  0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,
  0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,
  0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,
  0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,
  0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,
  0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};	

voltage VPPH, VHH;
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 ++;
  }
}
/* -----------------------------------------------------------------------
 * RAL convert
 * ----------------------------------------------------------------------- */
int RAL_convert()
{
  int  i, k;
  char tmp;

  for(i=0; i<8; i++) {
    tmp = arch_con[DEVICE*18+i];
    if(tmp == 2) continue;
    @Set 0, 2048+i;
    @Load tmp;
  }
  for(i=0; i<8; i++) {
    tmp = arch_con[DEVICE*18+i+8];
    @Set 0, 2120+i;
    @Load tmp;
  }
  for(i=0; i<2; i++) {
    tmp = arch_con[DEVICE*18+i+16];
    @Set 0, 2192+i;
    @Load tmp;
  }
  for(i=0; i<8; i++) {
    tmp = pt_d[DEVICE*8+i];
    for(k=0; k<8; k++) {
      @Set 0, i*8+k+2128;
      if((tmp >> k) & 1 == 1) @Load 1;
      else		      @Load 0;
    }
  }
}
/* -----------------------------------------------------------------------
 * init() ---> inital processing
 * ----------------------------------------------------------------------- */
int enter(vol2)
voltage vol2;
{
  @Vout 1,         vol2;  /* NULL */
  @Vout 2,	   vol2;
  @Vout 3, 	   5.00;
  @Out  GND, 	   @G;  
  @Delay 10, @Ms;

  @Out NC[0..1],   @W;
  @Out CLK,        @W;
  @Out SDIN,       @W;
  @Out MODE[0..3], @W;
  @Out PGM,        @W;
  @Out D[0..7],    @Z;

  @Out NC[0..1],   @L;
  @Out CLK,        @L;
  @Out SDIN,       @L;
  @Out MODE[0..3], @L;
  @Out PGM,        @L;

  @Out VCC, 	   @O;
  @Delay 100, @us;    
  @Out VPP,        @O;
  @Delay 100, @us;  
}
/* -----------------------------------------------------------------------
 * exit() ---> exit processing
 * ----------------------------------------------------------------------- */
int exit()
{
  @Out VPP, @F;
  @Out VCC, @F;
} 
/* -----------------------------------------------------------------------
 * Out Clock
 * ----------------------------------------------------------------------- */
int clock()
{
  @Out CLK, @H;
  @Out CLK, @L;
}
/* -----------------------------------------------------------------------
 * Read | Verify | Blank_check device
 * ----------------------------------------------------------------------- */
int verifyf(address, shift, data, option)
int address,
    shift,
    data,
    option;
{
  int 	tmp;

  @Display 67, 9, address, @d;
  
  @Set 0, address;
  data >>= shift;

  if     (option == 'r') @Load data;
  else if(option == 'v') {
    @Store tmp;
    if (tmp&1 != data&1) @Exit;
  }
  else if(option == 'b') {
    if(address > 2047) return;
    if(data&1 != 1)      @Exit;
  }
}
/* -----------------------------------------------------------------------
 * input addressing process
 * ----------------------------------------------------------------------- */
int input_addressing(i, option)
int i, option;
{
  int j;
  
  @Out MODE[0..3], 1;
  if(i > 33) i += 26;
  if(option == 'i') i = 58;
  if(option == 's') i = 59;
  for(j=0; j<6; j++) {
    @Out SDIN, (i >> (5-j)) & 1;
    clock();
  }
  @Out SDIN, @L;
}
/* -----------------------------------------------------------------------
 * Read data from device
 * Blank check
 * Verify
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int 	i, j, k,
        data,
    	tmp;

  disp(option, 0);
  enter(VHH);

  for(i=0; i<38; i++) {
    input_addressing(i, option);
    @Out MODE[0..3], 2;
    for(j=0; j<64; j++) {
      @Out SDIN, @L;
      if(i < 34) {
        if(j%8==7) @Out SDIN, @H;
      }
      clock();
    }
    @Out SDIN,  @L;    
    @Out MODE[0..3], 4;

    if(i < 34)	{
      for(j=0; j<8; j++) {
	@In D[0..7], data;
	clock();

	for(k=0; k<8; k++) {
	  if     (i< 32) tmp = 1792-(k*256)+(j*32)+i;  	/* Normal fuse */
	  else if(i==32) tmp = 2063-j+k*8;		/* UES fuse */
	  else if(i==33) tmp = 2135-j+k*8;		/* PT disable fuse */
	  verifyf(tmp, k, data, option);
	}
      }
    }
    else {
      @In D[0..7], data;
      clock();
      if     (i==34) {				/* XOR fuse */
	for(j=0; j<8; j++) verifyf(2055-j, j, data, option);
      }
      else if(i==35) {                          /* AC1 fuse */
	for(j=0; j<8; j++) verifyf(2127-j, j, data, option);
      }
      else if(i==36) {                          /* SYN fuse */
	verifyf(2192, 7, data, option);
      }
      else if(i==37) {                          /* AC0 fuse */
	verifyf(2193, 7, data, option);
      }
    }
  }
  exit();
  disp(option, 1);  
}
/* -----------------------------------------------------------------------
 * Program data to device
 * ----------------------------------------------------------------------- */
int program_device()
{
  int 	i, j;
  int	data, tmp;

  disp('p', 0);
  data = 0;
  if(DEVICE != dPALCE16V8) RAL_convert();
  enter(VPPH);

  for(i=0; i<38; i++) {
    input_addressing(i, 'p');
    @Out MODE[0..3], 2;				/* Product line addressing */
    for(j=0; j<64; j++) {
      if     (i< 32) tmp = 2016-j*32+i;		/* Normal fuse */
      else if(i==32) tmp = 2056+j;      	/* UES fuse */
      else if(i==33) tmp = 2128+j;      	/* PT disable fuse */
      else if(i==34) {				/* XOR fuse */
	if(j % 8 == 0) tmp = 2055-(j/8);
      }
      else if(i == 35) {			/* AC1 fuse */
	if(j % 8 == 0) tmp = 2127-(j/8);
      }
      else if(i == 36) {			/* SYN fuse */
	if(j == 56)    tmp = 2192;
      }
      else if(i == 37) {			/* AC0 fuse */
	if(j == 56)    tmp = 2193;
      }
      @Display 67, 9, tmp, @d;
      @Set 0, tmp;		 	             	
      @Store data;
      @Out SDIN, data;

      clock();
      @Out SDIN,  @L;      
    }
    @Out MODE[0..3], 3;				/* Program a bit(s) */
    @Out PGM, @H;
    @Delay 50, @Ms;
    @Out PGM, @L;
  }
  exit();
  disp('p', 1);  
}
/* -----------------------------------------------------------------------
 * ID Check
 * ----------------------------------------------------------------------- */
int ID_check()
{
  int 	i, j, tmp,
        data;

  enter(10.0);

  input_addressing(i, 'i');
  @Out MODE[0..3], 2;				/* Product line addressing */
  for(i=0; i<64; i++) clock();
  @Out MODE[0..3], 4;				/* Read data */
  @In D[0..7], data;

  if     (data == 0x80) {VPPH = 13.50; VHH = 10.50;}
  else if(data == 0x40) {VPPH =  9.25; VHH =  9.25;}
  else {
    @Display 26, 6, "Invalid ID !";
    @Exit;					/* device IC check error */
  }

  exit();
}
/* -----------------------------------------------------------------------
 * Erase device
 * ----------------------------------------------------------------------- */
int erase_device()
{
  disp('e', 0);
  enter(VPPH);

  @Out MODE[0..3], 0;
  @Out PGM, @H;
  @Delay 100, @Ms;
  @Out PGM, @L;
  exit(); 

  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('e', 1);
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security_device()
{
  int i;
               
  disp('s', 0);
  enter(VPPH);

  input_addressing(59, 's');
  @Out MODE[0..3],  2;				/* Product line addressing */
  for(i=0; i<64; i++) clock();
  @Out MODE[0..3], 3;				/* Program a bit(s) */
  @Out PGM, @H; 
  @Delay 50, @Ms;
  @Out PGM, @L;

  exit();
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;
  disp_flag = 0;

  ID_check();					/* Check ID */

  if     (FUNCTION == Program) {
    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 ------------------------ */
 