Revert "AP_GPS: GSOF robust config parsing"

This reverts commit bf9881579c.
This commit is contained in:
Peter Barker 2023-11-28 16:02:44 +11:00 committed by Peter Barker
parent 8b7652d1db
commit 2e41cf810c
2 changed files with 40 additions and 202 deletions

View File

@ -36,15 +36,12 @@
extern const AP_HAL::HAL& hal;
// Set this to 1 to enable debug messages
#define gsof_DEBUGGING 0
#if gsof_DEBUGGING
# define Debug(fmt, args ...) \
do { \
hal.console->printf("%u %s:%s:%d: " fmt "\n", \
AP_HAL::millis(), \
__FILE__, \
hal.console->printf("%s:%d: " fmt "\n", \
__FUNCTION__, __LINE__, \
## args); \
hal.scheduler->delay(1); \
@ -70,10 +67,10 @@ AP_GPS_GSOF::AP_GPS_GSOF(AP_GPS &_gps, AP_GPS::GPS_State &_state,
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "GSOF instance %d has invalid COM port setting of %d", state.instance, com_port);
return;
}
const HW_Baud baud = HW_Baud::BAUD115K;
// Start by disabling output during config
[[maybe_unused]] const auto output_disabled = disableOutput(static_cast<HW_Port>(com_port));
is_baud_configured = requestBaud(static_cast<HW_Port>(com_port), baud);
requestBaud(static_cast<HW_Port>(com_port));
const uint32_t now = AP_HAL::millis();
gsofmsg_time = now + 110;
}
// Process all bytes available from the stream
@ -81,27 +78,19 @@ AP_GPS_GSOF::AP_GPS_GSOF(AP_GPS &_gps, AP_GPS::GPS_State &_state,
bool
AP_GPS_GSOF::read(void)
{
if (!is_baud_configured) {
// Debug("Baud not configured, not ready to read()");
return false;
}
const uint32_t now = AP_HAL::millis();
bool gsof_configured = true;
static_assert(sizeof(gsofmsgreq) != 0, "gsofmsgreq is not empty");
while (gsofmsgreq_index < (sizeof(gsofmsgreq))) {
if (gsofmsgreq_index < (sizeof(gsofmsgreq))) {
const auto com_port = gps._com_port[state.instance].get();
if (!validate_com_port(com_port)) {
// The user parameter for COM port is not a valid GSOF port
return false;
}
gsof_configured &= requestGSOF(gsofmsgreq[gsofmsgreq_index], static_cast<HW_Port>(com_port), Output_Rate::FREQ_10_HZ);
gsofmsgreq_index++;
}
if (!gsof_configured) {
Debug("Failed to requestGSOF()");
return false;
if (now > gsofmsg_time) {
requestGSOF(gsofmsgreq[gsofmsgreq_index], static_cast<HW_Port>(com_port), Output_Rate::FREQ_10_HZ);
gsofmsg_time = now + 110;
gsofmsgreq_index++;
}
}
bool ret = false;
@ -172,152 +161,46 @@ AP_GPS_GSOF::parse(const uint8_t temp)
return false;
}
bool
AP_GPS_GSOF::requestBaud(const HW_Port portIndex, const HW_Baud baudRate)
void
AP_GPS_GSOF::requestBaud(const HW_Port portindex)
{
Debug("Requesting baud on port %u", (uint8_t)portIndex);
// GSOF is supported on the following bauds:
// 2400, 4800, 9600, 19200, 38400, 115200, 230400
// This packet is not documented in the API.
uint8_t buffer[19] = {0x02,0x00,0x64,0x0d,0x00,0x00,0x00, // application file record
0x03, 0x00, 0x01, 0x00, // file control information block
0x02, 0x04, static_cast<uint8_t>(portIndex), static_cast<uint8_t>(baudRate), 0x00,0x00, // serial port baud format
0x02, 0x04, static_cast<uint8_t>(portindex), 0x07, 0x00,0x00, // serial port baud format
0x00,0x03
};
}; // checksum
populateOutgoingTransNumber(buffer);
populateChecksum(buffer, sizeof(buffer));
buffer[4] = packetcount++;
return requestResponse(buffer, sizeof(buffer));
uint8_t checksum = 0;
for (uint8_t a = 1; a < (sizeof(buffer) - 1); a++) {
checksum += buffer[a];
}
buffer[17] = checksum;
port->write((const uint8_t*)buffer, sizeof(buffer));
}
bool
void
AP_GPS_GSOF::requestGSOF(const uint8_t messageType, const HW_Port portIndex, const Output_Rate rateHz)
{
Debug("Requesting gsof #%u on port %u", messageType, (uint8_t)portIndex);
// This packet is not documented in the API.
uint8_t buffer[21] = {0x02,0x00,0x64,0x0f,0x00,0x00,0x00, // application file record
0x03,0x00,0x01,0x00, // file control information block
0x07,0x06,0x0a,static_cast<uint8_t>(portIndex),static_cast<uint8_t>(rateHz),0x00,messageType,0x00, // output message record
0x00,0x03
};
}; // checksum
populateOutgoingTransNumber(buffer);
populateChecksum(buffer, sizeof(buffer));
buffer[4] = packetcount++;
return requestResponse(buffer, sizeof(buffer));
}
bool
AP_GPS_GSOF::disableOutput(const HW_Port portIndex) {
Debug("Disabling output on on port %u", (uint8_t)portIndex);
switch(portIndex) {
case HW_Port::COM1:
{
constexpr uint8_t cmd[8] = {
STX,
0x00,
0x51,
0x02,
0x0A,
0x01,
0x5E,
ETX
};
// The checksum is hard-coded.
// No need to calculate it.
return requestResponse(cmd, sizeof(cmd));
}
case HW_Port::COM2:
{
constexpr uint8_t cmd[8] = {
STX,
0x00,
0x51,
0x02,
0x0A,
0x02,
0x5F,
ETX
};
return requestResponse(cmd, sizeof(cmd));
}
}
return false;
}
bool
AP_GPS_GSOF::requestResponse(const uint8_t* buf, const uint8_t len) {
if (!port->is_initialized()) {
Debug("Port not initialized");
return false;
}
for (int attempt = 0; attempt <= configuration_attempts; attempt++) {
// Clear input buffer before doing configuration
if (!port->discard_input()) {
Debug("Failed to discard input");
return false;
};
port->write((const uint8_t*)buf, len);
constexpr uint16_t expected_bytes = 1;
// TODO use wait_timeout instead once HAL_SITL has it implemented.
const auto start_wait = AP_HAL::millis();
auto now = start_wait;
while (now - start_wait <= configuration_wait_time_ms) {
if (port->available() >= expected_bytes) {
break;
}
constexpr uint16_t delay_us = 100;
hal.scheduler->delay_microseconds(delay_us);
now = AP_HAL::millis();
}
const auto available_bytes = port->available();
if (available_bytes != expected_bytes) {
Debug("Didn't get expected bytes, got %u bytes back", available_bytes);
return false;
}
uint8_t resp_code;
if(port->read(resp_code) && resp_code == ACK) {
Debug("Got ack");
return true;
} else {
Debug("Didn't get ACK, got 0x%02x", resp_code);
}
}
return false;
}
void
AP_GPS_GSOF::populateChecksum(uint8_t* buf, const uint8_t len)
{
// The buffer is of size len.
// If ETX is not element buf[len-1], the buf/len numbers are wrong.
// Same problem if the len is too small for a valid packet.
if (len <= 3 || buf[len - 1] != ETX) {
return;
}
// The checksum field is at buf[len - 2]
uint8_t checksum = 0;
const uint8_t payload_size = len - 2;
for (uint8_t i = 1; i < payload_size; i++) {
checksum += buf[i];
for (uint8_t a = 1; a < (sizeof(buffer) - 1); a++) {
checksum += buffer[a];
}
buf[len -2] = checksum;
}
buffer[19] = checksum;
void
AP_GPS_GSOF::populateOutgoingTransNumber(uint8_t* buf) {
buf[4] = packetOutboundTransNumber++;
port->write((const uint8_t*)buffer, sizeof(buffer));
}
double
@ -376,7 +259,6 @@ AP_GPS_GSOF::process_message(void)
if (msg.packettype == 0x40) { // GSOF
// https://receiverhelp.trimble.com/oem-gnss/index.html#GSOFmessages_TIME.html?TocPath=Output%2520Messages%257CGSOF%2520Messages%257C_____25
#if gsof_DEBUGGING
//trans_number is functionally the sequence number.
const uint8_t trans_number = msg.data[0];
const uint8_t pageidx = msg.data[1];
const uint8_t maxpageidx = msg.data[2];
@ -478,16 +360,6 @@ AP_GPS_GSOF::process_message(void)
return false;
}
bool
AP_GPS_GSOF::validate_baud(const uint8_t baud) const {
switch(baud) {
case static_cast<uint8_t>(HW_Baud::BAUD230K):
case static_cast<uint8_t>(HW_Baud::BAUD115K):
return true;
default:
return false;
}
}
bool
AP_GPS_GSOF::validate_com_port(const uint8_t com_port) const {
switch(com_port) {

View File

@ -16,7 +16,6 @@
//
// Trimble GPS driver for ArduPilot.
// Code by Michael Oborne
// Maintained by Ryan Friedman
// https://receiverhelp.trimble.com/oem-gnss/index.html#Welcome.html?TocPath=_____1
#pragma once
@ -57,35 +56,17 @@ private:
FREQ_100_HZ = 16,
};
// A subset of the supported baud rates in the GSOF protocol that are useful.
// These values are not documented in the API.
// The matches the GPS_GSOF_BAUD parameter.
enum class HW_Baud {
BAUD115K = 0x07,
BAUD230K = 0x0B,
};
bool parse(const uint8_t temp) WARN_IF_UNUSED;
bool process_message() WARN_IF_UNUSED;
// Send a request to the GPS to configure its baud rate on a certain (serial) port.
// Note - these request functions expect an ACK from the device.
// If the device is already sending serial traffic, there is no mechanism to prevent this.
// According to the manufacturer, the best approach is to switch to ethernet.
// Use one port for configuration data and another for stream data to prevent conflict.
// Because there is only one TTL serial interface exposed, the approach here is using retry logic.
bool requestBaud(const HW_Port portIndex, const HW_Baud baudRate) WARN_IF_UNUSED;
// Send a request to the GPS to enable a message type on the port.
bool requestGSOF(const uint8_t messageType, const HW_Port portIndex, const Output_Rate rateHz) WARN_IF_UNUSED;
bool disableOutput(const HW_Port portIndex) WARN_IF_UNUSED;
// Generic handler for sending command and checking return code.
// Make sure to disableOutput() before doing configuration.
bool requestResponse(const uint8_t* buf, const uint8_t len) WARN_IF_UNUSED;
// Send a request to the GPS to set the baud rate on the specified port.
// Note - these request functions currently ignore the ACK from the device.
// If the device is already sending serial traffic, there is no mechanism to prevent conflict.
// According to the manufacturer, the best approach is to switch to ethernet.
void requestBaud(const HW_Port portIndex);
// Send a request to the GPS to enable a message type on the port at the specified rate.
void requestGSOF(const uint8_t messageType, const HW_Port portIndex, const Output_Rate rateHz);
static void populateChecksum(uint8_t* buf, const uint8_t len);
void populateOutgoingTransNumber(uint8_t* buf);
double SwapDouble(const uint8_t* src, const uint32_t pos) const WARN_IF_UNUSED;
float SwapFloat(const uint8_t* src, const uint32_t pos) const WARN_IF_UNUSED;
uint32_t SwapUint32(const uint8_t* src, const uint32_t pos) const WARN_IF_UNUSED;
@ -121,27 +102,12 @@ private:
uint8_t checksumcalc;
} msg;
static const uint8_t STX = 0x02;
static const uint8_t ETX = 0x03;
static const uint8_t ACK = 0x06;
static const uint8_t NACK = 0x15;
// How long to wait from sending configuration data for a response.
// This assumes delay is the same regardless of baud rate.
static const uint8_t configuration_wait_time_ms {5};
// How many attempts to attempt configuration.
// Raising this makes the initialization more immune to data conflicts with streamed data.
// Raising it too high will trigger the watchdog.
// Lowering this makes the driver quicker to return from initialization calls.
static const uint8_t configuration_attempts {3};
// The counter for number of outgoing packets
uint8_t packetOutboundTransNumber;
uint8_t packetcount;
uint32_t gsofmsg_time;
uint8_t gsofmsgreq_index;
const uint8_t gsofmsgreq[5] = {1,2,8,9,12};
bool is_baud_configured {false};
bool is_configured {false};
};
#endif