/* ----------------------------------------------------------------P. S. O---
 *  FIRST UPDATE : Oct. 18. 1990
 *                 Dec.  6. 1990   (PEEL22CV10) All ok !
 *				   (PEEL20CG10) preprogram check request
 *		     1. 17. 1991  all ok ! 		   
 *  LIB Ver      : 1.00
 * --------------------------------------------------------------------------
 * PEEL 22CV10
 * Fuse_su		      : 5828     [44 * 132 others 20]
 * Internal Security Fuse     : 1
 * -------------------------------------------------------------------------- 
 * PEEL 20CG10
 * Fuse_su		      : 4088     [44 * 92 others 40]
 * Internal Security Fuse     : 1
 * ==========================================================================
 * MANUFACTURER : ICT
 * --------------------------------------------------------------------------
 * SYMBOL |                              |    MIN   TYP   MAX  |  UNIT
 * -------+------------------------------+---------------------+-------------
 * Vccp   | Programming Voltage          |   4.75  5.00  5.25  |   V
 * Vhh    | Program/Verify Enable Voltage|  15.00     - 16.00  |   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
  ;
  Devices
    dPEEL20CG10     
    dPEEL22CV10
  ;
		/*  ΥΝΝΝΝΈΥΝΝΝΝΈ        */
  chips = PVE,  /* [³ 1     24 ³] VCC   */
	MODE0,  /* [³ 2     23 ³] D7    */
	MODE1,  /* [³ 3     12 ³] D6    */
	  VPP,  /* [³ 4     21 ³] A5:D5 */
	MODE2,  /* [³ 5     20 ³] A4:D4 */
	  ALE,  /* [³ 6     19 ³] A3:D3 */
	   A6,  /* [³ 7     18 ³] A2:D2 */
	   A7,  /* [³ 8     17 ³] A1:D1 */
	   A8,  /* [³ 9     16 ³] A0:D0 */
	   A9,  /* [³ 10    15 ³] NC2   */
	  A10,  /* [³ 11    14 ³] NC1   */
	  GND,  /* [³ 12    13 ³] NC0   */
		/*  ΤΝΝΝΝΝΝΝΝΝΝΎ        */
	NC0, NC1, NC2, A0:D0, A1:D1, A2:D2, A3:D3, A4:D4, A5:D5, D6, D7, VCC;

  $v2 = PVE;
  $v3 = VCC;
endd

int term_g[16] = {0   ,1   ,2   ,3   ,4   ,5   ,6   ,8   ,10  ,11  ,
		  12  ,13  ,14  ,15  ,16};
int pt[16]     = {0   ,8   ,16  ,22  ,28  ,34  ,36  ,44  ,52  ,60  ,
		  64  ,70  ,74  ,82  ,88};
int fuse_s[16] = {0xff,0xff,0xfc,0xfc,0xfc,0xc0,0xff,0xff,0xff,0xf0,
		  0xfc,0xf0,0xff,0xfc,0x0f};
int pt_addr[16]= {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x08,0x0a,0x0b,
		  0x0c,0x0d,0x0e,0x0f,0x10};

  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;    /* NULL */
  @Vout 2,       5.00;    /* Vhh  */
  @Vout 3,       5.00;    /* Vccp */
  @Out  GND,       @G;
  @Delay 10, @Ms;
  
  @Out VCC,        @W;
  @Out NC[0..2],   @W;  
  @Out D[0..7],    @Z;
  @Out A[6..10],   @W;
  @Out MODE[0..2], @W;
  @Out PVE,        @W;
  @Out ALE,        @W;
  @Out VPP,        @W;

  @Out VCC,        @L;
  @Out NC[0..2],   @L;
  @Out A[6..10],   @L;
  @Out MODE[0..2], @L;
  @Out PVE,        @L;
  @Out ALE,        @L;
  @Out VPP,        @L;

  @Out VCC,	 @O;
  @Delay 100, @Us;
  @Raising PVE, 5.00, 15.50, 500;
  @Delay 100, @Us;
}
/* -----------------------------------------------------------------------
 * exit() ---> exit processing
 * ----------------------------------------------------------------------- */
int exit()
{
  @Out D[0..7],    @Z;
  @Falling PVE, 15.50, 5.00, 500;  
  @Out PVE, @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 != 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, j,					/* Column & Row */
     data,					/* Read data    */
     arr_type,  				/* Array type   */
     option;    				/* Option       */
{
  int k, l, pgm_d;

  l = pgm_d = 0;          
  
if(DEVICE == dPEEL22CV10) {
  if(arr_type == 0) {				/* NORMAL array */
    for(k=0; k<8; k++) {
      if(i == 16)  {
	if(k > 3) break;
	pgm_d |= convert_sub(5632 + k*44 + j, data, k, option);
      }
      else pgm_d |= convert_sub((i*8 + k)*44 + j, data, k, option);
    }
  }
  else if(arr_type == 1) {			/* MACRO array */
    pgm_d |= convert_sub(5808 + (i-0x11)*2, data, 0, option);
    pgm_d |= convert_sub(5809 + (i-0x11)*2, data, 2, option);
  }
  
}

else if(DEVICE == dPEEL20CG10){
  if(arr_type == 0) {				/* NORMAL array */
    for(k=0; k<8; k++) {
      if(((fuse_s[i]>>k)&1) == 0)  continue;
      pgm_d |= convert_sub(pt[i]*44 + l*44 + j, data, k, option);
      l++;
    }
  }
  else if(arr_type == 1) {			/* MACRO array */
    for(k=0; k<8; k++) {
      if(((0x55>>k)&1) == 0)  continue;
      pgm_d |= convert_sub(4048 + (i-0x11)*4 + l, data, k, option);
      l++;
    }
  }
}

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * 1 byte 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;
  int pgm_d,					/* Program data     */
      read_d,					/* Read data        */
      mode;					/* define mode 	    */

  pgm_d = 0;

  if(option == 'p') {                          	/* Program mode 	*/
    mode = 3;			
    pgm_d = convert(i, j, 0, arr_type, option);
  }
  else mode = 1;				/* Verify mode  	*/

  @Out MODE[0..2], mode;			/* SET mode 		*/

  @Out A[0..5],  @W;
  if(DEVICE == dPEEL20CG10) {
    if(arr_type == 0) @Out A[6..10], pt_addr[i];    
    else              @Out A[6..10], i;
  }
  else @Out A[6..10], i;  			/* A6..10 Addressing 	*/
  
  @Out A[0..5],  j;				/* AD0..7 Addressing 	*/
  @Out ALE,      @H;				/* Address latch	*/

  if(option == 'p') {				/* Program byte 	*/
    @Out D[0..7], @W;				/* D0..7 Direction set  */
    @Out D[0..7], pgm_d;			/* Out data 		*/
    @Out VPP,     @H;
    @Delay 10, @Ms;
    @Out VPP,     @L;
  }
  else {					/* Verify byte 		*/
    @Out D[0..7], @Z;				/* AD0..7 Direction set */
    @Out VPP,     @H;
    @In D[0..7], read_d;
    @Out VPP,     @L;
    convert(i, j, read_d, arr_type, option);
  }
  @Out ALE,     @L;  
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j;

  disp(option, 0);
  init();

if(DEVICE == dPEEL22CV10) {
  for(i=0; i<17; i++)          			/* NORMAL array */
    for(j=0; j<44; j++)
      sub(i, j, 0, option);

  for(i=0; i<10; i++)				/* MACRO array */
    sub(i+0x11, 0x2c, 1, option);
}
else if(DEVICE == dPEEL20CG10) {
  for(i=0; i<15; i++)         			/* NORMAL array */
    for(j=0; j<44; j++) 
      sub(i, j, 0, option);

  for(i=0; i<10; i++) 				/* MACRO array */
    sub(i+0x11, 0x2c, 1, option);
}
  exit();
  disp(option, 1);      
}
/* -----------------------------------------------------------------------
 * Erase program
 * ----------------------------------------------------------------------- */
int erase_device()
{
  disp('e', 0);              
  init();

  @Out MODE[0..2], 0;				/* Erase mode set */
  @Out VPP,        @H;
  @Delay 10, @Ms;
  @Out VPP,        @L;

  exit();
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('e', 1);
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security_device()
{
  disp('s', 0);
  init();

  @Out MODE[0..2], 3;				/* Program byte mode set */
  @Out A[6..10],   0x1b;
  @Out A[0..5],    @W;
  @Out A[0..5],    0x2c;
  @Out ALE, 	   @H;
  @Out D[0..7],    @W;
  @Out D[0..7],    0xfe;
  @Out VPP,        @H;
  @Delay 10, @Ms;
  @Out VPP,        @L;

  exit();

  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('s', 1);
}
/* -----------------------------------------------------------------------
 * PreProgram
 * ----------------------------------------------------------------------- */
int preprogram()
{
  int i, j;

  init();

  @Out MODE[0..2], 3;				/* SET mode 		*/

  for(i=0; i<2; i++) {
    for(j=0; j<44; j++) {
      @Out A[6..10], 7+i*2;			/* A6..10 Addressing 	*/
      @Out A[0..5],  @W;			/* AD0..5 Direction set */
      @Out A[0..5],  j;                		/* AD0..7 Addressing 	*/
      @Out ALE,      @H;			/* Address latch	*/
      @Out D[0..7],  @W;
      @Out D[0..7],  0;
      @Out VPP,      @H;
      @Delay 10, @Ms;
      @Out VPP,      @L;
      @Out ALE,      @L;
    }
  }
  exit();
}
/* -----------------------------------------------------------------------
 * MAIN Program
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;
  disp_flag = 0;

  if     (FUNCTION == Program) {
    erase_device();
    if(DEVICE == dPEEL20CG10) 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();
    if(DEVICE == dPEEL20CG10) preprogram();    
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
    security_device();	                        /* Security device    */
  }
  else if(FUNCTION == Erase) {
    erase_device();				/* Erase device       */
  }
}
/* ------------------------------- End of program ------------------------ */
 