Skip to content

Commit

Permalink
Set the GPS device in raw mode and no delay, to cope with different G…
Browse files Browse the repository at this point in the history
…PS receivers behavior
  • Loading branch information
pascal-fb-martin committed Jan 20, 2020
1 parent adaed05 commit 91d01c5
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

OBJS= hc_db.o hc_http.o hc_clock.o hc_nmea.o hc_broadcast.o hc_ntp.o houseclock.o
OBJS= hc_db.o hc_http.o hc_clock.o hc_tty.o hc_nmea.o hc_broadcast.o hc_ntp.o houseclock.o

all: houseclock

Expand Down
20 changes: 11 additions & 9 deletions hc_nmea.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@
* -gps=<dev> Name of the system device to read the NMEA data from.
* -latency=<N> Delay between the GPS fix and the 1st sentence (ms).
* -burst Use burst start as the GPS fix timing reference.
* -baud=<N> GPS line baud speed.
*
* The default GPS device is /dev/ttyACM0.
* The default GPS device is /dev/ttyACM0. If no baud option is used,
* the default OS configuration is used.
*
* The latency depends on the GPS device. It can be estimated by using
* the options -drift and -latency=0, and then estimating the average
Expand Down Expand Up @@ -122,11 +124,11 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <termios.h>

#include "houseclock.h"
#include "hc_db.h"
#include "hc_clock.h"
#include "hc_tty.h"
#include "hc_nmea.h"

static int gpsLatency;
Expand All @@ -149,6 +151,7 @@ static int gpsTty = -1;
static int gpsUseBurst = 0;
static int gpsPrivacy = 0;
static int gpsShowNmea = 0;
static int gpsSpeed = 0;

static time_t gpsInitialized = 0;

Expand All @@ -157,9 +160,10 @@ static hc_nmea_status *hc_nmea_status_db = 0;
const char *hc_nmea_help (int level) {

static const char *nmeaHelp[] = {
" [-gps=DEV] [-latency=N] [-burst] [-privacy]",
" [-gps=DEV] [-baud=N] [-latency=N] [-burst] [-privacy]",
"-gps=DEV: device from which to read the NMEA data (/dev/ttyACM0).",
"-latency=N: delay between the GPS fix and the 1st NMEA sentence (70).",
"-baud=N: GPS device's baud speed (default: use OS default).",
"-show-nmea: trace NMEA sentences.",
"-burst: Use burst start as the GPS timing reference",
"-privacy: do not export location",
Expand Down Expand Up @@ -189,18 +193,21 @@ int hc_nmea_initialize (int argc, const char **argv) {

int i;
const char *latency_option = "70";
const char *speed_option = "0";

gpsDevice = "/dev/ttyACM0";
gpsUseBurst = 0;

for (i = 1; i < argc; ++i) {
hc_match ("-gps=", argv[i], &gpsDevice);
hc_match ("-baud=", argv[i], &speed_option);
hc_match ("-latency=", argv[i], &latency_option);
if (hc_present ("-burst", argv[i])) gpsUseBurst = 1;
if (hc_present ("-privacy", argv[i])) gpsPrivacy = 1;
if (hc_present ("-show-nmea", argv[i])) gpsShowNmea = 1;
}
gpsLatency = atoi(latency_option);
gpsSpeed = atoi(speed_option);

if (hc_nmea_status_db == 0) {
i = hc_db_new (HC_NMEA_STATUS, sizeof(hc_nmea_status), 1);
Expand All @@ -217,12 +224,7 @@ int hc_nmea_initialize (int argc, const char **argv) {

// Remove echo of characters from the GPS device.
if (gpsTty >= 0) {
struct termios options;
int status = tcgetattr(gpsTty, &options);
if (status == 0) {
options.c_lflag &= (~(ECHO+ECHONL));
tcsetattr(gpsTty, TCSANOW, &options);
}
hc_tty_set (gpsTty, gpsSpeed);
}

gpsInitialized = time(0);
Expand Down
112 changes: 112 additions & 0 deletions hc_tty.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* houseclock - A simple GPS Time Server with Web console
*
* Copyright 2019, Pascal Martin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*
* hc_tty.c - Handle setting up a TTY device.
*
* This module hides the TTY configuration's OS interface.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/termios.h>

#include "hc_tty.h"

int hc_tty_set (int fd, int baud) {

int speed;
struct termios settings;

if (! isatty(fd)) return 0; // No need to setup anything.

if (tcgetattr(fd,&settings) != 0) return errno;

// Optionally set the speed (if not 0). This is mostly useless with
// current USB GPS devices, but let's still allow it for special cases.

switch(baud) {
case 0: speed = B0; break;
case 50: speed = B50; break;
case 75: speed = B75; break;
case 110: speed = B110; break;
case 134: speed = B134; break;
case 150: speed = B150; break;
case 200: speed = B200; break;
case 300: speed = B300; break;
case 600: speed = B600; break;
case 1200: speed = B1200; break;
case 1800: speed = B1800; break;
case 2400: speed = B2400; break;
case 4800: speed = B4800; break;
case 9600: speed = B9600; break;
case 19200: speed = B19200; break;
case 38400: speed = B38400; break;
case 57600: speed = B57600; break;
case 115200: speed = B115200; break;
#ifdef B230400
case 230400: speed = B230400; break;
#endif
#ifdef B460800
case 460800: speed = B460800; break;
#endif
#ifdef B921600
case 921600: speed = B921600; break;
#endif
default: speed = B4800; break;
}

if (speed != B0) {
cfsetispeed(&settings, speed);
cfsetospeed(&settings, speed);
}

// Set the TTY as raw & non-blocking, 8 bits no parity, 1 stop bit,
// and VMIN = 0 and VTIME = 0 (return NMEA data as soon as received,
// so that the timing calculations means something).

memset(settings.c_cc, 0, sizeof(settings.c_cc));

settings.c_iflag = settings.c_oflag = settings.c_lflag = 0;

settings.c_cflag &= ~(CSTOPB | PARENB | PARODD | CRTSCTS | CSIZE);
settings.c_cflag |= (CREAD | CLOCAL | CS8);

if (tcsetattr(fd, TCSANOW, &settings) != 0) return errno;
if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & !O_NONBLOCK) != 0) return errno;

tcflush(fd, TCIOFLUSH);
return 0;
}

#ifdef TTY_TEST
int main (int argc, char **argv) {

hc_tty_set (open (argv[1], O_RDWR|O_NONBLOCK|O_NOCTTY), 4800);

// Just wait until killed.
for (;;) sleep(1);
}
#endif

24 changes: 24 additions & 0 deletions hc_tty.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* houseclock - A simple GPS Time Server with Web console
*
* Copyright 2019, Pascal Martin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*
* hc_tty.h - tty configuration's OS interface.
*/
int hc_tty_set (int fd, int baud);

0 comments on commit 91d01c5

Please sign in to comment.