/* ----------------------------------------------------------------P. S. O-
 *  FIRST UPDATE : Dec.  7. 1990
 *		     1. 16. 1991 all ok !
 *  LIB Ver      : 1.00
 * ------------------------------------------------------------------------
 *  EP900
 *  ALTERA=EP900/EP910  INTEL=5C090  TI=EP910
 * ------------------------------------------------------------------------
 * Fuse_su		      : 17402    [72 * 241 others 50]
 * 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
    TI
  ;
  Devices
    dEP900	/* ALTERA */
    dEP910	/* ALTERA */
    d5C090	/* INTEL  */
    d85C090     /* INTEL  ok ! */
    dTIEP910	/* TI     */
  ;
  chips =
         /*  ÕÍÍÍÍÍÍÍÍÍ¸       */
   PGM,  /* o³01     40³o VCC  */
   RA5,  /* o³02     39³o RA4  */
   NC0,  /* o³03     38³o NC14 */
   NC1,  /* o³04     37³o NC13 */
   D0,   /* o³05     36³o RA3  */
   D1,   /* o³06     35³o RA2  */
   NC2,  /* o³07     34³o NC12 */
   NC3,  /* o³08     33³o CA4  */
   D2,   /* o³09     32³o CA3  */
   D3,   /* o³10     31³o CA2  */
   D4,   /* o³11     30³o CA1  */
   D5,   /* o³12     29³o CA0  */
   NC4,  /* o³13     28³o NC11 */
   NC5,  /* o³14     27³o NC10 */
   D6,   /* o³15     26³o RA1  */
   D7,   /* o³16     25³o RA0  */
   RA6,  /* o³17     24³o NC9  */
   NC6,  /* o³18     23³o RA7  */
   NC7,  /* o³19     22³o NC8  */
   GND,  /* o³20     21³o VPP  */

  VPP, NC8, RA7,  NC9,  RA0,  RA1, NC10, NC11, CA0, CA1, 
  CA2, CA3, CA4,  NC12, RA2,  RA3, NC13, NC14, RA4, VCC;

  $v2 = PGM, VPP;
  $v3 = VCC;
endd

int addr[80] =
  {    0,  720, 2880, 3600, 4320, 5040, 7200, 7920,
     999, 1440, 2160,  999,  999, 5760, 6480,  999,	/* 999 -> not define */
    8640, 9360,11520,12240,12960,13680,15840,16560,
     999,10080,10800,  999,  999,14400,15120,  999,
   17280,17285,17300,17305,17310,17315,17330,17335,
     999,17290,17295,  999,  999,17320,17325,  999,
   17340,17345,17360,17365,17370,17375,17390,17395,
     999,17350,17355,  999,  999,17380,17385,  999,
   17400,  999,  999,  999,  999,  999,  999,  999,
   17401,  999,  999,  999,  999,  999,  999,  999};
   
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;

  @Out VCC,      @W;
  @Out NC[0..14],@Z;
  @Out CA[0..4], @W;
  @Out RA[0..7], @W;
  @Out D[0..7],  @Z;
  @Out PGM,	 @W;
  @Out VPP,      @W;

  @Out VCC,      @L;
  @Out CA[0..4], @L;
  @Out RA[0..7], @L;
  @Out PGM,      @H;
  @Out VPP,      @L;

  @Out VCC, 	 @O;
  @Delay 100, @Us;
  if(DEVICE == d85C090)  @Raising VPP, 5.00, 12.50, 100;
  else                   @Raising VPP, 5.00, 12.75, 100;
  @Delay 100, @Us;
}
int exit()
{
  if(DEVICE == d85C090) @Falling VPP, 12.50, 5.00, 100;
  else			@Falling VPP, 12.75, 5.00, 100;
  @Out VPP, @F;
  @Delay 100, @Us;
  @Out VCC, @F;
}
/* -----------------------------------------------------------------------
 * 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);
}
/* -----------------------------------------------------------------------
 * Program data convert
 * ----------------------------------------------------------------------- */
int convert(i, j, read_d, point, arr_type, option)
int  i,       					/* Column addressing	*/
     j,       					/* Row addressing	*/
     read_d,					/* Read data    	*/
     point,
     arr_type,  	
     option;    				/* Option       	*/
{
  int k, pgm_d;

  filter = pgm_d = 0;

  if(option == 's') {
    filter = pgm_d = 0x80;
    return(pgm_d);
  }
    
  for(k=0; k<8; k++) {
    if(addr[arr_type * 8 + k]==999) continue;
    else pgm_d |= convert_sub(addr[arr_type * 8 + k] + point, read_d, k, option);
    filter |= 1 << k;
  }

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * Sub program
 * ----------------------------------------------------------------------- */
int sub(ca, ra, option, point, arr_type)
int  ca,					/* Column Address */
     ra,					/* Row Address    */
     point,     				/* address point  */
     arr_type,					/* array type     */
     option;					/* Function type  */
{
  int 	i, j;
  int   pgm_d, read_d, final;

  read_d = pgm_d = final = 0;

  if(option == 'p' || option == 's') {		/* Program data convert */
    pgm_d = convert(ca, ra, 0, point, arr_type, option);
  }

  for(i=0; i<25; i++) {
    @Out CA[0..4], ca;				/* Column address 	*/
    @Out RA[0..7], ra;
    if(option == 'p' || option == 's') {	/* Program byte 	*/
      @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 	*/
    }
    @Out PGM,     @O;				/* PGM on 		*/
    @In  D[0..7], read_d;			/* READ data 		*/
    @Out PGM,     @F;				/* PGM off 		*/

    if(option == 'p') {
      if(final == 1) break;			/* Program success 	*/
      if(i ==24)  @Exit;
      if((filter&pgm_d) == (filter&read_d)) final = 1;	/* Need final pulse */      
    }
    else break;
  }

  if(option != 'p' && option != 's') convert(ca, ra, read_d, point, arr_type, option);
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j, k;


  disp(option, 0);
  init(option);

  k = 0;
  for(i=0; i<10; i++)
	for(j=0; j<72; j++)
		sub(i,     j, option, k++, 0);
  k = 0;
  for(i=0x10; i<0x1a; i++)
	for(j=0; j<72; j++)
		sub(i,     j, option, k++, 1);
  k = 0;
  for(i=0; i<10; i++)
	for(j=0; j<72; j++)
		sub(i,j+0x80, option, k++, 2);
  k = 0;
  for(i=0x10; i<0x1a; i++)
	for(j=0; j<72; j++)
		sub(i,j+0x80, option, k++, 3);
  k = 0;
  for(i=0x0a; i<0x0f; i++)
	sub(i,0x48, option, k++, 4);
  k = 0;
  for(i=0x1a; i<0x1f; i++)
	sub(i,0x48, option, k++, 5);
  k = 0;
  for(i=0x0a; i<0x0f; i++)
	sub(i,0xc8, option, k++, 6);
  k = 0;
  for(i=0x1a; i<0x1f; i++)
	sub(i,0xc8, option, k++, 7);
  k = 0;
  sub(0x0f,0xc8, option, k++, 8);
  k = 0;
  sub(0x0f,0x48, option, k++, 9);

  exit();
  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security()
{
  disp('s', 0);
  init('p');
  
  sub(0x0f, 0xc8, 's', 0, 10);

  exit();
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;

  if     (FUNCTION == Program) {		/* Program device     */
    top('p');					
    top('v');					
  }
  else if(FUNCTION == Security) {		/* Security device    */
    security();
  }
  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) {			/* Auto */
    top('b');
    top('p');
    top('v');
    security();
  }
}
/* ------------------------------- End of program ------------------------ */
 