• Pic® Basic


  • GPS code example

    Original Post by Ryan 'ohararp'

    If you can make sense of it here is the firmware for the FAT16 version of the datalogger I sell.


    Code:
    '$GPGGA,170834,4124.8963,N,08151.6838,W,1,05,1.5,280.2,M,-34.0,M,,,*75
    '$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
    'This design is meant for GPS_LOGGER_F_D No Battery Check
        Device = 18F2620
        XTAL = 8
        Declare PLL_REQ = True
        OSCCON  = %01110000         'Internal 8 MHz clock select
        OSCTUNE.6 = 1 ' Frequency Multiplier PLL for INTOSC Enable bit
         ALL_DIGITAL = True 
        Declare WATCHDOG = True
        FLOAT_DISPLAY_TYPE = LARGE
    ' Device Fuse configuration
        CONFIG_START
            OSC     = INTIO67   ; Internal Oscillator
            FCMEN    = OFF        ; Failsafe Clock Monitor Disabled
            IESO    = OFF        ; Int/Ext Oscillator Switch Over Disabled
            PWRT    = OFF        ; Power Up Timer Disabled
            BOREN    = OFF        ; Brownout Reset Disabled
            WDT     = OFF        ; Watchdog Timer Disabled
            MCLRE    = OFF        ; MCLR Disabled
            WDTPS   = 256       ; 15000 x 4mS  = 60 seconds
            LVP     = OFF       ' Low_Voltage Programming
            PBADEN  = OFF       ; PORTB Digital                
        CONFIG_END     
    
    'GPS Varibles    
        Dim LAT            As Float
        Dim SIGN_LAT       As Float
        Dim LON            As Float
        Dim SIGN_LONG      As Float
        Dim FIX            As Byte
        Dim SAT            As Byte 
        Dim ALT            As Float
        
        Dim SPD            As Float
        Dim HDG            As Float
    
        Dim IDX_GP         As Byte 'GP Sentence IDX
        Dim IDX_INT        As Word 'Inteval IDX
        Dim IDX_B          As Byte 'Baud IDX
        Dim IDX_SAVE       As Byte
        Dim GPGSV_TOT      As Byte
    
    'Position of Dilution Precision Variables    
        Dim PDOP           As Float
        Dim HDOP           As Float
        Dim VDOP           As Float        
     '*******************************************************************************
    'Test LED Setup 
        Dim BLINKS         As Byte
        Dim NUM_BLINKS     As Byte
    '*******************************************************************************
    'Extract the Value Variables
           Dim GPS_BLOOP      As Byte                             ' \
        Dim GPS_EXTRACT_ITEM As Byte                     '  \
        Dim GPS_COMMA_COUNT  As Byte                     '    General purpose variables
        Dim GPS_CHARPOS    As Byte                         '  /
        Dim GPS_CHAR       As Byte                             ' /
    '*******************************************************************************
    'GPS_PARSE Variables        
        Dim GPS_DATA_STRING[20] As Byte                        ' Temp buffer
        Symbol GPS_RXBUFFER_LENGTH = 100
        Dim GPS_RXBUFF[GPS_RXBUFFER_LENGTH] As Byte        ' Serial buffer for NMEA sentences
        Dim GPVTG_STR[GPS_RXBUFFER_LENGTH]  As Byte
        Dim GPRMC_STR[GPS_RXBUFFER_LENGTH]  As Byte
        Dim GPGSV_STR[GPS_RXBUFFER_LENGTH]  As Byte
        Dim GPGSV_STR1[GPS_RXBUFFER_LENGTH] As Byte
        Dim GPGSV_STR2[GPS_RXBUFFER_LENGTH] As Byte
        Dim GPGSV_STR3[GPS_RXBUFFER_LENGTH] As Byte
        Dim GPGSA_STR[GPS_RXBUFFER_LENGTH]  As Byte
        Dim GPGLL_STR[GPS_RXBUFFER_LENGTH]  As Byte
        Dim GPGGA_STR[GPS_RXBUFFER_LENGTH]  As Byte  
    '*******************************************************************************
    'String to Float Variables
        Dim N               As Byte
        Dim STF_STRING_IN[20] As Byte 'String to Float Variables
        Dim STF_POWER_10    As Float
        Dim STF_RESULT      As Float
        Dim STF_SIGN        As Byte
        Dim STF_CHAR        As Byte
        Dim STF_CHARPOS     As Byte
        Dim STF_TEMP        As Float
        Dim TEST_CHAR       As Byte     
        Dim TEST_CHAR_IDX   As Byte        
    '*******************************************************************************
    'String to Float Variables
        Dim DDMM_STRING_IN[20] As Byte 'String to Float Variables
        Dim DDMM_POWER_10    As Float
        Dim DDMM_RESULT      As Float
        Dim DDMM_SIGN        As Byte
        Dim DDMM_CHAR        As Byte
        Dim DDMM_CHARPOS     As Byte
        Dim DDMM_CHARPOS_LOW As Byte
        Dim DDMM_TEMP        As Float
        Dim DDMM_TEMP_STR[6] As Byte        
    '*******************************************************************************
    'Config File Variables
        Dim CONFIG_BUFF[50] As Byte
        Dim CONFIG_VALUE    As Word
        Dim CONFIG_IDX      As Byte
    
        Dim INTERVAL_INIT   As Word
        INTERVAL_INIT = 0
        Dim X               As Word       
        Dim INTERVAL        As Word
        Dim INTERVAL_SD     As Word
        Dim INTERVAL_EPROM  As Word
    
        Dim MODE_INIT       As Byte
        MODE_INIT = %11111111
        Dim MODE            As Byte    
        Dim MODE_SD         As Byte
        Dim MODE_EPROM      As Byte
        
        Dim FIXED_INIT      As Byte
        FIXED_INIT = 0
        Dim FIXED           As Byte    
        Dim FIXED_SD        As Byte
        Dim FIXED_EPROM     As Byte    
    '*******************************************************************************
    'SD VARIABLES
        Dim Response As Byte   'SD Card Response
        Dim IDX_FL   As Byte   'Filename Index
        Dim SAMPLES  As Byte   '# of Samples to take before writing file
        Dim WRITE_MODE As Byte '0 = NMEA & 1 = KML
        Symbol LED  = PORTB.2
    '*******************************************************************************
    'SD PIN DECLARES
        Symbol SD_CS  = PORTC.0                         'SPI CS to SD CS (SD pin 1)
        Symbol SD_DI  = PORTC.5                         'SPI DO to SD DI (SD Pin 2)
        Symbol SD_CLK = PORTC.3                        'SPI CLK to SD CLK (SD Pin 5)
        Symbol SD_DO  = PORTC.4                         'SPI DI to SD DO (SD Pin 7)
    '*******************************************************************************
        Include "RY_GPS_PARSEI_EB85_LIB.PBP"                'Include managed library file
    '*******************************************************************************        
    'HSERIAL = 38400 BAUD 
    RCSTA = $90 ' Enable serial port & continuous receive
    TXSTA = $20 ' Enable transmit, BRGH = 0
    SPBRG = 12  ' 38400 Baud @ 0.16%
    '*******************************************************************************
    'TURN MOSFET SWITCH ON
        Low PORTB.1
    '*******************************************************************************
    'SETUP ADC
        TRISA.0=1 ' Configure as Input
        TRISA.1=1 ' Configure as Input
        ADCON2.7 = 1
        Dim BATTERY     As Word
        Dim BATTERY_ON  As Byte
        Dim VOLTSB      As Float
    
        Dim VOLTST      As Float    
        Dim COUNTS      As Word
        Dim TEMPC       As Float
        Dim TEMPF       As Float
    '*******************************************************************************
    'BUBBLE SORT VARIABLES
        Symbol SAMPLES_TO_TAKE = 5                ' The amount of samples to take
        Dim SWAPTMP As Word                        ' Temporary variable for swapping
        Dim INDEX As Byte                        ' Holds the position in the sort     
        Dim SWAP_OCCURED As Byte                ' Indicates if the sort is complete
        Dim SAMPLE[SAMPLES_TO_TAKE + 1] As Word ' Create an array to hold the samples
    '*******************************************************************************           
    'RESTART PIC VALUES
        Dim emaN_eliF_DS[8] As Byte
        Dim txE_eliF_DS[8]  As Byte
    '*******************************************************************************           
    'Get Date and Time From GPS
    INIT:
        NUM_BLINKS = 1 :GoSub LED_TEST
        GoSub INIT_SD_CARD    
        NUM_BLINKS = 2 :GoSub LED_TEST    
        GoSub READ_CONFIG_FILE    
        NUM_BLINKS = 3 :GoSub LED_TEST    
        GoSub GPRMC_EXTRACT
        NUM_BLINKS = 4 :GoSub LED_TEST    
        GoSub INIT_SD_CREATE
        NUM_BLINKS = 5 :GoSub LED_TEST    
    '*******************************************************************************
    MAIN:
        GoSub BATTERY_CHECK
        GoSub BATTERY_LEVEL
        GoSub TEMPERATURE_LEVEL
    
        If MODE.7 = 0 Then
            GoSub NMEA_EXTRACT
            GoSub BATTERY_CHECK
            GoSub NMEA_WRITE
        ElseIf MODE.7 = 1 Then
            'Extract NMEA Sentences
            If MODE.4 = 1 Or MODE.3 = 1 Or MODE.0 = 1 Then GoSub GPRMC_EXTRACT
            If MODE.6 = 1 Or MODE.5 = 1 Or MODE.2 = 1 Then GoSub GPGGA_EXTRACT
            If MODE.2 = 1 Then GoSub GPGSA_EXTRACT
            'Process NMEA Data
            If MODE.4 = 1 Or MODE.3 = 1 Or MODE.0 = 1 Then GoSub GPRMC_PROCESS
            If MODE.6 = 1 Or MODE.5 = 1 Or MODE.2 = 1 Then GoSub GPGGA_PROCESS
            If MODE.2 = 1 Then GoSub GPGSA_PROCESS
            GoSub BATTERY_CHECK
            GoSub KML_WRITE
        EndIf
            
        If BATTERY < 1000 Then GoSub LOW_BAT_BLINK 
        If INTERVAL > 0 Then GoSub PIC_SLEEP       
    GoTo MAIN
    '*******************************************************************************
    PIC_SLEEP:
        If INTERVAL > 29 Then GoSub GPS_SLEEP
            X = INTERVAL
            WDTCON=1  ; software enable WDT
            Repeat
                @Sleep ; sleep 256 x 4mS per loop
                nop
                Dec X
            Until X = 0
            WDTCON=0  ; software disable WDT 
        If INTERVAL > 29 Then GoSub GPS_WAKE
    Return
    '*******************************************************************************
    GPS_SLEEP:
        High PORTB.1 'Turn off power to GPS and SD Card
    Return
    '*******************************************************************************
    GPS_WAKE:
        Low PORTB.1                     'Turn on GPS and SD Card
        DelayMS 1000
        GoSub INIT_SD_CARD              'Init SD Card
        DelayMS 10 
        SD_File_Name = Str emaN_eliF_DS 'Reload Filename
        SD_File_Ext = Str txE_eliF_DS   'Reload File Extension
        Response = SD_Append_File       'Reopen file for Appending
        DelayMS 10 
        Response = SD_Save_File
        Clear X 
        Repeat                          'Wait till GPS gets a fix again
            GoSub GPGGA_EXTRACT
            GoSub GPGGA_PROCESS
            If FIX = 0 Then GoSub NO_FIX_BLINK
            Inc X    
        Until FIX > 0 Or X > 99
    Return
    '*******************************************************************************
    BATTERY_CHECK:
        ADCON1 = %00001111 'Set PORTA Digital
        BATTERY_ON = PORTA.0
        If BATTERY_ON = 0 Then GoTo BATTERY_CHECK 'Loop Until SCAP1 Dies!    
    Return
    '*******************************************************************************
    BATTERY_LEVEL:
        ADCON1 = %00001101 'Set PORTA.0 &.1 Analog
        For N = 0 To SAMPLES_TO_TAKE
            SAMPLE[N] = ADIn 0
            DelayMS 10 
        Next
        GoSub BUBBLE_SORT
        BATTERY = SAMPLE[2]
        VOLTSB = BATTERY / 1024 * 3.3                                                                                                                                                    
    Return
    '*******************************************************************************
    TEMPERATURE_LEVEL:
        ADCON1 = %00001101 'Set PORTA.0 &.1 Analog
        For N = 0 To SAMPLES_TO_TAKE
            SAMPLE[N] = ADIn 1
            DelayMS 10 
        Next
        GoSub BUBBLE_SORT
        COUNTS = SAMPLE[2]
        VOLTST = COUNTS / 1024 * 3.3
        TEMPC = (VOLTST - .424) /.00625
        TEMPF = TEMPC * 9 /5
        TEMPF = TEMPF + 32
    Return
    '*******************************************************************************
    BUBBLE_SORT: 
        Repeat
            SWAP_OCCURED = 0                                ' Clear flag that indicates swap.                                 
            INDEX = 0
            Repeat                                            ' For each cell of the array...
                If SAMPLE[INDEX] > SAMPLE[INDEX + 1] Then      ' Move larger values up. 
                    SWAPTMP = SAMPLE[INDEX]                    ' ..by swapping them. 
                    SAMPLE[INDEX] = SAMPLE[INDEX + 1]
                    SAMPLE[INDEX + 1] = SWAPTMP
                    SWAP_OCCURED = 1                        ' Set bit if swap occurred.  
                EndIf
                Inc INDEX
            Until INDEX = SAMPLES_TO_TAKE                    ' Check next cell of the array. 
        Until SWAP_OCCURED = 0                                ' Keep sorting until no more swaps. 
        Return
    '*******************************************************************************    
    INIT_SD_CARD:
        DelayMS 250                   
        Response = 0 
        Repeat
            Low LED
            'Response = SD_Init_FS_MSSP SD_SPI_FOSC_64
            Response = SD_Init_FS
            High LED
            DelayMS 150
        Until Response = 0
    Return        
    '*******************************************************************************    
    READ_CONFIG_FILE:
        DelayMS 100
            SD_File_Name = "CONFIG"
            SD_File_Ext  = "CSV"
            Response = SD_Check_For_File
        
        'READ_CONFIG_STRING
        If Response = 0 Then '0 - File Present 1 - File Not Present
            Response = SD_Open_File
            
            'Get Spec'd Sampling Interval
            GoSub READ_CONFIG_VALUE
            INTERVAL_SD = Val (CONFIG_BUFF,Dec)            
    
            'Get Spec'd NMEA/KML Mode        
            GoSub READ_CONFIG_VALUE
            MODE_SD = Val (CONFIG_BUFF,BIN)            
            
            'Get FIXED/NOT FIXED Recording Option
            GoSub READ_CONFIG_VALUE
            FIXED_SD = Val (CONFIG_BUFF,Dec)            
            
            'Read EPROM Values
            GoSub READ_CONFIG_EPROM
            
            'Compare SD and EPROM Values
            Select INTERVAL_SD
                Case 0 To 65535
                    If INTERVAL_SD <> INTERVAL_EPROM  Then
                        INTERVAL = INTERVAL_SD
                    Else 
                        INTERVAL = INTERVAL_EPROM
                    EndIf
                Case Else
                        INTERVAL = INTERVAL_EPROM
            EndSelect
            
            'Compare SD and EPROM Values            
            Select MODE_SD
                Case 0 To 255
                    If MODE_SD <> MODE_EPROM  Then
                        MODE = MODE_SD
                    Else 
                        MODE = MODE_EPROM
                    EndIf                    
                Case Else
                    MODE = MODE_EPROM
            EndSelect
            
            'Compare SD and EPROM Values            
            Select FIXED_SD
                Case 0 To 1
                    If FIXED_SD <> FIXED_EPROM  Then
                        FIXED = FIXED_SD
                    Else 
                        FIXED = FIXED_EPROM
                    EndIf                    
                Case Else
                    FIXED = FIXED_EPROM
            EndSelect                    
        ElseIf Response = 1 Then 'File Not Present
            'Read Values from EPROM and Process
            GoSub READ_CONFIG_EPROM
            INTERVAL = INTERVAL_EPROM
            MODE     = MODE_EPROM
            FIXED    = FIXED_EPROM
            GoSub WRITE_CONFIG_FILE
        EndIf
        GoSub WRITE_CONFIG_EPROM    
    Return
    '*******************************************************************************
    INIT_SD_CREATE:
        GoSub INIT_SD_CHECK_WRITE
        GoSub INIT_SD_HEADER
    Return
    '*******************************************************************************        
    INIT_SD_CHECK_WRITE:
    DelayMS 100
        Clear IDX_FL
        Repeat 
            Select IDX_FL
                Case < 10
                    SD_File_Name = "GPSXX00" + Str$ (Dec IDX_FL)        'File Name, upper case only!
                Case < 100
                    SD_File_Name = "GPSXX0" + Str$ (Dec IDX_FL)        'File Name, upper case only!
                Case < 255    
                    SD_File_Name = "GPSXX" + Str$ (Dec IDX_FL)        'File Name, upper case only!
            EndSelect
            SD_File_Ext = "CSV"                             'File Ext, upper case only!  
            Response = SD_Check_For_File                    'Check if file already exists
            Inc IDX_FL
        Until Response = 1
        Str emaN_eliF_DS = Str SD_File_Name 'Save Filename for Restarting SD Card
        Str txE_eliF_DS = Str SD_File_Ext   'Save Ext      for Restarting SD Card
        Response = SD_New_File
        Response = SD_Save_File
    Return
    '*******************************************************************************        
    INIT_SD_HEADER:
        DelayMS 100
        If MODE.7 = 0 Then
            'DO NOT WRITE HEADER DATA IN NMEA MODE
        ElseIf MODE.7 = 1 Then
            If MODE.6 = 1 Then SD_IO_String = "LATITUDE,LONGITUDE"
            If MODE.5 = 1 Then SD_IO_String = SD_IO_String + ",ALTITUDE"
            If MODE.4 = 1 Then SD_IO_String = SD_IO_String + ",HEADING"
            If MODE.3 = 1 Then SD_IO_String = SD_IO_String + ",SPEED"
            If MODE.2 = 1 Then SD_IO_String = SD_IO_String + ",SATELLITES" + ",PDOP" + ",HDOP" + ",VDOP"
            If MODE.1 = 1 Then SD_IO_String = SD_IO_String + ",FIX"                                                                
            If MODE.0 = 1 Then SD_IO_String = SD_IO_String + ",UTC TIME" + ",UTC DATE"               
            'SD_IO_String = SD_IO_String + ",COUNTS" + ",VOLTS" 
            'SD_IO_String = SD_IO_String + ",COUNTS" + ",TEMPC" + ",TEMPF"
            'SD_IO_String = SD_IO_String + ",TEMPC" + ",TEMPF"
            SD_IO_String = SD_IO_String + 13 + 10
            SD_Write_String_To_File
        EndIf
        Response = SD_Save_File
    Return
    '*******************************************************************************        
    NMEA_EXTRACT:
        If MODE.0 = 1 Then 
            HSerIn[Wait("$GPRMC")]
            GoSub RECEIVE_GP_SENTENCE
            StrN GPRMC_STR = Str GPS_RXBUFF    
        EndIf
    
        If MODE.1 = 1 Then 
            'Capture First GPGSV String
                HSerIn [Wait("$GPGSV")]
                GoSub RECEIVE_GP_SENTENCE
                StrN GPGSV_STR = Str GPS_RXBUFF
            'Determine How Many Strings Present?
                GPS_EXTRACT_ITEM = 1        
                GoSub EXTRACT_THE_VALUE
                GPGSV_TOT = Val(GPS_DATA_STRING,Dec)
            'Capture all the GPGSV sentences
             Select GPGSV_TOT
                Case 1 
                    HSerIn [Wait("$GPGSV,1,1")] 
                    GoSub RECEIVE_GP_SENTENCE
                    StrN GPGSV_STR1 = Str GPS_RXBUFF
                Case 2 
                    HSerIn [Wait("$GPGSV,2,1")] 
                    GoSub RECEIVE_GP_SENTENCE
                    StrN GPGSV_STR1 = Str GPS_RXBUFF
                    
                    HSerIn [Wait("$GPGSV,2,2")] 
                    GoSub RECEIVE_GP_SENTENCE
                    StrN GPGSV_STR2 = Str GPS_RXBUFF            
                Case 3 
                    HSerIn [Wait("$GPGSV,3,1")] 
                    GoSub RECEIVE_GP_SENTENCE
                    StrN GPGSV_STR1 = Str GPS_RXBUFF
                    
                    HSerIn [Wait("$GPGSV,3,2")] 
                    GoSub RECEIVE_GP_SENTENCE
                    StrN GPGSV_STR2 = Str GPS_RXBUFF
    
                    HSerIn [Wait("$GPGSV,3,3")] 
                    GoSub RECEIVE_GP_SENTENCE
                    StrN GPGSV_STR3 = Str GPS_RXBUFF                
             EndSelect    
        EndIf
                
        If MODE.2 = 1 Then 
            HSerIn [Wait("$GPGSA")]
            GoSub RECEIVE_GP_SENTENCE
            StrN GPGSA_STR = Str GPS_RXBUFF                
        EndIf
        
        If MODE.3 = 1 Then 
            HSerIn [Wait("$GPGGA")] 
            GoSub RECEIVE_GP_SENTENCE
            StrN GPGGA_STR = Str GPS_RXBUFF                
        EndIf     
    Return
    '*******************************************************************************        
    RECEIVE_GP_SENTENCE:
        Clear GPS_CHARPOS
        Clear GPS_RXBUFF
        Repeat                                      ' Create a loop to receive the serial string
            HSerIn [GPS_CHAR]                     ' Receive a character serially
            If GPS_CHAR = 13 Then Break              ' Exit the loop if the string reaches the end
            GPS_RXBUFF[GPS_CHARPOS] = GPS_CHAR      ' Convert ASCII to INT and load array GPS_RXBUFF
             Inc GPS_CHARPOS
        Until GPS_CHARPOS > GPS_RXBUFFER_LENGTH      ' Repeat the loop until the buffer runs out
    Return
    '*******************************************************************************        
    NMEA_WRITE:
        If MODE <> 0 Then
            High LED   
            If MODE.0 = 1 Then 
                SD_IO_String = "$GPRMC" + Str GPRMC_STR + 13 + 10
                Response = SD_Write_String_To_File    
            EndIf
    
            If MODE.1 = 1 Then 
                Select GPGSV_TOT
                    Case 1 
                        SD_IO_String = "$GPGSV,1,1" + Str GPGSV_STR + 13 + 10
                        Response = SD_Write_String_To_File
                    Case 2
                        SD_IO_String = "$GPGSV,2,1" + Str GPGSV_STR1 + 13 + 10
                        Response = SD_Write_String_To_File
                        SD_IO_String = "$GPGSV,2,2" + Str GPGSV_STR2 + 13 + 10
                        Response = SD_Write_String_To_File
                    Case 3
                        SD_IO_String = "$GPGSV,3,1" + Str GPGSV_STR1 + 13 + 10
                        Response = SD_Write_String_To_File
                        SD_IO_String = "$GPGSV,3,2" + Str GPGSV_STR2 + 13 + 10
                        Response = SD_Write_String_To_File
                        SD_IO_String = "$GPGSV,3,3" + Str GPGSV_STR3 + 13 + 10
                        Response = SD_Write_String_To_File
                EndSelect
            EndIf
            
            If MODE.2 = 1 Then 
                SD_IO_String = "$GPGSA" + Str GPGSA_STR + 13 + 10
                Response = SD_Write_String_To_File
            EndIf                 
    
            If MODE.3 = 1 Then 
                SD_IO_String = "$GPGGA" + Str GPGGA_STR + 13 + 10
                Response = SD_Write_String_To_File
            EndIf
            Inc IDX_SAVE
            If IDX_SAVE = 255 Then 
                Response = SD_Save_File
                IDX_SAVE = 0
            EndIf
            Low LED
        EndIf      
    Return                                  
    '*******************************************************************************        
    GPGGA_EXTRACT:
        Clear GPS_RXBUFF
        HSerIn [Wait("$GPGGA")]
        GPS_CHARPOS = 0
        
        Repeat                                        ' Create a loop to receive the serial string
            HSerIn [GPS_CHAR]                       ' Receive a character serially
            If GPS_CHAR = 13 Then Break                ' Exit the loop if the string reaches the end
            GPGGA_STR[GPS_CHARPOS] = GPS_CHAR        ' Convert ASCII to INT and load array GPS_RXBUFF
             Inc GPS_CHARPOS
        Until GPS_CHARPOS > GPS_RXBUFFER_LENGTH        ' Repeat the loop until the buffer runs out
    Return
    '*******************************************************************************
    GPGGA_PROCESS:
        Str GPS_RXBUFF = Str GPGGA_STR
        If MODE.7 = 1 Then
            'GET LAT
                GPS_EXTRACT_ITEM = 2             
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING        
                GoSub STRING_TO_FLOAT
                   LAT = STF_RESULT / 100            
                   StrN DDMM_STRING_IN = Str$(DEC6 LAT)
                   GoSub DDMM_TO_FLOAT
                   LAT = DDMM_RESULT
            'GET LAT SIGN
                GPS_EXTRACT_ITEM = 3 
                GoSub EXTRACT_THE_VALUE        
                If GPS_DATA_STRING[0] = "N" Then SIGN_LAT = 1
                If GPS_DATA_STRING[0] = "S" Then SIGN_LAT = -1
                LAT = LAT * SIGN_LAT
            'GET LON
                GPS_EXTRACT_ITEM = 4        
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING             
                GoSub STRING_TO_FLOAT
                LON = STF_RESULT / 100        
                StrN DDMM_STRING_IN = Str$(DEC6 LON)
                   GoSub DDMM_TO_FLOAT
                   LON = DDMM_RESULT
            'GET LON SIGN
                GPS_EXTRACT_ITEM = 5        
                GoSub EXTRACT_THE_VALUE
                If GPS_DATA_STRING[0] = "W" Then SIGN_LONG = -1
                If GPS_DATA_STRING[0] = "E" Then SIGN_LONG = 1
                LON = LON * SIGN_LONG
        EndIf
        
            'GET FIX - Always Get Fix
                GPS_EXTRACT_ITEM = 6        
                GoSub EXTRACT_THE_VALUE
                FIX = Val(GPS_DATA_STRING,Dec)
                
        If MODE.2 = 1 Then
            'GET SAT
                GPS_EXTRACT_ITEM = 7        
                GoSub EXTRACT_THE_VALUE             
                SAT = Val(GPS_DATA_STRING,Dec)
        EndIf
                
        If MODE.5 = 1 Then    
            'GET ALT
                GPS_EXTRACT_ITEM = 9        
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING             
                GoSub STRING_TO_FLOAT
                ALT = STF_RESULT
        EndIf
    Return        
    '*******************************************************************************
    GPRMC_EXTRACT:
        Clear GPS_RXBUFF
        HSerIn [Wait("$GPRMC")] 
        GPS_CHARPOS = 0
        
        Repeat                                        ' Create a loop to receive the serial string
            HSerIn [GPS_CHAR]
            If GPS_CHAR = 13 Then Break                ' Exit the loop if the string reaches the end
            GPRMC_STR[GPS_CHARPOS] = GPS_CHAR        ' Convert ASCII to INT and load array GPS_RXBUFF
             Inc GPS_CHARPOS
        Until GPS_CHARPOS > GPS_RXBUFFER_LENGTH        ' Repeat the loop until the buffer runs out
    Return
    '*******************************************************************************
    GPRMC_PROCESS:
        Str GPS_RXBUFF = Str GPRMC_STR            
        If MODE.0 = 1 Then
            'GET TIME
                GPS_EXTRACT_ITEM = 1             
                GoSub EXTRACT_THE_VALUE            
                SD_Hours    = (GPS_DATA_STRING[0] - 48) * 10
                SD_Hours    = (GPS_DATA_STRING[1] - 48) + SD_Hours
                SD_Minutes  = (GPS_DATA_STRING[2] - 48) * 10
                SD_Minutes  = (GPS_DATA_STRING[3] - 48) + SD_Minutes
                SD_Seconds  = (GPS_DATA_STRING[4] - 48) * 10
                SD_Seconds  = (GPS_DATA_STRING[5] - 48) + SD_Seconds                
                SD_MSeconds = (GPS_DATA_STRING[6] - 48) * 10
                SD_MSeconds = (GPS_DATA_STRING[7] - 48) + SD_MSeconds                
            'GET DATE
                GPS_EXTRACT_ITEM = 9             
                GoSub EXTRACT_THE_VALUE            
                SD_Day   = (GPS_DATA_STRING[0] - 48) * 10
                SD_Day   = (GPS_DATA_STRING[1] - 48) + SD_Day
                SD_Month = (GPS_DATA_STRING[2] - 48) * 10
                SD_Month = (GPS_DATA_STRING[3] - 48) + SD_Month
                SD_Year  = (GPS_DATA_STRING[4] - 48) * 10
                SD_Year  = (GPS_DATA_STRING[5] - 48) + SD_Year
        EndIf
        
        If MODE.3 = 1 Then         
            'GET SPD
                GPS_EXTRACT_ITEM = 7        
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING
                GoSub STRING_TO_FLOAT
                SPD = STF_RESULT * 1.150779448 'KNOTS -> MPH
        EndIf
        
        If MODE.4 = 1 Then        
            'GET HDG
                GPS_EXTRACT_ITEM = 8
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING        
                GoSub STRING_TO_FLOAT
                HDG = STF_RESULT
        EndIf        
    Return        
    '*******************************************************************************
    GPGSA_EXTRACT:
        Clear GPS_RXBUFF
        HSerIn [Wait("$GPGSA")] 
        GPS_CHARPOS = 0
        
        Repeat                                        ' Create a loop to receive the serial string
            HSerIn [GPS_CHAR]
            If GPS_CHAR = 13 Then Break                ' Exit the loop if the string reaches the end
            GPGSA_STR[GPS_CHARPOS] = GPS_CHAR        ' Convert ASCII to INT and load array GPS_RXBUFF
             Inc GPS_CHARPOS
        Until GPS_CHARPOS > GPS_RXBUFFER_LENGTH        ' Repeat the loop until the buffer runs out
    Return
    '*******************************************************************************
    GPGSA_PROCESS:
        Str GPS_RXBUFF = Str GPGSA_STR
            If MODE.2 = 1 Then
            'GET PDOP
                GPS_EXTRACT_ITEM = 15
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING
                GoSub STRING_TO_FLOAT
                PDOP = STF_RESULT        
            'GET HDOP
                GPS_EXTRACT_ITEM = 16
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING
                GoSub STRING_TO_FLOAT
                HDOP = STF_RESULT         
            'GET VDOP
                GPS_EXTRACT_ITEM = 17        
                GoSub EXTRACT_THE_VALUE
                Str STF_STRING_IN = Str GPS_DATA_STRING
                GoSub STRING_TO_FLOAT
                VDOP = STF_RESULT         
        EndIf
    Return
    '*******************************************************************************
    KML_WRITE:
        If FIXED = 0 Or FIX > 0 Then 'Test whether it's okay to write data or not
            High LED
                If MODE.6 = 1 Then SD_IO_String = Str$(DEC8 LAT) + "," + Str$(DEC8 LON)
                If MODE.5 = 1 Then SD_IO_String = SD_IO_String + "," + Str$(DEC1 ALT)
                If MODE.4 = 1 Then SD_IO_String = SD_IO_String + "," + Str$(DEC1 HDG)
                If MODE.3 = 1 Then SD_IO_String = SD_IO_String + "," + Str$(DEC1 SPD)
                If MODE.2 = 1 Then SD_IO_String = SD_IO_String + "," + Str$(Dec SAT) + "," + Str$(DEC1 PDOP) + "," + Str$(DEC1 HDOP) + "," + Str$(DEC1 VDOP)
                If MODE.1 = 1 Then SD_IO_String = SD_IO_String + "," + Str$(Dec FIX)
                If MODE.0 = 1 Then
                    SD_IO_String = SD_IO_String + "," + Str$(Dec SD_Hours) + ":" + Str$(Dec SD_Minutes) + ":" + Str$(Dec SD_Seconds)
                    SD_IO_String = SD_IO_String + "," + Str$(Dec SD_Day) + "/" + Str$(Dec SD_Month) + "/" + Str$(Dec SD_Year + 2000)            
                EndIf
                'SD_IO_String = SD_IO_String + "," + Str$(Dec BATTERY) + "," + Str$(DEC4 VOLTSB)
                'SD_IO_String = SD_IO_String + "," + Str$(Dec COUNTS) + "," + Str$(DEC4 TEMPC) + "," + Str$(DEC4 TEMPF)
                'SD_IO_String = SD_IO_String + "," + Str$(DEC1 TEMPC) + "," + Str$(DEC1 TEMPF)
                SD_IO_String = SD_IO_String + 13 + 10
                Response = SD_Write_String_To_File
                Inc IDX_SAVE
                If IDX_SAVE = 255 Then 
                    Response = SD_Save_File
                    IDX_SAVE = 0
                EndIf
            Low LED
        Else
            GoSub NO_FIX_BLINK
        EndIf     
    Return
    '*******************************************************************************
    EXTRACT_THE_VALUE:
        Clear GPS_DATA_STRING
        GPS_COMMA_COUNT = 0                                        ' Reset the comma counting variable
        GPS_CHARPOS = 0                                            ' Start at the beginning of the array
        Repeat
            GPS_CHAR = GPS_RXBUFF[GPS_CHARPOS]                    ' Scan the array to parse
            If GPS_CHAR = "," Then Inc GPS_COMMA_COUNT            ' Increment GPS_COMMA_COUNT if a comma is found
            If GPS_COMMA_COUNT = GPS_EXTRACT_ITEM Then            ' Have we found the correct comma ?
                GPS_BLOOP = 0                                    ' Yes.  So....              
                Repeat                                            ' Form a loop
                    Inc GPS_CHARPOS                                ' Skip over the comma and keep scanning the array
                    GPS_CHAR = GPS_RXBUFF[GPS_CHARPOS]            ' Extract the pieces of the value into GPS_CHAR
                    If GPS_CHAR = 0 Then Return
                    If GPS_CHAR = "," Then Return
                    GPS_DATA_STRING[GPS_BLOOP] = GPS_CHAR'- 48    ' Fill GPS_DATA_STRING with the value, (converted into integers)
                    Inc GPS_BLOOP                                ' Point to the next data piece
                Until GPS_CHARPOS > GPS_RXBUFFER_LENGTH          ' Keep looping until a terminator is found, or the array runs out
                Return
            EndIf
        Inc GPS_CHARPOS
        Until GPS_CHARPOS > GPS_RXBUFFER_LENGTH
    Return 
    '*******************************************************************************        
    STRING_TO_FLOAT:
        STF_POWER_10 = 1
        STF_RESULT = 0
        STF_SIGN = 0
        STF_CHARPOS = 0
        
        STF_CHAR = STF_STRING_IN[STF_CHARPOS] ' \ Get a character from the String
             Inc STF_CHARPOS                  ' /
        If STF_CHAR = "-" Then        ' Have we found a "-" character ? 
            STF_CHAR = STF_STRING_IN[STF_CHARPOS] ' \ Yes. So Discard the "-" character
            Inc STF_CHARPOS                          ' /
            STF_SIGN = 1                ' Indicate that the value is negative
        Else If STF_CHAR = "+" Then ' Have we found a "+" character ?
            STF_CHAR = STF_STRING_IN[STF_CHARPOS] ' \ Yes. So Discard the "+" character
            Inc STF_CHARPOS                          ' /
        EndIf
        
        While 1 = 1             ' Scan the digits before the decimal point (if included)
            If STF_CHAR < "0" Then Break ' \
            If STF_CHAR > "9" Then Break ' / Exit the loop if non numeric characters found
            STF_RESULT = STF_RESULT * 10     ' \
            STF_RESULT = STF_RESULT + STF_CHAR    ' Calculate the whole part of the floating point value
            STF_RESULT = STF_RESULT - "0"     ' /
            STF_CHAR = STF_STRING_IN[STF_CHARPOS] ' \
            Inc STF_CHARPOS                          ' / Get another character from the string
        Wend
        
        If STF_CHAR == "." Then     ' Have we found a "." character ?
            STF_CHAR = STF_STRING_IN[STF_CHARPOS] ' \ Yes. So Discard the "." character
            Inc STF_CHARPOS                          ' / 
            
            While 1 = 1             ' Scan the digits after the decimal point (if included)
                If STF_CHAR < "0" Then Break ' \
                If STF_CHAR > "9" Then Break ' / Exit the loop if non numeric characters found
                STF_POWER_10 = STF_POWER_10 * 10        ' \ 
                STF_TEMP = (STF_CHAR - "0") / STF_POWER_10 ' Calculate the fractional part of the floating point value
                STF_RESULT = STF_RESULT + STF_TEMP        ' /
                STF_CHAR = STF_STRING_IN[STF_CHARPOS] ' \
                Inc STF_CHARPOS                          ' / Get another character from the string
            Wend
        EndIf
        If STF_SIGN = 1 Then STF_RESULT = -STF_RESULT ' Convert to negative if required
    Return
    '-------------------------------------------------------------------------------        
    'Convert from DD.MMSS to Decimal Degrees
    DDMM_TO_FLOAT: 
        DDMM_POWER_10    = 1
        DDMM_RESULT      = 0
        DDMM_SIGN        = 0
        DDMM_CHARPOS     = 0
        DDMM_CHARPOS_LOW = 0 
         
        DDMM_CHAR = DDMM_STRING_IN[DDMM_CHARPOS] ' \ Get a character from the String
            Inc DDMM_CHARPOS                     ' /
        If DDMM_CHAR = "-" Then        ' Have we found a "-" character ? 
            DDMM_CHAR = DDMM_STRING_IN[DDMM_CHARPOS] ' \ Yes. So Discard the "-" character
            Inc DDMM_CHARPOS                         ' /
            DDMM_SIGN = 1                ' Indicate that the value is negative
        Else If DDMM_CHAR = "+" Then ' Have we found a "+" character ?
            DDMM_CHAR = DDMM_STRING_IN[DDMM_CHARPOS] ' \ Yes. So Discard the "+" character
            Inc DDMM_CHARPOS                         ' /
        EndIf
        
        While 1 = 1             ' Scan the digits before the decimal point (if included)
            If DDMM_CHAR < "0" Then Break ' \
            If DDMM_CHAR > "9" Then Break ' / Exit the loop if non numeric characters found
            DDMM_RESULT = DDMM_RESULT * 10         ' \
            DDMM_RESULT = DDMM_RESULT + DDMM_CHAR    ' Calculate the whole part of the floating point value
            DDMM_RESULT = DDMM_RESULT - "0"         ' /
            DDMM_CHAR = DDMM_STRING_IN[DDMM_CHARPOS] ' \
            Inc DDMM_CHARPOS                         ' / Get another character from the string
        Wend
        
        If DDMM_CHAR == "." Then     ' Have we found a "." character ?
            DDMM_CHAR = DDMM_STRING_IN[DDMM_CHARPOS] ' \ Yes. So Discard the "." character
            Inc DDMM_CHARPOS                         ' / 
            
             While 1 = 1             ' Scan the digits after the decimal point (if included)
                If DDMM_CHAR < "0" Then Break ' \
                If DDMM_CHAR > "9" Then Break ' / Exit the loop if non numeric characters found
                DDMM_TEMP_STR[DDMM_CHARPOS_LOW] = DDMM_CHAR
                DDMM_CHAR = DDMM_STRING_IN[DDMM_CHARPOS] ' \
                Inc DDMM_CHARPOS             ' / Get another character from the string
                Inc DDMM_CHARPOS_LOW
                If DDMM_CHARPOS_LOW = 5 Then Break 'Quit at DEC6
            Wend
                DDMM_TEMP   = Val(DDMM_TEMP_STR,Dec)    ' Convert String to Decimal
                DDMM_TEMP   = DDMM_TEMP / 60000         ' Convert .MMMMM to .DDDD
                DDMM_RESULT = DDMM_RESULT + DDMM_TEMP
        EndIf
        If DDMM_SIGN = 1 Then DDMM_RESULT = -DDMM_RESULT ' Convert to negative if required
    Return
    '*******************************************************************************
    READ_CONFIG_VALUE:
        Clear CONFIG_BUFF
        Clear CONFIG_VALUE
        Clear CONFIG_IDX
        Repeat    
            Response = SD_Read_Byte_From_File
            If Response = "," Then Break
            If Response = 13  Then Break
            If Response = 10  Then Break  
            CONFIG_BUFF[CONFIG_IDX] = Response
            Inc CONFIG_IDX
        Until CONFIG_IDX = 50
    Return
    '*******************************************************************************
    READ_CONFIG_EPROM:
        INTERVAL_EPROM.HighByte = ERead 2
        INTERVAL_EPROM.LowByte  = ERead 3
        MODE_EPROM              = ERead 4
        FIXED_EPROM             = ERead 5
    Return
    '*******************************************************************************
    WRITE_CONFIG_EPROM:
        EWrite 2,[INTERVAL.HighByte]
        EWrite 3,[INTERVAL.LowByte]    
        EWrite 4,[MODE]
        EWrite 5,[FIXED]
    Return
    '*******************************************************************************
    WRITE_CONFIG_FILE:
        SD_File_Name = "CONFIG"
        SD_File_Ext  = "CSV"
        Response = SD_New_File
            SD_IO_String = Str$(Dec INTERVAL) + "," + Str$(BIN8 MODE) + "," + Str$(Dec FIXED)  + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "INTERVAL,OPTIONS,FIXED" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "INTERVAL (0-65536) SECONDS" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "NMEA MODE[7]=0 (MODE[7] NC[6]       NC[5]    NC[4]    GPGGA[3] GPGSA[2]     GPGSV[1] GPRMC[0])" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "KML  MODE[7]=1 (MODE[7] LAT/LONG[6] ALT[5]   HDG[4]   SPD[3]   SAT/DOP[2]   FIX[1]   TIME/DATE[0])" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "LATITUDE(DD.MMMMMM),LONGITUDE(DD.MMMMMM),ALTITUDE(M),HEADING,SPEED(MPH),SATELLITES,PDOP,HDOP,VDOP,FIX,UTC TIME(HH:MM:SS),DATE(DD/MM/YR)" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "BIT[X]=0=OFF" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "BIT[X]=1=ON" + 13 + 10
            Response = SD_Write_String_To_File                      
            SD_IO_String = "FIXED = 0 - DATA ALWAYS WRITTEN" + 13 + 10
            Response = SD_Write_String_To_File
            SD_IO_String = "FIXED = 1 - DATA ONLY WRITTEN WHEN GPS HAS SATELLITE FIX" + 13 + 10
            Response = SD_Write_String_To_File
            SD_IO_String = "*NOTE - FIXED OPTION ONLY USED IN KML MODE"
            Response = SD_Write_String_To_File
        Response = SD_Close_File
    Return
    '*******************************************************************************    
    LED_TEST:
        Clear BLINKS
        Repeat
            High LED
            DelayMS 150
            Low LED
            DelayMS 150
            Inc BLINKS
        Until BLINKS = NUM_BLINKS
        DelayMS 250                   
    Return    
    '*******************************************************************************    
    NO_FIX_BLINK:
        Clear BLINKS
        Repeat
            High LED
            DelayMS 150
            Low LED
            DelayMS 150
            Inc BLINKS
        Until BLINKS = 2   
    Return
    '*******************************************************************************    
    LOW_BAT_BLINK:
        Clear BLINKS
        Repeat
            High LED
            DelayMS 150
            Low LED
            DelayMS 150
            Inc BLINKS
        Until BLINKS = 4   
    Return
    '*******************************************************************************    
    'DEFAULT-EPROM
        EData As Byte 0, 0, 0, 0, %11111111, 0
    '*******************************************************************************    
    'HSERIAL BAUD MODES - 1200,2400,4800,9600,19200,38400
        HSERIAL_RCSTA_DATA: CData As Byte $90,$90,$90,$90,$90,$90,$90,$90
        HSERIAL_TXSTA_DATA: CData As Byte $20,$20,$20,$20,$20,$20,$24,$24
        HSERIAL_SPBRG_DATA: CData As Byte 255,129,64,32,15,7,21,10

    US Distributor of PDS - http://www.ohararp.com/compilers.html
    $25 SMT Kapton Stencils - http://www.ohararp.com/
    This article was originally published in forum thread: GPS code example started by John Drew View original post
  • Recent Activity

    Habro-24485

    Pic 16F1937 to 6 Analog input in Pic basic

    Thread Starter: Habro

    Hi all, I can’t manage to change the first six analog inputs into 8 bits inputs. I’ve tried several things with the registers ADCON0 and ADCON1,...

    Habro Yesterday, 20:38 Go to last post
    craig-17391

    TouchScreen Demo code HELP ?

    Thread Starter: craig

    Hi All Can someone please explain to me If I can use the Amicus18 Colour GLCD shield's "Touch Screen Demo code" on an 18F6622 Pic device using...

    craig Yesterday, 14:04 Go to last post