Cleanup ubloxd message parsing (#20664)
* use kaitai to generate parsers * add scons flag to generate parsers * add outer layer ephemeris parsing * create ephemeris packet at the right time * parse subframe 1 and 2 * add more fields * add generated files to release * fix signs * no cast * add unordered map include * add exception handling * small cleanup * parse iono data * cleanuppull/20680/head
parent
343fea2bf9
commit
eacacb8fba
18 changed files with 3376 additions and 519 deletions
@ -0,0 +1,16 @@ |
|||||||
|
#ifndef KAITAI_CUSTOM_DECODER_H |
||||||
|
#define KAITAI_CUSTOM_DECODER_H |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace kaitai { |
||||||
|
|
||||||
|
class custom_decoder { |
||||||
|
public: |
||||||
|
virtual ~custom_decoder() {}; |
||||||
|
virtual std::string decode(std::string src) = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,189 @@ |
|||||||
|
#ifndef KAITAI_EXCEPTIONS_H |
||||||
|
#define KAITAI_EXCEPTIONS_H |
||||||
|
|
||||||
|
#include <kaitai/kaitaistream.h> |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <stdexcept> |
||||||
|
|
||||||
|
// We need to use "noexcept" in virtual destructor of our exceptions
|
||||||
|
// subclasses. Different compilers have different ideas on how to
|
||||||
|
// achieve that: C++98 compilers prefer `throw()`, C++11 and later
|
||||||
|
// use `noexcept`. We define KS_NOEXCEPT macro for that.
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) |
||||||
|
#define KS_NOEXCEPT noexcept |
||||||
|
#else |
||||||
|
#define KS_NOEXCEPT throw() |
||||||
|
#endif |
||||||
|
|
||||||
|
namespace kaitai { |
||||||
|
|
||||||
|
/**
|
||||||
|
* Common ancestor for all error originating from Kaitai Struct usage. |
||||||
|
* Stores KSY source path, pointing to an element supposedly guilty of |
||||||
|
* an error. |
||||||
|
*/ |
||||||
|
class kstruct_error: public std::runtime_error { |
||||||
|
public: |
||||||
|
kstruct_error(const std::string what, const std::string src_path): |
||||||
|
std::runtime_error(src_path + ": " + what), |
||||||
|
m_src_path(src_path) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
virtual ~kstruct_error() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
const std::string m_src_path; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Error that occurs when default endianness should be decided with |
||||||
|
* a switch, but nothing matches (although using endianness expression |
||||||
|
* implies that there should be some positive result). |
||||||
|
*/ |
||||||
|
class undecided_endianness_error: public kstruct_error { |
||||||
|
public: |
||||||
|
undecided_endianness_error(const std::string src_path): |
||||||
|
kstruct_error("unable to decide on endianness for a type", src_path) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
virtual ~undecided_endianness_error() KS_NOEXCEPT {}; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Common ancestor for all validation failures. Stores pointer to |
||||||
|
* KaitaiStream IO object which was involved in an error. |
||||||
|
*/ |
||||||
|
class validation_failed_error: public kstruct_error { |
||||||
|
public: |
||||||
|
validation_failed_error(const std::string what, kstream* io, const std::string src_path): |
||||||
|
kstruct_error("at pos " + kstream::to_string(static_cast<int>(io->pos())) + ": validation failed: " + what, src_path), |
||||||
|
m_io(io) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
// "at pos #{io.pos}: validation failed: #{msg}"
|
||||||
|
|
||||||
|
virtual ~validation_failed_error() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
kstream* m_io; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals validation failure: we required "actual" value to be equal to |
||||||
|
* "expected", but it turned out that it's not. |
||||||
|
*/ |
||||||
|
template<typename T> |
||||||
|
class validation_not_equal_error: public validation_failed_error { |
||||||
|
public: |
||||||
|
validation_not_equal_error<T>(const T& expected, const T& actual, kstream* io, const std::string src_path): |
||||||
|
validation_failed_error("not equal", io, src_path), |
||||||
|
m_expected(expected), |
||||||
|
m_actual(actual) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
// "not equal, expected #{expected.inspect}, but got #{actual.inspect}"
|
||||||
|
|
||||||
|
virtual ~validation_not_equal_error<T>() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
const T& m_expected; |
||||||
|
const T& m_actual; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals validation failure: we required "actual" value to be greater |
||||||
|
* than or equal to "min", but it turned out that it's not. |
||||||
|
*/ |
||||||
|
template<typename T> |
||||||
|
class validation_less_than_error: public validation_failed_error { |
||||||
|
public: |
||||||
|
validation_less_than_error<T>(const T& min, const T& actual, kstream* io, const std::string src_path): |
||||||
|
validation_failed_error("not in range", io, src_path), |
||||||
|
m_min(min), |
||||||
|
m_actual(actual) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
// "not in range, min #{min.inspect}, but got #{actual.inspect}"
|
||||||
|
|
||||||
|
virtual ~validation_less_than_error<T>() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
const T& m_min; |
||||||
|
const T& m_actual; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals validation failure: we required "actual" value to be less |
||||||
|
* than or equal to "max", but it turned out that it's not. |
||||||
|
*/ |
||||||
|
template<typename T> |
||||||
|
class validation_greater_than_error: public validation_failed_error { |
||||||
|
public: |
||||||
|
validation_greater_than_error<T>(const T& max, const T& actual, kstream* io, const std::string src_path): |
||||||
|
validation_failed_error("not in range", io, src_path), |
||||||
|
m_max(max), |
||||||
|
m_actual(actual) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
// "not in range, max #{max.inspect}, but got #{actual.inspect}"
|
||||||
|
|
||||||
|
virtual ~validation_greater_than_error<T>() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
const T& m_max; |
||||||
|
const T& m_actual; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals validation failure: we required "actual" value to be from |
||||||
|
* the list, but it turned out that it's not. |
||||||
|
*/ |
||||||
|
template<typename T> |
||||||
|
class validation_not_any_of_error: public validation_failed_error { |
||||||
|
public: |
||||||
|
validation_not_any_of_error<T>(const T& actual, kstream* io, const std::string src_path): |
||||||
|
validation_failed_error("not any of the list", io, src_path), |
||||||
|
m_actual(actual) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
// "not any of the list, got #{actual.inspect}"
|
||||||
|
|
||||||
|
virtual ~validation_not_any_of_error<T>() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
const T& m_actual; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals validation failure: we required "actual" value to match |
||||||
|
* the expression, but it turned out that it doesn't. |
||||||
|
*/ |
||||||
|
template<typename T> |
||||||
|
class validation_expr_error: public validation_failed_error { |
||||||
|
public: |
||||||
|
validation_expr_error<T>(const T& actual, kstream* io, const std::string src_path): |
||||||
|
validation_failed_error("not matching the expression", io, src_path), |
||||||
|
m_actual(actual) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
// "not matching the expression, got #{actual.inspect}"
|
||||||
|
|
||||||
|
virtual ~validation_expr_error<T>() KS_NOEXCEPT {}; |
||||||
|
|
||||||
|
protected: |
||||||
|
const T& m_actual; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,689 @@ |
|||||||
|
#include <kaitai/kaitaistream.h> |
||||||
|
|
||||||
|
#if defined(__APPLE__) |
||||||
|
#include <machine/endian.h> |
||||||
|
#include <libkern/OSByteOrder.h> |
||||||
|
#define bswap_16(x) OSSwapInt16(x) |
||||||
|
#define bswap_32(x) OSSwapInt32(x) |
||||||
|
#define bswap_64(x) OSSwapInt64(x) |
||||||
|
#define __BYTE_ORDER BYTE_ORDER |
||||||
|
#define __BIG_ENDIAN BIG_ENDIAN |
||||||
|
#define __LITTLE_ENDIAN LITTLE_ENDIAN |
||||||
|
#elif defined(_MSC_VER) // !__APPLE__
|
||||||
|
#include <stdlib.h> |
||||||
|
#define __LITTLE_ENDIAN 1234 |
||||||
|
#define __BIG_ENDIAN 4321 |
||||||
|
#define __BYTE_ORDER __LITTLE_ENDIAN |
||||||
|
#define bswap_16(x) _byteswap_ushort(x) |
||||||
|
#define bswap_32(x) _byteswap_ulong(x) |
||||||
|
#define bswap_64(x) _byteswap_uint64(x) |
||||||
|
#else // !__APPLE__ or !_MSC_VER
|
||||||
|
#include <endian.h> |
||||||
|
#include <byteswap.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <iostream> |
||||||
|
#include <vector> |
||||||
|
#include <stdexcept> |
||||||
|
|
||||||
|
kaitai::kstream::kstream(std::istream* io) { |
||||||
|
m_io = io; |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
kaitai::kstream::kstream(std::string& data): m_io_str(data) { |
||||||
|
m_io = &m_io_str; |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
void kaitai::kstream::init() { |
||||||
|
exceptions_enable(); |
||||||
|
align_to_byte(); |
||||||
|
} |
||||||
|
|
||||||
|
void kaitai::kstream::close() { |
||||||
|
// m_io->close();
|
||||||
|
} |
||||||
|
|
||||||
|
void kaitai::kstream::exceptions_enable() const { |
||||||
|
m_io->exceptions( |
||||||
|
std::istream::eofbit | |
||||||
|
std::istream::failbit | |
||||||
|
std::istream::badbit |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Stream positioning
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
bool kaitai::kstream::is_eof() const { |
||||||
|
if (m_bits_left > 0) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
char t; |
||||||
|
m_io->exceptions( |
||||||
|
std::istream::badbit |
||||||
|
); |
||||||
|
m_io->get(t); |
||||||
|
if (m_io->eof()) { |
||||||
|
m_io->clear(); |
||||||
|
exceptions_enable(); |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
m_io->unget(); |
||||||
|
exceptions_enable(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void kaitai::kstream::seek(uint64_t pos) { |
||||||
|
m_io->seekg(pos); |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::pos() { |
||||||
|
return m_io->tellg(); |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::size() { |
||||||
|
std::iostream::pos_type cur_pos = m_io->tellg(); |
||||||
|
m_io->seekg(0, std::ios::end); |
||||||
|
std::iostream::pos_type len = m_io->tellg(); |
||||||
|
m_io->seekg(cur_pos); |
||||||
|
return len; |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Integer numbers
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Signed
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int8_t kaitai::kstream::read_s1() { |
||||||
|
char t; |
||||||
|
m_io->get(t); |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Big-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
int16_t kaitai::kstream::read_s2be() { |
||||||
|
int16_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 2); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_16(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
int32_t kaitai::kstream::read_s4be() { |
||||||
|
int32_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 4); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_32(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
int64_t kaitai::kstream::read_s8be() { |
||||||
|
int64_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 8); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_64(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Little-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
int16_t kaitai::kstream::read_s2le() { |
||||||
|
int16_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 2); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_16(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
int32_t kaitai::kstream::read_s4le() { |
||||||
|
int32_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 4); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_32(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
int64_t kaitai::kstream::read_s8le() { |
||||||
|
int64_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 8); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_64(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Unsigned
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
uint8_t kaitai::kstream::read_u1() { |
||||||
|
char t; |
||||||
|
m_io->get(t); |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Big-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
uint16_t kaitai::kstream::read_u2be() { |
||||||
|
uint16_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 2); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_16(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t kaitai::kstream::read_u4be() { |
||||||
|
uint32_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 4); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_32(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::read_u8be() { |
||||||
|
uint64_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 8); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_64(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Little-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
uint16_t kaitai::kstream::read_u2le() { |
||||||
|
uint16_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 2); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_16(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t kaitai::kstream::read_u4le() { |
||||||
|
uint32_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 4); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_32(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::read_u8le() { |
||||||
|
uint64_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 8); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_64(t); |
||||||
|
#endif |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Floating point numbers
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Big-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
float kaitai::kstream::read_f4be() { |
||||||
|
uint32_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 4); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_32(t); |
||||||
|
#endif |
||||||
|
return reinterpret_cast<float&>(t); |
||||||
|
} |
||||||
|
|
||||||
|
double kaitai::kstream::read_f8be() { |
||||||
|
uint64_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 8); |
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN |
||||||
|
t = bswap_64(t); |
||||||
|
#endif |
||||||
|
return reinterpret_cast<double&>(t); |
||||||
|
} |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Little-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
float kaitai::kstream::read_f4le() { |
||||||
|
uint32_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 4); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_32(t); |
||||||
|
#endif |
||||||
|
return reinterpret_cast<float&>(t); |
||||||
|
} |
||||||
|
|
||||||
|
double kaitai::kstream::read_f8le() { |
||||||
|
uint64_t t; |
||||||
|
m_io->read(reinterpret_cast<char *>(&t), 8); |
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN |
||||||
|
t = bswap_64(t); |
||||||
|
#endif |
||||||
|
return reinterpret_cast<double&>(t); |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Unaligned bit values
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
void kaitai::kstream::align_to_byte() { |
||||||
|
m_bits_left = 0; |
||||||
|
m_bits = 0; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::read_bits_int_be(int n) { |
||||||
|
int bits_needed = n - m_bits_left; |
||||||
|
if (bits_needed > 0) { |
||||||
|
// 1 bit => 1 byte
|
||||||
|
// 8 bits => 1 byte
|
||||||
|
// 9 bits => 2 bytes
|
||||||
|
int bytes_needed = ((bits_needed - 1) / 8) + 1; |
||||||
|
if (bytes_needed > 8) |
||||||
|
throw std::runtime_error("read_bits_int: more than 8 bytes requested"); |
||||||
|
char buf[8]; |
||||||
|
m_io->read(buf, bytes_needed); |
||||||
|
for (int i = 0; i < bytes_needed; i++) { |
||||||
|
uint8_t b = buf[i]; |
||||||
|
m_bits <<= 8; |
||||||
|
m_bits |= b; |
||||||
|
m_bits_left += 8; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// raw mask with required number of 1s, starting from lowest bit
|
||||||
|
uint64_t mask = get_mask_ones(n); |
||||||
|
// shift mask to align with highest bits available in @bits
|
||||||
|
int shift_bits = m_bits_left - n; |
||||||
|
mask <<= shift_bits; |
||||||
|
// derive reading result
|
||||||
|
uint64_t res = (m_bits & mask) >> shift_bits; |
||||||
|
// clear top bits that we've just read => AND with 1s
|
||||||
|
m_bits_left -= n; |
||||||
|
mask = get_mask_ones(m_bits_left); |
||||||
|
m_bits &= mask; |
||||||
|
|
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
// Deprecated, use read_bits_int_be() instead.
|
||||||
|
uint64_t kaitai::kstream::read_bits_int(int n) { |
||||||
|
return read_bits_int_be(n); |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::read_bits_int_le(int n) { |
||||||
|
int bits_needed = n - m_bits_left; |
||||||
|
if (bits_needed > 0) { |
||||||
|
// 1 bit => 1 byte
|
||||||
|
// 8 bits => 1 byte
|
||||||
|
// 9 bits => 2 bytes
|
||||||
|
int bytes_needed = ((bits_needed - 1) / 8) + 1; |
||||||
|
if (bytes_needed > 8) |
||||||
|
throw std::runtime_error("read_bits_int_le: more than 8 bytes requested"); |
||||||
|
char buf[8]; |
||||||
|
m_io->read(buf, bytes_needed); |
||||||
|
for (int i = 0; i < bytes_needed; i++) { |
||||||
|
uint8_t b = buf[i]; |
||||||
|
m_bits |= (static_cast<uint64_t>(b) << m_bits_left); |
||||||
|
m_bits_left += 8; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// raw mask with required number of 1s, starting from lowest bit
|
||||||
|
uint64_t mask = get_mask_ones(n); |
||||||
|
// derive reading result
|
||||||
|
uint64_t res = m_bits & mask; |
||||||
|
// remove bottom bits that we've just read by shifting
|
||||||
|
m_bits >>= n; |
||||||
|
m_bits_left -= n; |
||||||
|
|
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t kaitai::kstream::get_mask_ones(int n) { |
||||||
|
if (n == 64) { |
||||||
|
return 0xFFFFFFFFFFFFFFFF; |
||||||
|
} else { |
||||||
|
return ((uint64_t) 1 << n) - 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Byte arrays
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
std::string kaitai::kstream::read_bytes(std::streamsize len) { |
||||||
|
std::vector<char> result(len); |
||||||
|
|
||||||
|
// NOTE: streamsize type is signed, negative values are only *supposed* to not be used.
|
||||||
|
// http://en.cppreference.com/w/cpp/io/streamsize
|
||||||
|
if (len < 0) { |
||||||
|
throw std::runtime_error("read_bytes: requested a negative amount"); |
||||||
|
} |
||||||
|
|
||||||
|
if (len > 0) { |
||||||
|
m_io->read(&result[0], len); |
||||||
|
} |
||||||
|
|
||||||
|
return std::string(result.begin(), result.end()); |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::read_bytes_full() { |
||||||
|
std::iostream::pos_type p1 = m_io->tellg(); |
||||||
|
m_io->seekg(0, std::ios::end); |
||||||
|
std::iostream::pos_type p2 = m_io->tellg(); |
||||||
|
size_t len = p2 - p1; |
||||||
|
|
||||||
|
// Note: this requires a std::string to be backed with a
|
||||||
|
// contiguous buffer. Officially, it's a only requirement since
|
||||||
|
// C++11 (C++98 and C++03 didn't have this requirement), but all
|
||||||
|
// major implementations had contiguous buffers anyway.
|
||||||
|
std::string result(len, ' '); |
||||||
|
m_io->seekg(p1); |
||||||
|
m_io->read(&result[0], len); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::read_bytes_term(char term, bool include, bool consume, bool eos_error) { |
||||||
|
std::string result; |
||||||
|
std::getline(*m_io, result, term); |
||||||
|
if (m_io->eof()) { |
||||||
|
// encountered EOF
|
||||||
|
if (eos_error) { |
||||||
|
throw std::runtime_error("read_bytes_term: encountered EOF"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
// encountered terminator
|
||||||
|
if (include) |
||||||
|
result.push_back(term); |
||||||
|
if (!consume) |
||||||
|
m_io->unget(); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::ensure_fixed_contents(std::string expected) { |
||||||
|
std::string actual = read_bytes(expected.length()); |
||||||
|
|
||||||
|
if (actual != expected) { |
||||||
|
// NOTE: I think printing it outright is not best idea, it could contain non-ascii charactes like backspace and beeps and whatnot. It would be better to print hexlified version, and also to redirect it to stderr.
|
||||||
|
throw std::runtime_error("ensure_fixed_contents: actual data does not match expected data"); |
||||||
|
} |
||||||
|
|
||||||
|
return actual; |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::bytes_strip_right(std::string src, char pad_byte) { |
||||||
|
std::size_t new_len = src.length(); |
||||||
|
|
||||||
|
while (new_len > 0 && src[new_len - 1] == pad_byte) |
||||||
|
new_len--; |
||||||
|
|
||||||
|
return src.substr(0, new_len); |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool include) { |
||||||
|
std::size_t new_len = 0; |
||||||
|
std::size_t max_len = src.length(); |
||||||
|
|
||||||
|
while (new_len < max_len && src[new_len] != term) |
||||||
|
new_len++; |
||||||
|
|
||||||
|
if (include && new_len < max_len) |
||||||
|
new_len++; |
||||||
|
|
||||||
|
return src.substr(0, new_len); |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Byte array processing
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
std::string kaitai::kstream::process_xor_one(std::string data, uint8_t key) { |
||||||
|
size_t len = data.length(); |
||||||
|
std::string result(len, ' '); |
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) |
||||||
|
result[i] = data[i] ^ key; |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::process_xor_many(std::string data, std::string key) { |
||||||
|
size_t len = data.length(); |
||||||
|
size_t kl = key.length(); |
||||||
|
std::string result(len, ' '); |
||||||
|
|
||||||
|
size_t ki = 0; |
||||||
|
for (size_t i = 0; i < len; i++) { |
||||||
|
result[i] = data[i] ^ key[ki]; |
||||||
|
ki++; |
||||||
|
if (ki >= kl) |
||||||
|
ki = 0; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
std::string kaitai::kstream::process_rotate_left(std::string data, int amount) { |
||||||
|
size_t len = data.length(); |
||||||
|
std::string result(len, ' '); |
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) { |
||||||
|
uint8_t bits = data[i]; |
||||||
|
result[i] = (bits << amount) | (bits >> (8 - amount)); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef KS_ZLIB |
||||||
|
#include <zlib.h> |
||||||
|
|
||||||
|
std::string kaitai::kstream::process_zlib(std::string data) { |
||||||
|
int ret; |
||||||
|
|
||||||
|
unsigned char *src_ptr = reinterpret_cast<unsigned char*>(&data[0]); |
||||||
|
std::stringstream dst_strm; |
||||||
|
|
||||||
|
z_stream strm; |
||||||
|
strm.zalloc = Z_NULL; |
||||||
|
strm.zfree = Z_NULL; |
||||||
|
strm.opaque = Z_NULL; |
||||||
|
|
||||||
|
ret = inflateInit(&strm); |
||||||
|
if (ret != Z_OK) |
||||||
|
throw std::runtime_error("process_zlib: inflateInit error"); |
||||||
|
|
||||||
|
strm.next_in = src_ptr; |
||||||
|
strm.avail_in = data.length(); |
||||||
|
|
||||||
|
unsigned char outbuffer[ZLIB_BUF_SIZE]; |
||||||
|
std::string outstring; |
||||||
|
|
||||||
|
// get the decompressed bytes blockwise using repeated calls to inflate
|
||||||
|
do { |
||||||
|
strm.next_out = reinterpret_cast<Bytef*>(outbuffer); |
||||||
|
strm.avail_out = sizeof(outbuffer); |
||||||
|
|
||||||
|
ret = inflate(&strm, 0); |
||||||
|
|
||||||
|
if (outstring.size() < strm.total_out) |
||||||
|
outstring.append(reinterpret_cast<char*>(outbuffer), strm.total_out - outstring.size()); |
||||||
|
} while (ret == Z_OK); |
||||||
|
|
||||||
|
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
|
||||||
|
std::ostringstream exc_msg; |
||||||
|
exc_msg << "process_zlib: error #" << ret << "): " << strm.msg; |
||||||
|
throw std::runtime_error(exc_msg.str()); |
||||||
|
} |
||||||
|
|
||||||
|
if (inflateEnd(&strm) != Z_OK) |
||||||
|
throw std::runtime_error("process_zlib: inflateEnd error"); |
||||||
|
|
||||||
|
return outstring; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Misc utility methods
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
int kaitai::kstream::mod(int a, int b) { |
||||||
|
if (b <= 0) |
||||||
|
throw std::invalid_argument("mod: divisor b <= 0"); |
||||||
|
int r = a % b; |
||||||
|
if (r < 0) |
||||||
|
r += b; |
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
std::string kaitai::kstream::to_string(int val) { |
||||||
|
// if int is 32 bits, "-2147483648" is the longest string representation
|
||||||
|
// => 11 chars + zero => 12 chars
|
||||||
|
// if int is 64 bits, "-9223372036854775808" is the longest
|
||||||
|
// => 20 chars + zero => 21 chars
|
||||||
|
char buf[25]; |
||||||
|
int got_len = snprintf(buf, sizeof(buf), "%d", val); |
||||||
|
|
||||||
|
// should never happen, but check nonetheless
|
||||||
|
if (got_len > sizeof(buf)) |
||||||
|
throw std::invalid_argument("to_string: integer is longer than string buffer"); |
||||||
|
|
||||||
|
return std::string(buf); |
||||||
|
} |
||||||
|
|
||||||
|
#include <algorithm> |
||||||
|
std::string kaitai::kstream::reverse(std::string val) { |
||||||
|
std::reverse(val.begin(), val.end()); |
||||||
|
|
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t kaitai::kstream::byte_array_min(const std::string val) { |
||||||
|
uint8_t min = 0xff; // UINT8_MAX
|
||||||
|
std::string::const_iterator end = val.end(); |
||||||
|
for (std::string::const_iterator it = val.begin(); it != end; ++it) { |
||||||
|
uint8_t cur = static_cast<uint8_t>(*it); |
||||||
|
if (cur < min) { |
||||||
|
min = cur; |
||||||
|
} |
||||||
|
} |
||||||
|
return min; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t kaitai::kstream::byte_array_max(const std::string val) { |
||||||
|
uint8_t max = 0; // UINT8_MIN
|
||||||
|
std::string::const_iterator end = val.end(); |
||||||
|
for (std::string::const_iterator it = val.begin(); it != end; ++it) { |
||||||
|
uint8_t cur = static_cast<uint8_t>(*it); |
||||||
|
if (cur > max) { |
||||||
|
max = cur; |
||||||
|
} |
||||||
|
} |
||||||
|
return max; |
||||||
|
} |
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Other internal methods
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
#ifndef KS_STR_DEFAULT_ENCODING |
||||||
|
#define KS_STR_DEFAULT_ENCODING "UTF-8" |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef KS_STR_ENCODING_ICONV |
||||||
|
|
||||||
|
#include <iconv.h> |
||||||
|
#include <cerrno> |
||||||
|
#include <stdexcept> |
||||||
|
|
||||||
|
std::string kaitai::kstream::bytes_to_str(std::string src, std::string src_enc) { |
||||||
|
iconv_t cd = iconv_open(KS_STR_DEFAULT_ENCODING, src_enc.c_str()); |
||||||
|
|
||||||
|
if (cd == (iconv_t) -1) { |
||||||
|
if (errno == EINVAL) { |
||||||
|
throw std::runtime_error("bytes_to_str: invalid encoding pair conversion requested"); |
||||||
|
} else { |
||||||
|
throw std::runtime_error("bytes_to_str: error opening iconv"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
size_t src_len = src.length(); |
||||||
|
size_t src_left = src_len; |
||||||
|
|
||||||
|
// Start with a buffer length of double the source length.
|
||||||
|
size_t dst_len = src_len * 2; |
||||||
|
std::string dst(dst_len, ' '); |
||||||
|
size_t dst_left = dst_len; |
||||||
|
|
||||||
|
char *src_ptr = &src[0]; |
||||||
|
char *dst_ptr = &dst[0]; |
||||||
|
|
||||||
|
while (true) { |
||||||
|
size_t res = iconv(cd, &src_ptr, &src_left, &dst_ptr, &dst_left); |
||||||
|
|
||||||
|
if (res == (size_t) -1) { |
||||||
|
if (errno == E2BIG) { |
||||||
|
// dst buffer is not enough to accomodate whole string
|
||||||
|
// enlarge the buffer and try again
|
||||||
|
size_t dst_used = dst_len - dst_left; |
||||||
|
dst_left += dst_len; |
||||||
|
dst_len += dst_len; |
||||||
|
dst.resize(dst_len); |
||||||
|
|
||||||
|
// dst.resize might have allocated destination buffer in another area
|
||||||
|
// of memory, thus our previous pointer "dst" will be invalid; re-point
|
||||||
|
// it using "dst_used".
|
||||||
|
dst_ptr = &dst[dst_used]; |
||||||
|
} else { |
||||||
|
throw std::runtime_error("bytes_to_str: iconv error"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
// conversion successful
|
||||||
|
dst.resize(dst_len - dst_left); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (iconv_close(cd) != 0) { |
||||||
|
throw std::runtime_error("bytes_to_str: iconv close error"); |
||||||
|
} |
||||||
|
|
||||||
|
return dst; |
||||||
|
} |
||||||
|
#elif defined(KS_STR_ENCODING_NONE) |
||||||
|
std::string kaitai::kstream::bytes_to_str(std::string src, std::string src_enc) { |
||||||
|
return src; |
||||||
|
} |
||||||
|
#else |
||||||
|
#error Need to decide how to handle strings: please define one of: KS_STR_ENCODING_ICONV, KS_STR_ENCODING_NONE |
||||||
|
#endif |
@ -0,0 +1,268 @@ |
|||||||
|
#ifndef KAITAI_STREAM_H |
||||||
|
#define KAITAI_STREAM_H |
||||||
|
|
||||||
|
// Kaitai Struct runtime API version: x.y.z = 'xxxyyyzzz' decimal
|
||||||
|
#define KAITAI_STRUCT_VERSION 9000L |
||||||
|
|
||||||
|
#include <istream> |
||||||
|
#include <sstream> |
||||||
|
#include <stdint.h> |
||||||
|
#include <sys/types.h> |
||||||
|
|
||||||
|
namespace kaitai { |
||||||
|
|
||||||
|
/**
|
||||||
|
* Kaitai Stream class (kaitai::kstream) is an implementation of |
||||||
|
* <a href="https://doc.kaitai.io/stream_api.html">Kaitai Struct stream API</a> |
||||||
|
* for C++/STL. It's implemented as a wrapper over generic STL std::istream. |
||||||
|
* |
||||||
|
* It provides a wide variety of simple methods to read (parse) binary |
||||||
|
* representations of primitive types, such as integer and floating |
||||||
|
* point numbers, byte arrays and strings, and also provides stream |
||||||
|
* positioning / navigation methods with unified cross-language and |
||||||
|
* cross-toolkit semantics. |
||||||
|
* |
||||||
|
* Typically, end users won't access Kaitai Stream class manually, but would |
||||||
|
* describe a binary structure format using .ksy language and then would use |
||||||
|
* Kaitai Struct compiler to generate source code in desired target language. |
||||||
|
* That code, in turn, would use this class and API to do the actual parsing |
||||||
|
* job. |
||||||
|
*/ |
||||||
|
class kstream { |
||||||
|
public: |
||||||
|
/**
|
||||||
|
* Constructs new Kaitai Stream object, wrapping a given std::istream. |
||||||
|
* \param io istream object to use for this Kaitai Stream |
||||||
|
*/ |
||||||
|
kstream(std::istream* io); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs new Kaitai Stream object, wrapping a given in-memory data |
||||||
|
* buffer. |
||||||
|
* \param data data buffer to use for this Kaitai Stream |
||||||
|
*/ |
||||||
|
kstream(std::string& data); |
||||||
|
|
||||||
|
void close(); |
||||||
|
|
||||||
|
/** @name Stream positioning */ |
||||||
|
//@{
|
||||||
|
/**
|
||||||
|
* Check if stream pointer is at the end of stream. Note that the semantics |
||||||
|
* are different from traditional STL semantics: one does *not* need to do a |
||||||
|
* read (which will fail) after the actual end of the stream to trigger EOF |
||||||
|
* flag, which can be accessed after that read. It is sufficient to just be |
||||||
|
* at the end of the stream for this method to return true. |
||||||
|
* \return "true" if we are located at the end of the stream. |
||||||
|
*/ |
||||||
|
bool is_eof() const; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Set stream pointer to designated position. |
||||||
|
* \param pos new position (offset in bytes from the beginning of the stream) |
||||||
|
*/ |
||||||
|
void seek(uint64_t pos); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current position of a stream pointer. |
||||||
|
* \return pointer position, number of bytes from the beginning of the stream |
||||||
|
*/ |
||||||
|
uint64_t pos(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get total size of the stream in bytes. |
||||||
|
* \return size of the stream in bytes |
||||||
|
*/ |
||||||
|
uint64_t size(); |
||||||
|
//@}
|
||||||
|
|
||||||
|
/** @name Integer numbers */ |
||||||
|
//@{
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Signed
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int8_t read_s1(); |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Big-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
int16_t read_s2be(); |
||||||
|
int32_t read_s4be(); |
||||||
|
int64_t read_s8be(); |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Little-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
int16_t read_s2le(); |
||||||
|
int32_t read_s4le(); |
||||||
|
int64_t read_s8le(); |
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Unsigned
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
uint8_t read_u1(); |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Big-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
uint16_t read_u2be(); |
||||||
|
uint32_t read_u4be(); |
||||||
|
uint64_t read_u8be(); |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Little-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
uint16_t read_u2le(); |
||||||
|
uint32_t read_u4le(); |
||||||
|
uint64_t read_u8le(); |
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/** @name Floating point numbers */ |
||||||
|
//@{
|
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Big-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
float read_f4be(); |
||||||
|
double read_f8be(); |
||||||
|
|
||||||
|
// ........................................................................
|
||||||
|
// Little-endian
|
||||||
|
// ........................................................................
|
||||||
|
|
||||||
|
float read_f4le(); |
||||||
|
double read_f8le(); |
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/** @name Unaligned bit values */ |
||||||
|
//@{
|
||||||
|
|
||||||
|
void align_to_byte(); |
||||||
|
uint64_t read_bits_int_be(int n); |
||||||
|
uint64_t read_bits_int(int n); |
||||||
|
uint64_t read_bits_int_le(int n); |
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/** @name Byte arrays */ |
||||||
|
//@{
|
||||||
|
|
||||||
|
std::string read_bytes(std::streamsize len); |
||||||
|
std::string read_bytes_full(); |
||||||
|
std::string read_bytes_term(char term, bool include, bool consume, bool eos_error); |
||||||
|
std::string ensure_fixed_contents(std::string expected); |
||||||
|
|
||||||
|
static std::string bytes_strip_right(std::string src, char pad_byte); |
||||||
|
static std::string bytes_terminate(std::string src, char term, bool include); |
||||||
|
static std::string bytes_to_str(std::string src, std::string src_enc); |
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/** @name Byte array processing */ |
||||||
|
//@{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a XOR processing with given data, XORing every byte of input with a single |
||||||
|
* given value. |
||||||
|
* @param data data to process |
||||||
|
* @param key value to XOR with |
||||||
|
* @return processed data |
||||||
|
*/ |
||||||
|
static std::string process_xor_one(std::string data, uint8_t key); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a XOR processing with given data, XORing every byte of input with a key |
||||||
|
* array, repeating key array many times, if necessary (i.e. if data array is longer |
||||||
|
* than key array). |
||||||
|
* @param data data to process |
||||||
|
* @param key array of bytes to XOR with |
||||||
|
* @return processed data |
||||||
|
*/ |
||||||
|
static std::string process_xor_many(std::string data, std::string key); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a circular left rotation shift for a given buffer by a given amount of bits, |
||||||
|
* using groups of 1 bytes each time. Right circular rotation should be performed |
||||||
|
* using this procedure with corrected amount. |
||||||
|
* @param data source data to process |
||||||
|
* @param amount number of bits to shift by |
||||||
|
* @return copy of source array with requested shift applied |
||||||
|
*/ |
||||||
|
static std::string process_rotate_left(std::string data, int amount); |
||||||
|
|
||||||
|
#ifdef KS_ZLIB |
||||||
|
/**
|
||||||
|
* Performs an unpacking ("inflation") of zlib-compressed data with usual zlib headers. |
||||||
|
* @param data data to unpack |
||||||
|
* @return unpacked data |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
static std::string process_zlib(std::string data); |
||||||
|
#endif |
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs modulo operation between two integers: dividend `a` |
||||||
|
* and divisor `b`. Divisor `b` is expected to be positive. The |
||||||
|
* result is always 0 <= x <= b - 1. |
||||||
|
*/ |
||||||
|
static int mod(int a, int b); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts given integer `val` to a decimal string representation. |
||||||
|
* Should be used in place of std::to_string() (which is available only |
||||||
|
* since C++11) in older C++ implementations. |
||||||
|
*/ |
||||||
|
static std::string to_string(int val); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverses given string `val`, so that the first character becomes the |
||||||
|
* last and the last one becomes the first. This should be used to avoid |
||||||
|
* the need of local variables at the caller. |
||||||
|
*/ |
||||||
|
static std::string reverse(std::string val); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the minimal byte in a byte array, treating bytes as |
||||||
|
* unsigned values. |
||||||
|
* @param val byte array to scan |
||||||
|
* @return minimal byte in byte array as integer |
||||||
|
*/ |
||||||
|
static uint8_t byte_array_min(const std::string val); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the maximal byte in a byte array, treating bytes as |
||||||
|
* unsigned values. |
||||||
|
* @param val byte array to scan |
||||||
|
* @return maximal byte in byte array as integer |
||||||
|
*/ |
||||||
|
static uint8_t byte_array_max(const std::string val); |
||||||
|
|
||||||
|
private: |
||||||
|
std::istream* m_io; |
||||||
|
std::istringstream m_io_str; |
||||||
|
int m_bits_left; |
||||||
|
uint64_t m_bits; |
||||||
|
|
||||||
|
void init(); |
||||||
|
void exceptions_enable() const; |
||||||
|
|
||||||
|
static uint64_t get_mask_ones(int n); |
||||||
|
|
||||||
|
static const int ZLIB_BUF_SIZE = 128 * 1024; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,20 @@ |
|||||||
|
#ifndef KAITAI_STRUCT_H |
||||||
|
#define KAITAI_STRUCT_H |
||||||
|
|
||||||
|
#include <kaitai/kaitaistream.h> |
||||||
|
|
||||||
|
namespace kaitai { |
||||||
|
|
||||||
|
class kstruct { |
||||||
|
public: |
||||||
|
kstruct(kstream *_io) { m__io = _io; } |
||||||
|
virtual ~kstruct() {} |
||||||
|
protected: |
||||||
|
kstream *m__io; |
||||||
|
public: |
||||||
|
kstream *_io() { return m__io; } |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -1,5 +1,12 @@ |
|||||||
Import('env', 'common', 'cereal', 'messaging') |
Import('env', 'common', 'cereal', 'messaging') |
||||||
|
|
||||||
loc_libs = [cereal, messaging, 'zmq', common, 'capnp', 'kj', 'pthread'] |
loc_libs = [cereal, messaging, 'zmq', common, 'capnp', 'kj', 'kaitai', 'pthread'] |
||||||
|
|
||||||
env.Program("ubloxd", ["ubloxd.cc", "ublox_msg.cc"], LIBS=loc_libs) |
|
||||||
|
if GetOption('kaitai'): |
||||||
|
generated = Dir('generated').srcnode().abspath |
||||||
|
cmd = f"kaitai-struct-compiler --target cpp_stl --outdir {generated} $SOURCES" |
||||||
|
env.Command(['generated/ubx.cpp', 'generated/ubx.h'], 'ubx.ksy', cmd) |
||||||
|
env.Command(['generated/gps.cpp', 'generated/gps.h'], 'gps.ksy', cmd) |
||||||
|
|
||||||
|
env.Program("ubloxd", ["ubloxd.cc", "ublox_msg.cc", "generated/ubx.cpp", "generated/gps.cpp"], LIBS=loc_libs) |
||||||
|
@ -0,0 +1,325 @@ |
|||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "gps.h" |
||||||
|
#include "kaitai/exceptions.h" |
||||||
|
|
||||||
|
gps_t::gps_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = this; |
||||||
|
m_tlm = 0; |
||||||
|
m_how = 0; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::_read() { |
||||||
|
m_tlm = new tlm_t(m__io, this, m__root); |
||||||
|
m_how = new how_t(m__io, this, m__root); |
||||||
|
n_body = true; |
||||||
|
switch (how()->subframe_id()) { |
||||||
|
case 1: { |
||||||
|
n_body = false; |
||||||
|
m_body = new subframe_1_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 2: { |
||||||
|
n_body = false; |
||||||
|
m_body = new subframe_2_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 3: { |
||||||
|
n_body = false; |
||||||
|
m_body = new subframe_3_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 4: { |
||||||
|
n_body = false; |
||||||
|
m_body = new subframe_4_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::~gps_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::_clean_up() { |
||||||
|
if (m_tlm) { |
||||||
|
delete m_tlm; m_tlm = 0; |
||||||
|
} |
||||||
|
if (m_how) { |
||||||
|
delete m_how; m_how = 0; |
||||||
|
} |
||||||
|
if (!n_body) { |
||||||
|
if (m_body) { |
||||||
|
delete m_body; m_body = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_1_t::subframe_1_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
f_af_0 = false; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_1_t::_read() { |
||||||
|
m_week_no = m__io->read_bits_int_be(10); |
||||||
|
m_code = m__io->read_bits_int_be(2); |
||||||
|
m_sv_accuracy = m__io->read_bits_int_be(4); |
||||||
|
m_sv_health = m__io->read_bits_int_be(6); |
||||||
|
m_iodc_msb = m__io->read_bits_int_be(2); |
||||||
|
m_l2_p_data_flag = m__io->read_bits_int_be(1); |
||||||
|
m_reserved1 = m__io->read_bits_int_be(23); |
||||||
|
m_reserved2 = m__io->read_bits_int_be(24); |
||||||
|
m_reserved3 = m__io->read_bits_int_be(24); |
||||||
|
m_reserved4 = m__io->read_bits_int_be(16); |
||||||
|
m__io->align_to_byte(); |
||||||
|
m_t_gd = m__io->read_s1(); |
||||||
|
m_iodc_lsb = m__io->read_u1(); |
||||||
|
m_t_oc = m__io->read_u2be(); |
||||||
|
m_af_2 = m__io->read_s1(); |
||||||
|
m_af_1 = m__io->read_s2be(); |
||||||
|
m_af_0_sign = m__io->read_bits_int_be(1); |
||||||
|
m_af_0_value = m__io->read_bits_int_be(21); |
||||||
|
m_reserved5 = m__io->read_bits_int_be(2); |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_1_t::~subframe_1_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_1_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
int32_t gps_t::subframe_1_t::af_0() { |
||||||
|
if (f_af_0) |
||||||
|
return m_af_0; |
||||||
|
m_af_0 = ((af_0_sign()) ? ((af_0_value() - (1 << 21))) : (af_0_value())); |
||||||
|
f_af_0 = true; |
||||||
|
return m_af_0; |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_3_t::subframe_3_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
f_omega_dot = false; |
||||||
|
f_idot = false; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_3_t::_read() { |
||||||
|
m_c_ic = m__io->read_s2be(); |
||||||
|
m_omega_0 = m__io->read_s4be(); |
||||||
|
m_c_is = m__io->read_s2be(); |
||||||
|
m_i_0 = m__io->read_s4be(); |
||||||
|
m_c_rc = m__io->read_s2be(); |
||||||
|
m_omega = m__io->read_s4be(); |
||||||
|
m_omega_dot_sign = m__io->read_bits_int_be(1); |
||||||
|
m_omega_dot_value = m__io->read_bits_int_be(23); |
||||||
|
m__io->align_to_byte(); |
||||||
|
m_iode = m__io->read_u1(); |
||||||
|
m_idot_sign = m__io->read_bits_int_be(1); |
||||||
|
m_idot_value = m__io->read_bits_int_be(13); |
||||||
|
m_reserved = m__io->read_bits_int_be(2); |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_3_t::~subframe_3_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_3_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
int32_t gps_t::subframe_3_t::omega_dot() { |
||||||
|
if (f_omega_dot) |
||||||
|
return m_omega_dot; |
||||||
|
m_omega_dot = ((omega_dot_sign()) ? ((omega_dot_value() - (1 << 23))) : (omega_dot_value())); |
||||||
|
f_omega_dot = true; |
||||||
|
return m_omega_dot; |
||||||
|
} |
||||||
|
|
||||||
|
int32_t gps_t::subframe_3_t::idot() { |
||||||
|
if (f_idot) |
||||||
|
return m_idot; |
||||||
|
m_idot = ((idot_sign()) ? ((idot_value() - (1 << 13))) : (idot_value())); |
||||||
|
f_idot = true; |
||||||
|
return m_idot; |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_4_t::subframe_4_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_4_t::_read() { |
||||||
|
m_data_id = m__io->read_bits_int_be(2); |
||||||
|
m_page_id = m__io->read_bits_int_be(6); |
||||||
|
m__io->align_to_byte(); |
||||||
|
n_body = true; |
||||||
|
switch (page_id()) { |
||||||
|
case 56: { |
||||||
|
n_body = false; |
||||||
|
m_body = new ionosphere_data_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_4_t::~subframe_4_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_4_t::_clean_up() { |
||||||
|
if (!n_body) { |
||||||
|
if (m_body) { |
||||||
|
delete m_body; m_body = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_4_t::ionosphere_data_t::ionosphere_data_t(kaitai::kstream* p__io, gps_t::subframe_4_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_4_t::ionosphere_data_t::_read() { |
||||||
|
m_a0 = m__io->read_s1(); |
||||||
|
m_a1 = m__io->read_s1(); |
||||||
|
m_a2 = m__io->read_s1(); |
||||||
|
m_a3 = m__io->read_s1(); |
||||||
|
m_b0 = m__io->read_s1(); |
||||||
|
m_b1 = m__io->read_s1(); |
||||||
|
m_b2 = m__io->read_s1(); |
||||||
|
m_b3 = m__io->read_s1(); |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_4_t::ionosphere_data_t::~ionosphere_data_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_4_t::ionosphere_data_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::how_t::how_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::how_t::_read() { |
||||||
|
m_tow_count = m__io->read_bits_int_be(17); |
||||||
|
m_alert = m__io->read_bits_int_be(1); |
||||||
|
m_anti_spoof = m__io->read_bits_int_be(1); |
||||||
|
m_subframe_id = m__io->read_bits_int_be(3); |
||||||
|
m_reserved = m__io->read_bits_int_be(2); |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::how_t::~how_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::how_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::tlm_t::tlm_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::tlm_t::_read() { |
||||||
|
m_magic = m__io->read_bytes(1); |
||||||
|
if (!(magic() == std::string("\x8B", 1))) { |
||||||
|
throw kaitai::validation_not_equal_error<std::string>(std::string("\x8B", 1), magic(), _io(), std::string("/types/tlm/seq/0")); |
||||||
|
} |
||||||
|
m_tlm = m__io->read_bits_int_be(14); |
||||||
|
m_integrity_status = m__io->read_bits_int_be(1); |
||||||
|
m_reserved = m__io->read_bits_int_be(1); |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::tlm_t::~tlm_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::tlm_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_2_t::subframe_2_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_2_t::_read() { |
||||||
|
m_iode = m__io->read_u1(); |
||||||
|
m_c_rs = m__io->read_s2be(); |
||||||
|
m_delta_n = m__io->read_s2be(); |
||||||
|
m_m_0 = m__io->read_s4be(); |
||||||
|
m_c_uc = m__io->read_s2be(); |
||||||
|
m_e = m__io->read_s4be(); |
||||||
|
m_c_us = m__io->read_s2be(); |
||||||
|
m_sqrt_a = m__io->read_u4be(); |
||||||
|
m_t_oe = m__io->read_u2be(); |
||||||
|
m_fit_interval_flag = m__io->read_bits_int_be(1); |
||||||
|
m_aoda = m__io->read_bits_int_be(5); |
||||||
|
m_reserved = m__io->read_bits_int_be(2); |
||||||
|
} |
||||||
|
|
||||||
|
gps_t::subframe_2_t::~subframe_2_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void gps_t::subframe_2_t::_clean_up() { |
||||||
|
} |
@ -0,0 +1,359 @@ |
|||||||
|
#ifndef GPS_H_ |
||||||
|
#define GPS_H_ |
||||||
|
|
||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "kaitai/kaitaistruct.h" |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#if KAITAI_STRUCT_VERSION < 9000L |
||||||
|
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" |
||||||
|
#endif |
||||||
|
|
||||||
|
class gps_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
class subframe_1_t; |
||||||
|
class subframe_3_t; |
||||||
|
class subframe_4_t; |
||||||
|
class how_t; |
||||||
|
class tlm_t; |
||||||
|
class subframe_2_t; |
||||||
|
|
||||||
|
gps_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~gps_t(); |
||||||
|
|
||||||
|
class subframe_1_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
subframe_1_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~subframe_1_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
bool f_af_0; |
||||||
|
int32_t m_af_0; |
||||||
|
|
||||||
|
public: |
||||||
|
int32_t af_0(); |
||||||
|
|
||||||
|
private: |
||||||
|
uint64_t m_week_no; |
||||||
|
uint64_t m_code; |
||||||
|
uint64_t m_sv_accuracy; |
||||||
|
uint64_t m_sv_health; |
||||||
|
uint64_t m_iodc_msb; |
||||||
|
bool m_l2_p_data_flag; |
||||||
|
uint64_t m_reserved1; |
||||||
|
uint64_t m_reserved2; |
||||||
|
uint64_t m_reserved3; |
||||||
|
uint64_t m_reserved4; |
||||||
|
int8_t m_t_gd; |
||||||
|
uint8_t m_iodc_lsb; |
||||||
|
uint16_t m_t_oc; |
||||||
|
int8_t m_af_2; |
||||||
|
int16_t m_af_1; |
||||||
|
bool m_af_0_sign; |
||||||
|
uint64_t m_af_0_value; |
||||||
|
uint64_t m_reserved5; |
||||||
|
gps_t* m__root; |
||||||
|
gps_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
uint64_t week_no() const { return m_week_no; } |
||||||
|
uint64_t code() const { return m_code; } |
||||||
|
uint64_t sv_accuracy() const { return m_sv_accuracy; } |
||||||
|
uint64_t sv_health() const { return m_sv_health; } |
||||||
|
uint64_t iodc_msb() const { return m_iodc_msb; } |
||||||
|
bool l2_p_data_flag() const { return m_l2_p_data_flag; } |
||||||
|
uint64_t reserved1() const { return m_reserved1; } |
||||||
|
uint64_t reserved2() const { return m_reserved2; } |
||||||
|
uint64_t reserved3() const { return m_reserved3; } |
||||||
|
uint64_t reserved4() const { return m_reserved4; } |
||||||
|
int8_t t_gd() const { return m_t_gd; } |
||||||
|
uint8_t iodc_lsb() const { return m_iodc_lsb; } |
||||||
|
uint16_t t_oc() const { return m_t_oc; } |
||||||
|
int8_t af_2() const { return m_af_2; } |
||||||
|
int16_t af_1() const { return m_af_1; } |
||||||
|
bool af_0_sign() const { return m_af_0_sign; } |
||||||
|
uint64_t af_0_value() const { return m_af_0_value; } |
||||||
|
uint64_t reserved5() const { return m_reserved5; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class subframe_3_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
subframe_3_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~subframe_3_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
bool f_omega_dot; |
||||||
|
int32_t m_omega_dot; |
||||||
|
|
||||||
|
public: |
||||||
|
int32_t omega_dot(); |
||||||
|
|
||||||
|
private: |
||||||
|
bool f_idot; |
||||||
|
int32_t m_idot; |
||||||
|
|
||||||
|
public: |
||||||
|
int32_t idot(); |
||||||
|
|
||||||
|
private: |
||||||
|
int16_t m_c_ic; |
||||||
|
int32_t m_omega_0; |
||||||
|
int16_t m_c_is; |
||||||
|
int32_t m_i_0; |
||||||
|
int16_t m_c_rc; |
||||||
|
int32_t m_omega; |
||||||
|
bool m_omega_dot_sign; |
||||||
|
uint64_t m_omega_dot_value; |
||||||
|
uint8_t m_iode; |
||||||
|
bool m_idot_sign; |
||||||
|
uint64_t m_idot_value; |
||||||
|
uint64_t m_reserved; |
||||||
|
gps_t* m__root; |
||||||
|
gps_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
int16_t c_ic() const { return m_c_ic; } |
||||||
|
int32_t omega_0() const { return m_omega_0; } |
||||||
|
int16_t c_is() const { return m_c_is; } |
||||||
|
int32_t i_0() const { return m_i_0; } |
||||||
|
int16_t c_rc() const { return m_c_rc; } |
||||||
|
int32_t omega() const { return m_omega; } |
||||||
|
bool omega_dot_sign() const { return m_omega_dot_sign; } |
||||||
|
uint64_t omega_dot_value() const { return m_omega_dot_value; } |
||||||
|
uint8_t iode() const { return m_iode; } |
||||||
|
bool idot_sign() const { return m_idot_sign; } |
||||||
|
uint64_t idot_value() const { return m_idot_value; } |
||||||
|
uint64_t reserved() const { return m_reserved; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class subframe_4_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
class ionosphere_data_t; |
||||||
|
|
||||||
|
subframe_4_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~subframe_4_t(); |
||||||
|
|
||||||
|
class ionosphere_data_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
ionosphere_data_t(kaitai::kstream* p__io, gps_t::subframe_4_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~ionosphere_data_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
int8_t m_a0; |
||||||
|
int8_t m_a1; |
||||||
|
int8_t m_a2; |
||||||
|
int8_t m_a3; |
||||||
|
int8_t m_b0; |
||||||
|
int8_t m_b1; |
||||||
|
int8_t m_b2; |
||||||
|
int8_t m_b3; |
||||||
|
gps_t* m__root; |
||||||
|
gps_t::subframe_4_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
int8_t a0() const { return m_a0; } |
||||||
|
int8_t a1() const { return m_a1; } |
||||||
|
int8_t a2() const { return m_a2; } |
||||||
|
int8_t a3() const { return m_a3; } |
||||||
|
int8_t b0() const { return m_b0; } |
||||||
|
int8_t b1() const { return m_b1; } |
||||||
|
int8_t b2() const { return m_b2; } |
||||||
|
int8_t b3() const { return m_b3; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t::subframe_4_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
private: |
||||||
|
uint64_t m_data_id; |
||||||
|
uint64_t m_page_id; |
||||||
|
ionosphere_data_t* m_body; |
||||||
|
bool n_body; |
||||||
|
|
||||||
|
public: |
||||||
|
bool _is_null_body() { body(); return n_body; }; |
||||||
|
|
||||||
|
private: |
||||||
|
gps_t* m__root; |
||||||
|
gps_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
uint64_t data_id() const { return m_data_id; } |
||||||
|
uint64_t page_id() const { return m_page_id; } |
||||||
|
ionosphere_data_t* body() const { return m_body; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class how_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
how_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~how_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
uint64_t m_tow_count; |
||||||
|
bool m_alert; |
||||||
|
bool m_anti_spoof; |
||||||
|
uint64_t m_subframe_id; |
||||||
|
uint64_t m_reserved; |
||||||
|
gps_t* m__root; |
||||||
|
gps_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
uint64_t tow_count() const { return m_tow_count; } |
||||||
|
bool alert() const { return m_alert; } |
||||||
|
bool anti_spoof() const { return m_anti_spoof; } |
||||||
|
uint64_t subframe_id() const { return m_subframe_id; } |
||||||
|
uint64_t reserved() const { return m_reserved; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class tlm_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
tlm_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~tlm_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
std::string m_magic; |
||||||
|
uint64_t m_tlm; |
||||||
|
bool m_integrity_status; |
||||||
|
bool m_reserved; |
||||||
|
gps_t* m__root; |
||||||
|
gps_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
std::string magic() const { return m_magic; } |
||||||
|
uint64_t tlm() const { return m_tlm; } |
||||||
|
bool integrity_status() const { return m_integrity_status; } |
||||||
|
bool reserved() const { return m_reserved; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class subframe_2_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
subframe_2_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~subframe_2_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
uint8_t m_iode; |
||||||
|
int16_t m_c_rs; |
||||||
|
int16_t m_delta_n; |
||||||
|
int32_t m_m_0; |
||||||
|
int16_t m_c_uc; |
||||||
|
int32_t m_e; |
||||||
|
int16_t m_c_us; |
||||||
|
uint32_t m_sqrt_a; |
||||||
|
uint16_t m_t_oe; |
||||||
|
bool m_fit_interval_flag; |
||||||
|
uint64_t m_aoda; |
||||||
|
uint64_t m_reserved; |
||||||
|
gps_t* m__root; |
||||||
|
gps_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
uint8_t iode() const { return m_iode; } |
||||||
|
int16_t c_rs() const { return m_c_rs; } |
||||||
|
int16_t delta_n() const { return m_delta_n; } |
||||||
|
int32_t m_0() const { return m_m_0; } |
||||||
|
int16_t c_uc() const { return m_c_uc; } |
||||||
|
int32_t e() const { return m_e; } |
||||||
|
int16_t c_us() const { return m_c_us; } |
||||||
|
uint32_t sqrt_a() const { return m_sqrt_a; } |
||||||
|
uint16_t t_oe() const { return m_t_oe; } |
||||||
|
bool fit_interval_flag() const { return m_fit_interval_flag; } |
||||||
|
uint64_t aoda() const { return m_aoda; } |
||||||
|
uint64_t reserved() const { return m_reserved; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
gps_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
private: |
||||||
|
tlm_t* m_tlm; |
||||||
|
how_t* m_how; |
||||||
|
kaitai::kstruct* m_body; |
||||||
|
bool n_body; |
||||||
|
|
||||||
|
public: |
||||||
|
bool _is_null_body() { body(); return n_body; }; |
||||||
|
|
||||||
|
private: |
||||||
|
gps_t* m__root; |
||||||
|
kaitai::kstruct* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
tlm_t* tlm() const { return m_tlm; } |
||||||
|
how_t* how() const { return m_how; } |
||||||
|
kaitai::kstruct* body() const { return m_body; } |
||||||
|
gps_t* _root() const { return m__root; } |
||||||
|
kaitai::kstruct* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // GPS_H_
|
@ -0,0 +1,340 @@ |
|||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "ubx.h" |
||||||
|
#include "kaitai/exceptions.h" |
||||||
|
|
||||||
|
ubx_t::ubx_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = this; |
||||||
|
f_checksum = false; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::_read() { |
||||||
|
m_magic = m__io->read_bytes(2); |
||||||
|
if (!(magic() == std::string("\xB5\x62", 2))) { |
||||||
|
throw kaitai::validation_not_equal_error<std::string>(std::string("\xB5\x62", 2), magic(), _io(), std::string("/seq/0")); |
||||||
|
} |
||||||
|
m_msg_type = m__io->read_u2be(); |
||||||
|
m_length = m__io->read_u2le(); |
||||||
|
n_body = true; |
||||||
|
switch (msg_type()) { |
||||||
|
case 2569: { |
||||||
|
n_body = false; |
||||||
|
m_body = new mon_hw_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 533: { |
||||||
|
n_body = false; |
||||||
|
m_body = new rxm_rawx_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 531: { |
||||||
|
n_body = false; |
||||||
|
m_body = new rxm_sfrbx_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 2571: { |
||||||
|
n_body = false; |
||||||
|
m_body = new mon_hw2_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 263: { |
||||||
|
n_body = false; |
||||||
|
m_body = new nav_pvt_t(m__io, this, m__root); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::~ubx_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::_clean_up() { |
||||||
|
if (!n_body) { |
||||||
|
if (m_body) { |
||||||
|
delete m_body; m_body = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
if (f_checksum) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::rxm_rawx_t::rxm_rawx_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
m_measurements = 0; |
||||||
|
m__raw_measurements = 0; |
||||||
|
m__io__raw_measurements = 0; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::rxm_rawx_t::_read() { |
||||||
|
m_rcv_tow = m__io->read_f8le(); |
||||||
|
m_week = m__io->read_u2le(); |
||||||
|
m_leap_s = m__io->read_s1(); |
||||||
|
m_num_meas = m__io->read_u1(); |
||||||
|
m_rec_stat = m__io->read_u1(); |
||||||
|
m_reserved1 = m__io->read_bytes(3); |
||||||
|
int l_measurements = num_meas(); |
||||||
|
m__raw_measurements = new std::vector<std::string>(); |
||||||
|
m__raw_measurements->reserve(l_measurements); |
||||||
|
m__io__raw_measurements = new std::vector<kaitai::kstream*>(); |
||||||
|
m__io__raw_measurements->reserve(l_measurements); |
||||||
|
m_measurements = new std::vector<meas_t*>(); |
||||||
|
m_measurements->reserve(l_measurements); |
||||||
|
for (int i = 0; i < l_measurements; i++) { |
||||||
|
m__raw_measurements->push_back(m__io->read_bytes(32)); |
||||||
|
kaitai::kstream* io__raw_measurements = new kaitai::kstream(m__raw_measurements->at(m__raw_measurements->size() - 1)); |
||||||
|
m__io__raw_measurements->push_back(io__raw_measurements); |
||||||
|
m_measurements->push_back(new meas_t(io__raw_measurements, this, m__root)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::rxm_rawx_t::~rxm_rawx_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::rxm_rawx_t::_clean_up() { |
||||||
|
if (m__raw_measurements) { |
||||||
|
delete m__raw_measurements; m__raw_measurements = 0; |
||||||
|
} |
||||||
|
if (m__io__raw_measurements) { |
||||||
|
for (std::vector<kaitai::kstream*>::iterator it = m__io__raw_measurements->begin(); it != m__io__raw_measurements->end(); ++it) { |
||||||
|
delete *it; |
||||||
|
} |
||||||
|
delete m__io__raw_measurements; m__io__raw_measurements = 0; |
||||||
|
} |
||||||
|
if (m_measurements) { |
||||||
|
for (std::vector<meas_t*>::iterator it = m_measurements->begin(); it != m_measurements->end(); ++it) { |
||||||
|
delete *it; |
||||||
|
} |
||||||
|
delete m_measurements; m_measurements = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::rxm_rawx_t::meas_t::meas_t(kaitai::kstream* p__io, ubx_t::rxm_rawx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::rxm_rawx_t::meas_t::_read() { |
||||||
|
m_pr_mes = m__io->read_f8le(); |
||||||
|
m_cp_mes = m__io->read_f8le(); |
||||||
|
m_do_mes = m__io->read_f4le(); |
||||||
|
m_gnss_id = static_cast<ubx_t::gnss_type_t>(m__io->read_u1()); |
||||||
|
m_sv_id = m__io->read_u1(); |
||||||
|
m_reserved2 = m__io->read_bytes(1); |
||||||
|
m_freq_id = m__io->read_u1(); |
||||||
|
m_lock_time = m__io->read_u2le(); |
||||||
|
m_cno = m__io->read_u1(); |
||||||
|
m_pr_stdev = m__io->read_u1(); |
||||||
|
m_cp_stdev = m__io->read_u1(); |
||||||
|
m_do_stdev = m__io->read_u1(); |
||||||
|
m_trk_stat = m__io->read_u1(); |
||||||
|
m_reserved3 = m__io->read_bytes(1); |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::rxm_rawx_t::meas_t::~meas_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::rxm_rawx_t::meas_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::rxm_sfrbx_t::rxm_sfrbx_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
m_body = 0; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::rxm_sfrbx_t::_read() { |
||||||
|
m_gnss_id = static_cast<ubx_t::gnss_type_t>(m__io->read_u1()); |
||||||
|
m_sv_id = m__io->read_u1(); |
||||||
|
m_reserved1 = m__io->read_bytes(1); |
||||||
|
m_freq_id = m__io->read_u1(); |
||||||
|
m_num_words = m__io->read_u1(); |
||||||
|
m_reserved2 = m__io->read_bytes(1); |
||||||
|
m_version = m__io->read_u1(); |
||||||
|
m_reserved3 = m__io->read_bytes(1); |
||||||
|
int l_body = num_words(); |
||||||
|
m_body = new std::vector<uint32_t>(); |
||||||
|
m_body->reserve(l_body); |
||||||
|
for (int i = 0; i < l_body; i++) { |
||||||
|
m_body->push_back(m__io->read_u4le()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::rxm_sfrbx_t::~rxm_sfrbx_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::rxm_sfrbx_t::_clean_up() { |
||||||
|
if (m_body) { |
||||||
|
delete m_body; m_body = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::nav_pvt_t::nav_pvt_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::nav_pvt_t::_read() { |
||||||
|
m_i_tow = m__io->read_u4le(); |
||||||
|
m_year = m__io->read_u2le(); |
||||||
|
m_month = m__io->read_u1(); |
||||||
|
m_day = m__io->read_u1(); |
||||||
|
m_hour = m__io->read_u1(); |
||||||
|
m_min = m__io->read_u1(); |
||||||
|
m_sec = m__io->read_u1(); |
||||||
|
m_valid = m__io->read_u1(); |
||||||
|
m_t_acc = m__io->read_u4le(); |
||||||
|
m_nano = m__io->read_s4le(); |
||||||
|
m_fix_type = m__io->read_u1(); |
||||||
|
m_flags = m__io->read_u1(); |
||||||
|
m_flags2 = m__io->read_u1(); |
||||||
|
m_num_sv = m__io->read_u1(); |
||||||
|
m_lon = m__io->read_s4le(); |
||||||
|
m_lat = m__io->read_s4le(); |
||||||
|
m_height = m__io->read_s4le(); |
||||||
|
m_h_msl = m__io->read_s4le(); |
||||||
|
m_h_acc = m__io->read_u4le(); |
||||||
|
m_v_acc = m__io->read_u4le(); |
||||||
|
m_vel_n = m__io->read_s4le(); |
||||||
|
m_vel_e = m__io->read_s4le(); |
||||||
|
m_vel_d = m__io->read_s4le(); |
||||||
|
m_g_speed = m__io->read_s4le(); |
||||||
|
m_head_mot = m__io->read_s4le(); |
||||||
|
m_s_acc = m__io->read_s4le(); |
||||||
|
m_head_acc = m__io->read_u4le(); |
||||||
|
m_p_dop = m__io->read_u2le(); |
||||||
|
m_flags3 = m__io->read_u1(); |
||||||
|
m_reserved1 = m__io->read_bytes(5); |
||||||
|
m_head_veh = m__io->read_s4le(); |
||||||
|
m_mag_dec = m__io->read_s2le(); |
||||||
|
m_mag_acc = m__io->read_u2le(); |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::nav_pvt_t::~nav_pvt_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::nav_pvt_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::mon_hw2_t::mon_hw2_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::mon_hw2_t::_read() { |
||||||
|
m_ofs_i = m__io->read_s1(); |
||||||
|
m_mag_i = m__io->read_u1(); |
||||||
|
m_ofs_q = m__io->read_s1(); |
||||||
|
m_mag_q = m__io->read_u1(); |
||||||
|
m_cfg_source = static_cast<ubx_t::mon_hw2_t::config_source_t>(m__io->read_u1()); |
||||||
|
m_reserved1 = m__io->read_bytes(3); |
||||||
|
m_low_lev_cfg = m__io->read_u4le(); |
||||||
|
m_reserved2 = m__io->read_bytes(8); |
||||||
|
m_post_status = m__io->read_u4le(); |
||||||
|
m_reserved3 = m__io->read_bytes(4); |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::mon_hw2_t::~mon_hw2_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::mon_hw2_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::mon_hw_t::mon_hw_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { |
||||||
|
m__parent = p__parent; |
||||||
|
m__root = p__root; |
||||||
|
|
||||||
|
try { |
||||||
|
_read(); |
||||||
|
} catch(...) { |
||||||
|
_clean_up(); |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::mon_hw_t::_read() { |
||||||
|
m_pin_sel = m__io->read_u4le(); |
||||||
|
m_pin_bank = m__io->read_u4le(); |
||||||
|
m_pin_dir = m__io->read_u4le(); |
||||||
|
m_pin_val = m__io->read_u4le(); |
||||||
|
m_noise_per_ms = m__io->read_u2le(); |
||||||
|
m_agc_cnt = m__io->read_u2le(); |
||||||
|
m_a_status = static_cast<ubx_t::mon_hw_t::antenna_status_t>(m__io->read_u1()); |
||||||
|
m_a_power = static_cast<ubx_t::mon_hw_t::antenna_power_t>(m__io->read_u1()); |
||||||
|
m_flags = m__io->read_u1(); |
||||||
|
m_reserved1 = m__io->read_bytes(1); |
||||||
|
m_used_mask = m__io->read_u4le(); |
||||||
|
m_vp = m__io->read_bytes(17); |
||||||
|
m_jam_ind = m__io->read_u1(); |
||||||
|
m_reserved2 = m__io->read_bytes(2); |
||||||
|
m_pin_irq = m__io->read_u4le(); |
||||||
|
m_pull_h = m__io->read_u4le(); |
||||||
|
m_pull_l = m__io->read_u4le(); |
||||||
|
} |
||||||
|
|
||||||
|
ubx_t::mon_hw_t::~mon_hw_t() { |
||||||
|
_clean_up(); |
||||||
|
} |
||||||
|
|
||||||
|
void ubx_t::mon_hw_t::_clean_up() { |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t ubx_t::checksum() { |
||||||
|
if (f_checksum) |
||||||
|
return m_checksum; |
||||||
|
std::streampos _pos = m__io->pos(); |
||||||
|
m__io->seek((length() + 6)); |
||||||
|
m_checksum = m__io->read_u2le(); |
||||||
|
m__io->seek(_pos); |
||||||
|
f_checksum = true; |
||||||
|
return m_checksum; |
||||||
|
} |
@ -0,0 +1,410 @@ |
|||||||
|
#ifndef UBX_H_ |
||||||
|
#define UBX_H_ |
||||||
|
|
||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "kaitai/kaitaistruct.h" |
||||||
|
#include <stdint.h> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#if KAITAI_STRUCT_VERSION < 9000L |
||||||
|
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" |
||||||
|
#endif |
||||||
|
|
||||||
|
class ubx_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
class rxm_rawx_t; |
||||||
|
class rxm_sfrbx_t; |
||||||
|
class nav_pvt_t; |
||||||
|
class mon_hw2_t; |
||||||
|
class mon_hw_t; |
||||||
|
|
||||||
|
enum gnss_type_t { |
||||||
|
GNSS_TYPE_GPS = 0, |
||||||
|
GNSS_TYPE_SBAS = 1, |
||||||
|
GNSS_TYPE_GALILEO = 2, |
||||||
|
GNSS_TYPE_BEIDOU = 3, |
||||||
|
GNSS_TYPE_IMES = 4, |
||||||
|
GNSS_TYPE_QZSS = 5, |
||||||
|
GNSS_TYPE_GLONASS = 6 |
||||||
|
}; |
||||||
|
|
||||||
|
ubx_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~ubx_t(); |
||||||
|
|
||||||
|
class rxm_rawx_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
class meas_t; |
||||||
|
|
||||||
|
rxm_rawx_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~rxm_rawx_t(); |
||||||
|
|
||||||
|
class meas_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
meas_t(kaitai::kstream* p__io, ubx_t::rxm_rawx_t* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~meas_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
double m_pr_mes; |
||||||
|
double m_cp_mes; |
||||||
|
float m_do_mes; |
||||||
|
gnss_type_t m_gnss_id; |
||||||
|
uint8_t m_sv_id; |
||||||
|
std::string m_reserved2; |
||||||
|
uint8_t m_freq_id; |
||||||
|
uint16_t m_lock_time; |
||||||
|
uint8_t m_cno; |
||||||
|
uint8_t m_pr_stdev; |
||||||
|
uint8_t m_cp_stdev; |
||||||
|
uint8_t m_do_stdev; |
||||||
|
uint8_t m_trk_stat; |
||||||
|
std::string m_reserved3; |
||||||
|
ubx_t* m__root; |
||||||
|
ubx_t::rxm_rawx_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
double pr_mes() const { return m_pr_mes; } |
||||||
|
double cp_mes() const { return m_cp_mes; } |
||||||
|
float do_mes() const { return m_do_mes; } |
||||||
|
gnss_type_t gnss_id() const { return m_gnss_id; } |
||||||
|
uint8_t sv_id() const { return m_sv_id; } |
||||||
|
std::string reserved2() const { return m_reserved2; } |
||||||
|
uint8_t freq_id() const { return m_freq_id; } |
||||||
|
uint16_t lock_time() const { return m_lock_time; } |
||||||
|
uint8_t cno() const { return m_cno; } |
||||||
|
uint8_t pr_stdev() const { return m_pr_stdev; } |
||||||
|
uint8_t cp_stdev() const { return m_cp_stdev; } |
||||||
|
uint8_t do_stdev() const { return m_do_stdev; } |
||||||
|
uint8_t trk_stat() const { return m_trk_stat; } |
||||||
|
std::string reserved3() const { return m_reserved3; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
ubx_t::rxm_rawx_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
private: |
||||||
|
double m_rcv_tow; |
||||||
|
uint16_t m_week; |
||||||
|
int8_t m_leap_s; |
||||||
|
uint8_t m_num_meas; |
||||||
|
uint8_t m_rec_stat; |
||||||
|
std::string m_reserved1; |
||||||
|
std::vector<meas_t*>* m_measurements; |
||||||
|
ubx_t* m__root; |
||||||
|
ubx_t* m__parent; |
||||||
|
std::vector<std::string>* m__raw_measurements; |
||||||
|
std::vector<kaitai::kstream*>* m__io__raw_measurements; |
||||||
|
|
||||||
|
public: |
||||||
|
double rcv_tow() const { return m_rcv_tow; } |
||||||
|
uint16_t week() const { return m_week; } |
||||||
|
int8_t leap_s() const { return m_leap_s; } |
||||||
|
uint8_t num_meas() const { return m_num_meas; } |
||||||
|
uint8_t rec_stat() const { return m_rec_stat; } |
||||||
|
std::string reserved1() const { return m_reserved1; } |
||||||
|
std::vector<meas_t*>* measurements() const { return m_measurements; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
ubx_t* _parent() const { return m__parent; } |
||||||
|
std::vector<std::string>* _raw_measurements() const { return m__raw_measurements; } |
||||||
|
std::vector<kaitai::kstream*>* _io__raw_measurements() const { return m__io__raw_measurements; } |
||||||
|
}; |
||||||
|
|
||||||
|
class rxm_sfrbx_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
rxm_sfrbx_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~rxm_sfrbx_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
gnss_type_t m_gnss_id; |
||||||
|
uint8_t m_sv_id; |
||||||
|
std::string m_reserved1; |
||||||
|
uint8_t m_freq_id; |
||||||
|
uint8_t m_num_words; |
||||||
|
std::string m_reserved2; |
||||||
|
uint8_t m_version; |
||||||
|
std::string m_reserved3; |
||||||
|
std::vector<uint32_t>* m_body; |
||||||
|
ubx_t* m__root; |
||||||
|
ubx_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
gnss_type_t gnss_id() const { return m_gnss_id; } |
||||||
|
uint8_t sv_id() const { return m_sv_id; } |
||||||
|
std::string reserved1() const { return m_reserved1; } |
||||||
|
uint8_t freq_id() const { return m_freq_id; } |
||||||
|
uint8_t num_words() const { return m_num_words; } |
||||||
|
std::string reserved2() const { return m_reserved2; } |
||||||
|
uint8_t version() const { return m_version; } |
||||||
|
std::string reserved3() const { return m_reserved3; } |
||||||
|
std::vector<uint32_t>* body() const { return m_body; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
ubx_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class nav_pvt_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
nav_pvt_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~nav_pvt_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
uint32_t m_i_tow; |
||||||
|
uint16_t m_year; |
||||||
|
uint8_t m_month; |
||||||
|
uint8_t m_day; |
||||||
|
uint8_t m_hour; |
||||||
|
uint8_t m_min; |
||||||
|
uint8_t m_sec; |
||||||
|
uint8_t m_valid; |
||||||
|
uint32_t m_t_acc; |
||||||
|
int32_t m_nano; |
||||||
|
uint8_t m_fix_type; |
||||||
|
uint8_t m_flags; |
||||||
|
uint8_t m_flags2; |
||||||
|
uint8_t m_num_sv; |
||||||
|
int32_t m_lon; |
||||||
|
int32_t m_lat; |
||||||
|
int32_t m_height; |
||||||
|
int32_t m_h_msl; |
||||||
|
uint32_t m_h_acc; |
||||||
|
uint32_t m_v_acc; |
||||||
|
int32_t m_vel_n; |
||||||
|
int32_t m_vel_e; |
||||||
|
int32_t m_vel_d; |
||||||
|
int32_t m_g_speed; |
||||||
|
int32_t m_head_mot; |
||||||
|
int32_t m_s_acc; |
||||||
|
uint32_t m_head_acc; |
||||||
|
uint16_t m_p_dop; |
||||||
|
uint8_t m_flags3; |
||||||
|
std::string m_reserved1; |
||||||
|
int32_t m_head_veh; |
||||||
|
int16_t m_mag_dec; |
||||||
|
uint16_t m_mag_acc; |
||||||
|
ubx_t* m__root; |
||||||
|
ubx_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
uint32_t i_tow() const { return m_i_tow; } |
||||||
|
uint16_t year() const { return m_year; } |
||||||
|
uint8_t month() const { return m_month; } |
||||||
|
uint8_t day() const { return m_day; } |
||||||
|
uint8_t hour() const { return m_hour; } |
||||||
|
uint8_t min() const { return m_min; } |
||||||
|
uint8_t sec() const { return m_sec; } |
||||||
|
uint8_t valid() const { return m_valid; } |
||||||
|
uint32_t t_acc() const { return m_t_acc; } |
||||||
|
int32_t nano() const { return m_nano; } |
||||||
|
uint8_t fix_type() const { return m_fix_type; } |
||||||
|
uint8_t flags() const { return m_flags; } |
||||||
|
uint8_t flags2() const { return m_flags2; } |
||||||
|
uint8_t num_sv() const { return m_num_sv; } |
||||||
|
int32_t lon() const { return m_lon; } |
||||||
|
int32_t lat() const { return m_lat; } |
||||||
|
int32_t height() const { return m_height; } |
||||||
|
int32_t h_msl() const { return m_h_msl; } |
||||||
|
uint32_t h_acc() const { return m_h_acc; } |
||||||
|
uint32_t v_acc() const { return m_v_acc; } |
||||||
|
int32_t vel_n() const { return m_vel_n; } |
||||||
|
int32_t vel_e() const { return m_vel_e; } |
||||||
|
int32_t vel_d() const { return m_vel_d; } |
||||||
|
int32_t g_speed() const { return m_g_speed; } |
||||||
|
int32_t head_mot() const { return m_head_mot; } |
||||||
|
int32_t s_acc() const { return m_s_acc; } |
||||||
|
uint32_t head_acc() const { return m_head_acc; } |
||||||
|
uint16_t p_dop() const { return m_p_dop; } |
||||||
|
uint8_t flags3() const { return m_flags3; } |
||||||
|
std::string reserved1() const { return m_reserved1; } |
||||||
|
int32_t head_veh() const { return m_head_veh; } |
||||||
|
int16_t mag_dec() const { return m_mag_dec; } |
||||||
|
uint16_t mag_acc() const { return m_mag_acc; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
ubx_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class mon_hw2_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
enum config_source_t { |
||||||
|
CONFIG_SOURCE_FLASH = 102, |
||||||
|
CONFIG_SOURCE_OTP = 111, |
||||||
|
CONFIG_SOURCE_CONFIG_PINS = 112, |
||||||
|
CONFIG_SOURCE_ROM = 113 |
||||||
|
}; |
||||||
|
|
||||||
|
mon_hw2_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~mon_hw2_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
int8_t m_ofs_i; |
||||||
|
uint8_t m_mag_i; |
||||||
|
int8_t m_ofs_q; |
||||||
|
uint8_t m_mag_q; |
||||||
|
config_source_t m_cfg_source; |
||||||
|
std::string m_reserved1; |
||||||
|
uint32_t m_low_lev_cfg; |
||||||
|
std::string m_reserved2; |
||||||
|
uint32_t m_post_status; |
||||||
|
std::string m_reserved3; |
||||||
|
ubx_t* m__root; |
||||||
|
ubx_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
int8_t ofs_i() const { return m_ofs_i; } |
||||||
|
uint8_t mag_i() const { return m_mag_i; } |
||||||
|
int8_t ofs_q() const { return m_ofs_q; } |
||||||
|
uint8_t mag_q() const { return m_mag_q; } |
||||||
|
config_source_t cfg_source() const { return m_cfg_source; } |
||||||
|
std::string reserved1() const { return m_reserved1; } |
||||||
|
uint32_t low_lev_cfg() const { return m_low_lev_cfg; } |
||||||
|
std::string reserved2() const { return m_reserved2; } |
||||||
|
uint32_t post_status() const { return m_post_status; } |
||||||
|
std::string reserved3() const { return m_reserved3; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
ubx_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
class mon_hw_t : public kaitai::kstruct { |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
enum antenna_status_t { |
||||||
|
ANTENNA_STATUS_INIT = 0, |
||||||
|
ANTENNA_STATUS_DONTKNOW = 1, |
||||||
|
ANTENNA_STATUS_OK = 2, |
||||||
|
ANTENNA_STATUS_SHORT = 3, |
||||||
|
ANTENNA_STATUS_OPEN = 4 |
||||||
|
}; |
||||||
|
|
||||||
|
enum antenna_power_t { |
||||||
|
ANTENNA_POWER_FALSE = 0, |
||||||
|
ANTENNA_POWER_TRUE = 1, |
||||||
|
ANTENNA_POWER_DONTKNOW = 2 |
||||||
|
}; |
||||||
|
|
||||||
|
mon_hw_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
void _read(); |
||||||
|
void _clean_up(); |
||||||
|
|
||||||
|
public: |
||||||
|
~mon_hw_t(); |
||||||
|
|
||||||
|
private: |
||||||
|
uint32_t m_pin_sel; |
||||||
|
uint32_t m_pin_bank; |
||||||
|
uint32_t m_pin_dir; |
||||||
|
uint32_t m_pin_val; |
||||||
|
uint16_t m_noise_per_ms; |
||||||
|
uint16_t m_agc_cnt; |
||||||
|
antenna_status_t m_a_status; |
||||||
|
antenna_power_t m_a_power; |
||||||
|
uint8_t m_flags; |
||||||
|
std::string m_reserved1; |
||||||
|
uint32_t m_used_mask; |
||||||
|
std::string m_vp; |
||||||
|
uint8_t m_jam_ind; |
||||||
|
std::string m_reserved2; |
||||||
|
uint32_t m_pin_irq; |
||||||
|
uint32_t m_pull_h; |
||||||
|
uint32_t m_pull_l; |
||||||
|
ubx_t* m__root; |
||||||
|
ubx_t* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
uint32_t pin_sel() const { return m_pin_sel; } |
||||||
|
uint32_t pin_bank() const { return m_pin_bank; } |
||||||
|
uint32_t pin_dir() const { return m_pin_dir; } |
||||||
|
uint32_t pin_val() const { return m_pin_val; } |
||||||
|
uint16_t noise_per_ms() const { return m_noise_per_ms; } |
||||||
|
uint16_t agc_cnt() const { return m_agc_cnt; } |
||||||
|
antenna_status_t a_status() const { return m_a_status; } |
||||||
|
antenna_power_t a_power() const { return m_a_power; } |
||||||
|
uint8_t flags() const { return m_flags; } |
||||||
|
std::string reserved1() const { return m_reserved1; } |
||||||
|
uint32_t used_mask() const { return m_used_mask; } |
||||||
|
std::string vp() const { return m_vp; } |
||||||
|
uint8_t jam_ind() const { return m_jam_ind; } |
||||||
|
std::string reserved2() const { return m_reserved2; } |
||||||
|
uint32_t pin_irq() const { return m_pin_irq; } |
||||||
|
uint32_t pull_h() const { return m_pull_h; } |
||||||
|
uint32_t pull_l() const { return m_pull_l; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
ubx_t* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
private: |
||||||
|
bool f_checksum; |
||||||
|
uint16_t m_checksum; |
||||||
|
|
||||||
|
public: |
||||||
|
uint16_t checksum(); |
||||||
|
|
||||||
|
private: |
||||||
|
std::string m_magic; |
||||||
|
uint16_t m_msg_type; |
||||||
|
uint16_t m_length; |
||||||
|
kaitai::kstruct* m_body; |
||||||
|
bool n_body; |
||||||
|
|
||||||
|
public: |
||||||
|
bool _is_null_body() { body(); return n_body; }; |
||||||
|
|
||||||
|
private: |
||||||
|
ubx_t* m__root; |
||||||
|
kaitai::kstruct* m__parent; |
||||||
|
|
||||||
|
public: |
||||||
|
std::string magic() const { return m_magic; } |
||||||
|
uint16_t msg_type() const { return m_msg_type; } |
||||||
|
uint16_t length() const { return m_length; } |
||||||
|
kaitai::kstruct* body() const { return m_body; } |
||||||
|
ubx_t* _root() const { return m__root; } |
||||||
|
kaitai::kstruct* _parent() const { return m__parent; } |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // UBX_H_
|
@ -0,0 +1,189 @@ |
|||||||
|
# https://www.gps.gov/technical/icwg/IS-GPS-200E.pdf |
||||||
|
meta: |
||||||
|
id: gps |
||||||
|
endian: be |
||||||
|
bit-endian: be |
||||||
|
seq: |
||||||
|
- id: tlm |
||||||
|
type: tlm |
||||||
|
- id: how |
||||||
|
type: how |
||||||
|
- id: body |
||||||
|
type: |
||||||
|
switch-on: how.subframe_id |
||||||
|
cases: |
||||||
|
1: subframe_1 |
||||||
|
2: subframe_2 |
||||||
|
3: subframe_3 |
||||||
|
4: subframe_4 |
||||||
|
types: |
||||||
|
tlm: |
||||||
|
seq: |
||||||
|
- id: magic |
||||||
|
contents: [0x8b] |
||||||
|
- id: tlm |
||||||
|
type: b14 |
||||||
|
- id: integrity_status |
||||||
|
type: b1 |
||||||
|
- id: reserved |
||||||
|
type: b1 |
||||||
|
how: |
||||||
|
seq: |
||||||
|
- id: tow_count |
||||||
|
type: b17 |
||||||
|
- id: alert |
||||||
|
type: b1 |
||||||
|
- id: anti_spoof |
||||||
|
type: b1 |
||||||
|
- id: subframe_id |
||||||
|
type: b3 |
||||||
|
- id: reserved |
||||||
|
type: b2 |
||||||
|
subframe_1: |
||||||
|
seq: |
||||||
|
# Word 3 |
||||||
|
- id: week_no |
||||||
|
type: b10 |
||||||
|
- id: code |
||||||
|
type: b2 |
||||||
|
- id: sv_accuracy |
||||||
|
type: b4 |
||||||
|
- id: sv_health |
||||||
|
type: b6 |
||||||
|
- id: iodc_msb |
||||||
|
type: b2 |
||||||
|
# Word 4 |
||||||
|
- id: l2_p_data_flag |
||||||
|
type: b1 |
||||||
|
- id: reserved1 |
||||||
|
type: b23 |
||||||
|
# Word 5 |
||||||
|
- id: reserved2 |
||||||
|
type: b24 |
||||||
|
# Word 6 |
||||||
|
- id: reserved3 |
||||||
|
type: b24 |
||||||
|
# Word 7 |
||||||
|
- id: reserved4 |
||||||
|
type: b16 |
||||||
|
- id: t_gd |
||||||
|
type: s1 |
||||||
|
# Word 8 |
||||||
|
- id: iodc_lsb |
||||||
|
type: u1 |
||||||
|
- id: t_oc |
||||||
|
type: u2 |
||||||
|
# Word 9 |
||||||
|
- id: af_2 |
||||||
|
type: s1 |
||||||
|
- id: af_1 |
||||||
|
type: s2 |
||||||
|
# Word 10 |
||||||
|
- id: af_0_sign |
||||||
|
type: b1 |
||||||
|
- id: af_0_value |
||||||
|
type: b21 |
||||||
|
- id: reserved5 |
||||||
|
type: b2 |
||||||
|
instances: |
||||||
|
af_0: |
||||||
|
value: 'af_0_sign ? (af_0_value - (1 << 21)) : af_0_value' |
||||||
|
subframe_2: |
||||||
|
seq: |
||||||
|
# Word 3 |
||||||
|
- id: iode |
||||||
|
type: u1 |
||||||
|
- id: c_rs |
||||||
|
type: s2 |
||||||
|
# Word 4 & 5 |
||||||
|
- id: delta_n |
||||||
|
type: s2 |
||||||
|
- id: m_0 |
||||||
|
type: s4 |
||||||
|
# Word 6 & 7 |
||||||
|
- id: c_uc |
||||||
|
type: s2 |
||||||
|
- id: e |
||||||
|
type: s4 |
||||||
|
# Word 8 & 9 |
||||||
|
- id: c_us |
||||||
|
type: s2 |
||||||
|
- id: sqrt_a |
||||||
|
type: u4 |
||||||
|
# Word 10 |
||||||
|
- id: t_oe |
||||||
|
type: u2 |
||||||
|
- id: fit_interval_flag |
||||||
|
type: b1 |
||||||
|
- id: aoda |
||||||
|
type: b5 |
||||||
|
- id: reserved |
||||||
|
type: b2 |
||||||
|
subframe_3: |
||||||
|
seq: |
||||||
|
# Word 3 & 4 |
||||||
|
- id: c_ic |
||||||
|
type: s2 |
||||||
|
- id: omega_0 |
||||||
|
type: s4 |
||||||
|
# Word 5 & 6 |
||||||
|
- id: c_is |
||||||
|
type: s2 |
||||||
|
- id: i_0 |
||||||
|
type: s4 |
||||||
|
# Word 7 & 8 |
||||||
|
- id: c_rc |
||||||
|
type: s2 |
||||||
|
- id: omega |
||||||
|
type: s4 |
||||||
|
# Word 9 |
||||||
|
- id: omega_dot_sign |
||||||
|
type: b1 |
||||||
|
- id: omega_dot_value |
||||||
|
type: b23 |
||||||
|
# Word 10 |
||||||
|
- id: iode |
||||||
|
type: u1 |
||||||
|
- id: idot_sign |
||||||
|
type: b1 |
||||||
|
- id: idot_value |
||||||
|
type: b13 |
||||||
|
- id: reserved |
||||||
|
type: b2 |
||||||
|
instances: |
||||||
|
omega_dot: |
||||||
|
value: 'omega_dot_sign ? (omega_dot_value - (1 << 23)) : omega_dot_value' |
||||||
|
idot: |
||||||
|
value: 'idot_sign ? (idot_value - (1 << 13)) : idot_value' |
||||||
|
subframe_4: |
||||||
|
seq: |
||||||
|
# Word 3 |
||||||
|
- id: data_id |
||||||
|
type: b2 |
||||||
|
- id: page_id |
||||||
|
type: b6 |
||||||
|
- id: body |
||||||
|
type: |
||||||
|
switch-on: page_id |
||||||
|
cases: |
||||||
|
56: ionosphere_data |
||||||
|
types: |
||||||
|
ionosphere_data: |
||||||
|
seq: |
||||||
|
- id: a0 |
||||||
|
type: s1 |
||||||
|
- id: a1 |
||||||
|
type: s1 |
||||||
|
- id: a2 |
||||||
|
type: s1 |
||||||
|
- id: a3 |
||||||
|
type: s1 |
||||||
|
- id: b0 |
||||||
|
type: s1 |
||||||
|
- id: b1 |
||||||
|
type: s1 |
||||||
|
- id: b2 |
||||||
|
type: s1 |
||||||
|
- id: b3 |
||||||
|
type: s1 |
||||||
|
|
@ -0,0 +1,259 @@ |
|||||||
|
meta: |
||||||
|
id: ubx |
||||||
|
endian: le |
||||||
|
seq: |
||||||
|
- id: magic |
||||||
|
contents: [0xb5, 0x62] |
||||||
|
- id: msg_type |
||||||
|
type: u2be |
||||||
|
- id: length |
||||||
|
type: u2 |
||||||
|
- id: body |
||||||
|
type: |
||||||
|
switch-on: msg_type |
||||||
|
cases: |
||||||
|
0x0107: nav_pvt |
||||||
|
0x0213: rxm_sfrbx |
||||||
|
0x0215: rxm_rawx |
||||||
|
0x0a09: mon_hw |
||||||
|
0x0a0b: mon_hw2 |
||||||
|
instances: |
||||||
|
checksum: |
||||||
|
pos: length + 6 |
||||||
|
type: u2 |
||||||
|
|
||||||
|
types: |
||||||
|
mon_hw: |
||||||
|
seq: |
||||||
|
- id: pin_sel |
||||||
|
type: u4 |
||||||
|
- id: pin_bank |
||||||
|
type: u4 |
||||||
|
- id: pin_dir |
||||||
|
type: u4 |
||||||
|
- id: pin_val |
||||||
|
type: u4 |
||||||
|
- id: noise_per_ms |
||||||
|
type: u2 |
||||||
|
- id: agc_cnt |
||||||
|
type: u2 |
||||||
|
- id: a_status |
||||||
|
type: u1 |
||||||
|
enum: antenna_status |
||||||
|
- id: a_power |
||||||
|
type: u1 |
||||||
|
enum: antenna_power |
||||||
|
- id: flags |
||||||
|
type: u1 |
||||||
|
- id: reserved1 |
||||||
|
size: 1 |
||||||
|
- id: used_mask |
||||||
|
type: u4 |
||||||
|
- id: vp |
||||||
|
size: 17 |
||||||
|
- id: jam_ind |
||||||
|
type: u1 |
||||||
|
- id: reserved2 |
||||||
|
size: 2 |
||||||
|
- id: pin_irq |
||||||
|
type: u4 |
||||||
|
- id: pull_h |
||||||
|
type: u4 |
||||||
|
- id: pull_l |
||||||
|
type: u4 |
||||||
|
enums: |
||||||
|
antenna_status: |
||||||
|
0: init |
||||||
|
1: dontknow |
||||||
|
2: ok |
||||||
|
3: short |
||||||
|
4: open |
||||||
|
antenna_power: |
||||||
|
0: off |
||||||
|
1: on |
||||||
|
2: dontknow |
||||||
|
|
||||||
|
mon_hw2: |
||||||
|
seq: |
||||||
|
- id: ofs_i |
||||||
|
type: s1 |
||||||
|
- id: mag_i |
||||||
|
type: u1 |
||||||
|
- id: ofs_q |
||||||
|
type: s1 |
||||||
|
- id: mag_q |
||||||
|
type: u1 |
||||||
|
- id: cfg_source |
||||||
|
type: u1 |
||||||
|
enum: config_source |
||||||
|
- id: reserved1 |
||||||
|
size: 3 |
||||||
|
- id: low_lev_cfg |
||||||
|
type: u4 |
||||||
|
- id: reserved2 |
||||||
|
size: 8 |
||||||
|
- id: post_status |
||||||
|
type: u4 |
||||||
|
- id: reserved3 |
||||||
|
size: 4 |
||||||
|
|
||||||
|
enums: |
||||||
|
config_source: |
||||||
|
113: rom |
||||||
|
111: otp |
||||||
|
112: config_pins |
||||||
|
102: flash |
||||||
|
|
||||||
|
rxm_sfrbx: |
||||||
|
seq: |
||||||
|
- id: gnss_id |
||||||
|
type: u1 |
||||||
|
enum: gnss_type |
||||||
|
- id: sv_id |
||||||
|
type: u1 |
||||||
|
- id: reserved1 |
||||||
|
size: 1 |
||||||
|
- id: freq_id |
||||||
|
type: u1 |
||||||
|
- id: num_words |
||||||
|
type: u1 |
||||||
|
- id: reserved2 |
||||||
|
size: 1 |
||||||
|
- id: version |
||||||
|
type: u1 |
||||||
|
- id: reserved3 |
||||||
|
size: 1 |
||||||
|
- id: body |
||||||
|
type: u4 |
||||||
|
repeat: expr |
||||||
|
repeat-expr: num_words |
||||||
|
|
||||||
|
rxm_rawx: |
||||||
|
seq: |
||||||
|
- id: rcv_tow |
||||||
|
type: f8 |
||||||
|
- id: week |
||||||
|
type: u2 |
||||||
|
- id: leap_s |
||||||
|
type: s1 |
||||||
|
- id: num_meas |
||||||
|
type: u1 |
||||||
|
- id: rec_stat |
||||||
|
type: u1 |
||||||
|
- id: reserved1 |
||||||
|
size: 3 |
||||||
|
- id: measurements |
||||||
|
type: meas |
||||||
|
size: 32 |
||||||
|
repeat: expr |
||||||
|
repeat-expr: num_meas |
||||||
|
types: |
||||||
|
meas: |
||||||
|
seq: |
||||||
|
- id: pr_mes |
||||||
|
type: f8 |
||||||
|
- id: cp_mes |
||||||
|
type: f8 |
||||||
|
- id: do_mes |
||||||
|
type: f4 |
||||||
|
- id: gnss_id |
||||||
|
type: u1 |
||||||
|
enum: gnss_type |
||||||
|
- id: sv_id |
||||||
|
type: u1 |
||||||
|
- id: reserved2 |
||||||
|
size: 1 |
||||||
|
- id: freq_id |
||||||
|
type: u1 |
||||||
|
- id: lock_time |
||||||
|
type: u2 |
||||||
|
- id: cno |
||||||
|
type: u1 |
||||||
|
- id: pr_stdev |
||||||
|
type: u1 |
||||||
|
- id: cp_stdev |
||||||
|
type: u1 |
||||||
|
- id: do_stdev |
||||||
|
type: u1 |
||||||
|
- id: trk_stat |
||||||
|
type: u1 |
||||||
|
- id: reserved3 |
||||||
|
size: 1 |
||||||
|
|
||||||
|
nav_pvt: |
||||||
|
seq: |
||||||
|
- id: i_tow |
||||||
|
type: u4 |
||||||
|
- id: year |
||||||
|
type: u2 |
||||||
|
- id: month |
||||||
|
type: u1 |
||||||
|
- id: day |
||||||
|
type: u1 |
||||||
|
- id: hour |
||||||
|
type: u1 |
||||||
|
- id: min |
||||||
|
type: u1 |
||||||
|
- id: sec |
||||||
|
type: u1 |
||||||
|
- id: valid |
||||||
|
type: u1 |
||||||
|
- id: t_acc |
||||||
|
type: u4 |
||||||
|
- id: nano |
||||||
|
type: s4 |
||||||
|
- id: fix_type |
||||||
|
type: u1 |
||||||
|
- id: flags |
||||||
|
type: u1 |
||||||
|
- id: flags2 |
||||||
|
type: u1 |
||||||
|
- id: num_sv |
||||||
|
type: u1 |
||||||
|
- id: lon |
||||||
|
type: s4 |
||||||
|
- id: lat |
||||||
|
type: s4 |
||||||
|
- id: height |
||||||
|
type: s4 |
||||||
|
- id: h_msl |
||||||
|
type: s4 |
||||||
|
- id: h_acc |
||||||
|
type: u4 |
||||||
|
- id: v_acc |
||||||
|
type: u4 |
||||||
|
- id: vel_n |
||||||
|
type: s4 |
||||||
|
- id: vel_e |
||||||
|
type: s4 |
||||||
|
- id: vel_d |
||||||
|
type: s4 |
||||||
|
- id: g_speed |
||||||
|
type: s4 |
||||||
|
- id: head_mot |
||||||
|
type: s4 |
||||||
|
- id: s_acc |
||||||
|
type: s4 |
||||||
|
- id: head_acc |
||||||
|
type: u4 |
||||||
|
- id: p_dop |
||||||
|
type: u2 |
||||||
|
- id: flags3 |
||||||
|
type: u1 |
||||||
|
- id: reserved1 |
||||||
|
size: 5 |
||||||
|
- id: head_veh |
||||||
|
type: s4 |
||||||
|
- id: mag_dec |
||||||
|
type: s2 |
||||||
|
- id: mag_acc |
||||||
|
type: u2 |
||||||
|
enums: |
||||||
|
gnss_type: |
||||||
|
0: gps |
||||||
|
1: sbas |
||||||
|
2: galileo |
||||||
|
3: beidou |
||||||
|
4: imes |
||||||
|
5: qzss |
||||||
|
6: glonass |
Loading…
Reference in new issue