/*
 * gps.c - task 4 - decode gps messages
 *
 * 1. wait for a message from sci.
 * 2. process the message, extracting selected data
 * 3. goto 1.
 *
 * see gps.h and gps_strings.h
 *
 * cat gps45xxx.output | sed 's/,.*$//' | sort | uniq
 * and looking at the strings[2..5] as long's,
 * $G PBOD --> 0x50424F44
 * $G PGGA --> 0x50474741
 * $G PGLL --> 0x50474C4C
 * $G PGSA --> 0x50475341
 * $G PGSV --> 0x50475356
 * $G PRMB --> 0x50524D42
 * $G PRMC --> 0x50524D43
 * $G PRTE --> 0x50525445
 * $G PWPL --> 0x5057504C
 * $P GRME --> 0x47524D45
 * $P GRMM --> 0x47524D4D
 * $P GRMZ --> 0x47524D5A
 *
 * These hex values may be used in a switch statment.
 *
 * task message queue 
 * typedef struct msg_t {
 *   unsigned char task;       from task 
 *   unsigned char empty;       are we done with it? 
 *   struct msg_t *next;          linked list 
 *   unsigned char buf[80];       msg body 
 * } msg_t;
 *
 * at 9600 baud, counting messages,
 *    sent   lost   unknown
 *    2552     8      87
 *    5104    12     146
 *    7656    14     242
 *
 * $Id: gps.c,v 1.2 2002/08/03 17:52:57 tomdean Exp $
 */

#include <sys/ports_def.h>
#include <os.h>
#include <gps.h>
#include <lcd.h>

unsigned char gps_stack[STACK_SIZE];
/*                                      111111111122222222223333333333 */
/*                            0123456789012345678901234567890123456789 */
unsigned char gps_row_1 [] = "lat       lon        wpt    brg   rng   ";
unsigned char gps_row_2 [41];
unsigned char gps_row_3 [] = "sog   cse   vmg     cterr  date   utc   ";
unsigned char gps_row_4 [41];

void gps() {
  register unsigned short loop_count = 0;
  unsigned long *msg_id;
  register unsigned char *ptr;
  register unsigned short idx;
  msg_t *msg;
  
  while (1) {
	hex_to_ascii_4(++loop_count, TASK4_COUNT);
	/* get a message from the queue */
	SYS_RECV_WAIT(msg);
	if (msg != NULL) {
	  ptr = msg->buf;
	  /* All GPS messages start with '$G' or '$P' */
	  if ((ptr[0] == '$') && ((ptr[1] == 'G') || (ptr[1] == 'P'))) {
		/* process the message */
		ptr+=2;
		msg_id = (unsigned long *)ptr;
		switch (*msg_id) {
		case 0x50424F44:
		  /* $GPBOD */
		  gpbod_count++;
		  parse_gpbod(ptr+5);
		  break;
		case 0x50474741:
		  /* $GPGGA */
		  gpgga_count++;
		  parse_gpgga(ptr+5);
		  break;
		case 0x50474C4C:
		  /* $GPGLL */
		  gpgll_count++;
		  parse_gpgll(ptr+5);
		  break;
		case 0x50475341:
		  /* $GPGSA */
		  gpgsa_count++;
		  parse_gpgsa(ptr+5);
		  break;
		case 0x50475356:
		  /* $GPGSV */
		  gpgsv_count++;
		  parse_gpgsv(ptr+5);
		  break;
		case 0x50524D42:
		  /* $GPRMB */
		  gprmb_count++;
		  parse_gprmb(ptr+5);
		  break;
		case 0x50524D43:
		  /* $GPRMC */
		  gprmc_count++;
		  parse_gprmc(ptr+5);
		  break;
		case 0x50525445:
		  /* $GPRTE */
		  gprte_count++;
		  parse_gprte(ptr+5);
		  break;
		case 0x5057504C:
		  /* $GPWPL */
		  gpwpl_count++;
		  parse_gpwpl(ptr+5);
		  break;
		case 0x47524D45:
		  /* $PGRME */
		  pgrme_count++;
		  parse_pgrme(ptr+5);
		  break;
		case 0x47524D4D:
		  /* $PGRMM */
		  pgrmm_count++;
		  parse_pgrmm(ptr+5);
		  break;
		case 0x47524D5A:
		  /* $PGRMZ */
		  pgrmz_count++;
		  parse_pgrmz(ptr+5);
		  break;
		default:
		  /* What to do here? */
		  ignore_count++;
		  for (idx=0; idx<5; idx++) error1[idx] = *ptr++;
		}  /* end switch */
	  } /* end if gps message */
	  /*
	   * even if this is not a GPS message, it was passed to us
	   * and we don't know what to do with it here....
	   * so, mark it empty anyway!.
	   */
	  msg->empty = 1;
	} /* end msg != NULL */
  }  /* end while 1 */
}  /* end gps() */

/*
 * gps init
 */
void gps_init() {
  register unsigned short idx;
  gpbod_count = 0; /* defined in gps.h */
  gpgga_count = 0; /* defined in gps.h */
  gpgll_count = 0; /* defined in gps.h */
  gpgsa_count = 0; /* defined in gps.h */
  gpgsv_count = 0; /* defined in gps.h */
  gprmb_count = 0; /* defined in gps.h */
  gprmc_count = 0; /* defined in gps.h */
  gprte_count = 0; /* defined in gps.h */
  gpwpl_count = 0; /* defined in gps.h */
  pgrme_count = 0; /* defined in gps.h */
  pgrmm_count = 0; /* defined in gps.h */
  pgrmz_count = 0; /* defined in gps.h */
  ignore_count = 0; /* defined in gps.h */

  for(idx=0; idx<40; idx++) {
	gps_row_2[idx] = ' ';
	gps_row_4[idx] = ' ';
  }

  return;
}

/*
 * show gps_count
 */
void show_gps_count(char *buf) {
  hex_to_ascii_2(gpbod_count,buf);
  hex_to_ascii_2(gpgga_count,buf+3);
  hex_to_ascii_2(gpgll_count,buf+6);
  hex_to_ascii_2(gpgsa_count,buf+9);
  hex_to_ascii_2(gpgsv_count,buf+12);
  hex_to_ascii_2(gprmb_count,buf+15);
  hex_to_ascii_2(gprmc_count,buf+18);
  hex_to_ascii_2(gprte_count,buf+21);
  hex_to_ascii_2(gpwpl_count,buf+24);
  hex_to_ascii_2(pgrme_count,buf+27);
  hex_to_ascii_2(pgrmm_count,buf+30);
  hex_to_ascii_2(pgrmz_count,buf+33);
  hex_to_ascii_2(ignore_count,buf+36);

  return;
}
 
/*
 * parse_gpbod - parse the gpbod record into the global gpbod_t structure
 */
void parse_gpbod(unsigned char *buf) {
gpbod_t *gpbod_ptr;
 
return;
}
 
/*
 * parse_gpgga - parse the gpgga record into the global gpgga_t structure
 */
void parse_gpgga(unsigned char *buf) {
gpgga_t *gpgga_ptr;
 
return;
}
 
/*
 * parse_gpgll - parse the gpgll record into the global gpgll_t structure
 */
void parse_gpgll(unsigned char *buf) {
gpgll_t *gpgll_ptr;
 
return;
}
 
/*
 * parse_gpgsa - parse the gpgsa record into the global gpgsa_t structure
 */
void parse_gpgsa(unsigned char *buf) {
 
return;
}
 
/*
 * parse_gpgsv - parse the gpgsv record into the global gpgsv_t structure
 */
void parse_gpgsv(unsigned char *buf) {
 
return;
}
 
/*
 * parse_gprmb - parse the gprmb record into the global gprmb_t structure
 *           111111111122222222223333333333
 * 0123456789012345678901234567890123456789
 * lat       lon        wpt    brg  rng    
 * 4827.123N 12245.432W WPTNAM 090m 004.3nm
 * sog    cse   vmg    cterr   date   utc
 * 002.4k 102^ -000.8k 3.20 L ddmmyy 031504
 *
 * field, lcd_row, offset, record, recfield
 * wpt   2 21 gprmb 5
 * brg   2 28 gprmb 11
 * rng   2 33 gprmb 10
 * vmg   4 12 gprmb 12
 * cterr 4 20 gprmb 2
 *  dir  4 25 gprmb 3
 *
 * on entry, buf points to field 1
 */
void parse_gprmb(unsigned char *buf) {
  gprmb_t *gprmb_ptr;

  DEBUG_ON(BIT05);
  SKIP_FIELD(buf); /* don't want field 1 */
  COPY_FIELD(buf, CTERR_LOC); /* cterr */
  COPY_FIELD(buf, CTERR_DIR_LOC); /* cterr dir */
  SKIP_FIELD(buf); /* don't want field 4 */
  COPY_FIELD(buf, WPT_LOC);  /* wpt */
  SKIP_FIELD(buf); /* don't want field 6 */
  SKIP_FIELD(buf); /* don't want field 7 */
  SKIP_FIELD(buf); /* don't want field 8 */
  SKIP_FIELD(buf); /* don't want field 9 */
  COPY_FIELD(buf, RNG_LOC);  /* rng */
  COPY_FIELD(buf, BRG_LOC);  /* brg */
  COPY_FIELD(buf, VMG_LOC);  /* vmg */
  DEBUG_OFF(BIT05);
 
return;
}
 
/*
 * parse_gprmc - parse the gprmc record into the global gprmc_t structure
 *
 * field, lcd_row, offset, record, recfield
 * utc   4 35 gprmc 1
 * lat   2  0 gprmc 3
 *   dir 2  8 gprmc 4
 * lon   2 10 gprmc 5
 *   dir 2 19 gprmc 6
 * sog   4  0 gprmc 7
 * cse   4  7 gprmc 8
 * date  4 27 gprmc 9
 *
 * on entry, buf points to field 1
 */
void parse_gprmc(unsigned char *buf) {
  gprmc_t *gprmc_ptr;
  
  DEBUG_ON(BIT06);
  
  COPY_FIELD(buf, UTC_LOC); /* utc */
  SKIP_FIELD(buf); /* don't want field 2 */  
  COPY_FIELD(buf, LAT_LOC); /* lat */
  COPY_FIELD(buf, LAT_DIR_LOC); /* lat dir */
  COPY_FIELD(buf, LON_LOC); /* lon */
  COPY_FIELD(buf, LON_DIR_LOC); /* lon dir */
  COPY_FIELD(buf, SOG_LOC); /* sog */
  COPY_FIELD(buf, CSE_LOC); /* cse */
  COPY_FIELD(buf, DATE_LOC); /* date */
  
  DEBUG_OFF(BIT06);
 
return;
}
 
/*
 * parse_gprte - parse the gprte record into the global gprte_t structure
 */
void parse_gprte(unsigned char *buf) {
gprte_t *gprte_ptr;
 
return;
}
 
/*
 * parse_gpwpl - parse the gpwpl record into the global gpwpl_t structure
 */
void parse_gpwpl(unsigned char *buf) {
gpwpl_t *gpwpl_ptr;
 
return;
}
 
/*
 * parse_pgrme - parse the pgrme record into the global pgrme_t structure
 */
void parse_pgrme(unsigned char *buf) {
pgrme_t *pgrme_ptr;
 
return;
}
 
/*
 * parse_pgrmm - parse the pgrmm record into the global pgrmm_t structure
 */
void parse_pgrmm(unsigned char *buf) {
 
return;
}
 
/*
 * parse_pgrmz - parse the pgrmz record into the global pgrmz_t structure
 */
void parse_pgrmz(unsigned char *buf) {
 
return;
}
