## Thursday, September 14, 2006

### 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:
`#include <sys/types.h>#include <stdio.>intmain(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>intmain(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.

#### 1 comment:

Manni said...

Hi John,

guess the C code needs a little bit of html escaping. At least the #include statements look a little odd.