/*******************************************************************
 *    File Name : 28FXXX.D	(Flash Memory)
 *
 *    Device 	: INTEL 28F020  (Vpp:12.0  Vcc:5.0  10us)
 *    Size	: 2M   (3FFFF)
 *    Pin num	: 32-pin	(A0..A17   D0..D7)  
 *
 *    Device 	: INTEL 28F010  (Vpp:12.0  Vcc:5.0  10us)
 *		  AMD	28F010
 *		  NS	48F010
 *
 *    Size	: 1M   (1FFFF)
 *    Pin num	: 32-pin	(A0..A16   D0..D7) 
 *
 *    Device 	: INTEL 28F512  (Vpp:12.0  Vcc:5.0  10us)
 *		  AMD	28F512-P1
 *		  NS	48F512
 *		  TI	29F512
 *
 *    Size	: 512K (FFFF)
 *    Pin num	: 32-pin	(A0..A15   D0..D7)
 *
 *    Device 	: INTEL 28F256  (Vpp:12.0  Vcc:5.0  10us)
 *    Size	: 256K (7FFF)
 *    Pin num	: 32-pin	(A0..A14   D0..D7) 
 *
 *    Last Modify Date : 91. 3. 12
 ********************************************************************/
declaration
   dataunit : byte;
   functions
      Program
      Read
      Verify
      Blank_Check
      Data_Compare
      Erase
      Auto      
   ;
   Manufacturers
      AMD
      INTEL
      NS
      TI	      
   ;
   Devices
      D28F020   	/* 0 */
      D28F010		/* 1 */
      D48F010   	/* 2 */
      D28F512		/* 3 */
      D28F512_P1	/* 4 */
      D48F512		/* 5 */
      D29F512		/* 6 */
      D28F256      	/* 7 */
   ;
                   ΥΝΝΝΈΥΝΝΝΈ
  chips = Vpp, /* [³ 1   32 ³] VCC */
          A16, /* [³ 2   31 ³] WE  */
          A15, /* [³ 3   20 ³] NC  */
          A12, /* [³ 4   29 ³] A14 */
          A7,  /* [³ 5   28 ³] A13 */
          A6,  /* [³ 6   27 ³] A8  */
          A5,  /* [³ 7   26 ³] A9  */
          A4,  /* [³ 8   25 ³] A11 */
          A3,  /* [³ 9   24 ³] OE  */
          A2,  /* [³10   23 ³] A10 */
          A1,  /* [³11   22 ³] CE  */
          A0,  /* [³12   21 ³] D7  */
          D0,  /* [³13   20 ³] D6  */
          D1,  /* [³14   19 ³] D5  */
          D2,  /* [³15   18 ³] D4  */
          GND, /* [³16   17 ³] D3  */
               /*  ΤΝΝΝΝΝΝΝΝΎ      */
	  D3, D4, D5, D6, D7, CE, A10, OE, A11, A9, A8, A13, A14, A17, WE, Vcc;
	
   $v2 = Vpp;
   $v3 = Vcc;
endd

int disp_flag, index;
/* -----------------------------------------------------------------------
 * 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 == 'e') @Display 26, index, "Erasing ...";    
  }
  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 == 'e') @Display 26, index, "Erase OK!  ";    
    index ++;
  }
}
/* ----------------------------------------------------------------------- 
 * init () ---> Initial processing
 * ----------------------------------------------------------------------- */
int init (option)
int option;
{
   @Vout 1,	5.0;
   @Vout 2,	5.0;
   @Vout 3,	5.0;
   
   @Out GND,	@G;
   @Delay 10, @ms;

   @Out D[0..7],  @Z;
   @Out A[0..15], @W;
   @Out A[16..17],@W;
   @Out CE,	  @W;
   @Out WE,	  @W;
   @Out OE,	  @W;
   @Out Vcc,  	  @W;
   @Out Vpp,	  @W;   

   @Out A[0..15], @L;
   @Out A[16..17],@L;   
   @Out CE,	  @H;
   @Out WE,	  @H;
   @Out OE,	  @H;
   @Out Vcc,	  @H;
   @Out Vpp,	  @H;

   @Out Vcc,	@O;
   @Delay 1, @Ms;
   if(option == 'p') @Raising Vpp, 5.0, 12.0, 200;
   @Delay 1, @Ms;
   

}

int command(data)
int data;
{
  @Out CE,      @L;
  @Out WE,      @L;
  @Out D[0..7], @W;
  @Out D[0..7], data;				/* Program command */
  @Out WE,      @H;
  @Out CE,      @H;
  @Out D[0..7], @Z;
}
int read_data()
{
  int read_d;

  @Out CE, @L;
  @Out OE, @L;
  @In D[0..7], read_d;
  @Out CE, @H;
  @Out OE, @H;
  
  return(read_d);
}
/* -----------------------------------------------------------------------
 * Failf () ---> Fail address setting
 * ----------------------------------------------------------------------- */
int Failf (hwhb, hwlb, lwhb, lwlb, tmp)
int hwhb, hwlb, lwhb, lwlb, tmp;
{
int high, low;

   high = (hwhb << 8) | hwlb;
   low  = (lwhb << 8) | lwlb;

   @Fail high, low, tmp;
}
/* -----------------------------------------------------------------------
 * Verify 
 * ----------------------------------------------------------------------- */
int verifyf(read_d, pgm_d, option)
int read_d, pgm_d, option;
{
  if     (option == 'r') @Load read_d;		/* Read data	   */
  else if(option == 'v') {
    if(read_d != pgm_d) return(1);
  }
  else if(option == 'b') {
    if(read_d != 0xff)  return(1);
  }
  else if(option == 'c') {
    if(read_d != pgm_d)  @Compare read_d, pgm_d;
  }
  else if(option == 'p') {
    if(read_d != pgm_d) return(1);
  }

  return(0);
}
/* -----------------------------------------------------------------------
 * top() ---> read, program, verify processing
 * ----------------------------------------------------------------------- */
int top(option)
int	option;
{
int  hwhb, hwlb, lwhb, lwlb;
int  sll, ell, slh, elh, shl, ehl;
int  read_d, pgm_d;

  init(option);
  @Set	B_HADDR, B_LADDR;
  @Inc	__B_START__;
   
  disp(option, 0);
  read_d = pgm_d = 0;
   
  for ( hwhb=S_HWHB; hwhb<=E_HWHB; hwhb++ )
  {
      @Display 64, 9, hwhb;
      if (hwhb == S_HWHB)	shl = S_HWLB;
      else			shl = 0;
      if (hwhb == E_HWHB)	ehl = E_HWLB;
      else			ehl = 0xFF;      
      
      for ( hwlb=shl; hwlb<= ehl; hwlb++ )
      {
         @Display 66, 9, hwlb;
	 @Out A[16..17], hwlb;   /* Output High word address */         
	 
	 if (hwlb == S_HWLB)	slh = S_LWHB;
      	 else			slh = 0;
      	 if (hwlb == E_HWLB)	elh = E_LWHB;
      	 else			elh = 0xFF;               
         
	 for (lwhb=slh; lwhb<=elh; lwhb++)
         {
            @Display 68, 9, lwhb;
	    @Out A[8..15], lwhb;   /* Output High word address */
	    
	    if (lwhb == S_LWHB)	sll = S_LWLB;
	    else		sll = 0;
	    if (lwhb == E_LWHB)	ell = E_LWLB;
	    else		ell = 0xFF;

	    for (lwlb=sll; lwlb<=ell; lwlb++)
	    {
	       @Out A[0..7], lwlb;	    
	       @Store pgm_d;
 	       if(option == 'p') {
 	         if(pgm_d == 0xff) {
 	           @Inc SPLIT;
 	           continue;
 	         }
	         command(0x40);
	         command(pgm_d);
	         @Delay 10, @Us;
	         command(0xc0);
	       }
	       @Out CE, @L;
	       @Out OE, @L;
	       @In  D[0..7], read_d;
	       @Out OE, @H;
	       @Out CE, @H;
	       if(verifyf(read_d, pgm_d, option) == 1) {
	         Failf(hwhb, hwlb, lwhb, lwlb, read_d);
	       }
	       @Inc SPLIT;
            }
	 }
      }
   }
   disp(option, 1);
}
/* -----------------------------------------------------------------------
 * Erase
 * ----------------------------------------------------------------------- */
int write_erase()
{
    command(0x20);
    command(0x20);
    @Delay 10, @Ms;
} 
int erase()
{
int    erase_flag, read_d;
int    lwlb, lwhb, eaddr, k;
  
    erase_flag = read_d = eaddr = lwlb = lwhb = k = 0;
  
    if	    (DEVICE == D28F020)				eaddr = 0x03FF;
    else if (DEVICE == D28F010 || DEVICE == D48F010 ) 	eaddr = 0x01FF;
    else if (DEVICE >=3 && DEVICE <= 6)			eaddr = 0x00FF;
    else 						eaddr = 0x007F;

    disp('e', 0);
    init('p');
  
    for(lwhb=0; lwhb<=eaddr; lwhb++) 
    {
    	@Display 68, 9, lwhb;	  
        @Display 66, 9, lwhb>>8;	      	
    	@Out A[8..17], lwhb;	    	
    	
    	for (lwlb = 0; lwlb<= 0xFF; lwlb++)
    	{
      	   @Out A[0..7], lwlb;
      	   for(k=0; k<25; k++) 
      	   {
              command(0xc0);
              @Out CE, @L;
              @Out OE, @L;
              @In  D[0..7], read_d;
              @Out OE, @H;
              @Out CE, @H;
              if(read_d == 0) break;
      
              @Out D[0..7], @W;
              command(0x40);
              command(0);
              @Delay 10, @Us;
              command(0xc0);
              @Out CE, @L;
              @Out OE, @L;
              @In  D[0..7], read_d;
              @Out OE, @H;
              @Out CE, @H;
              if(read_d != 0) 
              {
          	if (k > 23) 
          	{
            	   @Display 26, 7, "Program all Fail !";
            	   Failf(0, lwhb>>8, lwhb, lwlb, read_d);
		}			            	   
              }
           }
        }	/*  end for : lwlb  */
    }		/*  end for : lwhb  */

    write_erase();
    for(lwhb=0; lwhb<=eaddr; lwhb++) 
    {
       @Display 68, 9, lwhb;  
       @Display 66, 9, lwhb>>8;
       @Out A[8..17], lwhb;
       for(k=0; k<=0xff; k++) 
       {
      	  @Out A[0..7], k;
      	  command(0xa0);
      	  read_d = read_data();
          if (read_d != 0xff) 
          {
             write_erase();
             erase_flag++;
          }
          if (erase_flag > 3000) 
          {
             @Display 26, 7, "Erase all Fail !";
             Failf(0, lwhb>>8, lwhb, k, read_d);
	  }
       }
    }
    disp('e', 1);
}
/* --------------------------------------------------------------------
 * main () ---> Control main
 * -------------------------------------------------------------------- */
int main ()
{
  index = 6;
  disp_flag = 0;

  if(FUNCTION == Program) {          		/* Program device */
    top('p');
    top('v');
  }
  if(FUNCTION == Blank_Check) {
    top('b');
  }
  if(FUNCTION == Data_Compare) {
    top('c');
  }
  if(FUNCTION == Erase) {
    erase();
  }
  else if(FUNCTION == Read) {           	/* Read device        */
    top('r');	
    @CheckSumOn;
  }
  else if(FUNCTION == Verify)      top('v'); 	/* Verify device      */
  else if(FUNCTION == Auto) {
    erase();
    top('b');
    top('p');
    top('v');
  }
}
/* ---------------------------- End of program --------------------------- */  