//////////////////////////////////////////////////////////////////////////////////                     PIC16F88 Delorme Tripmate GPS Logger//// Filename     : 16F88 - 24LC1025 GPS Compress DR1r7.c// Programmer   : Steven Cholewiak, www.semifluid.com// Version      : Version 1.7 - 06/15/2007// Remarks      : DR1r7 Changes the output format to be compatible with//                   Nmea2kmz (http://homepage2.nifty.com/k8/gps/file///                   nmea2kmz.htm) and semi-compatible with other programs which//                   process NMEA data.  Course Made Good and Date are disabled//                   to save space.  Note that current output format is://                   $GPRMC, (Time), A, Latitude, Lat. Direction, Longitude,//                      Long. Direction, Speed, EEPROM address//                DR1r6 includes time and speed updates//                DR1r4 is the initial release////                More information on the circuit can be found at://                http://semifluid.com/?p=43//                http://semifluid.com/?p=46//                http://semifluid.com/?p=80////////////////////////////////////////////////////////////////////////////////#include <16F88.h>#fuses INTRC_IO, MCLR, NOWDT, NOBROWNOUT, NOPROTECT, NOLVP, NODEBUG#use delay(clock=8000000)#use rs232(stream=PC, baud=4800, parity=N, bits=8, xmit=PIN_B5, rcv=PIN_B2, ERRORS)#define EEPROM_SDA   PIN_B7#define EEPROM_SCL   PIN_B6#define pinButton    PIN_A2#define pinLEDEEPROM PIN_A0#define pinLEDSTATUS PIN_A4#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)#build(reset=0x1, interrupt=0x5)#ORG 0x0F00,0x0FFF {}#include <241025multi.c>#include <STDLIB.H>struct {   int32 time;   int8  NRW;   int16 latHandM;   int16 latFractM;   int8  latDir;   int16 lonHandM;   int16 lonFractM;   int8  lonDir;   int16 speedH;   int16  speedL;   //int16 courseH;   //int16  courseL;   //int32 date;} GPRMC;int1 readData = FALSE;int1 saveData = TRUE;int1 dataOK = FALSE;int32 eeAddress =0;int8 theChar = 0;#define BUFFER_SIZE 44int8 buffer[BUFFER_SIZE];int8 next_in = 0;int8 next_out = 0;#INT_RDAvoid serial_isr() {                                                              // Serial Interrupt   int8 t;   buffer[next_in]=getc();   t=next_in;   next_in=(next_in+1) % BUFFER_SIZE;   if(next_in==next_out)     next_in=t;           // Buffer full !!}#define bkbhit (next_in!=next_out)int8 bgetc() {   int8 c;   WHILE(!bkbhit) ;   c=buffer[next_out];   next_out=(next_out+1) % BUFFER_SIZE;   return(c);}int32 bRead(int8 theEndChar, int8 theSize) {   int8 tempChar = 0;   int8 tempString[10];   int8 tPointer = 0;   tPointer = 0;                                                                 // Set string pointer to 0   tempChar = bgetc();                                                           // Get first character   WHILE (tempChar != theEndChar) {                                              // Loop until we reach the terminator character      tempString[tPointer] = tempChar; tPointer++;      tempChar = bgetc();   }   tempString[tPointer] = 0;                                                     // Add a null to the end of the string   if (theSize == 8) return atoi(tempString);                                   // Return an int16   else if (theSize == 16) return atol(tempString);                                   // Return an int16   else if (theSize == 32) return atoi32(tempString);                            // Return an int32}void getGPRMCdata() {   theChar = bgetc();                                                            // Discard ','   GPRMC.time = bRead(',', 32);                                                  // Save Time   GPRMC.NRW = bgetc();                                                          // Save Navigation Receiver Warning   theChar = bgetc();                                                            // Discard ','   GPRMC.latHandM = bRead('.', 16);                                              // Save Latitude Hours and Minutes   GPRMC.latFractM = bRead(',', 16);                                             // Save Latitude Fractional Minutes   GPRMC.latDir = bgetc();                                                       // Save Latitude North/South   theChar = bgetc();                                                            // Discard ','   GPRMC.lonHandM = bRead('.', 16);                                              // Save Longitude Hours and Minutes   GPRMC.lonFractM = bRead(',', 16);                                             // Save Longitude Fractional Minutes   GPRMC.lonDir = bgetc();                                                       // Save Longitude East/West   theChar = bgetc();                                                            // Discard ','   GPRMC.speedH = bRead('.', 16);                                                // Save Speed (whole units)   GPRMC.speedL = bRead(',', 16);                                                // Save Speed (fractional units)   //GPRMC.courseH = bRead('.', 16);                                               // Save Course Made Good (whole units)   //GPRMC.courseL = bRead(',', 16);                                               // Save Course Made Good (fractional units)   //GPRMC.date = bRead(',', 32);                                                  // Save Date}void sendDataToSerial() {   fprintf(PC,"$GPRMC,");   fprintf(PC,"%06Lu,", GPRMC.time);   fprintf(PC,"A,");   fprintf(PC,"%05Lu.%04Lu,%C,", GPRMC.latHandM, GPRMC.latFractM, GPRMC.latDir);   fprintf(PC,"%05Lu.%04Lu,%C,", GPRMC.lonHandM, GPRMC.lonFractM, GPRMC.lonDir);   fprintf(PC,"%03Lu.%03Lu,%Lu\r\n", GPRMC.speedH, GPRMC.speedL,eeAddress);}void readGPRMCdata() {   GPRMC.time = Make32(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1),read_ext_eeprom(0,eeAddress+2),read_ext_eeprom(0,eeAddress+3)); eeAddress++; eeAddress++; eeAddress++; eeAddress++;   GPRMC.latHandM = Make16(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1)); eeAddress++; eeAddress++;   GPRMC.latFractM = Make16(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1)); eeAddress++; eeAddress++;   GPRMC.latDir = read_ext_eeprom(0,eeAddress); eeAddress++;   GPRMC.lonHandM = Make16(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1)); eeAddress++; eeAddress++;   GPRMC.lonFractM = Make16(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1)); eeAddress++; eeAddress++;   GPRMC.lonDir = read_ext_eeprom(0,eeAddress); eeAddress++;   GPRMC.speedH = Make16(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1)); eeAddress++; eeAddress++;   GPRMC.speedL = Make16(read_ext_eeprom(0,eeAddress),read_ext_eeprom(0,eeAddress+1)); eeAddress++; eeAddress++;}void writeGPRMCdata() {   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.time,3)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.time,2)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.time,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.time,0)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.latHandM,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.latHandM,0)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.latFractM,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.latFractM,0)); eeAddress++;   write_ext_eeprom(0,eeAddress,GPRMC.latDir); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.lonHandM,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.lonHandM,0)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.lonFractM,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.lonFractM,0)); eeAddress++;   write_ext_eeprom(0,eeAddress,GPRMC.lonDir); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.speedH,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.speedH,0)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.speedL,1)); eeAddress++;   write_ext_eeprom(0,eeAddress,MAKE8(GPRMC.speedL,0)); eeAddress++;}void main() {   SETUP_OSCILLATOR(OSC_8MHZ);   SETUP_ADC_PORTS(NO_ANALOGS);   SETUP_ADC(ADC_OFF);   SETUP_COMPARATOR(NC_NC_NC_NC);   SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_1);   SETUP_TIMER_1(T1_DISABLED);   SETUP_TIMER_2(T2_DISABLED,0,1);   ENABLE_INTERRUPTS(GLOBAL);   ENABLE_INTERRUPTS(INT_RDA);   OUTPUT_HIGH(pinLEDSTATUS);   init_ext_eeprom();   DELAY_MS(50);   IF (INPUT(pinButton)) readData = TRUE;   ELSE readData = FALSE;   DELAY_MS(250);   IF (!readData) {      WHILE (!INPUT(pinButton));                                                 // Wait until button it pressed to start      OUTPUT_LOW(pinLEDSTATUS);      eeAddress = 0;      WHILE (eeAddress<EEPROM_SIZE) {         dataOK = FALSE;         WHILE (bgetc() != '$');                                                 // Look for a '$' - the start of a NMEA sentence         IF (bgetc() == 'G') {            IF (bgetc() == 'P') {               IF (bgetc() == 'R') {                  IF (bgetc() == 'M') {                     IF (bgetc() == 'C') {                        OUTPUT_HIGH(pinLEDSTATUS);                        getGPRMCdata();                        OUTPUT_LOW(pinLEDSTATUS);                        IF (GPRMC.NRW == 'A') dataOK = TRUE;                     // Check to see if data is valid                     }                  }               }            }         }         IF ((saveData) && (dataOK)) {            OUTPUT_HIGH(pinLEDEEPROM);            writeGPRMCdata();            OUTPUT_LOW(pinLEDEEPROM);         }      }   }   ELSE {      set_uart_speed(38400,PC);            OUTPUT_LOW(pinLEDSTATUS);      eeAddress = 0;      WHILE (eeAddress<EEPROM_SIZE) {         OUTPUT_TOGGLE(pinLEDEEPROM);         readGPRMCdata();         sendDataToSerial();      }      OUTPUT_LOW(pinLEDEEPROM);   }   WHILE (TRUE) {      OUTPUT_TOGGLE(pinLEDSTATUS);      delay_ms(250);   }}
