Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include "dat.h"

char *serial = "/dev/eia0";

int ttyfd, ctlfd, debug;
int baud = Baud;
char *baudstr = "b%dd1r1pns1l8i1w5";

Place where = {-(74.0 + 23.9191/60.0), 40.0 + 41.1346/60.0};

void    setline(void);
void    evermore80(Place, int);
void    evermore89(int);
void    evermore8e(void);

void
setline(void){
        char *serialctl;

        serialctl = smprint("%sctl", serial);
        if((ttyfd = open(serial, ORDWR)) < 0)
                sysfatal("%s: %r", serial);
        if((ctlfd = open(serialctl, OWRITE)) >= 0){
                if(fprint(ctlfd, baudstr, baud) < 0)
                        sysfatal("%s: %r", serialctl);
        }
        free(serialctl);
}

enum {
        GGAon = 0x01,
        GLLon = 0x02,
        GSAon = 0x04,
        GSVon = 0x08,
        RMCon = 0x10,
        VTGon = 0x20,
        CRCon = 0x40,
        EMTon = 0x80
};

char*
putbyte(char *s, int v)
{
        *s++ = v;
        if((v & 0xff) == 0x10)
                *s++ = v;
        return s;
}

char*
putshort(char *s, int v)
{
        s = putbyte(s, v);
        s = putbyte(s, v >> 8);
        return s;
}

char*
putlong(char *s, long v)
{
        s = putbyte(s, v);
        s = putbyte(s, v >> 8);
        s = putbyte(s, v >> 16);
        s = putbyte(s, v >> 24);
        return s;
}

void
evermoresend(char *body, int l)
{
        char buf[8], *s;
        int crc, i;

        s = buf;
        *s++ = 0x10;                    /* DCE */
        *s++ = 0x02;                    /* STX */
        s = putbyte(s, l);              /* length */
        write(ttyfd, buf, s-buf);       /* write header */

        write(ttyfd, body, l);          /* write body */

        crc = 0;
        for(i = 0; i < l; i++)
                crc += body[i];         /* calculate crc */
        s = buf;
        s = putbyte(s, crc);            /* checksum */
        *s++ = 0x10;                    /* DCE */
        *s++ = 0x03;                    /* ETX */
        write(ttyfd, buf, s-buf);       /* write trailer */
}

void
evermore80(Place pl, int baud)
{
        char buf[32], *s;
        long now, seconds, week;

        fprint(2, "Evermore80");

        time(&now);
        seconds = now - 315964800;
        week = (seconds / (7*24*3600));
        seconds = seconds %  (7*24*3600);
        s = buf;

        s = putbyte(s, 0x80);           /* message ID */
        s = putshort(s, week);          /* week number */
        s = putlong(s, seconds*100);    /* seconds */
        s = putshort(s, pl.lat*10.0);   /* latitude tenths degree */
        s = putshort(s, pl.lon*10.0);   /* longitude tenths degree */
        s = putshort(s, 100);           /* altitude meters */
        s = putshort(s, 0);             /* datumn ID */
        s = putbyte(s, 2);              /* warm start */
        s = putbyte(s, GGAon|GSAon|GSVon|RMCon|CRCon);
        switch(baud){
        case 4800:      s = putbyte(s, 0);      break;
        case 9600:      s = putbyte(s, 1);      break;
        case 19200:     s = putbyte(s, 2);      break;
        case 38400:     s = putbyte(s, 3);      break;
        default:
                sysfatal("Illegal baud rate");
        }

        evermoresend(buf, s - buf);
        fprint(2, "\n");
}

void
evermore89(int baud)
{
        char buf[32], *s;

        fprint(2, "Evermore89");
        s = buf;
        s = putbyte(s, 0x89);           /* message ID */
        s = putbyte(s, 0x01);           /* set main serial port */
        switch(baud){
        case  4800:     s = putbyte(s, 0x00);   break;
        case  9600:     s = putbyte(s, 0x01);   break;
        case 19200:     s = putbyte(s, 0x02);   break;
        case 38400:     s = putbyte(s, 0x03);   break;
        default:
                sysfatal("illegal baud rate %d", baud);
        }

        evermoresend(buf, s - buf);
        fprint(2, "\n");
}

void
evermore8e(void)
{
        char buf[32], *s;

        fprint(2, "Evermore8e");
        s = buf;
        s = putbyte(s, 0x8e);           /* message ID */
        s = putbyte(s, GGAon|GSAon|GSVon|RMCon);                /* all messages except GLL and VTG */
        s = putbyte(s, 0x01);           /* checksum on */
        s = putbyte(s, 0x01);           /* GGA update rate */
        s = putbyte(s, 0x0b);           /* GLL update rate */
        s = putbyte(s, 0x0a);           /* GSA update rate */
        s = putbyte(s, 0x14);           /* GSV update rate */
        s = putbyte(s, 0x08);           /* RMC update rate */
        s = putbyte(s, 0x0d);           /* VTG update rate */

        evermoresend(buf, s - buf);
        fprint(2, "\n");
}

void
main(int argc, char*argv[])
{
        char *p;
        Place pl;
        int newbaud;

        newbaud = -1;
        pl = nowhere;
        ARGBEGIN {
        default:
                fprint(2, "usage: %s [-b baud] [-d device] [-l longitude latitude] [-n newbaud]\n", argv0);
                exits("usage");
        case 'D':
                debug++;
                break;
        case 'b':
                baud = strtol(ARGF(), nil, 0);
                break;
        case 'd':
                serial = ARGF();
                break;
        case 'l':
                p = ARGF();
                if(strtolatlon(p, &p, &pl) < 0)
                        sysfatal("bad position");
                while(*p == ' ' || *p == '\t' || *p == '\n')
                        p++;
                if(*p == '\0')
                        p = ARGF();
                if (strtolatlon(p, &p, &pl) < 0)
                        sysfatal("bad position");
                while(*p == ' ' || *p == '\t' || *p == '\n')
                        p++;
                if(*p != '\0')
                        sysfatal("trailing gunk in position");
                where = pl;
                break;
        case 'n':
                newbaud = strtol(ARGF(), nil, 0);
                break;
        } ARGEND

        if(newbaud < 0)
                newbaud = baud;

        fmtinstall('L', placeconv);
        print("Initializing GPS to %d baud, at %L, time %s\n",
                newbaud, where, ctime(time(nil)));
        setline();
        evermore80(where, newbaud);
}