/* This demo program is run at PC-end to get the readings from different HP 34401A multimeters.
   The multimeters and PC don't connect directly. They use the following configuration.
       PC------7520---+--7522-----HP#1
		      |
		      +--7522-----HP#2
		      |
		      +--7522-----HP#3

*/
#include "com.h"
#include <conio.h>
#include <stdio.h>
#include <string.h>



#include        <dos.h>
#include        <time.h>


/* ===========================================================================
  Transmit one char to ComNo
 =========================================================================== */
int TxCharCOM(int ComNo, char ch)
{
  clock_t c1, c2;
  int time_wait;
  int ComBase;

  if(ComNo == COM1) ComBase = Com1Base;         /* Set base address */
  else if(ComNo == COM2) ComBase = Com2Base;

  c1 = clock();
  time_wait=0;
  while(!(inportb(LSR) & 0x20)) {               /* Wait until line ready */
    c2 = clock();
    if(c1 != c2) {
      c1 = c2;
      time_wait++;
    }
    if(time_wait > COM_MAX_RX_WAIT_TIME) return(RxTimeOut);
  }
  outportb(TxD, ch);                            /* Output char           */
  return(TxOK);
}

/* ===========================================================================
  Initial Port of ComNo
 =========================================================================== */
int InitCOM(int ComNo, unsigned long int BaudRate, int DataFormat)
{
  int br, ComBase;
  char MSB, LSB;

  if(ComNo == COM1) ComBase = Com1Base;
  else if(ComNo == COM2) ComBase = Com2Base;

  br = 115200L/BaudRate;
  MSB = (br&0xff00)>>8;
  LSB = br&0xff;

  disable();

  outportb(LCR, 0x80);                          /* Set baudrate */
  outportb(DLL, LSB);
  outportb(DLH, MSB);
  outportb(LCR, DataFormat);                    /* Set DataFormat */
  outportb(FCR,0xc1);        //enable FIFO, 14 bit buffer

  outportb(IER, 0);                             /* Disable all Interrupt */
  inportb(LSR);
  inportb(RxD);

  outportb(IER, 0x01);                          /* Int. while receive data */
  outportb(TxD, 0x0d);

  enable();
  return(0);

}

/* ===========================================================================
  Reset ReceiveQueue of ComNo
 =========================================================================== */
int ResetQueue(int ComNo)
{
  return(0);
}

/* ===========================================================================
  Polling a char from ComNo
  Return RxOK
         RxTimeOut
 =========================================================================== */
int PollRxChar(int ComNo, char* ch)
{
  clock_t c1, c2;
  int ComBase, wait_time;

  if(ComNo==COM1) ComBase = Com1Base;
  else ComBase = Com2Base;

  wait_time=0;
  c1 = clock();
  while((inportb(LSR) & 0x0f)!=0x01) {
    c2 = clock();
    if(c1 != c2) {
      c1 = c2;
      wait_time++;
    }
    if(wait_time > COM_MAX_RX_WAIT_TIME) return(RxTimeOut);
  };

  *ch=inportb(RxD);
  return(RxOK);
}

/* ===========================================================================
  Wait a clock tick
 =========================================================================== */
void WaitClock(int count)
{
  int temp;
  clock_t c1, c2;

  for(temp=0; temp<count; temp++) {
    c1 = clock();
    c2 = clock();
    while(c2==c1) {
      c2 = clock();
    }
  }
}



/////////// hputil.c


ComSetting com[2];

/* ============================================================================
  Initial HP in serial port
============================================================================ */
void InitHP(int ComNo)
{
  com[ComNo].ComNo = ComNo;
  com[ComNo].BaudRate = 9600L;
  com[ComNo].DataFormat = Data8bit + NonParity + Stop1bit;
  com[ComNo].CheckSum = CHKSUMdisable;
  OpenCOM(ComNo);

  HPSendCommand(ComNo, ":02SYST:REM");           // passing "SYST:REM" to the 7522 with address 01
  HPSendCommand(ComNo, ":02*CLS");

  HPSendCommand(ComNo, ":04SYST:REM");           // passing "SYST:REM" to the 7522 with address 02
  HPSendCommand(ComNo, ":04*CLS");
  HPSendCommand(ComNo, ":06SYST:REM");           // passing "SYST:REM" to the 7522 with address 03
  HPSendCommand(ComNo, ":06*CLS");
  WaitClock(18);
}

/* ============================================================================
  Close HP in serial port
============================================================================ */
void CloseHP(int ComNo)
{
  HPSendCommand(ComNo, ":02*CLS");
  HPSendCommand(ComNo, ":02SYST:LOC");
  HPSendCommand(ComNo, ":04*CLS");
  HPSendCommand(ComNo, ":04SYST:LOC");
  HPSendCommand(ComNo, ":06*CLS");
  HPSendCommand(ComNo, ":06SYST:LOC");
  CloseCOM(ComNo);
}

/* ============================================================================
  Send Command to HP in serial port
============================================================================ */
int HPSendCommand(int ComNo, char *str)
{
  int i;
  unsigned char chk=0;
  ResetQueue(ComNo);
  for(i=0; str[i]!=0; i++)
    {
    if(TxCharCOM(com[ComNo].ComNo, str[i]) == TxTimeOut) return(TxTimeOut);
    chk += str[i];
    }
  if(TxCharCOM(com[ComNo].ComNo, 0x0d)==TxTimeOut) return(TxTimeOut);
  return(TxOK);
}

/* ============================================================================
  Receive Command to HP in serial port
============================================================================ */
int HPReceiveCommand(int ComNo, char *str)
{
  int end_of_rx=0, i=0;

  for(i=0; !end_of_rx; i++) {
    str[i] = 0;
    switch(PollRxChar(com[ComNo].ComNo, str+i)) {
      case RxOK :
	if((str[i] == 0x0d))
	{
	  str[i] = 0;
	  end_of_rx = 1;
	}
	break;
      case RxTimeOut :
	return(RxTimeOut);
      case RxOverFlow :
	return(RxOverFlow);
    }
  }
  i--;

  return(i);
}

/* ============================================================================
  Read analog value from HP
============================================================================ */
int ReadHP(int ComNo, double *AI)
{
  int ret;
  float A;
  char str1[80] ;

  HPSendCommand(ComNo, "READ?");
  ret = HPReceiveCommand(ComNo, str1);
  if(ret < 0) return(ret);
  *AI = atof(str1);
  return(HP_OK);
}

/*=============================================================================
  Initial COM port
=============================================================================*/
int OpenCOM(int ComNo)
{
  InitCOM(com[ComNo].ComNo, com[ComNo].BaudRate, com[ComNo].DataFormat);
  ResetQueue(com[ComNo].ComNo);
  return(0);
}

/*=============================================================================
  Close/Restore COM port
=============================================================================*/
int CloseCOM(int ComNo)
{
  return(0);
}


int ShowErrorCode(int error_code);

int main(char argc, char* argv[])
{
  int ret, ComNo;

  int Bye=0;
  int i=0;//to clear the outout buffer of HP34401A
  char str[80];



  if(argc!=2) {
    printf("No COM port assigned\n");
    printf(" Use HP22_M 1 for COM1, HP22_M 2 for COM2");
    exit(0);
  }

  if(argv[1][0] == '1') {
    printf("Connect 7522 net in COM1\n");
    ComNo = COM1;
  }
  else if(argv[1][0] == '2') {
    printf("Connect 7522 net in COM2\n");
    ComNo = COM2;
  }
  else {
    printf(" Use HP22_M 1 for COM1, HP22_M 2 for COM2");
    exit(0);
  }



  InitHP(ComNo);                              // set all HP 34401A into remote control mode
  while(!Bye)
  {
    if(kbhit())
    {
      printf("\ncommand-> ");
      scanf("%s",str);
      if((str[0]=='q')||(str[0]=='Q'))
      {
	Bye=1;
      }
      else
      {
	ret = HPSendCommand(ComNo,str);      //forward the command to the 7522 net
	ShowErrorCode(ret);
	i=1;

      }
    }
    if(HPReceiveCommand(ComNo, str)>0)       //get the HP readings from 7522 net
       if(i==1) printf("\nresponse: %s ",str);

  }
  CloseHP(ComNo);                            // set all HP 34401A to the local mode
  return(0);
}

int ShowErrorCode(int error_code)
{
  printf("\n");
  switch(error_code) {
    case RxOK :         printf("RxOK        "); break;          /*   1 */
    case TxOK :         printf("TxOK        "); break;          /*   2 */
    case HP_OK :        printf("HP OK       "); break;          /*   3 */

    case TxTimeOut :    printf("TxTimeOut   "); break;          /* -10 */
    case RxTimeOut :    printf("RxTimeOut   "); break;          /* -11 */
    case RxOverFlow :   printf("RxOverFlow  "); break;          /* -12 */
    defualt :           printf("%d ", error_code); break;
  }
  return(0);
}

