Bmag incl gps rettelse

Dependencies:   mbed WDT MODSERIAL BME280

main.cpp

Committer:
MAA
Date:
2017-10-06
Branch:
MbedBMAGThrRev
Revision:
43:358e853ba2c9
Parent:
41:d7d77ddd32c6
Child:
44:14ec59d2170c

File content as of revision 43:358e853ba2c9:

#include "main.h"

//please note that mbed library should be of revision 137 or before.

//change GPSACQTIMELIMITINSECONDS to change the duration in seconds, allowed for the gps to get gps fix. 
//After this duration, an error indication will occur if fix is not present.
#define GPSACQTIMELIMITINSECONDS 120 

//to change battery low indication change this value
#define BATTERYLOWLIMIT 10.5 

//change BARCODE string inside double quotes to barcode of BMAG equipment
char BARCODE[6] = "00000";

//Global GPS variables
Timer t;
bool ppsTick = false;
char tmpHour[5];
char tmpMinute[5];
char tmpSecond[5];
char time_buffer[32];
bool RTC_set = false;
bool GPS_Data_Rdy = false;
bool GPS_Data_Valid = false;
bool GPS_Override_Active = false;
bool GGA_Fix_Present = false;
bool firstLineWritten = false;
bool fileNameUpdated = false;
bool lastErrStatus = true;
bool firstErrsWritten = false;
bool gpsStringsReceived = false;
char tmpGpsRxString[128];
char timer_ms[5];
int secCount = 0;
int missingGpsCnt = 0;
int GpsCntWithoutMagData = 0;
int magCntWithoutGpsData = 0;
char missingGpsConnectionCounter = 0;
char gpsOverridePushButtonCounter = 0;
int seconds;
int minutes;
int hours;
char timeArr[10]; 
string timeStr;

string INTERPRETERID = "";
char interpreterTmpID[10];

//global system variables
bool detachMag = false;
bool tickerUpdated = false;
bool gpsRunning = false;
bool gpsCheckedAfter10Sec = false;
bool run = true;
bool toggler = true;
bool dispFlag = false;
bool checkStateFlag = false;
bool flushStrErr = false;
char flushStr[200];
int togglecount = 0;
int fixPresentCnt = 0;
ErrorState prevState = NONE;
ErrorState presentState = NONE;

//global BMAG variables
string lastUTCTimestamp;
bool BMAG_Data_Rdy = false;
bool magTimeSetManually = false;
bool magStringsReceived = false;
char tmpBMAGRxString[128];
char magnTarr[15];
int magTimePromptCount = 0;
int timeSetManuallyCount = 0;
int tmpTime = 0;
char tmpChar1[5];
char tmpChar2[5];
int lastGPRMC_CNT = 0;
int timeDiffInt = 0;
int timeDiffStrLen = 0;

//PTH vars
void getPthValues();
bool PTHValuesReadyFlag = false;
bool PTHSensorActive = false;
float PTH_Preassure = 0;
float PTH_Temperature = 0;
float PTH_Humidity = 0;
char PreassureArr[10] = "";
char TemperatureArr[10] = "";
char HumidityArr[10] = "";

//batteryvoltage
char batteryvoltagearr[5];
string batteryvoltage;

//time
time_t t_of_day;

//Write to file prototype
bool writeToUsb(string line, FILE * f);

//Gps available check prototype
void gpsAvailCheck(void);


//epoch time conversion
time_t setMbedTime(string GPRMCDate, string GPRMCUtc, Serial * debug){
    
    char tmpYear[6];
    char tmpMonth[5];
    char tmpDay[5];
    char tmpHour[5];
    char tmpMinute[5];
    char tmpSecond[5];
    
    struct tm str_time;
    
    memset(tmpYear,'\0',6);
    memset(tmpMonth,'\0',5);
    memset(tmpDay,'\0',5);
    memset(tmpHour,'\0',5);
    memset(tmpMinute,'\0',5);
    memset(tmpSecond,'\0',5);    
    
    snprintf(tmpYear, 6, "%s", GPRMCDate.substr(0, 4));
    snprintf(tmpMonth, 5, "%s", GPRMCDate.substr(5, 2));
    snprintf(tmpDay, 5, "%s", GPRMCDate.substr(8, 2));
    
    snprintf(tmpHour, 5, "%s", GPRMCUtc.substr(0, 2));
    snprintf(tmpMinute, 5, "%s", GPRMCUtc.substr(3, 2));
    snprintf(tmpSecond, 5, "%s", GPRMCUtc.substr(6, 2));

    str_time.tm_year = atoi(tmpYear) - 1900;
    str_time.tm_mon = atoi(tmpMonth) - 1;           // Month, 0 - jan
    str_time.tm_mday = atoi(tmpDay);          // Day of the month
    str_time.tm_hour = atoi(tmpHour);
    str_time.tm_min = atoi(tmpMinute);
    str_time.tm_sec = atoi(tmpSecond)+2;
    str_time.tm_isdst = 0;        // Is DST on? 1 = yes, 0 = no, -1 = unknown
    t_of_day = mktime(&str_time);
    
    debug->printf("-------------------------------\r\n");
    debug->printf("Setting time as seen below:\r\n");
    debug->printf("Year: %s\r\n", tmpYear);
    debug->printf("Month: %s\r\n", tmpMonth);
    debug->printf("Day: %s\r\n", tmpDay);
    debug->printf("Hour: %s\r\n", tmpHour);
    debug->printf("Minute: %s\r\n", tmpMinute);
    debug->printf("Second: %s\r\n", tmpSecond);
    debug->printf("-------------------------------\r\n");
    debug->printf("time since epoch in seconds:");
    debug->printf("%d", (unsigned long)t_of_day);
    debug->printf("\r\n");
    debug->printf("-------------------------------\r\n");
    
    set_time((unsigned long)t_of_day);

    RTC_set = true;
    
    
    return t_of_day;        
}


//dispflag func
void setDispFlag(void){
    dispFlag = true;        
}

//set check state flag func
void setCheckStateFlag(void){
    checkStateFlag = true;    
}

//set time variables
void setTime(int s, int m, int h){
    seconds = s;
    minutes = m;
    hours = h;    
}

//get time
string getTime(void){
    memset(timeArr, '\0', 10);
    snprintf(timeArr, 10, "%.2d:%.2d:%.2d", hours, minutes, seconds);
    timeStr = timeArr;
    return timeStr;    
}

//pps tick
void pps_Tick(){
    seconds += 1;
    if(seconds == 60){
        minutes += 1;
        seconds = 0;    
    }
    if(minutes == 60){
        hours += 1;
        minutes = 0;    
    }
    if(hours == 24){
        hours = 0;
        //prompt for date change when this happens.    
    }   
} 

//timer reset // clock update
void resetTimer(void){
    t.reset();  
    pps_Tick();
}

//bmag interrupt enable
void bmagSerialInterruptEnable(void){        
    //BMAG communication init
    bmag.baud(115200);
    bmag.attach(&bmagrxCallback, MODSERIAL::RxIrq);
    detachMag = true;       
}

int main(void){
    //init pps timing variables
    seconds = 0;
    minutes = 0;
    hours = 0;
    memset(timeArr, '\0', 10);
    memset(flushStr,'\0',200);
    
    //init pth char arrays
    memset(PreassureArr,'\0',10);
    memset(TemperatureArr,'\0',10);
    memset(HumidityArr,'\0',10);
    memset(timer_ms,'\0',5);
    memset(time_buffer,'\0',32);    
    
    t.start();
    
    EA_OLED();
    
    //initializing watchdog, timeout 5 seconds
    Watchdog wd;
    wd.init(5.0);
    
    //PPS
    InterruptIn PPS(p12);  
    PPS.rise(&resetTimer);
      
    //Led outputs
    DigitalOut redLed(p25);
    DigitalOut greenLed(p23);
    
    //MagTime manually set by user input
    DigitalIn timeSetManuallyButton(p30);
    timeSetManuallyButton.mode(PullUp);
    
    redLed = 0;
    greenLed = 0; 
    
    //init of battery string
    memset(batteryvoltagearr,'\0',5);
    batteryvoltage = "";   
    
    //Analog battery reading
    AnalogIn battery(A5);  

    string currentFilename, nextFilename; 
    
    currentFilename = "/usb/tempFile.sps";
    
    //Initializing string buffer for GPS data
    string GPS_String_Buff;
    GPS_String_Buff.resize(128);
    memset(tmpGpsRxString,'\0',128);
    
    //Initializing string buffer for BMAG data
    string BMAG_String_Buff;
    BMAG_String_Buff.resize(128);
    memset(tmpBMAGRxString,'\0',128);
    
    //debug comm setup
    dbg.baud(115200);
    dbg.printf("Init...\r\n");

    //bme pth sensor init 
    if(!BME.init(BME280_i2c, 0x77)){
        dbg.printf("BME280 init failed!\r\n");
            
    }
    if(!BME.start()){
        dbg.printf("BME280 start failed!\r\n"); 
    }
    
    if(BME.is_ok()){
        PTHSensorActive = true;    
    }

    //setting up USB device
    USBHostMSD msd("usb");
    
    clear_display_waiting(); 
    
    //USB message
    l1 = "Mounting";
    l2 = "USB pen";
    thr_writelines.start(write_lines);    
    wait_ms(1000);    
    
    while(!msd.connect()){
        dbg.printf("Trying to connect to usb flash disk\r\n");
        wait_ms(500);      
    }
    
    //Opening a file on usb disk
    FILE * fp;
    FILE * e_fp;
    fp = fopen(currentFilename.c_str(), "a");
    e_fp = fopen("Errorlog.txt", "a");
    wait_ms(100);
    
    //initializing SPS generation 
    SPS spsGen;
    
    //GPS communication init
    gps.baud(9600);
    gps.attach(&rxCallback, MODSERIAL::RxIrq);
        
    clear_display_waiting();
    
    //GPS message
    l1 = "GPS";
    l2 = "Startup";    
    thr_writelines.start(write_lines);
    wait_ms(1000); 
    
    dbg.printf("Init.... Done!\r\n");
 
    //init interpreterid
    int barcodeint = atoi(BARCODE);
    memset(interpreterTmpID,'\0',10);
    sprintf(interpreterTmpID,"%4x", barcodeint);
    INTERPRETERID.assign(interpreterTmpID); 
    
    //Init Done!
    clear_display_waiting();
    l1 = "Init";
    l2 = "Done";  
    thr_writelines.start(write_lines);
    wait_ms(1000);
    
    //Init errorhandler
    ErrorHandler dispTxtHandler(&batteryvoltage, &GGA_Fix_Present, &magParser, &gpsNMEA);
    dispTxtHandler.setErrorState(NONE);
    
    //init of display timer
    Ticker dispTicker;
    dispTicker.attach(&setDispFlag, 1.0);
    
    //init of state ticker
    Ticker stateTicker;
    stateTicker.attach(&setCheckStateFlag, 1.0);
    
    //init ticker for bmag interrupt enable timing
    Ticker magTicker;
    magTicker.attach(&bmagSerialInterruptEnable, 30.0);
    
    //BME280 pth ticker
    Ticker PTHTicker;
    PTHTicker.attach(&getPthValues, 11.0);
    
    //gps available ticker
    Ticker gpsAvailableTicker;
    gpsAvailableTicker.attach(gpsAvailCheck, 10.0);
    
    //clock freqency info
    dbg.printf("SystemCoreClock = %d Hz\r\n", SystemCoreClock);
      
    snprintf(PreassureArr, 10, "%s", "NaN");
    snprintf(TemperatureArr, 10, "%s", "NaN");
    snprintf(HumidityArr, 10, "%s", "NaN");
      
    //infinite loop running after initialization
    while(run) {
        
        //disable continuous magtick detach
        if(detachMag){
            magTicker.detach();
            detachMag = false;    
        }
        
        //display txt on disp
        if(dispFlag){
            
            //get state to be displayed
            presentState = dispTxtHandler.getErrorState();
            //ensure that display is only cleared if the state to be displayed has changed.
            //this ensures that a minimum time duration is used to clear the display.
            
            //thr_writelines.start(clear_display);                    
            

            //update display text
            l1 = dispTxtHandler.getLine1();
            l2 = dispTxtHandler.getLine2(); 
            
            
            thr_writelines.start(write_lines);
            
                        
            //Ensure that next check will have the current state as previous state, as expected.
            prevState = presentState;
            
            //clear display flag
            dispFlag = false;    
        }
        
        //check state / set state
        if(checkStateFlag){
            
            
            //inform of missing GPS
            if(gpsCheckedAfter10Sec && !gpsRunning){
                dispTxtHandler.setErrorState(NO_GPS);            
            }
            
            if(gpsCheckedAfter10Sec && gpsRunning){
                gpsAvailableTicker.attach(NULL, 10.0);
                
                //bme pth sensor init 
                if(!BME.init(BME280_i2c, 0x77)){
                    dbg.printf("BME280 init failed!\r\n");
                        
                }
                if(!BME.start()){
                    dbg.printf("BME280 start failed!\r\n"); 
                }
                
                if(BME.is_ok()){
                    PTHSensorActive = true;    
                }                  
            }
            
            //missingGpsConnectionCounter gets cleared at every received gps string
            if(!GPS_Override_Active && missingGpsConnectionCounter < 10){
                
                missingGpsConnectionCounter += 1;
            }
            
            if(gpsOverridePushButtonCounter > 1){
                GPS_Override_Active = true;        
            }
            
                                        
            //pushbutton check gpsOverridePushButtonCounter
            if(!timeSetManuallyButton){
                gpsOverridePushButtonCounter += 1;        
            }
            
            if(missingGpsConnectionCounter > 30 && !GPS_Override_Active){
                dispTxtHandler.setErrorState(GPS_OVERRIDE_NEEDED);
                
                redLed = 1;
                greenLed = 0; 
                                
            }
            
            if((toggler && magStringsReceived &&(missingGpsCnt < GPSACQTIMELIMITINSECONDS)) || (toggler && dispTxtHandler.getMagTimePromtStatus()) && magStringsReceived) {
                //show battery voltage and gps fix status for 10 seconds
                dispTxtHandler.setErrorState(DISPLAY_VBAT_FIX);
                
                if(!tickerUpdated){
                    dispTicker.detach();
                    dispTicker.attach(&setDispFlag, 10.0);
                    tickerUpdated = true;
                            
                }
                
                togglecount += 1;
                if(togglecount >= 2) {
                    toggler = false;
                    togglecount = 0;
                }
    
            }
    
            if((!toggler && (missingGpsCnt < GPSACQTIMELIMITINSECONDS) && magStringsReceived) || (!toggler && dispTxtHandler.getMagTimePromtStatus()) && magStringsReceived) {
                //show magnT reading for 10 seconds
                dispTxtHandler.setErrorState(DISPLAY_MAG_MEASUREMENT);
    
                togglecount += 1;
                if(togglecount >= 2) {
                    toggler = true;
                    togglecount = 0;
                }
            }
            
            
            //if battery voltage is below BATTERYLOW limit, initiate battery low error state
            if((0.00036621652)*battery.read_u16() < BATTERYLOWLIMIT){
                dispTxtHandler.setErrorState(BATTERY_LOW);
                redLed = 1;
                greenLed = 0;    
            }
            
            //if gga fix is not present for a prolonged period of time, prompt user
            if((missingGpsCnt > GPSACQTIMELIMITINSECONDS) && !dispTxtHandler.getMagTimePromtStatus()) {

                //Prompt user to set mag time manually
                dispTxtHandler.setErrorState(NO_FIX);
            }            
            
            //if gps data is missing for more than 10 mag reading cycles
            if((magCntWithoutGpsData > 10) && !magTimeSetManually) {
                //show error indication of gps data missing
                dispTxtHandler.setErrorState(NO_GPS);

                //set led error status
                redLed = 1;
                greenLed = 0;
                
                GGA_Fix_Present = false;
                
                //knaptryk check 
                if(!timeSetManuallyButton){
                    timeSetManuallyCount += 1;        
                }
                
                if(timeSetManuallyCount > 3){
                    magTimeSetManually = true;         
                }
                     
            }                        
            
                
            if(!GGA_Fix_Present && GpsCntWithoutMagData < 20){
                //Missing GGA fix LED indicator
                greenLed = 0;
                redLed = 1;
            }
            
            if(GpsCntWithoutMagData > 20){
                //Missing MAG data prompt
                dispTxtHandler.setErrorState(NO_MAG_DATA);
                greenLed = 0;
                redLed = 1;
            }
                    
            if((GGA_Fix_Present && GpsCntWithoutMagData < 20) || (magTimeSetManually && GpsCntWithoutMagData < 20)){
                //GGA fix LED indicator / time set manually unless battery is low
                if(dispTxtHandler.getErrorState() != BATTERY_LOW){
                    greenLed = 1;
                    redLed = 0;                    
                }     
            }    
                        
            checkStateFlag = false;    
        }
        
        //if the gps rx buffer is full, get info to error file.
        if(gps.rxBufferFull()){
            gps.move(flushStr, gps.rxBufferGetCount());
            flushStrErr = true;
            //remkark hvis dette sker i error fil   
        }
        
        //if the bmag rx buffer is full, flush the buffer.
        if(bmag.rxBufferFull()){
            bmag.move(flushStr, bmag.rxBufferGetCount());
            flushStrErr = true;
            //remkark hvis dette sker i error fil  
        }
        
        
        //if bmag data string is available
        if(BMAG_Data_Rdy) {
            
            //reset last read ms val
            memset(timer_ms,'\0',5);
            
            //read time since pps interrupt
            tmpTime = t.read_ms();
            snprintf (timer_ms, 5, "%d",tmpTime);    
            
            if(tmpTime > 1000){
                writeToUsb("timer abover 1000 ms\r\n", e_fp);                    
            } 
                         
            if(RTC_set){
                
                string tmpTime = getTime();
                
                                
                //HH
                gpsNMEA.currentUTCFromGPRMC[0] = tmpTime[0];
                gpsNMEA.currentUTCFromGPRMC[1] = tmpTime[1];
             
                //MM
                gpsNMEA.currentUTCFromGPRMC[3] = tmpTime[3];
                gpsNMEA.currentUTCFromGPRMC[4] = tmpTime[4];
             
                //SS
                gpsNMEA.currentUTCFromGPRMC[6] = tmpTime[6];
                gpsNMEA.currentUTCFromGPRMC[7] = tmpTime[7];                   
            }
            
            
            if(strlen(timer_ms) == 1){
                gpsNMEA.currentUTCFromGPRMC[9] = '0';
                gpsNMEA.currentUTCFromGPRMC[10] = '0';
                gpsNMEA.currentUTCFromGPRMC[11] = timer_ms[0];                  
            }
            
            if(strlen(timer_ms) == 2){
                gpsNMEA.currentUTCFromGPRMC[9] = '0';
                gpsNMEA.currentUTCFromGPRMC[10] = timer_ms[0];
                gpsNMEA.currentUTCFromGPRMC[11] = timer_ms[1];    
            }
            
            if(strlen(timer_ms) == 3){
                gpsNMEA.currentUTCFromGPRMC[9] = timer_ms[0];
                gpsNMEA.currentUTCFromGPRMC[10] = timer_ms[1];
                gpsNMEA.currentUTCFromGPRMC[11] = timer_ms[2];       
            }
            
            if(strlen(timer_ms) > 3 || strlen(timer_ms) == 0){
                gpsNMEA.currentUTCFromGPRMC[9] = '0';
                gpsNMEA.currentUTCFromGPRMC[10] = '0';
                gpsNMEA.currentUTCFromGPRMC[11] = '0';                       
            }
            
                       
            //change magStringsReceived flag to true when mag data is available
            if(magStringsReceived == false){
                magStringsReceived = true;    
            }
            
            //if gps override is active reset magCntWithoutGpsData
            if(GPS_Override_Active){
                magCntWithoutGpsData = 0;    
            }
            
            //if mag data is present but gps data is not and gps override is not active
            if(magCntWithoutGpsData < 100 && !GPS_Override_Active) {
                magCntWithoutGpsData += 1;
            }
            
            //move bmag data from rxbuffer to temporary array
            bmag.move(tmpBMAGRxString, bmag.rxBufferGetCount());

            //copy c_string to string
            BMAG_String_Buff.assign(tmpBMAGRxString);

            //clear tmpRxBuffer
            memset(tmpBMAGRxString,'\0',128);

            //parse bmag string
            magParser.parseBMAGString(BMAG_String_Buff);

            //reset counter containing gps string count without mag data
            GpsCntWithoutMagData = 0;

            //update filename when date is available with gga fix
            if(!fileNameUpdated && GGA_Fix_Present) {
                spsGen.generateSpsFilename(gpsNMEA.currentDATEFromGPRMC);
                nextFilename.assign(spsGen.getSpsFileName());
                fclose(fp);
                currentFilename.assign(nextFilename);
                nextFilename = "";

                fp = fopen(currentFilename.c_str(), "a");

                fileNameUpdated = true;
                
                spsGen.UpdateHeaderString(BARCODE, IDENTIFIERID, GROUP, TIMEZONE, ENCODING,SOURCEIDENTIFICATION, INTERPRETERID, DATALINEVERSION, FWSRCVERSION, FWIVERSION);
                //add header to top of file
                writeToUsb(spsGen.getHeaderString(), fp);
            }

            //if date has changed, ensure new file creation.
            spsGen.generateSpsFilename(gpsNMEA.currentDATEFromGPRMC);
            if(currentFilename != spsGen.getSpsFileName()) {
                fileNameUpdated = false;
            }
            
            //read battery voltage
            sprintf(batteryvoltagearr, "%0.1f",(0.00036621652)*battery.read_u16());
            batteryvoltage.assign(batteryvoltagearr);

            //generate default sps string
            spsGen.UpdateCurrentString(TAG, IDENTIFIERID, GROUP, gpsNMEA.currentDATEFromGPRMC, gpsNMEA.currentUTCFromGPRMC, TIMEZONE, ENCODING, SOURCEIDENTIFICATION, INTERPRETERID, DATALINEVERSION, FWSRCVERSION, FWIVERSION, BARCODE,gpsNMEA.currentLatitude, gpsNMEA.currentLongitude, GGA_Fix_Present, batteryvoltage, PreassureArr, TemperatureArr, HumidityArr, magParser.getMagTimeStr(), magParser.getMagNTStr(), magParser.getMagSq(), &dbg);

            //write data strings to sps file
            if(GGA_Fix_Present) {

                missingGpsCnt = 0;
                        
                writeToUsb(spsGen.getCurrentString(), fp);             
                
                if(!firstLineWritten) {
                    spsGen.UpdateHeaderString(BARCODE, IDENTIFIERID, GROUP, TIMEZONE, ENCODING,SOURCEIDENTIFICATION, INTERPRETERID, DATALINEVERSION, FWSRCVERSION, FWIVERSION);
                    writeToUsb(spsGen.getHeaderString(), fp);
                    firstLineWritten = true;
                }

                

                if(!lastErrStatus && firstErrsWritten) {
                    //force clock resync
                    RTC_set = false;  
                    
                    //error end string
                    spsGen.UpdateCurrentErrString("ERRE", IDENTIFIERID, GROUP, gpsNMEA.currentDATEFromGPRMC, gpsNMEA.currentUTCFromGPRMC, TIMEZONE, ENCODING, SOURCEIDENTIFICATION, INTERPRETERID, DATALINEVERSION, FWSRCVERSION, FWIVERSION, gpsNMEA.currentLatitude, gpsNMEA.currentLongitude, GGA_Fix_Present, magParser.getMagTimeStr(), magParser.getMagNTStr(), magParser.getMagSq(), &dbg);
                    writeToUsb(spsGen.getCurrentErrString(), fp);
                    lastErrStatus = true;
                    firstErrsWritten = false;
                    firstLineWritten = false;
                }
            }

            //write data strings to sps file, with error messages as defined in *.sps definition
            if(!GGA_Fix_Present) {

                if(missingGpsCnt <=  GPSACQTIMELIMITINSECONDS) {
                    missingGpsCnt += 1;
                }

                if(!firstLineWritten) {
                    spsGen.UpdateHeaderString(BARCODE, IDENTIFIERID, GROUP, TIMEZONE, ENCODING,SOURCEIDENTIFICATION, INTERPRETERID, DATALINEVERSION, FWSRCVERSION, FWIVERSION);
                    writeToUsb(spsGen.getHeaderString(), fp);
                    firstLineWritten = true;
                }

                if(firstErrsWritten){
                    writeToUsb(spsGen.getCurrentString(), fp);
                }

                if(lastErrStatus && !firstErrsWritten) {
                    spsGen.UpdateCurrentErrString("ERRS", IDENTIFIERID, GROUP, gpsNMEA.currentDATEFromGPRMC, gpsNMEA.currentUTCFromGPRMC, TIMEZONE, ENCODING, SOURCEIDENTIFICATION, INTERPRETERID, DATALINEVERSION, FWSRCVERSION, FWIVERSION, gpsNMEA.currentLatitude, gpsNMEA.currentLongitude, GGA_Fix_Present, magParser.getMagTimeStr(), magParser.getMagNTStr(), magParser.getMagSq(), &dbg);
                    writeToUsb(spsGen.getCurrentErrString(), fp);
                    lastErrStatus = false;
                    firstErrsWritten = true;
                }

            }

            //if user has been notified of time settings needed on bmag, pushbutton can be held for a few cycles to circumvent the set mag time display prompt.
            if(!timeSetManuallyButton && dispTxtHandler.getMagTimePromtStatus()) {
                timeSetManuallyCount += 1;

                if(timeSetManuallyCount > 3) {
                    magTimeSetManually = true;
                }
            }

            BMAG_Data_Rdy = false;
        }
     
        
        if(GPS_Data_Rdy){
            
            gpsRunning = true;
            
            missingGpsConnectionCounter = 0;
            
            if(gpsStringsReceived == false){
                gpsStringsReceived = true;    
            }
            
            //clear mag data string counter, counting mag data received since last gps string received
            magCntWithoutGpsData = 0;
            
            //if gps data has been received without mag data since last gps string, increment counter.
            if(GpsCntWithoutMagData < 200){
                
                GpsCntWithoutMagData += 1;
                
            }
                          
            gps.scanf("%s", &tmpGpsRxString);
            
            //copy c_string to string
            GPS_String_Buff.assign(tmpGpsRxString);
            dbg.printf(tmpGpsRxString);
            dbg.printf("\r\n");
            
            //clear tmpRxBuffer
            memset(tmpGpsRxString,'\0',128);
            
            //Validate CRC
            GPS_Data_Valid = gpsNMEA.ValidateData(GPS_String_Buff);
         
            //store valid string, either gga or rmc
            if(GPS_Data_Valid){
                 gpsNMEA.StoreString(GPS_String_Buff/*, &dbg*/);   
            }
            
            //Get gga fix flag
            GGA_Fix_Present = gpsNMEA.GGAFixVerification();
            
            //Assign value to error flag
            spsGen.setErrStatus(GGA_Fix_Present);  
            
            //Clearing RX buffer.
            GPS_String_Buff = "";
            GPS_String_Buff.resize(128);
            
            //parse current date 
            gpsNMEA.ParseCurrentDateFromGPRMC();
            
            //parse current time
            gpsNMEA.ParseCurrentUTCFromGPRMC();
            
            //parse gps coordinates
            gpsNMEA.ParseCurrentLatitudeFromGPRMC();
            gpsNMEA.ParseCurrentLongitudeFromGPRMC();
  
            //clearing flags
            GPS_Data_Valid = false;
            GPS_Data_Rdy = false;
            
            if(GGA_Fix_Present && !RTC_set){
                fixPresentCnt += 1;    
            }
            
            if(GGA_Fix_Present && !RTC_set && (fixPresentCnt > 5)){
                    setMbedTime(gpsNMEA.currentDATEFromGPRMC, gpsNMEA.currentUTCFromGPRMC, &dbg);
                                 
                    memset(tmpHour, '\0', 5);
                    memset(tmpMinute, '\0', 5);
                    memset(tmpSecond, '\0', 5);
                    
                    snprintf(tmpHour, 5, "%s", gpsNMEA.currentUTCFromGPRMC.substr(0, 2));
                    snprintf(tmpMinute, 5, "%s", gpsNMEA.currentUTCFromGPRMC.substr(3, 2));
                    snprintf(tmpSecond, 5, "%s", gpsNMEA.currentUTCFromGPRMC.substr(6, 2));
                    
                    int hours = atoi(tmpHour);
                    int minutes = atoi(tmpMinute);
                    int seconds = atoi(tmpSecond);                 
                    setTime(seconds, minutes, hours);
                    
                    dbg.printf("Clock resync done!\r\n"); 
                    dbg.printf("Clock set to %s\r\n", getTime());    
                    
                    RTC_set = true;
                    fixPresentCnt = 0;                          
            }
                
        }
        
        //if pth data is due, convert pth values to char arrays
        if(PTHValuesReadyFlag){
            memset(TemperatureArr,'\0',10);
            memset(HumidityArr,'\0',10);
            
            //assign last measured preassure to char array, and ensure correct zero padding
            if(PTH_Preassure <= 999){
                memset(PreassureArr,'\0',10);
                snprintf(PreassureArr, 10, "0%.0f", PTH_Preassure);                
            }
            
            if(PTH_Preassure >= 1000){
                memset(PreassureArr,'\0',10);
                snprintf(PreassureArr, 10, "%.0f", PTH_Preassure);                
            }      
            
            //ensure correct  temperature operator (+ or -) to show if temperature is positive or negative
            if(PTH_Temperature >= 0){
                //assign last measured temperature to char array with zero padding if needed
                
                if((PTH_Temperature > -10) && (PTH_Temperature < 10)){
                    
                    if(PTH_Temperature < 0){
                        snprintf(TemperatureArr, 10, "-0%.0f", PTH_Temperature);
                    }
                    
                    if(PTH_Temperature >= 0){
                        snprintf(TemperatureArr, 10, "+0%.0f", PTH_Temperature);    
                    }                
                }
                
                if(PTH_Temperature < -10){
                    snprintf(TemperatureArr, 10, "-%.0f", PTH_Temperature);        
                }
                
                if(PTH_Temperature > 9){
                    snprintf(TemperatureArr, 10, "+%.0f", PTH_Temperature);        
                } 
     
            }  
            
            //assign last measured relative humidity to char array            
            if(PTH_Humidity < 10){
                snprintf(HumidityArr, 10, "00%.0f", PTH_Humidity);                                            
            }
            
            if((PTH_Humidity < 100) && (PTH_Humidity >= 10)){
                snprintf(HumidityArr, 10, "0%.0f", PTH_Humidity);                          
            } 
            
            if(PTH_Humidity >= 100){
               snprintf(HumidityArr, 10, "%.0f", PTH_Humidity);    
            }
            
            dbg.printf("P = %s, T = %s, H = %s\r\n",PreassureArr,TemperatureArr, HumidityArr);     
            
            PTHValuesReadyFlag = false;
                                   
        }
        
        //If the pth sensor is inactive write NaN in the data columns normally containing PTH values
        if(!PTHSensorActive){
            memset(PreassureArr,'\0',10);
            memset(TemperatureArr,'\0',10);
            memset(HumidityArr,'\0',10);
            snprintf(PreassureArr, 10, "%s", "NaN");
            snprintf(TemperatureArr, 10, "%s", "NaN"); 
            snprintf(HumidityArr, 10, "%s", "NaN");             
        }  

        //If connection to USB flash disk is lost, reconnect to the flash disk
        if(!msd.connected()){
            
            //USB message
            clear_display_waiting();            
            l1 = "USB pen";
            l2 = "Missing!"; 
            thr_writelines.start(write_lines);
            
            //reestablish usb connection
            while(!msd.connect()){
                dbg.printf("Trying to reconnect to usb flash disk\r\n");
                wait_ms(200);
                msd.connect();
            }
            
            thr_writelines.terminate();
                
            //Reopening a file on usb disk
            fp = fopen(currentFilename.c_str(), "a");
            
            writeToUsb("\r\n", fp);
            writeToUsb(spsGen.getHeaderString(), fp);
                        
        }
        
        if(flushStrErr){
            writeToUsb(flushStr, e_fp);
            writeToUsb("\r\n", e_fp);
            
            memset(flushStr, '\0', 200);
            
            flushStrErr = false;    
        }
        
        //kick / feed watchdog 
        wd.kick();
        
        Thread::yield();
    }    
   
    return 0;    
}

//Thanks to MODSERIAL!
// Called everytime a new character goes into
// the RX buffer. Test that character for \n
// Note, rxGetLastChar() gets the last char that
// we received but it does NOT remove it from
// the RX buffer. 
void rxCallback(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *serial = q->serial;
    if (serial->rxGetLastChar() == '\n') {
        GPS_Data_Rdy = true;
    }
}

//Thanks to MODSERIAL!
// Called everytime a new character goes into
// the RX buffer. Test that character for \r and buffer char count
// Note, rxGetLastChar() gets the last char that
// we received but it does NOT remove it from
// the RX buffer. 
void bmagrxCallback(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *serial = q->serial;
    if ((serial->rxBufferGetCount() > 20) && (serial->rxGetLastChar() == '\r')) {
        BMAG_Data_Rdy = true;
    }
}

//Write to file
bool writeToUsb(string line, FILE * f){

    if (f != NULL) {
        fprintf(f, "\r\n");
        fprintf(f, line.c_str());  
              
    }
                 
    if(f == NULL){
        return false;
    }
    
    return true;      
}


void getPthValues(){
    if(BME.get(PTH_Temperature, PTH_Preassure, PTH_Humidity)){
         PTHValuesReadyFlag = true;   
    }
};


void gpsAvailCheck(void){
    gpsCheckedAfter10Sec = true;
};