00001
00053 #include "nmea.h"
00054
00055 #include "cfg/cfg_nmea.h"
00056
00057 #include <cfg/debug.h>
00058
00059 #define LOG_LEVEL NMEA_LOG_LEVEL
00060 #define LOG_FORMAT NMEA_LOG_FORMAT
00061 #include <cfg/log.h>
00062
00063 #include <net/nmeap/inc/nmeap.h>
00064
00065 #include <ctype.h>
00066 #include <time.h>
00067 #include <string.h>
00068 #include <stdlib.h>
00069
00070
00071
00072
00073
00074
00075
00076 static uint32_t tokenToInt(const char *s, int precision)
00077 {
00078 uint32_t num = 0;
00079 bool sep_found = false;
00080 int i;
00081
00082 if (!s)
00083 return 0;
00084
00085 for(i = 0; i < NMEAP_MAX_SENTENCE_LENGTH; i++)
00086 {
00087 char c = *s++;
00088
00089 if (c == '.')
00090 {
00091 sep_found = true;
00092 continue;
00093 }
00094
00095 if (c == '\0' || !isdigit(c) || (precision == 0 && sep_found))
00096 break;
00097
00098 if (sep_found)
00099 precision--;
00100
00101 num *= 10;
00102 num += c - '0';
00103 }
00104
00105 while (precision--)
00106 num *= 10;
00107
00108 return num;
00109 }
00110
00111
00112
00113
00114 static udegree_t convertToDegree(const char *str)
00115 {
00116 uint32_t dec;
00117 uint32_t deg;
00118 uint32_t min;
00119
00120 if (*str == 0)
00121 {
00122 return 0;
00123 }
00124
00125 dec = tokenToInt(str, 4);
00126 deg = dec / 1000000;
00127 min = dec - deg * 1000000;
00128 dec = deg * 1000000 + ((min * 5) + 1) / 3;
00129
00130 return dec;
00131 }
00132
00133
00134
00135
00136 static udegree_t nmea_latitude(const char *plat, const char *phem)
00137 {
00138 int ns;
00139
00140 if (*phem == 0)
00141 return 0;
00142
00143
00144 ns = (*phem == 'N') ? 1 : -1;
00145
00146
00147 return ns * convertToDegree(plat);
00148 }
00149
00150
00151
00152
00153 static udegree_t nmea_longitude(const char *plot, const char *phem)
00154 {
00155 int ew;
00156
00157 if (*phem == 0)
00158 return 0;
00159
00160
00161 ew = (*phem == 'E') ? 1 : -1;
00162
00163 return ew * convertToDegree(plot);
00164 }
00165
00166
00167
00168
00169
00170 static uint16_t nmea_altitude(const char *palt, const char *punits)
00171 {
00172 uint32_t alt;
00173
00174 if (*palt == 0)
00175 return 0;
00176
00177 alt = atoi(palt);
00178
00179 if (*punits == 'F')
00180 {
00181
00182
00183 alt = alt * 3 +
00184 (alt >> 2) +
00185 (alt >> 6) +
00186 (alt >> 7) +
00187 (alt >> 8);
00188
00189 }
00190
00191 return alt;
00192 }
00193
00194
00195
00196
00197 static time_t timestampToSec(uint32_t time_stamp, uint32_t date_stamp)
00198 {
00199 struct tm t;
00200 uint16_t msec;
00201 uint16_t tmr[3];
00202 uint16_t date[3];
00203
00204 memset(&t, 0, sizeof(t));
00205 memset(&tmr, 0, sizeof(tmr));
00206 memset(&date, 0, sizeof(date));
00207
00208 LOG_INFO("time_s[%lu],date[%lu]\n", (long)time_stamp, (long)date_stamp);
00209 uint32_t res = time_stamp / 1000;
00210 uint32_t all = time_stamp;
00211 msec = all - res * 1000;
00212
00213 for (int i = 0; i < 3; i++)
00214 {
00215 all = res;
00216 res = all / 100;
00217 tmr[i] = all - res * 100;
00218 LOG_INFO("t[%d]%d\n", tmr[i],i);
00219 }
00220
00221 t.tm_sec = tmr[0] + (ROUND_UP(msec, 1000) / 1000);
00222 t.tm_min = tmr[1];
00223 t.tm_hour = tmr[2];
00224
00225 t.tm_mday = 1;
00226 t.tm_mon = 0;
00227 t.tm_year = 70;
00228
00229 if (date_stamp)
00230 {
00231 res = all = date_stamp;
00232 for (int i = 0; i < 3; i++)
00233 {
00234 all = res;
00235 res = all / 100;
00236 date[i] = all - res * 100;
00237 LOG_INFO("d[%d]%d\n", date[i],i);
00238 }
00239 t.tm_mday = date[2];
00240 t.tm_mon = date[1] - 1;
00241
00242
00243 t.tm_year = date[0] + 100;
00244 }
00245 LOG_INFO("times=%d,%d,%d,%d,%d,%d\n",t.tm_sec, t.tm_min, t.tm_hour, t.tm_year, t.tm_mon, t.tm_mday);
00246
00247 return mktime(&t);
00248 }
00249
00253 void gpgga_callout(nmeap_context_t *context, void *data, void *user_data)
00254 {
00255 (void)context;
00256 (void)user_data;
00257 (void)data;
00258 LOG_INFOB(
00259 NmeaGga *gga = (NmeaGga *)data;
00260 LOG_INFO("Found GPGGA message %ld %ld %d %lu %d %d %d %d\n",
00261 (long)gga->latitude,
00262 (long)gga->longitude,
00263 gga->altitude,
00264 gga->time,
00265 gga->satellites,
00266 gga->quality,
00267 gga->hdop,
00268 gga->geoid);
00269 );
00270 }
00271
00275 void gprmc_callout(nmeap_context_t *context, void *data, void *user_data)
00276 {
00277 (void)context;
00278 (void)user_data;
00279 (void)data;
00280 LOG_INFOB(
00281 NmeaRmc *rmc = (NmeaRmc *)data;
00282
00283 LOG_INFO("Found GPRMC message %lu %c %ld %ld %d %d %d\n",
00284 rmc->time,
00285 rmc->warn,
00286 (long)rmc->latitude,
00287 (long)rmc->longitude,
00288 rmc->speed,
00289 rmc->course,
00290 rmc->mag_var);
00291 );
00292 }
00293
00297 void gpgsv_callout(nmeap_context_t *context, void *data, void *user_data)
00298 {
00299 (void)context;
00300 (void)user_data;
00301 (void)data;
00302 LOG_INFOB(
00303 NmeaGsv *gsv = (NmeaGsv *)data;
00304
00305 LOG_INFO("Found GPGSV message %d %d %d\n", gsv->tot_message, gsv->message_num, gsv->tot_svv);
00306
00307 for (int i = 0; i < 4; i++)
00308 LOG_INFO("%d %d %d %d\n", gsv->info[i].sv_prn, gsv->info[i].elevation, gsv->info[i].azimut, gsv->info[i].snr);
00309 );
00310 }
00311
00315 void gpvtg_callout(nmeap_context_t *context, void *data, void *user_data)
00316 {
00317 (void)context;
00318 (void)user_data;
00319 (void)data;
00320 LOG_INFOB(
00321 NmeaVtg *vtg = (NmeaVtg *)data;
00322 LOG_INFO("Found GPVTG message %d %d %d\n", vtg->track_good, vtg->knot_speed, vtg->km_speed);
00323 );
00324 }
00325
00326
00327
00331 int nmea_gpgga(nmeap_context_t *context, nmeap_sentence_t *sentence)
00332 {
00333
00334
00335
00336 NmeaGga *gga = (NmeaGga *)sentence->data;
00337
00338 ASSERT(gga);
00339 ASSERT(context->tokens >= 12);
00340
00341 gga->latitude = nmea_latitude(context->token[2],context->token[3]);
00342 gga->longitude = nmea_longitude(context->token[4],context->token[5]);
00343 gga->altitude = nmea_altitude(context->token[9],context->token[10]);
00344 gga->time = timestampToSec(tokenToInt(context->token[1], 3), 0);
00345 gga->satellites = atoi(context->token[7]);
00346 gga->quality = atoi(context->token[6]);
00347 gga->hdop = tokenToInt(context->token[8], 1);
00348 gga->geoid = nmea_altitude(context->token[11],context->token[12]);
00349
00350
00351
00352
00353
00354 if (sentence->callout != 0)
00355 (*sentence->callout)(context, gga, context->user_data);
00356
00357 return NMEA_GPGGA;
00358 }
00359
00363 int nmea_gprmc(nmeap_context_t *context, nmeap_sentence_t *sentence)
00364 {
00365
00366
00367
00368
00369 NmeaRmc *rmc = (NmeaRmc *)sentence->data;
00370
00371 ASSERT(rmc);
00372 ASSERT(context->tokens >= 10);
00373
00374
00375
00376
00377 rmc->time = timestampToSec(tokenToInt(context->token[1], 3), tokenToInt(context->token[9], 0));
00378 rmc->warn = *context->token[2];
00379 rmc->latitude = nmea_latitude(context->token[3],context->token[4]);
00380 rmc->longitude = nmea_longitude(context->token[5],context->token[6]);
00381 rmc->speed = atoi(context->token[7]);
00382 rmc->course = atoi(context->token[8]);
00383 rmc->mag_var = atoi(context->token[10]);
00384
00385 if (sentence->callout != 0)
00386 (*sentence->callout)(context, rmc, context->user_data);
00387
00388 return NMEA_GPRMC;
00389 }
00390
00391
00395 int nmea_gpvtg(nmeap_context_t *context, nmeap_sentence_t *sentence)
00396 {
00397
00398
00399
00400
00401 NmeaVtg *vtg = (NmeaVtg *)sentence->data;
00402
00403 ASSERT(vtg);
00404 ASSERT(context->tokens >= 7);
00405
00406
00407
00408
00409 vtg->track_good = atoi(context->token[1]);
00410 vtg->knot_speed = atoi(context->token[5]);
00411 vtg->km_speed = atoi(context->token[7]);
00412
00413
00414
00415
00416 if (sentence->callout != 0)
00417 (*sentence->callout)(context, vtg, context->user_data);
00418
00419 return NMEA_GPVTG;
00420 }
00421
00425 int nmea_gpgsv(nmeap_context_t *context, nmeap_sentence_t *sentence)
00426 {
00427
00428
00429
00430
00431 NmeaGsv *gsv = (NmeaGsv *)sentence->data;
00432
00433
00434
00435
00436
00437 gsv->tot_message = atoi(context->token[1]);
00438 gsv->message_num = atoi(context->token[2]);
00439 gsv->tot_svv = atoi(context->token[3]);
00440
00441
00442 int j = 0;
00443 for (int i = 4; i < context->tokens - 3; i += 4, j++)
00444 {
00445
00446 gsv->info[j].sv_prn = atoi(context->token[i]);
00447 gsv->info[j].elevation = atoi(context->token[i + 1]);
00448 gsv->info[j].azimut = atoi(context->token[i + 2]);
00449 gsv->info[j].snr = atoi(context->token[i + 3]);
00450 }
00451
00452
00453
00454
00455 if (sentence->callout != 0)
00456 (*sentence->callout)(context, gsv, context->user_data);
00457
00458 return NMEA_GPGSV;
00459 }
00460
00461
00462
00463
00464
00465 void nmea_poll(nmeap_context_t *context, KFile *channel)
00466 {
00467 int c;
00468 while ((c = kfile_getc(channel)) != EOF)
00469 {
00470 nmeap_parse(context, c);
00471 }
00472 }
00473