/* ****************************************************************************
 *    File Name : 27512.D 	           	(*) Spec non-exist !!!	
 *    Pin num 	: 28 pin   (A0..A15	D0..D7)
 *    Size 	: 512K	   (FFFF)
 *    Last Modify Date : 91. 3. 8 
 * 
 * +-------------------------------------------------------------------------+
 * +      1. Vpp :12.5  Vcc:6.0   Dur:1ms 				     +
 * +-------------------------------------------------------------------------+
 *    Device :	AMD		27512	 +27512DC    27C512	
 *			 	27C512P	 *27512F    *27512PC	  	
 *		ATMEL		27C512		
 *		CSI		27512 (OTP)
 *		FUJITSU		27C512P-25 (OTP)        27C512-20(/25/30)
 *		HITACHI		27512P(OTP)	27512	27512G	
 *		MITSUBITHI	27512	27C512A
 *		NEC		27512	27C512	
 *		OKI		27512	(Quick:12.75  6.25)
 *		SGS		27512
 *		TOSHIBA		24512	24512A	27512	27512A
 *	  			24512P	27512D	27512DI
 *		VLSI		*27C512 
 * +-------------------------------------------------------------------------+
 * +      1. Vpp :12.5  Vcc:5.5   Dur:5ms(1-10ms) 				     +
 * +-------------------------------------------------------------------------+ 
 *		WSI		27C512F
 * +-------------------------------------------------------------------------+
 * +      1. Vpp :12.75  Vcc:5.8   Dur:5ms(1-10ms) 				     +
 * +------------------------------------------------------------------ 
 *		WSI		27C512L
 * +-------------------------------------------------------------------------+
 * +    2. Vpp:12.75 	Vcc:6.25   Dur:100us
 * +-------------------------------------------------------------------------+
 *		CSI		*27512P-20 (OTP)		  
 *		FUJITSU		27C512
 *    		INTEL 		27512	27C512	 27S512
 *		MICROCHIP	27C512 (Express : 13.0  6.5  LOP=10)
 *		NEC		*27512AD  *27512ACT 
 *		NS		27C512	27C512A	 27C512AN(OTP:OneTimeProgram)
 *		SIGNETICS	27C512
 *		SGS		27C512
 *		TI		27C512 	27PC512
 *		(a) Spec data: Vpp=12.5 Vcc=6.0 Dur=1ms
 * +-------------------------------------------------------------------------+ 
 * +    3. Vpp:13.0 	Vcc:6.5   Dur:100us	lop=10 				     
 * +-------------------------------------------------------------------------+
 *		ATMEL	27C512R
 * *************************************************************************** */
declaration
   dataunit : byte;
   functions
      Program
      Read
      Verify
      Blank_Check
      Data_Compare
      Auto      
   ;
   Manufacturers
      AMD		/* 0 */
      ATMEL     	/* 1 */
      CSI		/* 2 */
      HITACHI		/* 3 */
      INTEL		/* 4 */
      MICROCHIP		/* 5 */
      MITSUBISHI	/* 6 */
      NEC		/* 7 */
      OKI		/* 8 */
      SIGNETICS		/* 9 */
      SGS		/* 10 */
      TOSHIBA		/* 11 */
      VLSI		/* 12 */
      WSI		/* 13 */
      FUJITSU		/* 14 */
      NS		/* 15 */
      TI		/* 16 */
   ;
   Devices
      D27512		/*  Vpp=12.5	Vcc=6.0	    Dur=1ms   */
      D27C512P
      D27512F
      D27512PC
      D24512
      D24512A
      D27512A
      D24512P
      D27512D
      D27512DI
      D27512G
      D27512P
      D27C512_20
      D27C512P_25
      D27C512F		/* 14:	Vpp=12.5   Vcc=5.5   Dur=5ms	*/
      D27C512L  	/* 15:	Vpp=12.75  Vcc=5.8   Dur=5ms    */
      D27C512R		/* 16:  Vpp=13.0   Vcc=6.5   Dur=100us  LOP=10  */      
      D27C512P_20       /* 17:  Vpp=12.75  Vcc=6.25  Dur=100us  */
      D27512AD
      D27512ACT
      D27C512AN      		   
      D27C512		  
      D27C512A
      D27PC512
      D27S512
   ;
   chips = A15, A12, A7, A6, A5, A4, A3, A2, A1, A0, D0, D1, D2, GND,
	   D3, D4, D5, D6, D7, CE, A10, OE:Vpp, A11, A9, A8, A13, A14, Vcc;
   $v2 = Vpp;
   $v3 = Vcc;
endd

int durstat [] = { 0 , 3, 3, 0, 1, 1, 0, 3, 0, 1, 3, 0, 0, 3, 3, 1, 1 };
int volstat [] = { 0 , 3, 3, 0, 1, 2, 0, 3, 0, 1, 3, 0, 0, 3, 3, 1, 1 };
int durtbl  [] = { 1000, 100 };

voltage vpptbl [] = { 12.5, 12.75, 13.0 };
voltage vcctbl [] = {  6.0,  6.25, 6.5 };

/* -----------------------------------------------------------------------
 * 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;
}
/* -----------------------------------------------------------------------
 * init () ---> Initial processing
 * ----------------------------------------------------------------------- */
int     init (vol2, vol3)
voltage vol2, vol3;
{
   @Vout 2, vol2;            /* Voltage Source #2 */
   @Vout 3, vol3;            /* Voltage Source #3 */
   @Out GND      , @G;       /* Ground output */
   @Delay 10	 , @ms;

   @Out D [0..7] , @W;       /* ------------------------ */
   @Out A [0..7] , @W;       /*                          */
   @Out A [8..15], @W;       /*   Initial Direction      */
   @Out CE       , @W;       /*         Of               */
   @Out OE       , @W;       /* ------------------------ */
   @Out Vcc	 , @W;
   @Out __GANG__[0..3], @W;
   
   @Out CE       , @H;       /* Chip enable  is High */
   @Out OE       , @H;       /* Out  enable  is High */
   @Out Vcc	 , @H;
   @Out __GANG__[0..3], @H;

   @Out Vcc	 , @O;       /* Vcc Enable */
   @Delay  100 	 , @us;
}
/* -----------------------------------------------------------------------
 * InitProcess () ---> Initial Buffer | Voltage source
 * ----------------------------------------------------------------------- */
int InitProcess ()
{
int	stat, dur;

   if (FUNCTION != Program) init ( 5.0 , 5.0 );
   else
   {
      stat = volstat [MFG];
      if (stat != 3) 
      {
         init (vpptbl [stat], vcctbl [stat]);
         stat = durstat [MFG];
         dur = durtbl [stat];
      }
      else
      {
         if (MFG == ATMEL)
         {
            if (DEVICE == D27C512) 
            {
               init (12.5 , 6.0);
               dur = 1000;
            }
            else 
            {
               init (13.0, 6.5);
               dur = 100;
            }
         }		/* end if: (MFG == ATMEL)  */
         else if (MFG == CSI)
         {
            if (DEVICE == 27512) 
            {
               init (12.5, 6.0);
               dur = 1000;
            }
            else 
            {
               init (12.75 , 6.25 );
               dur = 100;
            }
         }		/*  end if : (MFG == CSI) */
         else if (MFG == FUJITSU)
         {
             if (DEVICE == D27C512)
             {
             	init (12.75 , 6.25);
             	dur = 100;
             }
             else 
             {
             	init (12.5 , 6.0 );
		dur = 1000;             	
             } 
         }		/*  end if : (MFG == FUJITSU) */
         else if (MFG == NEC)
         {
             if (DEVICE == D27512 || DEVICE == D27C512)
             {
		init ( 12.5 , 6.0 );      
		dur = 1000;		
             }
             else 
             {
		init (12.75 , 6.25 );
		dur = 100;             	             	
             }
         }   		/*  end if : (MFG == NEC)  */
         else if (MFG == SGS)
         {
	     if (DEVICE == D27512)
	     {
	     	init ( 12.5, 6.0 );
	     	dur = 1000;
	     }             
	     else 
	     {
	     	init ( 12.75, 6.25);
	     	dur = 100;
	     }
         }   		/*  end if : (MFG == SGS)  */
         else if (MFG == WSI)
         {
             if (DEVICE == D27C512F)
      	     {
      	     	init ( 12.5, 5.5 );
      	     	dur = 5000;
      	     }	
      	     else 
      	     {
	     	init ( 12.75 , 5.8 );
	     	dur = 5000;      	     
      	     }
         }		/*  end if : (MFG == WSI)	*/
      }			/*  end else : stat == 2	*/         
   }			/*  end if : (FUNCTION != Program) */
   return (dur);
}
/* -----------------------------------------------------------------------
 * read () ---> read processing
 * ----------------------------------------------------------------------- */
int read (row)
int	row;
{
int  hwhb, hwlb, lwhb, lwlb;	
int  slh, sll, elh, ell; 
int  tmp, tmp2;

   @Set	B_HADDR, B_LADDR;
   @Inc __B_START__;
   
   lwlb = lwhb = hwhb = hwlb = 0;
   slh = sll = elh = ell = tmp = tmp2 = 0;
   @Out D [0..7], @Z;	/* Data Input  */
   
   if (FUNCTION == Read ) 
   {
      @Display 26, row, "Reading...";
      @CheckSumON;
   }
   else if (FUNCTION == Verify)		@Display 26, row, "Verifying...";
   else if (FUNCTION == Blank_Check)	@Display 26, row, "Blank Checking...";
   else 			        @Display 26, row, "Data Comparing...";
   
   for ( hwhb=0; hwhb<=0; hwhb++ )
   {
      @Display 64, 9, hwhb;
      for ( hwlb=S_HWLB; hwlb<=E_HWLB; hwlb++ )
      {
	 @Display 66, 9, hwlb;
	 
         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_HWLB)   sll = S_LWLB;
            else                  sll = 0;
            if (lwhb == E_HWLB)   ell = E_LWLB;
            else                  ell = 0xFF;
	   
	    for ( lwlb=sll; lwlb<=ell; lwlb++)
	    {
	       @Out A [0..7], lwlb;    /* Low  byte address output */
	       
	       if (GANG == 0)	@Out CE      	   , @L;
	       else		@Out __GANG__[GANG], @L;
	       
	       @Out OE      , @L;
	       @In D [0..7] , tmp;
	       
	       if (GANG == 0)	@Out CE	    	   , @H;
	       else		@Out __GANG__[GANG], @H;
	       
	       @Out OE      , @H;
	       
	       if      (FUNCTION == Read)          @Load tmp;
	       else if (FUNCTION == Blank_Check)
	       {
		    if (tmp != 0xFF)  Failf(hwhb, hwlb, lwhb, lwlb, tmp);
	       }
	       else if (FUNCTION == Verify)
	       {
		   @Store tmp2;
		   if (tmp != tmp2)  Failf (hwhb, hwlb, lwhb, lwlb, tmp);
	       }
	       else if (FUNCTION == Data_Compare) 	   
	       {
	       	    @Store   tmp2;
	       	    @Compare tmp, tmp2;
	       }
	       if (FUNCTION != Blank_Check)	@Inc SPLIT;
            }
	 }
      }
   }
   if 	   (FUNCTION == Read)		@Display 26, row, "Read OK!   ";
   else if (FUNCTION == Verify)		@Display 26, row, "Verification OK!";
   else if (FUNCTION == Blank_Check)	@Display 26, row, "Blank Check OK!  ";
   else 			        @Display 26, row, "Data Comparison OK!";
}
/* -----------------------------------------------------------------------
 * program() ---> Control main
 * ----------------------------------------------------------------------- */
int	program (row, kind, Dur)
int	row, kind, Dur;
{
int  hwhb, hwlb, lwhb, lwlb, sll, ell, slh, elh;
int  tmp , tmp2,  failcnt, lopnum;

   @Set B_HADDR, B_LADDR;
   @Inc	__B_START__;
   
   Dur = failcnt = lopnum = tmp = tmp2 = 0;
   lwlb = lwhb = hwhb = hwlb = 0;
   slh = elh = sll = ell = 0;
   
   @Out OE	, @L;

   if (MFG == MICROCHIP)	lopnum = 10;
   else if (MFG == ATMEL)	
   {
   	if (DEVICE == D27C512R)	lopnum = 10;
   	else			lopnum = 25;
   }
   else				lopnum = 25;
   
   @Display 26, row, "Programming...";
   
   for ( hwhb=0 /* S_HWHB */; hwhb<=0 /* E_HWHB */; hwhb++ )
   {
       @Display 64, 9, hwhb;

       for ( hwlb=S_HWLB; hwlb<=E_HWLB; hwlb++ )
       {
	   @Display 66, 9, hwlb;
	   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++)
	       {
		  @Store tmp;
		  
		  if (tmp == 0xFF)
		  {
		      @Inc  SPLIT;
		      continue;
		  }            
		  
	          @Out A [0..7], lwlb;
		  @Out D [0..7], tmp;
		  @Out Vpp     , @O;
		  
		  if (GANG == 0)	@Out CE	, @L;
		  else 			@Out __GANG__[GANG], @L;
		  @Delay Dur   , @us;
		  if (GANG == 0)	@Out CE	, @H;
		  else			@Out __GANG__[GANG], @H;		  
		  
		  @Out Vpp     , @F;

		  /* -------- Verify ----------- */
                  @Out D [0..7], @Z;
                  
		  if (GANG == 0)	@Out CE	, @L;
		  else			@Out __GANG__[GANG], @L;
		  
		  @In  D [0..7], tmp2;
		  
		  if (GANG == 0)	@Out CE	  	   , @H;
		  else			@Out __GANG__[GANG], @H;
		  
		  @Out D [0..7], @W;
		  
		  if (tmp != tmp2)
                  {
		     if (failcnt > lopnum) Failf (hwhb, hwlb, lwhb, lwlb, tmp2);
		     else
		     {
			++ failcnt;
			lwlb--;
		     }
                  }
		  else
		  {
                      failcnt = 0;
		      @Inc SPLIT;
		  }
               }
	   }
       }
   }
   @Display 26, row, "Program OK!   ";
   if (kind == 0)	row = 7;
   else			row = 8;
   FUNCTION = Verify;
   @Vout  2, 5.0;
   @Vout  3, 5.0;
   if (DEVICE == D27C512R)	@Out OE	, @L;
   read (row);		/*  Verify  */
}
/* -----------------------------------------------------------------------
 * main () ---> Control main
 * ----------------------------------------------------------------------- */
int main ()
{
int	dur;

   dur = InitProcess();
   
   if ( FUNCTION == Auto )
   {
	FUNCTION = Blank_Check;
	read (6);

	FUNCTION = Program;	
        dur = InitProcess();
	program(7, 1, dur);
   }
   else if ( FUNCTION == Program ) program(6, 0, dur);
   else if ( FUNCTION == Read )
   {
   	if 	(GANG >= 1 && __B_START__ == 0);
   	else if (GANG == 3 && __B_START__ == 1);
   	else read (6);
   }    
   else 			   read (6);
}
/* ---------------------------- End of program --------------------------- */  