Index: configure.ac =================================================================== --- configure.ac (revision 4804) +++ configure.ac (working copy) @@ -409,6 +409,21 @@ AC_MSG_RESULT([no]) fi +dnl check for OceanServer support +AC_ARG_ENABLE(oceanserver, + AC_HELP_STRING([--enable-oceanserver], + [enable OceanServer support]), + [ac_oceanserver=$enableval], [ac_oceanserver=no]) +AC_MSG_CHECKING([for OceanServer support]) +if test x"$ac_oceanserver" = "xyes"; then + ac_nmea=yes + AC_MSG_RESULT([yes]) + AC_DEFINE([OCEANSERVER_ENABLE], 1, [OceanServer support]) + AC_DEFINE([NMEA_ENABLE], 1, [OceanServer requires NMEA support]) +else + AC_MSG_RESULT([no]) +fi + dnl check for UBX support AC_ARG_ENABLE(ubx, AC_HELP_STRING([--disable-ubx], @@ -759,6 +774,7 @@ echo "Trimble TSIP : $ac_tsip" echo "Tripmate : $ac_tripmate" echo "True North : $ac_tnt" +echo "OceanServer : $ac_oceanserver" echo "UBX : $ac_ubx" echo "GPSclock : $ac_gpsclock" dnl Below this line are non-protocol switches @@ -793,6 +809,7 @@ x"$ac_rtcm104v2" = "xno" -a \ x"$ac_sirf" = "xno" -a \ x"$ac_tnt" = "xno" -a \ + x"$ac_oceanserver" = "xno" -a \ x"$ac_tripmate" = "xno" -a \ x"$ac_tsip" = "xno" -a \ x"$ac_ubx" = "xno"; then Index: drivers.c =================================================================== --- drivers.c (revision 4804) +++ drivers.c (working copy) @@ -737,6 +737,153 @@ .cycle = 20, /* updates per second */ }; #endif +#ifdef OCEANSERVER_ENABLE +/************************************************************************** + * OceanServer - Digital Compass, OS5000 Series + * + * More info: http://www.ocean-server.com/download/OS5000_Compass_Manual.pdf + * + * This is a digital compass which uses magnetometers to measure the + * strength of the earth's magnetic field. Based on these measurements + * it provides a compass heading using NMEA formatted output strings. + * This is useful to supplement the heading provided by another GPS + * unit. A GPS heading is unreliable at slow speed or no speed. + * + **************************************************************************/ + +enum { +#include "packet_states.h" +}; + +static int oceanserver_send(int fd, const char *fmt, ... ) +{ + int status; + char buf[BUFSIZ]; + va_list ap; + + va_start(ap, fmt) ; + (void)vsnprintf(buf, sizeof(buf)-5, fmt, ap); + va_end(ap); + strlcat(buf, "", BUFSIZ); + status = (int)write(fd, buf, strlen(buf)); + tcdrain(fd); + if (status == (int)strlen(buf)) { + gpsd_report(LOG_IO, "=> GPS: %s\n", buf); + return status; + } else { + gpsd_report(LOG_WARN, "=> GPS: %s FAILED\n", buf); + return -1; + } +} + +#ifdef ALLOW_RECONFIGURE +static void oceanserver_configure(struct gps_device_t *session, unsigned int seq) +{ + if (seq == 0){ + (void)oceanserver_send(session->gpsdata.gps_fd, "2\n"); + (void)oceanserver_send(session->gpsdata.gps_fd, "X4096 "); + } +} +#endif /* ALLOW_RECONFIGURE */ + +#define OCEANSERVER_SNIFF_RETRIES 100 + +static int oceanserver_packet_sniff(struct gps_device_t *session) +{ + unsigned int n, count = 0; + + gpsd_report(LOG_RAW, "oceanserver_packet_sniff begins\n"); + for (n = 0; n < OCEANSERVER_SNIFF_RETRIES; n++) + { + count = 0; + (void)oceanserver_send(session->gpsdata.gps_fd, "V\n"); + if (ioctl(session->gpsdata.gps_fd, FIONREAD, &count) < 0) + return BAD_PACKET; + if (count == 0) { + //int delay = 10000000000.0 / session->gpsdata.baudrate; + //gpsd_report(LOG_RAW, "usleep(%d)\n", delay); + //usleep(delay); + gpsd_report(LOG_RAW, "sleep(1)\n"); + (void)sleep(1); + } else if (generic_get(session) >= 0) { + if((session->packet.type == NMEA_PACKET)&&(session->packet.state == NMEA_RECOGNIZED)) + { + gpsd_report(LOG_RAW, "oceanserver_packet_sniff returns %d\n",session->packet.type); + return session->packet.type; + } + } + } + + gpsd_report(LOG_RAW, "oceanserver_packet_sniff found no packet\n"); + return BAD_PACKET; +} + +/* + * The OceanServer compass has different output modes + * we would like to make it talk in a NMEA like protocol + */ +static bool oceanserver_probe(struct gps_device_t *session) +{ + unsigned int *ip; +#ifdef FIXED_PORT_SPEED + /* just the one fixed port speed... */ + static unsigned int rates[] = {FIXED_PORT_SPEED}; +#else /* FIXED_PORT_SPEED not defined */ + /* The supported baud rates */ + static unsigned int rates[] = {4800, 9600, 14400, 19200, 38400, 57600, 115200 }; +#endif /* FIXED_PORT_SPEED defined */ + + gpsd_report(LOG_PROG, "Probing OceanServer Compass\n"); + + /* + * Only block until we get at least one character, whatever the + * third arg of read(2) says. + */ + /*@ ignore @*/ + memset(session->ttyset.c_cc,0,sizeof(session->ttyset.c_cc)); + session->ttyset.c_cc[VMIN] = 1; + /*@ end @*/ + + session->ttyset.c_cflag &= ~(PARENB | PARODD | CRTSCTS); + session->ttyset.c_cflag |= CREAD | CLOCAL; + session->ttyset.c_iflag = session->ttyset.c_oflag = session->ttyset.c_lflag = (tcflag_t) 0; + + session->baudindex = 0; + for (ip = rates; ip < rates + sizeof(rates)/sizeof(rates[0]); ip++) + if (ip == rates || *ip != rates[0]) + { + gpsd_report(LOG_PROG, "hunting at speed %d\n", *ip); + gpsd_set_speed(session, *ip, 'N',1); + if (oceanserver_packet_sniff(session) != BAD_PACKET) + return true; + } + return false; +} + +struct gps_type_t oceanServer = { + .type_name = "OceanServer Digital Compas OS5000", /* full name of type */ + .trigger = " OS5000", + .channels = 0, /* not an actual GPS at all */ + .probe_wakeup = NULL, /* this will become a real method */ + .probe_detect = oceanserver_probe,/* probe by sending ID query */ + .probe_subtype = NULL, /* probe for True North Digital Compass */ +#ifdef ALLOW_RECONFIGURE + .configurator = oceanserver_configure, /* no setting changes */ +#endif /* ALLOW_RECONFIGURE */ + .get_packet = generic_get, /* how to get a packet */ + .parse_packet = nmea_parse_input, /* how to interpret a packet */ + .rtcm_writer = NULL, /* Don't send */ + .speed_switcher = NULL, /* no speed switcher */ + .mode_switcher = NULL, /* no mode switcher */ + .rate_switcher = NULL, /* no wrapup */ + .cycle_chars = -1, /* not relevant, no rate switch */ +#ifdef ALLOW_RECONFIGURE + .revert = NULL, /* no setting-reversion method */ +#endif /* ALLOW_RECONFIGURE */ + .wrapup = NULL, /* no wrapup */ + .cycle = 20, /* updates per second */ +}; +#endif #ifdef RTCM104V2_ENABLE /************************************************************************** * @@ -912,6 +1059,9 @@ #ifdef TNT_ENABLE &trueNorth, #endif /* TSIP_ENABLE */ +#ifdef OCEANSERVER_ENABLE + &oceanServer, +#endif /* OCEANSERVER_ENABLE */ #ifdef EVERMORE_ENABLE &evermore_binary, #endif /* EVERMORE_ENABLE */ Index: nmea_parse.c =================================================================== --- nmea_parse.c (revision 4804) +++ nmea_parse.c (working copy) @@ -599,6 +599,65 @@ } #endif /* TNT_ENABLE */ +#ifdef OCEANSERVER_ENABLE +static gps_mask_t processOHPR(int c UNUSED, char *field[], struct gps_device_t *session) +{ + /* + * Proprietary sentence for OceanServer Magnetic Compass. + + OHPR,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x*hh + Fields in order: + 1. Azimuth + 2. Pitch Angle + 3. Roll Angle + 4. Temperature + 5. Depth (feet) + 6. Magnetic Vector Length + 7-9. 3 axis Magnetic Field readings x,y,z + 10. Acceleration Vector Length + 11-13. 3 axis Acceleration Readings x,y,z + 14. Reserved + 15-16. 2 axis Gyro Output, X,y + 17. Reserved + 18. Reserved + *hh mandatory nmea_checksum + */ + gps_mask_t mask; + mask = ONLINE_SET; + + //gpsd_zero_satellites(&session->gpsdata); + + /* + * Heading maps to track. + * Pitch maps to climb. + * Roll maps to speed. + * Depth maps to altitude. + */ + session->gpsdata.fix.time = timestamp(); + session->gpsdata.fix.track = atof(field[1]); + session->gpsdata.fix.climb = atof(field[2]); + session->gpsdata.fix.speed = atof(field[3]); + session->gpsdata.temperature = atof(field[4]); + session->gpsdata.fix.altitude = atof(field[5]); + session->gpsdata.magnetic_length = atof(field[6]); + session->gpsdata.magnetic_field_x = atof(field[7]); + session->gpsdata.magnetic_field_y = atof(field[8]); + session->gpsdata.magnetic_field_z = atof(field[9]); + session->gpsdata.acceleration_length = atof(field[10]); + session->gpsdata.acceleration_field_x = atof(field[11]); + session->gpsdata.acceleration_field_y = atof(field[12]); + session->gpsdata.acceleration_field_z = atof(field[13]); + session->gpsdata.gyro_output_x = atof(field[15]); + session->gpsdata.gyro_output_y = atof(field[16]); + session->gpsdata.fix.mode = MODE_3D; + mask |= (STATUS_SET | MODE_SET | TRACK_SET | SPEED_SET | CLIMB_SET | ALTITUDE_SET); + session->gpsdata.status = STATUS_FIX; /* could be DGPS_FIX */ + + gpsd_report(LOG_RAW, "Heading %lf.\n", session->gpsdata.fix.track); + return mask; +} +#endif /* OCEANSERVER_ENABLE */ + #ifdef ASHTECH_ENABLE static gps_mask_t processPASHR(int c UNUSED, char *field[], struct gps_device_t *session) { @@ -705,7 +764,10 @@ #endif /* TNT_ENABLE */ #ifdef ASHTECH_ENABLE {"PASHR", 3, processPASHR}, /* general handler for Ashtech */ -#endif /* TNT_ENABLE */ +#endif /* ASHTECH_ENABLE */ +#ifdef OCEANSERVER_ENABLE + {"OHPR", 18, processOHPR}, +#endif /* OCEANSERVER_ENABLE */ }; volatile unsigned char buf[NMEA_MAX+1]; Index: gps.h =================================================================== --- gps.h (revision 4804) +++ gps.h (working copy) @@ -531,12 +531,28 @@ #define SAT_FIX_USED 0x40 /* used for position fix */ #endif +#ifdef TNT_ENABLE /* compass status -- TrueNorth (and any similar) devices only */ char headingStatus; char pitchStatus; char rollStatus; double horzField; /* Magnitude of horizontal magnetic field */ +#endif +#ifdef OCEANSERVER_ENABLE + double magnetic_length; /* unitvector sqrt(x^2 + y^2 +z^2) */ + double magnetic_field_x; + double magnetic_field_y; + double magnetic_field_z; + double acceleration_length; /* unitvector sqrt(x^2 + y^2 +z^2) */ + double acceleration_field_x; + double acceleration_field_y; + double acceleration_field_z; + double gyro_output_x; + double gyro_output_y; + double temperature; +#endif + /* where and what gpsd thinks the device is */ char gps_device[PATH_MAX]; /* only valid if non-null. */ char *gps_id; /* only valid if non-null. */