From 74e2beb5b80470a26054c8c51665996b10303f68 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 22 Jan 2016 14:08:58 +0100 Subject: Add repetition rate analyser --- CMakeLists.txt | 3 +- etisnoop.cpp | 63 +++++++++++++++-------- fig0_0.cpp | 4 +- fig0_1.cpp | 23 ++++++++- fig0_10.cpp | 4 +- fig0_11.cpp | 26 +++++++++- fig0_13.cpp | 32 +++++++++++- fig0_14.cpp | 24 ++++++++- fig0_16.cpp | 29 ++++++++++- fig0_17.cpp | 23 ++++++++- fig0_18.cpp | 23 ++++++++- fig0_19.cpp | 22 +++++++- fig0_2.cpp | 25 ++++++++- fig0_21.cpp | 23 ++++++++- fig0_22.cpp | 25 ++++++++- fig0_24.cpp | 23 ++++++++- fig0_25.cpp | 23 ++++++++- fig0_26.cpp | 23 ++++++++- fig0_27.cpp | 23 ++++++++- fig0_28.cpp | 23 ++++++++- fig0_3.cpp | 24 ++++++++- fig0_31.cpp | 25 ++++++++- fig0_5.cpp | 27 +++++++++- fig0_6.cpp | 24 ++++++++- fig0_8.cpp | 32 +++++++++++- fig0_9.cpp | 4 +- fig1.cpp | 15 +++--- figs.cpp | 52 ++++++++++--------- figs.hpp | 54 ++++++++++---------- repetitionrate.cpp | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++ repetitionrate.hpp | 37 ++++++++++++++ utils.hpp | 2 +- 32 files changed, 799 insertions(+), 108 deletions(-) create mode 100644 repetitionrate.cpp create mode 100644 repetitionrate.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8935610..bebb0c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ set(VERSION_INFO_MAINT_VERSION git) # Compiler specific setup ######################################################################## -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -W -Wall -std=c++11") ######################################################################## @@ -77,6 +77,7 @@ list(APPEND etisnoop_sources figs.cpp firecode.c lib_crc.c + repetitionrate.cpp rsdecoder.cpp tables.cpp utils.cpp diff --git a/etisnoop.cpp b/etisnoop.cpp index 078a245..251c725 100644 --- a/etisnoop.cpp +++ b/etisnoop.cpp @@ -49,6 +49,7 @@ #include "etiinput.h" #include "figs.hpp" #include "watermarkdecoder.hpp" +#include "repetitionrate.hpp" struct FIG { @@ -154,6 +155,7 @@ struct eti_analyse_config_t { bool ignore_error; std::map streams_to_decode; bool analyse_fic_carousel; + bool analyse_fig_rates; bool decode_watermark; }; @@ -193,6 +195,7 @@ void usage(void) " -v increase verbosity (can be given more than once)\n" " -d N decode subchannel N into .dabp and .wav files\n" " -f analyse FIC carousel\n" + " -r analyse FIG rates\n" " -w decode CRC-DABMUX and ODR-DabMux watermark.\n"); } @@ -201,36 +204,36 @@ int main(int argc, char *argv[]) int index; int ch = 0; string file_name("-"); - map streams_to_decode; - bool ignore_error = false; - bool analyse_fic_carousel = false; - bool decode_watermark = false; + eti_analyse_config_t config; while(ch != -1) { - ch = getopt_long(argc, argv, "d:efhvwi:", longopts, &index); + ch = getopt_long(argc, argv, "d:efhrvwi:", longopts, &index); switch (ch) { case 'd': { int subchix = atoi(optarg); DabPlusSnoop dps; - streams_to_decode[subchix] = dps; + config.streams_to_decode[subchix] = dps; } break; case 'e': - ignore_error = true; + config.ignore_error = true; break; case 'i': file_name = optarg; break; case 'f': - analyse_fic_carousel = true; + config.analyse_fic_carousel = true; + break; + case 'r': + config.analyse_fig_rates = true; break; case 'v': set_verbosity(get_verbosity() + 1); break; case 'w': - decode_watermark = true; + config.decode_watermark = true; break; case 'h': usage(); @@ -252,14 +255,8 @@ int main(int argc, char *argv[]) return 1; } } + config.etifd = etifd; - eti_analyse_config_t config = { - .etifd = etifd, - .ignore_error = ignore_error, - .streams_to_decode = streams_to_decode, - .analyse_fic_carousel = analyse_fic_carousel, - .decode_watermark = decode_watermark - }; eti_analyse(config); fclose(etifd); } @@ -377,9 +374,10 @@ int eti_analyse(eti_analyse_config_t& config) // LIDATA - FC printbuf("FC - Frame Characterization field", 1, p+4, 4); // LIDATA - FC - FCT - char fct[25]; - sprintf(fct, "%d", p[4]); - printbuf("FCT - Frame Count", 2, p+4, 1, fct); + char fct_str[25]; + sprintf(fct_str, "%d", p[4]); + int fct = p[4]; + printbuf("FCT - Frame Count", 2, p+4, 1, fct_str); // LIDATA - FC - FICF ficf = (p[5] & 0x80) >> 7; @@ -556,6 +554,7 @@ int eti_analyse(eti_analyse_config_t& config) printbuf(sdesc, 1, NULL, 0); fig=fib; figs.set_fib(i); + rate_new_fib(i); endmarker=0; figcount=0; while (!endmarker) { @@ -648,6 +647,10 @@ int eti_analyse(eti_analyse_config_t& config) if (get_verbosity()) { printf("-------------------------------------------------------------------------------------------------------------\n"); } + + if (config.analyse_fig_rates and (fct % 250) == 0) { + rate_disply_analysis(); + } } @@ -663,8 +666,13 @@ int eti_analyse(eti_analyse_config_t& config) printf("Watermark:\n %s\n", watermark.c_str()); } + if (config.analyse_fig_rates) { + rate_disply_analysis(); + } + figs_cleardb(); + return 0; } @@ -688,7 +696,8 @@ void decodeFIG(FIGalyser &figs, figs.push_back(figtype, fig0.ext(), figlen); - fig0_select(fig0, indent); + bool complete = fig0_select(fig0, indent); + rate_announce_fig(figtype, fig0.ext(), complete); } break; @@ -698,7 +707,8 @@ void decodeFIG(FIGalyser &figs, figs.push_back(figtype, fig1.ext(), figlen); - fig1_select(fig1, indent); + bool complete = fig1_select(fig1, indent); + rate_announce_fig(figtype, fig1.ext(), complete); } break; case 2: @@ -716,6 +726,9 @@ void decodeFIG(FIGalyser &figs, printbuf(desc, indent, f+1, figlen-1); figs.push_back(figtype, ext, figlen); + + bool complete = true; // TODO verify + rate_announce_fig(figtype, ext, complete); } break; case 5: @@ -733,6 +746,9 @@ void decodeFIG(FIGalyser &figs, printbuf(desc, indent, f+1, figlen-1); figs.push_back(figtype, ext, figlen); + + bool complete = true; // TODO verify + rate_announce_fig(figtype, ext, complete); } break; case 6: @@ -740,6 +756,11 @@ void decodeFIG(FIGalyser &figs, fprintf(stderr, "ERROR: ETI contains unsupported FIG 6\n"); } break; + default: + { + fprintf(stderr, "ERROR: ETI contains unknown FIG %d\n", figtype); + } + break; } } diff --git a/fig0_0.cpp b/fig0_0.cpp index 2b2b6a2..82bfadf 100644 --- a/fig0_0.cpp +++ b/fig0_0.cpp @@ -29,7 +29,7 @@ // FIG 0/0 Ensemble information // ETSI EN 300 401 6.4 -void fig0_0(fig0_common_t& fig0, int indent) +bool fig0_0(fig0_common_t& fig0, int indent) { uint8_t cid, al, ch, hic, lowc, occ; uint16_t eid, eref; @@ -56,5 +56,7 @@ void fig0_0(fig0_common_t& fig0, int indent) eid, cid, eref, ch, al, hic, lowc); } printbuf(desc, indent+1, NULL, 0); + + return true; } diff --git a/fig0_1.cpp b/fig0_1.cpp index 791c0ec..f5df4c4 100644 --- a/fig0_1.cpp +++ b/fig0_1.cpp @@ -26,18 +26,38 @@ #include "figs.hpp" #include +#include + +static std::unordered_set subchannels_seen; + +bool fig0_1_is_complete(int subch_id) +{ + bool complete = subchannels_seen.count(subch_id); + + if (complete) { + subchannels_seen.clear(); + } + else { + subchannels_seen.insert(subch_id); + } + + return complete; +} // FIG 0/1 Basic sub-channel organization // ETSI EN 300 401 6.2.1 -void fig0_1(fig0_common_t& fig0, int indent) +bool fig0_1(fig0_common_t& fig0, int indent) { int i = 1; uint8_t* f = fig0.f; char desc[128]; + bool complete = false; while (i < fig0.figlen-3) { // iterate over subchannels int subch_id = f[i] >> 2; + complete |= fig0_1_is_complete(subch_id); + int start_addr = ((f[i] & 0x03) << 8) | (f[i+1]); int long_flag = (f[i+2] >> 7); @@ -87,5 +107,6 @@ void fig0_1(fig0_common_t& fig0, int indent) printbuf(desc, indent+1, NULL, 0); } + return complete; } diff --git a/fig0_10.cpp b/fig0_10.cpp index c374ef9..5c81c3f 100644 --- a/fig0_10.cpp +++ b/fig0_10.cpp @@ -31,7 +31,7 @@ // FIG 0/10 Date and time // ETSI EN 300 401 8.1.3.1 -void fig0_10(fig0_common_t& fig0, int indent) +bool fig0_10(fig0_common_t& fig0, int indent) { char desc[256]; char dateStr[256]; @@ -68,5 +68,7 @@ void fig0_10(fig0_common_t& fig0, int indent) fig0.ext(), MJD, dateStr, LSI, ConfInd, hours, minutes); printbuf(desc, indent+1, NULL, 0); } + + return true; } diff --git a/fig0_11.cpp b/fig0_11.cpp index cc6bead..40136c3 100644 --- a/fig0_11.cpp +++ b/fig0_11.cpp @@ -28,10 +28,28 @@ #include #include #include +#include + +static std::unordered_set region_ids_seen; + +bool fig0_11_is_complete(int region_id) +{ + bool complete = region_ids_seen.count(region_id); + + if (complete) { + region_ids_seen.clear(); + } + else { + region_ids_seen.insert(region_id); + } + + return complete; +} + // FIG 0/11 Region definition // ETSI EN 300 401 8.1.16.1 -void fig0_11(fig0_common_t& fig0, int indent) +bool fig0_11(fig0_common_t& fig0, int indent) { Lat_Lng gps_pos = {0, 0}; int16_t Latitude_coarse, Longitude_coarse; @@ -43,12 +61,15 @@ void fig0_11(fig0_common_t& fig0, int indent) bool GE_flag; uint8_t* f = fig0.f; uint8_t Mode_Identity = get_mode_identity(); + bool complete = false; while (i < (fig0.figlen - 1)) { // iterate over Region definition GATy = f[i] >> 4; GE_flag = (f[i] >> 3) & 0x01; Region_Id = ((uint16_t)(f[i] & 0x07) << 8) | ((uint16_t)f[i+1]); + complete |= fig0_11_is_complete(Region_Id); + key = ((uint16_t)fig0.oe() << 12) | ((uint16_t)fig0.pd() << 11) | Region_Id; i += 2; if (GATy == 0) { @@ -182,4 +203,7 @@ void fig0_11(fig0_common_t& fig0, int indent) i = fig0.figlen; } } + + return complete; } + diff --git a/fig0_13.cpp b/fig0_13.cpp index 113bb49..ffb5b89 100644 --- a/fig0_13.cpp +++ b/fig0_13.cpp @@ -28,6 +28,31 @@ #include #include #include +#include + +/* EN 300 401, 8.1.20, User application information + * The combination of the SId and the SCIdS provides a service component + * identifier which is valid globally. + */ +using SId_t = int; +using SCIdS_t = int; +static std::set > components_ids_seen; + +bool fig0_13_is_complete(SId_t SId, SCIdS_t SCIdS) +{ + auto key = std::make_pair(SId, SCIdS); + bool complete = components_ids_seen.count(key); + + if (complete) { + components_ids_seen.clear(); + } + else { + components_ids_seen.insert(key); + } + + return complete; +} + std::string get_fig_0_13_userapp(int user_app_type) { @@ -48,7 +73,7 @@ std::string get_fig_0_13_userapp(int user_app_type) // FIG 0/13 User application information // ETSI EN 300 401 8.1.20 -void fig0_13(fig0_common_t& fig0, int indent) +bool fig0_13(fig0_common_t& fig0, int indent) { uint32_t SId; uint8_t SCIdS; @@ -56,6 +81,7 @@ void fig0_13(fig0_common_t& fig0, int indent) uint8_t* f = fig0.f; const int figtype = 0; char desc[256]; + bool complete = false; int k = 1; @@ -81,6 +107,8 @@ void fig0_13(fig0_common_t& fig0, int indent) } + complete |= fig0_13_is_complete(SId, SCIdS); + sprintf(desc, "FIG %d/%d: SId=0x%X SCIdS=%u No=%u", figtype, fig0.ext(), SId, SCIdS, No); printbuf(desc, indent+1, NULL, 0); @@ -97,5 +125,7 @@ void fig0_13(fig0_common_t& fig0, int indent) user_app_len); printbuf(desc, indent+2, NULL, 0); } + + return complete; } diff --git a/fig0_14.cpp b/fig0_14.cpp index 8d63cae..e72d121 100644 --- a/fig0_14.cpp +++ b/fig0_14.cpp @@ -28,6 +28,24 @@ #include #include #include +#include + +static std::unordered_set subch_ids_seen; + +bool fig0_14_is_complete(int subch_id) +{ + bool complete = subch_ids_seen.count(subch_id); + + if (complete) { + subch_ids_seen.clear(); + } + else { + subch_ids_seen.insert(subch_id); + } + + return complete; +} + // fig 0/14 FEC Scheme: this 2-bit field shall indicate the Forward Error Correction scheme in use, as follows: const char *FEC_schemes_str[4] = { @@ -40,20 +58,24 @@ const char *FEC_schemes_str[4] = { // FIG 0/14 FEC sub-channel organization // ETSI EN 300 401 6.2.2 -void fig0_14(fig0_common_t& fig0, int indent) +bool fig0_14(fig0_common_t& fig0, int indent) { uint8_t i = 1, SubChId, FEC_scheme; uint8_t* f = fig0.f; char desc[256]; + bool complete = false; while (i < fig0.figlen) { // iterate over Sub-channel SubChId = f[i] >> 2; + complete |= fig0_14_is_complete(SubChId); FEC_scheme = f[i] & 0x3; sprintf(desc, "SubChId=0x%X, FEC scheme=%d %s", SubChId, FEC_scheme, FEC_schemes_str[FEC_scheme]); printbuf(desc, indent+1, NULL, 0); i++; } + + return complete; } diff --git a/fig0_16.cpp b/fig0_16.cpp index aee7d10..24c9040 100644 --- a/fig0_16.cpp +++ b/fig0_16.cpp @@ -28,10 +28,33 @@ #include #include #include +#include + +/* SId and PNum look like good candidates to uniquely identify a FIG0_16 + */ +using SId_t = int; +using PNum_t = int; +static std::set > components_seen; + +bool fig0_16_is_complete(SId_t SId, PNum_t PNum) +{ + auto key = std::make_pair(SId, PNum); + bool complete = components_seen.count(key); + + if (complete) { + components_seen.clear(); + } + else { + components_seen.insert(key); + } + + return complete; +} + // FIG 0/16 Programme Number & fig0.oe() Programme Number // ETSI EN 300 401 8.1.4 & 8.1.10.3 -void fig0_16(fig0_common_t& fig0, int indent) +bool fig0_16(fig0_common_t& fig0, int indent) { uint16_t SId, PNum, New_SId, New_PNum; uint8_t i = 1, Rfa, Rfu; @@ -39,11 +62,13 @@ void fig0_16(fig0_common_t& fig0, int indent) char desc[256]; bool Continuation_flag, Update_flag; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 4)) { // iterate over Programme Number SId = ((uint16_t)f[i] << 8) | ((uint16_t)f[i+1]); PNum = ((uint16_t)f[i+2] << 8) | ((uint16_t)f[i+3]); + complete |= fig0_16_is_complete(SId, PNum); Rfa = f[i+4] >> 6; Rfu = (f[i+4] >> 2) & 0x0F; Continuation_flag = (f[i+4] >> 1) & 0x01; @@ -96,5 +121,7 @@ void fig0_16(fig0_common_t& fig0, int indent) printbuf(desc, indent+1, NULL, 0); } + + return complete; } diff --git a/fig0_17.cpp b/fig0_17.cpp index 264d151..120cb4c 100644 --- a/fig0_17.cpp +++ b/fig0_17.cpp @@ -28,10 +28,27 @@ #include #include #include +#include + +static std::unordered_set services_ids_seen; + +bool fig0_17_is_complete(int services_id) +{ + bool complete = services_ids_seen.count(services_id); + + if (complete) { + services_ids_seen.clear(); + } + else { + services_ids_seen.insert(services_id); + } + + return complete; +} // FIG 0/17 Programme Type // ETSI EN 300 401 8.1.5 -void fig0_17(fig0_common_t& fig0, int indent) +bool fig0_17(fig0_common_t& fig0, int indent) { uint16_t SId; uint8_t i = 1, Rfa, Language, Int_code, Comp_code; @@ -39,10 +56,12 @@ void fig0_17(fig0_common_t& fig0, int indent) char desc[256]; bool SD_flag, PS_flag, L_flag, CC_flag, Rfu; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 3)) { // iterate over announcement support SId = (f[i] << 8) | f[i+1]; + complete |= fig0_17_is_complete(SId); SD_flag = (f[i+2] >> 7); PS_flag = ((f[i+2] >> 6) & 0x01); L_flag = ((f[i+2] >> 5) & 0x01); @@ -113,5 +132,7 @@ void fig0_17(fig0_common_t& fig0, int indent) } printbuf(desc, indent+1, NULL, 0); } + + return complete; } diff --git a/fig0_18.cpp b/fig0_18.cpp index c7d7f8a..46a399c 100644 --- a/fig0_18.cpp +++ b/fig0_18.cpp @@ -28,11 +28,28 @@ #include #include #include +#include + +static std::unordered_set services_seen; + +bool fig0_18_is_complete(int services_id) +{ + bool complete = services_seen.count(services_id); + + if (complete) { + services_seen.clear(); + } + else { + services_seen.insert(services_id); + } + + return complete; +} // FIG 0/18 Announcement support // ETSI EN 300 401 8.1.6.1 -void fig0_18(fig0_common_t& fig0, int indent) +bool fig0_18(fig0_common_t& fig0, int indent) { uint32_t key; uint16_t SId, Asu_flags; @@ -41,11 +58,13 @@ void fig0_18(fig0_common_t& fig0, int indent) char desc[256]; uint8_t* f = fig0.f; const int figtype = 0; + bool complete = false; while (i < (fig0.figlen - 4)) { // iterate over announcement support // SId, Asu flags, Rfa, Number of clusters SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1]; + complete |= fig0_18_is_complete(SId); Asu_flags = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3]; Rfa = (f[i+4] >> 5); Number_clusters = (f[i+4] & 0x1F); @@ -87,5 +106,7 @@ void fig0_18(fig0_common_t& fig0, int indent) } } } + + return complete; } diff --git a/fig0_19.cpp b/fig0_19.cpp index 1d3593e..31b4ca1 100644 --- a/fig0_19.cpp +++ b/fig0_19.cpp @@ -28,11 +28,27 @@ #include #include #include +#include +static std::unordered_set clusters_seen; + +bool fig0_19_is_complete(int clusters_id) +{ + bool complete = clusters_seen.count(clusters_id); + + if (complete) { + clusters_seen.clear(); + } + else { + clusters_seen.insert(clusters_id); + } + + return complete; +} // FIG 0/19 Announcement switching // ETSI EN 300 401 8.1.6.2 -void fig0_19(fig0_common_t& fig0, int indent) +bool fig0_19(fig0_common_t& fig0, int indent) { uint16_t Asw_flags; uint8_t i = 1, j, Cluster_Id, SubChId, Rfa, RegionId_LP; @@ -41,12 +57,14 @@ void fig0_19(fig0_common_t& fig0, int indent) bool New_flag, Region_flag; uint8_t* f = fig0.f; const int figtype = 0; + bool complete = false; while (i < (fig0.figlen - 3)) { // iterate over announcement switching // Cluster Id, Asw flags, New flag, Region flag, // SubChId, Rfa, Region Id Lower Part Cluster_Id = f[i]; + complete |= fig0_19_is_complete(Cluster_Id); Asw_flags = ((uint16_t)f[i+1] << 8) | (uint16_t)f[i+2]; New_flag = (f[i+3] >> 7); Region_flag = (f[i+3] >> 6) & 0x1; @@ -81,5 +99,7 @@ void fig0_19(fig0_common_t& fig0, int indent) } i += (4 + Region_flag); } + + return complete; } diff --git a/fig0_2.cpp b/fig0_2.cpp index 29b52fa..95e6268 100644 --- a/fig0_2.cpp +++ b/fig0_2.cpp @@ -28,10 +28,27 @@ #include #include #include +#include + +static std::unordered_set services_seen; + +bool fig0_2_is_complete(int services_id) +{ + bool complete = services_seen.count(services_id); + + if (complete) { + services_seen.clear(); + } + else { + services_seen.insert(services_id); + } + + return complete; +} // FIG 0/2 Basic service and service component definition // ETSI EN 300 401 6.3.1 -void fig0_2(fig0_common_t& fig0, int indent) +bool fig0_2(fig0_common_t& fig0, int indent) { uint16_t sref, sid; uint8_t cid, ecc, local, caid, ncomp, timd, ps, ca, subchid, scty; @@ -40,6 +57,7 @@ void fig0_2(fig0_common_t& fig0, int indent) uint8_t* f = fig0.f; char sctydesc[32]; char desc[256]; + bool complete = false; while (k < fig0.figlen) { if (fig0.pd() == 0) { @@ -63,6 +81,8 @@ void fig0_2(fig0_common_t& fig0, int indent) k += 4; } + complete |= fig0_2_is_complete(sid); + local = (f[k] & 0x80) >> 7; caid = (f[k] & 0x70) >> 4; ncomp = f[k] & 0x0F; @@ -141,6 +161,7 @@ void fig0_2(fig0_common_t& fig0, int indent) k += 2; } } -} + return complete; +} diff --git a/fig0_21.cpp b/fig0_21.cpp index 9e6b113..69f18b9 100644 --- a/fig0_21.cpp +++ b/fig0_21.cpp @@ -28,11 +28,28 @@ #include #include #include +#include + +static std::unordered_set regions_seen; + +bool fig0_21_is_complete(int region_id) +{ + bool complete = regions_seen.count(region_id); + + if (complete) { + regions_seen.clear(); + } + else { + regions_seen.insert(region_id); + } + + return complete; +} // FIG 0/21 Frequency Information // ETSI EN 300 401 8.1.8 -void fig0_21(fig0_common_t& fig0, int indent) +bool fig0_21(fig0_common_t& fig0, int indent) { float freq; uint32_t ifreq; @@ -44,11 +61,13 @@ void fig0_21(fig0_common_t& fig0, int indent) char desc[256]; bool Continuity_flag; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 1)) { // iterate over frequency information // decode RegionId, Length of FI list RegionId = (f[i] << 3) | (f[i+1] >> 5); + complete |= fig0_21_is_complete(RegionId); Length_FI_list = (f[i+1] & 0x1F); sprintf(desc, "RegionId=0x%03x", RegionId); printbuf(desc, indent+1, NULL, 0); @@ -298,5 +317,7 @@ void fig0_21(fig0_common_t& fig0, int indent) i += Length_FI_list; } } + + return complete; } diff --git a/fig0_22.cpp b/fig0_22.cpp index 5c29e8d..dfee52b 100644 --- a/fig0_22.cpp +++ b/fig0_22.cpp @@ -28,6 +28,25 @@ #include #include #include +#include + +static std::unordered_set identifiers_seen; + +bool fig0_22_is_complete(int M_S, int MainId) +{ + int identifier = (M_S << 7) | MainId; + + bool complete = identifiers_seen.count(identifier); + + if (complete) { + identifiers_seen.clear(); + } + else { + identifiers_seen.insert(identifier); + } + + return complete; +} // map for fig 0/22 database @@ -40,7 +59,7 @@ void fig0_22_cleardb() // FIG 0/22 Transmitter Identification Information (TII) database // ETSI EN 300 401 8.1.9 -void fig0_22(fig0_common_t& fig0, int indent) +bool fig0_22(fig0_common_t& fig0, int indent) { Lat_Lng gps_pos = {0, 0}; double latitude_sub, longitude_sub; @@ -54,11 +73,13 @@ void fig0_22(fig0_common_t& fig0, int indent) bool MS; const uint8_t Mode_Identity = get_mode_identity(); uint8_t* f = fig0.f; + bool complete = false; while (i < fig0.figlen) { // iterate over Transmitter Identification Information (TII) fields MS = f[i] >> 7; MainId = f[i] & 0x7F; + complete |= fig0_22_is_complete(MS, MainId); key = (fig0.oe() << 8) | (fig0.pd() << 7) | MainId; sprintf(desc, "M/S=%d %sidentifier, MainId=0x%X", MS, MS?"Sub-":"Main ", MainId); @@ -159,5 +180,7 @@ void fig0_22(fig0_common_t& fig0, int indent) } } } + + return complete; } diff --git a/fig0_24.cpp b/fig0_24.cpp index 03642fb..7867d9e 100644 --- a/fig0_24.cpp +++ b/fig0_24.cpp @@ -28,10 +28,27 @@ #include #include #include +#include + +static std::unordered_set services_seen; + +bool fig0_24_is_complete(int services_id) +{ + bool complete = services_seen.count(services_id); + + if (complete) { + services_seen.clear(); + } + else { + services_seen.insert(services_id); + } + + return complete; +} // FIG 0/24 fig0.oe() Services // ETSI EN 300 401 8.1.10.2 -void fig0_24(fig0_common_t& fig0, int indent) +bool fig0_24(fig0_common_t& fig0, int indent) { uint64_t key; uint32_t SId; @@ -41,6 +58,7 @@ void fig0_24(fig0_common_t& fig0, int indent) char desc[256]; uint8_t* f = fig0.f; bool Rfa; + bool complete = false; while (i < (fig0.figlen - (((uint8_t)fig0.pd() + 1) * 2))) { // iterate over other ensembles services @@ -53,6 +71,7 @@ void fig0_24(fig0_common_t& fig0, int indent) ((uint32_t)f[i+2] << 8) | (uint32_t)f[i+3]; i += 4; } + complete |= fig0_24_is_complete(SId); Rfa = (f[i] >> 7); CAId = (f[i] >> 4); Number_of_EIds = (f[i] & 0x0f); @@ -84,5 +103,7 @@ void fig0_24(fig0_common_t& fig0, int indent) } i += (Number_of_EIds * 2); } + + return complete; } diff --git a/fig0_25.cpp b/fig0_25.cpp index 7e6b69b..7859868 100644 --- a/fig0_25.cpp +++ b/fig0_25.cpp @@ -28,11 +28,28 @@ #include #include #include +#include + +static std::unordered_set services_seen; + +bool fig0_25_is_complete(int services_id) +{ + bool complete = services_seen.count(services_id); + + if (complete) { + services_seen.clear(); + } + else { + services_seen.insert(services_id); + } + + return complete; +} // FIG 0/25 fig0.oe() Announcement support // ETSI EN 300 401 8.1.10.5.1 -void fig0_25(fig0_common_t& fig0, int indent) +bool fig0_25(fig0_common_t& fig0, int indent) { uint32_t key; uint16_t SId, Asu_flags, EId; @@ -40,11 +57,13 @@ void fig0_25(fig0_common_t& fig0, int indent) char tmpbuf[256]; char desc[256]; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 4)) { // iterate over other ensembles announcement support // SId, Asu flags, Rfu, Number of EIds SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1]; + complete |= fig0_25_is_complete(SId); Asu_flags = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3]; Rfu = (f[i+4] >> 4); Number_EIds = (f[i+4] & 0x0F); @@ -87,5 +106,7 @@ void fig0_25(fig0_common_t& fig0, int indent) } } } + + return complete; } diff --git a/fig0_26.cpp b/fig0_26.cpp index b519ed8..c2e4316 100644 --- a/fig0_26.cpp +++ b/fig0_26.cpp @@ -28,11 +28,28 @@ #include #include #include +#include + +static std::unordered_set clusters_seen; + +bool fig0_26_is_complete(int cluster_id) +{ + bool complete = clusters_seen.count(cluster_id); + + if (complete) { + clusters_seen.clear(); + } + else { + clusters_seen.insert(cluster_id); + } + + return complete; +} // FIG 0/26 fig0.oe() Announcement switching // ETSI EN 300 401 8.1.10.5.2 -void fig0_26(fig0_common_t& fig0, int indent) +bool fig0_26(fig0_common_t& fig0, int indent) { uint16_t Asw_flags, EId_Other_Ensemble; uint8_t i = 1, j, Rfa, Cluster_Id_Current_Ensemble, Region_Id_Current_Ensemble; @@ -41,10 +58,12 @@ void fig0_26(fig0_common_t& fig0, int indent) char tmpbuf[256]; char desc[256]; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 6)) { // iterate over other ensembles announcement switching Cluster_Id_Current_Ensemble = f[i]; + complete = fig0_26_is_complete(Cluster_Id_Current_Ensemble); Asw_flags = ((uint16_t)f[i+1] << 8) | (uint16_t)f[i+2]; New_flag = f[i+3] >> 7; Region_flag = (f[i+3] >> 6) & 0x01; @@ -84,5 +103,7 @@ void fig0_26(fig0_common_t& fig0, int indent) } } } + + return complete; } diff --git a/fig0_27.cpp b/fig0_27.cpp index 6e906b7..1f3f08d 100644 --- a/fig0_27.cpp +++ b/fig0_27.cpp @@ -28,21 +28,40 @@ #include #include #include +#include + +static std::unordered_set services_seen; + +bool fig0_27_is_complete(int services_id) +{ + bool complete = services_seen.count(services_id); + + if (complete) { + services_seen.clear(); + } + else { + services_seen.insert(services_id); + } + + return complete; +} // FIG 0/27 FM Announcement support // ETSI EN 300 401 8.1.11.2.1 -void fig0_27(fig0_common_t& fig0, int indent) +bool fig0_27(fig0_common_t& fig0, int indent) { uint16_t SId, PI; uint8_t i = 1, j, Rfu, Number_PI_codes, key; char tmpbuf[256]; char desc[256]; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 2)) { // iterate over FM announcement support SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1]; + complete |= fig0_27_is_complete(SId); Rfu = f[i+2] >> 4; Number_PI_codes = f[i+2] & 0x0F; key = (fig0.oe() << 5) | (fig0.pd() << 4) | Number_PI_codes; @@ -79,5 +98,7 @@ void fig0_27(fig0_common_t& fig0, int indent) fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen); } } + + return complete; } diff --git a/fig0_28.cpp b/fig0_28.cpp index 8c727b9..68798c4 100644 --- a/fig0_28.cpp +++ b/fig0_28.cpp @@ -28,11 +28,28 @@ #include #include #include +#include + +static std::unordered_set clusters_seen; + +bool fig0_28_is_complete(int cluster_id) +{ + bool complete = clusters_seen.count(cluster_id); + + if (complete) { + clusters_seen.clear(); + } + else { + clusters_seen.insert(cluster_id); + } + + return complete; +} // FIG 0/28 FM Announcement switching // ETSI EN 300 401 8.1.11.2.2 -void fig0_28(fig0_common_t& fig0, int indent) +bool fig0_28(fig0_common_t& fig0, int indent) { uint16_t PI; uint8_t i = 1, Cluster_Id_Current_Ensemble, Region_Id_Current_Ensemble; @@ -40,10 +57,12 @@ void fig0_28(fig0_common_t& fig0, int indent) char tmpbuf[256]; char desc[256]; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - 3)) { // iterate over FM announcement switching Cluster_Id_Current_Ensemble = f[i]; + complete = fig0_28_is_complete(Cluster_Id_Current_Ensemble); New_flag = f[i+1] >> 7; Rfa = (f[i+1] >> 6) & 0x01; Region_Id_Current_Ensemble = f[i+1] & 0x3F; @@ -65,5 +84,7 @@ void fig0_28(fig0_common_t& fig0, int indent) printbuf(desc, indent+1, NULL, 0); i += 4; } + + return complete; } diff --git a/fig0_3.cpp b/fig0_3.cpp index 71547b6..adc502f 100644 --- a/fig0_3.cpp +++ b/fig0_3.cpp @@ -27,22 +27,42 @@ #include "figs.hpp" #include #include +#include + +static std::unordered_set components_ids_seen; + +bool fig0_3_is_complete(int components_id) +{ + bool complete = components_ids_seen.count(components_id); + + if (complete) { + components_ids_seen.clear(); + } + else { + components_ids_seen.insert(components_id); + } + + return complete; +} + // FIG 0/3 Service component in packet mode with or without Conditional Access // ETSI EN 300 401 6.3.2 -void fig0_3(fig0_common_t& fig0, int indent) +bool fig0_3(fig0_common_t& fig0, int indent) { uint16_t SCId, Packet_address, CAOrg; uint8_t i = 1, Rfa, DSCTy, SubChId, CAMode, SharedFlag; char tmpbuf[256]; char desc[256]; bool CAOrg_flag, DG_flag, Rfu; + bool complete = false; uint8_t* f = fig0.f; while (i < (fig0.figlen - 4)) { // iterate over service component in packet mode SCId = ((uint16_t)f[i] << 4) | ((uint16_t)(f[i+1] >> 4) & 0x0F); + complete |= fig0_3_is_complete(SCId); Rfa = (f[i+1] >> 1) & 0x07; CAOrg_flag = f[i+1] & 0x01; DG_flag = (f[i+2] >> 7) & 0x01; @@ -84,5 +104,7 @@ void fig0_3(fig0_common_t& fig0, int indent) } printbuf(desc, indent+1, NULL, 0); } + + return complete; } diff --git a/fig0_31.cpp b/fig0_31.cpp index e4c3a92..cbaf296 100644 --- a/fig0_31.cpp +++ b/fig0_31.cpp @@ -28,15 +28,33 @@ #include #include #include +#include + +static std::unordered_set figtype_flags_seen; + +bool fig0_31_is_complete(uint64_t figtype_flags) +{ + bool complete = figtype_flags_seen.count(figtype_flags); + + if (complete) { + figtype_flags_seen.clear(); + } + else { + figtype_flags_seen.insert(figtype_flags); + } + + return complete; +} // FIG 0/31 FIC re-direction // ETSI EN 300 401 8.1.12 -void fig0_31(fig0_common_t& fig0, int indent) +bool fig0_31(fig0_common_t& fig0, int indent) { uint32_t FIG_type0_flag_field = 0, flag_field; uint8_t i = 1, j, FIG_type1_flag_field = 0, FIG_type2_flag_field = 0; char desc[256]; uint8_t* f = fig0.f; + bool complete = false; if (i < (fig0.figlen - 5)) { // Read FIC re-direction @@ -45,6 +63,9 @@ void fig0_31(fig0_common_t& fig0, int indent) FIG_type1_flag_field = f[i+4]; FIG_type2_flag_field = f[i+5]; + uint64_t key = ((uint64_t)FIG_type1_flag_field << 32) | ((uint64_t)FIG_type2_flag_field << 40) | FIG_type0_flag_field; + complete |= fig0_31_is_complete(key); + sprintf(desc, "FIG type 0 flag field=0x%X, FIG type 1 flag field=0x%X, FIG type 2 flag field=0x%X", FIG_type0_flag_field, FIG_type1_flag_field, FIG_type2_flag_field); printbuf(desc, indent+1, NULL, 0); @@ -106,5 +127,7 @@ void fig0_31(fig0_common_t& fig0, int indent) if (fig0.figlen != 7) { fprintf(stderr, "WARNING: FIG 0/%d invalid length %d, expecting 7\n", fig0.ext(), fig0.figlen); } + + return complete; } diff --git a/fig0_5.cpp b/fig0_5.cpp index f3ef08c..8d966a6 100644 --- a/fig0_5.cpp +++ b/fig0_5.cpp @@ -28,16 +28,34 @@ #include #include #include +#include + +static std::unordered_set components_seen; + +bool fig0_5_is_complete(int components_id) +{ + bool complete = components_seen.count(components_id); + + if (complete) { + components_seen.clear(); + } + else { + components_seen.insert(components_id); + } + + return complete; +} // FIG 0/5 Service component language // ETSI EN 300 401 8.1.2 -void fig0_5(fig0_common_t& fig0, int indent) +bool fig0_5(fig0_common_t& fig0, int indent) { uint16_t SCId; uint8_t i = 1, SubChId, FIDCId, Language, Rfa; char tmpbuf[256]; char desc[256]; bool LS_flag, MSC_FIC_flag; + bool complete = false; uint8_t* f = fig0.f; @@ -62,6 +80,9 @@ void fig0_5(fig0_common_t& fig0, int indent) LS_flag, MSC_FIC_flag, FIDCId, Language, get_language_name(Language)); } + + int key = (MSC_FIC_flag << 7) | (f[i] % 0x3F); + complete |= fig0_5_is_complete(key); printbuf(desc, indent+1, NULL, 0); i += 2; } @@ -70,6 +91,8 @@ void fig0_5(fig0_common_t& fig0, int indent) if (i < (fig0.figlen - 2)) { Rfa = (f[i] >> 4) & 0x07; SCId = (((uint16_t)f[i] & 0x0F) << 8) | (uint16_t)f[i+1]; + int key = (LS_flag << 15) | SCId; + complete |= fig0_5_is_complete(key); Language = f[i+2]; sprintf(desc, "L/S flag=%d long form", LS_flag); if (Rfa != 0) { @@ -85,5 +108,7 @@ void fig0_5(fig0_common_t& fig0, int indent) i += 3; } } + + return complete; } diff --git a/fig0_6.cpp b/fig0_6.cpp index e863951..dc35640 100644 --- a/fig0_6.cpp +++ b/fig0_6.cpp @@ -28,6 +28,23 @@ #include #include #include +#include + +static std::unordered_set links_seen; + +bool fig0_6_is_complete(int link_key) +{ + bool complete = links_seen.count(link_key); + + if (complete) { + links_seen.clear(); + } + else { + links_seen.insert(link_key); + } + + return complete; +} // map between fig 0/6 database key and LA to detect activation and deactivation of links static std::map fig0_6_key_la; @@ -39,7 +56,7 @@ void fig0_6_cleardb() // FIG 0/6 Service linking information // ETSI EN 300 401 8.1.15 -void fig0_6(fig0_common_t& fig0, int indent) +bool fig0_6(fig0_common_t& fig0, int indent) { uint32_t j; uint16_t LSN, key; @@ -47,6 +64,7 @@ void fig0_6(fig0_common_t& fig0, int indent) char signal_link[256]; char desc[256]; bool Id_list_flag, LA, SH, ILS, Shd; + bool complete = false; uint8_t* f = fig0.f; @@ -58,6 +76,7 @@ void fig0_6(fig0_common_t& fig0, int indent) ILS = (f[i] >> 4) & 0x01; LSN = ((f[i] & 0x0F) << 8) | f[i+1]; key = (fig0.oe() << 15) | (fig0.pd() << 14) | (SH << 13) | (ILS << 12) | LSN; + complete |= fig0_6_is_complete(key); strcpy(signal_link, ""); // check activation / deactivation if ((fig0_6_key_la.count(key) > 0) && (fig0_6_key_la[key] != LA)) { @@ -165,6 +184,7 @@ void fig0_6(fig0_common_t& fig0, int indent) } } } -} + return complete; +} diff --git a/fig0_8.cpp b/fig0_8.cpp index 29fda9a..60f2e0c 100644 --- a/fig0_8.cpp +++ b/fig0_8.cpp @@ -28,10 +28,36 @@ #include #include #include +#include + +/* EN 300 401, 8.1.14.3 Service component label + * The combination of the SId and the SCIdS provides a service component + * identifier which is valid globally. + */ +using SId_t = int; +using SCIdS_t = int; +static std::set > components_seen; + +bool fig0_8_is_complete(SId_t SId, SCIdS_t SCIdS) +{ + auto key = std::make_pair(SId, SCIdS); + bool complete = components_seen.count(key); + + if (complete) { + components_seen.clear(); + } + else { + components_seen.insert(key); + } + + return complete; +} + + // FIG 0/8 Service component global definition // ETSI EN 300 401 6.3.5 -void fig0_8(fig0_common_t& fig0, int indent) +bool fig0_8(fig0_common_t& fig0, int indent) { uint32_t SId; uint16_t SCId; @@ -40,6 +66,7 @@ void fig0_8(fig0_common_t& fig0, int indent) char desc[256]; bool Ext_flag, LS_flag, MSC_FIC_flag; uint8_t* f = fig0.f; + bool complete = false; while (i < (fig0.figlen - (2 + (2 * fig0.pd())))) { // iterate over service component global definition @@ -57,6 +84,7 @@ void fig0_8(fig0_common_t& fig0, int indent) Ext_flag = f[i] >> 7; Rfa = (f[i] >> 4) & 0x7; SCIdS = f[i] & 0x0F; + complete |= fig0_8_is_complete(SId, SCIdS); sprintf(desc, "SId=0x%X, Ext flag=%d 8-bit Rfa %s", SId, Ext_flag, (Ext_flag)?"present":"absent"); if (Rfa != 0) { sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa); @@ -113,5 +141,7 @@ void fig0_8(fig0_common_t& fig0, int indent) } printbuf(desc, indent+1, NULL, 0); } + + return complete; } diff --git a/fig0_9.cpp b/fig0_9.cpp index 9be0a03..5c8271c 100644 --- a/fig0_9.cpp +++ b/fig0_9.cpp @@ -37,7 +37,7 @@ bool LTO_uniq; // FIG 0/9 Country, LTO and International table // ETSI EN 300 401 8.1.3.2 -void fig0_9(fig0_common_t& fig0, int indent) +bool fig0_9(fig0_common_t& fig0, int indent) { uint32_t SId; uint8_t i = 1, j, key, Number_of_services, ECC; @@ -127,5 +127,7 @@ void fig0_9(fig0_common_t& fig0, int indent) } } } + + return true; } diff --git a/fig1.cpp b/fig1.cpp index 1af64de..6bb095c 100644 --- a/fig1.cpp +++ b/fig1.cpp @@ -32,7 +32,7 @@ using namespace std; // SHORT LABELS -void fig1_select(fig1_common_t& fig1, int indent) +bool fig1_select(fig1_common_t& fig1, int indent) { uint16_t ext,oe,charset; uint16_t flag; @@ -60,7 +60,7 @@ void fig1_select(fig1_common_t& fig1, int indent) uint16_t eid; eid = f[1] * 256 + f[2]; sprintf(desc, "Ensemble ID 0x%04X label: \"%s\", Short label mask: 0x%04X", eid, label, flag); - printinfo(desc, indent+1); + printinfo(desc, indent+1, 1); } break; @@ -69,7 +69,7 @@ void fig1_select(fig1_common_t& fig1, int indent) uint16_t sid; sid = f[1] * 256 + f[2]; sprintf(desc, "Service ID 0x%X label: \"%s\", Short label mask: 0x%04X", sid, label, flag); - printinfo(desc, indent+1); + printinfo(desc, indent+1, 1); } break; @@ -92,7 +92,7 @@ void fig1_select(fig1_common_t& fig1, int indent) sprintf(desc, "Service ID 0x%X , Service Component ID 0x%04X Short, label: \"%s\", label mask: 0x%04X", sid, SCIdS, label, flag); - printinfo(desc, indent+1); + printinfo(desc, indent+1, 1); } break; @@ -107,7 +107,7 @@ void fig1_select(fig1_common_t& fig1, int indent) sprintf(desc, "Service ID 0x%X label: \"%s\", Short label mask: 0x%04X", sid, label, flag); - printinfo(desc, indent+1); + printinfo(desc, indent+1, 1); } break; @@ -150,7 +150,8 @@ void fig1_select(fig1_common_t& fig1, int indent) } break; } -} - + // FIG1s always contain a complete set of information + return true; +} diff --git a/figs.cpp b/figs.cpp index 4e7e94c..a1557d7 100644 --- a/figs.cpp +++ b/figs.cpp @@ -74,33 +74,33 @@ void figs_cleardb() } -void fig0_select(fig0_common_t& fig0, int indent) +bool fig0_select(fig0_common_t& fig0, int indent) { switch (fig0.ext()) { - case 0: fig0_0(fig0, indent); break; - case 1: fig0_1(fig0, indent); break; - case 2: fig0_2(fig0, indent); break; - case 3: fig0_3(fig0, indent); break; - case 5: fig0_5(fig0, indent); break; - case 6: fig0_6(fig0, indent); break; - case 8: fig0_8(fig0, indent); break; - case 9: fig0_9(fig0, indent); break; - case 10: fig0_10(fig0, indent); break; - case 11: fig0_11(fig0, indent); break; - case 13: fig0_13(fig0, indent); break; - case 14: fig0_14(fig0, indent); break; - case 16: fig0_16(fig0, indent); break; - case 17: fig0_17(fig0, indent); break; - case 18: fig0_18(fig0, indent); break; - case 19: fig0_19(fig0, indent); break; - case 21: fig0_21(fig0, indent); break; - case 22: fig0_22(fig0, indent); break; - case 24: fig0_24(fig0, indent); break; - case 25: fig0_25(fig0, indent); break; - case 26: fig0_26(fig0, indent); break; - case 27: fig0_27(fig0, indent); break; - case 28: fig0_28(fig0, indent); break; - case 31: fig0_31(fig0, indent); break; + case 0: return fig0_0(fig0, indent); break; + case 1: return fig0_1(fig0, indent); break; + case 2: return fig0_2(fig0, indent); break; + case 3: return fig0_3(fig0, indent); break; + case 5: return fig0_5(fig0, indent); break; + case 6: return fig0_6(fig0, indent); break; + case 8: return fig0_8(fig0, indent); break; + case 9: return fig0_9(fig0, indent); break; + case 10: return fig0_10(fig0, indent); break; + case 11: return fig0_11(fig0, indent); break; + case 13: return fig0_13(fig0, indent); break; + case 14: return fig0_14(fig0, indent); break; + case 16: return fig0_16(fig0, indent); break; + case 17: return fig0_17(fig0, indent); break; + case 18: return fig0_18(fig0, indent); break; + case 19: return fig0_19(fig0, indent); break; + case 21: return fig0_21(fig0, indent); break; + case 22: return fig0_22(fig0, indent); break; + case 24: return fig0_24(fig0, indent); break; + case 25: return fig0_25(fig0, indent); break; + case 26: return fig0_26(fig0, indent); break; + case 27: return fig0_27(fig0, indent); break; + case 28: return fig0_28(fig0, indent); break; + case 31: return fig0_31(fig0, indent); break; default: { char desc[256]; sprintf(desc, "FIG 0/%d: unknown", fig0.ext()); @@ -108,5 +108,7 @@ void fig0_select(fig0_common_t& fig0, int indent) break; } } + + return false; } diff --git a/figs.hpp b/figs.hpp index 7dd92eb..7bd5fd0 100644 --- a/figs.hpp +++ b/figs.hpp @@ -80,34 +80,34 @@ void set_international_table(size_t intl_table); void set_mode_identity(uint8_t mid); uint8_t get_mode_identity(); -void fig0_select(fig0_common_t& fig0, int indent); +bool fig0_select(fig0_common_t& fig0, int indent); -void fig0_0(fig0_common_t& fig0, int indent); -void fig0_1(fig0_common_t& fig0, int indent); -void fig0_2(fig0_common_t& fig0, int indent); -void fig0_3(fig0_common_t& fig0, int indent); -void fig0_5(fig0_common_t& fig0, int indent); +bool fig0_0(fig0_common_t& fig0, int indent); +bool fig0_1(fig0_common_t& fig0, int indent); +bool fig0_2(fig0_common_t& fig0, int indent); +bool fig0_3(fig0_common_t& fig0, int indent); +bool fig0_5(fig0_common_t& fig0, int indent); void fig0_6_cleardb(); -void fig0_6(fig0_common_t& fig0, int indent); -void fig0_8(fig0_common_t& fig0, int indent); -void fig0_9(fig0_common_t& fig0, int indent); -void fig0_10(fig0_common_t& fig0, int indent); -void fig0_11(fig0_common_t& fig0, int indent); -void fig0_13(fig0_common_t& fig0, int indent); -void fig0_14(fig0_common_t& fig0, int indent); -void fig0_16(fig0_common_t& fig0, int indent); -void fig0_17(fig0_common_t& fig0, int indent); -void fig0_18(fig0_common_t& fig0, int indent); -void fig0_19(fig0_common_t& fig0, int indent); -void fig0_21(fig0_common_t& fig0, int indent); +bool fig0_6(fig0_common_t& fig0, int indent); +bool fig0_8(fig0_common_t& fig0, int indent); +bool fig0_9(fig0_common_t& fig0, int indent); +bool fig0_10(fig0_common_t& fig0, int indent); +bool fig0_11(fig0_common_t& fig0, int indent); +bool fig0_13(fig0_common_t& fig0, int indent); +bool fig0_14(fig0_common_t& fig0, int indent); +bool fig0_16(fig0_common_t& fig0, int indent); +bool fig0_17(fig0_common_t& fig0, int indent); +bool fig0_18(fig0_common_t& fig0, int indent); +bool fig0_19(fig0_common_t& fig0, int indent); +bool fig0_21(fig0_common_t& fig0, int indent); void fig0_22_cleardb(); -void fig0_22(fig0_common_t& fig0, int indent); -void fig0_24(fig0_common_t& fig0, int indent); -void fig0_25(fig0_common_t& fig0, int indent); -void fig0_26(fig0_common_t& fig0, int indent); -void fig0_27(fig0_common_t& fig0, int indent); -void fig0_28(fig0_common_t& fig0, int indent); -void fig0_31(fig0_common_t& fig0, int indent); - -void fig1_select(fig1_common_t& fig1, int indent); +bool fig0_22(fig0_common_t& fig0, int indent); +bool fig0_24(fig0_common_t& fig0, int indent); +bool fig0_25(fig0_common_t& fig0, int indent); +bool fig0_26(fig0_common_t& fig0, int indent); +bool fig0_27(fig0_common_t& fig0, int indent); +bool fig0_28(fig0_common_t& fig0, int indent); +bool fig0_31(fig0_common_t& fig0, int indent); + +bool fig1_select(fig1_common_t& fig1, int indent); diff --git a/repetitionrate.cpp b/repetitionrate.cpp new file mode 100644 index 0000000..45dd495 --- /dev/null +++ b/repetitionrate.cpp @@ -0,0 +1,147 @@ +/* + Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Authors: + Matthias P. Braendli + +*/ + +#include "repetitionrate.hpp" +#include +#include +#include + +using namespace std; + +const double frame_duration = 24e-3; + +struct FIGTypeExt { + int figtype; + int figextension; + + bool operator<(const FIGTypeExt& other) const { + if (this->figtype == other.figtype) { + return this->figextension < other.figextension; + } + else { + return this->figtype < other.figtype ; + } + } +}; + +struct FIGRateInfo { + // List of frame numbers in which the FIG is present + vector frames_present; + + // List of frame numbers in which a complete DB for that FIG has been sent + vector frames_complete; + + // Which FIBs this FIG was seen in + unordered_set in_fib; +}; + + +static map fig_rates; + +static int current_frame_number = 0; +static int current_fib = 0; + +void rate_announce_fig(int figtype, int figextension, bool complete) +{ + FIGTypeExt f = {.figtype = figtype, .figextension = figextension}; + + if (fig_rates.count(f) == 0) { + FIGRateInfo rate; + fig_rates[f] = rate; + } + + FIGRateInfo& rate = fig_rates[f]; + + rate.frames_present.push_back(current_frame_number); + if (complete) { + rate.frames_complete.push_back(current_frame_number); + } + rate.in_fib.insert(current_fib); +} + +void rate_disply_analysis() +{ + printf("FIG carousel analysis. Format:\n" + " average FIGs per second (total count, delta variance in frames)\n" + " average complete FIGs per second (total count, delta variance in frames)\n"); + for (auto& fig_rate : fig_rates) { + auto& frames_present = fig_rate.second.frames_present; + auto& frames_complete = fig_rate.second.frames_complete; + + const size_t n_present = frames_present.size(); + const size_t n_complete = frames_complete.size(); + + if (n_present and n_complete) { + double average_present_interval = + (double)(frames_present.back() - frames_present.front()) / + (double)(frames_present.size() - 1); + + double average_complete_interval = + (double)(frames_complete.back() - frames_complete.front()) / + (double)(frames_complete.size() - 1); + + double variance_of_delta_present = 0; + for (size_t i = 1; i < frames_present.size(); i++) { + double s = + (double)(frames_present[i] - frames_present[i-1]) - + average_present_interval; + + variance_of_delta_present += s * s; + } + variance_of_delta_present /= frames_present.size(); + + double variance_of_delta_complete = 0; + for (size_t i = 1; i < frames_complete.size(); i++) { + double s = + (double)(frames_complete[i] - frames_complete[i-1]) - + average_complete_interval; + + variance_of_delta_complete += s * s; + } + variance_of_delta_complete /= frames_complete.size(); + + const double n_present_per_second = + (double)n_present / (double)current_frame_number / frame_duration; + + const double n_complete_per_second = + (double)n_complete / (double)current_frame_number / frame_duration; + + printf("FIG%2d/%2d %2.2f (%6zu %2.2f) %2.2f (%6zu %2.2f)\n", + fig_rate.first.figtype, fig_rate.first.figextension, + n_present_per_second, n_present, variance_of_delta_present, + n_complete_per_second, n_complete, variance_of_delta_complete); + } + else { + printf("FIG%2d/%2d 0\n", + fig_rate.first.figtype, fig_rate.first.figextension); + } + } +} + +void rate_new_fib(int fib) +{ + if (fib == 0) { + current_frame_number++; + } + + current_fib = fib; +} + diff --git a/repetitionrate.hpp b/repetitionrate.hpp new file mode 100644 index 0000000..72d9db4 --- /dev/null +++ b/repetitionrate.hpp @@ -0,0 +1,37 @@ +/* + Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Authors: + Matthias P. Braendli + +*/ + +#pragma once +#include "utils.hpp" + +/* Tell the repetition rate analyser that we have received a given FIG. + * The complete flag should be set to true every time a complete + * set of information for that FIG has been received + */ +void rate_announce_fig(int figtype, int figextension, bool complete); + +/* Tell the repetition rate analyser that a new FIB starts. + */ +void rate_new_fib(int fib); + +/* Print analysis + */ +void rate_disply_analysis(void); diff --git a/utils.hpp b/utils.hpp index 3913f87..5455957 100644 --- a/utils.hpp +++ b/utils.hpp @@ -44,7 +44,7 @@ void printbuf(std::string header, void printinfo(std::string header, int indent_level, - int min_verb = 0); + int min_verb); // sprintfMJD: convert MJD (Modified Julian Date) into date string int sprintfMJD(char *dst, int mjd); -- cgit v1.2.3