/* ----------------------------------------------------------------P. S. O--
 *  FIRST UPDATE : Oct. 18. 1990
 *                 Dec.  5. 1990
 *                   1. 17. 1991 all ok!
 *  LIB Ver      : 1.00
 * -------------------------------------------------------------------------
 * Fuse_su		      : 2696     [36 * 64 others 32]
 * Internal Security Fuse     : 1
 * ==========================================================================
 * MANUFACTURER : HYUNDAI / ICT
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vccp   | Programming Voltage          |   4.75  5.00  5.25  |   V
 * Vhh1   | Program/Verify Voltage1      |  11.50     - 13.00  |   V
 * Vhh2   | Program/Verify Voltage2      |  15.00     - 16.00  |   V
 * --------------------------------------------------------------------------
 * SYMBOL |                              | Diagram  | MIN  MAX  |  UNIT
 * -------+------------------------------+----------+-----------+------------
 * Taz1   | AD0-7 Hi-Z setup to ENA(rise)| Pb, V, E | 1.00      |   us
 * Tps    | PVE 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/Erase) Pb, E    |10.00      |   ms
 * Tsp    | PVP Security pulse width     | S        |300        |   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
 * 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
    HYUNDAI
    ICT
  ;
  Devices
    dHY18CV8	/* HYUNDAI */
    dPEEL18CV8	/* ICT     */
  ;
		/*  ΥΝΝΝΝΈΥΝΝΝΝΈ          */
  chips = PVE,  /* [³ 1     20 ³] VCC     */
	MODE0,  /* [³ 2     19 ³] IAD7    */
	MODE1,  /* [³ 3     18 ³] IAD6    */
	  PVP,  /* [³ 4     17 ³] IAD5    */
	 TGA0,  /* [³ 5     16 ³] IAD4    */
	 TGA1,  /* [³ 6     15 ³] IAD3    */
	 TGA2,  /* [³ 7     14 ³] IAD2    */
	 TGA3,  /* [³ 8     13 ³] IAD1    */
	  SEC,  /* [³ 9     12 ³] IAD0    */
	  GND,  /* [³ 10    11 ³] ALE_ERA */
		/*  ΤΝΝΝΝΝΝΝΝΝΝΎ          */
	ALE_ERA, IAD0, IAD1, IAD2, IAD3, IAD4, IAD5, IAD6, IAD7, VCC;
  $v1 = PVE;
  $v2 = PVP, ALE_ERA, SEC;
  $v3 = VCC;
endd

int iad_l[37] = { 0x01, 0x03, 0x02, 0x04, 0x05,
		  0x07, 0x21, 0x23, 0x09, 0x0b,
		  0x1d, 0x1f, 0x0d, 0x0f, 0x19,
		  0x1b, 0x11, 0x13, 0x15, 0x17,
		  0x12, 0x14, 0x18, 0x16, 0x0e,
		  0x10, 0x1c, 0x1a, 0x0a, 0x0c,
		  0x20, 0x1e, 0x06, 0x08, 0x24,
		  0x22, 0x25};

  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 2, @Ms;

  @Out IAD[0..7],  @Z;
  @Out VCC,        @W;
  @Out ALE_ERA,    @W;
  @Out TGA[0..3],  @W;
  @Out MODE[0..1], @W;
  @Out PVE,        @W;
  @Out PVP,        @W;
  @Out SEC,        @W;

  @Out VCC,        @L;
  @Out ALE_ERA,    @L;
  @Out TGA[0..3],  @L;
  @Out MODE[0..1], @L;
  @Out PVE,        @L;
  @Out PVP,        @L;
  @Out SEC,        @L;

  @Out VCC,	   @O;
  @Delay 100, @Us;
  @Raising PVE, 5.00, 12.50, 500;
}
/* -----------------------------------------------------------------------
 * exit() ---> exit processing
 * ----------------------------------------------------------------------- */
int exit()
{
  @Out IAD[0..7],  @Z;
  @Falling PVE, 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(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;

  @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);
}
/* -----------------------------------------------------------------------
 * convert
 * ----------------------------------------------------------------------- */
int convert(i, j, data, arr_type, option)
int  i,       	/* Term group addressing	*/
     j,       	/* Input line addressing	*/
     data,	/* Read data    */
     arr_type,  /* Array type   */
     option;    /* Option       */
{
  int k, pgm_d;

  pgm_d = 0;
               
  if(arr_type == 0) {				/* NORMAL array */
    for(k=0; k<8; k++) {
      pgm_d |= convert_sub((i*8 + (7-k))*36 + j, data, k, option);
    }
  }
  else if(arr_type == 1) {			/* OE array */
    for(k=0; k<8; k++) {
      pgm_d |= convert_sub(2304 + (7-k)*36 + j, data, k, option);
    }
  }
  else if(arr_type == 2) {			/* SP & AR array */
    pgm_d |= convert_sub(2592 + j, data, 1, option);
    pgm_d |= convert_sub(2628 + j, data, 0, option);
  }
  else if(arr_type == 3) {			/* MACRO array */
    for(k=0; k<4; k++) {
      pgm_d |= convert_sub(2664 + i*4 + k, data, k*2 + 1, option);
    }
  }

  return(~pgm_d);
}
/* -----------------------------------------------------------------------
 * 1 byte data process
 * ----------------------------------------------------------------------- */
int sub(i, j, arr_type, option)
int  i,       	/* Term group addressing	*/
     j,       	/* Input line 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 	    */

  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 MODE[0..1], mode;			/* SET mode */

  if     (arr_type == 0) tmp= 8 - i;    	/* NORMAL array */
  else if(arr_type == 1) tmp= 9;		/* OE array	*/
  else if(arr_type == 2) tmp= 0x0a;     	/* AR & SP array*/
  else if(arr_type == 3) tmp= 8 - i;    	/* MACRO array  */

  @Out TGA[0..3], tmp;				/* Term group Addressing */
  @Out IAD[0..7], @W;				/* IAD0..7 Direction set */
  @Out IAD[0..7], iad_l[j];			/* Input line Addressing */
  @Out ALE_ERA,   @H;				/* Address latch         */

  if(option == 'p') {				/* Program byte -------- */
    @Out IAD[0..7], pgm_d;			/* Out data		 */
    @Raising PVP, 5.00, 15.50, 500;
    @Out ALE_ERA,   @L;				/* ALE --> Vil		 */
    @Delay 10, @Ms;				/* Dealy 10 ms 		 */
    @falling PVP, 15.50, 5.00, 500;
    @Out PVP, @F;
  }
  else {					/* Verify byte --------- */
    @Out IAD[0..7], @Z;				/* IAD0..7 Direction set */
    @Raising PVP, 5.00, 15.50, 500;
    @Out ALE_ERA,   @L;				/* ALE --> Vil		 */
    @In IAD[0..7], read_d;
    @falling PVP, 15.50, 5.00, 500;
    @Out PVP, @F;
    convert(i, j, read_d, arr_type, option);
  }
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j;

  disp(option, 0);
  init();

  for(i=0; i<8; i++)           			/* NORMAL array */
    for(j=0; j<36; j++)
      sub(i, j, 0, option);

  for(j=0; j<36; j++)          			/* OE array */
      sub(9, j, 1, option);

  for(j=0; j<36; j++)				/* AR & SP array */
    sub(0x0a, j, 2, option);

  for(i=0; i<8; i++)				/* MACRO array */
    sub(i, 36, 3, option);

  exit();
  disp(option, 1);         
}
/* -----------------------------------------------------------------------
 * Erase program
 * ----------------------------------------------------------------------- */
int erase_device()
{
  disp('e', 0);
  init();

  @Out MODE[0..1], 0;				/* Erase mode set        */
  @Out TGA[0..3],  0;				/* Term group Addressing */
  @Out IAD[0..7],  @W;				/* IAD0..7 Direction set */
  @Out IAD[0..7],  0;				/* Input line Addressing */
  @Raising ALE_ERA, 5.0, 15.5, 500;
  @Out PVP,        @O;   			/* PVP --> VIHH 	 */
  @Delay 10, @Ms;  				/* Dealy 10 ms 		 */
  @Out PVP,        @F;				/* PVP --> Vil		 */
  @Falling ALE_ERA, 15.5, 5.0, 500;
  @Out ALE_ERA, @F;
  @Out IAD[0..7],  @Z;				/* IAD0..7 Direction set */

  exit();
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('e', 1);
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security_device()
{
  disp('s', 0);
  init();

  @Out MODE[0..1], 3;				/* Security mode set     */
  @Out TGA[0..3],  0;				/* Term group Addressing */
  @Out IAD[0..7],  @W;				/* IAD0..7 Direction set */
  @Out IAD[0..7],  0;				/* Input line Addressing */
  @Out ALE_ERA,    @H;				/* Address latch 	 */
  @Raising SEC, 5.0, 15.5, 500;
  @Out PVP,        @O;   			/* PVP --> VIHH */
  @Delay 300, @Ms;  				/* Dealy 300 ms */
  @Out PVP,        @F;				/* PVP --> Vil	*/
  @Falling SEC, 15.5, 5.0, 500;
  @Out IAD[0..7],  @Z;				/* IAD0..7 Direction set */

  exit();
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * MAIN Program
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;
  disp_flag = 0;

  if     (FUNCTION == Program) {
    erase_device();				/* Erase device       */
    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	      */
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
    security_device();	                        /* Security device    */
  }
  else if(FUNCTION == Erase) {
    erase_device();				/* Erase device       */
  }
}
/* ------------------------------- End of program ------------------------ */
  