/* -----------------------------------------------------------------------
 *  FIRST UPDATE : 3. 12. 1991.
 *  LIB Ver      : 1.00
 *  Fuse_su      : 13713     [68 * others ]
 *  Security Fuse: 1     
 *----------------------------------------------------------------------*/
declaration
  dataunit : bit 
  ;
  functions
    Program    
    Read
    Verify
    Blank_Check
    Security
    Auto
  ;
  Manufacturers
    INTEL
  ;
  Devices
    D5AC312
  ;
		/*  +---v---+       */
  chips = VPP,  /* [|1    24|] VCC  */
	   D0,  /* [|2    23|] NC4  */
	  PWB,  /* [|3    22|] D6   */
	   M0,  /* [|4    21|] NC3  */
	   M1,  /* [|5    20|] D5   */
	  CA0,  /* [|6    19|] NC2  */
	  CA1,  /* [|7    18|] D4   */
	  CA2,  /* [|8    17|] D3   */
	  CA3,  /* [|9    16|] NC1  */
	  CA4,  /* [|10   15|] D2   */
	   D1,  /* [|11   14|] NC0  */
	  GND,  /* [|12   13|] CA5  */
		/*  +-------+       */
	  CA5, NC0, D2, NC1, D3, D4, NC2, D5, NC3, D6, NC4, VCC;
	  
  $v2 = VPP;
  $v3 = VCC;
endd

int addr0[8] = 
  {    0,  2176,  4352,  6528,  8704, 10880, 13056}; 
int addr1[8] = 
  { 1088,  3264,  5440,  7616,  9792, 11968};  
int addr2[8] =
  {13600, 13616, 13632, 13648, 13664, 13680};   
  
int io_bit0[8] = { 1, 2, 3, 5, 6, 0, 4};
int io_bit1[8] = { 2, 3, 1, 6, 0, 5};
    

int filter;

int index, disp_flag;
/* -----------------------------------------------------------------------
 * 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;
  @Vout 2,     5.00;
  @Vout 3,     5.00;
  @Out  GND,  	 @G;

  @Out VCC,      @W;
  @Out NC[0..4], @Z;
  @Out CA[0..5], @W;
  @Out D[0..6],  @Z;
  @Out PWB,	 @W;
  @Out M[0..1],  @W;
  @Out VPP,      @W;

  @Out VCC,      @L;
  @Out CA[0..5], @L;
  @Out PWB,	 @H;
  @Out M[0..1],  @L;
  @Out VPP,      @L;

  @Out VCC, 	 @O;
  @Delay 100, @Us;
  @Raising VPP, 5.00, 12.75, 100;
  @Delay 100, @Us;
}
int exit(flag)
int flag;
{
  @Falling VPP, 12.75, 5.00, 100;
  @Out VPP, @F;
  @Delay 100, @Us;
  @Out VCC, @F;
  
  if(flag == 1) @Exit; 
}
/* -----------------------------------------------------------------------
 * Sector change program
 * ----------------------------------------------------------------------- */
int change_sector(sector)
int sector;
{
  int i, tmp;

  @Out M[0..1], 0;  
  
  if(sector == 1) tmp = 0x34;
  else		  tmp = 0x2b;

  @Out D[0..6], @W;

  for(i=0; i<8; i++) {
    if((tmp >> i) & 1 == 1) @Out D[0..6], @H;
    else                    @Out D[0..6], @L;

    @Out PWB, @L;
    @Out PWB, @H;
  }
  @Out D[0..6], @Z;
}
/* -----------------------------------------------------------------------
 * Read data from device
 * Blank check
 * Verify
 * ----------------------------------------------------------------------- */
int verifyf(address, data, shift, option)
int address, data, shift, option;
{
  int	tmp;

  @Set 0, address;
  @Display 67, 9, address, @d;
  data = (data >> shift) & 1;
  
  if     (option == 'r') @Load data;		/* Read data	   */
  else if(option == 'b') {			/* Blank check     */
    if(data & 1 != 0)    exit(1);
  }
  else if(option == 'v') {			/* Verify check    */
    @Store tmp;
    if ((tmp&1) != (data&1)) exit(1);
  }
}
/* -----------------------------------------------------------------------
 * putdata() --> Write data to device
 * ----------------------------------------------------------------------- */
int putdata(address, shift)
int address, shift;
{
  int data;

  @Display 67, 9, address, @d;

  @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, arr_type, option)
int  i,       					/* Column addressing	*/
     j,       					/* Row addressing	*/
     read_d,					/* Read data    	*/
     arr_type,  	
     option;    				/* Option       	*/
{
  int k, pgm_d, address, shift;

  pgm_d = 0;

  if     (arr_type==5) {			/* Security */
    pgm_d = filter = 0x10;
  }
  else if(arr_type==0) {
    for(k=0; k<7; k++) {
      if(io_bit0[k] == 4) {
        if(i > 7)  address = addr0[k] + (i-8)*68 + j;
        else       continue;
      }
      else address = addr0[k] + i*68 + j;
      pgm_d |= convert_sub(address, read_d, io_bit0[k], option);
    }
    if(i > 7) filter = 0x7f;
    else      filter = 0x6f;
  }
  else if(arr_type==1) {
    for(k=0; k<6; k++) {
      address = addr1[k] + (i-0x20)*68 + j;
      if(i < 0x24) shift = io_bit1[k];
      else         shift = io_bit0[k];
      pgm_d |= convert_sub(address, read_d, shift, option);
    }
    filter = 0x6f;
  }
  else if(arr_type==2) {
    for(k=0; k<6; k++) pgm_d |= convert_sub(addr2[k]+(i-0x10)*16+j-0x0b, read_d, io_bit0[k], option);
    filter = 0x6f;
  }
  else if(arr_type==3) {
    for(k=0; k<6; k++) pgm_d |= convert_sub(addr2[k]+8+(i-0x30)*16+j-0x0b, read_d, io_bit0[k], option);
    filter = 0x6f;
  }
  else if(arr_type==4) {
    pgm_d |= convert_sub(13696 + (j-1), read_d, 4, option);
    filter = 0x10;
  }

  return(pgm_d);
}
/* -----------------------------------------------------------------------
 * Sub program
 * ----------------------------------------------------------------------- */
int sub(ca, ra, option, arr_type)
int  ca,					/* Column Address */
     ra,					/* Row Address    */
     arr_type,					/* array type     */
     option;					/* Function type  */
{
  int 	i;
  int   pgm_d, read_d;

  read_d = pgm_d = 0;

  if(option == 'p') {				/* Program data convert */
    pgm_d = convert(ca, ra, read_d, arr_type, option);
  }

  for(i=0; i<4; i++) {
    @Out M0,       @L;
    @Out M1,       @H;
    @Out PWB,      @L;
    @Out CA[0..5], ca;				/* Column address out	*/
    @Out D[0..6],  @W;
    @Out D[0..6],  ra;				/* ROW address out	*/
    @Out PWB,      @H;				/* address latched	*/
    if(option == 'p') {   			/* Program byte 	*/
      @Out M0,     @H;
      @Out M1,     @H;
      @Out D[0..6], pgm_d;			/* Out data 		*/
      @PinDelay PWB, @L, @H, 100;
    }
    @Out D[0..6], @Z;				/* Data In direction 	*/    
    @Out M0,      @H;
    @Out M1,      @L;    
    @Out PWB,     @L;				/* PGM on 		*/
    @In  D[0..6], read_d;			/* READ data 		*/
    @Out PWB,     @H;				/* PGM off 		*/
    @Out M0,      @L;
    if(option == 'p') {
      if((filter&pgm_d) == (filter&read_d)) break;
    }     
    else break; 
  }
  if(i > 2) {
    @Exit;
  }

  if(option != 'p') convert(ca, ra, read_d, arr_type, option);
}
/* -----------------------------------------------------------------------
 * Top program
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int i, j;

  disp(option, 0);

  init();
  change_sector(1);

  for(i=0; i<0x10; i++)
    for(j=0; j<0x44; j++)
      sub(i, j, option, 0);

  for(i=0x0b; i<0x13; i++)
    sub(0x10, i, option, 2);
    
  for(i=1; i<0x12; i++)
    sub(0x10, i, option, 4);  

  change_sector(2);

  for(i=0x20; i<0x30; i++)
    for(j=0; j<0x44; j++)
      sub(i, j, option, 1);

  for(i=0x0b; i<0x13; i++)
    sub(0x30, i, option, 3);    

  exit(0);

  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * Security device
 * ----------------------------------------------------------------------- */
int security()
{
  disp('s', 0);

  init();
  change_sector(1);
  sub(0x10, 0x12, 'p', 5);
  disp('s', 1);
  exit(0);
}
/* -----------------------------------------------------------------------
 * MAIN Porgram
 * ----------------------------------------------------------------------- */
int main()
{
  index = 6;
  disp_flag = 0;

  if     (FUNCTION == Program) {
    top('p');					/* Program device     */
    top('v');					/* Verify device      */
  }
  else if(FUNCTION == Security) {
    security();
  }
  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();					/* Security device    */
  }
}
/* ------------------------------- End of program ------------------------ */
 