This my big project for PYRN Board
Dependencies: CAN HTTPClient MODSERIAL MyThings Pyrn3GModem Socket TinyGPS MyUSBHost lwip-sys lwip mbed-rtos mbed-src
GPSSensor.cpp
- Committer:
- clemounet
- Date:
- 2015-04-14
- Revision:
- 0:efe6085327fd
File content as of revision 0:efe6085327fd:
#include "GPSSensor.h" #define __DEBUG__ 2 #ifndef __MODULE__ #define __MODULE__ "GPSSensor.cpp" #endif #include "MyDebug.h" #define GPS_THREAD_STACK_SIZE 768 bool gpsNewlineDetected; void rxFullCallback(MODSERIAL_IRQ_INFO *q){ DBG("OVF"); MODSERIAL *serial = q->serial; serial->rxBufferFlush(); } void rxCallback(MODSERIAL_IRQ_INFO *q) { MODSERIAL *serial = q->serial; if ( serial->rxGetLastChar() == '\n') { gpsNewlineDetected = true; } } // Well there is an issue in the RX Serial data, sometime multiples frames collides between themselves... // To debug when we gonna have GSP Signal GPSSensor::GPSSensor(PinName tx, PinName rx, uint32_t trackingTime, uint32_t idle): MySensor(SENSOR_NAME_GPS, SENSOR_TYPE_GPS, idle, GPS_THREAD_STACK_SIZE), gps(tx,rx) { fixed = false; trackTime = trackingTime; lastImpact = 0; gpsNewlineDetected = false; gps.baud(9600); gps.rxBufferFlush(); gps.txBufferFlush(); WARN("Increase the baudrate to 57600"); gps.printf("$PUBX,41,1,0007,0003,57600,0*2B\r\n"); Thread::wait(1000); gps.baud(57600); WARN("Disabling all unused NMEA sentences"); gps.printf("$PUBX,40,GLL,0,0,0,0,0,0*5C\r\n"); gps.printf("$PUBX,40,ZDA,0,0,0,0,0,0*44\r\n"); gps.printf("$PUBX,40,VTG,0,0,0,0,0,0*5E\r\n"); gps.printf("$PUBX,40,GSV,0,0,0,0,0,0*59\r\n"); gps.printf("$PUBX,40,GSA,0,0,0,0,0,0*4E\r\n"); //gps.printf("$PUBX,40,RMC,0,0,0,0,0,0*47\r\n"); Thread::wait(500); gps.rxBufferFlush(); gps.txBufferFlush(); WARN("Setup Callbacks"); gps.attach(&rxCallback, MODSERIAL::RxIrq); gps.attach(&rxFullCallback, MODSERIAL::RxOvIrq); InitResults(SENSOR_RESSZ_DEFAULT); WARN("Finish Init"); } // Could we have a way to put the InitResultStatic/StoreLastImpact into the base class? void GPSSensor::InitResultsStatic(void) { DBG("InitResultStatic have been defined"); results.start = (uint8_t*)store; results.current = (uint8_t*)store; results.max = sizeof(store); //IMU_STORE_SIZE*sizeof(uint16_t); } void GPSSensor::Loop(void) { // We read all the available data as fast as possible // but giving opportunity to be preampted (wait 100ms) // Doing this reading should avoid serial internal buffer to ovf Sample(); StoreLastImpact(); Thread::wait(idleTime); } void GPSSensor::StoreLastImpact(void) { if(fixed && NeedImpact()) { if((results.max - results.num)>=sizeof(gpsImpact)){ DBG("===========> Storing New impact <==========="); if(resultsMutex.trylock()) { memcpy((char*)results.current,(const char*)&impact,sizeof(gpsImpact)); results.current += sizeof(gpsImpact); results.num += sizeof(gpsImpact); DBG("%p %d %d",results.current,results.num,sizeof(gpsImpact)); resultsMutex.unlock(); } } else ERR("No Space to Store results... Data will be overwrited at next Loop"); } else { DBG("Nope, (%s)", (!fixed)?"not fixed":"no impact needed"); } } bool GPSSensor::NeedImpact(void) { time_t now = time(NULL); DBG("%ld-%ld = %d > %d ",now,lastImpact,now-lastImpact,trackTime); if((now-lastImpact)>trackTime){ DBG("NEED IMPACT"); lastImpact = now; return true; } return false; } int GPSSensor::GetLine(void) { int len = 0; // Consume the chars until we found a '$' while (gps.getc() != '$'); recvBuff[0] = '$'; // Fill the GPS_RECV_BUFF for (int i=1; i<(GPS_RECV_BUFF-2); i++) { recvBuff[i] = gps.getc(); len++; if (recvBuff[i] == '\n') { recvBuff[i+1] = '\0'; return len; } } error("Overflow in getline"); return GPS_RECV_BUFF-2; } void GPSSensor::Sample(void) { int len = 0; bool newData = false; if(gpsNewlineDetected) { while(1) { int nChars = gps.rxBufferGetCount(); if(nChars == 0) break; //else // DBG("To read --> %d",nChars); // We could consider passing the data directly to parser whithout buffering it // but: That's annoying cause if so we could not printf them smoothly on console len = GetLine(); //DBG("GotLine(%d) %s",len,recvBuff); // DBG_MEMDUMP("GPSData",(const char*)recvBuff,len); for(unsigned int i = 0; i < len; i++) { // Insert all data to gpsParser if(gpsParser.encode(recvBuff[i])) { newData = true; } } // Only take a sample when all the data for each epoch have been received if(newData && gpsParser.rmc_ready() && gpsParser.gga_ready()){ long lat = 0, lon = 0, hdop = 0; unsigned long date = 0, time = 0; gpsParser.get_position(&lat,&lon); gpsParser.get_datetime(&date,&time); hdop = gpsParser.hdop(); if((lat != TinyGPS::GPS_INVALID_ANGLE) && (lon != TinyGPS::GPS_INVALID_ANGLE)){ fixed = true; impact.date = date; impact.time = time/100; impact.lat = lat; impact.lon = lon; if(hdop>0xffff) { impact.hdop = -1; } else { impact.hdop = hdop; } WARN("######[%ld-%ld][%09ld|%09ld|%04d]######",impact.date,impact.time,impact.lat,impact.lon,impact.hdop); } else { fixed = false; DBG("All data have been received but lat/lon does not seems to be valid",date,time,lat,lon,hdop); } gpsParser.reset_ready(); } else { fixed = false; DBG("All frames did not came yet RMC(%c)GGA(%c)newData(%c)",gpsParser.rmc_ready()?'x':'o',gpsParser.gga_ready()?'x':'o',newData?'x':'o'); } } } } // OLD SAMPLING /* void GPSSensor::Sample(void) { int lineParsed = 0; DBG("Read GPS"); if(gpsNewlineDetected) { gpsNewlineDetected = false; while(1) { int nChars = gps.rxBufferGetCount(); if(nChars == 0) { DBG("No data to read anymore on gps line"); break; } else { DBG("--> %d",nChars); } DBG("Read Line GPS"); GetLine(); DBG("GotLine, %s",recvBuff); DBG_MEMDUMP("GPSData",(const char*)recvBuff,strlen((const char*)recvBuff)); // Stuffs used in GPGGA // The only NMEA sentence we gonna have (all other are disabled) int nArgs = sscanf((const char*)recvBuff, "GPGGA,%f,%f,%c,%f,%c,%d,%d,%f,%f,%c",&hour,&lat,&ns,&lon,&ew,&q,&su,&hdop,&alt,&altU); if(nArgs == 10) { DBG("We got all the arguments"); DBG("%d [%f/%f/%c/%f/%c/%d/%d/%f/%f/%c]\n",nArgs,hour,lat,ns,lon,ew,q,su,hdop,alt,altU); lineParsed = GGA; } // if lineParsed is different from zero meens that's we got new data if(lineParsed) { DBG("Impact Result %d", su); // When 0 satelites usualy this we can't lock if(su == 0) q = 0; if(q!=0){ DBG("Locked (q = %d)",q); fixed = true; impact.utc = (uint32_t) hour; impact.lat = DegToDec(lat,ns); impact.lon = DegToDec(lon,ew); impact.alt = alt; impact.su = su; impact.hdop = hdop; DBG("Impact Results %d, %f, %f, %f, %d, %d", impact.utc, impact.lat, impact.lon, impact.alt, impact.su, impact.hdop); } } } } } */