mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-03-03 18:25:23 +00:00
[TAS-174] retrieve NavData (W1→W5) directly from osnma test vector file. Add Osnma_Helper class. remove tag.build_message. Ignore W33. Reporting changes.
This commit is contained in:
parent
c9259d87db
commit
a3a5f28e7f
@ -22,6 +22,7 @@
|
|||||||
#include "gnss_crypto.h"
|
#include "gnss_crypto.h"
|
||||||
#include "gnss_satellite.h"
|
#include "gnss_satellite.h"
|
||||||
#include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader
|
#include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader
|
||||||
|
#include "osnma_helper.h"
|
||||||
#include <glog/logging.h> // for DLOG
|
#include <glog/logging.h> // for DLOG
|
||||||
#include <gnuradio/io_signature.h> // for gr::io_signature::make
|
#include <gnuradio/io_signature.h> // for gr::io_signature::make
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -60,6 +61,7 @@ osnma_msg_receiver::osnma_msg_receiver(
|
|||||||
{
|
{
|
||||||
d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>();
|
d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>();
|
||||||
d_crypto = std::make_unique<Gnss_Crypto>(pemFilePath, merkleFilePath);
|
d_crypto = std::make_unique<Gnss_Crypto>(pemFilePath, merkleFilePath);
|
||||||
|
d_helper = std::make_unique<Osnma_Helper>();
|
||||||
// register OSNMA input message port from telemetry blocks
|
// register OSNMA input message port from telemetry blocks
|
||||||
this->message_port_register_in(pmt::mp("OSNMA_from_TLM"));
|
this->message_port_register_in(pmt::mp("OSNMA_from_TLM"));
|
||||||
// register OSNMA output message port to PVT block
|
// register OSNMA output message port to PVT block
|
||||||
@ -89,14 +91,13 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg)
|
|||||||
{
|
{
|
||||||
const auto nma_msg = wht::any_cast<std::shared_ptr<OSNMA_msg>>(pmt::any_ref(msg));
|
const auto nma_msg = wht::any_cast<std::shared_ptr<OSNMA_msg>>(pmt::any_ref(msg));
|
||||||
const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN);
|
const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN);
|
||||||
LOG(INFO) << "Galileo OSNMA: Subframe received starting at "
|
LOG(WARNING) << "Galileo OSNMA: Subframe received starting at "
|
||||||
<< "WN="
|
<< "WN="
|
||||||
<< nma_msg->WN_sf0
|
<< nma_msg->WN_sf0
|
||||||
<< ", TOW="
|
<< ", TOW="
|
||||||
<< nma_msg->TOW_sf0
|
<< nma_msg->TOW_sf0
|
||||||
<< ", from satellite "
|
<< ", from satellite "
|
||||||
<< sat
|
<< sat;
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
process_osnma_message(nma_msg);
|
process_osnma_message(nma_msg);
|
||||||
|
|
||||||
@ -127,7 +128,10 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr<OSNMA_msg>&
|
|||||||
{
|
{
|
||||||
read_nma_header(osnma_msg->hkroot[0]);
|
read_nma_header(osnma_msg->hkroot[0]);
|
||||||
if(d_osnma_data.d_nma_header.nmas == 0 || d_osnma_data.d_nma_header.nmas == 3 /*&& d_kroot_verified*/)
|
if(d_osnma_data.d_nma_header.nmas == 0 || d_osnma_data.d_nma_header.nmas == 3 /*&& d_kroot_verified*/)
|
||||||
return;
|
{
|
||||||
|
LOG(ERROR) << "Galileo OSNMA: NMAS invalid, skipping osnma message\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
read_dsm_header(osnma_msg->hkroot[1]);
|
read_dsm_header(osnma_msg->hkroot[1]);
|
||||||
read_dsm_block(osnma_msg);
|
read_dsm_block(osnma_msg);
|
||||||
process_dsm_block(osnma_msg); // will process dsm block if received a complete one, then will call mack processing upon re-setting the dsm block to 0
|
process_dsm_block(osnma_msg); // will process dsm block if received a complete one, then will call mack processing upon re-setting the dsm block to 0
|
||||||
@ -574,6 +578,9 @@ void osnma_msg_receiver::read_and_process_mack_block(const std::shared_ptr<OSNMA
|
|||||||
if (d_kroot_verified || d_tesla_key_verified || d_osnma_data.d_dsm_kroot_message.ts != 0 /*mack parser needs to know the tag size, otherwise cannot parse mack messages*/) // C: 4 ts < ts < 10
|
if (d_kroot_verified || d_tesla_key_verified || d_osnma_data.d_dsm_kroot_message.ts != 0 /*mack parser needs to know the tag size, otherwise cannot parse mack messages*/) // C: 4 ts < ts < 10
|
||||||
{ // TODO - correct? with this, MACK would not be processed unless a Kroot is available -- no, if TK available MACK sould go on, this has to change in future
|
{ // TODO - correct? with this, MACK would not be processed unless a Kroot is available -- no, if TK available MACK sould go on, this has to change in future
|
||||||
read_mack_header();
|
read_mack_header();
|
||||||
|
d_osnma_data.d_mack_message.PRNa = osnma_msg->PRN; // FIXME this is ugly.
|
||||||
|
d_osnma_data.d_mack_message.TOW = osnma_msg->TOW_sf0;
|
||||||
|
d_osnma_data.d_mack_message.WN = osnma_msg->WN_sf0;
|
||||||
read_mack_body();
|
read_mack_body();
|
||||||
process_mack_message();
|
process_mack_message();
|
||||||
// TODO - shorten the MACK processing for the cases where no TK verified or no Kroot verified (warm and cold start)
|
// TODO - shorten the MACK processing for the cases where no TK verified or no Kroot verified (warm and cold start)
|
||||||
@ -649,8 +656,6 @@ void osnma_msg_receiver::read_mack_header()
|
|||||||
d_osnma_data.d_mack_message.header.tag0 = first_lt_bits;
|
d_osnma_data.d_mack_message.header.tag0 = first_lt_bits;
|
||||||
d_osnma_data.d_mack_message.header.macseq = macseq;
|
d_osnma_data.d_mack_message.header.macseq = macseq;
|
||||||
d_osnma_data.d_mack_message.header.cop = cop;
|
d_osnma_data.d_mack_message.header.cop = cop;
|
||||||
d_osnma_data.d_mack_message.PRNa = d_osnma_data.d_nav_data.PRNa; // FIXME this is ugly.
|
|
||||||
d_osnma_data.d_mack_message.TOW = d_osnma_data.d_nav_data.TOW_sf0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -866,9 +871,10 @@ void osnma_msg_receiver::process_mack_message()
|
|||||||
if(d_tesla_keys.find(mack->TOW + 30) != d_tesla_keys.end()){
|
if(d_tesla_keys.find(mack->TOW + 30) != d_tesla_keys.end()){
|
||||||
bool ret = verify_macseq(*mack);
|
bool ret = verify_macseq(*mack);
|
||||||
if (ret || d_flag_debug){
|
if (ret || d_flag_debug){
|
||||||
for(auto& tag:mack->tag_and_info)
|
for(std::size_t i = 0; i < mack->tag_and_info.size(); ++i)
|
||||||
{
|
{
|
||||||
Tag t(tag, mack->TOW, mack->PRNa);
|
auto& tag = mack->tag_and_info[i];
|
||||||
|
Tag t(tag, mack->TOW, mack->WN, mack->PRNa, i + 2); // tag0 (mack header) has CTR1, so first tag of MTI has CTR = 2.
|
||||||
d_tags_awaiting_verify.insert(std::pair(mack->TOW, t));
|
d_tags_awaiting_verify.insert(std::pair(mack->TOW, t));
|
||||||
LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa;
|
LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa;
|
||||||
}
|
}
|
||||||
@ -992,7 +998,43 @@ bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message)
|
|||||||
}
|
}
|
||||||
bool osnma_msg_receiver::verify_tag(Tag& tag)
|
bool osnma_msg_receiver::verify_tag(Tag& tag)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> m = tag.build_message();
|
// build message
|
||||||
|
std::vector<uint8_t> m;
|
||||||
|
m.push_back(static_cast<uint8_t>(tag.PRN_d));
|
||||||
|
m.push_back(static_cast<uint8_t>(tag.PRNa));
|
||||||
|
uint32_t GST = d_helper->compute_gst(tag.TOW, tag.WN);
|
||||||
|
std::vector<uint8_t> GST_uint8 = d_helper->gst_to_uint8(GST);
|
||||||
|
m.insert(m.end(),GST_uint8.begin(),GST_uint8.end());
|
||||||
|
m.push_back(tag.CTR);
|
||||||
|
// Extracts only two bits from d_osnma_data.d_nma_header.nmas
|
||||||
|
uint8_t two_bits_nmas = d_osnma_data.d_nma_header.nmas & 0b00000011;
|
||||||
|
two_bits_nmas = two_bits_nmas << 6;
|
||||||
|
m.push_back(two_bits_nmas);
|
||||||
|
|
||||||
|
// convert std::string to vector<uint8_t>
|
||||||
|
std::string ephemeris_iono_vector_2 = d_satellite_nav_data[tag.TOW][tag.PRNa].ephemeris_iono_vector_2;
|
||||||
|
std::vector<uint8_t> ephemeris_iono_vector_2_bytes(ephemeris_iono_vector_2.begin(), ephemeris_iono_vector_2.end());
|
||||||
|
|
||||||
|
// Convert and add ephemeris_iono_vector_2 into the vector
|
||||||
|
for (uint8_t byte : ephemeris_iono_vector_2_bytes) {
|
||||||
|
m.back() |= (byte >> 2); // First take the 6 MSB bits of byte and add to m
|
||||||
|
m.push_back(byte << 6); // Then take the last 2 bits of byte, shift them to MSB position and insert the new element into m
|
||||||
|
}
|
||||||
|
if(m.back() == 0) {
|
||||||
|
m.pop_back(); // Remove the last element if its value is 0 (only padding was added)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Pad with zeros if the last element wasn't full
|
||||||
|
for (int bits = 2; bits < 8; bits += 2) {
|
||||||
|
// Check if the last element in the vector has 2 '00' bits in its LSB position
|
||||||
|
if((m.back() & 0b00000011) == 0) {
|
||||||
|
m.back() <<= 2; // Shift the existing bits to make room for new 2 bits
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break; // If it does not have 2 '00' bits in its LSB position, then the padding is complete
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> mac;
|
std::vector<uint8_t> mac;
|
||||||
if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256
|
if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256
|
||||||
@ -1044,36 +1086,9 @@ bool osnma_msg_receiver::verify_tag(Tag& tag)
|
|||||||
|
|
||||||
// Compare computed tag with received one truncated
|
// Compare computed tag with received one truncated
|
||||||
if (tag.received_tag == computed_mac)
|
if (tag.received_tag == computed_mac)
|
||||||
{
|
|
||||||
// if(tag.ADKD == 0 || tag.ADKD == 12)
|
|
||||||
// {
|
|
||||||
// std::cout << "Galileo OSNMA: tag verification successful for PRN_a "
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].PRNa << " with WN="
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].WN_sf0 << ", TOW="
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].TOW_sf0 << "NavData= "
|
|
||||||
// << "Ephemeris, Clock and Ionospheric data" << ". "
|
|
||||||
// << std::endl;
|
|
||||||
// }
|
|
||||||
// else if(tag.ADKD == 4)
|
|
||||||
// {
|
|
||||||
// std::cout << "Galileo OSNMA: tag verification successful for PRN_a "
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].PRNa << " with WN="
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].WN_sf0 << ", TOW="
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].TOW_sf0 << "NavData= "
|
|
||||||
// << "Timing data" << ". "
|
|
||||||
// << std::endl;
|
|
||||||
// }
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// std::cout << "Galileo OSNMA: Tag verification failed for PRN_a "
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].PRNa << " with WN="
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].WN_sf0 << ", TOW="
|
|
||||||
// << d_satellite_nav_data[tag.PRN_d][tag.TOW-30].TOW_sf0 << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void osnma_msg_receiver::add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data)
|
void osnma_msg_receiver::add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,7 @@ friend class test_case_name##_##test_name##_Test
|
|||||||
|
|
||||||
class OSNMA_DSM_Reader;
|
class OSNMA_DSM_Reader;
|
||||||
class Gnss_Crypto;
|
class Gnss_Crypto;
|
||||||
|
class Osnma_Helper;
|
||||||
class osnma_msg_receiver;
|
class osnma_msg_receiver;
|
||||||
|
|
||||||
using osnma_msg_receiver_sptr = gnss_shared_ptr<osnma_msg_receiver>;
|
using osnma_msg_receiver_sptr = gnss_shared_ptr<osnma_msg_receiver>;
|
||||||
@ -88,6 +89,7 @@ private:
|
|||||||
std::multimap<uint32_t, Tag> d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW
|
std::multimap<uint32_t, Tag> d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW
|
||||||
std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader;
|
std::unique_ptr<OSNMA_DSM_Reader> d_dsm_reader;
|
||||||
std::unique_ptr<Gnss_Crypto> d_crypto;
|
std::unique_ptr<Gnss_Crypto> d_crypto;
|
||||||
|
std::unique_ptr<Osnma_Helper> d_helper;
|
||||||
|
|
||||||
std::array<std::array<uint8_t, 256>, 16> d_dsm_message{}; // structure for recording DSM blocks, when filled it sends them to parse and resets itself.
|
std::array<std::array<uint8_t, 256>, 16> d_dsm_message{}; // structure for recording DSM blocks, when filled it sends them to parse and resets itself.
|
||||||
std::array<std::array<uint8_t, 16>, 16> d_dsm_id_received{};
|
std::array<std::array<uint8_t, 16>, 16> d_dsm_id_received{};
|
||||||
|
@ -96,6 +96,8 @@ set(SYSTEM_PARAMETERS_HEADERS
|
|||||||
Galileo_OSNMA.h
|
Galileo_OSNMA.h
|
||||||
osnma_data.h
|
osnma_data.h
|
||||||
osnma_dsm_reader.h
|
osnma_dsm_reader.h
|
||||||
|
osnma_helper.cc
|
||||||
|
osnma_helper.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(SORT SYSTEM_PARAMETERS_HEADERS)
|
list(SORT SYSTEM_PARAMETERS_HEADERS)
|
||||||
|
@ -51,7 +51,8 @@ public:
|
|||||||
uint32_t PRN{};
|
uint32_t PRN{};
|
||||||
uint32_t WN_sf0{}; // TODO - this is present in UtcModelData already
|
uint32_t WN_sf0{}; // TODO - this is present in UtcModelData already
|
||||||
uint32_t TOW_sf0{};
|
uint32_t TOW_sf0{};
|
||||||
std::vector<uint8_t> EphemerisClockAndStatusData {};
|
std::vector<uint8_t> EphemerisClockAndStatusData {}; // TODO _2 rename and substitute this
|
||||||
|
std::string EphemerisClockAndStatusData_2{};
|
||||||
std::vector<uint8_t> TimingData {};
|
std::vector<uint8_t> TimingData {};
|
||||||
Galileo_Ephemeris EphemerisData {};
|
Galileo_Ephemeris EphemerisData {};
|
||||||
Galileo_Iono IonoData {};
|
Galileo_Iono IonoData {};
|
||||||
|
@ -35,6 +35,9 @@ void NavData::init(const std::shared_ptr<OSNMA_msg> &osnma_msg)
|
|||||||
PRNa = osnma_msg->PRN;
|
PRNa = osnma_msg->PRN;
|
||||||
WN_sf0 = osnma_msg->WN_sf0;
|
WN_sf0 = osnma_msg->WN_sf0;
|
||||||
TOW_sf0 = osnma_msg->TOW_sf0;
|
TOW_sf0 = osnma_msg->TOW_sf0;
|
||||||
|
|
||||||
|
// new parsing, directly parsing bits
|
||||||
|
ephemeris_iono_vector_2 = osnma_msg->EphemerisClockAndStatusData_2;
|
||||||
};
|
};
|
||||||
void NavData::generate_eph_iono_vector()
|
void NavData::generate_eph_iono_vector()
|
||||||
{
|
{
|
||||||
@ -166,8 +169,3 @@ void NavData::generate_utc_vector()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> Tag::build_message()
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return std::vector<uint8_t>();
|
|
||||||
}
|
|
||||||
|
@ -121,7 +121,8 @@ public:
|
|||||||
MACK_header header;
|
MACK_header header;
|
||||||
std::vector<MACK_tag_and_info> tag_and_info;
|
std::vector<MACK_tag_and_info> tag_and_info;
|
||||||
std::vector<uint8_t> key;
|
std::vector<uint8_t> key;
|
||||||
uint32_t TOW; // TODO duplicated variable
|
uint32_t TOW; // TODO duplicated variable, also in NavData
|
||||||
|
uint32_t WN;
|
||||||
uint32_t PRNa;
|
uint32_t PRNa;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,6 +132,7 @@ public:
|
|||||||
NavData()=default;
|
NavData()=default;
|
||||||
void init(const std::shared_ptr<OSNMA_msg> &osnma_msg);
|
void init(const std::shared_ptr<OSNMA_msg> &osnma_msg);
|
||||||
std::vector<uint8_t> ephemeris_iono_vector{};
|
std::vector<uint8_t> ephemeris_iono_vector{};
|
||||||
|
std::string ephemeris_iono_vector_2{};
|
||||||
std::vector<uint8_t> utc_vector{};
|
std::vector<uint8_t> utc_vector{};
|
||||||
uint32_t PRNa{};
|
uint32_t PRNa{};
|
||||||
uint32_t WN_sf0{};
|
uint32_t WN_sf0{};
|
||||||
@ -168,10 +170,12 @@ public:
|
|||||||
SUCCESS,
|
SUCCESS,
|
||||||
FAIL,
|
FAIL,
|
||||||
UNVERIFIED};
|
UNVERIFIED};
|
||||||
Tag(const MACK_tag_and_info& MTI, uint32_t TOW, uint32_t PRNa)
|
Tag(const MACK_tag_and_info& MTI, uint32_t TOW,uint32_t WN, uint32_t PRNa,uint8_t CTR)
|
||||||
: tag_id(id_counter++),
|
: tag_id(id_counter++),
|
||||||
TOW(TOW),
|
TOW(TOW), // TODO missing for build_message WN for GST computation, CTR, NMAS, NavData missing
|
||||||
|
WN(WN),
|
||||||
PRNa(PRNa),
|
PRNa(PRNa),
|
||||||
|
CTR(CTR),
|
||||||
status(UNVERIFIED),
|
status(UNVERIFIED),
|
||||||
received_tag(MTI.tag),
|
received_tag(MTI.tag),
|
||||||
computed_tag(0),
|
computed_tag(0),
|
||||||
@ -184,10 +188,11 @@ public:
|
|||||||
|
|
||||||
const uint32_t tag_id;
|
const uint32_t tag_id;
|
||||||
uint32_t TOW;
|
uint32_t TOW;
|
||||||
|
uint32_t WN;
|
||||||
uint32_t PRNa;
|
uint32_t PRNa;
|
||||||
|
uint8_t CTR;
|
||||||
e_verification_status status;
|
e_verification_status status;
|
||||||
uint64_t received_tag;
|
uint64_t received_tag;
|
||||||
std::vector<uint8_t> build_message();
|
|
||||||
|
|
||||||
uint32_t static id_counter;
|
uint32_t static id_counter;
|
||||||
uint64_t computed_tag;
|
uint64_t computed_tag;
|
||||||
|
34
src/core/system_parameters/osnma_helper.cc
Normal file
34
src/core/system_parameters/osnma_helper.cc
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* \file osnma_helper.h
|
||||||
|
* \brief Class for auxiliary osnma functions
|
||||||
|
* \author Carles Fernandez-Prades, 2024 cfernandez(at)cttc.es
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osnma_helper.h"
|
||||||
|
|
||||||
|
uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const
|
||||||
|
{
|
||||||
|
uint32_t GST = (WN & 0x00000FFF) << 20 | (TOW & 0x000FFFFF);
|
||||||
|
return GST;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Osnma_Helper::gst_to_uint8(uint32_t GST) const
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> res(4);
|
||||||
|
|
||||||
|
res[1] = static_cast<uint8_t>((GST & 0xFF000000) >> 24);
|
||||||
|
res[2] = static_cast<uint8_t>((GST & 0x00FF0000) >> 16);
|
||||||
|
res[3] = static_cast<uint8_t>((GST & 0x0000FF00) >> 8);
|
||||||
|
res[4] = static_cast<uint8_t>(GST & 0x000000FF);
|
||||||
|
return res;
|
||||||
|
}
|
33
src/core/system_parameters/osnma_helper.h
Normal file
33
src/core/system_parameters/osnma_helper.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*!
|
||||||
|
* \file osnma_helper.h
|
||||||
|
* \brief Class for auxiliary osnma functions
|
||||||
|
* \author Carles Fernandez-Prades, 2024 cfernandez(at)cttc.es
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_OSNMA_HELPER_H
|
||||||
|
#define GNSS_SDR_OSNMA_HELPER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
class Osnma_Helper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Osnma_Helper() = default;
|
||||||
|
~Osnma_Helper() = default;
|
||||||
|
uint32_t compute_gst(uint32_t WN, uint32_t TOW) const;
|
||||||
|
std::vector<uint8_t> gst_to_uint8(uint32_t GST) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GNSS_SDR_OSNMA_HELPER_H
|
@ -99,6 +99,8 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
|||||||
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES};
|
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES};
|
||||||
const int DURATION_SUBFRAME{30};
|
const int DURATION_SUBFRAME{30};
|
||||||
|
|
||||||
|
const int DUMMY_PAGE{63};
|
||||||
|
bool flag_dummy_page{false};
|
||||||
std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS
|
std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS
|
||||||
<< ", TOW=" << TOW
|
<< ", TOW=" << TOW
|
||||||
<< ", WN=" << WN << std::endl;
|
<< ", WN=" << WN << std::endl;
|
||||||
@ -107,10 +109,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
|||||||
// Act
|
// Act
|
||||||
while (end_of_hex_stream == false){ // loop over all bytes of data. Note all TestVectors have same amount of data.
|
while (end_of_hex_stream == false){ // loop over all bytes of data. Note all TestVectors have same amount of data.
|
||||||
for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe
|
for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe
|
||||||
|
std::cout << "OsnmaTestVectorsSimulation: SVID "<< tv.svId << std::endl;
|
||||||
auto osnmaMsg_sptr = std::make_shared<OSNMA_msg>();
|
auto osnmaMsg_sptr = std::make_shared<OSNMA_msg>();
|
||||||
std::array<uint8_t, 15> hkroot{};
|
std::array<uint8_t, 15> hkroot{};
|
||||||
std::array<uint32_t, 15> mack{};
|
std::array<uint32_t, 15> mack{};
|
||||||
byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes)
|
byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes)
|
||||||
|
std::map<uint8_t, std::bitset<128>> words;
|
||||||
for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe
|
for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe
|
||||||
{
|
{
|
||||||
// extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index
|
// extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index
|
||||||
@ -133,6 +137,34 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
|||||||
bool tail_bits_OK = even_page.substr(even_page.size() - 6) == "000000" && odd_page.substr(odd_page.size() - 6) == "000000";
|
bool tail_bits_OK = even_page.substr(even_page.size() - 6) == "000000" && odd_page.substr(odd_page.size() - 6) == "000000";
|
||||||
if(!even_odd_OK || !page_type_OK || !tail_bits_OK)
|
if(!even_odd_OK || !page_type_OK || !tail_bits_OK)
|
||||||
std::cerr<< "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
|
std::cerr<< "OsnmaTestVectorsSimulation: error parsing pages." << std::endl;
|
||||||
|
|
||||||
|
std::bitset<112> data_k(even_page.substr(2,112));
|
||||||
|
std::bitset<16> data_j(odd_page.substr(2,16));
|
||||||
|
std::bitset<112> shifted_data_k = data_k;
|
||||||
|
// uint8_t word_type = 0;
|
||||||
|
// for(int i = 0; i < 6; ++i) {
|
||||||
|
// word_type |= (data_k[104 + i] << i);
|
||||||
|
// }
|
||||||
|
uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word
|
||||||
|
std::cout<< "OsnmaTestVectorsSimulation: received Word "<< static_cast<int>(word_type) << std::endl;
|
||||||
|
if( (word_type >= 1 && word_type <=5) || word_type == 6 || word_type == 10)
|
||||||
|
{
|
||||||
|
// store raw word
|
||||||
|
std::bitset<128> data_combined(data_k.to_string() + data_j.to_string());
|
||||||
|
words[word_type] = data_combined;
|
||||||
|
// std::vector<uint8_t> concatenatedData;
|
||||||
|
// for (std::size_t i = 0; i < data_k.size(); i += 8) {
|
||||||
|
// std::bitset<8> byte(data_k.to_string().substr(i, 8));
|
||||||
|
// concatenatedData.push_back(static_cast<uint8_t>(byte.to_ulong()));
|
||||||
|
// }
|
||||||
|
// for (std::size_t i = 0; i < data_j.size(); i += 8) {
|
||||||
|
// std::bitset<8> byte(data_j.to_string().substr(i, 8));
|
||||||
|
// concatenatedData.push_back(static_cast<uint8_t>(byte.to_ulong()));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
if(word_type == DUMMY_PAGE)
|
||||||
|
flag_dummy_page = true;
|
||||||
|
// place it into osnma object.
|
||||||
std::bitset<40> osnmaBits(odd_page.substr(18, 40));
|
std::bitset<40> osnmaBits(odd_page.substr(18, 40));
|
||||||
// Extract bits for hkroot and mack
|
// Extract bits for hkroot and mack
|
||||||
std::bitset<8> hkrootBits(osnmaBits.to_string().substr(0, 8));
|
std::bitset<8> hkrootBits(osnmaBits.to_string().substr(0, 8));
|
||||||
@ -142,8 +174,13 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
|||||||
|
|
||||||
byte_index += SIZE_PAGE_BYTES;
|
byte_index += SIZE_PAGE_BYTES;
|
||||||
}
|
}
|
||||||
|
std::cout<< "----------" << std::endl;
|
||||||
if(end_of_hex_stream)
|
if(end_of_hex_stream)
|
||||||
break;
|
break;
|
||||||
|
if(flag_dummy_page){
|
||||||
|
flag_dummy_page = false;
|
||||||
|
continue; // skip this SV
|
||||||
|
}
|
||||||
osnmaMsg_sptr->hkroot = hkroot;
|
osnmaMsg_sptr->hkroot = hkroot;
|
||||||
osnmaMsg_sptr->mack = mack;
|
osnmaMsg_sptr->mack = mack;
|
||||||
|
|
||||||
@ -151,6 +188,63 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
|||||||
osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ;
|
osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ;
|
||||||
osnmaMsg_sptr->PRN = tv.svId;
|
osnmaMsg_sptr->PRN = tv.svId;
|
||||||
|
|
||||||
|
bool allWordsReceived = true;
|
||||||
|
for (int i = 1; i <= 5; ++i)
|
||||||
|
{
|
||||||
|
if (words.find(i) == words.end() && flag_dummy_page == false)
|
||||||
|
{
|
||||||
|
allWordsReceived = false;
|
||||||
|
std::cerr<< "OsnmaTestVectorsSimulation: error parsing words 1->5. "
|
||||||
|
"Word "<< i << " should be received for each subframe but was not." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(allWordsReceived)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Define the starting position and length of bits to extract for each word
|
||||||
|
std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
|
||||||
|
{1, {6, 120}},
|
||||||
|
{2, {6, 120}},
|
||||||
|
{3, {6, 122}},
|
||||||
|
{4, {6, 120}},
|
||||||
|
{5, {6, 67}},
|
||||||
|
// TODO words 6 and 10 for TimingData
|
||||||
|
};
|
||||||
|
|
||||||
|
// Iterate over the extraction parameters
|
||||||
|
for (const auto& param : extractionParams) {
|
||||||
|
uint8_t wordKey = param.first;
|
||||||
|
uint8_t start = param.second.first;
|
||||||
|
uint8_t length = param.second.second;
|
||||||
|
|
||||||
|
// Extract the required bits
|
||||||
|
std::bitset<128> word = words[wordKey];
|
||||||
|
|
||||||
|
osnmaMsg_sptr->EphemerisClockAndStatusData_2 += words[wordKey].
|
||||||
|
to_string().substr(
|
||||||
|
start, length);
|
||||||
|
|
||||||
|
// std::bitset<8> byte;
|
||||||
|
// int byteIndex = 0;
|
||||||
|
// for (uint8_t i = start; i < start + length; ++i) {
|
||||||
|
// byte[byteIndex] = word[i];
|
||||||
|
// byteIndex++;
|
||||||
|
//
|
||||||
|
// // Once we have collected 8 bits, we can add them as an uint8_t to the vector
|
||||||
|
// if (byteIndex == 8) {
|
||||||
|
// osnmaMsg_sptr->EphemerisClockAndStatusData.push_back(static_cast<uint8_t>(byte.to_ulong()));
|
||||||
|
// byte.reset();
|
||||||
|
// byteIndex = 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Push remaining bits if it didn't reach 8 bits
|
||||||
|
// if (byteIndex > 0) {
|
||||||
|
// osnmaMsg_sptr->EphemerisClockAndStatusData.push_back(static_cast<uint8_t>(byte.to_ulong()));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto temp_obj = pmt::make_any(osnmaMsg_sptr);
|
auto temp_obj = pmt::make_any(osnmaMsg_sptr);
|
||||||
|
|
||||||
osnma->msg_handler_osnma(temp_obj); // osnma entry point
|
osnma->msg_handler_osnma(temp_obj); // osnma entry point
|
||||||
@ -169,9 +263,6 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user