/*
  ping-apollo - exchange data with Apollo speech synthesizer

*/

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
#include <linux/serial.h>

#define DEFAULT_DEVICE "/dev/ttyS0"
#define MAXCHARS 128

static int readable (int fd, int usec);

/* write usage message and exit with status n.  Write message to
   stderr if n is nonzero, otherwise to stdout. */
void usage(int n)
{
  fprintf(n?stderr:stdout, 
	  "ping-apollo - exchange data with Apollo synthesizer\n"
	  "usage: ping-apollo  data-to-write  [device]\n"
	  "default device is /dev/ttyS0\n");
  exit(n);
}

/* return nonzero if file descriptor fd could be read without
   blocking. */
static int readable (int fd, int usec)
{  
  int retval;
  fd_set rfds, wfds, efds;
  struct timeval tv;
  FD_ZERO(&rfds);
  FD_SET(fd, &rfds);
  FD_ZERO(&wfds);
  FD_ZERO(&efds);
  tv.tv_sec = usec/1000000;	/* wait the specified time for the files to
				   become readable */
  tv.tv_usec = usec%1000000;
  retval = select(fd+1, &rfds, &wfds, &efds, &tv);
  return retval;
}

int main(int argc, char **argv)
{
  unsigned long status=0;
  int fd;
  int numchars=0;
  char *devname=DEFAULT_DEVICE;
  char buf[MAXCHARS+1];

  if (argc < 2) usage(1);
  if (argc > 2) devname=argv[2];
  fd = open(devname,O_RDWR);
  if (fd == -1)
    {
      fprintf(stderr, "cannot open %s\n", devname);
      exit(1);
    }

  ioctl(fd, TIOCMGET, &status);
  status |= TIOCM_RTS;
  ioctl(fd, TIOCMSET, &status); /* assert RTS i.e. raise RTS line
				   (required before the Apollo will
				   read) */

  usleep(10000);		/* 100 usec is enough */
  write(fd, argv[1], strlen(argv[1]));
  {
    unsigned lsr;
    		
    /* wait until UART transmit buffer is empty */
    while(1)
      {
	ioctl(fd, TIOCSERGETLSR, &lsr); /* get line status register */
	if (lsr) break;
	usleep(10000);
      } 
  }

  usleep(10000);		/* 100 usec is enough */
  status &= ~TIOCM_RTS;
  ioctl(fd, TIOCMSET, &status); /* un-assert RTS i.e. raise RTS line
				   (required before the Apollo will
				   write) */
  /*
  fprintf(stderr, "status=%lx RTS=%d DTR=%d DSR=%d\n",
	 status,
	 (status&TIOCM_RTS)!=0,
	 (status&TIOCM_DTR)!=0,
	 (status&TIOCM_DSR)!=0);
  */
  /* 100000: stops after first punctuation
     70000: stops after first punctuation
     30000: stops after first punctuation
     10000: stops after first punctuation
  */
  while(readable(fd, 10000) && numchars < MAXCHARS)
    {
      if (read(fd, buf+numchars++, 1) < 0)
	{
	  perror("read-apollo");
	  exit(1);
	}
    }
  buf[numchars]=0;
  printf("%s", buf);
  return 0;
}
