A C implementation of my simple GPS code
Reader Chris Kuethe wrote in with a version of my simple code for entering latitude and longitude to GPS devices written in C (my demonstration code was in Perl).
Seems Chris is a bit of a GPS fanatic and maintains a page on GPS hackery.
He ported my Perl code to C and is releasing the code freely. He gave me the choice of releasing under two clause BSD license or making it public domain. I think the most generous is public domain (especially since the Perl code was public domain).
Here's the code to compute a SOC:
And to compute latitude and longitude from a SOC:
Thanks Chris!
Update: Chris writes to say that B1NLADEN02 can be found in Antarctica: -76.7847/-106.0187 and JIMMYHOFFA is here: -23.3433/-61.6087.
Seems Chris is a bit of a GPS fanatic and maintains a page on GPS hackery.
He ported my Perl code to C and is releasing the code freely. He gave me the choice of releasing under two clause BSD license or making it public domain. I think the most generous is public domain (especially since the Perl code was public domain).
Here's the code to compute a SOC:
#include <sys/types.h>
#include <stdio.>
int
main(int argc, char **argv){
int i, j;
unsigned long long lat, lon, c, p, soc_num;
char soc[11], *alpha = "ABCDEFGHJKLMNPQRTUVWXY0123456789";
int primes[] = { 2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37 };
float f;
if (argc != 3){
printf("Usage: %s <lat> <lon>\n", argv[0]);
exit(1);
}
sscanf(argv[1], "%f", &f);
lat = (int)((f + 90.0) * 10000.0);
sscanf(argv[2], "%f", &f);
lon = (int)((f +180.0) * 10000.0);
p = lat * 3600000 + lon;
soc_num = p * 128;
c = 0;
for(i = 0; i < (sizeof(primes)/sizeof(primes[0])); i++){
c += ((p % 32) * primes[i]);
p /= 32;
}
c %= 127;
soc_num += c;
for(i = 9; i >= 0; i--){
j = soc_num % 32;
soc[i] = alpha[j];
soc_num /= 32;
}
soc[10] = '\0';
printf("%s\n", soc);
}
And to compute latitude and longitude from a SOC:
#include <sys/types.h>
#include <stdio.h>
int
main(int argc, char **argv){
int i, j, c, k;
unsigned long long x, y, p, soc_num;
char soc[11], *alpha = "ABCDEFGHJKLMNPQRTUVWXY0123456789";
int primes[] = { 2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37 };
float lat, lon;
if ((argc != 2 )|| (strlen(argv[1]) != 10)){
printf("Usage: %s <10-digit-SOC>\n", argv[0]);
exit(1);
}
soc_num = 0;
for (i = 0; i < 10; i++){
c = (char)argv[1][i];
c = c & 0xff;
c = toupper(c);
switch(c){
case 'I': c = '1'; break;
case 'O': c = '0'; break;
case 'S': c = '5'; break;
case 'Z': c = '2'; break;
default: ;
}
for (j = 0; j < strlen(alpha); j++)
if (c == alpha[j]){
soc_num = (soc_num * 32 + j);
}
}
p = soc_num / 128;
k = soc_num % 128;
lon = ((p % 3600000) / 10000.0) -180.0;
lat = ((p / 3600000) / 10000.0) - 90.0;
c = 0;
for (i = 0; i < (sizeof(primes)/sizeof(primes[0])); i++){
c += ((p % 32) * primes[i]);
p /= 32;
}
c %= 127;
if (c != k)
printf("warning: checksum mismatch - %d %d\n", c, k);
printf("%0.4f %0.4f\n", lat, lon);
}
Thanks Chris!
Update: Chris writes to say that B1NLADEN02 can be found in Antarctica: -76.7847/-106.0187 and JIMMYHOFFA is here: -23.3433/-61.6087.
Labels: my services





1 Comments:
Hi John,
guess the C code needs a little bit of html escaping. At least the #include statements look a little odd.
Post a Comment
Links to this post:
Create a Link
<< Home