pull/1/head
bert hubert 2019-07-24 13:24:48 +02:00
parent be82279efd
commit e793f440cd
3 changed files with 262 additions and 50 deletions

View File

@ -1,6 +1,6 @@
CXXFLAGS:= -std=gnu++17 -Wall -O3 -MMD -MP -ggdb -fno-omit-frame-pointer -Iext/fmt-5.2.1/include/
PROGRAMS = ubxparse
PROGRAMS = ubxparse minread
all: $(PROGRAMS)
@ -10,5 +10,5 @@ clean:
rm -f *~ *.o *.d ext/*/*.o $(PROGRAMS)
ubxparse: ubxparse.o ext/fmt-5.2.1/src/format.o
g++ -std=gnu++17 $^ -o $@ -pthread
g++ -std=gnu++17 $^ -o $@ -pthread -lncurses

View File

@ -41,11 +41,12 @@ int main()
tcsetattr(fd,TCSANOW,&newtio);
for(;;) {
res = read(fd, buf, 255);
res = read(fd, buf, 25);
if(res < 0)
break;
for(int n=0; n < res; ++n)
printf("%c", buf[n]);
fflush(stdout);
}
tcsetattr(fd,TCSANOW,&oldtio);
}

View File

@ -5,7 +5,10 @@
#include "fmt/format.h"
#include "fmt/printf.h"
#include <fstream>
#include <map>
#include <bitset>
#include <curses.h>
#include <vector>
using namespace std;
struct EofException{};
@ -38,6 +41,13 @@ unsigned int getbitu(const unsigned char *buff, int pos, int len)
return bits;
}
extern int getbits(const unsigned char *buff, int pos, int len)
{
unsigned int bits=getbitu(buff,pos,len);
if (len<=0||32<=len||!(bits&(1u<<(len-1)))) return (int)bits;
return (int)(bits|(~0u<<len)); /* extend sign */
}
uint16_t calcUbxChecksum(uint8_t ubxClass, uint8_t ubxType, std::basic_string_view<uint8_t> str)
{
@ -58,18 +68,205 @@ uint16_t calcUbxChecksum(uint8_t ubxClass, uint8_t ubxType, std::basic_string_vi
return (CK_B << 8) + CK_A;
}
struct SVIOD
{
std::bitset<32> words;
uint32_t t0e;
uint8_t sisa;
bool complete() const
{
return words[1] && words[3];
}
void addWord(std::basic_string_view<uint8_t> page);
};
void SVIOD::addWord(std::basic_string_view<uint8_t> page)
{
uint8_t wtype = getbitu(&page[0], 0, 6);
words[wtype]=true;
if(wtype == 1) {
t0e = 60*getbitu(&page[0], 16, 14);
}
else if(wtype == 3) {
sisa = getbitu(&page[0], 120, 8);
}
}
struct SVStat
{
uint8_t e5bhs{0}, e1bhs{0};
bool e5bdvs{false}, e1bdvs{false};
bool disturb1{false}, disturb2{false}, disturb3{false}, disturb4{false}, disturb5{false};
uint16_t wn{0};
uint32_t tow{0}; // "last seen"
uint32_t a0{0}, a1{0};
map<int, SVIOD> iods;
void addWord(std::basic_string_view<uint8_t> page);
bool completeIOD() const;
uint16_t getIOD() const;
SVIOD liveIOD() const;
};
bool SVStat::completeIOD() const
{
for(const auto& iod : iods)
if(iod.second.complete())
return true;
return false;
}
uint16_t SVStat::getIOD() const
{
for(const auto& iod : iods)
if(iod.second.complete())
return iod.first;
throw std::runtime_error("Asked for unknown IOD");
}
SVIOD SVStat::liveIOD() const
{
if(auto iter = iods.find(getIOD()); iter != iods.end())
return iter->second;
throw std::runtime_error("Asked for unknown IOD");
}
void SVStat::addWord(std::basic_string_view<uint8_t> page)
{
uint8_t wtype = getbitu(&page[0], 0, 6);
if(wtype >=1 && wtype <= 4) { // ephemeris
uint16_t iod = getbitu(&page[0], 6, 10);
iods[iod].addWord(page);
if(iods[iod].complete()) {
SVIOD latest = iods[iod];
iods.clear();
iods[iod] = latest;
}
}
else if(wtype==5) { // disturbance, health, time
e5bhs = getbitu(&page[0], 67, 2);
e1bhs = getbitu(&page[0], 69, 2);
e5bdvs = getbitu(&page[0], 71, 1);
e1bdvs = getbitu(&page[0], 72, 1);
wn = getbitu(&page[0], 73, 12);
tow = getbitu(&page[0], 85, 20);
// cout<<"Setting tow to "<<tow<<endl;
}
}
struct WinKeeper
{
WinKeeper();
struct Window
{
WINDOW *header, *text;
int sv;
void setHeader(std::string_view line)
{
wclear(header);
wmove(header, 0, 0);
wattron(header, A_BOLD | A_UNDERLINE);
wprintw(header, "%s", &line[0]);
wattroff(header, A_BOLD | A_UNDERLINE);
wrefresh(header);
}
void setStatus(std::string_view line)
{
wmove(header, 1, 0);
wattron(header, A_BOLD);
wprintw(header, "%s", &line[0]);
wattroff(header, A_BOLD);
wrefresh(header);
}
void emitLine(std::string_view line)
{
wprintw(text, "%s\n", &line[0]);
wrefresh(text);
}
};
vector<Window> d_windows;
static int d_h, d_w;
void emitLine(int sv, std::string_view line);
void setStatus(int sv, std::string_view line);
};
int WinKeeper::d_h;
int WinKeeper::d_w;
WinKeeper::WinKeeper()
{
initscr();
getmaxyx(stdscr, d_h, d_w);
int winwidth = d_w / 6;
for(int n=0; n < 5 ; ++n) {
d_windows.push_back({
newwin(3, winwidth, 0, n*(winwidth+2)),
newwin(d_h-3, winwidth, 3, n*(winwidth+2)),
0});
scrollok(d_windows[n].text, 1);
}
};
void WinKeeper::emitLine(int sv, std::string_view line)
{
for(auto& w: d_windows) {
if(w.sv == sv) {
w.emitLine(line);
return;
}
}
// nothing matched
for(auto& w: d_windows) {
if(!w.sv) {
w.sv = sv;
w.setHeader(std::to_string(sv));
w.emitLine(line);
return;
}
}
throw std::runtime_error("Ran out of windows searching for sv "+std::to_string(sv));
}
void WinKeeper::setStatus(int sv, std::string_view line)
{
for(auto& w: d_windows) {
if(w.sv == sv) {
w.setStatus(line);
return;
}
}
// nothing matched
for(auto& w: d_windows) {
if(!w.sv) {
w.sv = sv;
w.setHeader(std::to_string(sv));
w.setStatus(line);
return;
}
}
throw std::runtime_error("Ran out of windows searching for sv "+std::to_string(sv));
}
std::map<int, SVStat> g_svstats;
int main()
try
{
unsigned int tow=0, wn=0;
WinKeeper wk;
// unsigned int tow=0, wn=0;
ofstream csv("iod.csv");
ofstream csv2("toe.csv");
csv<<"timestamp sv iod sisa"<<endl;
csv2<<"timestamp sv tow toe"<<endl;
int tow=0;
for(;;) {
auto c = getUint8();
if(c != 0xb5) {
cout << (char)c;
// cout << (char)c;
continue;
}
c = getUint8();
@ -84,7 +281,7 @@ try
uint8_t ubxType = getUint8();
uint16_t msgLen = getUint16();
cout <<"Had an ubx message of class "<<(int) ubxClass <<" and type "<< (int) ubxType << " of " << msgLen <<" bytes"<<endl;
// cout <<"Had an ubx message of class "<<(int) ubxClass <<" and type "<< (int) ubxType << " of " << msgLen <<" bytes"<<endl;
std::basic_string<uint8_t> msg;
msg.reserve(msgLen);
@ -94,42 +291,49 @@ try
uint16_t ubxChecksum = getUint16();
if(ubxChecksum != calcUbxChecksum(ubxClass, ubxType, msg)) {
cout<<"Checksum: "<<ubxChecksum<< ", calculated: "<<
calcUbxChecksum(ubxClass, ubxType, msg)<<endl;
calcUbxChecksum(ubxClass, ubxType, msg)<<"\n";
}
if(ubxClass == 2 && ubxType == 89) { // SAR
cout<<"SAR: sv = "<< (int)msg[2] <<" ";
for(int n=4; n < 12; ++n)
cout << (int)msg[n]<<" ";
cout << "Type: "<< msg[12] <<endl;
cout<<endl;
// cout<<"SAR: sv = "<< (int)msg[2] <<" ";
// for(int n=4; n < 12; ++n)
// fmt::printf("%02x", (int)msg[n]);
// for(int n = 0; n < 15; ++n)
// fmt::printf("%x", (int)getbitu(msg.c_str(), 36 + 4*n, 4));
// cout << " Type: "<< (int) msg[12] <<"\n";
// cout<<"Parameter: (len = "<<msg.length()<<") ";
// for(unsigned int n = 13; n < msg.length(); ++n)
// fmt::printf("%02x ", (int)msg[n]);
// cout<<"\n";
}
if(ubxClass == 2 && ubxType == 19) { //UBX-RXM-SFRBX
cout<<"SFRBX GNSSID "<< (int)msg[0]<<", SV "<< (int)msg[1];
cout<<" words "<< (int)msg[4]<<", version "<< (int)msg[6];
cout<<endl;
if(msg[0] != 2)
// cout<<"SFRBX GNSSID "<< (int)msg[0]<<", SV "<< (int)msg[1];
// cout<<" words "<< (int)msg[4]<<", version "<< (int)msg[6];
// cout<<"\n";
if(msg[0] != 2) // version field
continue;
// 7 is reserved
// cout << ((msg[8]&128) ? "Even " : "Odd ");
// cout << ((msg[8]&64) ? "Alert " : "Nominal ");
unsigned int wtype = (int)(msg[11] & (~(64+128)));
unsigned int sv = (int)msg[1];
cout << "Word type "<< (int)(msg[11] & (~(64+128))) <<" SV " << (int)msg[1]<<endl;
for(unsigned int n = 8; n < msg.size() ; ++n) {
fmt::printf("%02x ", msg[n]);
}
cout<<"\n";
// cout << "Word type "<< (int)(msg[11] & (~(64+128))) <<" SV " << (int)msg[1]<<"\n";
// for(unsigned int n = 8; n < msg.size() ; ++n) {
// fmt::printf("%02x ", msg[n]);
// }
// cout<<"\n";
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]);
for(auto& c : payload)
fmt::printf("%02x ", c);
// for(auto& c : payload)
// fmt::printf("%02x ", c);
cout<<endl;
// cout<<"\n";
std::basic_string<uint8_t> inav;
unsigned int i,j;
@ -138,35 +342,42 @@ try
for (i=0,j=2; i< 2; i++, j+=8)
inav.append(1, (unsigned char)getbitu(payload.c_str()+16,j,8));
cout<<"inav for "<<wtype<<" for sv "<<sv<<": ";
for(auto& c : inav)
fmt::printf("%02x ", c);
// cout<<"inav for "<<wtype<<" for sv "<<sv<<": ";
// for(auto& c : inav)
// fmt::printf("%02x ", c);
cout<<endl;
if(wtype == 1 && tow) {
time_t t = 935280000 + wn * 7*86400 + tow;
csv2<<t<<" "<<sv<<" " << tow<<" "<<60*getbitu(inav.c_str(), 16, 14)<<"\n";
g_svstats[sv].addWord(inav);
if(wtype >=1 && wtype <= 4) { // ephemeris
uint16_t iod = getbitu(&inav[0], 6, 10);
if(wtype == 1 && tow) {
int t0e = 60*getbitu(&inav[0], 16, 14);
int age = (tow - t0e)/60;
wk.emitLine(sv, "Eph" +std::to_string(wtype)+", iod=" + to_string(iod)+", age="+to_string(age)+"m" );
}
else
wk.emitLine(sv, "Eph" +std::to_string(wtype)+", iod=" + to_string(iod));
}
if(wtype == 3 && tow) {
time_t t = 935280000 + wn * 7*86400 + tow;
csv<<t<<" "<<sv<<" " << getbitu(inav.c_str(), 6, 10)<<" " << getbitu(inav.c_str(), 120, 8) << endl;
else
wk.emitLine(sv, "Word "+std::to_string(wtype));
if(wtype == 5) {
wk.setStatus(sv, "Health: "+std::to_string(getbitu(&inav[0], 67, 2)));
tow = getbitu(&inav[0], 85, 20);
}
if(wtype==5) {
tow = getbitu(inav.c_str(), 85, 20);
wn = getbitu(inav.c_str(), 73, 12);
cout<<"gst wn " << wn << " tow "<<tow<<endl;
unsigned int e5bhs = getbitu(inav.c_str(), 67, 2);
unsigned int e1bhs = getbitu(inav.c_str(), 69, 2);
unsigned int e5bdvs = getbitu(inav.c_str(), 71, 1);
unsigned int e1bdvs = getbitu(inav.c_str(), 72, 1);
cout<<"health: sv "<< sv<<" " << e5bhs << " " << e1bhs <<" " << e5bdvs<<" " << e1bdvs <<endl;
}
// time_t t = 935280000 + wn * 7*86400 + tow;
/*
for(const auto& ent : g_svstats) {
// 12 iod t0e
fmt::printf("%2d\t", ent.first);
if(ent.second.completeIOD()) {
cout << ent.second.getIOD() << "\t" << ( ent.second.tow - ent.second.liveIOD().t0e ) << "\t" << (unsigned int)ent.second.liveIOD().sisa;
}
cout<<"\n";
}
cout<<"\n";
*/
}
}
}
}
catch(EofException& e)
{}