/*===========================
  This program is run at the PC-end to get readings from HP 34401A which is not connected directly to the PC.
  The system is configured as follows:
     PC------7520------7523--+---HP#1
		    |        |---HP#2
		    |
		    |--7523--+---HP#3
		    |        |---HP#4
		    |
		    |--7523--+---HP#5
		    |        |---HP#6
*/
#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();
    }
  }
}

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");                // #1 HP
  HPSendCommand(ComNo, ":02CONF:VOLT:DC");            // #1 HP
  HPSendCommand(ComNo, ":03SYST:REM");                // #2 HP
  HPSendCommand(ComNo, ":03CONF:VOLT:DC");            // #2 HP
  HPSendCommand(ComNo, ":05SYST:REM");                // #3 HP
  HPSendCommand(ComNo, ":05CONF:VOLT:DC");            // #3 HP
  HPSendCommand(ComNo, ":06SYST:REM");                // #4 HP
  HPSendCommand(ComNo, ":06CONF:VOLT:DC");            // #4 HP
  HPSendCommand(ComNo, ":08SYST:REM");                // #5 HP
  HPSendCommand(ComNo, ":08CONF:VOLT:DC");            // #5 HP
  HPSendCommand(ComNo, ":09SYST:REM");                // #6 HP
  HPSendCommand(ComNo, ":09CONF:VOLT:DC");            // #6 HP
  WaitClock(18);
}

/* ============================================================================
  Close HP in serial port
============================================================================ */
void CloseHP(int ComNo)
{
  HPSendCommand(ComNo, ":02*CLS");                    // #1 HP
  HPSendCommand(ComNo, ":02SYST:LOC");                // #1 HP
  HPSendCommand(ComNo, ":03*CLS");                    // #2 HP
  HPSendCommand(ComNo, ":03SYST:LOC");                // #2 HP
  HPSendCommand(ComNo, ":05*CLS");                    // #3 HP
  HPSendCommand(ComNo, ":05SYST:LOC");                // #3 HP
  HPSendCommand(ComNo, ":06*CLS");                    // #4 HP
  HPSendCommand(ComNo, ":06SYST:LOC");                // #4 HP
  HPSendCommand(ComNo, ":08*CLS");                    // #5 HP
  HPSendCommand(ComNo, ":08SYST:LOC");                // #5 HP
  HPSendCommand(ComNo, ":09*CLS");                    // #6 HP
  HPSendCommand(ComNo, ":09SYST:LOC");                // #6 HP
  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)
{
}

/*=============================================================================
  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;
  double AI;
  int Bye=0;
  int i;
  char str[80];



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

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



  InitHP(ComNo);
  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 7523 net
	ShowErrorCode(ret);
	i=1;
      }
    }

    if(HPReceiveCommand(ComNo, str)>0)  //get the HP readings from 7523 net
       if(i==1) printf("\nresponse: %s ",str);
  }
  CloseHP(ComNo);
  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);
}

