declaration
  dataunit : byte;

  functions
    Program  
    Read
    Verify    
    Blank_Check
    Erase
    Auto
  ;
  Manufacturers
    EXEL
  ;
  Devices
    XLS9346
  ;

  chips =
       /*  ÕÍÍÍÍÍÍÍÍÍ¸      */
  CS,  /* o³1      12³o VCC */
  SK,  /* o³2      11³o NC5 */
  DI,  /* o³3      10³o NC4 */
  DO,  /* o³4       9³o GND */
  NC0, /* o³5       8³o NC3 */
  NC1, /* o³6       7³o NC2 */
  NC2, NC3, GND, NC4, NC5, VCC;

  $v2 = VCC;
endd

int disp_flag = 0;
int index     = 6;
/* -----------------------------------------------------------------------
 * 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 () ---> Initial processing
 * ----------------------------------------------------------------------- */
int     init ()
{
  @Vout 1, 	5.0;
  @Vout 2, 	5.0;
  @Vout 3, 	5.0; 
  @Out GND     , @G;
  @Delay 10, @Ms;

  @Out NC[0..5], @W;
  @Out CS      , @W;
  @Out SK      , @W;
  @Out DI      , @W;
  @Out DO      , @Z;

  @Out NC[0..5], @L;
  @Out CS      , @L;
  @Out SK      , @L;
  @Out DI      , @L;

  @Out VCC     , @O;
  @Delay 2, @Ms;
}
/* -----------------------------------------------------------------------
 *
 * ----------------------------------------------------------------------- */
int clk()
{
  @Out SK, @H;
  @Out SK, @L;
}
/* -----------------------------------------------------------------------
 *
 * ----------------------------------------------------------------------- */
int out_command(command)
int command;
{
  int i, tmp;
  
  for(i=0; i<3; i++) {
    tmp = command >> i;
    if(tmp & 1 == 1) @Out DI, @H;
    else             @Out DI, @L;
    clk();
  }
  @Out DI, @L;
}
/* -----------------------------------------------------------------------
 *
 * ----------------------------------------------------------------------- */
int out_address(address)
int address;
{
  int i, tmp;
  
  for(i=0; i<6; i++) {
    tmp = address >> (5-i);
    if(tmp & 1 == 1) @Out DI, @H;
    else             @Out DI, @L;      
    clk();
  }
  @Out DI, @L;
}
/* -----------------------------------------------------------------------
 * Read data from device
 * Blank check
 * Verify
 * ----------------------------------------------------------------------- */
int verifyf(address, data, option)
int address, data, option;
{
  int tmp, tmp1;
  
  address *= 2;
  tmp = tmp1 = 0;
  
  @Display 70, 9, address;
  
  if     (option == 'r') {
    @Load data;
    @Inc SPLIT;
    @Load data >> 8;
    @Inc SPLIT;
  }
  else if(option == 'b') {			/* Blank check     */
    if(data != 0xffff)  @fail 0, address, data;
  }
  else if(option == 'v') {			/* Verify check    */
    @Store tmp;
    @Inc SPLIT;
    @Store tmp1;
    @Inc SPLIT;
    tmp |= tmp1 << 8;
    if (tmp != data) @fail 0, address, data;
  }
}
/* -----------------------------------------------------------------------
 * read () ---> read processing
 * ----------------------------------------------------------------------- */
int top(option)
int option;
{
  int  i, j;
  int  tmp, data;

  @Set 0, 0;
  disp(option, 0);
  for(i=0; i<0x40; i++) {
    data = 0;
    @Out CS, @H;
    out_command(3);
    out_address(i);
    clk();
    for(j=0; j<16; j++) {		/* read data */
      @IN DO, tmp;
      clk();      
      data |= tmp << (15 - j);
    }
    @Out CS, @L;

    verifyf(i, data, option);
  }
  disp(option, 1);
}
/* -----------------------------------------------------------------------
 * program () ---> Program processing
 * ----------------------------------------------------------------------- */
int program()
{
  int  i, j, k;
  int  tmp, data;

  @Set 0, 0;
  disp('p', 0);
  for (i=0; i<0x40; i++) {
    tmp = data = 0;
    @Out CS, @H;
    out_command(5);
    out_address(i);

    @Store data;
    @Inc SPLIT;
    @Store tmp;
    @Inc SPLIT;

    data |= tmp << 8;
    for(j=0; j<16; j++) {
      tmp = data >> (15-j);
      if(tmp & 1 == 1)  @Out DI, @H;
      else 		@Out DI, @L;
      clk();
    }    
    @Out DI, @L; 
    
    @Out CS, @L;
    clk();
    @Out CS, @H;
    clk();
    @Out DO, @W;
    @Out DO, @L;
    @Delay 9, @Ms;
    @Out DO, @H;
    clk();
    @Out CS, @L;    
    @Out DO, @Z;
  }
  
  disp('p', 1);
  top('v');
}
/* -----------------------------------------------------------------------
 * Erase () ---> Erase processing
 * ----------------------------------------------------------------------- */
int erase()
{
  int  i, j;

  disp('e', 0);

  for (i=0; i<0x40; i++) {
    @Out CS, @H;
    out_command(7);
    out_address(i);
    @Out CS, @L;
    clk();
    @Out CS, @H;
    clk();
    @Out DO, @W;
    @Out DO, @L;
    @Delay 9, @Ms;
    @Out DO, @H;
    clk();
    @Out CS, @L;    
    @Out DO, @Z;
  }
  disp_flag = 1;
  top('b');
  disp_flag = 0;
  disp('e', 1);
}
/* -----------------------------------------------------------------------
 * Write Enable
 * ----------------------------------------------------------------------- */
int write_enable()
{
  @Out CS, @H;
  out_command(1);
  out_address(0x30);

  @Out CS, @L;
}
/* -----------------------------------------------------------------------
 * main () ---> Controll main
 * ----------------------------------------------------------------------- */
int main ()
{
  index = 6;
  @Set 0, 0;
  
  init();
  write_enable();
 
  if     (FUNCTION == Program) {
    program();
  }
  else if(FUNCTION == Erase) {
    erase();
  }
  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();
    program();
  }
}
/* ---------------------------- End of program --------------------------- */  
