/*
 *
 *  ALL03
 *
 *  26.07.2002
 *
 *  by Fabio Sturman
 *
 *  fabio.sturman@tiscali.it
 *
 *  all03.c
 *
 *  general routines for accessing all03
 *
 */

/* 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 <ctype.h>
#include <conio.h>
#include "../include/all03.h"
#include "../include/keys.h"
#include "../include/all03ft.h"
#include "../include/binmask.h"


#ifdef DJGPP
#include <pc.h>
#endif

unsigned short int all03_base=ALL03_BASE;
unsigned short int all03_id_port;
unsigned short int all03_data_port;

unsigned char all03_vop, all03_vhh, all03_vcc, all03_other_en;
unsigned char all03_ttl[5], all03_vop_en[5], all03_vhh_en[5], all03_vcc_en[2], all03_vhh_en_c[2];
unsigned char all03_id_f7;

unsigned char all03_data_w[255], all03_index_w;
unsigned char all03_data_r[255], all03_index_r;

unsigned short int all03_tab_base[]=
{
  0x200, 0x210, 0x220, 0x230,
  0x240, 0x250, 0x260, 0x270,
  0x280, 0x290, 0x2A0, 0x2B0,
  0x2C0, 0x2D0, 0x2E0, 0x2F0,
};

/* write to all03 device id reg */
void all03_wr_id(unsigned char id)
{
  outp(all03_id_port,id);
  all03_index_r=id;
  all03_index_w=id;
}

/* write to all03 data reg */
void all03_wr_data(unsigned char data)
{
  outp(all03_data_port, data);
  all03_data_w[all03_index_w]=data;
}

/* read all03 data reg */
unsigned char all03_rd_data(void)
{
  unsigned char data;
  
  data=inp(all03_data_port);
  all03_data_r[all03_index_r]=data;
  return(data);
}

/* write data to device id */
void all03_wr(unsigned char id, unsigned char data)
{
  all03_wr_id(id);
  all03_wr_data(data);
}

/* read data from device id */
unsigned char all03_rd(unsigned char id)
{
  all03_wr_id(id);
  return(all03_rd_data());
}

/* set vop */
void all03_set_vop(float v)
{
  int n;
  
#ifdef DEBUG
  char ts[256];

  if((v>ALL03_MAX_VOP) || (v<ALL03_MIN_VOP))
  {
    sprintf(ts,"* ALL03 Error - all03_set_vop: voltage %.3f not in range!",v);
    all03_msg(ts);
  }
#endif
  v=v+0.6;
  n=(int)(v / ALL03_DELTA_VOP);
#ifdef DEBUG
  if(n>255)
  {
    sprintf(ts,"* ALL03 Error - all03_set_vop: n %d overrange!",n);
    all03_msg(ts);
  }
#endif
  all03_wr(ALL03_VOP_ID,n);
  all03_vop=n;
}

/* set vhh */
void all03_set_vhh(float v)
{
  int n;
  
#ifdef DEBUG
  char ts[256];

  if((v>ALL03_MAX_VHH) || (v<ALL03_MIN_VHH))
  {
    sprintf(ts,"* ALL03 Error - all03_set_vhh: voltage %.1f not in range!",v);
    all03_msg(ts);
  }
#endif
  v=v+0.6;
  n=(int)(v / ALL03_DELTA_VHH);
#ifdef DEBUG
  if(n>255)
  {
    sprintf(ts,"* ALL03 Error - all03_set_vhh: n %d overrange!",n);
    all03_msg(ts);
  }
#endif
  all03_wr(ALL03_VHH_ID,n);
  all03_vhh=n;
}

/* set vcc */
void all03_set_vcc(float v)
{
  int n;
  
#ifdef DEBUG
  char ts[256];

  if((v>ALL03_MAX_VCC) || (v<ALL03_MIN_VCC))
  {
    sprintf(ts,"* ALL03 Error - all03_set_vcc: voltage %.1f not in range!",v);
    all03_msg(ts);
  }
#endif
  v=v+0.6;
  n=(int)(v / ALL03_DELTA_VCC);
#ifdef DEBUG
  if(n>255)
  {
    sprintf(ts,"* ALL03 Error - all03_set_vcc: n %d overrange!",n);
    all03_msg(ts);
  }
#endif
  all03_wr(ALL03_VCC_ID,n);
  all03_vcc=n;
}

/*
 *  init_h
 *
 *  puts all pins to GND
 *
 */
void all03_init_h(void)
{
  int i;
  
  all03_id_port=all03_base;
  all03_data_port=all03_base+2;

  for(i=0;i<5;i++)
  {
    all03_vop_en[i]=0x00;
    all03_wr(ALL03_VOP_EN_ID+i,all03_vop_en[i]);
  }

  for(i=0;i<5;i++)
  {
    all03_vhh_en[i]=0x00;
    all03_wr(ALL03_VHH_EN_ID+i,all03_vhh_en[i]);
  }

  for(i=0;i<2;i++)
  {
    all03_vhh_en_c[i]=0x00;
    all03_wr(ALL03_VHH_EN_C_ID+i,all03_vhh_en_c[i]);
  }

  for(i=0;i<2;i++)
  {
    all03_vcc_en[i]=0x00;
    all03_wr(ALL03_VCC_EN_ID+i,all03_vcc_en[i]);
  }

  all03_other_en=0;
  all03_wr(ALL03_OTHER_EN_ID,all03_other_en);

  for(i=0;i<5;i++)
  {
    all03_ttl[i]=0x00;
    all03_wr(ALL03_TTL_ID+i,all03_ttl[i]);
  }

  /* bit 3 of reg 0xf7 switces good led */
  all03_id_f7=0;
  all03_wr(0xf7,all03_id_f7);

  all03_vcc=0;
  all03_wr(ALL03_VCC_ID,all03_vcc);

  all03_vhh=85;
  all03_wr(ALL03_VHH_ID,all03_vhh);

  all03_vop=102;
  all03_wr(ALL03_VOP_ID,all03_vop);
}

/* if all03 installed at base address returns 0

   write all 0 from 0xe0 to 0xf6
   must read back 0 0 0 0 0 ff ff ff ff ... ff
*/
int all03_test_base_address(void)
{
  unsigned char trd[32], t0, t1;
  int i;


  all03_init_h();
  for(i=0;i<0x17;i++) trd[i]=all03_rd(0xe0+i);

  t0=0;
  for(i=0;i<5;i++)  t0|=trd[i];

  t1=0xff;
  for(i=5;i<0x17;i++)  t1&=trd[i];

  if(t0==0 && t1==0xff) return(0);

  return(1);
}

/* switch on/off the good led */
void all03_wr_led_good(int state)
{
  if(state) all03_id_f7|=BIT(3);
  else all03_id_f7&=~BIT(3);
  all03_wr(0xf7,all03_id_f7);
}


/*
 *  wr_pin
 *
 *  writes to pin
 *
 */
void all03_wr_pin(int pin, int state)
{
  int b, i;

#ifdef DEBUG
  char ts[256];

  if(!all03_is_ttl_pin(pin))
  {
    sprintf(ts,"* ALL03 Error - all03_wr_pin: pin %d not in range!",pin);
    all03_msg(ts);
    return;
  }
#endif

  i=(pin-1) / 8;
  b=(pin-1) & 0x07;
  if(state) all03_ttl[i]|=BIT(b);
  else all03_ttl[i]&=~BIT(b);
  all03_wr(ALL03_TTL_ID+i,all03_ttl[i]);
}

/*
 *  rd_pin
 *
 *
 *  reads pin
 *
 */
int all03_rd_pin(int pin)
{
  unsigned char uc;
  int b, i;

#ifdef DEBUG
  char ts[256];

  if(!all03_is_ttl_pin(pin))
  {
    sprintf(ts,"* ALL03 Error -  all03_rd_pin: pin %d not in range!",pin);
    all03_msg(ts);
    return(1);
  }
#endif
  i=(pin-1) / 8;
  b=(pin-1) & 0x07;
  all03_wr_pin(pin, 1);
  uc=all03_rd(ALL03_TTL_ID+i);
  if(uc & BIT(b)) return(1);
  else return(0);
}

/*
 *  wr_vcc_pin
 *
 *
 *  enables/disables vcc to pin
 *
 */
void all03_wr_vcc_pin(int pin, int state)
{
#ifdef DEBUG
  char ts[256];

  if(!all03_is_vcc_pin(pin))
  {
    sprintf(ts,"* ALL03 Error - all03_wr_vcc_pin: pin %d not in range!",pin);
    all03_msg(ts);
    return;
  }
#endif

  switch(pin)
  {
    case 40: if(state) all03_vcc_en[0]|=BIT(0); else all03_vcc_en[0]&=~BIT(0); break;
    case 36: if(state) all03_vcc_en[0]|=BIT(1); else all03_vcc_en[0]&=~BIT(1); break;
    case 34: if(state) all03_vcc_en[0]|=BIT(2); else all03_vcc_en[0]&=~BIT(2); break;
    case 32: if(state) all03_vcc_en[0]|=BIT(3); else all03_vcc_en[0]&=~BIT(3); break;
    case 31: if(state) all03_vcc_en[0]|=BIT(4); else all03_vcc_en[0]&=~BIT(4); break;
    case 30: if(state) all03_vcc_en[0]|=BIT(5); else all03_vcc_en[0]&=~BIT(5); break;
    case 29: if(state) all03_vcc_en[0]|=BIT(6); else all03_vcc_en[0]&=~BIT(6); break;
    case 28: if(state) all03_vcc_en[0]|=BIT(7); else all03_vcc_en[0]&=~BIT(7); break;

    case 27: if(state) all03_vcc_en[1]|=BIT(0); else all03_vcc_en[1]&=~BIT(0); break;
    case 26: if(state) all03_vcc_en[1]|=BIT(1); else all03_vcc_en[1]&=~BIT(1); break;
    case  9: if(state) all03_vcc_en[1]|=BIT(2); else all03_vcc_en[1]&=~BIT(2); break;
    case  7: if(state) all03_vcc_en[1]|=BIT(3); else all03_vcc_en[1]&=~BIT(3); break;
    case  5: if(state) all03_vcc_en[1]|=BIT(4); else all03_vcc_en[1]&=~BIT(4); break;
    case  1: if(state) all03_vcc_en[1]|=BIT(5); else all03_vcc_en[1]&=~BIT(5); break;
  }
  all03_wr(ALL03_VCC_EN_ID+0,all03_vcc_en[0]);
  all03_wr(ALL03_VCC_EN_ID+1,all03_vcc_en[1]);
}

/*
 *  wr_vop_pin
 *
 *
 *  enables/disables vop to pin
 *
 */
void all03_wr_vop_pin(int pin, int state)
{
  int i, b;
#ifdef DEBUG
  char ts[256];

  if(!all03_is_vop_pin(pin))
  {
    sprintf(ts,"* ALL03 Error - all03_wr_vop_pin: pin %d not in range!",pin);
    all03_msg(ts);
    return;
  }
#endif

  i=(pin-1) / 8;
  b=(pin-1) & 0x07;
  if(state) all03_vop_en[i]|=BIT(b); else all03_vop_en[i]&=~BIT(b);
  all03_wr(ALL03_VOP_EN_ID+i,all03_vop_en[i]);
}

/*
 *  wr_vhh_pin
 *
 *
 *  enables/disables vhh to pin
 *
 */
void all03_wr_vhh_pin(int pin, int state)
{
  int i, b;
#ifdef DEBUG
  char ts[256];

  if(!all03_is_vhh_pin(pin))
  {
    sprintf(ts,"* ALL03 Error - all03_wr_vhh_pin: pin %d not in range!",pin);
    all03_msg(ts);
    return;
  }
#endif

  i=(pin-1) / 8;
  b=(pin-1) & 0x07;
  if(state) all03_vhh_en[i]|=BIT(b); else all03_vhh_en[i]&=~BIT(b);
  all03_wr(ALL03_VHH_EN_ID+i,all03_vhh_en[i]);
}

/*
 *  wr_vhh_c_pin
 *
 *
 *  enables/disables vhh_c to pin
 *
 */
void all03_wr_vhh_c_pin(int pin, int state)
{
  int i;
#ifdef DEBUG
  char ts[256];

  if(!all03_is_vhh_c_pin(pin))
  {
    sprintf(ts,"* ALL03 Error - all03_wr_vhh_c_pin: pin %d not in range!",pin);
    all03_msg(ts);
    return;
  }
#endif

  i=0;
  switch(pin)
  {
    case 32: if(state) all03_vhh_en_c[i]|=BIT(3); else all03_vhh_en_c[i]&=~BIT(3); break;
    case 31: if(state) all03_vhh_en_c[i]|=BIT(4); else all03_vhh_en_c[i]&=~BIT(4); break;
    case 30: if(state) all03_vhh_en_c[i]|=BIT(5); else all03_vhh_en_c[i]&=~BIT(5); break;
    case 29: if(state) all03_vhh_en_c[i]|=BIT(6); else all03_vhh_en_c[i]&=~BIT(6); break;
    case 28: if(state) all03_vhh_en_c[i]|=BIT(7); else all03_vhh_en_c[i]&=~BIT(7); break;
  }
  all03_wr(ALL03_VHH_EN_C_ID+i,all03_vhh_en_c[i]);
}

/*
 *  set_gnd_20
 *
 *  clamps pin 20 to GND
 *
 */
void all03_set_gnd_20(void)
{
  
  all03_wr_pin(20,1);
  all03_wr_vhh_pin(20,0);
  all03_wr_vop_pin(20,0);

  all03_other_en&=~BIT(0);
  all03_wr(ALL03_OTHER_EN_ID, all03_other_en);
}

/*
 * set_gnd_11_30
 *
 * clamps pin 11 and 30 to GND
 *
 */
void all03_set_gnd_11_30(void)
{
  all03_wr_pin(11,1);
  all03_wr_vhh_pin(11,0);
  all03_wr_vop_pin(11,0);

  all03_wr_pin(30,1);
  all03_wr_vhh_pin(30,0);
  all03_wr_vop_pin(30,0);
  all03_wr_vcc_pin(30,0);
  all03_wr_vhh_c_pin(30,0);

  all03_other_en|=BIT(0);
  all03_wr(ALL03_OTHER_EN_ID, all03_other_en);
}

/* enables/disables vop-2,4v to pin 7 */
void all03_set_vop24_7(int state)
{
  all03_wr_pin(7,1);
  all03_wr_vhh_pin(7,0);
  all03_wr_vop_pin(7,0);
  all03_wr_vcc_pin(7,0);
  if(state) all03_other_en|=BIT(1); else all03_other_en&=~BIT(1);
  all03_wr(ALL03_OTHER_EN_ID,all03_other_en);
}

/* enables/disables vop-2,4v to pin 25 */
void all03_set_vop24_25(int state)
{
  all03_wr_pin(25,1);
  all03_wr_vhh_pin(25,0);
  all03_wr_vop_pin(25,0);
  if(state) all03_other_en|=BIT(2); else all03_other_en&=~BIT(2);
  all03_wr(ALL03_OTHER_EN_ID,all03_other_en);
}

/* select fosc 0=>2.2MHz 1=>4.4MHz */
void all03_select_f_osc(int val)
{
  if(val) all03_other_en|=BIT(5); else all03_other_en&=~BIT(5);
  all03_wr(ALL03_OTHER_EN_ID,all03_other_en);
}

/* enables/disables osc to pin 2 and 3
   set pin 2, 3 to high
   disables all power supplis like Vcc, Vhh to pin 2, 3
*/
void all03_set_osc_2_3(int state)
{
  all03_wr_pin(2,1);
  all03_wr_pin(3,1);
  all03_wr_vhh_pin(2,0);
  all03_wr_vhh_pin(3,0);
  if(state) all03_other_en|=BIT(3); else all03_other_en&=~BIT(3);
  all03_wr(ALL03_OTHER_EN_ID,all03_other_en);
}

/* enables/disables osc to pin 18 and 19
   set pin 18, 19 to high
   disables all power supplis like Vcc, Vhh to pin 18, 19
*/
void all03_set_osc_18_19(int state)
{
  all03_wr_pin(18,1);
  all03_wr_pin(19,1);
  all03_wr_vhh_pin(18,0);
  all03_wr_vhh_pin(19,0);
  all03_wr_vop_pin(18,0);
  all03_wr_vop_pin(19,0);
  if(state) all03_other_en|=BIT(4); else all03_other_en&=~BIT(4);
  all03_wr(ALL03_OTHER_EN_ID,all03_other_en);
}

/* test if pin is ttl */
int all03_is_ttl_pin(int pin)
{
  if(pin<ALL03_MIN_PIN && pin>ALL03_MAX_PIN) return(0);
  return(1);
}


/* test if pin may be connected to Vcc */
int all03_is_vcc_pin(int pin)
{
  switch(pin)
  {
    case 40:
    case 36:
    case 34:
    case 32:
    case 31:
    case 30:
    case 29:
    case 28:

    case 27:
    case 26:
    case  9:
    case  7:
    case  5:
    case  1:
      return(1);
    break;
  }
  return(0);
}


/* test if pin may be connected to Vhh */
int all03_is_vhh_pin(int pin)
{
  if(pin<ALL03_MIN_PIN && pin>ALL03_MAX_PIN) return(0);
  else if(pin>=1 && pin<=8) return(0);
  else if(pin>=33 && pin<=40) return(0);
  return(1);
}


/* test if pin may be connected to Vop */
int all03_is_vop_pin(int pin)
{

  if(pin<ALL03_MIN_PIN && pin>ALL03_MAX_PIN) return(0);
  if(pin==2 || pin==3 || pin==4 || pin==6 || pin==8 || pin==33 || pin==40)
    return(0);
  return(1);
}


/* test if pin may be is connected to Vvhh_c */
int all03_is_vhh_c_pin(int pin)
{
  switch(pin)
  {
    case 32:
    case 31:
    case 30:
    case 29:
    case 28:
      return(1);
    break;
  }
  return(0);
}

/* connect (state=1) disconnect (state=0) pin to Vcc
   but disconnect pin from all other power supplies
   like Vhh, Vop...
*/
void all03_set_vcc_pin(int pin, int state)
{
#ifdef DEBUG
  int c;
  char ts[256], ats[256];

  if(pin==30)
  {
    sprintf(ts,"* ALL03 Warning - all03_set_vcc_pin: pin %d may be connected to GND!",pin);
    sprintf(ats,"ESC) Abort  ENTER) Continue");
    c=all03_msg_rv(ts,ats);
    if(c!=K_ENTER) return;
  }
#endif

  if(state)
  {
    all03_wr_pin(pin,1);
    if(all03_is_vhh_pin(pin)) all03_wr_vhh_pin(pin,0);
    if(all03_is_vop_pin(pin)) all03_wr_vop_pin(pin,0);
    if(all03_is_vhh_c_pin(pin)) all03_wr_vhh_c_pin(pin,0);
    if(all03_is_vcc_pin(pin)) all03_wr_vcc_pin(pin,1);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vcc_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
  else
  {
    if(all03_is_vcc_pin(pin)) all03_wr_vcc_pin(pin,0);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vcc_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
}


/* connect (state=1) disconnect (state=0) pin to Vhh
   but disconnect pin from all other power supplies
   like Vcc, Vop...
*/
void all03_set_vhh_pin(int pin, int state)
{
#ifdef DEBUG
  int c;
  char ts[256], ats[256];

  if(pin==30 || pin==11 || pin==20)
  {
    sprintf(ts,"* ALL03 Warning - all03_set_vhh_pin: pin %d may be connected to GND!",pin);
    sprintf(ats,"ESC) Abort  ENTER) Continue");
    all03_msg(ts);
    if(c!=K_ENTER) return;
  }
#endif

  if(state)
  {
    all03_wr_pin(pin,1);
    if(all03_is_vcc_pin(pin)) all03_wr_vcc_pin(pin,0);
    if(all03_is_vop_pin(pin)) all03_wr_vop_pin(pin,0);
    if(all03_is_vhh_c_pin(pin)) all03_wr_vhh_c_pin(pin,0);
    if(all03_is_vhh_pin(pin)) all03_wr_vhh_pin(pin,1);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vhh_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
  else
  {
    if(all03_is_vhh_pin(pin)) all03_wr_vhh_pin(pin,0);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vhh_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
}


/* connect (state=1) disconnect (state=0) pin to Vhh_c
   but disconnect pin from all other power supplies
   like Vhh, Vop...
*/
void all03_set_vhh_c_pin(int pin, int state)
{
#ifdef DEBUG
  int c;
  char ts[256], ats[256];

  if(pin==30)
  {
    sprintf(ts,"* ALL03 Warning - all03_set_vhh_c_pin: pin %d may be connected to GND!",pin);
    sprintf(ats,"ESC) Abort  ENTER) Continue");
    c=all03_msg_rv(ts,ats);
    if(c!=K_ENTER) return;
  }
#endif
  if(state)
  {
    all03_wr_pin(pin,1);
    if(all03_is_vcc_pin(pin)) all03_wr_vcc_pin(pin,0);
    if(all03_is_vop_pin(pin)) all03_wr_vop_pin(pin,0);
    if(all03_is_vhh_pin(pin)) all03_wr_vhh_pin(pin,0);
    if(all03_is_vhh_c_pin(pin)) all03_wr_vhh_c_pin(pin,1);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vhh_c_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
  else
  {
    if(all03_is_vhh_c_pin(pin)) all03_wr_vhh_c_pin(pin,0);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vhh_c_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
}


void all03_set_vop_pin(int pin, int state)
{
#ifdef DEBUG
  int c;
  char ts[256], ats[256];

  if(pin==30 || pin==11 || pin==20)
  {
    sprintf(ts,"* ALL03 Warning - all03_set_vop_pin: pin %d may be connected to GND!",pin);
    sprintf(ats,"ESC) Abort  ENTER) Continue");
    c=all03_msg_rv(ts,ats);
    if(c!=K_ENTER) return;
  }
#endif
  if(state)
  {
    all03_wr_pin(pin,1);
    if(all03_is_vhh_pin(pin)) all03_wr_vhh_pin(pin,0);
    if(all03_is_vcc_pin(pin)) all03_wr_vcc_pin(pin,0);
    if(all03_is_vhh_c_pin(pin)) all03_wr_vhh_c_pin(pin,0);
    if(all03_is_vop_pin(pin)) all03_wr_vop_pin(pin,1);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vop_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
  else
  {
    if(all03_is_vop_pin(pin)) all03_wr_vop_pin(pin,0);
    else
    {
#ifdef DEBUG
      sprintf(ts,"* ALL03 Error - all03_set_vop_pin: pin %d not in range!",pin);
      all03_msg(ts);
      return;
#endif
    }
  }
}


/*
   read and write buffers vcc_en, vhh_en,...
*/
unsigned char all03_rd_ttl_buf(int i)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>4)
  {
      sprintf(ts,"* ALL03 Error - all03_rd_ttl_buf: index %d out of range!",i);
      all03_msg(ts);
      return(1);
  }
#endif
  return(all03_ttl[i]);
}

void all03_wr_ttl_buf(int i, unsigned char b)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>4)
  {
    sprintf(ts,"* ALL03 Error - all03_wr_ttl_buf: index %d out of range!",i);
    all03_msg(ts);
    return;
  }
#endif
  all03_ttl[i]=b;
}

unsigned char all03_rd_vop_en_buf(int i)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>4)
  {
      sprintf(ts,"* ALL03 Error - all03_rd_vop_en_buf: index %d out of range!",i);
      all03_msg(ts);
      return(1);
  }
#endif
  return(all03_vop_en[i]);
}

void all03_wr_vop_en_buf(int i, unsigned char b)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>4)
  {
      sprintf(ts,"* ALL03 Error - all03_wr_vop_en_buf: index %d out of range!",i);
      all03_msg(ts);
      return;
  }
#endif
  all03_vop_en[i]=b;
}

unsigned char all03_rd_vhh_en_buf(int i)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>4)
  {
      sprintf(ts,"* ALL03 Error - all03_rd_vhh_en_buf: index %d out of range!",i);
      all03_msg(ts);
      return(1);
  }
#endif
  return(all03_vhh_en[i]);
}

void all03_wr_vhh_en_buf(int i, unsigned char b)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>4)
  {
      sprintf(ts,"* ALL03 Error - all03_wr_vhh_en_buf: index %d out of range!",i);
      all03_msg(ts);
      return;
  }
#endif
  all03_vhh_en[i]=b;
}


unsigned char all03_rd_vcc_en_buf(int i)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>2)
  {
      sprintf(ts,"* ALL03 Error - all03_rd_vcc_en_buf: index %d out of range!",i);
      all03_msg(ts);
      return(1);
  }
#endif
  return(all03_vcc_en[i]);
}

void all03_wr_vcc_en_buf(int i, unsigned char b)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>2)
  {
      sprintf(ts,"* ALL03 Error - all03_wr_vcc_en_buf: index %d out of range!",i);
      all03_msg(ts);
      return;
  }
#endif
  all03_vcc_en[i]=b;
}

unsigned char all03_rd_vhh_en_c_buf(int i)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>2)
  {
      sprintf(ts,"* ALL03 Error - all03_rd_vhh_en_c_buf: index %d out of range!",i);
      all03_msg(ts);
      return(1);
  }
#endif
  return(all03_vhh_en_c[i]);
}

void all03_wr_vhh_en_c_buf(int i, unsigned char b)
{
#ifdef DEBUG
  char ts[256];

  if(i<0 || i>2)
  {
      sprintf(ts,"* ALL03 Error - all03_wr_vhh_en_c_buf: index %d out of range!",i);
      all03_msg(ts);
      return;
  }
#endif
  all03_vhh_en_c[i]=b;
}

unsigned char all03_rd_vhh_buf(void)
{
  return(all03_vhh);
}

void all03_wr_vhh_buf(unsigned char b)
{
  all03_vhh=b;
}

unsigned char all03_rd_vcc_buf(void)
{
  return(all03_vcc);
}

void all03_wr_vcc_buf(unsigned char b)
{
  all03_vcc=b;
}

unsigned char all03_rd_vop_buf(void)
{
  return(all03_vop);
}

void all03_wr_vop_buf(unsigned char b)
{
  all03_vop=b;
}

unsigned char all03_rd_other_en_buf(void)
{
  return(all03_other_en);
}

void all03_wr_other_en_buf(unsigned char b)
{
  all03_other_en=b;
}

unsigned char all03_rd_id_f7_buf(void)
{
  return(all03_id_f7);
}

void all03_wr_id_f7_buf(unsigned char b)
{
  all03_id_f7=b;
}


/* returns base address of ALL03 */
unsigned short int all03_get_base_address(void)
{
  return(all03_base);
}

/* sets base address of ALL03 */
void all03_set_base_address(unsigned short int ba)
{
  all03_base=ba;
}


/* ****************** UTILITIES ******************* */

/*
 * dec_to_hex
 *
 * converts decimal to hex char '0', '1', '2', .. 'E', 'F'
 *
 */
char all03_dec_to_hex(int dec)
{
  dec&=0x0f;
  if(dec >= 0 && dec <=9) return(0x30+dec);
  else return(0x37+dec);
}

/*
 * hex_to_dec
 *
 * converts chars '0', '1', '2', .. 'E', 'F'
 * to decimal
 *
 */
int all03_hex_to_dec(char h)
{
  if(islower(h)) h=toupper(h);
  if(h>='0' && h<='9') return h-'0';
  else if(h>='A' && h<='F') return h-0x37;
  return(-1);
}

/*
 *  reverse_bits
 *
 *  exchanges bits in by
 *
 *  0 <-> 7
 *  1 <-> 6
 *  2 <-> 5
 *  3 <-> 4
 *  
 */
unsigned char all03_reverse_bits(unsigned char by)
{
  int i;
  unsigned char tb;

  tb=0;
  for(i=0;i<8;i++)
    if(by & BIT(i)) tb|=BIT(7-i) ;
    
  return(tb);
}


/***** input/output **************************/

/*
 *  msg
 *
 *  displays error message
 *  and waits enter
 *  
 */
void all03_msg(char *ts)
{
  printf("\n\007%s\n",ts);
  printf("Press <ENTER>");
  wait_enter();
}


/*
 *  msg_rv
 *
 *  displays 2 error messages
 *  and waits a key
 *  returns the code of the key
 *  to the caller
 *  
 */
int all03_msg_rv(char *ts, char *ats)
{
  printf("\n\007%s\n",ts);
  printf("%s\n",ats);
  return(key_get());
}


/*
 * edit_base
 *
 * change all03 base addres (unsigned short int base)
 *
 */
void all03_edit_base(void)
{
  int r, c, k;

  for(;;)
  {
    clear_screen();
    printf("*** EDIT BASE ADDRESS ***\n\n");
    printf("BASE ADDRESS: %04x\n\n", all03_base);
    for(r=0;r<4;r++)
    {
      printf("\n");
      for(c=0;c<4;c++)
        printf("%c) %04x   ",all03_dec_to_hex(4*r+c),all03_tab_base[4*r+c]);
    }
    printf("\n");
    printf("\n");
    printf("Q) Quit\n");
    printf("\n");
    printf("Enter command: ");
    flush_out();

    k=key_get();
    if((k>=32) && (k<127)) printf("%c\n",k);
    if(islower(k)) k=toupper(k);

    if(all03_hex_to_dec(k)>=0)
    {
      all03_base=all03_tab_base[all03_hex_to_dec(k)];
      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();
      }
    }
    if(k=='q' || k=='Q')
    {
      if(all03_test_base_address())
      {
        printf("\n\007* ALL03 Error - Programmer not found at base address=%04x!!!\n",all03_get_base_address());
        wait_enter();
        return;
      }
      else return;
    }
  }
}


/*
 * dump
 *
 * prints all03 registers
 *
 */
void all03_dump(void)
{
  int i;
  unsigned char dat0, dat1;
  
  clear_screen();
  printf("*** DUMP ALL03 REGISTERS ***\n\n");

  for(i=0;i<16;i++)
  {
    outp(all03_id_port,0xe0+i);
    dat0=inp(all03_data_port);
    outp(all03_id_port,0xf0+i);
    dat1=inp(all03_data_port);
    
    printf("id=%02x  data=%02x  --  id=%02x  data=%02x\n",
      0xe0+i, dat0, 0xf0+i, dat1);
  }  
}


