fix(gps): make ephemeris flash persistence hardware-safe
Add freestanding S25FL256S read/program/erase/verify support and seed a newly formatted ephemeris store with stale records. Age-gate navigation readiness, persist the continuous Toe week, and regenerate the Genesys2 MAX2771 integration and flash image.
This commit is contained in:
@@ -17,7 +17,7 @@ typedef struct {
|
||||
uint16_t record_len;
|
||||
uint32_t sequence;
|
||||
uint32_t toe_sec;
|
||||
uint16_t week;
|
||||
uint16_t toe_week;
|
||||
uint16_t iodc;
|
||||
uint8_t prn;
|
||||
uint8_t iode;
|
||||
@@ -385,6 +385,8 @@ bool gps_ephemeris_store_save(
|
||||
if((store == NULL) || !store->mounted || store->capacity_exceeded ||
|
||||
(ephemeris == NULL) ||
|
||||
(subframe_words == NULL) || (prn >= GPS_PRN_COUNT) ||
|
||||
!ephemeris->toe_week_valid || (ephemeris->toe.week < 0) ||
|
||||
(ephemeris->toe.week > 0xffff) ||
|
||||
(gps_ephemeris_check_static(ephemeris, prn) != GPS_EPHEMERIS_OK))
|
||||
{
|
||||
return false;
|
||||
@@ -426,7 +428,7 @@ bool gps_ephemeris_store_save(
|
||||
record.record_len = (uint16_t)sizeof(record);
|
||||
record.sequence = store->sequence + 1u;
|
||||
record.toe_sec = (uint32_t)ephemeris->toe.sec;
|
||||
record.week = (uint16_t)ephemeris->WN;
|
||||
record.toe_week = (uint16_t)ephemeris->toe.week;
|
||||
record.iodc = (uint16_t)ephemeris->iodc;
|
||||
record.prn = (uint8_t)prn;
|
||||
record.iode = ephemeris->iode;
|
||||
@@ -508,11 +510,23 @@ unsigned int gps_ephemeris_store_load_all(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!parsed || !frame.gps_ephems.ephemeris_valid)
|
||||
if(!parsed || !frame.gps_ephems.ephemeris_valid ||
|
||||
(record.toe_sec != (uint32_t)frame.gps_ephems.toe.sec) ||
|
||||
(record.iodc != (uint16_t)frame.gps_ephems.iodc) ||
|
||||
(record.iode != frame.gps_ephems.iode) ||
|
||||
(record.health != frame.gps_ephems.svhlth) ||
|
||||
(record.flags != (frame.gps_ephems.fit_flag ? 1u : 0u)) ||
|
||||
((record.toe_week & 0x03ffu) !=
|
||||
((uint16_t)frame.gps_ephems.toe.week & 0x03ffu)))
|
||||
{
|
||||
store->records_rejected++;
|
||||
break;
|
||||
}
|
||||
/* Raw LNAV only carries WN modulo 1024. Version 2 records retain
|
||||
* the continuous week resolved from HOW when the live set was
|
||||
* committed, so flash restore preserves the age domain. */
|
||||
frame.gps_ephems.toe.week = (int)record.toe_week;
|
||||
frame.gps_ephems.toe_week_valid = true;
|
||||
frame.gps_ephems.SVID = (unsigned char)prn;
|
||||
if(gps_ephemeris_check_static(&frame.gps_ephems, prn) !=
|
||||
GPS_EPHEMERIS_OK)
|
||||
@@ -527,3 +541,89 @@ unsigned int gps_ephemeris_store_load_all(
|
||||
}
|
||||
return delivered;
|
||||
}
|
||||
|
||||
static void build_initial_seed_subframes(
|
||||
unsigned int words[3][10], unsigned int iodc)
|
||||
{
|
||||
/*
|
||||
* Week 380 and Toe Tuesday 00:00 are intentionally old. Keep the orbital
|
||||
* fields structurally plausible so restore exercises the same decoder and
|
||||
* validity rules as a live LNAV data set, while the age check guarantees
|
||||
* that this diagnostic seed can never be used as current ephemeris.
|
||||
*/
|
||||
const unsigned int week = 380u;
|
||||
const unsigned int toe_sec = 86400u;
|
||||
const unsigned int how_count = toe_sec / 6u;
|
||||
const unsigned int iode = iodc & 0xffu;
|
||||
const uint32_t ecc_raw = (uint32_t)(0.008 * 8589934592.0);
|
||||
const uint32_t sqrta_raw = (uint32_t)(5153.6 * 524288.0);
|
||||
|
||||
memset(words, 0, sizeof(unsigned int) * 3u * 10u);
|
||||
for(unsigned int sf = 0u; sf < 3u; sf++)
|
||||
{
|
||||
words[sf][1] = ((how_count + sf) << 13) | ((sf + 1u) << 8);
|
||||
}
|
||||
|
||||
words[0][2] = (week << 20) | (2u << 14) |
|
||||
(((iodc >> 8) & 0x03u) << 6);
|
||||
words[0][7] = ((iodc & 0xffu) << 22) | ((toe_sec >> 4) << 6);
|
||||
|
||||
words[1][2] = iode << 22;
|
||||
words[1][5] = ((ecc_raw >> 24) & 0xffu) << 6;
|
||||
words[1][6] = (ecc_raw & 0xffffffu) << 6;
|
||||
words[1][7] = ((sqrta_raw >> 24) & 0xffu) << 6;
|
||||
words[1][8] = (sqrta_raw & 0xffffffu) << 6;
|
||||
words[1][9] = (toe_sec >> 4) << 14;
|
||||
|
||||
words[2][9] = iode << 22;
|
||||
}
|
||||
|
||||
unsigned int gps_ephemeris_store_seed_initial(
|
||||
gps_ephemeris_store_t* store)
|
||||
{
|
||||
if((store == NULL) || !store->mounted || (store->generation == 0u))
|
||||
{
|
||||
return 0u;
|
||||
}
|
||||
|
||||
unsigned int seeded = 0u;
|
||||
for(unsigned int prn = 0u;
|
||||
prn < GPS_EPH_STORE_INITIAL_SEED_COUNT;
|
||||
prn++)
|
||||
{
|
||||
unsigned int words[3][10];
|
||||
build_initial_seed_subframes(words, 0x120u + prn);
|
||||
|
||||
gps_frame_t frame;
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
frame.gps_ephems.SVID = (unsigned char)prn;
|
||||
bool parsed = true;
|
||||
for(unsigned int sf = 0u; sf < 3u; sf++)
|
||||
{
|
||||
unsigned int how_tow = 0u;
|
||||
if(parse_subframe(words[sf], &frame, &how_tow) !=
|
||||
(unsigned char)(sf + 1u))
|
||||
{
|
||||
parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
frame.gps_ephems.SVID = (unsigned char)prn;
|
||||
if(!parsed || !frame.gps_ephems.ephemeris_valid ||
|
||||
(gps_ephemeris_check_static(&frame.gps_ephems, prn) !=
|
||||
GPS_EPHEMERIS_OK))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bool wrote = false;
|
||||
if(!gps_ephemeris_store_save(
|
||||
store, prn, &frame.gps_ephems,
|
||||
(const unsigned int (*)[10])words, &wrote) || !wrote)
|
||||
{
|
||||
break;
|
||||
}
|
||||
seeded++;
|
||||
}
|
||||
return seeded;
|
||||
}
|
||||
|
||||
@@ -363,6 +363,40 @@ static void gps_nav_epoch_account(uint32_t expected_mask,
|
||||
}
|
||||
}
|
||||
|
||||
static bool gps_nav_channel_ephemeris_ready(unsigned int tracking_index)
|
||||
{
|
||||
if(tracking_index >= GPS_TRCK_IP_COUNT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
volatile gps_ephem_ll_t* node =
|
||||
get_element_by_ip_number(&tracking_node,
|
||||
(unsigned char)tracking_index);
|
||||
if((node == NULL) || (node->data_p == NULL) ||
|
||||
!node->gps_how_anchor_valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int time_week;
|
||||
double time_sec;
|
||||
if(node->gps_nav_solve_sequence != 0u)
|
||||
{
|
||||
time_week = node->gps_last_nav_solve_tow.week;
|
||||
time_sec = node->gps_last_nav_solve_tow.sec;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_week = node->gps_how_tow.week;
|
||||
time_sec = node->gps_how_tow.sec;
|
||||
}
|
||||
unsigned int prn = trck_ips[tracking_index]->PRN_NUMBER;
|
||||
return gps_ephemeris_check(
|
||||
(const gps_ephemeris_t*)node->data_p, prn, true,
|
||||
time_week, time_sec) == GPS_EPHEMERIS_OK;
|
||||
}
|
||||
|
||||
static uint32_t gps_nav_ready_channel_mask(void)
|
||||
{
|
||||
uint32_t eligible_mask = 0u;
|
||||
@@ -380,7 +414,7 @@ static uint32_t gps_nav_ready_channel_mask(void)
|
||||
* an unproven seed cannot hold up a coalescing epoch; it joins as soon
|
||||
* as its first epoch validates. */
|
||||
if(!tracking_allocated[i] || !busy || !locked || !nav_irq_enabled ||
|
||||
trk_seed_unconfirmed[i])
|
||||
trk_seed_unconfirmed[i] || !gps_nav_channel_ephemeris_ready(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -408,7 +442,7 @@ static uint32_t gps_nav_ready_channel_mask(void)
|
||||
return eligible_mask;
|
||||
}
|
||||
|
||||
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
|
||||
#if ((GPS_EPHEMERIS_FLASH_ENABLE == 1) || (GPS_NAV_CONTEXT_ENABLE == 1))
|
||||
static void gps_flash_read(void* ctx, uint32_t address, void* dst,
|
||||
uint32_t len)
|
||||
{
|
||||
@@ -429,6 +463,28 @@ static bool gps_flash_program(void* ctx, uint32_t address, const void* src,
|
||||
return bsp_spi_flash_program(address, src, len);
|
||||
}
|
||||
|
||||
static bool gps_flash_device_init(void)
|
||||
{
|
||||
bsp_spi_flash_init();
|
||||
bsp_spi_flash_reset();
|
||||
uint32_t id = bsp_spi_flash_read_id();
|
||||
uint8_t status = bsp_spi_flash_read_status();
|
||||
uint8_t config = bsp_spi_flash_read_config();
|
||||
GPS_LOG(DEBUG_STATUS, GPS_LOG_CAT_NAV,
|
||||
"SPI flash: id=0x%06lx status=0x%02x config=0x%02x\r\n",
|
||||
(unsigned long)id, status, config);
|
||||
if(id != BSP_SPI_FLASH_JEDEC_ID)
|
||||
{
|
||||
GPS_LOG(DEBUG_ERROR, GPS_LOG_CAT_NAV,
|
||||
"unsupported SPI flash JEDEC id=0x%06lx expected=0x%06lx\r\n",
|
||||
(unsigned long)id,
|
||||
(unsigned long)BSP_SPI_FLASH_JEDEC_ID);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
|
||||
static void gps_ephemeris_flash_loaded(void* ctx, unsigned int prn,
|
||||
const gps_ephemeris_t* ephemeris)
|
||||
{
|
||||
@@ -450,12 +506,14 @@ static void gps_ephemeris_flash_loaded(void* ctx, unsigned int prn,
|
||||
prn, ephemeris->iode, ephemeris->toe.sec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Persistent navigation context: almanac, ionosphere model, last position.
|
||||
* Kept separate from the ephemeris store because it has a different lifetime
|
||||
* (weeks, not hours) and a different shape (one small blob, not a per-PRN log).
|
||||
*/
|
||||
#if (GPS_NAV_CONTEXT_ENABLE == 1)
|
||||
static bool gps_receiver_time_now(int* week_out, double* tow_sec_out);
|
||||
|
||||
static gps_nav_context_store_t gps_nav_context_store;
|
||||
@@ -696,6 +754,9 @@ static void gps_nav_context_flash_service(void)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GPS_NAV_CONTEXT_ENABLE */
|
||||
|
||||
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
|
||||
static void gps_ephemeris_flash_init(void)
|
||||
{
|
||||
gps_ephemeris_store_flash_t flash;
|
||||
@@ -716,14 +777,18 @@ static void gps_ephemeris_flash_init(void)
|
||||
"persistent ephemeris store unavailable\r\n");
|
||||
return;
|
||||
}
|
||||
if((bsp_spi_flash_read_config() & BSP_SPI_FLASH_CONFIG_TBPARM) != 0u)
|
||||
{
|
||||
gps_ephemeris_store_ready = false;
|
||||
gps_runtime_diagnostics.flash_ephemeris_error_total++;
|
||||
GPS_LOG(DEBUG_ERROR, GPS_LOG_CAT_NAV,
|
||||
"ephemeris flash disabled: CR1.TBPARM places 4 KiB sectors at the top\r\n");
|
||||
return;
|
||||
}
|
||||
#if (GPS_EPHEMERIS_STORE_MAX_SLOTS != 0u)
|
||||
gps_ephemeris_store_limit_slots(&gps_ephemeris_store,
|
||||
GPS_EPHEMERIS_STORE_MAX_SLOTS);
|
||||
#endif
|
||||
unsigned int loaded = gps_ephemeris_store_load_all(
|
||||
&gps_ephemeris_store, gps_ephemeris_flash_loaded, NULL);
|
||||
gps_runtime_diagnostics.flash_ephemeris_loaded_total = loaded;
|
||||
|
||||
/*
|
||||
* A blank or unreadable store needs two sector erases before it can hold
|
||||
* anything. Spend them here, during init, rather than letting the first
|
||||
@@ -744,8 +809,35 @@ static void gps_ephemeris_flash_init(void)
|
||||
gps_runtime_diagnostics.flash_ephemeris_error_total++;
|
||||
GPS_LOG(DEBUG_WARNING, GPS_LOG_CAT_NAV,
|
||||
"persistent ephemeris store format failed; persistence disabled\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int loaded = gps_ephemeris_store_load_all(
|
||||
&gps_ephemeris_store, gps_ephemeris_flash_loaded, NULL);
|
||||
#if (GPS_EPHEMERIS_FLASH_SEED_INITIAL == 1)
|
||||
if(loaded == 0u)
|
||||
{
|
||||
unsigned int seeded =
|
||||
gps_ephemeris_store_seed_initial(&gps_ephemeris_store);
|
||||
if(seeded != GPS_EPH_STORE_INITIAL_SEED_COUNT)
|
||||
{
|
||||
gps_runtime_diagnostics.flash_ephemeris_error_total++;
|
||||
GPS_LOG(DEBUG_WARNING, GPS_LOG_CAT_NAV,
|
||||
"initial stale ephemeris seed incomplete: wrote=%u expected=%u\r\n",
|
||||
seeded, GPS_EPH_STORE_INITIAL_SEED_COUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPS_LOG(DEBUG_STATUS, GPS_LOG_CAT_NAV,
|
||||
"initial stale ephemeris seed written: records=%u\r\n",
|
||||
seeded);
|
||||
}
|
||||
loaded = gps_ephemeris_store_load_all(
|
||||
&gps_ephemeris_store, gps_ephemeris_flash_loaded, NULL);
|
||||
}
|
||||
#endif
|
||||
gps_runtime_diagnostics.flash_ephemeris_loaded_total = loaded;
|
||||
GPS_LOG(DEBUG_INFO, GPS_LOG_CAT_NAV,
|
||||
"persistent ephemeris store mounted: generation=%u loaded=%u rejected=%u\r\n",
|
||||
gps_ephemeris_store.generation, loaded,
|
||||
@@ -831,6 +923,7 @@ static void gps_ephemeris_flash_queue(unsigned int prn,
|
||||
gps_ephemeris_flash_pending_mask |= (1u << prn);
|
||||
}
|
||||
#endif /* GPS_EPHEMERIS_FLASH_ENABLE */
|
||||
#endif /* GPS_EPHEMERIS_FLASH_ENABLE || GPS_NAV_CONTEXT_ENABLE */
|
||||
|
||||
static void gps_prn_context_store(unsigned int prn,
|
||||
int week,
|
||||
@@ -1065,6 +1158,7 @@ static void gps_refresh_acq_visibility(void)
|
||||
* retried slowly, and it self-corrects the moment a real fix replaces
|
||||
* the seed.
|
||||
*/
|
||||
#if (GPS_NAV_CONTEXT_ENABLE == 1)
|
||||
if(!gps_nav_context_position_seed_valid)
|
||||
{
|
||||
gps_acq_manager_set_search_mask(&gps_acq_manager, 0xffffffffu);
|
||||
@@ -1086,6 +1180,10 @@ static void gps_refresh_acq_visibility(void)
|
||||
* back to its normal value.
|
||||
*/
|
||||
mask_elevation_deg = GPS_ACQ_VISIBILITY_SEED_MASK_ELEVATION_DEG;
|
||||
#else
|
||||
gps_acq_manager_set_search_mask(&gps_acq_manager, 0xffffffffu);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t mask = 0xffffffffu;
|
||||
@@ -1293,10 +1391,19 @@ static void gps_runtime_state_init(void)
|
||||
gps_ephemeris_cache_init(
|
||||
&gps_ephemeris_cache,
|
||||
GPS_EPHEMERIS_CACHE_MAX_AGE_TICKS);
|
||||
#if ((GPS_EPHEMERIS_FLASH_ENABLE == 1) || (GPS_NAV_CONTEXT_ENABLE == 1))
|
||||
bool gps_flash_ready = gps_flash_device_init();
|
||||
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
|
||||
gps_ephemeris_flash_init();
|
||||
if(gps_flash_ready)
|
||||
{
|
||||
gps_ephemeris_flash_init();
|
||||
}
|
||||
#endif
|
||||
#if (GPS_NAV_CONTEXT_ENABLE == 1)
|
||||
gps_nav_context_flash_init();
|
||||
if(gps_flash_ready)
|
||||
{
|
||||
gps_nav_context_flash_init();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2147,32 +2254,10 @@ static void gps_process_tracking_nav_bits(const gps_isr_event_t* event)
|
||||
unsigned char subframe_id = parse_subframe((unsigned int*)gps_subframe,
|
||||
(gps_frame_t*)gps_frame_parsed,
|
||||
&how_tow_sec);
|
||||
if((subframe_id >= 1u) && (subframe_id <= 3u) &&
|
||||
(gps_frame_parsed->pending_ephemeris_mask == 0u))
|
||||
{
|
||||
bool ephemeris_changed = false;
|
||||
if(gps_ephemeris_cache_store_if_new(
|
||||
&gps_ephemeris_cache, event->prn,
|
||||
(const gps_ephemeris_t*)&gps_frame_parsed->gps_ephems,
|
||||
event->tick, &ephemeris_changed) &&
|
||||
ephemeris_changed)
|
||||
{
|
||||
gps_runtime_diagnostics.ephemeris_cache_store_total++;
|
||||
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
|
||||
/* Only a genuinely new data set reaches flash; the same
|
||||
* broadcast decoded again is filtered out above. */
|
||||
gps_ephemeris_flash_queue(
|
||||
event->prn,
|
||||
(const unsigned int (*)[10])
|
||||
gps_frame_parsed->pending_ephemeris_words);
|
||||
#endif
|
||||
GPS_LOG(DEBUG_INFO, GPS_LOG_CAT_NAV,
|
||||
"stored ephemeris cache: prn=%u trk=%u iode=%u toe=%.0f\r\n",
|
||||
event->prn, trck_ip_no,
|
||||
gps_frame_parsed->gps_ephems.iode,
|
||||
gps_frame_parsed->gps_ephems.toe.sec);
|
||||
}
|
||||
}
|
||||
bool ephemeris_committed =
|
||||
(subframe_id >= 1u) && (subframe_id <= 3u) &&
|
||||
(gps_frame_parsed->pending_ephemeris_mask == 0u);
|
||||
bool how_anchor_accepted = false;
|
||||
if((subframe_id >= 1u) && (subframe_id <= 5u) &&
|
||||
(how_tow_sec < (unsigned int)GPS_TIME_WEEK_SECONDS))
|
||||
{
|
||||
@@ -2226,6 +2311,19 @@ static void gps_process_tracking_nav_bits(const gps_isr_event_t* event)
|
||||
(double)how_tow_sec, event,
|
||||
node->gps_how_week_valid ||
|
||||
(subframe_id == 1u));
|
||||
/* The decoder can only reconstruct Toe in the broadcast's
|
||||
* modulo-1024 week domain. Once HOW has supplied the receiver's
|
||||
* continuous week, lift Toe into that same domain before the
|
||||
* curve-fit age check compares them. */
|
||||
if(gps_frame_parsed->gps_ephems.toe_week_valid)
|
||||
{
|
||||
gps_frame_parsed->gps_ephems.toe.week =
|
||||
gps_time_extend_lnav_week(
|
||||
true, anchor_week,
|
||||
(unsigned int)gps_frame_parsed->gps_ephems.toe.week);
|
||||
}
|
||||
gps_frame_parsed->gps_ephems.tow.week = anchor_week;
|
||||
how_anchor_accepted = true;
|
||||
GPS_LOG(recovered_anchor ? DEBUG_WARNING : DEBUG_TRACE,
|
||||
GPS_LOG_CAT_NAV,
|
||||
"%s HOW anchor: trk=%u prn=%u week=%d tow=%.3f abs=%u corrected=%.6f\r\n",
|
||||
@@ -2258,6 +2356,36 @@ static void gps_process_tracking_nav_bits(const gps_isr_event_t* event)
|
||||
trck_ip_no, subframe_id, how_tow_sec);
|
||||
}
|
||||
|
||||
/* Cache only after Toe has been lifted from WN modulo 1024 into the HOW
|
||||
* anchor's continuous week. Flash persists that full week; storing before
|
||||
* this point makes a fresh record appear 1024 or 2048 weeks old at boot. */
|
||||
if(ephemeris_committed && how_anchor_accepted)
|
||||
{
|
||||
bool ephemeris_changed = false;
|
||||
if(gps_ephemeris_cache_store_if_new(
|
||||
&gps_ephemeris_cache, event->prn,
|
||||
(const gps_ephemeris_t*)&gps_frame_parsed->gps_ephems,
|
||||
event->tick, &ephemeris_changed) &&
|
||||
ephemeris_changed)
|
||||
{
|
||||
gps_runtime_diagnostics.ephemeris_cache_store_total++;
|
||||
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
|
||||
/* Only a genuinely new data set reaches flash; the same
|
||||
* broadcast decoded again is filtered out above. */
|
||||
gps_ephemeris_flash_queue(
|
||||
event->prn,
|
||||
(const unsigned int (*)[10])
|
||||
gps_frame_parsed->pending_ephemeris_words);
|
||||
#endif
|
||||
GPS_LOG(DEBUG_INFO, GPS_LOG_CAT_NAV,
|
||||
"stored ephemeris cache: prn=%u trk=%u iode=%u toe=%d/%.0f\r\n",
|
||||
event->prn, trck_ip_no,
|
||||
gps_frame_parsed->gps_ephems.iode,
|
||||
gps_frame_parsed->gps_ephems.toe.week,
|
||||
gps_frame_parsed->gps_ephems.toe.sec);
|
||||
}
|
||||
}
|
||||
|
||||
gps_mark_node_fresh(node, event->status, event->tick);
|
||||
|
||||
GPS_LOG(DEBUG_TRACE, GPS_LOG_CAT_TRK, "nav bits: trk=%u prn=%u mask=0x%x status=0x%x\r\n",
|
||||
|
||||
@@ -171,14 +171,6 @@ static bool gps_node_has_committed_ephemeris(volatile gps_ephem_ll_t* node)
|
||||
node->data_p->ephemeris_valid;
|
||||
}
|
||||
|
||||
static bool gps_ephemeris_ready_for_position(
|
||||
const gps_ephemeris_t* eph,
|
||||
unsigned int expected_svid)
|
||||
{
|
||||
return gps_ephemeris_check_static(eph, expected_svid) ==
|
||||
GPS_EPHEMERIS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same structural rules plus the IS-GPS-200 curve fit window evaluated at the
|
||||
* epoch's own transmit time. This is what keeps a cached or flash-restored
|
||||
@@ -229,9 +221,26 @@ static bool gps_node_ready_for_position(volatile gps_ephem_ll_t* node)
|
||||
return false;
|
||||
}
|
||||
|
||||
return gps_ephemeris_ready_for_position(
|
||||
if(!node->gps_how_anchor_valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int time_week;
|
||||
double time_sec;
|
||||
if(node->gps_nav_solve_sequence != 0u)
|
||||
{
|
||||
time_week = node->gps_last_nav_solve_tow.week;
|
||||
time_sec = node->gps_last_nav_solve_tow.sec;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_week = node->gps_how_tow.week;
|
||||
time_sec = node->gps_how_tow.sec;
|
||||
}
|
||||
return gps_ephemeris_check(
|
||||
(const gps_ephemeris_t*)node->data_p,
|
||||
trck_ips[node->tracking_ip_no]->PRN_NUMBER);
|
||||
trck_ips[node->tracking_ip_no]->PRN_NUMBER,
|
||||
true, time_week, time_sec) == GPS_EPHEMERIS_OK;
|
||||
}
|
||||
|
||||
static bool gps_channel_nav_solve_enabled(unsigned char trck_ip_no)
|
||||
|
||||
Reference in New Issue
Block a user