//
//	Garmin host-mode protocol engine.
//
//	Paul Nash
//	paul@frcs.alt.za

//
//	$Header: /usr/home/pilot/gypsy-1.6/RCS/host.c,v 1.9 1999/08/30 06:35:32 paul Exp $
//
//	$Log: host.c,v $
//	Revision 1.9  1999/08/30 06:35:32  paul
//	Added Jaque Andre's patches
//
//	Revision 1.8  1999/05/13 10:25:13  paul
//	Still trying to make GPSy work.
//
//	Revision 1.7  1999/05/12 08:48:05  paul
//	Ready for release as Gypsy 1.4.  Major changes include:
//	*  Rudimentary track/route buffer to transfer data between GPS
//	   and PC (a'la gps2p2pc)
//	*  Protocol fix for DLE escaping bug
//	*  Code changes from <andre@drfmc.ceng.cea.fr> to be able to
//	   compile a PalmOS2 version
//	*  Garmin protocol tries a bit harder to recover from comms
//	   errors (but is still *very* dumb)
//
//


#pragma pack(2)

#include "gps.h"
#include <Common.h>
#include <System/SysAll.h>
#include <System/SerialMgr.h>
#include <System/SysEvtMgr.h>
#include <UI/UIAll.h>
//	This is only needed for the GNU C/C++ 0.5 cross-compiler
#include "callback.h"

#include "globals.h"


//
//	Local function prototypes
//

void GetHostCommand (void);
void displayPacket (char *msg, char *buf);
void showLog (char *contents);

//	Internal global variables and the like

static char *rcs_id = "$Id: host.c,v 1.9 1999/08/30 06:35:32 paul Exp $";
#define BUFLEN 256


//
//	Primary form event handler
//

Boolean HandleHostEvent (EventPtr e)
{
   int handled = false;
   FormPtr form;
   Long num_bytes = 0L;

   CALLBACK_PROLOGUE;
   form = FrmGetActiveForm ();
   switch (e->eType) {
      case frmOpenEvent:
	 setField (dbName, currentDBName ());
	 showLog ("Initialising");
	 FrmDrawForm (form);
	 if (OpenSerialPort ()) {
	    FrmGotoForm (gpsWptListFrm);
	 }
	 handled = true;
	 break;
      case ctlSelectEvent:
         switch (e->data.ctlEnter.controlID) {
	    case gpsNokBtn:
	       if (serial_port_open) {
		  SerClose (serial_lib);
		  serial_port_open = false;
	       }
	       FrmGotoForm (gpsWptListFrm);
	       handled = true;
	       break;
	 }
	 break;
      case nilEvent:
	 SerReceiveCheck(serial_lib, &num_bytes);
	 if (num_bytes != 0L) {
//	    showLog ("Checking");
	    GetHostCommand ();
	 }
	 handled = true;
	 break;
      default:
	break;
   }
   FrmDrawForm (form);
   CALLBACK_EPILOGUE;
   return handled;
}


//
//	Get a Garmin host type command and act on it
//

void GetHostCommand (void)
{
   unsigned char buf[BUFLEN];
   int len, err;
   UInt num_wpts;

   len = BUFLEN;
   err = 0;
   if (GarminGetPacket (buf, &len, &err)) {
      if (buf[1] != 0x06 && buf[1] != 0x15) {
	 SendAck (buf[1], false);
      }
      displayPacket ("G:", buf);
      return;
   }
   if (buf[1] != 0x06 && buf[1] != 0x15) {
      SendAck (buf[1], true);
   }
   switch (buf[1]) {
      case 0x06:
      case 0x15:
	 break;
      case 0x0A:
	 switch (buf[3]) {
	    case 0x07:
	       showLog ("Send waypoints");
	       GarminSend (menuSendAll);
	       break;
	    case 0x05:
	       showLog ("Time");
	       MemSet (buf, BUFLEN, 0);
	       buf[0] = 14;
	       buf[1] = 10;
	       GarminSendPacket (buf, 12);
	       break;
	    case 0x31:
	       showLog ("PVT data");
	       MemSet (buf, BUFLEN, 0);
	       buf[0] = 51;
	       buf[1] = 63;
	       buf[18] = 1;
	       GarminSendPacket (buf, 65);
	       break;
	    case 0x02:
	       showLog ("Position");
	       break;
	    case 0x32:
	       showLog ("stop PVT");
	       break;
	    case 0x06:
	       showLog ("Send track");
	       GarminSendTrack ();
	       break;
	    case 0x04:
	       showLog ("Send routes");
	       GarminSendRaw (menuXferRouteOut);
	       break;
	    default:
	       displayPacket ("U:", buf);
	       break;
	 }
	 break;
      case 0x0C:
	 displayPacket ("EOF", buf);
	 break;
      case 0x1B:
	 showLog ("Rx waypoint/track/route");
	 num_wpts = buf[4];
	 num_wpts = num_wpts << 8;
	 num_wpts |= buf[3];
	 num_wpts &= 0x00FFFFFF;
	 GarminGetAll (HOST_WAYPOINT, num_wpts);
	 break;
      case 0xFE:
	 showLog ("GPS type");
	 buf[0] = 0xFF;
	 buf[1] = 13;
	 buf[2] = 97;
	 buf[3] = 0;
	 buf[4] = 1;
	 buf[5] = 0;
	 StrCopy (buf + 6, "Gypsy 1.4");
	 GarminSendPacket (buf, 15);
	 break;
      default:
	 displayPacket ("U:", buf);
	 break;
   }
}



//
//	Display the first few bytes of a Garmin packet
//

void displayPacket (char *msg, char *buf)
{
   char txt[256];
   char tmp[16];
   int i;

   StrCopy (txt, msg);
   StrCat (txt, " 0x");
   for (i = 1; i < 5; ++i) {
      if (i > 1) 
	 StrCat (txt, " ");
      StrIToH (tmp, buf[i]);
      StrCat (txt, tmp + 6);
   }
   showLog (txt);
}


//
//	display the last ten lines or so ,,,
//

void showLog (char *contents)
{
#define LOG 150
   FormPtr form;
   FieldPtr field;
   VoidHand handle;
   static char log[LOG + 1] = {'\0'};
   char *txt;
   int i;

   form = FrmGetActiveForm ();
   field = FrmGetObjectPtr( form, FrmGetObjectIndex( form, hostAction));
   i = (StrLen (log) + StrLen (contents) + 2) - LOG;
   if (i > 0) {
      StrCopy (log, log + i);
   }
   StrCat (log, "; ");
   StrCat (log, contents);
   handle = MemHandleNew (StrLen (log) + 1);
   txt = MemHandleLock (handle);
   StrCopy (txt, log);
   FldSetText(field, handle, 0, StrLen(log));
   MemHandleUnlock (handle);
   FldDrawField (field);
}
