/**
 * This is a small program which implements a little terminal
 * application for talking directly to the Delta-Tau PMAC
 * motion controller via TCP/IP
 *
 * copyright: GPL
 *
 * Mark Koennecke, March 2009
 */
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include "asynnet.h"

#define ETHERNET_DATA_SIZE 1492
#define INPUT_SIZE        (ETHERNET_DATA_SIZE+1)        /* +1 to allow space to add terminating ACK */
#define STX   '\2'
#define CTRLB '\2'
#define CTRLC '\3'
#define ACK   '\6'
#define CTRLF '\6'
#define BELL  '\7'
#define CTRLG '\7'
#define CTRLP '\16'
#define CTRLV '\22'
#define CTRLX '\24'

/* PMAC ethernet command structure */
#pragma pack(1)
typedef struct tagEthernetCmd {
  unsigned char RequestType; 
  unsigned char Request;
  unsigned short wValue;
  unsigned short wIndex;
  unsigned short wLength;       /* length of bData */
  unsigned char bData[ETHERNET_DATA_SIZE];
} ethernetCmd;
#pragma pack()

#define ETHERNET_CMD_HEADER ( sizeof(ethernetCmd) - ETHERNET_DATA_SIZE )

/* PMAC ethernet commands - RequestType field */
#define VR_UPLOAD   0xC0
#define VR_DOWNLOAD 0x40

/* PMAC ethernet commands - Request field */
#define VR_PMAC_SENDLINE    0xB0
#define VR_PMAC_GETLINE     0xB1
#define VR_PMAC_FLUSH       0xB3
#define VR_PMAC_GETMEM      0xB4
#define VR_PMAC_SETMEN      0xB5
#define VR_PMAC_SETBIT      0xBA
#define VR_PMAC_SETBITS     0xBB
#define VR_PMAC_PORT        0xBE
#define VR_PMAC_GETRESPONSE 0xBF
#define VR_PMAC_READREADY   0xC2
#define VR_CTRL_RESPONSE    0xC4
#define VR_PMAC_GETBUFFER   0xC5
#define VR_PMAC_WRITEBUFFER 0xC6
#define VR_PMAC_WRITEERROR  0xC7
#define VR_FWDOWNLOAD       0xCB
#define VR_IPADDRESS        0xE0

/*--------------------------------------------------------*/
int main(int argc, char *argv[])
{
  ethernetCmd cmd;
  int pmacHandle, port, bytesToWrite;
  char *colon, line[132], output, expectCR, repChar;
  time_t start;

  if(argc < 2) {
    printf("Usage:\n\tpmacterm host:port\n");
    exit(1);
  }
  
  colon = strchr(argv[1],':');
  if(colon == NULL){
    printf("ERROR: no colon in host:port\n");
    exit(1);
  }
  port = atoi(colon+1);
  *colon = '\0';
  pmacHandle = ANETconnect(argv[1],port);
  if(pmacHandle < 0){
    printf("ERROR: failed to connect to the PMAC controller with errno %d\n",errno);
    printf("Try to use the numeric IP, sometimes this helps\n");
    exit(1);
  }

  memset(&cmd, 0, sizeof(ethernetCmd));
  cmd.RequestType = VR_DOWNLOAD;
  cmd.Request = VR_PMAC_GETRESPONSE;
  cmd.wValue = 0;
  cmd.wIndex = 0;
   
  while(1){
    fprintf(stdout,"pmac> ");
    memset(line,0,132);
    fgets(line,132,stdin);
    if(strstr(line,"exit") != NULL){
      break;
    }
    cmd.wLength = htons(strlen(line));
    bytesToWrite = strlen(line) + 1+ ETHERNET_CMD_HEADER;
    strcpy((char *)cmd.bData, line);
    ANETwrite(pmacHandle, &cmd,bytesToWrite);
    start = time(NULL);
    output = 0;
    expectCR = 0;
    while(1){
       ANETprocess();
       if(time(NULL) > start + 10){
         printf("TIMEOUT!!!\n");
	 fflush(stdout);
         break;
       }
       if(ANETread(pmacHandle, &repChar,1) == 1){
	 ANETreadConsume(pmacHandle,1);
         if(repChar == STX || repChar == BELL){
	   expectCR = 1;
	   continue;
         }
	 if(expectCR && repChar == '\r'){
	   printf("\n");
	   fflush(stdout);
	   break;
	 }
	 if(repChar == '\n'){
	   printf("\n");
	   fflush(stdout);
	   break;
	 }
	 if(repChar == ACK){
	   if(output){
	     printf("\n");
	   } else {
	     printf("ACK\n");
           }
	   fflush(stdout);
	   break;
	 }
	 printf("%c",repChar);
	 output = 1;
       }
    }
  }

  ANETclose(pmacHandle);
  exit(0);
}
