/* ----------------------------------------------------------------P. S. O---
 *  FIRST UPDATE : Oct. 18. 1990
 *                 Dec.  5. 1990
 *                   1. 17. 1991 all ok!
 *  LIB Ver      : 1.00
 * --------------------------------------------------------------------------
 * PEEL173
 * Fuse_su		      : 2178     [54 * 40 others 18]
 * Internal Security Fuse     : 1
 * --------------------------------------------------------------------------
 * PEEL273
 * Fuse_su		      : 2714     [64 * 42 others 26]
 * Internal Security Fuse     : 1
 * ==========================================================================
 * MANUFACTURER : ICT
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vccp   | Programming Voltage          |   4.75  5.00  5.25  |   V
 * Vhh1   | Program/Verify Voltage1      |  11.00     - 15.50  |   V
 * Vhh2   | Program/Verify Voltage2      |  15.55     - 16.50  |   V
 * --------------------------------------------------------------------------
 * SYMBOL |                              | Diagram  | MIN  MAX  |  UNIT
 * -------+------------------------------+----------+-----------+------------
 * Tes    | ENA set-up to Vpp            | Pb, V, E | 4.00      |   us
 * Tms    | MODE set-up to Vpp           | Pb, V, E | 3.00      |   us
 * Tasle  | AD0-7 Address set-up to ALE  | Pb, V    | 1.00      |   us
 * Tahle  | AD0-7 Address hold after ALE | Pb, V    | 1.00      |   us
 * Tds    | AD0-7 DATA Set-up to Vpp     | Pb       | 1.00      |   us
 * Tas    | A8-11 Address Set-up to Vpp  | Pb, V    | 1.00      |   us
 * Trp    | Vpp rise time                | Pb, V, E |50.00      |   us/V
 * Tpw    | Vpp pulse width(Program)     | Pb, E    |10.00      |   ms
 * Tvw    | Vpp pulse width(Veify)       | V        | 1.00      |   us
 * Tfp    | Vpp fall time                | Pb, V, E | 1.00      |   us
 * Tdhle  | AD0-7 Date hold after Vpp    | Pb       | 1.00      |   us
 * Tah    | A8-11 Address hold after Vpp | Pb, V    | 1.00      |   us
 * Tmh    | Mode hold after Vpp          | Pb, V, E | 1.00      |   us
 * Teh    | VENA hold after Vpp          | Pb, V, E | 1.00      |   us
 * Tls    | ALE set-up to Vpp            | V        | 1.00      |   us
 * Tdv    | AD0-7 Data valid after Vpp   | V        | 1.00      |   us
 * Td2    | AD0-7 Date hold after Vpp    | V        | 1.00      |   us
 * Tvcgs  | VCG set-up to Vpp            | E        | 1.00      |   us
 * Tvcgh  | VCG hold after Vpp           | E        | 1.00      |   us
 * Taleh  | ALE hold after Vpp           | Pb, V    | 1.00      |   us
 * Tale   | ALE hold after Vpp           | Pb, V    | 5.00      |   us
 * Tts    | TEST set-up to ENA           | Pb, V, E | 1.00      |   us
 * Tth    | TEST hold after ENA          | Pb, V, E | 1.00      |   us
 * Taz1   | AD0-7 Hi-Z setup to ENA(rise)| Pb, V, E | 1.00      |   us
 * Taz2   | AD0-7 Hi-Z setup to ENA(rise)| Pb, V    | 1.00      |   us
 * ==========================================================================
  Pb : Program Byte
  V  : Verify Byte
  E  : Erase All
 * ======================================================================= */
declaration
  dataunit : bit 
  ;
  functions
    Program  
    Read
    Verify
    Blank_Check
    Security
    Auto
    Erase
  ;
  Manufacturers
    ICT
    GOULD
  ;
  Devices
    dPEEL173 
    dPEEL273

  ;
		/*  ΥΝΝΝΝΈΥΝΝΝΝΈ        */
  chips = ENA,  /* [³ 1     24 ³] VCC   */
	   C0,  /* [³ 2     23 ³] A7    */
	   C1,  /* [³ 3     12 ³] A6    */
	  VPP,  /* [³ 4     21 ³] A5    */
	 TEST,  /* [³ 5     20 ³] A4    */
      ALE_VCG,  /* [³ 6     19 ³] A3    */
	  NC0,  /* [³ 7     18 ³] A2    */
	  NC1,  /* [³ 8     17 ³] A1    */
	   A8,  /* [³ 9     16 ³] NC3   */
	   A9,  /* [³ 10    15 ³] A0    */
	  A10,  /* [³ 11    14 ³] A11   */
	  GND,  /* [³ 12    13 ³] NC2   */
		/*  ΤΝΝΝΝΝΝΝΝΝΝΎ        */
	NC2, A11, A0, NC3, A1, A2, A3, A4, A5, A6, A7, VCC;
  $v1 = ENA;
  $v2 = VPP, ALE_VCG;
  $v3 = VCC;
endd

  int or0173[3] = {0x05, 0x55,0x55};
  int or1173[3] = {   0,    2,   6};
  int xor173[2] = {0x03, 0xff};

  int or0273[3] = {0x0f, 0xff,0xff};
  int or1273[3] = {   0,    4,  12};
  int xor273[2] = {0x03, 0xff};

  
  int term_group[10] = {0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x09,0x0a,0x0a};
  int fuse_state[10] = {0xfd,0xf7,0xdf,0x7f,0xfd,0xf7,0xdf,0x7f,0x0d,0x07};

  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 == '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 init()
{
  @Vout 1,     5.00;	/* Vhh1 */
  @Vout 2,     5.00;    /* Vhh2 */
  @Vout 3,     5.00;    /* Vccp */
  @Out  GND,  	 @G;
  @Delay 10, @Ms;  

  @Out A[0..7],  @Z;
  @Out VCC,      @W;
  @Out NC[0..3], @W;  
  @Out ENA,      @W;
  @Out A[8..11], @W;
  @Out C[0..1],  @W;
  @Out TEST,     @W;
  @Out VPP,      @W;
  @Out ALE_VCG,  @W;

  @Out VCC,      @L;
  @Out NC[0..3], @L;
  @Out ENA,      @L;
  @Out A[8..11], @L;
  @Out C[0..1],  @L;
  @Out TEST,     @L;
  @Out VPP,      @L;
  @Out ALE_VCG,  @L;

  @Out VCC,	 @O;
  @Delay 100, @Us;
  @Raising ENA, 5.00, 12.50, 500;
  @Delay 100, @Us;
}
/* -----------------------------------------------------------------------
 * exit() ---> exit processing
 * ----------------------------------------------------------------------- */
int exit()
{
  @Out A[0..7],  @Z;
  @Falling ENA, 12.50, 5.00, 500;
}
/* -----------------------------------------------------------------------
 * 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(DEVICE == dPEEL173) {if(address > 2167) return;}
     else                   {if(address > 2167) return;}
     if(data&1 != 1)      @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;

  data = 0;
  @Set 0, address;
  @Store data;
  data <<= 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);
}
/* -----------------------------------------------------------------------
 *
 * ----------------------------------------------------------------------- */
int convert(i, j, data, arr_type, option)
int  i, j,	/* Column & Row */
     data,	/* Read data    */
     arr_type,  /* Array type   */
     option;    /* Option       */
{
  int k, l, pgm_d;

  l = pgm_d = 0;

if(DEVICE == dPEEL173) {
  if(arr_type == 0) {				 /* AND & OE array */ 
    for(k=0; k<8; k++) {
      if(i==5 && k>1) break;
      if(i < 4) pgm_d |= convert_sub((i*8 + k)*54 + j, data, k, option);
      else      pgm_d |= convert_sub(1728 + ((i - 4)*8 + k)*44 + j, data, k, option);
    }
  }
  else if(arr_type == 1) {			/* OR array */
    for(k=0; k<8; k++) {
      if(((or0173[i] << k) & 0x80) == 0) continue;
      pgm_d |= convert_sub(or1173[i] + j*54 + 44 + l, data, 7 - k, option);
      l++;
    }
    pgm_d |= 0xaa;
  }
  else if(arr_type == 2) {			/* EXOR array */
    for(k=0; k<8; k++) {
      if(((xor173[i] << k) & 0x80) == 0) continue;
      pgm_d |= convert_sub(2168 + i*2 + l, ~data, 7 - k, option);
      l++;
    }
    pgm_d = ~ pgm_d;             
  }
}
else {
  if(arr_type == 0) {				/* AND & OE array */
    for(k=0; k<8; k++) {
      if(i==5 && k>1) break;
      pgm_d |= convert_sub((i*8 + k)*64 + j, data, k, option);
    }
  }
  else if(arr_type == 1) {			/* OR array */
    for(k=0; k<8; k++) {
      if(((or0273[i] << k) & 0x80) == 0) continue;
      pgm_d |= convert_sub(or1273[i] + j*64 + 44 + l, data, 7 - k, option);
      l++;
    }
  }
  else if(arr_type == 2) {			/* EXOR array */
    for(k=0; k<8; k++) {
      if(((xor273[i] << k) & 0x80) == 0) continue;
      pgm_d |= convert_sub(2688 + i*2 + l, ~data, 7 - k, option);
      l++;
    }
    pgm_d = ~pgm_d;
  }
  else if(arr_type == 3) {			/* Signature array */
    for(k=0; k<8; k++) {
      pgm_d |= convert_sub(2713 - (i*8 + k), data, k, option);
    }
  }
}

  return(pgm_d);                 
}
/* -----------------------------------------------------------------------
 * 1 bit(s) data process
 * ----------------------------------------------------------------------- */
int sub(i, j, arr_type, option)
int  i,       					/* Column addressing	   */
     j,       					/* Row addressing	   */
     arr_type, 					/* Array type	 	   */
     option;   					/* Read, Program.. or more */
{
  int k, l, tmp,
      pgm_d,					/* Program data     */
      read_d,					/* Read data        */
      mode;					/* define mode 	    */

  read_d = pgm_d = l = 0;
  
  if(option == 'p') {				/* Programming byte conv */
    pgm_d = convert(i, j, 0, arr_type, option);
  }

  if(option == 'p') mode = 3;			/* Program mode 	*/
  else              mode = 1;			/* Verify mode  	*/

  @Out C[0..1], mode;				/* SET mode  	     	*/

  if(arr_type == 0)      tmp = i;       	/* AND & OE array 	*/
  else if(arr_type == 1) tmp = 0x0a - i; 	 /* OR array       	*/
  else if(arr_type == 2) tmp = 0x0b;	 	/* EXOR arry       	*/
  else if(arr_type == 3) tmp = 0x0c + i;	/* Signature array 	*/

  @Out A[8..11], tmp;				/* A8..11 Addressing 	*/
  @Out A[0..7],  @W;				/* AD0..7 Direction set */
  @Out A[1..6],  j;				/* AD0..7 Addressing 	*/
  @Out ALE_VCG,  @H;				/* Address latch 	*/

  if(option == 'p') {				/* Program byte 	*/
    @Out A[0..7], pgm_d;			/* Out data 		*/	
    @Raising VPP, 5.00, 16.00, 500;
    @Delay 10, @Ms;
    @Falling VPP, 16.00, 5.00, 500;
    @Out VPP,     @F;
  }
  else {					/* Verify byte 		*/
    @Out A[0..7], @Z;				/* AD0..7 Direction set */
    @Raising VPP, 5.00, 16.00, 500;
    @In A[0..7],  read_d;
    @Falling VPP, 16.00, 5.00, 500;
    @Out VPP,     @F;
    convert(i, j, read_d, arr_type, option);
  }
  @Out ALE_VCG, @L;
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j;

  disp(option, 0);         
  init();

  for(i=0; i<6; i++)           			/* AND array */
    for(j=0; j<44; j++)
      sub(i, j, 0, option);

if(DEVICE == dPEEL173) {
  for(i=0; i<3; i++)				/* OR  array */
    for(j=0; j<32; j++)
      sub(i, j, 1, option);

  for(i=0; i<2; i++)				/* XOR array */
    sub(i, 0x2c-i, 2, option);
}
else {
  for(i=0; i<3; i++)				/* OR  array */
    for(j=0; j<42; j++)
      sub(i, j, 1, option);

  for(i=0; i<2; i++)				/* XOR array */
    sub(i, 0x2c-i, 2, option);

  for(i=0;i<2;i++)				/* Signature ward */
    sub(i, 0x2a, 3, option);
}

  exit();
  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * Erase program
 * ----------------------------------------------------------------------- */
int erase_device()
{
  disp('e', 0);                 
  init();

  @Out C[0..1], 0;				/* Erase mode set */
  @Raising ALE_VCG, 5.00, 16.00, 500;
  @Out VPP,     @O;
  @Delay 10, @Ms;
  @Out VPP,     @F;
  @Falling ALE_VCG, 16.00, 5.00, 500;
  @Out ALE_VCG, @F;

  exit();
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('e', 1);
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security_device()
{
  disp('s', 0);
  init();

  @Out C[0..1],  3;				/* Program byte mode set */
  @Out A[8..11], 0x0b;
  @Out A[0..7],  @W;
  @Out A[0..7],  0x58;
  @Out ALE_VCG,  @H;
  @Out A[0..7],  3;
  @Raising VPP, 5.00, 16.00, 500;
  @Delay 10, @Ms;
  @Falling VPP, 16.00, 5.00, 500;
  @Out VPP,      @F;
  @Out ALE_VCG,  @L;
  
  exit();
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * PreProgram
 * ----------------------------------------------------------------------- */
int preprogram()
{
  int i;

  init();
  @Out A[0..7],  @W;				/* AD0..7 Direction set */

  @Out C[0..1],  3;				/* Program mode */

  for(i=0; i<10; i++) {
    @Out A[8..11], term_group[i];		/* A8..11 Addressing */
    @Out A[0..7],  0x40 + i*2;			/* AD0..7 Addressing */
    @Out ALE_VCG,  @H;				/* Address latch     */    
    @Out A[0..7],  fuse_state[i];		/* AD0..7 Addressing */
    @Raising VPP, 5.00, 16.00, 500;
    @Delay 10, @Ms;
    @Falling VPP, 16.00, 5.00, 500;
    @Out VPP,     @F;
    @Out ALE_VCG, @L;
  }
  exit();
}
/* -----------------------------------------------------------------------
 * MAIN Program
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;
  disp_flag = 0;

  if     (FUNCTION == Program) {
    erase_device();				/* Erase device       */
    if(DEVICE == dPEEL173) preprogram();	/* PreProgram	      */
    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();				/* Erase device	      */
    if(DEVICE == dPEEL173) preprogram();	/* PreProgram	      */
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
    security_device();	                        /* Security device    */
  }
  else if(FUNCTION == Erase) {
    erase_device();				/* Erase device       */
  }
}
/* ------------------------------- End of program ------------------------ */
 