#include <bios.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>


#define COM1       0
#define DATA_READY 0x100
#define TRUE       1
#define FALSE      0
#define B9600      0xE0    /* Define baud rates and other IOCTL stuff */
#define DATA7      0x02
#define DATA8      0x03
#define STOP1      0x00
#define STOP2      0x04
#define NOPAR      0x00
#define ODPAR      0x08
#define EVPAR      0x18

#define COMBASE	   0x3f8	/* base address of com1        */
#define MCR        COMBASE + 4	/* modem ctl reg. for com1     */
#define LSR        COMBASE + 5	/* modem line status register  */
#define MSR        COMBASE + 6	/* modem status reg for com1   */
#define RDR        0x01		/* Rec. Data Ready             */
#define LOOPBACK   0x10		/* loopback bit                */
#define RISC	   0x04		/* ring indicator state change */

#define FSETTINGS ( B9600 | NOPAR | STOP2 | DATA8 )

#define BIGW	0	/* whole screen window                  */
#define CMD 	1	/* command window                       */
#define STATUS	2	/* status window                        */
#define INFO	3	/* info - avail cmds etc                */

extern void send();
extern void pulse(void);
extern unsigned char word0,word1;
extern int fcount;
extern unsigned char dstr[];

unsigned char rdata[10];	/* rcv data buffer */
int last_min = 0xff;    /* invalid nums - force display first time */
int last_sec = 0xff;
int last_hr  = 0xff;	/* last data displayed on status window  */
int last_sign= 0xff;	/* last sign on counter (+/-)            */
int last_stat= 0xff;    /* last status word (word 6)             */
int last_tran= 0xff;	/* last transition flag (B3 of word 7)   */
int last_fun = 0xff;	/* last function - word 2                */
int nocam    = FALSE;	/* no camera present flag                */

struct WINFO {			/* structure for info for all windows */
       int  left,top,rt,bottom;	/* window corners                */
       int  txt,bkgnd;		/* window colors                 */
       } winfo[10] = {		/* allocate 10 window structs    */
         {1,1,80,24,WHITE,BLACK},    /* whole screen window      */
	 {40,1,70,13,RED,LIGHTGRAY}, /* CMD window               */
	 {30,18,60,24,YELLOW,BLUE},  /* STATUS window colors     */
         {1,1,27,25,YELLOW,MAGENTA}, /* INFO window - avail cmds */
	 };
struct text_info ti;

int main(void)
{
   int in, out, status, DONE = FALSE;
   int TIMER = FALSE;
   int mcr_value, msr_value, count;
   long int TIME;
   unsigned char *scrn_buf;	/* screen buffer to save old screen */

   gettextinfo(&ti);		/* get current screen info          */
   if((scrn_buf=malloc(ti.screenheight * ti.screenwidth *2)) ==NULL)
      {
      printf("Sorry - not enough memory to save current screen!\n");
      exit(1);
      }
   gettext(1,1,ti.screenwidth,ti.screenheight,scrn_buf); /* save screen img. */
   bioscom(0, FSETTINGS, COM1);
   wininit();
   while (!DONE)
   {
   read_camera();	/* show status info                      */
   if(TIMER == TRUE)	/* must be taking pix - check time       */
       {
       if(biostime(0,0L) > TIME)
	 {
         word0=0x18;
	 word1=0x33;
	 fcount=0x6;
	 send(); 
	 sound(1000);
	 delay(160);
	 sound(1500);
	 delay(160);
	 nosound();
	 TIMER = FALSE;
	 clrcmd();	/* clear 'taking pix' message            */
	 }
       }
   if (kbhit())
	 {
	    in = getch();
	    if(in == '\x1B')
	       {
	       DONE=TRUE;
	       continue;
               }
	    if(nocam == TRUE)
	       {
	       shocmd(" =====>> ERROR - NO camera!!!");
	       sleep(1);
               clrcmd();
	       continue;
               }
	    switch(in)
	       {

	       case 'H':	/* hex data entry - try new command */
		  shocmd("   Hex data entry mode ...");
		  gotoxy(1,6);
		  cprintf("Word 0     = 0x");
		  cscanf("%x",&word0);
		  gotoxy(1,7);
		  cprintf("Word 1     = 0x");
		  cscanf("%x",&word1);
		  gotoxy(1,8);
		  cprintf("Frame cnt. = 0x");
		  cscanf("%x",&fcount);
		  send();	/* do what ever it was  */
		  clrcmd();
		  sleep(1);
		  gotoxy(1,6); clreol();
		  gotoxy(1,7); clreol();
                  gotoxy(1,8); clreol();
		  break;

	       case 'b':	/* try our beep routine */
                  shocmd("   da beep ... da beep!");
		  tout();
		  clrcmd();
		  break;

	       case 'c':	/* calibrate routine */
                  shocmd(" ===>  CALIBRATE <===");
		  cal();
                  clrcmd();
                  break;
	       
	       case 'e':	/* eject tape */
		   shocmd(" ===> EJECT tape <===");
		   word0=0x18;
		   word1=0x2c;
		   fcount=6;
		   send();
		   sleep(3);
		   clrcmd();
		   break;

	       case 'r':			/*    reset counter */
		   shocmd(" ==> Reset Counter <==");
		   word0=0x18;
		   word1=0x8c;
		   fcount=6;
		   send();
		   sleep(1);
		   clrcmd();
                   break;
	    
	       case 's':	/* send via assm lang. routines     */
		   word0=0x18;
		   word1=0x33;
		   fcount=0x6; /*normally 5                         */
		   shocmd(" ===> Start/Stop <==");
                   clrcmd();
		   send();
		   TIMER = FALSE; /* clear timer if we use this key */
		   break;

	       case 't':	/* zoom tele - until any key hit    */
		   word0=0x28;
		   word1=0x35;	/* zoom tele command                */
                   shocmd(" ===> ZOOM Tele <===");
                   gotoxy(1,13); /* secondary command info line     */
		   textcolor(winfo[CMD].txt + BLINK);
		   cprintf("   ZOOOOOMing Telephoto ... ");
		   while(!kbhit())
		      {
		      fcount=1;	/* send modifies this each time     */
		      send();
		      }
		   textcolor(winfo[CMD].txt);
		   gotoxy(1,13);
		   clreol();
		   clrcmd();
		   break;

               case 'w':	/* zoom wide - until any key hit       */
		   word0=0x28;
		   word1=0x37;	/* zoom wide command                   */
                   shocmd(" ===> ZOOM wide <===");
		   gotoxy(1,13); /* secondary command info line        */
		   textcolor(winfo[CMD].txt + BLINK);
                   cprintf("   ZOOOOOMing Wide Angle ... ");
		   while(!kbhit())
		      {
		      fcount=1;	/* send modifies this each time        */
		      send();
		      }
		   textcolor(winfo[CMD].txt);
		   gotoxy(1,13);
		   clreol();
		   clrcmd();     
		   break;
	       case 'p':	/* take pix - start,12sec,stop         */
		   shocmd(" => Taking 12sec pix ...");
		   word0=0x18;	/* start stop command			 */
		   word1=0x33;
		   fcount=6;	/* repeat for 6 frames			 */
		   send(); 
		   TIMER = TRUE;/* set timer active flag		 */
		   TIME = biostime(0,0L) + (14 * 18); /* cur. time +
                   					14 sec * 18 tics */
		   break;

	       default:
		   break;
	       }
         gotoxy(1,3);
	 cprintf(" F70 control ==> ");
	 }
       }
   sel_win(BIGW);			/* select whole screen again    */
   normvideo();				/* make sure normal video set   */
   _setcursortype(_NORMALCURSOR);	/* set cursor back to normal    */
   puttext(1,1,ti.screenwidth,ti.screenheight,scrn_buf); /* reload usr screen    */
   if(ti.cury == ti.screenheight)
     {
     gotoxy(ti.curx,ti.cury-1);
     printf("\n\r");		/* force a scroll */
     }
   gotoxy(ti.curx,ti.cury);
   return;				/* goodbye - back to dos!       */              


}

tout(void) /* called from sendstuf.asm - used for time out
		   from frame sync routine - no start bit detected */
	{
	sound(1200);
	delay(150);
	sound(800);
	delay(150);
	nosound();
	sel_win(CMD);
	gotoxy(6,10);
	textcolor(GREEN + BLINK);
        textbackground(BLACK);
	cprintf("Frame sync time out!!!\r");
        sleep(4);
	sel_win(CMD);	/* reset defaults */
	gotoxy(6,10);
	clreol();
        return 0;
	}

read_camera(void)
	{
	int count,sflag;
        sel_win(STATUS);
	for (count=0;count<5;count++)  /* sync to frame gap             */
	    {
	    if(inportb(MSR) & RISC) count = 0 ;
	    delay(1);		/* wait 1 ms and try again              */
	    }
	while(inportb(LSR) & RDR) inportb(COMBASE); /* empty uart rcv   */
	for (count=0; count<8; count++)	/* read next 8 chars in         */
	    {
	    rdata[count]=rdcom();	/* read a char in               */
	    }
	if(rdata[5] == 0) return(-1);   /* skip rest if rdata[5] is bad */
	if(last_fun != rdata[4])	/* function camera is now doing */
	    {
	    gotoxy(1,6);		/* line 6 for camera function   */
            cprintf("FUNCTION: ");
            disp_fun(rdata[4]);		/* display what camera is doing */
	    last_fun = rdata[4];
	    }

	if(rdata[5] & 0x01)		/* illeagle command             */
	    {
	    gotoxy(1,5);
	    textcolor(winfo[STATUS].txt + BLINK);
	    if(rdata[5] == 0xff)        /* no cam present               */
	      {
	      if(nocam == FALSE)
                 {
		 cprintf("=====> No Camera Present! <====");
	         nocam=TRUE;
                 }
              }
	    else
	      {
	      nocam=FALSE;
	      cprintf(" **** UNRECOGNIZED Command ****");
	      sleep(4);
	      textcolor(winfo[STATUS].txt);
	      gotoxy(1,5);
	      clreol();
	      }

	    }
	else if(nocam==TRUE)		/* if camera now here clear err */
	   {
	   nocam=FALSE;
	   gotoxy(1,5);
	   textcolor(winfo[STATUS].txt);
	   clreol();
	   }    			/* error line                   */
	sflag = (rdata[5] & 0xf0);	/* find out what words mean     */
	switch(sflag)
	    {
	    case 0x10:			/* 8mm vcr status data          */
	       if(last_stat != rdata[6])  /* status has changed         */
		 {
		 gotoxy(2,4);		/* status line                  */
		 cprintf("Status: 0x%02x  ",rdata[6]);
		 last_stat = rdata[6];
		 }
	       if(last_tran != rdata[7] & 0x08)
		 {
		 gotoxy(15,4);		/* show transition flag if chg */
		 if(rdata[7] & 0x08)
                    {
		    textcolor(winfo[STATUS].txt + BLINK);
		    cprintf("In transition");
		    }
		 else
		    {
		    textcolor(winfo[STATUS].txt); /* set back to normal */
		    cprintf("              ");
		    }
		 last_tran = rdata[7] & 0x08;
		 }
	       break;

	    case 0x20:
	       sound(2000);
	       delay(150);
	       sound(400);
	       delay(300);
	       nosound();		/* 4 digit counter in 6,7,8     */
	       break;

	    case 0x30:       /* seconds/mins - only update if chg       */
	       if((rdata[7] != last_min) || (rdata[6] != last_sec))
	       {			/* seconds/minutes data         */
	         gotoxy(13,3);		/* do minutes first             */
	         cprintf(":%d%d",((rdata[7]&0xf0)>>4),(rdata[7]&0x0f));
	         cprintf(":%d%d",((rdata[6]&0xf0)>>4),(rdata[6]&0x0f));
	         last_min = rdata[7];  /* update records                */
		 last_sec = rdata[6];
	       }
	       break;

	    case 0x40:		/* hours data- only update if chg       */
	       if(rdata[6] != last_hr)
                 {
	         gotoxy(3,3);
		 cprintf("Timer:  %d%d",(rdata[6]&0x0f),((rdata[6]&0xf0)>>4));
		 last_hr = rdata[6];
		 }
	       if((rdata[7]&0x80) != last_sign)
		 {
                 gotoxy(10,3);
	         cprintf("%c",(((rdata[7]&0x80) ==0x80)?'-':' ')); 
		 last_sign=(rdata[7]&0x80);
                 }
	       break;
		
	    }
	sel_win(CMD);			/* back to command window */
       	return(0);
	}

rdcom(void)
	{
        int count = 0xfff,x;
	while(((inportb(LSR)&RDR)==0 ) && (0 < count--)); /*loop till data ready */
	if(count == 0) cprintf("rdcom timeout!!");
        x = (count > 0) ? ~(inportb(COMBASE)) : 0xff;  /* 0xff = timeout */
	return(x);
        }

xmit(xdata)
    unsigned char xdata;
    {
    union REGS regs;

    regs.h.ah = 1;	/* write char function */
    regs.x.dx = 0;	/* com1 */
    regs.h.al = xdata;	/* data to send */
    int86(0x14,&regs,&regs); /* send char */
    return(0);
    }


wininit(void)
    {
    sel_win(BIGW);	/* clear whole screen */
    clrscr();
    _setcursortype(_NOCURSOR);
    sel_win(STATUS);	/* now do status window */
    clrscr();
    cprintf("        Sony F-70 Status ");
    sel_win(CMD);	/* select command window */
    clrscr();		/* clear to background color */
    cprintf("     F-70 Command window\n\r\nF-70 CTL =>");
    sel_win(INFO);	/* commands available etc in this window */
    clrscr();
    cprintf("  Available Commands:\n\r\n");
    cprintf("===> CAMERA Mode <=====\n\r");
    cprintf("* b .. beep (time out)\n\r");
    cprintf("* e .. eject tape\n\r");
    cprintf("  p .. take 12 sec pix\n\r");
    cprintf("* r .. reset counter\n\r");
    cprintf("  s .. start/stop\n\r");
    cprintf("  t .. zoom telephoto\n\r");
    cprintf("  w .. zoom wide angle\n\r");
    cprintf("    (any key stops zoom)\n\n\r");
    cprintf("===> VCR MODE <===\n\r");
    cprintf("   (* also work)\n\r");
    cprintf("  F .. Fast Forward\n\r");
    cprintf("  P .. Play\n\r");
    cprintf("  R .. Rewind\n\r");
    cprintf("  S .. stop\n\r");
    cprintf("  H .. Hex data entry mode\n\r"); 
    textcolor(CYAN);
    highvideo();
    cprintf("\n\r==>  <ESC> to exit  <===");
    gotoxy(1,24);
    cprintf("SENDSTUF.ASM dated \n\r   %s",dstr);
    return;
    }			/* leave command window selected */


sel_win(int win)
    {
    window(winfo[win].left,winfo[win].top,winfo[win].rt,winfo[win].bottom);
    textcolor(winfo[win].txt);
    textbackground(winfo[win].bkgnd);
    return(0);
    }


disp_fun(int fun)	/* display camera funct. - word 4 */
    {
    switch(fun)
       {
       case 0x01:
	  cprintf("EJECTED Cassette    ");
	  break;

       case 0x02:
	  cprintf("STOP Normal         ");
	  break;

       case 0x03:
	  cprintf("FFwd                ");
	  break;

       case 0x04:
	  cprintf("REC Normal          ");
	  break;

       case 0x06:
	  cprintf("PLAY Normal         ");
	  break;

       case 0x07:
	  cprintf("PLAY <PAUSE>        ");
	  break;

       case 0x14:
	  cprintf("REC <PAUSE>         ");
	  break;

       case 0x32:
	  cprintf("STOP Battery down   ");
	  break;

       case 0x46:
	  cprintf("SEARCH Forward      ");
	  break;

       case 0x47:
	  cprintf("SLOW (1/10)         ");
          break;

       case 0x56:
	  cprintf("SEARCH Reverse      ");
	  break;

       case 0x67:
	  cprintf("FRAME Advance       ");
	  delay(300);
          break;

       case 0x83:
	  cprintf("REWIND              ");
	  break;

       case 0x85:	/* this code is not doc in CTL L spec */
	  cprintf("EDITSEARCH +        ");
	  break;

       case 0x95:	/* this code is not doc in CTL L spec */
	  cprintf("EDITSEARCH -        ");
          break;

       default:
	  cprintf("Unknown code '0x%x' ",fun);
          if(fun == 0) sho_all();
	  break;
       }
    return;
    }


shocmd(unsigned char *str)
    {
    sel_win(CMD);
    gotoxy(1,12);
    cprintf("%s",str);
    sound(2400);
    delay(150);
    sound(1600);
    delay(200);
    nosound();
    return;
    }


clrcmd(void)		/* clear command info line in CMD window */
    {
    sel_win(CMD);	/* make sure we are in right window      */
    gotoxy(1,12);	/* command status info line              */
    clreol();		/* clear whatever is on this line        */
    return;
    }

sho_all(void)		/* debug stuff - dump all data bytes     */
    {
    int x;
    sel_win(CMD);	/* use command window for dump */
    gotoxy(1,5);
    for(x=0;x<8;x++)
       cprintf("word%d = 0x%x\n\r",x,rdata[x]);
    cprintf("===> any key contines");
    while(!kbhit());
    getch();
    return;
    }


