/* --< 6 >---------------------------------------------------------P. S. O--
 *  FIRST UPDATE : Oct. 15. 90
 *  LIB Ver      : 1.00
 * -------------------------------------------------------------------------
 * Fuse_su		      : 5828     [44 * 132 others 20]
 * Internal Security Fuse     : 1        [Verify --> blank_check OK]
 * ==========================================================================
 * MANUFACTURER : ATMEL
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vpp    | Programming Voltage          |  12.00 12.50 13.00  |   V
 * Vccp   | Programming supply voltage   |   5.75  6.00  6.25  |   V
 * Tpw    | PGM InitalProgram pulse Width|   0.95  1.00  1.05  |   ms
 * Topw   | PGM Overprogram pulse Width  |   2.85     - 78.75  |   ms
 * Tas    | Addrss Setup Time            |      2              |   us
 * Toes   | OE Setup Time                |      2              |   us
 * Tds    | Data SEtup Time              |      2              |   us
 * Tah    | Addrss Hold Time             |      0              |   us
 * Tdh    | Data Hold Time               |      2              |   us
 * Tvcs   | Vcc Setup Time               |      2              |   us
 * ==========================================================================
 * MANUFACTURER : SAMSUNG & CYPRESS
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vpp    | Programming Voltage          |  13.00 13.50 14.00  |   V
 * Vccp   | Programming supply voltage   |   4.75  5.00  5.25  |   V
 * Tpw    | PGM InitalProgram pulse Width|    0.1  1.00 10.00  |   ms
 * Ts     | Setup Time                   |    1.0              |   us
 * Th     | Hold time                    |    1.0              |   us
 * Tr, Tf | Vpp Rise and Fall Time       |    1.0              |   us
 * Tvd    | Delay to Verify              |    1.0              |   us
 * Tvp    | Verify pulse width           |    2.0              |   us
 * Tdv    | Verify to Data valid         |   20.0              |   us
 * Tdz    | Verify to High Z             |                1.0  |   us
 * ==========================================================================
 * MANUFACTURER : MMI
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vpp    | Programming Voltage          |  13.25 13.50 13.75  |   V
 * Vccp   | Programming supply voltage   |   4.75  5.00  5.25  |   V
 * Vcclv  | Low Supply Voltage Verify    |   4.40  4.50  4.60  |   V
 * Vcchv  | High Supply Voltage Verify   |   5.40  5.50  5.60  |   V
 * Tp     | Delay to Programming Voltage |  20.00 20.10 20.20  |   ms
 * Tdp    | Delay to Programming         |   1.00  2.00  5.00  |   us
 * Thp    | Hold from Programming or Verify  1.00  2.00  5.00  |   us
 * Tr,Tf  | Vpp Rise and Fall Time       |  50.00 55.00 60.00  |   us
 * Ts     | Setup Time                   |   1.00  2.00  5.00  |   us
 * Th     | Hold Time                    |   1.00  2.00  5.00  |   us
 * Tspp   | Security Programming Pulse Width49.90 50.00 50.10  |   ms
 * Tpp    | Variable Algo Base Pulse Width   0.95  1.00  1.05  |   ms
 * Tdv    | Delay from Programming to Verify 2.00  3.00  4.00  |   us
 * Tvd    | Delay to data available      |   0.50  1.00  2.00  |   us
 * Tvp    | Verfiy Pulsewidth            |   2.00  3.00  4.00  |   us
 * Tdz    | Verify to High Z             |   0.50  1.00  2.00  |   us
 * ==========================================================================
 * MANUFACTURER : TI
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vihh   | Programming Voltage          |  13.00 13.50 14.00  |   V
 * Vccp   | Programming supply voltage   |   4.75  5.00  5.25  |   V
 * Tpw    | PGM InitalProgram pulse Width|   0.95  1.00  1.05  |   ms
 * Topw   | PGM Overprogram pulse Width  |   3.80     - 42.00  |   ms
 * Tas    | Addrss Setup Time            |      1              |   us
 * Tah    | Address Hold Time            |      1              |   us
 * Thp    | Hold from Program or Verify  |      1              |   us
 * Tds    | Data Setup Time              |      1              |   us
 * Tdh    | Data Hold Time               |      1              |   us
 * Tscty  | Programming PW for Security  |  50.00	       |   ms
 * Tdv    | Dealy from Program to Verify |      2	       |   us
 * tvd    | Dealy to data out 		 |		 1     |   us
 * tvp    | Verify Pluse Width           |      2              |   us
 * Tdz    | Verify to High Z             |		 1     |   us
 *------------------------------------------------------------------------ */
declaration
  dataunit : bit
  ;
  functions
    Program
    Read
    Verify
    Blank_Check
    Security
    Auto
  ;
  Manufacturers
    ATMEL
    AMD__MMI
    CYPRESS
    SAMSUNG
    TI
  ;
  Devices
    dATV22V10		/* ATMEL   */
    dPALC22V10B		/* CYPRESS */
    dCPL22V10   	/* SAMSUNG, CYPRESS */
    dTICPAL22V10 	/* TI      */
    dPALC22V10		/* MMI     */
  ;
		/*  ------v-----        */
  chips = VPP,  /* [³ 1     24 ³] Vcc   */
	   A0,  /* [³ 2     23 ³] D9    */
	   A1,  /* [³ 3     22 ³] D8    */
	   A2,  /* [³ 4     21 ³] D7    */
	   A3,  /* [³ 5     20 ³] D6    */
	   A4,  /* [³ 6     19 ³] D5    */
	   A5,  /* [³ 7     18 ³] D4    */
	   A6,  /* [³ 8     17 ³] D3    */
	   A7,  /* [³ 9     16 ³] D2    */
	   A8,  /* [³ 10    15 ³] D1    */
	   A9,  /* [³ 11    14 ³] D0    */
	  GND,  /* [³ 12    13 ³] PGM_OE*/
		/*  ------------        */
	PGM_OE, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, VCC;

  $v2 = VPP, PGM_OE, A1, A2, A3, A9;
  $v3 = VCC;
endd

voltage PVpp,
        PVcc;
int     S_pw,
        first_pw,
        mul = 3,
        loop;
int 	filter;            

int limit[10] =
{ 8,10,12,14,16,16,14,12,10,8 };

int addr[42] =                          /* PROGRAM START ADDRESS --------- */
   {  88, 484, 968,1540,2200,2948,3696,4356,4928,5412,	/* Normal fuse */
      44, 440, 924,1496,2156,2904,3652,4312,4884,5368,  /* OE fuse     */
    5808,5810,5812,5814,5816,5818,5820,5822,5824,5826,  /* P fuse      */
    5809,5811,5813,5815,5817,5819,5821,5823,5825,5827,  /* R fuse      */
       0,5764};						/* AR, SP fuse */

int disp_flag = 0;
int index     = 6;
/* -----------------------------------------------------------------------
 * 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()
{
  if(MFG == ATMEL) {			/* If Manufacturer EQ ATMEL 	*/
    loop     = 125;			/* Set program loop count 	*/
    PVpp     = 12.50;			/* Set Program voltage 		*/
    PVcc     = 6.00;			/* Set Program Vcc voltage	*/
    first_pw = 1000;
  }
  else if(MFG == AMD__MMI) {
    loop     = 	10;
    PVpp     = 	13.50;
    PVcc     = 	5.00;
    S_pw     =  1; /* Ms */
    first_pw =  1000;
  }
  else if(MFG == TI) {
    loop     = 	10;
    PVpp     =  13.50;
    PVcc     =  5.00;
    first_pw =  1000;
    S_pw     =  50; /* Ms */
    mul      =  4;
  }
  else if(MFG == SAMSUNG) {
    loop     = 20;
    PVpp     = 13.50;
    PVcc     = 5.00;
    S_pw     = 1; /* Ms */
    first_pw = 100;
    mul      = 4;
  }
  else if(MFG == CYPRESS) {
    loop     = 	5;
    if(DEVICE == dPALC22V10) PVpp = 13.50;
    else                     PVpp = 12.50;
    PVcc     =  5.00;
    S_pw     =  1; /* Ms */
    first_pw =  400;
  }
  @Vout 1,    PVpp;	/* NULL */
  @Vout 2,    PVpp;
  @Vout 3,    PVcc;
  @Out  GND,  	 @G;
  @Delay 10, @Ms;

  @Out A[0..9],  @W;
  @Out D[0..9],  @Z;
  @Out VPP,      @W;
  @Out PGM_OE,   @W;

  @Out A[0..9],  @L;
  @Out VPP,      @L;
  @Out PGM_OE,   @H;

  @Out  VCC, 	 @O;
  @Delay 40 , @Ms;
  @Out  VPP,     @O;
  @Delay 100, @Us;
}
/* -----------------------------------------------------------------------
 * 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     */
    tmp = 0;
    if(data&1 != tmp)    @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(pt, it, data, arr_type, option)
int pt, it,					/* Column & Row */
    data,					/* Read data    */
    arr_type,  					/* Array type   */
    option;   				 	/* Option       */
{
  int j, pgm_d;

  pgm_d = filter = 0;

  if(arr_type == 0) {				/* Normal array */
    for(j=0; j<10; j++) {
      if(pt < limit[j]) {
        pgm_d |= convert_sub(addr[j]+(pt*44)+it, data, 9-j, option);
        filter |= 1 << j;
      }
    }
  }
  else if(arr_type == 1) {			/* OE array */
    for(j=0; j<10; j++) {
      pgm_d |= convert_sub(addr[j+10]+it, data, 9-j, option);
    }
    filter = 0x3ff;
  }
  else if(arr_type == 2 || arr_type == 3) {	/* P & R array */
    for(j=0; j<10; j++) {
      pgm_d |= convert_sub(addr[j+arr_type*10], data, 9-j, option);
    }
    filter = 0x3ff;    
  }
  else if(arr_type == 4) {			/* AR & SP array */
    if(MFG == ATMEL) {
      pgm_d |= convert_sub(addr[40]+it, data, 1, option);
      pgm_d |= convert_sub(addr[41]+it, data, 8, option);
      filter = 0x102;          
    }
    else {
      pgm_d |= convert_sub(addr[40]+it, data, 6, option);
      pgm_d |= convert_sub(addr[41]+it, data, 3, option);
      filter = 0x48;          
    }
  }
  else if(arr_type == 5) {			/* Security array */
    pgm_d = filter = 0x0100;
  }

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * 1 bit data process
 * ----------------------------------------------------------------------- */
int sub(pt, it, arr_type, option)
int  pt,       					/* Column addressing     */
     it,       					/* Input line addressing */
     arr_type, 					/* Array flag		 */
     option;   					/* Read, Program..  or more */
{
  int i, j,
      flag,             			/* Final fulse flag */
      pgm_d,					/* Program data    */
      read_d;					/* Read data       */

  pgm_d = flag = 0;

  if(option == 'p' || option == 's') {		/* Programming byte conv   */
    pgm_d = convert(pt, it, 0, arr_type, option);
  }
        
  for(i=0; i<loop; i++) {			/* Limit of program        */

    if(MFG == ATMEL) {                  	
      @Out A[0..3], pt;				/* Product term address    */
      @Out A[4..9], it;                 	/* Input term address      */
      if(arr_type > 0) @Out A3, @O;		/* A3 Vpp on               */
    }
    else {
      @Out A[6..9], pt;				/* Product term address    */
      @Out A[0..5], it;				/* Input term address      */
      if(arr_type == 1 || arr_type == 2 || arr_type == 3 || arr_type == 5)
	@Out A9, @O;
    }
						/* LOAD DATA TO pgm_d ----- */
						/* PROGRAM A BIT(S) ------- */
    if(option == 'p' || option == 's') {
      @Out D[0..9], @W;				/* Direction : write        */
      @Out D[0..9], pgm_d;			/* Program data             */
      @Out PGM_OE,  @O;
      if(flag == 0) @Delay first_pw, @us;
      else          @Delay first_pw*i*mul, @us;
      @Out PGM_OE,  @F;
      @Out D[0..9], @Z;				/* Direction : read 	    */
    }
						/* READ DATA -------------- */
    @Out PGM_OE, @L;				/* PGM_OE : verify mode     */
    @In D[0..9], read_d;			/* Read data from device    */
    @Out PGM_OE, @H;				/* PGM_OE : normal mode     */
    @Out A3,     @F;
    @Out A9,     @F;
    if(MFG != TI) read_d = ~read_d;/* convert data             */
						/* PROGRAM VERIFY --------- */
    if(option == 'p') {
      if(flag == 1) break;			/* Program OK! & final pulse out */
      if(i == loop-1) @Exit;
      if(read_d&filter == pgm_d&filter) flag = 1;/* Need last program pulse */
    }
    else {
      convert(pt, it, read_d, arr_type, option);
      break;
    }
  }
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j, k;

  disp(option, 0);
  init();

  for(i=0; i<16; i++) {                         /* Normal array */
    for(j=0; j<44; j++) {
      sub(i, j, 0, option);
    }
  }
  for(j=0; j<44; j++) {				/* OE ARRAY -------------- */
    if(MFG == ATMEL) sub(0, j, 1, option);
    else             sub(7, j, 1, option);	/* MFG:SAMSUNG,CYPRESS,MMI,TI */
  }
						/* P & R ARRAY ----------- */
  if(MFG == ATMEL) {
    sub(1, 63, 2, option);			/* P array */
    sub(2, 63, 3, option);			/* R array */
  }
  else if(MFG == SAMSUNG || MFG == CYPRESS) {
    sub(0, 0, 2, option);			/* P array */
    sub(2, 0, 3, option);			/* R array */
  }
  else {
    sub(0, 0x3f, 2, option);			/* P array */
    sub(2, 0x3f, 3, option);			/* R array */
  }

  for(j=0; j<44; j++) {				/* AR & SP ARRAY */
    if(MFG == ATMEL) sub( 3, j, 4, option);
    else                    sub(15, j, 4, option); /* MFG:SAMSUNG,CYPRESS,MMI,TI */
  }
  disp(option, 1);             
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security_device()		/* ATMEL & TI Security test ok ! */
{
  int tmp;

  disp('s', 0);

  init();
  if     (MFG == ATMEL) sub(5, 63, 5, 's');
  else {
    @Out A1,     @O;
    @Out PGM_OE, @O;
    @Delay S_pw, @Ms;
    @Out PGM_OE, @F;
    @Out A1,     @F;
    	
    @Out A1,     @Z;
    @Out A2,     @O;
    @In A1, tmp;
    @Out A2,     @F;
    if(tmp&1 == 0)  @Exit;
  }
/*  else {  samsung
    @Out A1,     @O;
    @Out PGM_OE, @O;
    @Delay S_pw, @Ms;
    @Out PGM_OE, @F;
    @Out A1,     @F;
    @Out VPP,    @F;
    
    @Out A1,     @Z;
    @Out A2,     @O;
    @In A1, tmp;
    @Out A2,     @F;
@Display 1,1, tmp;    
    if(tmp&1 == 1) @Exit;
  }*/

  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;

  if     (FUNCTION == Program) {
    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) {
    top('b');					/* Blank check        	*/
    top('p');					/* Program device     	*/
    top('v');					/* Verify device      	*/
    security_device();	                        /* Security device    	*/
  }
}
/* ------------------------------- end of program ------------------------ */
  