int main(int argc, char **argv) { long long a, b, c; if (argc!=3 && argc!=4) { fprintf(stderr, "Usage: %s a [step] b\n", argv[0]); return 1; } a = getll(argv[1]); b = getll(argv[2]); if (argc==3) { c = b; b = 1; } else c = getll(argv[3]); if (!b) { fprintf(stderr, "Step cannot be 0\n"); return 3; } if (b<0) for (; a>=c; a+=b) out(a); else for (; a<=c; a+=b) out(a); return 0; }
// expects single null terminated strings (line ends dont matter) int getgpsinfo(char *buf) { char *c, *d; int i, fmax; c = buf; d = NULL; // required for pathologic cases of $GPABC...$GPXYZ...*ck // where $GPABC... resolves to zero for (;;) { // find last $ - start of NMEA c = strchr(c, '$'); if (!c) break; d = c; c++; } if (!d) return 0; // ignore all but standard NMEA if (*d != '$') return 0; if (d[1] != 'G') return 0; if (d[2] != 'P' && d[2] != 'N' && d[2] != 'L') return 0; c = d; c++; //verify checksum i = 0; while (*c && *c != '*') i ^= *c++; if (!*c || (unsigned) (i & 0xff) != strtoul(++c, NULL, 16)) { printf("Bad NMEA Checksum, calc'd %02x:\n %s", i, d); return -1; } --c; //null out asterisk *c = 0; c = d; //Split into fields at the commas fmax = 0; c += 2; char satype = *c++; // P,L,N for (;;) { field[fmax++] = c; c = strchr(c, ','); if (c == NULL) break; *c++ = 0; } //Latitude, Longitude, and other info if (fmax == 13 && !strcmp(field[0], "RMC")) { //NEED TO VERIFY FMAX FOR EACH if (field[2][0] != 'A') { if (gpst.lock) gpst.lock = 0; return 1; } else { if (!gpst.lock) gpst.lock = 1; gethms(1); getll(3); gpst.gspd = getndp(field[7], 3) * 1151 / 1000; //convert to MPH gpst.gtrk = getndp(field[8], 3); //Date, DDMMYY gpst.dy = get2(field[9]); gpst.mo = get2(&field[9][2]); gpst.yr = get2(&field[9][4]); // this will be slightly late if (!firstlock) writelock(); } } else if (fmax == 15 && (!strcmp(field[0], "GGA") || !strcmp(field[0], "GNS"))) { i = field[6][0] - '0'; // was gpst.lock, but it would prevent GPRMC alt if (!i) return 1; else if (gpst.lock != i) gpst.lock = i; // Redundant: getll(2); // don't get this here since it won't increment the YMD // and create a midnight bug // gethms(1); //7 - 2 plc Sats Used // 8 - HDOP gpst.hdop = getndp(field[8], 3); gpst.alt = getndp(field[9], 3); //9, 10 - Alt, units M } else if (fmax == 8 && !strcmp(field[0], "GLL")) { if (field[6][0] != 'A') { if (strlen(field[5])) gethms(5); if (gpst.lock) gpst.lock = 0; return 1; } if (!gpst.lock) gpst.lock = 1; getll(1); gethms(5); } else if (fmax == 10 && !strcmp(field[0], "VTG")) { gpst.gtrk = getndp(field[1], 3); gpst.gspd = getndp(field[5], 3) * 1151 / 1000; //convert to MPH } //Satellites and status else if (!(fmax & 3) && fmax >= 8 && fmax <= 20 && !strcmp(field[0], "GSV")) { int j, tot, seq; //should check (fmax % 4 == 3) tot = getndp(field[1], 0); seq = getndp(field[2], 0); if (satype == 'P') { if (seq == 1) for (j = 0; j < 65; j++) gpsat.view[j] = 0; gpsat.pnsats = getndp(field[3], 0); gpsat.psatset &= (1 << tot) - 1; gpsat.psatset &= ~(1 << (seq - 1)); } else { if (seq == 1) for (j = 65; j < 100; j++) gpsat.view[j] = 0; gpsat.lnsats = getndp(field[3], 0); gpsat.lsatset &= (1 << tot) - 1; gpsat.lsatset &= ~(1 << (seq - 1)); } for (j = 4; j < 20 && j < fmax; j += 4) { i = getndp(field[j], 0); if (!i) break; if (i > 119) // WAAS,EGNOS high numbering i -= 87; gpsat.view[i] = 1; gpsat.el[i] = getndp(field[j + 1], 0); gpsat.az[i] = getndp(field[j + 2], 0); gpsat.sn[i] = getndp(field[j + 3], 0); } int n; if (satype == 'P' && !gpsat.psatset) { gpst.pnsats = 0; gpst.pnused = 0; for (n = 0; n < 65; n++) { if (gpsat.view[n]) { int k = gpst.pnsats++; gpst.psats[k].num = n; gpst.psats[k].el = gpsat.el[n]; gpst.psats[k].az = gpsat.az[n]; gpst.psats[k].sn = gpsat.sn[n]; if (gpsat.used[n]) { gpst.pnused++; gpst.psats[k].num = -n; } else gpst.psats[k].num = n; } } } // else if (satype == 'L' && !gpsat.lsatset) { gpst.lnsats = 0; gpst.lnused = 0; for (n = 65; n < 99; n++) { if (gpsat.view[n]) { int k = gpst.lnsats++; gpst.lsats[k].num = n; gpst.lsats[k].el = gpsat.el[n]; gpst.lsats[k].az = gpsat.az[n]; gpst.lsats[k].sn = gpsat.sn[n]; if (gpsat.used[n]) { gpst.lnused++; gpst.lsats[k].num = -n; } else gpst.lsats[k].num = n; } } } } else if (fmax == 18 && !strcmp(field[0], "GSA")) { gpst.fix = getndp(field[2], 0); gpst.pdop = getndp(field[15], 3); gpst.hdop = getndp(field[16], 3); gpst.vdop = getndp(field[17], 3); int j = getndp(field[3], 0); if (j > 119) j -= 87; if (j && j < 65) { gpsat.psatset = 255; for (i = 0; i < 65; i++) gpsat.used[i] = 0; gpsat.pnused = 0; for (i = 3; i < 15; i++) { int k = getndp(field[i], 0); if (k > 119) k -= 87; if (k) { gpsat.used[k]++; gpsat.pnused++; } // else break;? } } if (j && j > 64) { gpsat.lsatset = 255; for (i = 65; i < 100; i++) gpsat.used[i] = 0; gpsat.lnused = 0; for (i = 3; i < 15; i++) { int k = getndp(field[i], 0); if (k > 119) k -= 87; if (k) { gpsat.used[k]++; gpsat.lnused++; } // else break;? } } } else printf("?%s\n", field[0]); return -1; }
// expects single null terminated strings (line ends dont matter) int getgpsinfo(int chan, char *buf, int msclock) { char *c, *d; int i, fmax; c = buf; d = NULL; // required for pathologic cases of $GPABC...$GPXYZ...*ck // where $GPABC... resolves to zero for (;;) { // find last $ - start of NMEA c = strchr(c, '$'); if (!c) break; d = c; c++; } if (!d) return 0; // ignore all but standard NMEA if (*d != '$') return 0; if (d[1] != 'G') return 0; if (d[2] != 'P' && d[2] != 'N' && d[2] != 'L') return 0; c = d; c++; //verify checksum i = 0; while (*c && *c != '*') i ^= *c++; if (!*c || (unsigned) (i & 0xff) != strtoul(++c, NULL, 16)) { fprintf(errfd, "Bad NMEA Checksum, calc'd %02x:\n %s", i, d); return -1; } --c; //null out asterisk *c = 0; c = d; //find and update timestamp for (cidx = 0; cidx < MAXSRC; cidx++) if (gpst[cidx].gpsfd == chan || gpst[cidx].gpsfd == -2) // found or EOL break; if (cidx == MAXSRC) // full, find empty or stale for (cidx = 0; cidx < MAXSRC; cidx++) if (gpst[cidx].gpsfd < 0 || (100000 + msclock - gpst[cidx].lastseen) % 100000 > 1250) break; gpst[cidx].gpsfd = chan; gpst[cidx].lastseen = msclock; //Split into fields at the commas fmax = 0; c += 2; char satype = *c++; // P,L,N for (;;) { field[fmax++] = c; c = strchr(c, ','); if (c == NULL) break; *c++ = 0; } //Latitude, Longitude, and other info if (fmax == 13 && !strcmp(field[0], "RMC")) { //NEED TO VERIFY FMAX FOR EACH if (field[2][0] != 'A') { if (gpst[cidx].lock) gpst[cidx].lock = 0; return 1; } else { if (!gpst[cidx].lock) gpst[cidx].lock = 1; gethms(1); getll(3); gpst[cidx].gspd = getndp(field[7], 3) * 1151 / 1000; //convert to MPH gpst[cidx].gtrk = getndp(field[8], 3); //Date, DDMMYY gpst[cidx].dy = get2(field[9]); gpst[cidx].mo = get2(&field[9][2]); gpst[cidx].yr = get2(&field[9][4]); // this will be slightly late if (!firstlock) writelock(); } } else if (fmax == 15 && (!strcmp(field[0], "GGA") || !strcmp(field[0], "GNS"))) { i = field[6][0] - '0'; // was gpst[cidx].lock, but it would prevent GPRMC alt if (!i) return 1; else if (gpst[cidx].lock != i) gpst[cidx].lock = i; // Redundant: getll(2); // don't get this here since it won't increment the YMD // and create a midnight bug // gethms(1); //7 - 2 plc Sats Used // 8 - HDOP gpst[cidx].hdop = getndp(field[8], 3); gpst[cidx].alt = getndp(field[9], 3); //9, 10 - Alt, units M } #if 0 // depend on RMC to avoid midnight bugs else if (fmax == 8 && !strcmp(field[0], "GLL")) { if (field[6][0] != 'A') { #if 0 // this will cause problems for the kml rotate if the time is wrong if (strlen(field[5])) gethms(5); #endif if (gpst[cidx].lock) gpst[cidx].lock = 0; return 1; } if (!gpst[cidx].lock) gpst[cidx].lock = 1; getll(1); gethms(5); } #endif #if 0 else if (fmax == 10 && !strcmp(field[0], "VTG")) { gpst[cidx].gtrk = getndp(field[1], 3); gpst[cidx].gspd = getndp(field[5], 3) * 1151 / 1000; //convert to MPH } #endif //Satellites and status else if (!(fmax & 3) && fmax >= 8 && fmax <= 20 && !strcmp(field[0], "GSV")) { int j, tot, seq; //should check (fmax % 4 == 3) tot = getndp(field[1], 0); seq = getndp(field[2], 0); if (satype == 'P') { if (seq == 1) for (j = 0; j < 65; j++) gpsat[cidx].view[j] = 0; gpsat[cidx].pnsats = getndp(field[3], 0); gpsat[cidx].psatset &= (1 << tot) - 1; gpsat[cidx].psatset &= ~(1 << (seq - 1)); } else { if (seq == 1) for (j = 65; j < 100; j++) gpsat[cidx].view[j] = 0; gpsat[cidx].lnsats = getndp(field[3], 0); gpsat[cidx].lsatset &= (1 << tot) - 1; gpsat[cidx].lsatset &= ~(1 << (seq - 1)); } for (j = 4; j < 20 && j < fmax; j += 4) { i = getndp(field[j], 0); if (!i) break; if (i > 119) // WAAS,EGNOS high numbering i -= 87; if (i > 100) i -= 46; //QZSS will be 60..64 gpsat[cidx].view[i] = 1; gpsat[cidx].el[i] = getndp(field[j + 1], 0); gpsat[cidx].az[i] = getndp(field[j + 2], 0); gpsat[cidx].sn[i] = getndp(field[j + 3], 0); } int n; if (satype == 'P' && !gpsat[cidx].psatset) { gpst[cidx].pnsats = 0; gpst[cidx].pnused = 0; for (n = 0; n < 65; n++) { if (gpsat[cidx].view[n]) { int k = gpst[cidx].pnsats++; gpst[cidx].psats[k].num = n; gpst[cidx].psats[k].el = gpsat[cidx].el[n]; gpst[cidx].psats[k].az = gpsat[cidx].az[n]; gpst[cidx].psats[k].sn = gpsat[cidx].sn[n]; if (gpsat[cidx].used[n]) { gpst[cidx].pnused++; gpst[cidx].psats[k].num = -n; } else gpst[cidx].psats[k].num = n; } } } // else if (satype == 'L' && !gpsat[cidx].lsatset) { gpst[cidx].lnsats = 0; gpst[cidx].lnused = 0; for (n = 65; n < 99; n++) { if (gpsat[cidx].view[n]) { int k = gpst[cidx].lnsats++; gpst[cidx].lsats[k].num = n; gpst[cidx].lsats[k].el = gpsat[cidx].el[n]; gpst[cidx].lsats[k].az = gpsat[cidx].az[n]; gpst[cidx].lsats[k].sn = gpsat[cidx].sn[n]; if (gpsat[cidx].used[n]) { gpst[cidx].lnused++; gpst[cidx].lsats[k].num = -n; } else gpst[cidx].lsats[k].num = n; } } } } else if (fmax == 18 && !strcmp(field[0], "GSA")) { gpst[cidx].fix = getndp(field[2], 0); gpst[cidx].pdop = getndp(field[15], 3); gpst[cidx].hdop = getndp(field[16], 3); gpst[cidx].vdop = getndp(field[17], 3); int j = getndp(field[3], 0); if (j > 119) j -= 87; if (j && j < 65) { gpsat[cidx].psatset = 255; for (i = 0; i < 65; i++) gpsat[cidx].used[i] = 0; gpsat[cidx].pnused = 0; for (i = 3; i < 15; i++) { int k = getndp(field[i], 0); if (k > 119) k -= 87; if (k) { gpsat[cidx].used[k]++; gpsat[cidx].pnused++; } // else break;? } } if (j && j > 64) { gpsat[cidx].lsatset = 255; for (i = 65; i < 100; i++) gpsat[cidx].used[i] = 0; gpsat[cidx].lnused = 0; for (i = 3; i < 15; i++) { int k = getndp(field[i], 0); if (k > 119) k -= 87; if (k) { gpsat[cidx].used[k]++; gpsat[cidx].lnused++; } // else break;? } } } #if 0 else printf("?%s\n", field[0]); #endif if (bestgps != cidx) return 1; if (!gpst[cidx].mo || !gpst[cidx].dy) return 1; // within 24 hours, only when gpst[cidx].lock since two unlocked GPS can have different times // only when sc < 30 to avoid bestgps jitter (5:00->4:59) causing a hiccup if (firstlock == 1 || (kmlinterval && gpst[cidx].lock && gpst[cidx].sc < 30 && kmmn != (gpst[cidx].hr * 60 + gpst[cidx].mn) / kmlinterval)) { firstlock = 2; kmmn = (gpst[cidx].hr * 60 + gpst[cidx].mn) / kmlinterval; rotatekml(); sprintf(currkml, "%02d%02d%02d%02d%02d%02d.kml", gpst[cidx].yr, gpst[cidx].mo, gpst[cidx].dy, gpst[cidx].hr, gpst[cidx].mn, gpst[cidx].sc); logfd = fopen(currkml, "w+b"); if (logfd) { symlink(currkml, "current.kml"); // this will fail on FAT fprintf(logfd, kmlhead, kmlname, gpst[cidx].llon / 1000000, abs(gpst[cidx].llon % 1000000), gpst[cidx].llat / 1000000, abs(gpst[cidx].llat % 1000000), gpst[cidx].gtrk / 1000, gpst[cidx].gtrk % 1000); fflush(logfd); } } if (kmlsc == gpst[cidx].sc && kmscth == gpst[cidx].scth) return 1; if (!gpst[cidx].llat && !gpst[cidx].llon) // time, but no location return 1; if (kmlsc != gpst[cidx].sc) { if (!kmlinterval || !logfd) return 1; kmlsc = gpst[cidx].sc; sprintf(&kmlstr[kmlful], pmarkfmt, gpst[cidx].llon / 1000000, abs(gpst[cidx].llon % 1000000), gpst[cidx].llat / 1000000, abs(gpst[cidx].llat % 1000000), gpst[cidx].gspd / 1000, gpst[cidx].gspd % 1000, // last point this second, first point next below. gpst[cidx].yr, gpst[cidx].mo, gpst[cidx].dy, gpst[cidx].hr, gpst[cidx].mn, gpst[cidx].sc); kmlful = strlen(kmlstr); } kmscth = gpst[cidx].scth; sprintf(&kmlstr[kmlful], "%d.%06d,%d.%06d,%d.%03d\n", gpst[cidx].llon / 1000000, abs(gpst[cidx].llon % 1000000), gpst[cidx].llat / 1000000, abs(gpst[cidx].llat % 1000000), gpst[cidx].gspd / 1000, gpst[cidx].gspd % 1000); kmlful = strlen(kmlstr); if (kmlful > BUFLEN / 2) dokmltail(); return 2; }