@@ -579,6 +579,11 @@ bool GNSS_MOSAIC::configureOnce()
579
579
setting = String (" sso,Stream" + String (MOSAIC_SBF_INPUTLINK_STREAM) + " ,COM1,InputLink,sec1\n\r " );
580
580
response &= sendWithResponse (setting, " SBFOutput" );
581
581
582
+ // Output SBF ChannelStatus on its own stream - at 0.5Hz - on COM1 only
583
+ // OnChange is too often. The message is typically 1000 bytes in size.
584
+ setting = String (" sso,Stream" + String (MOSAIC_SBF_CHANNELSTATUS_STREAM) + " ,COM1,ChannelStatus,sec2\n\r " );
585
+ response &= sendWithResponse (setting, " SBFOutput" );
586
+
582
587
response &= setElevation (settings.minElev );
583
588
584
589
response &= setMinCnoRadio (settings.minCNO );
@@ -2367,16 +2372,105 @@ void GNSS_MOSAIC::storeBlock4007(SEMP_PARSE_STATE *parse)
2367
2372
_longitude = sempSbfGetF8 (parse, 24 ) * 180.0 / PI;
2368
2373
_altitude = (float )sempSbfGetF8 (parse, 32 );
2369
2374
_horizontalAccuracy = ((float )sempSbfGetU2 (parse, 90 )) / 100.0 ; // Convert from cm to m
2370
- _satellitesInView = sempSbfGetU1 (parse, 74 );
2371
- if (_satellitesInView == 255 ) // 255 indicates "Do-Not-Use"
2372
- _satellitesInView = 0 ;
2375
+
2376
+ // NrSV is the total number of satellites used in the PVT computation.
2377
+ // _satellitesInView = sempSbfGetU1(parse, 74);
2378
+ // if (_satellitesInView == 255) // 255 indicates "Do-Not-Use"
2379
+ // _satellitesInView = 0;
2380
+
2373
2381
_fixType = sempSbfGetU1 (parse, 14 ) & 0x0F ;
2374
2382
_determiningFixedPosition = (sempSbfGetU1 (parse, 14 ) >> 6 ) & 0x01 ;
2375
2383
_clkBias_ms = sempSbfGetF8 (parse, 60 );
2376
2384
_pvtArrivalMillis = millis ();
2377
2385
_pvtUpdated = true ;
2378
2386
}
2379
2387
2388
+ // ----------------------------------------
2389
+ // Save the data from the SBF Block 4013
2390
+ // ----------------------------------------
2391
+ void GNSS_MOSAIC::storeBlock4013 (SEMP_PARSE_STATE *parse)
2392
+ {
2393
+ uint16_t N = (uint16_t )sempSbfGetU1 (parse, 14 );
2394
+ uint16_t SB1Length = (uint16_t )sempSbfGetU1 (parse, 15 );
2395
+ uint16_t SB2Length = (uint16_t )sempSbfGetU1 (parse, 16 );
2396
+ uint16_t ChannelInfoBytes = 0 ;
2397
+ for (uint16_t i = 0 ; i < N; i++)
2398
+ {
2399
+ uint8_t SVID = sempSbfGetU1 (parse, 20 + ChannelInfoBytes + 0 );
2400
+
2401
+ uint16_t N2 = (uint16_t )sempSbfGetU1 (parse, 20 + ChannelInfoBytes + 9 );
2402
+
2403
+ for (uint16_t j = 0 ; j < N2; j++)
2404
+ {
2405
+ uint16_t TrackingStatus = sempSbfGetU2 (parse, 20 + ChannelInfoBytes + SB1Length + (j * SB2Length) + 2 );
2406
+
2407
+ bool Tracking = false ;
2408
+ for (uint16_t shift = 0 ; shift < 16 ; shift += 2 ) // Step through each 2-bit status field
2409
+ {
2410
+ if ((TrackingStatus & (0x0003 << shift)) == (0x0003 << shift)) // 3 : Tracking
2411
+ {
2412
+ Tracking = true ;
2413
+ }
2414
+ }
2415
+
2416
+ if (Tracking)
2417
+ {
2418
+ // SV is being tracked. If it is not in svInTracking, add it
2419
+ std::vector<uint8_t >::iterator pos =
2420
+ std::find (svInTracking.begin (), svInTracking.end (), SVID);
2421
+ if (pos == svInTracking.end ())
2422
+ svInTracking.push_back (SVID);
2423
+ }
2424
+ else
2425
+ {
2426
+ // SV is not being tracked. If it is in svInTracking, remove it
2427
+ std::vector<uint8_t >::iterator pos =
2428
+ std::find (svInTracking.begin (), svInTracking.end (), SVID);
2429
+ if (pos != svInTracking.end ())
2430
+ svInTracking.erase (pos);
2431
+ }
2432
+
2433
+ // uint16_t PVTStatus = sempSbfGetU2(parse, 20 + ChannelInfoBytes + SB1Length + (j * SB2Length) + 4);
2434
+
2435
+ // bool Used = false;
2436
+ // for (uint16_t shift = 0; shift < 16; shift += 2) // Step through each 2-bit status field
2437
+ // {
2438
+ // if ((PVTStatus & (0x0003 << shift)) == (0x0002 << shift)) // 2 : Used
2439
+ // {
2440
+ // Used = true;
2441
+ // }
2442
+ // }
2443
+
2444
+ // if (Used)
2445
+ // {
2446
+ // // SV is being used for PVT. If it is not in svInPVT, add it
2447
+ // std::vector<uint8_t>::iterator pos =
2448
+ // std::find(svInPVT.begin(), svInPVT.end(), SVID);
2449
+ // if (pos == svInPVT.end())
2450
+ // svInPVT.push_back(SVID);
2451
+ // }
2452
+ // else
2453
+ // {
2454
+ // // SV is not being used for PVT. If it is in svInPVT, remove it
2455
+ // std::vector<uint8_t>::iterator pos =
2456
+ // std::find(svInPVT.begin(), svInPVT.end(), SVID);
2457
+ // if (pos != svInPVT.end())
2458
+ // svInPVT.erase(pos);
2459
+ // }
2460
+
2461
+ }
2462
+
2463
+ ChannelInfoBytes += SB1Length + (N2 * SB2Length);
2464
+ }
2465
+
2466
+ _satellitesInView = (uint8_t )std::distance (svInTracking.begin (), svInTracking.end ());
2467
+
2468
+ // uint8_t _inPVT = (uint8_t)std::distance(svInPVT.begin(), svInPVT.end());
2469
+
2470
+ // systemPrintf("%d %d %d %d %d %d\r\n", N, SB1Length, SB2Length, ChannelInfoBytes, _satellitesInView, _inPVT);
2471
+
2472
+ }
2473
+
2380
2474
// ----------------------------------------
2381
2475
// Save the data from the SBF Block 4090
2382
2476
// ----------------------------------------
@@ -2726,6 +2820,10 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type)
2726
2820
if (sempSbfGetBlockNumber (parse) == 4007 )
2727
2821
mosaic->storeBlock4007 (parse);
2728
2822
2823
+ // If this is ChannelStatus, extract some data
2824
+ if (sempSbfGetBlockNumber (parse) == 4013 )
2825
+ mosaic->storeBlock4013 (parse);
2826
+
2729
2827
// If this is InputLink, extract some data
2730
2828
if (sempSbfGetBlockNumber (parse) == 4090 )
2731
2829
mosaic->storeBlock4090 (parse);
0 commit comments