ublox E6 patch based on ptudor

ublox-e6
Jeff Moe 2022-06-16 11:31:05 -06:00
parent c27b3466e6
commit e5b5fbe509
8 changed files with 161 additions and 24 deletions

View File

@ -25,6 +25,11 @@ bool getTOWFromInav(std::basic_string_view<uint8_t> inav, uint32_t *satTOW, uint
return false;
}
bool getTOWFromFnav(std::basic_string_view<uint8_t> fnav, uint32_t *satTOW, uint16_t *wn)
{
return false;
}
int GalileoMessage::parseFnav(std::basic_string_view<uint8_t> page)
{
const uint8_t* ptr = &page[0];

View File

@ -7,6 +7,7 @@
#include "bits.hh"
bool getTOWFromInav(std::basic_string_view<uint8_t> inav, uint32_t *satTOW, uint16_t *wn);
bool getTOWFromFnav(std::basic_string_view<uint8_t> fnav, uint32_t *satTOW, uint16_t *wn);
struct GalileoMessage : GPSLikeEphemeris
{

View File

@ -303,6 +303,8 @@ function updateSats()
wantIt = true;
if(d3.select("#GPSL2C").property("checked") && arr[n].gnssid==0 && arr[n].sigid == 4)
wantIt = true;
if(d3.select("#GPSL5").property("checked") && arr[n].gnssid==0 && arr[n].sigid == 6)
wantIt = true;
if(d3.select("#BeiDouB1I").property("checked") && arr[n].gnssid==3 && arr[n].sigid == 0)
wantIt = true;
if(d3.select("#BeiDouB2I").property("checked") && arr[n].gnssid==3 && arr[n].sigid == 2)
@ -311,6 +313,10 @@ function updateSats()
wantIt = true;
if(d3.select("#GlonassL2").property("checked") && arr[n].gnssid==6 && arr[n].sigid == 2)
wantIt = true;
if(d3.select("#NAVICL5").property("checked") && arr[n].gnssid==98 && arr[n].sigid == 6)
wantIt = true;
if(d3.select("#QZSSL5").property("checked") && arr[n].gnssid==99 && arr[n].sigid == 6)
wantIt = true;
if(!wantIt)
continue;
@ -383,7 +389,7 @@ function setButtonSetting(name)
localStorage.setItem("want"+name, d3.select("#"+name).property("checked"));
}
var modes=["GalE1", "GalE5b", "GPSL1CA", "GPSL2C", "BeiDouB1I", "BeiDouB2I", "GlonassL1", "GlonassL2"];
var modes=["GalE1", "GalE5b", "GalE5a", "GPSL1CA", "GPSL2C", "GPSL5", "BeiDouB1I", "BeiDouB2I", "GlonassL1", "GlonassL2", "NAVICL5", "QZSSL5"];
function setButtonSettings()
{

View File

@ -18,6 +18,9 @@
<input type="checkbox" id="GlonassL2" onclick="updateSats();"> <label for="GlonassL2">Glonass L2</label> &nbsp;&nbsp;
<input type="checkbox" id="GPSL1CA" onclick="updateSats();"> <label for="GPSL1CA">GPS L1C/A</label> &nbsp;&nbsp;
<input type="checkbox" id="GPSL2C" onclick="updateSats();"> <label for="GPSL2C">GPS L2C</label>
<input type="checkbox" id="GPSL5" onclick="updateSats();"> <label for="GPSL5">GPS L5</label>
<input type="checkbox" id="NAVICL5" onclick="updateSats();"> <label for="NAVICL5">NavIC L5</label>
<input type="checkbox" id="QZSSL5" onclick="updateSats();"> <label for="QZSSL5">QZSS L5</label>
</div>
<hr/>
<table id="svs"></table>

View File

@ -872,7 +872,7 @@ try
item["observed"] = false;
for(uint32_t sigid : {0,1,5}) {
for(uint32_t sigid : {0,1,5,6}) {
if(auto iter = svstats.find({2, (uint32_t)ae.first, sigid}); iter != svstats.end()) {
if(iter->second.completeIOD()) {
@ -937,7 +937,7 @@ try
item["eph-latitude"]= 180*longlat.second/M_PI;
item["observed"] = false;
for(uint32_t sigid : {0,1,4}) {
for(uint32_t sigid : {0,1,4,6}) {
if(auto iter = svstats.find({0, (uint32_t)ae.first, sigid}); iter != svstats.end()) {
if(time(0) - nanoTime(0, iter->second.wn(), iter->second.tow())/1000000000 < 300)
item["observed"] = true;
@ -1928,6 +1928,8 @@ try
int sigid = nmm.rd().sigid();
if(gnssid==2 && sigid == 0)
sigid = 1;
if(gnssid==2 && sigid == 4)
sigid = 3;
SatID id{(uint32_t)gnssid, (uint32_t)sv, (uint32_t)sigid};
auto& perrecv = g_svstats[id].perrecv[nmm.sourceid()];

12
ubx.cc
View File

@ -163,3 +163,15 @@ basic_string<uint8_t> getSBASFromSFRBXMsg(std::basic_string_view<uint8_t> msg)
return payload;
}
basic_string<uint8_t> getFnavFromSFRBXMsg(std::basic_string_view<uint8_t> msg)
{
// byte order adjustment
std::basic_string<uint8_t> payload;
for(unsigned int i = 0 ; i < (msg.size() - 8) / 4; ++i)
for(int j=1; j <= 4; ++j)
payload.append(1, msg[8 + (i+1) * 4 -j]);
return payload;
}

1
ubx.hh
View File

@ -17,6 +17,7 @@ std::basic_string<uint8_t> getGPSFromSFRBXMsg(std::basic_string_view<uint8_t> ms
std::basic_string<uint8_t> getGlonassFromSFRBXMsg(std::basic_string_view<uint8_t> msg);
std::basic_string<uint8_t> getBeidouFromSFRBXMsg(std::basic_string_view<uint8_t> msg);
std::basic_string<uint8_t> getSBASFromSFRBXMsg(std::basic_string_view<uint8_t> msg);
std::basic_string<uint8_t> getFnavFromSFRBXMsg(std::basic_string_view<uint8_t> msg);
struct CRCMismatch{};
struct TrkSatStat

View File

@ -56,6 +56,8 @@ static int getBaudrate(int baud)
{
if(baud==115200)
return B115200;
else if(baud==460800)
return B460800;
else if(baud==57600)
return B57600;
else if(baud==38400)
@ -72,6 +74,8 @@ static int getBaudrateFromSymbol(int baud)
{
if(baud==B115200)
return 115200;
else if(baud==B460800)
return 460800;
else if(baud==B57600)
return 57600;
else if(baud==B38400)
@ -293,13 +297,14 @@ bool sendAndWaitForUBXAckNack(int fd, int seconds, basic_string_view<uint8_t> ms
bool version9 = false;
bool version9_L2_E5b = false;
bool version9_L5_E5a = false;
void enableUBXMessageOnPort(int fd, uint8_t ubxClass, uint8_t ubxType, uint8_t port, uint8_t rate=1)
{
for(int n=0 ; n < 5; ++n) {
try {
basic_string<uint8_t> payload;
if(version9) {
if(version9_L2_E5b || version9_L5_E5a) {
payload= basic_string<uint8_t>({ubxClass, ubxType, rate});
}
else {
@ -503,6 +508,7 @@ int main(int argc, char** argv)
bool doGPS{true}, doGalileo{true}, doGlonass{false}, doBeidou{false}, doReset{false}, doWait{true}, doRTSCTS{true}, doSBAS{false};
bool doQZSS(false), doNAVIC(false);
bool doFakeFix{false};
bool doKeepNMEA{false};
bool doSTDOUT=false;
@ -528,6 +534,9 @@ int main(int argc, char** argv)
app.add_flag("--glonass,-r", doGlonass, "Enable Glonass reception");
app.add_flag("--galileo,-e", doGalileo, "Enable Galileo reception");
app.add_flag("--sbas,-s", doSBAS, "Enable SBAS (EGNOS/WAAS/etc) reception");
app.add_flag("--zed-e5a", version9_L5_E5a, "Enable uBlox ZED F9T-10B support for L5 signals");
app.add_flag("--navic", doNAVIC, "Enable NAVIC reception");
app.add_flag("--qzss", doQZSS, "Enable QZSS reception");
app.add_option("--rtscts", doRTSCTS, "Set hardware handshaking");
app.add_flag("--stdout", doSTDOUT, "Emit output to stdout");
auto pn = app.add_option("--port,-p", portName, "Device or file to read serial from");
@ -593,7 +602,7 @@ int main(int argc, char** argv)
baudrate = getBaudrateFromSymbol(g_baudval);
if(doFakeFix) // hack
version9 = true;
version9_L2_E5b = true;
bool m8t = false;
string hwversion;
@ -647,7 +656,9 @@ int main(int argc, char** argv)
cerr<<humanTimeNow()<<" Extended info: "<<line <<endl;
if(line.find("F9") != string::npos)
version9=true;
if (!version9_L5_E5a) {
version9_L2_E5b=true;
}
if(line.find("M8T") != string::npos) {
m8t=true;
@ -667,8 +678,10 @@ int main(int argc, char** argv)
cerr<<humanTimeNow()<<" Serial number "<< serialno <<endl;
if(version9)
if(version9_L2_E5b)
cerr<<humanTimeNow()<<" Detected version U-Blox 9"<<endl;
if(version9_L5_E5a)
cerr<<humanTimeNow()<<" Detected version U-Blox 9 on ZED F9T 10B with L5 signals"<<endl;
usleep(50000);
if (doDEBUG) { cerr<<humanTimeNow()<<" Sending GNSS query"<<endl; }
msg = buildUbxMessage(0x06, 0x3e, {});
@ -689,7 +702,7 @@ int main(int argc, char** argv)
}catch(...) {
cerr<<"Got timeout waiting for ack of poll, no problem"<<endl;
}
if(!version9) {
if(!version9_L2_E5b && !version9_L5_E5a) {
// ver RO maxch cfgs
msg = buildUbxMessage(0x06, 0x3e, {0x00, 0x00, 0xff, 0x06,
// GPS min max res x1 x2 x3, x4
@ -718,6 +731,61 @@ int main(int argc, char** argv)
exit(-1);
}
}
else if(version9_L5_E5a) {
// UBX-CFG-VALSET
// vers ram res res
/*
* compat
B5 62 06 8A 63
00 01 05 00 00
-
01 00 31 10 01 //signal Gps L1C
04 00 31 10 00 //signal GPS L5
05 00 31 10 00 //signal SBAS L1C
07 00 31 10 01 //sig GAL E1
09 00 31 10 00 //sig GAL E5a
0D 00 31 10 01 //sig BDS B1
0F 00 31 10 01 //sig BDS B1c
12 00 31 10 01 //sig QZSS L1C/A
17 00 31 10 00 //sig QZSS L5
18 00 31 10 01 //sig GLO L1
1D 00 31 10 01 //sig NAVIC L5
1F 00 31 10 01 //enable GPS
20 00 31 10 00 //enable SBAS
21 00 31 10 01 //enable GAL
22 00 31 10 01 //enable BDS
24 00 31 10 00 //sig GLO L1 part two? dunno
25 00 31 10 01 //enable GLO
26 00 31 10 00 //enable NAVIC
28 00 31 10 01 //sig BDS B2a
33 73
*/
bool doCrashFast = false;
msg = buildUbxMessage(0x06, 0x8a,
{0x01,0x01,0x00,0x00, // intro stanza ptudor blindly copied
0x01,0x00,0x31,0x10, doGPS, // signal gps L1C/A
0x04,0x00,0x31,0x10, doGPS, // signal gps L5
0x1f,0x00,0x31,0x10, doGPS, // enable GPS
0x21,0x00,0x31,0x10, doGalileo, //enable
0x07,0x00,0x31,0x10, doGalileo, // signal E1
// getting CRC errors on E5a
0x09,0x00,0x31,0x10, doGalileo, //signal E5a
0x0d,0x00,0x31,0x10, doBeidou, // BDS B1
// getting a nack from this one
//0x0f,0x00,0x31,0x10, doBeidou, // BDS B1C
// getting an immediate crash with this one
//0x28,0x00,0x31,0x10, doBeidou, // BDS B2a
0x28,0x00,0x31,0x10, doCrashFast, // BDS B2a
0x22,0x00,0x31,0x10, doBeidou, // BDS enable
0x25,0x00,0x31,0x10, doGlonass, //enable GLO
0x18,0x00,0x31,0x10, doGlonass, // GLO L1
0x24,0x00,0x31,0x10, doGlonass //Glo part 2
});
}
else { // UBX-CFG-VALSET
// vers ram res res
msg = buildUbxMessage(0x06, 0x8a, {0x00, 0x01, 0x00, 0x00,
@ -737,8 +805,9 @@ int main(int argc, char** argv)
0x18,0x00,0x31,0x10, doGlonass,
0x1a,0x00,0x31,0x10, doGlonass
});
if (doDEBUG) { cerr<<humanTimeNow()<<" Sending F9P GNSS setting, GPS: "<<doGPS<<", Galileo: "<<doGalileo<<", BeiDou: "<<doBeidou<<", GLONASS: "<<doGlonass<<", SBAS: "<<doSBAS<<endl; }
}
if(version9_L2_E5b || version9_L5_E5a) {
if (doDEBUG) { cerr<<humanTimeNow()<<" Sending F9P GNSS setting, GPS: "<<doGPS<<", Galileo: "<<doGalileo<<", BeiDou: "<<doBeidou<<", GLONASS: "<<doGlonass<<", SBAS: "<<doSBAS<<", QZSS: "<<doQZSS<<", NAVIC: "<<doNAVIC<<endl; }
if(sendAndWaitForUBXAckNack(fd, 2, msg, 0x06, 0x8a)) { // GNSS setting, F9 stylee
if (doDEBUG) { cerr<<humanTimeNow()<<" Got ack on F9P GNSS setting"<<endl; }
@ -809,7 +878,7 @@ int main(int argc, char** argv)
uint8_t* ptrSeconds = (uint8_t*)&minSecondsVal, *ptrCent= (uint8_t*)&minCentimetersVal;
uint8_t cmd;
std::basic_string<uint8_t> msg;
if(version9) {
if(version9_L2_E5b) {
cmd = 0x8a;
msg = buildUbxMessage(0x06, cmd, {0x00, 0x01, 0x00, 0x00,
0x01,0x00,0x03,0x20, 1, // survey in mode
@ -930,12 +999,7 @@ int main(int argc, char** argv)
if (doDEBUG) { cerr<<humanTimeNow()<<" Enabling UBX-MON-HW"<<endl; }
enableUBXMessageOnPort(fd, 0x0A, 0x09, ubxport, 16); // UBX-MON-HW
if(version9) {
if (doDEBUG) { cerr<<humanTimeNow()<<" Enabling UBX-NAV-SVIN"<<endl; } // Survey-in results
enableUBXMessageOnPort(fd, 0x01, 0x3b, ubxport, 2);
}
else if(m8t) {
if(m8t) {
if (doDEBUG) { cerr<<humanTimeNow()<<" Enabling UBX-TIM-SVIN"<<endl; } // Survey-in results
enableUBXMessageOnPort(fd, 0x0d, 0x04, ubxport, 2);
}
@ -964,7 +1028,7 @@ int main(int argc, char** argv)
}
}
if(!version9 && !m8t && !fuzzPositionMeters) {
if(!version9_L2_E5b && !m8t && !fuzzPositionMeters) {
if (doDEBUG) { cerr<<humanTimeNow()<<" Enabling debugging data"<<endl; } // RF doppler
enableUBXMessageOnPort(fd, 0x03, 0x10, ubxport, 4);
}
@ -977,7 +1041,7 @@ int main(int argc, char** argv)
if (doDEBUG) { cerr<<humanTimeNow()<<" Enabling UBX-NAV-POSECEF"<<endl; } // position
enableUBXMessageOnPort(fd, 0x01, 0x01, ubxport, 8); // POSECEF
if(version9) {
if(version9_L2_E5b || version9_L5_E5a) {
if (doDEBUG) { cerr<<humanTimeNow()<<" Enabling UBX-NAV-SIG"<<endl; } // satellite reception details
enableUBXMessageOnPort(fd, 0x01, 0x43, ubxport, 8); // NAV-SIG
/*
@ -1216,12 +1280,22 @@ int main(int argc, char** argv)
int gnssid = payload[36+32*n];
int sv = payload[37+32*n];
int sigid=0;
if(version9) {
if(version9_L2_E5b || version9_L5_E5a) {
sigid = payload[38+32*n];
if(gnssid == 2 && sigid ==4) // they separate out I and Q, but the rest of UBX doesn't
sigid = 3; // so map it back
if(gnssid == 2 && sigid ==6) // they separate out I and Q, but the rest of UBX doesn't
sigid = 5; // so map it back
if(gnssid == 2 && sigid ==0) // they separate out I and Q, but the rest of UBX doesn't
sigid = 1; // so map it back
if(gnssid ==0) {
if(sigid==3) // L2C is sent as '4' and '3', but the '4' numbers here are bogus
sigid=4; // if we see 3, use it, and change number to 4 to be consistent
if(sigid==7) // L5-CNAV is sent as '6' and '7', but the '7' numbers here are bogus
sigid=6; // if we see 7, use it, and change number to 6 to be consistent
else if(sigid != 0) // sigid 0 = 0
continue; // ignore the rest
}
}
else if(gnssid==2) { // version 8 defaults galileo to E1B
sigid = 1;
@ -1357,7 +1431,7 @@ int main(int argc, char** argv)
ns.emitNMM( nmm);
continue;
}
if(id.first == 0 && sigid) { // new GPS
if(id.first == 0 && sigid) { // "The L5-CNAV is modulated onto L5I signal component, containing basically the same information data as L2-CNAV. The message structure is exactly the same but its content may vary slightly.
auto cnav = getGPSFromSFRBXMsg(payload);
static int wn, tow;
@ -1385,6 +1459,7 @@ int main(int argc, char** argv)
ns.emitNMM( nmm);
}
else if(id.first ==2) { // GALILEO
if(sigid == 1 || sigid == 5) {
basic_string<uint8_t> reserved1, reserved2, sar, spare, crc;
auto inav = getInavFromSFRBXMsg(payload, reserved1, reserved2, sar, spare, crc);
unsigned int wtype = getbitu(&inav[0], 0, 6);
@ -1474,6 +1549,30 @@ int main(int argc, char** argv)
nmm.mutable_gi()->set_spare((const char*)&spare[0], spare.size());
ns.emitNMM( nmm);
}
else if(sigid == 3) {
auto fnav = getFnavFromSFRBXMsg(payload);
uint32_t satTOW;
int msgTOW{0};
if(getTOWFromFnav(fnav, &satTOW, &g_galwn)) { // 0, 6, 5
msgTOW = satTOW;
curCycleTOW = satTOW - (satTOW %30);
}
auto gstr = getFnavFromSFRBXMsg(payload);
NavMonMessage nmm;
nmm.set_localutcseconds(g_gnssutc.tv_sec);
nmm.set_localutcnanoseconds(g_gnssutc.tv_nsec);
nmm.set_sourceid(g_srcid);
nmm.set_type(NavMonMessage::GalileoFnavType);
nmm.mutable_gf()->set_gnssid(id.first);
nmm.mutable_gf()->set_gnsssv(id.second);
nmm.mutable_gf()->set_sigid(sigid);
nmm.mutable_gf()->set_contents(string((char*)gstr.c_str(), gstr.size()));
nmm.mutable_gf()->set_gnsswn(g_galwn);
nmm.mutable_gf()->set_gnsstow(msgTOW);
ns.emitNMM( nmm);
}
}
else if(id.first==3) {
auto gstr = getGlonassFromSFRBXMsg(payload);
@ -1571,7 +1670,7 @@ int main(int argc, char** argv)
}
else if(msg.getClass() == 1 && msg.getType() == 0x35) { // UBX-NAV-SAT
if(version9) // we have UBX-NAV-SIG
if(version9_L2_E5b || version9_L5_E5a)
continue;
// if (doDEBUG) { cerr<<humanTimeNow()<<" Info for "<<(int) payload[5]<<" svs: \n"; }
for(unsigned int n = 0 ; n < payload[5]; ++n) {
@ -1627,15 +1726,23 @@ int main(int argc, char** argv)
memcpy(&sigflags, &payload[18+16*n], 2);
int sigid = 0;
if(version9) { // we only use this on version9 right now tho
if(version9_L2_E5b || version9_L5_E5a) { // we only use this on version9_L2_E5b right now tho
sigid = payload[10+16*n];
// sigId 3 = E5aI; sigId 4 = e5aQ; sigId 5 = e5bI ; sigId 6 = E5bQ
if(gnssid == 2 && sigid ==4) // they separate out I and Q, but the rest of UBX doesn't
sigid = 3; // so map it back
if(gnssid == 2 && sigid ==6) // they separate out I and Q, but the rest of UBX doesn't
sigid = 5; // so map it back
// reset 3 to 6 after 6 becomes 5 and 4 becomes 3. my brain hurts. see page 19 UBX-21048598
if(gnssid == 2 && sigid ==3) // they separate out I and Q, but the rest of UBX doesn't
sigid = 6; // so map it back
if(gnssid == 2 && sigid ==0)
sigid = 1;
if(gnssid ==0) {
if(sigid==3) // L2C is sent as '4' and '3', but the '4' numbers here are bogus
sigid=4; // if we see 3, use it, and change number to 4 to be consistent
if(sigid==7) // L5-CNAV is sent as '6' and '7', but the '7' numbers here are bogus
sigid=6; // if we see 7, use it, and change number to 6 to be consistent
else if(sigid != 0) // sigid 0 = 0
continue; // ignore the rest
}