/*
 *
 *  ALL03
 *
 *  26.07.2002
 *
 *  by Fabio Sturman
 *
 *  fabio.sturman@tiscali.it
 *
 *  90slv.c
 *
 *  main module for programming AT90S8515, AT90S/LS2323 and
 *  AT90S/LS2343 in serial mode low voltage
 *
 */

/* Copyright (c) 2002 Fabio Sturman (fabio.sturman@tiscali.it)
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include "../include/all03.h"
#include "../include/all03ft.h"
#include "../include/keys.h"
#include "../include/sleep.h"
#include "../include/binmask.h"

#define print_eprom_model() printf("Eprom model: %s\n",eprom_model)
#define IS_27256   !strcmp(eprom_model,"27256")
#define IS_27C512A !strcmp(eprom_model,"27C512A")

#define PROC_STRING "Insert eprom %s and press <Enter>!\n",eprom_model


char eprom_model[256]="27C512A";
unsigned long max_address=0x10000;

unsigned char eprom[0x10000];

unsigned char signature[2];

char file_name[256]= "ep512.bin";


/* write read */
void wr_chip_data(unsigned char byt)
{
  unsigned char b2, b3;

  b2=all03_rd_ttl_buf(2);
  b3=all03_rd_ttl_buf(3);
  if(byt & BIT(0)) b2|=BIT(0); else b2&=NBIT(0);
  if(byt & BIT(1)) b2|=BIT(1); else b2&=NBIT(1);
  if(byt & BIT(2)) b2|=BIT(2); else b2&=NBIT(2);
  if(byt & BIT(3)) b2|=BIT(4); else b2&=NBIT(4);
  if(byt & BIT(4)) b2|=BIT(5); else b2&=NBIT(5);
  if(byt & BIT(5)) b2|=BIT(6); else b2&=NBIT(6);
  if(byt & BIT(6)) b2|=BIT(7); else b2&=NBIT(7);
  if(byt & BIT(7)) b3|=BIT(0); else b3&=NBIT(0);

  all03_wr_ttl_buf(2,b2);
  all03_wr_ttl_buf(3,b3);

  all03_wr(ALL03_TTL_ID+2,b2);
  all03_wr(ALL03_TTL_ID+3,b3);
}


unsigned char rd_chip_data(void)
{
  unsigned char b2, b3, tb;

  wr_chip_data(0xff);
  b2=all03_rd(ALL03_TTL_ID+2);
  b3=all03_rd(ALL03_TTL_ID+3);
  tb=0;
  if(b2&BIT(0)) tb|=BIT(0);
  if(b2&BIT(1)) tb|=BIT(1);
  if(b2&BIT(2)) tb|=BIT(2);
  if(b2&BIT(4)) tb|=BIT(3);
  if(b2&BIT(5)) tb|=BIT(4);
  if(b2&BIT(6)) tb|=BIT(5);
  if(b2&BIT(7)) tb|=BIT(6);
  if(b3&BIT(0)) tb|=BIT(7);
  return(tb);
}


void wr_chip_address(unsigned long address)
{
  unsigned char b0, b1, b3, b4;

  b0=all03_rd_ttl_buf(0);
  b1=all03_rd_ttl_buf(1);
  b3=all03_rd_ttl_buf(3);
  b4=all03_rd_ttl_buf(4);

  if(address & BIT( 0)) b1|=BIT(7); else b1&=NBIT(7);
  if(address & BIT( 1)) b1|=BIT(6); else b1&=NBIT(6);
  if(address & BIT( 2)) b1|=BIT(5); else b1&=NBIT(5);
  if(address & BIT( 3)) b1|=BIT(4); else b1&=NBIT(4);
  if(address & BIT( 4)) b1|=BIT(3); else b1&=NBIT(3);
  if(address & BIT( 5)) b1|=BIT(2); else b1&=NBIT(2);
  if(address & BIT( 6)) b1|=BIT(1); else b1&=NBIT(1);
  if(address & BIT( 7)) b1|=BIT(0); else b1&=NBIT(0);
  if(address & BIT( 8)) b3|=BIT(6); else b3&=NBIT(6);
  if(address & BIT( 9)) b3|=BIT(5); else b3&=NBIT(5);
  if(address & BIT(10)) b3|=BIT(2); else b3&=NBIT(2);
  if(address & BIT(11)) b3|=BIT(4); else b3&=NBIT(4);
  if(address & BIT(12)) b0|=BIT(7); else b0&=NBIT(7);
  if(address & BIT(13)) b3|=BIT(7); else b3&=NBIT(7);
  if(address & BIT(14)) b4|=BIT(0); else b4&=NBIT(0);
  if(IS_27C512A)
  {
    if(address & BIT(15)) b0|=BIT(6); else b0&=NBIT(6);
  }

  all03_wr_ttl_buf(0,b0);
  all03_wr_ttl_buf(1,b1);
  all03_wr_ttl_buf(3,b3);
  all03_wr_ttl_buf(4,b4);

  all03_wr(ALL03_TTL_ID+0,b0);
  all03_wr(ALL03_TTL_ID+1,b1);
  all03_wr(ALL03_TTL_ID+3,b3);
  all03_wr(ALL03_TTL_ID+4,b4);
}

#define NCE                26
#define set_nce(x)         all03_wr_pin(NCE,x)

#define NOE                28
#define set_noe(x)         all03_wr_pin(NOE,x)

#define set_vop_noe(x)     all03_set_vop_pin(NOE,x)

#define VCC                34
#define set_vcc_vcc(x)     all03_set_vcc_pin(VCC,x)

#define ADDRESS9           30
#define set_vop_a9(x)      all03_set_vop_pin(ADDRESS9,x)

#define ADDRESS0           16
#define set_a0(x)          all03_wr_pin(ADDRESS0,x)

#define VPP256             7
#define set_vpp_256(x)     all03_wr_pin(VPP256,x)
#define set_vop_vpp_256(x) all03_set_vop_pin(VPP256,x)

#define VPP512             28
#define set_vpp_512(x)     all03_wr_pin(VPP512,x)
#define set_vop_vpp_512(x) all03_set_vop_pin(VPP512,x)

void wd(int n)
{
  printf("DEBUG(%d): Press <ENTER>\n",n);
  wait_enter();
}

void chip_init(void)
{
  all03_set_vcc(5.0);
  all03_set_vop(12.0);
  all03_set_gnd_20();
  all03_set_vcc_pin(VCC,1);
  if(IS_27256) all03_set_vcc_pin(VPP256,1); /* Vpp <- Vcc */
  set_noe(1);
  set_nce(1);
  wr_chip_data(0xff);
  wr_chip_address(0xffff);
}



void edit_eprom_model(void)
{
  int c;
  
  for(;;)
  {
    clear_screen();
    printf("*** EDIT EPROM MODEL ***\n\n");
    print_eprom_model();
    printf("\n");
    printf("A) 27256     B) 27C512A\n");
    printf("\n");
    printf("Q) QUIT\n");
    printf("\n");
    printf("Enter command: ");
    flush_out();

    c=key_get();
    if((c>=32) && (c<127)) printf("%c\n",c);
    if(islower(c)) c=toupper(c);

    switch(c)
    {
      case 'A':
        strcpy(eprom_model,"27256");
        max_address=0x8000;
      break;
      case 'B':
        strcpy(eprom_model,"27C512A");
        max_address=0x10000;
      break;

      case 'Q': return; break;
    }
  }
}

/*
 *  read_signature()
 *
 *  reads signature bytes
 *
 */
void read_signature(void)
{
  int i;

  clear_screen();
  printf("*** READ SIGNATURE ***\n");
  printf(PROC_STRING);
  wait_enter();

  printf("READING...\n");
  chip_init();

  set_vop_a9(1);
  set_noe(0);
  set_nce(0);
  set_a0(0);
  signature[0]=rd_chip_data();
  set_a0(1);
  signature[1]=rd_chip_data();

  all03_init_h();

  for(i=0;i<2;i++)
    printf("Signature[%d]=%02x\n", i, signature[i]);

  printf("OK\n");
}


void write(void)
{
  unsigned long address;
  int x;
  unsigned char tb;

  clear_screen();
  if(test_if_timer()) return;
  printf("*** WRITE MEMORY ***\n");
  printf(PROC_STRING);
  wait_enter();

  printf("WRITING...\n");
  chip_init();

  if(IS_27C512A)
  {
    /*** MICROCHIP EXPRESS ALORITHM ***/
    all03_set_vcc(6.5);
    all03_set_vop(13.0);
    for(address=0; address<max_address; address++)
    {
      if(eprom[address]!=0xff)
      {
        printf("Address: %04lx\r", address);
        wr_chip_address(address);
        wr_chip_data(eprom[address]);
        for(x=0; x<10; x++)
        {
          set_vop_vpp_512(1); /* puts noe=1 */
          set_nce(0);
          wait(0.1);
          set_vop_vpp_512(0);
          set_noe(0);
          tb=rd_chip_data();
          if(tb==eprom[address]) break;
        }
        if(!(tb==eprom[address]))
        {
          printf("Programming failure at address %04lx\n",address);
          goto write_q;
        }
      }
    }
  }
  else if(IS_27256)
  {
    /*** ST FAST PROGRAMMING ALGORITHM ***/
    all03_set_vcc(6.0);
    all03_set_vop(12.5);
    //wd(1);
    all03_set_vop_pin(VPP256,1);
    //wd(2);
    for(address=0; address<max_address; address++)
    {
      if(eprom[address]!=0xff)
      {
        printf("Address: %04lx\r", address);
        wr_chip_address(address);
        wr_chip_data(eprom[address]);
        for(x=1; x<=25; x++)
        {
          set_nce(0);
          wait(1.0);
          set_nce(1);
          set_noe(0);
          tb=rd_chip_data();
          set_noe(1);
          if(tb==eprom[address]) break;
        }
        if(!(tb==eprom[address]))
        {
          printf("Programming failure at address %04lx\n",address);
          goto write_q;
        }
        else
        {
          /* over program pulse */
          set_nce(0);
          wait(3.0*x);
          set_nce(1);
        }
      }
    }
  }

write_q:

  all03_init_h();
  printf("\n");

  printf("OK\n");
}

/*
 *  read_memory()
 *
 */
void read(void)
{
  unsigned long address;

  clear_screen();
  printf("*** READ MEMORY ***\n");
  printf(PROC_STRING);
  wait_enter();

  printf("READING...\n");
  chip_init();

  set_noe(0);
  set_nce(0);
  for(address=0; address<max_address; address++)
  {
    printf("Address: %04lx\r",address);
    wr_chip_address(address);
    eprom[address]=rd_chip_data();
  }

  all03_init_h();
  printf("\n");

  printf("OK\n");
}



/*
 *  blak_check()
 *
 */
void blank_check(void)
{
  unsigned long err;
  unsigned long address;

  err=0;
  clear_screen();
  printf("*** BLANK CHECK ***\n");
  printf(PROC_STRING);
  wait_enter();

  printf("CHECKING...\n");
  chip_init();


  set_noe(0);
  set_nce(0);
  for(address=0; address<max_address; address++)
  {
    printf("Address: %04lx\r",address);
    wr_chip_address(address);
    if(rd_chip_data()!=0xff) err++;
  }

  all03_init_h();
  printf("\n");

  if(err) printf("Eprom not blank - %ld errors!\n", err);
  else printf("Eprom is blank!\n");

  printf("OK\n");
}

/*
 *  verify()
 *
 */
void verify(void)
{
  unsigned long err;
  unsigned long address;

  err=0;
  clear_screen();
  printf("*** VERIFY PROGRAM MEMORY ***\n");
  printf(PROC_STRING);
  wait_enter();

  printf("VERIFYING...\n");
  chip_init();

  set_noe(0);
  set_nce(0);
  for(address=0; address<max_address; address++)
  {
    printf("Address: %04lx\r",address);
    wr_chip_address(address);
    if(rd_chip_data()!=eprom[address]) err++;
  }

  all03_init_h();
  printf("\n");

  if(err) printf("Counted %ld errors!\n",err);
  else printf("No errors!\n");
  
  printf("OK\n");
}

/*
 *  read_from_file()
 *
 *  reads data for buffer from disk
 *
 */
void read_from_file(void)
{
  clear_screen();
  printf("*** READ FILE TO BUFFER ***\n\n");
  read_file_to_buf("ENTER FILE NAME:  ",\
    file_name, eprom, max_address, 0xff);
}


/*
 *  write_to_file()
 *
 *  writes data from buffer to disk
 *
 */
void write_to_file(void)
{
  clear_screen();
  printf("*** WRITE BUFFER TO FILE ***\n\n");
  write_buf_to_file("ENTER FILE NAME:  ",\
    file_name, eprom, max_address);
}


/* displays help screen */
void display_help(void)
{
    printf("use: 27c512a [<option>] [<file_name>]\n");
    printf("option:\n");
    printf(" -s       skip processor speed test\n");
    printf(" -h       display this screen\n");
    printf(" -bxxx    set all03 base address\n");

    exit(1);
}

/* main program */
int main(int argc, char *argv[])
{
  int c, ac, skip, tbase;

  all03_init_h();
  disable_ctrl_c_break();

  ac=argc-1;
  skip=0;
  while(ac)
  {
    if(!strcmp(argv[ac],"-s") || !strcmp(argv[ac],"-S")) skip=1;
    else if(!strcmp(argv[ac],"-h") || !strcmp(argv[ac],"-H"))
    {
      display_help();
      return(1);
    }
    else if(!strncmp(argv[ac],"-b",2) || !strncmp(argv[ac],"-B",2))
    {
      sscanf(&argv[ac][2],"%x",&tbase);
      all03_set_base_address(tbase);
    }
    else strcpy(file_name,argv[ac]);
    ac--;
  }  

  if(!skip)
  {
    printf("TESTING SPEED...\n");
    if(!test_timer()) printf("TIMER OK\n");
    else printf("\n\007* ALL03 Error - Timing not OK!\n");
  }

  if(all03_test_base_address())
  {
    printf("\n\007* ALL03 Error - Programmer not found at base address %04x!\n",all03_get_base_address());
    printf("Press <ENTER>\n");
    wait_enter();
  }

  for(;;)
  {
    clear_screen();
    printf("-------------------------------------------------------\n");
    printf("-- ALL03 - 27C256/512A ---  PROGRAMMING MODULE --------\n");
    printf("------------------------by FaSt - Ver 1.0BETA3---------\n");
    printf("\n");
    print_eprom_model();
    printf("\n");
    printf("    Menu:\n");
    printf("\n");
    printf("2 - Read from file\n");
    printf("3 - Save to file\n");
    printf("6 - Edit base address\n");
    printf("B - Blank check\n");
    printf("R - Read\n");
    printf("P - Program\n");
    printf("S - Read signature\n");
    printf("V - Verify\n");
    printf("T - Select chip model\n");
    //printf("{ - Test\n");
    //printf("} - Dump ALL03 registers\n");
    printf("Q - quit\n");
    printf("\n");
    printf("Enter command: ");
    flush_out();

    c=key_get();
    if((c>=32) && (c<=126)) printf("%c\n",c);
    if(islower(c)) c=toupper(c);
    
    switch(c)
    {
      case '2': read_from_file(); break;
      case '3': write_to_file(); break;
      case '6': all03_edit_base(); break;

      case 'B': blank_check(); break;
      case 'R': read(); break;
      case 'S': read_signature(); break;
      case 'P': write(); break;
      case 'V': verify(); break;
      case 'T': edit_eprom_model(); break;

      case '{': test(); break;
      case '}': all03_dump(); break;

      case 'Q':
        enable_ctrl_c_break();
        return(0);
      break;
    }
    
    printf("Press <ENTER>\n");
    wait_enter();
  }
  return(0);
}

