1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-04 23:40:04 +00:00

Merge branch 'ism' into next

This commit is contained in:
Carles Fernandez 2024-09-26 07:12:35 +02:00
commit c45909f091
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
11 changed files with 603 additions and 5 deletions

View File

@ -47,6 +47,9 @@ All notable changes to GNSS-SDR will be documented in this file.
It requires the `-DENABLE_ION=ON` building configuration option.
- The `Monitor` and `PVT` blocks are now able to send data to multiple UDP
ports.
- Add experimental decoding of Galileo's I/NAV ARAIM Integrity Support Message
(ISM) as defined in the OS SIS ICD v2.1. Values, if received, are only logged
but not used.
### Improvements in Portability:

View File

@ -202,7 +202,7 @@ bool sbas_l1_telemetry_decoder_gs::Symbol_Aligner_And_Decoder::get_bits(const st
const int32_t nbits_requested = symbols.size() / D_SYMBOLS_PER_BIT;
int32_t nbits_decoded;
// fill two vectors with the two possible symbol alignments
const std::vector<double> symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector
const std::vector<double> &symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector
std::vector<double> symbols_vd2; // shifted symbol vector -> add past sample in front of input vector
symbols_vd2.push_back(d_past_symbol);
for (auto symbol_it = symbols.cbegin(); symbol_it != symbols.cend() - 1; ++symbol_it)

View File

@ -19,6 +19,7 @@ set(SYSTEM_PARAMETERS_SOURCES
galileo_fnav_message.cc
galileo_has_data.cc
galileo_inav_message.cc
galileo_ism.cc
galileo_reduced_ced.cc
beidou_dnav_navigation_message.cc
beidou_dnav_ephemeris.cc
@ -57,6 +58,7 @@ set(SYSTEM_PARAMETERS_HEADERS
galileo_fnav_message.h
galileo_has_data.h
galileo_inav_message.h
galileo_ism.h
galileo_reduced_ced.h
sbas_ephemeris.h
gps_cnav_ephemeris.h
@ -119,6 +121,7 @@ target_link_libraries(core_system_parameters
PUBLIC
Boost::date_time
Boost::serialization
Boost::headers
PRIVATE
Pugixml::pugixml
)

View File

@ -274,6 +274,23 @@ constexpr int32_t BITS_IN_OCTET = 8;
constexpr int32_t FIRST_RS_BIT = 7;
constexpr int32_t FIRST_RS_BIT_AFTER_IODNAV = 17;
/* Page 22 */
const std::vector<std::pair<int32_t, int32_t>> ISM_CONSTELLATION_ID_BIT({{7, 3}});
const std::vector<std::pair<int32_t, int32_t>> ISM_SERVICE_LEVEL_ID_BIT({{10, 3}});
const std::vector<std::pair<int32_t, int32_t>> ISM_WN_BIT({{13, 12}});
const std::vector<std::pair<int32_t, int32_t>> ISM_T0_BIT({{25, 9}});
const std::vector<std::pair<int32_t, int32_t>> ISM_MASK_MSB_BIT({{34, 1}});
const std::vector<std::pair<int32_t, int32_t>> ISM_MASK_BIT({{35, 32}});
const std::vector<std::pair<int32_t, int32_t>> ISM_PCONST_BIT({{67, 4}});
const std::vector<std::pair<int32_t, int32_t>> ISM_PSAT_BIT({{71, 4}});
const std::vector<std::pair<int32_t, int32_t>> ISM_URA_BIT({{75, 4}});
const std::vector<std::pair<int32_t, int32_t>> ISM_URE_BIT({{79, 4}});
const std::vector<std::pair<int32_t, int32_t>> ISM_BNOM_BIT({{83, 4}});
const std::vector<std::pair<int32_t, int32_t>> ISM_TVALIDITY_BIT({{87, 4}});
const std::vector<std::pair<int32_t, int32_t>> ISM_CRC_BIT({{97, 32}});
constexpr int32_t GALILEO_ISM_CRC_DATA_BITS = 96;
constexpr int32_t GALILEO_ISM_CRC_DATA_BYTES = 12;
/* Page 0 */
const std::vector<std::pair<int32_t, int32_t>> TIME_0_BIT({{7, 2}});
const std::vector<std::pair<int32_t, int32_t>> WN_0_BIT({{97, 12}});

View File

@ -392,7 +392,7 @@ std::vector<float> Galileo_HAS_data::get_delta_clock_subset_correction_m(uint8_t
}
auto subset_corr_matrix = this->get_delta_clock_subset_correction_m();
const std::vector<float> delta_clock_subset_correction_m_v = subset_corr_matrix[nsys_sub_index];
const std::vector<float>& delta_clock_subset_correction_m_v = subset_corr_matrix[nsys_sub_index];
std::vector<float> delta_clock_subset_correction_m_aux;
std::vector<uint8_t> num_satellites_subset = this->get_num_subset_satellites();
uint8_t num_sats_in_this_system_subset = num_satellites_subset[nsys_sub_index];

View File

@ -44,7 +44,7 @@ Galileo_Inav_Message::Galileo_Inav_Message()
}
// here the compiler knows how to destrcut rs
// here the compiler knows how to destroy rs
Galileo_Inav_Message::~Galileo_Inav_Message() = default;
@ -407,6 +407,17 @@ bool Galileo_Inav_Message::have_new_reduced_ced()
}
bool Galileo_Inav_Message::have_new_ism()
{
if (have_ISM)
{
have_ISM = false;
return true;
}
return false;
}
Galileo_Ephemeris Galileo_Inav_Message::get_ephemeris() const
{
Galileo_Ephemeris ephemeris;
@ -1367,6 +1378,50 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
break;
}
case 22: // Word Type 22: ARAIM Integrity Support Message (ISM)
DLOG(INFO) << "Word type 22 arrived";
ism_constellation_id = read_octet_unsigned(data_jk_bits, ISM_CONSTELLATION_ID_BIT);
ism_service_level_id = read_octet_unsigned(data_jk_bits, ISM_SERVICE_LEVEL_ID_BIT);
if (gal_ism.check_ism_crc(data_jk_bits))
{
DLOG(INFO) << "I/NAV ARAIM Integrity Support Message CRC OK";
gal_ism.set_ism_constellation_id(ism_constellation_id);
gal_ism.set_ism_service_level_id(ism_service_level_id);
if (ism_constellation_id == 0)
{
LOG(INFO) << "I/NAV ARAIM Integrity Support Message in Test";
}
if (ism_constellation_id == 1)
{
if (ism_service_level_id == 2)
{
gal_ism.set_ism_wn(static_cast<uint16_t>(read_navigation_unsigned(data_jk_bits, ISM_WN_BIT)));
gal_ism.set_ism_t0(static_cast<uint16_t>(read_navigation_unsigned(data_jk_bits, ISM_T0_BIT)));
gal_ism.set_ism_mask_msb(read_navigation_bool(data_jk_bits, ISM_MASK_MSB_BIT));
gal_ism.set_ism_mask(static_cast<uint32_t>(read_navigation_unsigned(data_jk_bits, ISM_MASK_BIT)));
gal_ism.set_ism_pconst(read_octet_unsigned(data_jk_bits, ISM_PCONST_BIT));
gal_ism.set_ism_psat(read_octet_unsigned(data_jk_bits, ISM_PSAT_BIT));
gal_ism.set_ism_ura(read_octet_unsigned(data_jk_bits, ISM_URA_BIT));
gal_ism.set_ism_ure(read_octet_unsigned(data_jk_bits, ISM_URE_BIT));
gal_ism.set_ism_bnom(read_octet_unsigned(data_jk_bits, ISM_BNOM_BIT));
gal_ism.set_ism_Tvalidity(read_octet_unsigned(data_jk_bits, ISM_TVALIDITY_BIT));
LOG(INFO) << "I/NAV ARAIM Integrity Support Message: "
<< "WN_ISM=" << static_cast<uint32_t>(gal_ism.get_WN_ISM()) << ", "
<< "t0_ISM=" << static_cast<uint32_t>(gal_ism.get_t0_ISM()) << ", "
<< "Mask_MSB_ISM=" << static_cast<uint32_t>(gal_ism.get_ism_mask_msb()) << ", "
<< "Mask_ISM=" << gal_ism.get_mask_ISM() << ", "
<< "Pconst=" << gal_ism.get_pconst_value() << ", "
<< "Psat=" << gal_ism.get_psat_value() << ", "
<< "URA=" << gal_ism.get_ura_m() << " [m], "
<< "URE=" << gal_ism.get_ure_m() << " [m], "
<< "Bnom=" << gal_ism.get_bnom_m() << " [m], "
<< "Tvalidity=" << static_cast<uint32_t>(gal_ism.get_Tvalidity_hours()) << " [h]";
}
}
have_ISM = true;
}
break;
case 0: // Word type 0: I/NAV Spare Word
Time_0 = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, TIME_0_BIT));
DLOG(INFO) << "Time_0= " << Time_0;
@ -1403,6 +1458,12 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
}
Galileo_ISM Galileo_Inav_Message::get_galileo_ism() const
{
return gal_ism;
}
/**
* @brief Get data relevant for Galileo OSNMA
*

View File

@ -23,6 +23,7 @@
#include "galileo_almanac_helper.h"
#include "galileo_ephemeris.h"
#include "galileo_iono.h"
#include "galileo_ism.h"
#include "galileo_utc_model.h"
#include "gnss_sdr_make_unique.h" // for std::unique_ptr in C++11
#include <array>
@ -95,6 +96,11 @@ public:
*/
bool have_new_reduced_ced();
/*
* \brief Returns true if new ISM data have arrived. The flag is set to false when the function is executed
*/
bool have_new_ism();
/*
* \brief Returns true if new NMA data have arrived. The flag is set to false when the function is executed
*/
@ -125,6 +131,11 @@ public:
*/
Galileo_Ephemeris get_reduced_ced() const;
/*
* \brief Returns a Galileo_ISMs object filled with the latest ISM data received
*/
Galileo_ISM get_galileo_ism() const;
/*
* \brief Returns an OSNMA_msg object filled with the latest NMA message received. Resets msg buffer.
*/
@ -277,6 +288,7 @@ private:
std::bitset<GALILEO_DATA_JK_BITS> regenerate_page_3(const std::vector<uint8_t>& decoded) const;
std::bitset<GALILEO_DATA_JK_BITS> regenerate_page_4(const std::vector<uint8_t>& decoded) const;
Galileo_ISM gal_ism{};
std::string page_Even{};
std::vector<uint8_t> rs_buffer; // Reed-Solomon buffer
@ -456,6 +468,9 @@ private:
uint8_t IODnav_LSB19{};
uint8_t IODnav_LSB20{};
uint8_t ism_constellation_id{};
uint8_t ism_service_level_id{};
bool flag_CRC_test{};
bool flag_all_ephemeris{}; // Flag indicating that all words containing ephemeris have been received
bool flag_ephemeris_1{}; // Flag indicating that ephemeris 1/4 (word 1) have been received
@ -483,6 +498,7 @@ private:
bool flag_CED{};
bool enable_rs{};
bool have_ISM{};
};

View File

@ -0,0 +1,253 @@
/*!
* \file galileo_ism.cc
* \brief Interface of a Galileo Integrity Support Message
* \author Carles Fernandez, 2024. cfernandez(at)cttc.cat
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "galileo_ism.h"
#include <algorithm>
void Galileo_ISM::set_ism_constellation_id(uint8_t const_id)
{
this->d_ism_constellation_id = const_id;
}
void Galileo_ISM::set_ism_service_level_id(uint8_t sl_id)
{
this->d_ism_service_level_id = sl_id;
}
void Galileo_ISM::set_ism_wn(uint16_t wn_ism)
{
this->d_ism_wn = wn_ism;
}
void Galileo_ISM::set_ism_t0(uint16_t t0)
{
this->d_ism_t0 = t0;
}
void Galileo_ISM::set_ism_mask_msb(bool mask_msb)
{
this->d_ism_mask_msb = mask_msb;
}
void Galileo_ISM::set_ism_mask(uint32_t mask)
{
this->d_ism_mask = mask;
}
void Galileo_ISM::set_ism_pconst(uint8_t pconst)
{
this->d_ism_pconst = pconst;
}
void Galileo_ISM::set_ism_psat(uint8_t psat)
{
this->d_ism_psat = psat;
}
void Galileo_ISM::set_ism_ura(uint8_t ura)
{
this->d_ism_ura = ura;
}
void Galileo_ISM::set_ism_ure(uint8_t ure)
{
this->d_ism_ure = ure;
}
void Galileo_ISM::set_ism_bnom(uint8_t bnom)
{
this->d_ism_bnom = bnom;
}
void Galileo_ISM::set_ism_Tvalidity(uint8_t tvalidity)
{
this->d_ism_Tvalidity = tvalidity;
}
uint16_t Galileo_ISM::get_WN_ISM() const
{
return this->d_ism_wn;
}
uint16_t Galileo_ISM::get_t0_ISM() const
{
return (this->d_ism_t0 * 1800);
}
double Galileo_ISM::get_pconst_value() const
{
auto it = d_ISM_PCONST_MAP.find(this->d_ism_pconst);
if (it == d_ISM_PCONST_MAP.end())
{
return 0.0;
}
return it->second;
}
double Galileo_ISM::get_psat_value() const
{
auto it = d_ISM_PSAT_MAP.find(this->d_ism_psat);
if (it == d_ISM_PSAT_MAP.end())
{
return 0.0;
}
return it->second;
}
bool Galileo_ISM::get_ism_mask_msb() const
{
return d_ism_mask_msb;
}
float Galileo_ISM::get_ura_m() const
{
auto it = d_ISM_URA_MAP.find(this->d_ism_ura);
if (it == d_ISM_URA_MAP.end())
{
return 0.0;
}
return it->second;
}
float Galileo_ISM::get_ure_m() const
{
auto it = d_ISM_URE_MAP.find(this->d_ism_ure);
if (it == d_ISM_URE_MAP.end())
{
return 0.0;
}
return it->second;
}
uint32_t Galileo_ISM::get_mask_ISM() const
{
return d_ism_mask;
}
float Galileo_ISM::get_bnom_m() const
{
auto it = d_ISM_BNOM_MAP.find(this->d_ism_bnom);
if (it == d_ISM_BNOM_MAP.end())
{
return 5.0; //
}
return it->second;
}
uint16_t Galileo_ISM::get_Tvalidity_hours() const
{
auto it = d_ISM_TVALIDITY_MAP.find(this->d_ism_Tvalidity);
if (it == d_ISM_TVALIDITY_MAP.end())
{
return 0.0;
}
return it->second;
}
bool Galileo_ISM::check_ism_crc(const std::bitset<GALILEO_DATA_JK_BITS>& bits)
{
std::bitset<GALILEO_ISM_CRC_DATA_BITS> data_bits;
for (int32_t i = 0; i < GALILEO_ISM_CRC_DATA_BITS; ++i)
{
data_bits[i] = bits[i + 32];
}
std::bitset<32> crc_bits;
for (int32_t i = 0; i < 32; ++i)
{
crc_bits[i] = bits[i];
}
this->d_ism_crc = crc_bits.to_ulong();
std::vector<uint8_t> data_bytes((data_bits.size() + 7) / 8);
for (size_t i = 0; i < data_bits.size(); i += 8)
{
uint8_t byte = 0;
for (size_t j = 0; j < 8 && i + j < data_bits.size(); ++j)
{
byte |= (data_bits[i + j] << j);
}
data_bytes[i / 8] = byte;
}
std::reverse(data_bytes.begin(), data_bytes.end());
const uint32_t crc_computed = this->compute_crc(data_bytes);
if (this->d_ism_crc == crc_computed)
{
return true;
}
return false;
}
uint32_t Galileo_ISM::compute_crc(const std::vector<uint8_t>& data)
{
d_crc32_ism.process_bytes(data.data(), data.size());
const uint32_t crc = d_crc32_ism.checksum();
d_crc32_ism.reset();
return crc;
}
bool Galileo_ISM::ism_parameters_apply(uint32_t prn) const
{
// ICD 2.1 Table 96
if (prn == 0 || prn > 63 || d_ism_service_level_id != 2 || d_ism_constellation_id != 1)
{
return false;
}
std::bitset<32> b(d_ism_mask);
if (d_ism_mask_msb == false)
{
// For numbering in the ICD, the most significant bit/byte is numbered as bit/byte 0
if (prn > 32)
{
return false;
}
return b.test(32 - prn);
}
else
{
if (prn <= 32)
{
return false;
}
return b.test(64 - prn);
}
}

View File

@ -0,0 +1,210 @@
/*!
* \file galileo_ism.h
* \brief Interface of a Galileo Integrity Support Message
* \author Carles Fernandez, 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-2024 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_ISM_H
#define GNSS_SDR_GALILEO_ISM_H
#include "Galileo_INAV.h"
#include <boost/crc.hpp>
#include <bitset>
#include <cstdint>
#include <unordered_map>
#include <vector>
/** \addtogroup Core
* \{ */
/** \addtogroup System_Parameters
* \{ */
/*!
* \brief This class is a storage for the GALILEO Integrity Support Message as described
* in Galileo ICD paragraph 5.2
*
* See https://www.gsc-europa.eu/sites/default/files/sites/all/files/Galileo_OS_SIS_ICD_v2.1.pdf
*/
class Galileo_ISM
{
public:
/*!
* Default constructor
*/
Galileo_ISM() = default;
void set_ism_constellation_id(uint8_t const_id);
void set_ism_service_level_id(uint8_t sl_id);
void set_ism_wn(uint16_t wn_ism);
void set_ism_t0(uint16_t t0);
void set_ism_mask_msb(bool mask_msb);
void set_ism_mask(uint32_t mask);
void set_ism_pconst(uint8_t pconst);
void set_ism_psat(uint8_t psat);
void set_ism_ura(uint8_t ura);
void set_ism_ure(uint8_t ure);
void set_ism_bnom(uint8_t bnom);
void set_ism_Tvalidity(uint8_t tvalidity);
bool check_ism_crc(const std::bitset<GALILEO_DATA_JK_BITS>& bits);
double get_pconst_value() const;
double get_psat_value() const;
float get_ura_m() const;
float get_ure_m() const;
float get_bnom_m() const;
uint32_t get_mask_ISM() const;
uint16_t get_WN_ISM() const;
uint16_t get_t0_ISM() const;
uint16_t get_Tvalidity_hours() const;
bool get_ism_mask_msb() const;
bool ism_parameters_apply(uint32_t prn) const;
private:
uint32_t compute_crc(const std::vector<uint8_t>& data);
boost::crc_optimal<32, 0x814141AB, 0, 0, false, false> d_crc32_ism;
// ICD 2.1 Table 97
std::unordered_map<uint8_t, double> d_ISM_PCONST_MAP = {
{0, 1.0e-8},
{1, 1.0e-7},
{2, 1.0e-6},
{3, 3.0e-6},
{4, 6.0e-6},
{5, 8.0e-6},
{6, 1.0e-5},
{7, 2.0e-5},
{8, 4.0e-5},
{9, 6.0e-5},
{10, 8.0e-5},
{11, 1.0e-4},
{12, 1.25e-4},
{13, 1.5e-4},
{14, 1.75e-4},
{15, 2.0e-4}};
// ICD 2.1 Table 98
std::unordered_map<uint8_t, double> d_ISM_PSAT_MAP = {
{0, 1.0e-7},
{1, 3.0e-7},
{2, 6.0e-7},
{3, 1.0e-6},
{4, 2.0e-6},
{5, 3.0e-6},
{6, 5.0e-6},
{7, 7.0e-6},
{8, 1.0e-5},
{9, 1.2e-5},
{10, 1.4e-5},
{11, 1.7e-5},
{12, 2.05e-5},
{13, 2.4e-5},
{14, 2.8e-5},
{15, 3.0e-5}};
// ICD 2.1 Table 99
std::unordered_map<uint8_t, float> d_ISM_URA_MAP = {
{0, 0.75},
{1, 1.0},
{2, 1.5},
{3, 2.0},
{4, 2.25},
{5, 2.50},
{6, 2.75},
{7, 3.0},
{8, 3.25},
{9, 3.50},
{10, 3.75},
{11, 4.0},
{12, 4.50},
{13, 5.0},
{14, 5.50},
{15, 6.0}};
// ICD 2.1 Table 100
std::unordered_map<uint8_t, float> d_ISM_URE_MAP = {
{0, 0.25},
{1, 0.50},
{2, 0.75},
{3, 1.00},
{4, 1.25},
{5, 1.50},
{6, 1.75},
{7, 2.0},
{8, 2.25},
{9, 2.50},
{10, 2.75},
{11, 3.0},
{12, 3.25},
{13, 3.50},
{14, 3.75},
{15, 4.00}};
// ICD 2.1 Table 101
std::unordered_map<uint8_t, float> d_ISM_BNOM_MAP = {
{0, 0.0},
{1, 0.10},
{2, 0.20},
{3, 0.30},
{4, 0.40},
{5, 0.50},
{6, 0.60},
{7, 0.75},
{8, 0.85},
{9, 1.0},
{10, 1.20},
{11, 1.40},
{12, 1.60},
{13, 1.80},
{14, 2.0},
{15, 2.4}};
// ICD 2.1 Table 102
std::unordered_map<uint8_t, uint16_t> d_ISM_TVALIDITY_MAP = {
{0, 1},
{1, 2},
{2, 3},
{3, 4},
{4, 6},
{5, 8},
{6, 12},
{7, 18},
{8, 24},
{9, 36},
{10, 48},
{11, 72},
{12, 120},
{13, 168},
{14, 720},
{15, 1440}};
uint32_t d_ism_crc{};
uint32_t d_ism_mask{};
uint16_t d_ism_wn{};
uint16_t d_ism_t0{};
uint8_t d_ism_constellation_id{};
uint8_t d_ism_service_level_id{};
uint8_t d_ism_pconst{};
uint8_t d_ism_psat{};
uint8_t d_ism_ura{};
uint8_t d_ism_ure{};
uint8_t d_ism_bnom{};
uint8_t d_ism_Tvalidity{};
bool d_ism_mask_msb{};
};
/** \} */
/** \} */
#endif // GNSS_SDR_GALILEO_ISM_H

View File

@ -133,7 +133,7 @@ private:
#include "unit-tests/signal-processing-blocks/tracking/tracking_loop_filter_test.cc"
#include "unit-tests/system-parameters/galileo_e1b_reed_solomon_test.cc"
#include "unit-tests/system-parameters/galileo_e6b_reed_solomon_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_crc_test.cc"
#include "unit-tests/system-parameters/galileo_ism_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_nav_message_test.cc"
#include "unit-tests/system-parameters/has_decoding_test.cc"

View File

@ -0,0 +1,35 @@
/*!
* \file galileo_ism_test.cc
* \brief Tests for Galileo Integrity Support Message
* \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-2024 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "galileo_ism.h"
#include <gtest/gtest.h>
TEST(GalileoISMTest, CRC)
{
// Example from ANNEX G Galileo ICD
Galileo_ISM gal_ism{};
std::bitset<128> input{"01011000001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010110010111101001101011010101111"};
bool result = gal_ism.check_ism_crc(input);
EXPECT_TRUE(result);
// Check if it can be used twice
bool result2 = gal_ism.check_ism_crc(input);
EXPECT_TRUE(result2);
// Check if it fails
input.set(127);
bool result3 = gal_ism.check_ism_crc(input);
EXPECT_TRUE(!result3);
}