LP-56 - Better txpid option namings, fix tabs-spaces, tooltips. headers, variable...
[librepilot.git] / flight / modules / GPS / ubx_autoconfig.c
blob3e0adf0127b92905ed1383fda9e0c8b2510b67ab
1 /**
2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
4 * @{
5 * @addtogroup GSPModule GPS Module
6 * @brief Support code for UBX AutoConfig
7 * @{
9 * @file ubx_autoconfig.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014.
11 * @brief Support code for UBX AutoConfig
12 * @see The GNU Public License (GPL) Version 3
14 *****************************************************************************/
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <openpilot.h>
31 #include "hwsettings.h"
32 #include "gpssettings.h"
34 #include "inc/ubx_autoconfig.h"
35 #include <pios_mem.h>
36 #include "taskinfo.h"
38 // private type definitions
40 typedef enum {
41 INIT_STEP_DISABLED = 0,
42 INIT_STEP_START,
43 INIT_STEP_SEND_MON_VER,
44 INIT_STEP_WAIT_MON_VER_ACK,
45 INIT_STEP_RESET_GPS,
46 INIT_STEP_REVO_9600_BAUD,
47 INIT_STEP_GPS_BAUD,
48 INIT_STEP_REVO_BAUD,
49 INIT_STEP_ENABLE_SENTENCES,
50 INIT_STEP_ENABLE_SENTENCES_WAIT_ACK,
51 INIT_STEP_CONFIGURE,
52 INIT_STEP_CONFIGURE_WAIT_ACK,
53 INIT_STEP_SAVE,
54 INIT_STEP_SAVE_WAIT_ACK,
55 INIT_STEP_PRE_DONE,
56 INIT_STEP_DONE,
57 INIT_STEP_PRE_ERROR,
58 INIT_STEP_ERROR
59 } initSteps_t;
61 typedef struct {
62 initSteps_t currentStep; // Current configuration "fsm" status
63 initSteps_t currentStepSave; // Current configuration "fsm" status
64 uint32_t lastStepTimestampRaw; // timestamp of last operation
65 uint32_t lastConnectedRaw; // timestamp of last time gps was connected
66 struct {
67 union {
68 struct {
69 UBXSentPacket_t working_packet; // outbound "buffer"
70 // bufferPaddingForPiosBugAt2400Baud must exist for baud rate change to work at 2400 or 4800
71 // failure mode otherwise:
72 // - send message with baud rate change
73 // - wait 1 second (even at 2400, the baud rate change command
74 // - should clear even an initially full 31 byte PIOS buffer much more quickly)
75 // - change Revo port baud rate
76 // sometimes fails (much worse for lowest baud rates)
77 // FIXME: remove this and retest when someone has time
78 uint8_t bufferPaddingForPiosBugAt2400Baud[2]; // must be at least 2 for 2400 to work, probably 1 for 4800 and 0 for 9600+
79 } __attribute__((packed));
80 GPSSettingsData gpsSettings;
81 } __attribute__((packed));
82 } __attribute__((packed));
83 volatile ubx_autoconfig_settings_t currentSettings;
84 int8_t lastConfigSent; // index of last configuration string sent
85 struct UBX_ACK_ACK requiredAck; // Class and id of the message we are waiting for an ACK from GPS
86 uint8_t retryCount;
87 } status_t;
89 ubx_cfg_msg_t msg_config_ubx6[] = {
90 // messages to disable
91 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_CLOCK, .rate = 0 },
92 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_POSECEF, .rate = 0 },
93 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_SBAS, .rate = 0 },
94 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_TIMEGPS, .rate = 0 },
95 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_VELECEF, .rate = 0 },
97 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_HW, .rate = 0 },
98 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_HW2, .rate = 0 },
99 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_IO, .rate = 0 },
100 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_MSGPP, .rate = 0 },
101 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_RXBUFF, .rate = 0 },
102 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_RXR, .rate = 0 },
103 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_TXBUF, .rate = 0 },
105 { .msgClass = UBX_CLASS_RXM, .msgID = UBX_ID_RXM_SVSI, .rate = 0 },
107 // message to enable
108 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_POSLLH, .rate = 1 },
109 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_DOP, .rate = 1 },
110 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_SOL, .rate = 1 },
111 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_STATUS, .rate = 1 },
112 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_VELNED, .rate = 1 },
113 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_TIMEUTC, .rate = 1 },
114 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_SVINFO, .rate = 10 },
117 ubx_cfg_msg_t msg_config_ubx7[] = {
118 // messages to disable
119 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_AOPSTATUS, .rate = 0 },
120 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_CLOCK, .rate = 0 },
121 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_DGPS, .rate = 0 },
122 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_POSECEF, .rate = 0 },
123 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_SBAS, .rate = 0 },
124 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_TIMEGPS, .rate = 0 },
125 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_VELECEF, .rate = 0 },
126 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_SOL, .rate = 0 },
127 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_STATUS, .rate = 0 },
128 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_VELNED, .rate = 0 },
129 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_TIMEUTC, .rate = 0 },
130 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_POSLLH, .rate = 0 },
132 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_HW, .rate = 0 },
133 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_HW2, .rate = 0 },
134 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_IO, .rate = 0 },
135 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_MSGPP, .rate = 0 },
136 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_RXBUFF, .rate = 0 },
137 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_RXR, .rate = 0 },
138 { .msgClass = UBX_CLASS_MON, .msgID = UBX_ID_MON_TXBUF, .rate = 0 },
140 { .msgClass = UBX_CLASS_RXM, .msgID = UBX_ID_RXM_SVSI, .rate = 0 },
142 // message to enable
143 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_PVT, .rate = 1 },
144 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_DOP, .rate = 1 },
145 { .msgClass = UBX_CLASS_NAV, .msgID = UBX_ID_NAV_SVINFO, .rate = 10 },
148 // private defines
150 #define LAST_CONFIG_SENT_START (-1)
151 #define LAST_CONFIG_SENT_COMPLETED (-2)
152 // always reset the stored GPS configuration, even when doing autoconfig.nostore
153 // that is required to do a 100% correct configuration
154 // but is unexpected because it changes the stored configuration when doing autoconfig.nostore
155 // note that a reset is always done with autoconfig.store
156 // #define ALWAYS_RESET
158 // we can enable this when we know how to make the Flight Controller save an object to permanent storage
159 // also see comment about simple edit in gpssettings.xml
160 #define AUTOBAUD_CONFIGURE_STORE_AND_DISABLE
161 // Alessio Morale May 20 3:16 AM
162 // @Cliff you should update the ObjectPersistence uavo passing the object id and the desired operation.
164 // private variables
166 // enable the autoconfiguration system
167 static volatile bool enabled = false;
168 static volatile bool current_step_touched = false;
169 // both the pointer and what it points to are volatile. Yuk.
170 static volatile status_t *volatile status = 0;
171 static uint8_t hwsettings_baud;
172 static uint8_t baud_to_try_index = 255;
174 // functions
176 static void append_checksum(UBXSentPacket_t *packet)
178 uint8_t i;
179 uint8_t ck_a = 0;
180 uint8_t ck_b = 0;
181 uint16_t len = packet->message.header.len + sizeof(UBXSentHeader_t);
183 for (i = 2; i < len; i++) {
184 ck_a += packet->buffer[i];
185 ck_b += ck_a;
188 packet->buffer[len] = ck_a;
189 packet->buffer[len + 1] = ck_b;
194 * prepare a packet to be sent, fill the header and appends the checksum.
195 * return the total packet lenght comprising header and checksum
197 static uint16_t prepare_packet(UBXSentPacket_t *packet, uint8_t classID, uint8_t messageID, uint16_t len)
199 memset((uint8_t *)status->working_packet.buffer + len + sizeof(UBXSentHeader_t) + 2, 0, sizeof(status->bufferPaddingForPiosBugAt2400Baud));
200 packet->message.header.prolog[0] = UBX_SYNC1;
201 packet->message.header.prolog[1] = UBX_SYNC2;
202 packet->message.header.class = classID;
203 packet->message.header.id = messageID;
204 packet->message.header.len = len;
205 append_checksum(packet);
207 status->requiredAck.clsID = classID;
208 status->requiredAck.msgID = messageID;
210 return len + sizeof(UBXSentHeader_t) + 2 + sizeof(status->bufferPaddingForPiosBugAt2400Baud); // payload + header + checksum + extra bytes
214 static void build_request(UBXSentPacket_t *packet, uint8_t classID, uint8_t messageID, uint16_t *bytes_to_send)
216 *bytes_to_send = prepare_packet(packet, classID, messageID, 0);
220 static void set_current_step_if_untouched(initSteps_t new_steps)
222 // assume this one byte initSteps_t is atomic
223 // take care of some concurrency issues
225 if (!current_step_touched) {
226 status->currentStep = new_steps;
228 if (current_step_touched) {
229 status->currentStep = status->currentStepSave;
234 void gps_ubx_reset_sensor_type()
236 static uint8_t mutex; // = 0
238 // is this needed?
239 // what happens if two tasks / threads try to do an XyzSet() at the same time?
240 if (__sync_fetch_and_add(&mutex, 1) == 0) {
241 ubxHwVersion = -1;
242 baud_to_try_index -= 1; // undo postincrement and start with the one that was most recently successful
243 sensorType = GPSPOSITIONSENSOR_SENSORTYPE_UNKNOWN;
244 GPSPositionSensorSensorTypeSet(&sensorType);
245 // make the sensor type / autobaud code time out immediately to send the request immediately
246 status->lastStepTimestampRaw += 0x8000000UL;
248 --mutex;
252 static void config_reset(uint16_t *bytes_to_send)
254 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_cfg_t));
255 // mask LSB=ioPort|msgConf|infMsg|navConf|rxmConf|||||rinvConf|antConf|....|= MSB
256 // ioPort=1, msgConf=2, infMsg=4, navConf=8, tpConf=0x10, sfdrConf=0x100, rinvConf=0x200, antConf=0x400
257 // first: reset (permanent settings to default) all but rinv = e.g. owner name
258 status->working_packet.message.payload.cfg_cfg.clearMask = UBX_CFG_CFG_OP_RESET_SETTINGS;
259 // then: don't store any current settings to permanent
260 status->working_packet.message.payload.cfg_cfg.saveMask = UBX_CFG_CFG_SETTINGS_NONE;
261 // lastly: load (immediately start to use) all but rinv = e.g. owner name
262 status->working_packet.message.payload.cfg_cfg.loadMask = UBX_CFG_CFG_OP_RESET_SETTINGS;
263 // all devices
264 status->working_packet.message.payload.cfg_cfg.deviceMask = UBX_CFG_CFG_DEVICE_ALL;
266 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_CFG, sizeof(ubx_cfg_cfg_t));
270 // set the GPS baud rate to the user specified baud rate
271 // because we may have started up with 9600 baud (for a GPS with no permanent settings)
272 static void config_gps_baud(uint16_t *bytes_to_send)
274 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_prt_t));
275 status->working_packet.message.payload.cfg_prt.mode = UBX_CFG_PRT_MODE_DEFAULT; // 8databits, 1stopbit, noparity, and non-zero reserved
276 status->working_packet.message.payload.cfg_prt.portID = 1; // 1 = UART1, 2 = UART2
277 // for protocol masks, bit 0 is UBX enable, bit 1 is NMEA enable
278 status->working_packet.message.payload.cfg_prt.inProtoMask = 1; // 1 = UBX only (bit 0)
279 // disable current UBX messages for low baud rates
280 status->working_packet.message.payload.cfg_prt.outProtoMask = 1;
281 // Ask GPS to change it's speed
282 status->working_packet.message.payload.cfg_prt.baudRate = hwsettings_gpsspeed_enum_to_baud(hwsettings_baud);
283 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_PRT, sizeof(ubx_cfg_prt_t));
287 static void config_rate(uint16_t *bytes_to_send)
289 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_rate_t));
290 // if rate is less than 1 uses the highest rate for current hardware
291 uint16_t rate = status->currentSettings.navRate > 0 ? status->currentSettings.navRate : 99;
292 if (ubxHwVersion < UBX_HW_VERSION_7 && rate > UBX_MAX_RATE) {
293 rate = UBX_MAX_RATE;
294 } else if (ubxHwVersion < UBX_HW_VERSION_8 && rate > UBX_MAX_RATE_VER7) {
295 rate = UBX_MAX_RATE_VER7;
296 } else if (ubxHwVersion >= UBX_HW_VERSION_8 && rate > UBX_MAX_RATE_VER8) {
297 rate = UBX_MAX_RATE_VER8;
299 uint16_t period = 1000 / rate;
300 status->working_packet.message.payload.cfg_rate.measRate = period;
301 status->working_packet.message.payload.cfg_rate.navRate = 1; // must be set to 1
302 status->working_packet.message.payload.cfg_rate.timeRef = 1; // 0 = UTC Time, 1 = GPS Time
304 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_RATE, sizeof(ubx_cfg_rate_t));
308 static void config_nav(uint16_t *bytes_to_send)
310 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_nav5_t));
311 status->working_packet.message.payload.cfg_nav5.dynModel = status->currentSettings.dynamicModel;
312 status->working_packet.message.payload.cfg_nav5.fixMode = 2; // 1=2D only, 2=3D only, 3=Auto 2D/3D
313 // mask LSB=dyn|minEl|posFixMode|drLim|posMask|statisticHoldMask|dgpsMask|......|reservedBit0 = MSB
314 status->working_packet.message.payload.cfg_nav5.mask = 0x01 + 0x04; // Dyn Model | posFixMode configuration
316 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_NAV5, sizeof(ubx_cfg_nav5_t));
320 static void config_sbas(uint16_t *bytes_to_send)
322 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_sbas_t));
323 status->working_packet.message.payload.cfg_sbas.maxSBAS =
324 status->currentSettings.SBASChannelsUsed < 4 ? status->currentSettings.SBASChannelsUsed : 3;
325 status->working_packet.message.payload.cfg_sbas.usage =
326 (status->currentSettings.SBASCorrection ? UBX_CFG_SBAS_USAGE_DIFFCORR : 0) |
327 (status->currentSettings.SBASIntegrity ? UBX_CFG_SBAS_USAGE_INTEGRITY : 0) |
328 (status->currentSettings.SBASRanging ? UBX_CFG_SBAS_USAGE_RANGE : 0);
329 // If sbas is used for anything then set mode as enabled
330 status->working_packet.message.payload.cfg_sbas.mode =
331 status->working_packet.message.payload.cfg_sbas.usage != 0 ? UBX_CFG_SBAS_MODE_ENABLED : 0;
332 status->working_packet.message.payload.cfg_sbas.scanmode1 =
333 status->currentSettings.SBASSats == UBX_SBAS_SATS_WAAS ? UBX_CFG_SBAS_SCANMODE1_WAAS :
334 status->currentSettings.SBASSats == UBX_SBAS_SATS_EGNOS ? UBX_CFG_SBAS_SCANMODE1_EGNOS :
335 status->currentSettings.SBASSats == UBX_SBAS_SATS_MSAS ? UBX_CFG_SBAS_SCANMODE1_MSAS :
336 status->currentSettings.SBASSats == UBX_SBAS_SATS_GAGAN ? UBX_CFG_SBAS_SCANMODE1_GAGAN :
337 status->currentSettings.SBASSats == UBX_SBAS_SATS_SDCM ? UBX_CFG_SBAS_SCANMODE1_SDCM : UBX_SBAS_SATS_AUTOSCAN;
338 status->working_packet.message.payload.cfg_sbas.scanmode2 =
339 UBX_CFG_SBAS_SCANMODE2;
341 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_SBAS, sizeof(ubx_cfg_sbas_t));
345 static void config_gnss(uint16_t *bytes_to_send)
347 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_gnss_t));
348 status->working_packet.message.payload.cfg_gnss.numConfigBlocks = UBX_GNSS_ID_MAX;
349 status->working_packet.message.payload.cfg_gnss.numTrkChHw = (ubxHwVersion > UBX_HW_VERSION_7) ? UBX_CFG_GNSS_NUMCH_VER8 : UBX_CFG_GNSS_NUMCH_VER7;
350 status->working_packet.message.payload.cfg_gnss.numTrkChUse = status->working_packet.message.payload.cfg_gnss.numTrkChHw;
352 for (int32_t i = 0; i < UBX_GNSS_ID_MAX; i++) {
353 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].gnssId = i;
354 switch (i) {
355 case UBX_GNSS_ID_GPS:
356 if (status->currentSettings.enableGPS) {
357 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].flags = UBX_CFG_GNSS_FLAGS_ENABLED | UBX_CFG_GNSS_FLAGS_GPS_L1CA;
358 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].maxTrkCh = 16;
359 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].resTrkCh = 8;
361 break;
362 case UBX_GNSS_ID_QZSS:
363 if (status->currentSettings.enableGPS) {
364 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].flags = UBX_CFG_GNSS_FLAGS_ENABLED | UBX_CFG_GNSS_FLAGS_QZSS_L1CA;
365 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].maxTrkCh = 3;
366 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].resTrkCh = 0;
368 break;
369 case UBX_GNSS_ID_SBAS:
370 if (status->currentSettings.SBASCorrection || status->currentSettings.SBASIntegrity || status->currentSettings.SBASRanging) {
371 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].flags = UBX_CFG_GNSS_FLAGS_ENABLED | UBX_CFG_GNSS_FLAGS_SBAS_L1CA;
372 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].maxTrkCh = status->currentSettings.SBASChannelsUsed < 4 ? status->currentSettings.SBASChannelsUsed : 3;
373 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].resTrkCh = 1;
375 break;
376 case UBX_GNSS_ID_GLONASS:
377 if (status->currentSettings.enableGLONASS) {
378 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].flags = UBX_CFG_GNSS_FLAGS_ENABLED | UBX_CFG_GNSS_FLAGS_GLONASS_L1OF;
379 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].maxTrkCh = 14;
380 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].resTrkCh = 8;
382 break;
383 case UBX_GNSS_ID_BEIDOU:
384 if (status->currentSettings.enableBeiDou) {
385 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].flags = UBX_CFG_GNSS_FLAGS_ENABLED | UBX_CFG_GNSS_FLAGS_BEIDOU_B1I;
386 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].maxTrkCh = 14;
387 status->working_packet.message.payload.cfg_gnss.cfgBlocks[i].resTrkCh = 8;
389 break;
390 default:
391 break;
395 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_GNSS, sizeof(ubx_cfg_gnss_t));
399 static void config_save(uint16_t *bytes_to_send)
401 memset((uint8_t *)status->working_packet.buffer, 0, sizeof(UBXSentHeader_t) + sizeof(ubx_cfg_cfg_t));
402 // mask LSB=ioPort|msgConf|infMsg|navConf|rxmConf|||||rinvConf|antConf|....|= MSB
403 // ioPort=1, msgConf=2, infMsg=4, navConf=8, tpConf=0x10, sfdrConf=0x100, rinvConf=0x200, antConf=0x400
404 status->working_packet.message.payload.cfg_cfg.saveMask = UBX_CFG_CFG_OP_STORE_SETTINGS; // a list of settings we just set
405 status->working_packet.message.payload.cfg_cfg.clearMask = UBX_CFG_CFG_OP_CLEAR_SETTINGS; // everything else gets factory default
406 status->working_packet.message.payload.cfg_cfg.deviceMask = UBX_CFG_CFG_DEVICE_ALL;
408 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_CFG, sizeof(ubx_cfg_cfg_t));
412 static void configure(uint16_t *bytes_to_send)
414 switch (status->lastConfigSent) {
415 case LAST_CONFIG_SENT_START:
416 // increase message rates to 5 fixes per second
417 config_rate(bytes_to_send);
418 break;
420 case LAST_CONFIG_SENT_START + 1:
421 config_nav(bytes_to_send);
422 break;
424 case LAST_CONFIG_SENT_START + 2:
425 if (status->currentSettings.enableGLONASS || status->currentSettings.enableGPS) {
426 config_gnss(bytes_to_send);
427 break;
428 } else {
429 // Skip and fall through to next step
430 status->lastConfigSent++;
432 // in the else case we must fall through because we must send something each time because successful send is tested externally
434 case LAST_CONFIG_SENT_START + 3:
435 config_sbas(bytes_to_send);
436 break;
438 default:
439 status->lastConfigSent = LAST_CONFIG_SENT_COMPLETED;
440 break;
445 static void enable_sentences(__attribute__((unused)) uint16_t *bytes_to_send)
447 int8_t msg = status->lastConfigSent + 1;
448 uint8_t msg_count = (ubxHwVersion >= UBX_HW_VERSION_7) ?
449 NELEMENTS(msg_config_ubx7) : NELEMENTS(msg_config_ubx6);
450 ubx_cfg_msg_t *msg_config = (ubxHwVersion >= UBX_HW_VERSION_7) ?
451 &msg_config_ubx7[0] : &msg_config_ubx6[0];
453 if (msg >= 0 && msg < msg_count) {
454 status->working_packet.message.payload.cfg_msg = msg_config[msg];
455 *bytes_to_send = prepare_packet((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_CFG, UBX_ID_CFG_MSG, sizeof(ubx_cfg_msg_t));
456 } else {
457 status->lastConfigSent = LAST_CONFIG_SENT_COMPLETED;
462 #if defined(AUTOBAUD_CONFIGURE_STORE_AND_DISABLE)
463 // permanently store our version of GPSSettings.UbxAutoConfig
464 // we use this to disable after AbConfigStoreAndDisable is complete
465 static void setGpsSettings()
467 // trying to do this as perfectly as possible we must realize that they may have pressed Send on some fields
468 // and so those fields are not stored permanently
469 // if we write the memory copy to flash, we will have made those permanent
471 // we could save off the uavo memory copy to a local buffer with a standard GPSSettingsGet()
472 // load from flash to uavo memory with a UAVObjLoad()
473 // update our one setting in uavo memory with a standard GPSSettingsUbxAutoConfigSet()
474 // save from uavo memory to flash with a UAVObjSave()
475 // modify our saved off copy to have our new setting in it too
476 // and finally copy the local buffer back out to uavo memory
478 // that would do it as correctly as possible, but it doesn't work
479 // so we do it the way autotune.c does it
481 #if 0
482 // get the "in memory" version to a local buffer
483 GPSSettingsGet((void *)&status->gpsSettings);
484 // load the permanent version into memory
485 UAVObjLoad(GPSSettingsHandle(), 0);
486 #endif
487 // change the in memory version of the field we want to change
488 GPSSettingsUbxAutoConfigSet((GPSSettingsUbxAutoConfigOptions *)&status->currentSettings.UbxAutoConfig);
489 // save the in memory version to permanent
490 UAVObjSave(GPSSettingsHandle(), 0);
491 #if 0
492 // copy the setting into the struct we will use to Set()
493 status->gpsSettings.UbxAutoConfig = status->currentSettings.UbxAutoConfig;
494 // try casting it correctly and it says:
495 // expected 'struct GPSSettingsData *' but argument is of type 'struct GPSSettingsData *'
496 // probably a volatile or align issue
497 GPSSettingsSet((void *)&status->gpsSettings); // set the "in memory" version back into use
498 #endif
500 #endif /* if defined(AUTOBAUD_CONFIGURE_STORE_AND_DISABLE) */
503 // 9600 baud and lower are not usable, and are best left at factory default
504 // if the user selects 9600
505 void gps_ubx_autoconfig_run(char * *buffer, uint16_t *bytes_to_send)
507 *bytes_to_send = 0;
508 *buffer = (char *)status->working_packet.buffer;
509 current_step_touched = false;
511 // autoconfig struct not yet allocated
512 if (!status) {
513 return;
516 // get UBX version whether autobaud / autoconfig is enabled or not
517 // this allows the user to manually try some baud rates and visibly see when it works
518 // it also is how the autobaud code determines when the baud rate is correct
519 // ubxHwVersion is a global set externally by the caller of this function
520 // it is set when the GPS responds to a MON_VER message
521 if (ubxHwVersion <= 0) {
522 // at low baud rates and high data rates the ubx gps simply must drop some outgoing data
523 // this isn't really an error
524 // and when a lot of data is being dropped, the MON VER reply often gets dropped
525 // on the other hand, uBlox documents that some versions discard data that is over 1 second old
526 // implying a 1 second send buffer and that it could be over 1 second before a reply is received
527 // later uBlox versions dropped this 1 second constraint and drop data when the send buffer is full
528 // and that could be even longer than 1 second
529 // send this more quickly and it will get a reply more quickly if a fixed percentage of replies are being dropped
531 // wait for the normal reply timeout before sending it over and over
532 if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_PARSER_TIMEOUT) {
533 return;
536 // at this point we have already waited for the MON_VER reply to time out (except the first time where it times out without being sent)
537 // and the fact we are here says that ubxHwVersion has not been set (it is set externally)
538 // so this try at this baud rate has failed
539 // if we get here
540 // select the next baud rate, skipping ahead if new baud rate is HwSettings.GPSSpeed
541 // set Revo baud rate to current++ value (immediate change so we can send right after that) and send the MON_VER request
542 // baud rate search order are most likely matches first
544 // if AutoBaud or higher, do AutoBaud
545 if (status->currentSettings.UbxAutoConfig >= GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUD) {
546 uint8_t baud_to_try;
547 static uint8_t baud_array[] = {
548 HWSETTINGS_GPSSPEED_57600,
549 HWSETTINGS_GPSSPEED_9600,
550 HWSETTINGS_GPSSPEED_115200,
551 HWSETTINGS_GPSSPEED_38400,
552 HWSETTINGS_GPSSPEED_19200,
553 HWSETTINGS_GPSSPEED_230400,
554 HWSETTINGS_GPSSPEED_4800,
555 HWSETTINGS_GPSSPEED_2400
558 // first try HwSettings.GPSSpeed and then
559 // get the next baud rate to try from the table, but skip over the value of HwSettings.GPSSpeed
560 do {
561 // index is inited to be out of bounds, which is interpreted as "currently defined baud rate" (= HwSettings.GPSSpeed)
562 if (baud_to_try_index >= sizeof(baud_array) / sizeof(baud_array[0])) {
563 HwSettingsGPSSpeedGet(&hwsettings_baud);
564 baud_to_try = hwsettings_baud;
565 baud_to_try_index = 0;
566 break;
567 } else {
568 baud_to_try = baud_array[baud_to_try_index++];
570 // skip HwSettings.GPSSpeed when you run across it in the list
571 } while (baud_to_try == hwsettings_baud);
572 // set the FC (Revo) baud rate
573 gps_set_fc_baud_from_arg(baud_to_try);
576 // this code is executed even if ubxautoconfig is disabled
577 // it detects the "sensor type" = type of GPS
578 // the user can use this to manually determine if the baud rate is correct
579 build_request((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_MON, UBX_ID_MON_VER, bytes_to_send);
580 // keep timeouts running properly, we (will have) just sent a packet that generates a reply
581 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
582 return;
585 if (!enabled) {
586 // keep resetting the timeouts here if we are not actually going to run the configure code
587 // not really necessary, but it keeps the timer from wrapping every 50 seconds
588 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
589 return; // autoconfig not enabled
592 ////////
593 // FSM
594 ////////
595 switch (status->currentStep) {
596 // if here, we have verified that the baud rates are in sync sometime in the past
597 case INIT_STEP_START:
598 // we should look for the GPS version again (user may plug in a different GPS and then do autoconfig again)
599 // zero retries for the next state that needs it (INIT_STEP_SAVE)
600 set_current_step_if_untouched(INIT_STEP_SEND_MON_VER);
601 // fall through to next state
602 // we can do that if we choose because we haven't sent any data in this state
603 // break;
605 case INIT_STEP_SEND_MON_VER:
606 build_request((UBXSentPacket_t *)&status->working_packet, UBX_CLASS_MON, UBX_ID_MON_VER, bytes_to_send);
607 // keep timeouts running properly, we (will have) just sent a packet that generates a reply
608 set_current_step_if_untouched(INIT_STEP_WAIT_MON_VER_ACK);
609 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
610 break;
612 case INIT_STEP_WAIT_MON_VER_ACK:
613 // wait for previous step
614 // extra wait time might well be unnecessary but we want to make sure
615 // that we don't stop waiting too soon
616 if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_UNVERIFIED_STEP_WAIT_TIME) {
617 return;
619 // Continue with next configuration option
620 set_current_step_if_untouched(INIT_STEP_RESET_GPS);
621 // fall through to next state
622 // we can do that if we choose because we haven't sent any data in this state
623 // break;
625 // if here, we have just verified that the baud rates are in sync (again)
626 case INIT_STEP_RESET_GPS:
627 // make sure we don't change the baud rate too soon and garble the packet being sent
628 // even after pios says the buffer is empty, the serial port buffer still has data in it
629 // and changing the baud will screw it up
630 // when the GPS is configured to send a lot of data, but has a low baud rate
631 // it has way too many messages to send and has to drop most of them
633 // Retrieve desired GPS baud rate once for use throughout this module
634 HwSettingsGPSSpeedGet(&hwsettings_baud);
635 #if !defined(ALWAYS_RESET)
636 // ALWAYS_RESET is undefined because it causes stored settings to change even with autoconfig.nostore
637 // but with it off, some settings may be enabled that should really be disabled (but aren't) after autoconfig.nostore
638 // if user requests a low baud rate then we just reset and avoid adding navigation sentences
639 // because low GPS baud and high OP data rate doesn't play nice
640 // if user requests that settings be saved, we will reset here too
641 // that makes sure that all strange settings are reset to factory default
642 // else these strange settings may persist because we don't reset all settings by table
643 if (status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGUREANDSTORE
644 #if defined(AUTOBAUD_CONFIGURE_STORE_AND_DISABLE)
645 || status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGURESTOREANDDISABLE
646 #endif
648 #endif
650 // reset all GPS parameters to factory default (configure low rate NMEA for low baud rates)
651 // this is not usable by OP code for either baud rate or types of messages sent
652 // but it starts up very quickly for use with autoconfig-nostore (which sets a high baud and enables all the necessary messages)
653 config_reset(bytes_to_send);
654 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
656 // else allow it enter the next state immmediately by not setting status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
657 set_current_step_if_untouched(INIT_STEP_REVO_9600_BAUD);
658 break;
660 // GPS was just reset, so GPS is running 9600 baud, and Revo is running whatever baud it was before
661 case INIT_STEP_REVO_9600_BAUD:
662 #if !defined(ALWAYS_RESET)
663 // if user requests a low baud rate then we just reset and leave it set to NMEA
664 // because low baud and high OP data rate doesn't play nice
665 // if user requests that settings be saved, we will reset here too
666 // that makes sure that all strange settings are reset to factory default
667 // else these strange settings may persist because we don't reset all settings by hand
668 if (status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGUREANDSTORE
669 #if defined(AUTOBAUD_CONFIGURE_STORE_AND_DISABLE)
670 || status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGURESTOREANDDISABLE
671 #endif
673 #endif
675 // wait for previous step
676 // extra wait time might well be unnecessary but we want to make very sure
677 // that we don't stop waiting too soon as that could leave us at an unknown baud rate
678 // (i.e. set or not set) if the the transmit buffer was full and we were running at a low baud rate
679 if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_UNVERIFIED_STEP_WAIT_TIME) {
680 return;
682 // set the Revo GPS port to 9600 baud to match the reset to factory default that has already been done
683 gps_set_fc_baud_from_arg(HWSETTINGS_GPSSPEED_9600);
685 // at most, we just set Revo baud and that doesn't send any data
686 // fall through to next state
687 // we can do that if we choose because we haven't sent any data in this state
688 // set_current_step_if_untouched(INIT_STEP_GPS_BAUD);
689 // allow it enter the next state immmediately by not setting status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
690 // break;
692 // Revo and GPS are both at 9600 baud
693 case INIT_STEP_GPS_BAUD:
694 // https://www.u-blox.com/images/downloads/Product_Docs/u-bloxM8_ReceiverDescriptionProtocolSpec_%28UBX-13003221%29_Public.pdf
695 // It is possible to change the current communications port settings using a UBX-CFG-CFG message. This could
696 // affect baud rate and other transmission parameters. Because there may be messages queued for transmission
697 // there may be uncertainty about which protocol applies to such messages. In addition a message currently in
698 // transmission may be corrupted by a protocol change. Host data reception parameters may have to be changed to
699 // be able to receive future messages, including the acknowledge message associated with the UBX-CFG-CFG message.
701 // so the message that changes the baud rate will send it's acknowledgement back at the new baud rate; this is not good.
702 // if your message was corrupted, you didn't change the baud rate and you have to guess; try pinging at both baud rates.
703 // also, you would have to change the baud rate instantly after the last byte of the sentence was sent,
704 // and you would have to poll the port in real time for that, and there may be messages ahead of the baud rate change.
706 // so we ignore the ack from this. it has proven to be reliable (with the addition of two dummy bytes after the packet)
708 // set the GPS internal baud rate to the user configured value
709 config_gps_baud(bytes_to_send);
710 set_current_step_if_untouched(INIT_STEP_REVO_BAUD);
711 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
712 break;
714 // GPS is at final baud and Revo is at old baud (old is 9600 or initial detected baud)
715 case INIT_STEP_REVO_BAUD:
716 // wait for previous step
717 if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_UNVERIFIED_STEP_WAIT_TIME) {
718 return;
720 // set the Revo GPS port baud rate to the (same) user configured value
721 gps_set_fc_baud_from_arg(hwsettings_baud);
722 status->lastConfigSent = LAST_CONFIG_SENT_START;
723 // zero the retries for the first "enable sentence"
724 status->retryCount = 0;
725 // skip enabling UBX sentences for low baud rates
726 // low baud rates are not usable, and higher data rates just makes it harder for this code to change the configuration
727 if (hwsettings_baud <= HWSETTINGS_GPSSPEED_9600) {
728 set_current_step_if_untouched(INIT_STEP_SAVE);
729 } else {
730 set_current_step_if_untouched(INIT_STEP_ENABLE_SENTENCES);
732 // allow it enter the next state immmediately by not setting status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
733 break;
735 case INIT_STEP_ENABLE_SENTENCES:
736 case INIT_STEP_CONFIGURE:
738 bool step_configure = (status->currentStep == INIT_STEP_CONFIGURE);
739 if (step_configure) {
740 configure(bytes_to_send);
741 } else {
742 enable_sentences(bytes_to_send);
745 // for some branches, allow it enter the next state immmediately by not setting status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
746 if (status->lastConfigSent == LAST_CONFIG_SENT_COMPLETED) {
747 if (step_configure) {
748 // zero retries for the next state that needs it (INIT_STEP_SAVE)
749 status->retryCount = 0;
750 set_current_step_if_untouched(INIT_STEP_SAVE);
751 } else {
752 // finished enabling sentences, now configure() needs to start at the beginning
753 status->lastConfigSent = LAST_CONFIG_SENT_START;
754 set_current_step_if_untouched(INIT_STEP_CONFIGURE);
756 } else {
757 set_current_step_if_untouched(step_configure ? INIT_STEP_CONFIGURE_WAIT_ACK : INIT_STEP_ENABLE_SENTENCES_WAIT_ACK);
758 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
760 break;
763 case INIT_STEP_ENABLE_SENTENCES_WAIT_ACK:
764 case INIT_STEP_CONFIGURE_WAIT_ACK: // Wait for an ack from GPS
766 bool step_configure = (status->currentStep == INIT_STEP_CONFIGURE_WAIT_ACK);
767 if (ubxLastAck.clsID == status->requiredAck.clsID && ubxLastAck.msgID == status->requiredAck.msgID) {
768 // Continue with next configuration option
769 // start retries over for the next setting to be sent
770 status->retryCount = 0;
771 status->lastConfigSent++;
772 } else if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_REPLY_TIMEOUT &&
773 (ubxLastNak.clsID != status->requiredAck.clsID || ubxLastNak.msgID != status->requiredAck.msgID)) {
774 // allow timeouts to count up by not setting status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
775 break;
776 } else {
777 // timeout or NAK, resend the message or abort
778 status->retryCount++;
779 if (status->retryCount > UBX_MAX_RETRIES) {
780 set_current_step_if_untouched(INIT_STEP_PRE_ERROR);
781 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
782 break;
785 // success or failure here, retries are handled elsewhere
786 if (step_configure) {
787 set_current_step_if_untouched(INIT_STEP_CONFIGURE);
788 } else {
789 set_current_step_if_untouched(INIT_STEP_ENABLE_SENTENCES);
791 break;
794 // all configurations have been made
795 case INIT_STEP_SAVE:
796 // now decide whether to save them permanently into the GPS
797 if (status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGUREANDSTORE
798 #if defined(AUTOBAUD_CONFIGURE_STORE_AND_DISABLE)
799 || status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGURESTOREANDDISABLE
800 #endif
802 config_save(bytes_to_send);
803 set_current_step_if_untouched(INIT_STEP_SAVE_WAIT_ACK);
804 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
805 } else {
806 set_current_step_if_untouched(INIT_STEP_PRE_DONE);
807 // allow it enter INIT_STEP_PRE_DONE immmediately by not setting status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
809 break;
811 // command to save configuration has already been issued
812 case INIT_STEP_SAVE_WAIT_ACK:
813 // save doesn't appear to respond, even in 24 seconds
814 // just delay a while, in case there it is busy with a flash write, etc.
815 if (PIOS_DELAY_DiffuS(status->lastStepTimestampRaw) < UBX_SAVE_WAIT_TIME) {
816 return;
818 // fall through to next state
819 // we can do that if we choose because we haven't sent any data in this state
820 set_current_step_if_untouched(INIT_STEP_PRE_DONE);
821 // break;
823 // the autoconfig has completed normally
824 case INIT_STEP_PRE_DONE:
825 #if defined(AUTOBAUD_CONFIGURE_STORE_AND_DISABLE)
826 // determine if we need to disable autoconfig via the autoconfig==AUTOBAUDCONFIGSTOREANDDISABLE setting
827 if (status->currentSettings.UbxAutoConfig == GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDCONFIGURESTOREANDDISABLE) {
828 enabled = false;
829 status->currentSettings.UbxAutoConfig = GPSSETTINGS_UBXAUTOCONFIG_DISABLED;
830 // like it says
831 setGpsSettings();
833 #endif
834 set_current_step_if_untouched(INIT_STEP_DONE);
835 break;
837 // an error, such as retries exhausted, has occurred
838 case INIT_STEP_PRE_ERROR:
839 // on error we should get the GPS version immediately
840 gps_ubx_reset_sensor_type();
841 set_current_step_if_untouched(INIT_STEP_ERROR);
842 break;
844 case INIT_STEP_DONE:
845 case INIT_STEP_ERROR:
846 case INIT_STEP_DISABLED:
847 break;
852 // this can be called from a different thread
853 // so everything it touches must be declared volatile
854 void gps_ubx_autoconfig_set(ubx_autoconfig_settings_t *config)
856 initSteps_t new_step;
858 enabled = false;
860 if (!status) {
861 status = (status_t *)pios_malloc(sizeof(status_t));
862 PIOS_Assert(status);
863 memset((status_t *)status, 0, sizeof(status_t));
866 // if caller used NULL, just use current settings to restart autoconfig process
867 if (config != NULL) {
868 status->currentSettings = *config;
870 if (status->currentSettings.UbxAutoConfig >= GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDANDCONFIGURE) {
871 new_step = INIT_STEP_START;
872 } else {
873 new_step = INIT_STEP_DISABLED;
875 status->lastStepTimestampRaw = PIOS_DELAY_GetRaw();
877 // assume this one byte initSteps_t is atomic
878 // take care of some but not all concurrency issues
880 status->currentStep = new_step;
881 status->currentStepSave = new_step;
882 current_step_touched = true;
883 status->currentStep = new_step;
884 status->currentStepSave = new_step;
886 if (status->currentSettings.UbxAutoConfig >= GPSSETTINGS_UBXAUTOCONFIG_AUTOBAUDANDCONFIGURE) {
887 // enabled refers to autoconfigure
888 // note that sensor type (gps type) detection happens even if completely disabled
889 // also note that AutoBaud is less than Configure
890 enabled = true;
891 } else {
892 // this forces the sensor type detection to occur outside the FSM
893 // and _can_ also engage the autobaud detection that is outside the FSM
894 // don't do it if FSM is enabled as FSM can change the baud itself
895 // (don't do it because the baud rates are already in sync)
896 gps_ubx_reset_sensor_type();
901 int32_t ubx_autoconfig_get_status()
903 if (!status || !enabled) {
904 return UBX_AUTOCONFIG_STATUS_DISABLED;
906 switch (status->currentStep) {
907 case INIT_STEP_ERROR:
908 return UBX_AUTOCONFIG_STATUS_ERROR;
910 case INIT_STEP_DISABLED:
911 return UBX_AUTOCONFIG_STATUS_DISABLED;
913 case INIT_STEP_DONE:
914 return UBX_AUTOCONFIG_STATUS_DONE;
916 default:
917 break;
919 return UBX_AUTOCONFIG_STATUS_RUNNING;