mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-07-06 12:02:55 +00:00
Implement HAS message page decoding
Signed-off-by: Carles Fernandez <carles.fernandez@gmail.com>
This commit is contained in:
parent
c67ac1247f
commit
e262dfc315
@ -24,6 +24,7 @@
|
|||||||
#include "galileo_almanac.h"
|
#include "galileo_almanac.h"
|
||||||
#include "galileo_almanac_helper.h"
|
#include "galileo_almanac_helper.h"
|
||||||
#include "galileo_ephemeris.h"
|
#include "galileo_ephemeris.h"
|
||||||
|
#include "galileo_has_data.h"
|
||||||
#include "galileo_iono.h"
|
#include "galileo_iono.h"
|
||||||
#include "galileo_utc_model.h"
|
#include "galileo_utc_model.h"
|
||||||
#include "geojson_printer.h"
|
#include "geojson_printer.h"
|
||||||
@ -500,6 +501,7 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels,
|
|||||||
d_galileo_utc_model_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Utc_Model>).hash_code();
|
d_galileo_utc_model_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Utc_Model>).hash_code();
|
||||||
d_galileo_almanac_helper_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Almanac_Helper>).hash_code();
|
d_galileo_almanac_helper_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Almanac_Helper>).hash_code();
|
||||||
d_galileo_almanac_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Almanac>).hash_code();
|
d_galileo_almanac_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Almanac>).hash_code();
|
||||||
|
d_galileo_has_message_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_HAS_data>).hash_code();
|
||||||
d_glonass_gnav_ephemeris_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Ephemeris>).hash_code();
|
d_glonass_gnav_ephemeris_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Ephemeris>).hash_code();
|
||||||
d_glonass_gnav_utc_model_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Utc_Model>).hash_code();
|
d_glonass_gnav_utc_model_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Utc_Model>).hash_code();
|
||||||
d_glonass_gnav_almanac_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Almanac>).hash_code();
|
d_glonass_gnav_almanac_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Almanac>).hash_code();
|
||||||
@ -1315,6 +1317,10 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
|
|||||||
d_user_pvt_solver->galileo_almanac_map[galileo_alm->PRN] = *galileo_alm;
|
d_user_pvt_solver->galileo_almanac_map[galileo_alm->PRN] = *galileo_alm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (msg_type_hash_code == d_galileo_has_message_sptr_type_hash_code)
|
||||||
|
{
|
||||||
|
// Store HAS message and print its content
|
||||||
|
}
|
||||||
|
|
||||||
// **************** GLONASS GNAV Telemetry *************************
|
// **************** GLONASS GNAV Telemetry *************************
|
||||||
else if (msg_type_hash_code == d_glonass_gnav_ephemeris_sptr_type_hash_code)
|
else if (msg_type_hash_code == d_glonass_gnav_ephemeris_sptr_type_hash_code)
|
||||||
|
@ -216,6 +216,7 @@ private:
|
|||||||
size_t d_galileo_utc_model_sptr_type_hash_code;
|
size_t d_galileo_utc_model_sptr_type_hash_code;
|
||||||
size_t d_galileo_almanac_helper_sptr_type_hash_code;
|
size_t d_galileo_almanac_helper_sptr_type_hash_code;
|
||||||
size_t d_galileo_almanac_sptr_type_hash_code;
|
size_t d_galileo_almanac_sptr_type_hash_code;
|
||||||
|
size_t d_galileo_has_message_sptr_type_hash_code;
|
||||||
size_t d_glonass_gnav_ephemeris_sptr_type_hash_code;
|
size_t d_glonass_gnav_ephemeris_sptr_type_hash_code;
|
||||||
size_t d_glonass_gnav_utc_model_sptr_type_hash_code;
|
size_t d_glonass_gnav_utc_model_sptr_type_hash_code;
|
||||||
size_t d_glonass_gnav_almanac_sptr_type_hash_code;
|
size_t d_glonass_gnav_almanac_sptr_type_hash_code;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "galileo_almanac_helper.h" // for Galileo_Almanac_Helper
|
#include "galileo_almanac_helper.h" // for Galileo_Almanac_Helper
|
||||||
#include "galileo_ephemeris.h" // for Galileo_Ephemeris
|
#include "galileo_ephemeris.h" // for Galileo_Ephemeris
|
||||||
|
#include "galileo_has_data.h" // For Galileo HAS messages
|
||||||
#include "galileo_iono.h" // for Galileo_Iono
|
#include "galileo_iono.h" // for Galileo_Iono
|
||||||
#include "galileo_utc_model.h" // for Galileo_Utc_Model
|
#include "galileo_utc_model.h" // for Galileo_Utc_Model
|
||||||
#include "gnss_synchro.h"
|
#include "gnss_synchro.h"
|
||||||
@ -512,15 +513,15 @@ void galileo_telemetry_decoder_gs::decode_CNAV_word(float *page_symbols, int32_t
|
|||||||
// 4. If we have a new full message, read it
|
// 4. If we have a new full message, read it
|
||||||
if (d_cnav_nav.have_new_HAS_message() == true)
|
if (d_cnav_nav.have_new_HAS_message() == true)
|
||||||
{
|
{
|
||||||
// TODO: Retrieve data from message and send it somewhere
|
if (d_cnav_nav.is_HAS_message_dummy() == true)
|
||||||
// Galileo_HAS_data has_data = d_cnav_nav.get_HAS_data();
|
|
||||||
if (d_cnav_nav.is_HAS_message_dummy())
|
|
||||||
{
|
{
|
||||||
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
|
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS dummy message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS dummy message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
|
const std::shared_ptr<Galileo_HAS_data> tmp_obj = std::make_shared<Galileo_HAS_data>(d_cnav_nav.get_HAS_data());
|
||||||
|
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
|
||||||
|
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -649,7 +650,7 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
|
|||||||
if (abs(corr_value) >= d_samples_per_preamble)
|
if (abs(corr_value) >= d_samples_per_preamble)
|
||||||
{
|
{
|
||||||
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
||||||
DLOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite;
|
LOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite << " in channel " << this->d_channel;
|
||||||
d_stat = 1; // enter into frame pre-detection status
|
d_stat = 1; // enter into frame pre-detection status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,14 +68,16 @@ constexpr int32_t GALILEO_CNAV_CRC_LENGTH = 24;
|
|||||||
constexpr int32_t GALILEO_CNAV_MESSAGE_BITS_PER_PAGE = 424;
|
constexpr int32_t GALILEO_CNAV_MESSAGE_BITS_PER_PAGE = 424;
|
||||||
constexpr int32_t GALILEO_CNAV_PAGE_HEADER_BITS = 24;
|
constexpr int32_t GALILEO_CNAV_PAGE_HEADER_BITS = 24;
|
||||||
constexpr int32_t GALILEO_CNAV_PREAMBLE_LENGTH_BITS = 16;
|
constexpr int32_t GALILEO_CNAV_PREAMBLE_LENGTH_BITS = 16;
|
||||||
constexpr int32_t GALILEO_CNAV_MAX_NUMBER_ENCODED_BLOCKS = 255;
|
constexpr int32_t GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK = 255;
|
||||||
constexpr int32_t GALILEO_CNAV_MT1_HEADER_BITS = 32;
|
constexpr int32_t GALILEO_CNAV_MT1_HEADER_BITS = 32;
|
||||||
|
constexpr int32_t GALILEO_CNAV_OCTETS_IN_SUBPAGE = 53;
|
||||||
|
constexpr int32_t GALILEO_CNAV_INFORMATION_VECTOR_LENGTH = 32;
|
||||||
|
|
||||||
constexpr int32_t HAS_MSG_MAX_SATS = 40;
|
constexpr int32_t HAS_MSG_MAX_SATS = 40;
|
||||||
constexpr int32_t HAS_MSG_MAX_SIGNALS = 16;
|
constexpr int32_t HAS_MSG_MAX_SIGNALS = 16;
|
||||||
|
|
||||||
constexpr uint8_t HAS_MSG_GPS_SYSTEM = 0; // Table 8 ICD
|
constexpr uint8_t HAS_MSG_GPS_SYSTEM = 0; // Table 8 ICD v1.2
|
||||||
constexpr uint8_t HAS_MSG_GALILEO_SYSTEM = 2; // Table 8 ICD
|
constexpr uint8_t HAS_MSG_GALILEO_SYSTEM = 2; // Table 8 ICD v1.2
|
||||||
|
|
||||||
constexpr char GALILEO_CNAV_PREAMBLE[17] = "1011011101110000";
|
constexpr char GALILEO_CNAV_PREAMBLE[17] = "1011011101110000";
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
* \brief Implementation of a Galileo CNAV Data message as described in
|
* \brief Implementation of a Galileo CNAV Data message as described in
|
||||||
* Galileo High Accuracy Service E6-B Signal-In-Space Message Specification v1.2
|
* Galileo High Accuracy Service E6-B Signal-In-Space Message Specification v1.2
|
||||||
* (April 2020)
|
* (April 2020)
|
||||||
* \author Carles Fernandez-Prades, 2020 cfernandez(at)cttc.es
|
* \author Carles Fernandez-Prades, 2020-2021 cfernandez(at)cttc.es
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -60,10 +60,11 @@ void Galileo_Cnav_Message::read_HAS_page(const std::string& page_string)
|
|||||||
if (CRC_test(Word_for_CRC_bits, checksum.to_ulong()) == true)
|
if (CRC_test(Word_for_CRC_bits, checksum.to_ulong()) == true)
|
||||||
{
|
{
|
||||||
d_flag_CRC_test = true;
|
d_flag_CRC_test = true;
|
||||||
// CRC correct: Read HAS page header
|
// CRC correct: Read 24 bits of HAS page header
|
||||||
read_HAS_page_header(page_string.substr(GALILEO_CNAV_PAGE_RESERVED_BITS, GALILEO_CNAV_PAGE_HEADER_BITS));
|
read_HAS_page_header(page_string.substr(GALILEO_CNAV_PAGE_RESERVED_BITS, GALILEO_CNAV_PAGE_HEADER_BITS));
|
||||||
bool use_has = false;
|
bool use_has = false;
|
||||||
d_test_mode = false;
|
d_test_mode = false;
|
||||||
|
// HAS status as defined in ICD v1.2 Table 5 HAS Page Header
|
||||||
switch (d_has_page_status)
|
switch (d_has_page_status)
|
||||||
{
|
{
|
||||||
case 0: // HAS is in Test Mode
|
case 0: // HAS is in Test Mode
|
||||||
@ -73,11 +74,14 @@ void Galileo_Cnav_Message::read_HAS_page(const std::string& page_string)
|
|||||||
case 1: // HAS is in Operational Mode
|
case 1: // HAS is in Operational Mode
|
||||||
use_has = true;
|
use_has = true;
|
||||||
break;
|
break;
|
||||||
|
case 2: // HAS is in "reserved" status
|
||||||
|
case 3: // Do not use HAS
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (use_has)
|
if (use_has)
|
||||||
{
|
{
|
||||||
|
// Process the 424 bits of encoded data
|
||||||
process_HAS_page(page_string.substr(GALILEO_CNAV_PAGE_RESERVED_BITS + GALILEO_CNAV_PAGE_HEADER_BITS, GALILEO_CNAV_MESSAGE_BITS_PER_PAGE));
|
process_HAS_page(page_string.substr(GALILEO_CNAV_PAGE_RESERVED_BITS + GALILEO_CNAV_PAGE_HEADER_BITS, GALILEO_CNAV_MESSAGE_BITS_PER_PAGE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,11 +105,12 @@ void Galileo_Cnav_Message::read_HAS_page_header(const std::string& page_string)
|
|||||||
}
|
}
|
||||||
if (!d_page_dummy)
|
if (!d_page_dummy)
|
||||||
{
|
{
|
||||||
|
// ICD v1.2 Table 5: HAS page header
|
||||||
const std::bitset<GALILEO_CNAV_PAGE_HEADER_BITS> has_page_header(page_string);
|
const std::bitset<GALILEO_CNAV_PAGE_HEADER_BITS> has_page_header(page_string);
|
||||||
d_has_page_status = read_has_page_header_parameter(has_page_header, GALILEO_HAS_STATUS);
|
d_has_page_status = read_has_page_header_parameter(has_page_header, GALILEO_HAS_STATUS);
|
||||||
d_received_message_type = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_TYPE);
|
d_received_message_type = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_TYPE);
|
||||||
d_received_message_id = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_ID);
|
d_received_message_id = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_ID);
|
||||||
d_received_message_size = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_SIZE);
|
d_received_message_size = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_SIZE) + 1; // "0" means 1
|
||||||
d_received_message_page_id = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_PAGE_ID);
|
d_received_message_page_id = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_PAGE_ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,14 +121,27 @@ void Galileo_Cnav_Message::process_HAS_page(const std::string& page_string)
|
|||||||
if (d_current_message_id == d_received_message_id)
|
if (d_current_message_id == d_received_message_id)
|
||||||
{
|
{
|
||||||
// if receiver pid was not there, store it.
|
// if receiver pid was not there, store it.
|
||||||
if (std::find(d_list_pid.begin(), d_list_pid.end(), d_received_message_page_id) == d_list_pid.end())
|
if (d_received_message_page_id == 0)
|
||||||
{
|
{
|
||||||
if (d_received_message_type == 1) // contains satellite corrections
|
// reserved, ignore it
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (std::find(d_list_pid.begin(), d_list_pid.end(), d_received_message_page_id) == d_list_pid.end())
|
||||||
{
|
{
|
||||||
d_received_encoded_messages++;
|
if (d_received_message_type == 1) // contains satellite corrections
|
||||||
d_list_pid.push_back(d_received_message_page_id);
|
{
|
||||||
// Store encoded page
|
d_received_encoded_messages++;
|
||||||
d_encoded_message_type_1 += std::string(page_string);
|
d_list_pid.push_back(d_received_message_page_id);
|
||||||
|
// Pack encoded string into 53 octets and put it in
|
||||||
|
// the corresponding row of d_C_matrix.
|
||||||
|
for (int k = 0; k < GALILEO_CNAV_OCTETS_IN_SUBPAGE; k++)
|
||||||
|
{
|
||||||
|
std::string bits8 = page_string.substr(k * 8, 8);
|
||||||
|
std::bitset<8> bs(bits8);
|
||||||
|
d_C_matrix[d_received_message_page_id - 1][k] = static_cast<uint8_t>(bs.to_ulong());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,48 +152,112 @@ void Galileo_Cnav_Message::process_HAS_page(const std::string& page_string)
|
|||||||
d_received_encoded_messages = 0;
|
d_received_encoded_messages = 0;
|
||||||
d_new_message = false;
|
d_new_message = false;
|
||||||
d_current_message_size = d_received_message_size;
|
d_current_message_size = d_received_message_size;
|
||||||
// erase stored pages and start storing again
|
// erase stored pages and data, and start storing again
|
||||||
d_encoded_message_type_1.clear();
|
|
||||||
d_list_pid.clear();
|
d_list_pid.clear();
|
||||||
|
d_HAS_data = Galileo_HAS_data();
|
||||||
if (d_received_message_type == 1)
|
if (d_received_message_type == 1)
|
||||||
{
|
{
|
||||||
d_encoded_message_type_1.reserve(GALILEO_CNAV_MAX_NUMBER_ENCODED_BLOCKS * GALILEO_CNAV_MESSAGE_BITS_PER_PAGE);
|
|
||||||
d_received_encoded_messages++;
|
d_received_encoded_messages++;
|
||||||
d_list_pid.push_back(d_received_message_page_id);
|
d_list_pid.push_back(d_received_message_page_id);
|
||||||
d_encoded_message_type_1 += std::string(page_string);
|
// Pack encoded string into 53 octets and put it in
|
||||||
|
// the corresponding row of d_C_matrix.
|
||||||
|
for (int k = 0; k < GALILEO_CNAV_OCTETS_IN_SUBPAGE; k++)
|
||||||
|
{
|
||||||
|
std::string bits8 = page_string.substr(k * 8, 8);
|
||||||
|
std::bitset<8> bs(bits8);
|
||||||
|
d_C_matrix[d_received_message_page_id - 1][k] = static_cast<uint8_t>(bs.to_ulong());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d_received_encoded_messages == d_current_message_size)
|
if (d_received_encoded_messages == d_current_message_size)
|
||||||
{
|
{
|
||||||
// we have a full encoded message stored in d_encoded_message_type_1
|
// we have a full encoded message stored in d_C_matrix
|
||||||
d_received_encoded_messages = 0;
|
d_received_encoded_messages = 0;
|
||||||
d_current_message_id = 0;
|
d_current_message_id = 0;
|
||||||
d_new_message = true;
|
|
||||||
decode_message_type1();
|
int res = decode_message_type1();
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
d_new_message = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_new_message = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Galileo_Cnav_Message::decode_message_type1()
|
int Galileo_Cnav_Message::decode_message_type1()
|
||||||
{
|
{
|
||||||
// TODO: Reed-Solomon decoding of d_encoded_message_type_1
|
// All rows in d_C_matrix with no data are erasure positions
|
||||||
// TODO: reordering
|
std::vector<int> erasure_positions;
|
||||||
// decoded_message_type1 = ...
|
erasure_positions.reserve(GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK - d_list_pid.size());
|
||||||
// read_HAS_message_type1(decoded_message_type1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (uint8_t mpid = 1; mpid <= GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK; mpid++)
|
||||||
|
{
|
||||||
|
if (std::find(d_list_pid.begin(), d_list_pid.end(), mpid) == d_list_pid.end())
|
||||||
|
{
|
||||||
|
erasure_positions.push_back(mpid - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_list_pid.remove(mpid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Galileo_Cnav_Message::read_HAS_message_type1(const std::string& message_string)
|
// Vertical decoding of d_C_matrix
|
||||||
{
|
for (int col = 0; col < GALILEO_CNAV_OCTETS_IN_SUBPAGE; col++)
|
||||||
d_HAS_data = Galileo_HAS_data();
|
{
|
||||||
read_MT1_header(message_string);
|
std::vector<uint8_t> C_column(GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, 0);
|
||||||
read_MT1_body(message_string);
|
for (int row = 0; row < GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK; row++)
|
||||||
|
{
|
||||||
|
C_column[row] = d_C_matrix[row][col];
|
||||||
|
}
|
||||||
|
int result = rs.decode(C_column, erasure_positions);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
// Decoding failed
|
||||||
|
d_C_matrix = {GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)};
|
||||||
|
d_M_matrix = {GALILEO_CNAV_INFORMATION_VECTOR_LENGTH, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE)};
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> M_column(C_column.begin(), C_column.begin() + GALILEO_CNAV_INFORMATION_VECTOR_LENGTH);
|
||||||
|
for (int i = 0; i < GALILEO_CNAV_INFORMATION_VECTOR_LENGTH; i++)
|
||||||
|
{
|
||||||
|
d_M_matrix[i][col] = M_column[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form the decoded HAS message by reading rows of d_M_matrix
|
||||||
|
std::string decoded_message_type_1;
|
||||||
|
decoded_message_type_1.reserve(d_current_message_size * GALILEO_CNAV_OCTETS_IN_SUBPAGE * 8);
|
||||||
|
for (uint8_t row = 0; row < d_current_message_size; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < GALILEO_CNAV_OCTETS_IN_SUBPAGE; col++)
|
||||||
|
{
|
||||||
|
std::bitset<8> bs(d_M_matrix[row][col]);
|
||||||
|
decoded_message_type_1 += bs.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset d_C_matrix and d_M_matrix for next decoding
|
||||||
|
d_C_matrix = {GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)};
|
||||||
|
d_M_matrix = {GALILEO_CNAV_INFORMATION_VECTOR_LENGTH, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)};
|
||||||
|
|
||||||
|
// Trigger HAS message content reading
|
||||||
|
read_MT1_header(decoded_message_type_1);
|
||||||
|
read_MT1_body(decoded_message_type_1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Galileo_Cnav_Message::read_MT1_header(const std::string& message_string)
|
void Galileo_Cnav_Message::read_MT1_header(const std::string& message_string)
|
||||||
{
|
{
|
||||||
|
// ICD v1.2 Table 6: MT1 Message Header.
|
||||||
const std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> has_mt1_header(message_string);
|
const std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> has_mt1_header(message_string);
|
||||||
d_HAS_data.header.toh = read_has_message_header_parameter_uint16(has_mt1_header, GALILEO_MT1_HEADER_TOH);
|
d_HAS_data.header.toh = read_has_message_header_parameter_uint16(has_mt1_header, GALILEO_MT1_HEADER_TOH);
|
||||||
d_HAS_data.header.mask_id = read_has_message_header_parameter_uint8(has_mt1_header, GALILEO_MT1_HEADER_MASK_ID);
|
d_HAS_data.header.mask_id = read_has_message_header_parameter_uint8(has_mt1_header, GALILEO_MT1_HEADER_MASK_ID);
|
||||||
@ -192,6 +274,7 @@ void Galileo_Cnav_Message::read_MT1_header(const std::string& message_string)
|
|||||||
|
|
||||||
void Galileo_Cnav_Message::read_MT1_body(const std::string& message_string)
|
void Galileo_Cnav_Message::read_MT1_body(const std::string& message_string)
|
||||||
{
|
{
|
||||||
|
// ICD v1.2 Table 7: MT1 Message Body.
|
||||||
auto message = std::string(message_string.begin() + GALILEO_CNAV_MT1_HEADER_BITS, message_string.end()); // Remove header
|
auto message = std::string(message_string.begin() + GALILEO_CNAV_MT1_HEADER_BITS, message_string.end()); // Remove header
|
||||||
int Nsat = 0;
|
int Nsat = 0;
|
||||||
if (d_HAS_data.header.mask_flag)
|
if (d_HAS_data.header.mask_flag)
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
* \brief Implementation of a Galileo CNAV Data message as described in
|
* \brief Implementation of a Galileo CNAV Data message as described in
|
||||||
* Galileo High Accuracy Service E6-B Signal-In-Space Message Specification v1.2
|
* Galileo High Accuracy Service E6-B Signal-In-Space Message Specification v1.2
|
||||||
* (April 2020)
|
* (April 2020)
|
||||||
* \author Carles Fernandez-Prades, 2020 cfernandez(at)cttc.es
|
* \author Carles Fernandez-Prades, 2020-2021 cfernandez(at)cttc.es
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -21,10 +21,12 @@
|
|||||||
|
|
||||||
#include "Galileo_CNAV.h"
|
#include "Galileo_CNAV.h"
|
||||||
#include "galileo_has_data.h"
|
#include "galileo_has_data.h"
|
||||||
|
#include "reed_solomon.h"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/** \addtogroup Core
|
/** \addtogroup Core
|
||||||
* \{ */
|
* \{ */
|
||||||
@ -68,23 +70,24 @@ private:
|
|||||||
bool CRC_test(std::bitset<GALILEO_CNAV_BITS_FOR_CRC> bits, uint32_t checksum) const;
|
bool CRC_test(std::bitset<GALILEO_CNAV_BITS_FOR_CRC> bits, uint32_t checksum) const;
|
||||||
void read_HAS_page_header(const std::string& page_string);
|
void read_HAS_page_header(const std::string& page_string);
|
||||||
void process_HAS_page(const std::string& page_string);
|
void process_HAS_page(const std::string& page_string);
|
||||||
void decode_message_type1();
|
|
||||||
void read_HAS_message_type1(const std::string& message_string);
|
|
||||||
void read_MT1_header(const std::string& message_string);
|
void read_MT1_header(const std::string& message_string);
|
||||||
void read_MT1_body(const std::string& message_string);
|
void read_MT1_body(const std::string& message_string);
|
||||||
|
int decode_message_type1();
|
||||||
|
|
||||||
uint8_t read_has_page_header_parameter(std::bitset<GALILEO_CNAV_PAGE_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
uint8_t read_has_page_header_parameter(std::bitset<GALILEO_CNAV_PAGE_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
||||||
uint8_t read_has_message_header_parameter_uint8(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
uint8_t read_has_message_header_parameter_uint8(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
||||||
uint16_t read_has_message_header_parameter_uint16(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
uint16_t read_has_message_header_parameter_uint16(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
||||||
bool read_has_message_header_parameter_bool(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
bool read_has_message_header_parameter_bool(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
|
||||||
|
|
||||||
uint8_t read_has_message_body_uint8(const std::string& bits) const;
|
uint8_t read_has_message_body_uint8(const std::string& bits) const;
|
||||||
uint16_t read_has_message_body_uint16(const std::string& bits) const;
|
uint16_t read_has_message_body_uint16(const std::string& bits) const;
|
||||||
uint64_t read_has_message_body_uint64(const std::string& bits) const;
|
uint64_t read_has_message_body_uint64(const std::string& bits) const;
|
||||||
int16_t read_has_message_body_int16(const std::string& bits) const;
|
int16_t read_has_message_body_int16(const std::string& bits) const;
|
||||||
|
|
||||||
Galileo_HAS_data d_HAS_data{};
|
Galileo_HAS_data d_HAS_data{};
|
||||||
|
ReedSolomon rs = ReedSolomon();
|
||||||
std::string d_encoded_message_type_1;
|
std::vector<std::vector<uint8_t>> d_C_matrix{GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)}; // 255 x 53
|
||||||
|
std::vector<std::vector<uint8_t>> d_M_matrix{GALILEO_CNAV_INFORMATION_VECTOR_LENGTH, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)}; // 32 x 53
|
||||||
std::list<uint8_t> d_list_pid;
|
std::list<uint8_t> d_list_pid;
|
||||||
|
|
||||||
uint8_t d_has_page_status{};
|
uint8_t d_has_page_status{};
|
||||||
|
@ -409,21 +409,21 @@ uint8_t ReedSolomon::galois_mul_table(uint8_t a, uint8_t b) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t x = log_table[a];
|
uint8_t x = d_log_table[a];
|
||||||
uint8_t y = log_table[b];
|
uint8_t y = d_log_table[b];
|
||||||
uint8_t log_mult = (x + y) % d_symbols_per_block;
|
uint8_t log_mult = (x + y) % d_symbols_per_block;
|
||||||
|
|
||||||
return antilog[log_mult];
|
return d_antilog[log_mult];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ReedSolomon::init_log_tables()
|
void ReedSolomon::init_log_tables()
|
||||||
{
|
{
|
||||||
log_table[0] = 0; // dummy value
|
d_log_table[0] = 0; // dummy value
|
||||||
for (int i = 0, x = 1; i < d_symbols_per_block; x = galois_mul(x, d_min_poly), i++)
|
for (int i = 0, x = 1; i < d_symbols_per_block; x = galois_mul(x, d_min_poly), i++)
|
||||||
{
|
{
|
||||||
log_table[x] = i;
|
d_log_table[x] = i;
|
||||||
antilog[i] = x;
|
d_antilog[i] = x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ public:
|
|||||||
* of the input vector.
|
* of the input vector.
|
||||||
*
|
*
|
||||||
* The second parameter is optional, and contains a vector of erasure
|
* The second parameter is optional, and contains a vector of erasure
|
||||||
* positions to be passed to the decoding algorithm.
|
* positions to be passed to the decoding algorithm. Defaults to empty.
|
||||||
*
|
*
|
||||||
* Returns the number of corrected errors or -1 if decoding failed.
|
* Returns the number of corrected errors or -1 if decoding failed.
|
||||||
*/
|
*/
|
||||||
@ -105,36 +105,37 @@ public:
|
|||||||
private:
|
private:
|
||||||
static const int d_symbols_per_block = 255; // the total number of symbols in a RS block.
|
static const int d_symbols_per_block = 255; // the total number of symbols in a RS block.
|
||||||
|
|
||||||
int decode_rs_8(uint8_t* data, const int* eras_pos, int no_eras, int pad) const;
|
|
||||||
int mod255(int x) const;
|
int mod255(int x) const;
|
||||||
int rs_min(int a, int b) const;
|
int rs_min(int a, int b) const;
|
||||||
|
int decode_rs_8(uint8_t* data, const int* eras_pos, int no_eras, int pad) const;
|
||||||
|
|
||||||
uint8_t galois_mul(uint8_t a, uint8_t b) const;
|
uint8_t galois_mul(uint8_t a, uint8_t b) const;
|
||||||
uint8_t galois_add(uint8_t a, uint8_t b) const;
|
uint8_t galois_add(uint8_t a, uint8_t b) const;
|
||||||
uint8_t galois_mul_table(uint8_t a, uint8_t b) const;
|
uint8_t galois_mul_table(uint8_t a, uint8_t b) const;
|
||||||
|
|
||||||
void encode_rs_8(const uint8_t* data, uint8_t* parity) const;
|
void encode_rs_8(const uint8_t* data, uint8_t* parity) const;
|
||||||
void init_log_tables();
|
void init_log_tables(); // initialize d_log_table and d_antilog
|
||||||
void init_alpha_tables();
|
void init_alpha_tables(); // initialize d_alpha_to, d_index_of
|
||||||
|
|
||||||
std::array<uint8_t, 256> log_table{};
|
std::array<uint8_t, 256> d_alpha_to{}; // used for decoding
|
||||||
std::array<uint8_t, 255> antilog{};
|
std::array<uint8_t, 256> d_index_of{}; // used for decoding
|
||||||
std::array<uint8_t, 256> d_alpha_to{};
|
std::array<uint8_t, 256> d_log_table{}; // used for encoding
|
||||||
std::array<uint8_t, 256> d_index_of{};
|
std::array<uint8_t, 255> d_antilog{}; // used for encoding
|
||||||
std::vector<std::vector<uint8_t>> d_genmatrix;
|
|
||||||
std::vector<uint8_t> d_genpoly_coeff;
|
|
||||||
std::vector<uint8_t> d_genpoly_index;
|
|
||||||
|
|
||||||
size_t d_data_in_block;
|
std::vector<std::vector<uint8_t>> d_genmatrix; // used for encoding
|
||||||
|
std::vector<uint8_t> d_genpoly_coeff; // used for encoding
|
||||||
|
std::vector<uint8_t> d_genpoly_index; // used for encoding
|
||||||
|
|
||||||
|
size_t d_data_in_block; // number of information symbols in a block
|
||||||
|
|
||||||
int d_nroots; // number of parity symbols in a block
|
int d_nroots; // number of parity symbols in a block
|
||||||
int d_prim; // The primitive root of the generator poly.
|
int d_prim; // The primitive root of the generator poly
|
||||||
int d_pad; // the number of pad symbols in a block.
|
int d_pad; // the number of pad symbols in a block
|
||||||
int d_iprim; // prim-th root of 1, index form
|
int d_iprim; // prim-th root of 1, index form
|
||||||
int d_fcr; // first consecutive root
|
int d_fcr; // first consecutive root
|
||||||
|
|
||||||
uint8_t d_min_poly;
|
uint8_t d_min_poly; // primitive polynomial
|
||||||
uint8_t d_a0;
|
uint8_t d_a0; // auxiliar variable
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user