Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_GPS/AP_GPS_NOVA.cpp
Views: 1798
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/1415// Novatel/Tersus/ComNav GPS driver for ArduPilot.16// Code by Michael Oborne17// Derived from http://www.novatel.com/assets/Documents/Manuals/om-20000129.pdf1819#include "AP_GPS.h"20#include "AP_GPS_NOVA.h"21#include <AP_Logger/AP_Logger.h>2223#if AP_GPS_NOVA_ENABLED2425extern const AP_HAL::HAL& hal;2627#define NOVA_DEBUGGING 02829#if NOVA_DEBUGGING30#include <cstdio>31# define Debug(fmt, args ...) \32do { \33printf("%s:%d: " fmt "\n", \34__FUNCTION__, __LINE__, \35## args); \36hal.scheduler->delay(1); \37} while(0)38#else39# define Debug(fmt, args ...)40#endif4142AP_GPS_NOVA::AP_GPS_NOVA(AP_GPS &_gps,43AP_GPS::Params &_params,44AP_GPS::GPS_State &_state,45AP_HAL::UARTDriver *_port) :46AP_GPS_Backend(_gps, _params, _state, _port)47{48nova_msg.nova_state = nova_msg_parser::PREAMBLE1;4950nova_msg.header.data[0] = NOVA_PREAMBLE1;51nova_msg.header.data[1] = NOVA_PREAMBLE2;52nova_msg.header.data[2] = NOVA_PREAMBLE3;5354if (gps._auto_config != AP_GPS::GPS_AUTO_CONFIG_DISABLE) {55const char *init_str = _initialisation_blob[0];56const char *init_str1 = _initialisation_blob[1];5758port->write((const uint8_t*)init_str, strlen(init_str));59port->write((const uint8_t*)init_str1, strlen(init_str1));60}61}6263const char* const AP_GPS_NOVA::_initialisation_blob[4] {64"\r\n\r\nunlogall\r\n", // cleanup enviroment65"log bestposb ontime 0.2 0 nohold\r\n",66"log bestvelb ontime 0.2 0 nohold\r\n",67"log psrdopb ontime 0.2 0 nohold\r\n",68};6970// Process all bytes available from the stream71//72bool73AP_GPS_NOVA::read(void)74{75if (gps._auto_config != AP_GPS::GPS_AUTO_CONFIG_DISABLE) {76const uint32_t now = AP_HAL::millis();7778if (_init_blob_index < (sizeof(_initialisation_blob) / sizeof(_initialisation_blob[0]))) {79const char *init_str = _initialisation_blob[_init_blob_index];8081if (now > _init_blob_time) {82port->write((const uint8_t*)init_str, strlen(init_str));83_init_blob_time = now + 200;84_init_blob_index++;85}86}87}8889bool ret = false;90for (uint16_t i=0; i<8192; i++) {91uint8_t temp;92if (!port->read(temp)) {93break;94}95#if AP_GPS_DEBUG_LOGGING_ENABLED96log_data(&temp, 1);97#endif98ret |= parse(temp);99}100101return ret;102}103104bool105AP_GPS_NOVA::parse(uint8_t temp)106{107switch (nova_msg.nova_state)108{109default:110case nova_msg_parser::PREAMBLE1:111if (temp == NOVA_PREAMBLE1) {112nova_msg.nova_state = nova_msg_parser::PREAMBLE2;113}114nova_msg.read = 0;115break;116case nova_msg_parser::PREAMBLE2:117if (temp == NOVA_PREAMBLE2) {118nova_msg.nova_state = nova_msg_parser::PREAMBLE3;119} else {120nova_msg.nova_state = nova_msg_parser::PREAMBLE1;121}122break;123case nova_msg_parser::PREAMBLE3:124if (temp == NOVA_PREAMBLE3) {125nova_msg.nova_state = nova_msg_parser::HEADERLENGTH;126} else {127nova_msg.nova_state = nova_msg_parser::PREAMBLE1;128}129break;130case nova_msg_parser::HEADERLENGTH:131Debug("NOVA HEADERLENGTH\n");132nova_msg.header.data[3] = temp;133nova_msg.header.nova_headeru.headerlength = temp;134nova_msg.nova_state = nova_msg_parser::HEADERDATA;135nova_msg.read = 4;136break;137case nova_msg_parser::HEADERDATA:138if (nova_msg.read >= sizeof(nova_msg.header.data)) {139Debug("parse header overflow length=%u\n", (unsigned)nova_msg.read);140nova_msg.nova_state = nova_msg_parser::PREAMBLE1;141break;142}143nova_msg.header.data[nova_msg.read] = temp;144nova_msg.read++;145if (nova_msg.read >= nova_msg.header.nova_headeru.headerlength) {146nova_msg.nova_state = nova_msg_parser::DATA;147}148break;149case nova_msg_parser::DATA:150if (nova_msg.read >= sizeof(nova_msg.data)) {151Debug("parse data overflow length=%u msglength=%u\n", (unsigned)nova_msg.read,nova_msg.header.nova_headeru.messagelength);152nova_msg.nova_state = nova_msg_parser::PREAMBLE1;153break;154}155nova_msg.data.bytes[nova_msg.read - nova_msg.header.nova_headeru.headerlength] = temp;156nova_msg.read++;157if (nova_msg.read >= (nova_msg.header.nova_headeru.messagelength + nova_msg.header.nova_headeru.headerlength)) {158Debug("NOVA DATA exit\n");159nova_msg.nova_state = nova_msg_parser::CRC1;160}161break;162case nova_msg_parser::CRC1:163nova_msg.crc = (uint32_t) (temp << 0);164nova_msg.nova_state = nova_msg_parser::CRC2;165break;166case nova_msg_parser::CRC2:167nova_msg.crc += (uint32_t) (temp << 8);168nova_msg.nova_state = nova_msg_parser::CRC3;169break;170case nova_msg_parser::CRC3:171nova_msg.crc += (uint32_t) (temp << 16);172nova_msg.nova_state = nova_msg_parser::CRC4;173break;174case nova_msg_parser::CRC4:175nova_msg.crc += (uint32_t) (temp << 24);176nova_msg.nova_state = nova_msg_parser::PREAMBLE1;177178uint32_t crc = crc_crc32((uint32_t)0, (uint8_t *)&nova_msg.header.data, (uint32_t)nova_msg.header.nova_headeru.headerlength);179crc = crc_crc32(crc, (uint8_t *)&nova_msg.data, (uint32_t)nova_msg.header.nova_headeru.messagelength);180181if (nova_msg.crc == crc) {182return process_message();183} else {184Debug("crc failed");185crc_error_counter++;186}187break;188}189190return false;191}192193bool194AP_GPS_NOVA::process_message(void)195{196const uint16_t messageid = nova_msg.header.nova_headeru.messageid;197198Debug("NOVA process_message messid=%u\n",messageid);199200check_new_itow(nova_msg.header.nova_headeru.tow, nova_msg.header.nova_headeru.messagelength + nova_msg.header.nova_headeru.headerlength);201202if (messageid == 42) // bestpos203{204const bestpos &bestposu = nova_msg.data.bestposu;205206state.time_week = nova_msg.header.nova_headeru.week;207state.time_week_ms = (uint32_t) nova_msg.header.nova_headeru.tow;208state.last_gps_time_ms = AP_HAL::millis();209210state.location.lat = (int32_t) (bestposu.lat * (double)1e7);211state.location.lng = (int32_t) (bestposu.lng * (double)1e7);212state.have_undulation = true;213state.undulation = bestposu.undulation;214set_alt_amsl_cm(state, bestposu.hgt * 100);215216state.num_sats = bestposu.svsused;217218state.horizontal_accuracy = norm(bestposu.latsdev, bestposu.lngsdev);219state.vertical_accuracy = (float) bestposu.hgtsdev;220state.have_horizontal_accuracy = true;221state.have_vertical_accuracy = true;222state.rtk_age_ms = bestposu.diffage * 1000;223state.rtk_num_sats = bestposu.svsused;224225if (bestposu.solstat == 0) // have a solution226{227switch (bestposu.postype)228{229case 16:230state.status = AP_GPS::GPS_OK_FIX_3D;231break;232case 17: // psrdiff233case 18: // waas234case 20: // omnistar235case 68: // ppp_converg236case 69: // ppp237state.status = AP_GPS::GPS_OK_FIX_3D_DGPS;238break;239case 32: // l1 float240case 33: // iono float241case 34: // narrow float242state.status = AP_GPS::GPS_OK_FIX_3D_RTK_FLOAT;243break;244case 48: // l1 int245case 50: // narrow int246state.status = AP_GPS::GPS_OK_FIX_3D_RTK_FIXED;247break;248case 0: // NONE249case 1: // FIXEDPOS250case 2: // FIXEDHEIGHT251default:252state.status = AP_GPS::NO_FIX;253break;254}255} else {256state.status = AP_GPS::NO_FIX;257}258259_new_position = true;260}261262if (messageid == 99) // bestvel263{264const bestvel &bestvelu = nova_msg.data.bestvelu;265266state.ground_speed = (float) bestvelu.horspd;267state.ground_course = (float) bestvelu.trkgnd;268fill_3d_velocity();269state.velocity.z = -(float) bestvelu.vertspd;270state.have_vertical_velocity = true;271272_last_vel_time = (uint32_t) nova_msg.header.nova_headeru.tow;273_new_speed = true;274}275276if (messageid == 174) // psrdop277{278const psrdop &psrdopu = nova_msg.data.psrdopu;279280state.hdop = (uint16_t) (psrdopu.hdop*100);281state.vdop = (uint16_t) (psrdopu.htdop*100);282return false;283}284285// ensure out position and velocity stay insync286if (_new_position && _new_speed && _last_vel_time == state.time_week_ms) {287_new_speed = _new_position = false;288289return true;290}291292return false;293}294295#endif296297298