aboutsummaryrefslogtreecommitdiffstats
path: root/etisnoop.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2016-01-15 15:03:38 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2016-01-15 15:03:38 +0100
commit3576bfcd68ff58e022efc07ef8e1f1b757ccf6fb (patch)
treedd8b4ae93ce1b87260794022f56cf8892958692a /etisnoop.cpp
parent275b55e39a84a3877e7e68b7c800bd0de28c128c (diff)
downloadetisnoop-3576bfcd68ff58e022efc07ef8e1f1b757ccf6fb.tar.gz
etisnoop-3576bfcd68ff58e022efc07ef8e1f1b757ccf6fb.tar.bz2
etisnoop-3576bfcd68ff58e022efc07ef8e1f1b757ccf6fb.zip
Refactor all FIG0/x into separate files
Diffstat (limited to 'etisnoop.cpp')
-rw-r--r--etisnoop.cpp2331
1 files changed, 12 insertions, 2319 deletions
diff --git a/etisnoop.cpp b/etisnoop.cpp
index 049790d..09f8280 100644
--- a/etisnoop.cpp
+++ b/etisnoop.cpp
@@ -44,9 +44,11 @@
#include <sstream>
#include <time.h>
#include "lib_crc.h"
-
+#include "utils.hpp"
#include "dabplussnoop.h"
#include "etiinput.h"
+#include "figs.hpp"
+#include "watermarkdecoder.hpp"
struct FIG
{
@@ -55,68 +57,6 @@ struct FIG
int len;
};
-class WatermarkDecoder
-{
- public:
- void push_confind_bit(bool confind)
- {
- // The ConfInd of FIG 0/10 contains the CRC-DABMUX and ODR-DabMux watermark
- m_confind_bits.push_back(confind);
- }
-
- std::string calculate_watermark()
- {
- // First try to find the 0x55 0x55 sync in the waternark data
- size_t bit_ix;
- int alternance_count = 0;
- bool last_bit = 1;
- for (bit_ix = 0; bit_ix < m_confind_bits.size(); bit_ix++) {
- if (alternance_count == 16) {
- break;
- }
- else {
- if (last_bit != m_confind_bits[bit_ix]) {
- last_bit = m_confind_bits[bit_ix];
- alternance_count++;
- }
- else {
- alternance_count = 0;
- last_bit = 1;
- }
- }
-
- }
-
- printf("Found SYNC at offset %zu out of %zu\n", bit_ix - alternance_count, m_confind_bits.size());
-
- std::stringstream watermark_ss;
-
- uint8_t b = 0;
- size_t i = 0;
- while (bit_ix < m_confind_bits.size()) {
-
- b |= m_confind_bits[bit_ix] << (7 - i);
-
- if (i == 7) {
- watermark_ss << (char)b;
-
- b = 0;
- i = 0;
- }
- else {
- i++;
- }
-
- bit_ix += 2;
- }
-
- return watermark_ss.str();
- }
-
- private:
- std::vector<bool> m_confind_bits;
-};
-
class FIGalyser
{
public:
@@ -204,167 +144,6 @@ struct FIG0_13_shortAppInfo
uint8_t SCIdS:4;
} PACKED;
-class FIG0_5 {
- public:
- // Constructor
- FIG0_5() {
- // Initialization of Language_code_to_char_map:
- // ETSI TS 101 756 V1.6.1 Table 9: European languages
- Language_code_to_char_map[0x00] = "Unknown/not applicable";
- Language_code_to_char_map[0x01] = "Albanian";
- Language_code_to_char_map[0x02] = "Breton";
- Language_code_to_char_map[0x03] = "Catalan";
- Language_code_to_char_map[0x04] = "Croatian";
- Language_code_to_char_map[0x05] = "Welsh";
- Language_code_to_char_map[0x06] = "Czech";
- Language_code_to_char_map[0x07] = "Danish";
- Language_code_to_char_map[0x08] = "German";
- Language_code_to_char_map[0x09] = "English";
- Language_code_to_char_map[0x0A] = "Spanish";
- Language_code_to_char_map[0x0B] = "Esperanto";
- Language_code_to_char_map[0x0C] = "Estonian";
- Language_code_to_char_map[0x0D] = "Basque";
- Language_code_to_char_map[0x0E] = "Faroese";
- Language_code_to_char_map[0x0F] = "French";
- Language_code_to_char_map[0x10] = "Frisian";
- Language_code_to_char_map[0x11] = "Irish";
- Language_code_to_char_map[0x12] = "Gaelic";
- Language_code_to_char_map[0x13] = "Galician";
- Language_code_to_char_map[0x14] = "Icelandic";
- Language_code_to_char_map[0x15] = "Italian";
- Language_code_to_char_map[0x16] = "Lappish";
- Language_code_to_char_map[0x17] = "Latin";
- Language_code_to_char_map[0x18] = "Latvian";
- Language_code_to_char_map[0x19] = "Luxembourgian";
- Language_code_to_char_map[0x1A] = "Lithuanian";
- Language_code_to_char_map[0x1B] = "Hungarian";
- Language_code_to_char_map[0x1C] = "Maltese";
- Language_code_to_char_map[0x1D] = "Dutch";
- Language_code_to_char_map[0x1E] = "Norwegian";
- Language_code_to_char_map[0x1F] = "Occitan";
- Language_code_to_char_map[0x20] = "Polish";
- Language_code_to_char_map[0x21] = "Portuguese";
- Language_code_to_char_map[0x22] = "Romanian";
- Language_code_to_char_map[0x23] = "Romansh";
- Language_code_to_char_map[0x24] = "Serbian";
- Language_code_to_char_map[0x25] = "Slovak";
- Language_code_to_char_map[0x26] = "Slovene";
- Language_code_to_char_map[0x27] = "Finnish";
- Language_code_to_char_map[0x28] = "Swedish";
- Language_code_to_char_map[0x29] = "Turkish";
- Language_code_to_char_map[0x2A] = "Flemish";
- Language_code_to_char_map[0x2B] = "Walloon";
- Language_code_to_char_map[0x2C] = "rfu";
- Language_code_to_char_map[0x2D] = "rfu";
- Language_code_to_char_map[0x2E] = "rfu";
- Language_code_to_char_map[0x2F] = "rfu";
- Language_code_to_char_map[0x30] = "Reserved for national assignment";
- Language_code_to_char_map[0x31] = "Reserved for national assignment";
- Language_code_to_char_map[0x32] = "Reserved for national assignment";
- Language_code_to_char_map[0x33] = "Reserved for national assignment";
- Language_code_to_char_map[0x34] = "Reserved for national assignment";
- Language_code_to_char_map[0x35] = "Reserved for national assignment";
- Language_code_to_char_map[0x36] = "Reserved for national assignment";
- Language_code_to_char_map[0x37] = "Reserved for national assignment";
- Language_code_to_char_map[0x38] = "Reserved for national assignment";
- Language_code_to_char_map[0x39] = "Reserved for national assignment";
- Language_code_to_char_map[0x3A] = "Reserved for national assignment";
- Language_code_to_char_map[0x3B] = "Reserved for national assignment";
- Language_code_to_char_map[0x3C] = "Reserved for national assignment";
- Language_code_to_char_map[0x3D] = "Reserved for national assignment";
- Language_code_to_char_map[0x3E] = "Reserved for national assignment";
- Language_code_to_char_map[0x3F] = "Reserved for national assignment";
-
- // ETSI TS 101 756 V1.6.1 Table 10: Other languages
- Language_code_to_char_map[0x40] = "Background sound/clean feed";
- Language_code_to_char_map[0x41] = "rfu";
- Language_code_to_char_map[0x42] = "rfu";
- Language_code_to_char_map[0x43] = "rfu";
- Language_code_to_char_map[0x44] = "rfu";
- Language_code_to_char_map[0x45] = "Zulu";
- Language_code_to_char_map[0x46] = "Vietnamese";
- Language_code_to_char_map[0x47] = "Uzbek";
- Language_code_to_char_map[0x48] = "Urdu";
- Language_code_to_char_map[0x49] = "Ukranian";
- Language_code_to_char_map[0x4A] = "Thai";
- Language_code_to_char_map[0x4B] = "Telugu";
- Language_code_to_char_map[0x4C] = "Tatar";
- Language_code_to_char_map[0x4D] = "Tamil";
- Language_code_to_char_map[0x4E] = "Tadzhik";
- Language_code_to_char_map[0x4F] = "Swahili";
- Language_code_to_char_map[0x50] = "Sranan Tongo";
- Language_code_to_char_map[0x51] = "Somali";
- Language_code_to_char_map[0x52] = "Sinhalese";
- Language_code_to_char_map[0x53] = "Shona";
- Language_code_to_char_map[0x54] = "Serbo-Croat";
- Language_code_to_char_map[0x55] = "Rusyn";
- Language_code_to_char_map[0x56] = "Russian";
- Language_code_to_char_map[0x57] = "Quechua";
- Language_code_to_char_map[0x58] = "Pushtu";
- Language_code_to_char_map[0x59] = "Punjabi";
- Language_code_to_char_map[0x5A] = "Persian";
- Language_code_to_char_map[0x5B] = "Papiamento";
- Language_code_to_char_map[0x5C] = "Oriya";
- Language_code_to_char_map[0x5D] = "Nepali";
- Language_code_to_char_map[0x5E] = "Ndebele";
- Language_code_to_char_map[0x5F] = "Marathi";
- Language_code_to_char_map[0x60] = "Moldavian";
- Language_code_to_char_map[0x61] = "Malaysian";
- Language_code_to_char_map[0x62] = "Malagasay";
- Language_code_to_char_map[0x63] = "Macedonian";
- Language_code_to_char_map[0x64] = "Laotian";
- Language_code_to_char_map[0x65] = "Korean";
- Language_code_to_char_map[0x66] = "Khmer";
- Language_code_to_char_map[0x67] = "Kazakh";
- Language_code_to_char_map[0x68] = "Kannada";
- Language_code_to_char_map[0x69] = "Japanese";
- Language_code_to_char_map[0x6A] = "Indonesian";
- Language_code_to_char_map[0x6B] = "Hindi";
- Language_code_to_char_map[0x6C] = "Hebrew";
- Language_code_to_char_map[0x6D] = "Hausa";
- Language_code_to_char_map[0x6E] = "Gurani";
- Language_code_to_char_map[0x6F] = "Gujurati";
- Language_code_to_char_map[0x70] = "Greek";
- Language_code_to_char_map[0x71] = "Georgian";
- Language_code_to_char_map[0x72] = "Fulani";
- Language_code_to_char_map[0x73] = "Dari";
- Language_code_to_char_map[0x74] = "Chuvash";
- Language_code_to_char_map[0x75] = "Chinese";
- Language_code_to_char_map[0x76] = "Burmese";
- Language_code_to_char_map[0x77] = "Bulgarian";
- Language_code_to_char_map[0x78] = "Bengali";
- Language_code_to_char_map[0x79] = "Belorussian";
- Language_code_to_char_map[0x7A] = "Bambora";
- Language_code_to_char_map[0x7B] = "Azerbaijani";
- Language_code_to_char_map[0x7C] = "Assamese";
- Language_code_to_char_map[0x7D] = "Armenian";
- Language_code_to_char_map[0x7E] = "Arabic";
- Language_code_to_char_map[0x7F] = "Amharic";
- }
-
- // Destructor
- ~FIG0_5() {
- // Remove elements from Language_code_to_char_map map container
- Language_code_to_char_map.clear();
- }
-
- // Language_to_char decode fig 0/5 language code in string
- // Input : Language code number
- // Return: Language char *
- const char * Language_to_char(uint8_t language) {
- if (Language_code_to_char_map.count(language) > 0) {
- return Language_code_to_char_map[language];
- }
- else {
- return "";
- }
- }
-
- private:
- // Map between fig 0/5 Language code and Language char
- std::map<uint8_t, const char *> Language_code_to_char_map;
-};
-
#define ETINIPACKETSIZE 6144
@@ -379,152 +158,7 @@ struct eti_analyse_config_t {
};
-// Globals
-static int verbosity;
-static uint8_t Mode_Identity = 0;
-
-// fig 0/2 fig 0/3 DSCTy types string:
-const char *DSCTy_types_str[64] = {
- // ETSI TS 101 756 V1.6.1 (2014-05) table 2
- "Unspecified data", "Traffic Message Channel (TMC)",
- "Emergency Warning System (EWS)", "Interactive Text Transmission System (ITTS)",
- "Paging", "Transparent Data Channel (TDC)",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "MPEG-2 Transport Stream, see ETSI TS 102 427", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Rfu",
- "Rfu", "Embedded IP packets",
- "Multimedia Object Transfer (MOT)", "Proprietary service: no DSCTy signalled",
- "Not used", "Not used"
-};
-
-// map between fig 0/6 database key and LA to detect activation and deactivation of links
-std::map<uint16_t, bool> fig0_6_key_la;
-
-// fig 0/9 global variables
-uint8_t Ensemble_ECC=0, International_Table_Id=0;
-int8_t Ensemble_LTO=0;
-bool LTO_uniq;
-
-// 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] = {
- "no FEC scheme applied",
- "FEC scheme applied according to ETSI EN 300 401 clause 5.3.5",
- "reserved for future definition",
- "reserved for future definition"
-};
-
-// fig 0/17 Programme type codes
-#define INTERNATIONAL_TABLE_SIZE 2
-#define PROGRAMME_TYPE_CODES_SIZE 32
-const char *Programme_type_codes_str[INTERNATIONAL_TABLE_SIZE][PROGRAMME_TYPE_CODES_SIZE] = {
- { // ETSI TS 101 756 V1.6.1 (2014-05) table 12
- "No programme type", "News",
- "Current Affairs", "Information",
- "Sport", "Education",
- "Drama", "Culture",
- "Science", "Varied",
- "Pop Music", "Rock Music",
- "Easy Listening Music", "Light Classical",
- "Serious Classical", "Other Music",
- "Weather/meteorology", "Finance/Business",
- "Children's programmes", "Social Affairs",
- "Religion", "Phone In",
- "Travel", "Leisure",
- "Jazz Music", "Country Music",
- "National Music", "Oldies Music",
- "Folk Music", "Documentary",
- "Not used", "Not used"
- },
- { // ETSI TS 101 756 V1.6.1 (2014-05) table 13
- "No program type", "News",
- "Information", "Sports",
- "Talk", "Rock",
- "Classic Rock", "Adult Hits",
- "Soft Rock", "Top 40",
- "Country", "Oldies",
- "Soft", "Nostalgia",
- "Jazz", "Classical",
- "Rhythm and Blues", "Soft Rhythm and Blues",
- "Foreign Language", "Religious Music",
- "Religious Talk", "Personality",
- "Public", "College",
- "rfu", "rfu",
- "rfu", "rfu",
- "rfu", "Weather",
- "Not used", "Not used"
- }
-};
-
-// fig 0/18 0/19 announcement types (ETSI TS 101 756 V1.6.1 (2014-05) table 14 & 15)
-const char *announcement_types_str[16] = {
- "Alarm",
- "Road Traffic flash",
- "Transport flash",
- "Warning/Service",
- "News flash",
- "Area weather flash",
- "Event announcement",
- "Special event",
- "Programme Information",
- "Sport report",
- "Financial report",
- "Reserved for future definition",
- "Reserved for future definition",
- "Reserved for future definition",
- "Reserved for future definition",
- "Reserved for future definition"
-};
-
-// fig 0/22 struct
-typedef struct lat_lng {
- double latitude, longitude;
-}Lat_Lng;
-// map for fig 0/22 database
-std::map<uint16_t, Lat_Lng> fig0_22_key_Lat_Lng;
-
-// ETSI TS 102 367 V1.2.1 (2006-01) 5.4.1 Conditional Access Mode (CAMode)
-const char *CAMode_str[8] = {
- "Sub-channel CA", "Data Group CA",
- "MOT CA", "proprietary CA",
- "reserved", "reserved",
- "reserved", "reserved"
-};
-
-
// Function prototypes
-void printinfo(string header,
- int indent_level,
- int min_verb=0);
-
-void printbuf(string header,
- int indent_level,
- uint8_t* buffer,
- size_t size,
- string desc="");
-
void decodeFIG(FIGalyser &figs,
WatermarkDecoder &wm_decoder,
uint8_t* figdata,
@@ -535,26 +169,8 @@ void decodeFIG(FIGalyser &figs,
int eti_analyse(eti_analyse_config_t& config);
const char *get_programme_type_str(size_t int_table_Id, size_t pty);
-char *strcatPNum(char *dest_str, uint16_t Programme_Number);
int sprintfMJD(char *dst, int mjd);
-std::string get_fig_0_13_userapp(int user_app_type)
-{
- switch (user_app_type) {
- case 0x000: return "Reserved for future definition";
- case 0x001: return "Not used";
- case 0x002: return "MOT Slideshow";
- case 0x003: return "MOT Broadacst Web Site";
- case 0x004: return "TPEG";
- case 0x005: return "DGPS";
- case 0x006: return "TMC";
- case 0x007: return "EPG";
- case 0x008: return "DAB Java";
- case 0x44a: return "Journaline";
- default: return "Reserved for future applications";
- }
-}
-
#define no_argument 0
#define required_argument 1
#define optional_argument 2
@@ -587,7 +203,6 @@ int main(int argc, char *argv[])
string file_name("-");
map<int, DabPlusSnoop> streams_to_decode;
- verbosity = 0;
bool ignore_error = false;
bool analyse_fic_carousel = false;
bool decode_watermark = false;
@@ -612,7 +227,7 @@ int main(int argc, char *argv[])
analyse_fic_carousel = true;
break;
case 'v':
- verbosity++;
+ set_verbosity(get_verbosity() + 1);
break;
case 'w':
decode_watermark = true;
@@ -809,7 +424,7 @@ int eti_analyse(eti_analyse_config_t& config)
ss << "4";
}
printbuf("MID - Mode Identity", 2, &mid, 1, ss.str());
- Mode_Identity = mid;
+ set_mode_identity(mid);
}
// LIDATA - FC - FL
@@ -991,7 +606,7 @@ int eti_analyse(eti_analyse_config_t& config)
else {
sprintf(sdesc, "id %d, len %d, not selected for decoding", i, stl[i]*8);
}
- if (verbosity > 1) {
+ if (get_verbosity() > 1) {
printbuf("Stream Data", 1, streamdata, stl[i]*8, sdesc);
}
else {
@@ -1030,7 +645,7 @@ int eti_analyse(eti_analyse_config_t& config)
printbuf("TIST - Time Stamp", 1, p+12+4*nst+ficf*ficl*4+offset+4, 4, sdesc);
- if (verbosity) {
+ if (get_verbosity()) {
printf("-------------------------------------------------------------------------------------------------------------\n");
}
}
@@ -1048,9 +663,7 @@ int eti_analyse(eti_analyse_config_t& config)
printf("Watermark:\n %s\n", watermark.c_str());
}
- // remove elements from fig0_6_key_la and fig0_22_key_Lat_Lng map containers
- fig0_6_key_la.clear();
- fig0_22_key_Lat_Lng.clear();
+ figs_cleardb();
return 0;
}
@@ -1063,1812 +676,19 @@ void decodeFIG(FIGalyser &figs,
int indent)
{
char desc[512];
- static FIG0_5 fig0_5;
switch (figtype) {
case 0:
{
- uint16_t ext,cn,oe,pd;
+ fig0_common_t fig0(f, figlen, wm_decoder);
- cn = (f[0] & 0x80) >> 7;
- oe = (f[0] & 0x40) >> 6;
- pd = (f[0] & 0x20) >> 5;
- ext = f[0] & 0x1F;
sprintf(desc, "FIG %d/%d: C/N=%d OE=%d P/D=%d",
- figtype, ext, cn, oe, pd);
+ figtype, fig0.ext(), fig0.cn(), fig0.oe(), fig0.pd());
printbuf(desc, indent, f+1, figlen-1);
- figs.push_back(figtype, ext, figlen);
-
- switch (ext) {
-
- case 0: // FIG 0/0 Ensemble information
- { // ETSI EN 300 401 6.4
- uint8_t cid, al, ch, hic, lowc, occ;
- uint16_t eid, eref;
-
- eid = f[1]*256+f[2];
- cid = (f[1] & 0xF0) >> 4;
- eref = (f[1] & 0x0F)*256 + \
- f[2];
- ch = (f[3] & 0xC0) >> 6;
- al = (f[3] & 0x20) >> 5;
- hic = f[3] & 0x1F;
- lowc = f[4];
- if (ch != 0) {
- occ = f[5];
- sprintf(desc,
- "Ensemble ID=0x%02x (Country id=%d, Ensemble reference=%d), Change flag=%d, Alarm flag=%d, CIF Count=%d/%d, Occurance change=%d",
- eid, cid, eref, ch, al, hic, lowc, occ);
- }
- else {
- sprintf(desc,
- "Ensemble ID=0x%02x (Country id=%d, Ensemble reference=%d), Change flag=%d, Alarm flag=%d, CIF Count=%d/%d",
- eid, cid, eref, ch, al, hic, lowc);
- }
- printbuf(desc, indent+1, NULL, 0);
-
- }
- break;
- case 1: // FIG 0/1 Basic sub-channel organization
- { // ETSI EN 300 401 6.2.1
- int i = 1;
-
- while (i < figlen-3) {
- // iterate over subchannels
- int subch_id = f[i] >> 2;
- int start_addr = ((f[i] & 0x03) << 8) |
- (f[i+1]);
- int long_flag = (f[i+2] >> 7);
-
- if (long_flag) {
- int option = (f[i+2] >> 4) & 0x07;
- int protection_level = (f[i+2] >> 2) & 0x03;
- int subchannel_size = ((f[i+2] & 0x03) << 8 ) |
- f[i+3];
-
- i += 4;
-
- if (option == 0x00) {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, long, EEP %d-A, subch size %d",
- subch_id, start_addr, protection_level, subchannel_size);
- }
- else if (option == 0x01) {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, long, EEP %d-B, subch size %d",
- subch_id, start_addr, protection_level, subchannel_size);
- }
- else {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, long, invalid option %d, protection %d, subch size %d",
- subch_id, start_addr, option, protection_level, subchannel_size);
- }
- }
- else {
- int table_switch = (f[i+2] >> 6) & 0x01;
- uint32_t table_index = (f[i+2] & 0x3F);
-
-
- if (table_switch == 0) {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, short, table index %d",
- subch_id, start_addr, table_index);
- }
- else {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, short, invalid table_switch(=1), table index %d",
- subch_id, start_addr, table_index);
- }
-
- i += 3;
- }
- printbuf(desc, indent+1, NULL, 0);
- }
-
- }
- break;
- case 2: // FIG 0/2 Basic service and service component definition
- { // ETSI EN 300 401 6.3.1
- uint16_t sref, sid;
- uint8_t cid, ecc, local, caid, ncomp, timd, ps, ca, subchid, scty;
- int k=1;
- string psdesc;
- char sctydesc[32];
-
- while (k<figlen) {
- if (pd == 0) {
- sid = f[k] * 256 + f[k+1];
- cid = (f[k] & 0xF0) >> 4;
- sref = (f[k] & 0x0F) * 256 + f[k+1];
- k += 2;
- }
- else {
- sid = f[k] * 256 * 256 * 256 + \
- f[k+1] * 256 * 256 + \
- f[k+2] * 256 + \
- f[k+3];
-
- ecc = f[k];
- cid = (f[k+1] & 0xF0) >> 4;
- sref = (f[k+1] & 0x0F) * 256 * 256 + \
- f[k+2] * 256 + \
- f[k+3];
-
- k += 4;
- }
-
- local = (f[k] & 0x80) >> 7;
- caid = (f[k] & 0x70) >> 4;
- ncomp = f[k] & 0x0F;
-
- if (pd == 0)
- sprintf(desc,
- "Service ID=0x%X (Country id=%d, Service reference=%d), Number of components=%d, Local flag=%d, CAID=%d",
- sid, cid, sref, ncomp, local, caid);
- else
- sprintf(desc,
- "Service ID=0x%X (ECC=%d, Country id=%d, Service reference=%d), Number of components=%d, Local flag=%d, CAID=%d",
- sid, ecc, cid, sref, ncomp, local, caid);
- printbuf(desc, indent+1, NULL, 0);
-
- k++;
- for (int i=0; i<ncomp; i++) {
- uint8_t scomp[2];
-
- memcpy(scomp, f+k, 2);
- sprintf(desc, "Component[%d]", i);
- printbuf(desc, indent+2, scomp, 2, "");
- timd = (scomp[0] & 0xC0) >> 6;
- ps = (scomp[1] & 0x02) >> 1;
- ca = scomp[1] & 0x01;
- scty = scomp[0] & 0x3F;
- subchid = (scomp[1] & 0xFC) >> 2;
-
- /* useless, kept as reference
- if (timd == 3) {
- uint16_t scid;
- scid = scty*64 + subchid;
- }
- */
-
- if (ps == 0) {
- psdesc = "Secondary service";
- }
- else {
- psdesc = "Primary service";
- }
-
-
- if (timd == 0) {
- //MSC stream audio
- if (scty == 0)
- sprintf(sctydesc, "MPEG Foreground sound (%d)", scty);
- else if (scty == 1)
- sprintf(sctydesc, "MPEG Background sound (%d)", scty);
- else if (scty == 2)
- sprintf(sctydesc, "Multi Channel sound (%d)", scty);
- else if (scty == 63)
- sprintf(sctydesc, "AAC sound (%d)", scty);
- else
- sprintf(sctydesc, "Unknown ASCTy (%d)", scty);
-
- sprintf(desc, "Stream audio mode, %s, %s, SubChannel ID=%02X, CA=%d", psdesc.c_str(), sctydesc, subchid, ca);
- printbuf(desc, indent+3, NULL, 0);
- }
- else if (timd == 1) {
- // MSC stream data
- sprintf(sctydesc, "DSCTy=%d %s", scty, DSCTy_types_str[scty]);
- sprintf(desc, "Stream data mode, %s, %s, SubChannel ID=%02X, CA=%d", psdesc.c_str(), sctydesc, subchid, ca);
- printbuf(desc, indent+3, NULL, 0);
- }
- else if (timd == 2) {
- // FIDC
- sprintf(sctydesc, "DSCTy=%d %s", scty, DSCTy_types_str[scty]);
- sprintf(desc, "FIDC mode, %s, %s, Fast Information Data Channel ID=%02X, CA=%d", psdesc.c_str(), sctydesc, subchid, ca);
- printbuf(desc, indent+3, NULL, 0);
- }
- else if (timd == 3) {
- // MSC Packet mode
- sprintf(desc, "MSC Packet Mode, %s, Service Component ID=%02X, CA=%d", psdesc.c_str(), subchid, ca);
- printbuf(desc, indent+3, NULL, 0);
- }
- k += 2;
- }
- }
- }
- break;
- case 3: // FIG 0/3 Service component in packet mode with or without Conditional Access
- { // ETSI EN 300 401 6.3.2
- uint16_t SCId, Packet_address, CAOrg;
- uint8_t i = 1, Rfa, DSCTy, SubChId, CAMode, SharedFlag;
- char tmpbuf[256];
- bool CAOrg_flag, DG_flag, Rfu;
-
- while (i < (figlen - 4)) {
- // iterate over service component in packet mode
- SCId = ((uint16_t)f[i] << 4) | ((uint16_t)(f[i+1] >> 4) & 0x0F);
- Rfa = (f[i+1] >> 1) & 0x07;
- CAOrg_flag = f[i+1] & 0x01;
- DG_flag = (f[i+2] >> 7) & 0x01;
- Rfu = (f[i+2] >> 6) & 0x01;
- DSCTy = f[i+2] & 0x3F;
- SubChId = (f[i+3] >> 2);
- Packet_address = ((uint16_t)(f[i+3] & 0x03) << 8) | ((uint16_t)f[i+4]);
- sprintf(desc, "SCId=0x%X, CAOrg flag=%d CAOrg field %s, DG flag=%d data groups are %sused to transport the service component, DSCTy=%d %s, SubChId=0x%X, Packet address=0x%X",
- SCId, CAOrg_flag, CAOrg_flag?"present":"absent", DG_flag, DG_flag?"not ":"", DSCTy, DSCTy_types_str[DSCTy], SubChId, Packet_address);
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- i += 5;
- if (CAOrg_flag) {
- if (i < (figlen - 1)) {
- CAOrg = ((uint16_t)f[i] << 8) | ((uint16_t)f[i+1]);
- CAMode = (f[i] >> 5);
- SharedFlag = f[i+1];
- sprintf(tmpbuf, ", CAOrg=0x%X CAMode=%d \"%s\" SharedFlag=0x%X%s",
- CAOrg, CAMode, CAMode_str[CAMode], SharedFlag, (SharedFlag == 0)?" invalid":"");
- strcat(desc, tmpbuf);
- }
- else {
- sprintf(tmpbuf, ", invalid figlen");
- strcat(desc, tmpbuf);
- }
- i += 2;
- }
- printbuf(desc, indent+1, NULL, 0);
- }
- }
- break;
- case 5: // FIG 0/5 Service component language
- { // ETSI EN 300 401 8.1.2
- uint16_t SCId;
- uint8_t i = 1, SubChId, FIDCId, Language, Rfa;
- char tmpbuf[256];
- bool LS_flag, MSC_FIC_flag;
-
- while (i < (figlen - 1)) {
- // iterate over service component language
- LS_flag = f[i] >> 7;
- if (LS_flag == 0) {
- // Short form (L/S = 0)
- MSC_FIC_flag = (f[i] >> 6) & 0x01;
- Language = f[i+1];
- if (MSC_FIC_flag == 0) {
- // 0: MSC in Stream mode and SubChId identifies the sub-channel
- SubChId = f[i] & 0x3F;
- sprintf(desc, "L/S flag=%d short form, MSC/FIC flag=%d MSC, SubChId=0x%X, Language=0x%X %s",
- LS_flag, MSC_FIC_flag, SubChId, Language, fig0_5.Language_to_char(Language));
- }
- else {
- // 1: FIC and FIDCId identifies the component
- FIDCId = f[i] & 0x3F;
- sprintf(desc, "L/S flag=%d short form, MSC/FIC flag=%d FIC, FIDCId=0x%X, Language=0x%X %s",
- LS_flag, MSC_FIC_flag, FIDCId, Language, fig0_5.Language_to_char(Language));
- }
- printbuf(desc, indent+1, NULL, 0);
- i += 2;
- }
- else {
- // Long form (L/S = 1)
- if (i < (figlen - 2)) {
- Rfa = (f[i] >> 4) & 0x07;
- SCId = (((uint16_t)f[i] & 0x0F) << 8) | (uint16_t)f[i+1];
- Language = f[i+2];
- sprintf(desc, "L/S flag=%d long form", LS_flag);
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", SCId=0x%X, Language=0x%X %s",
- SCId, Language, fig0_5.Language_to_char(Language));
- strcat(desc, tmpbuf);
- printbuf(desc, indent+1, NULL, 0);
- }
- i += 3;
- }
- }
- }
- break;
- case 6: // FIG 0/6 Service linking information
- { // ETSI EN 300 401 8.1.15
- uint32_t j;
- uint16_t LSN, key;
- uint8_t i = 1, Number_of_Ids, IdLQ;
- char signal_link[256];
- bool Id_list_flag, LA, SH, ILS, Shd;
-
- while (i < (figlen - 1)) {
- // iterate over service linking
- Id_list_flag = (f[i] >> 7) & 0x01;
- LA = (f[i] >> 6) & 0x01;
- SH = (f[i] >> 5) & 0x01;
- ILS = (f[i] >> 4) & 0x01;
- LSN = ((f[i] & 0x0F) << 8) | f[i+1];
- key = (oe << 15) | (pd << 14) | (SH << 13) | (ILS << 12) | LSN;
- strcpy(signal_link, "");
- // check activation / deactivation
- if ((fig0_6_key_la.count(key) > 0) && (fig0_6_key_la[key] != LA)) {
- if (LA == 0) {
- strcat(signal_link, " deactivated");
- }
- else {
- strcat(signal_link, " activated");
- }
- }
- fig0_6_key_la[key] = LA;
- i += 2;
- if (Id_list_flag == 0) {
- if (cn == 0) { // Id_list_flag=0 && cn=0: CEI Change Event Indication
- strcat(signal_link, " CEI");
- }
- sprintf(desc, "Id list flag=%d, LA=%d %s, S/H=%d %s, ILS=%d %s, LSN=%d, database key=0x%04x%s",
- Id_list_flag, LA, (LA)?"active":"inactive", SH, (SH)?"Hard":"Soft", ILS, (ILS)?"international":"national", LSN, key, signal_link);
- printbuf(desc, indent+1, NULL, 0);
- }
- else { // Id_list_flag == 1
- if (i < figlen) {
- Number_of_Ids = (f[i] & 0x0F);
- if (pd == 0) {
- IdLQ = (f[i] >> 5) & 0x03;
- Shd = (f[i] >> 4) & 0x01;
- sprintf(desc, "Id list flag=%d, LA=%d %s, S/H=%d %s, ILS=%d %s, LSN=%d, database key=0x%04x, IdLQ=%d, Shd=%d %s, Number of Ids=%d%s",
- Id_list_flag, LA, (LA)?"active":"inactive", SH, (SH)?"Hard":"Soft", ILS, (ILS)?"international":"national", LSN, key, IdLQ, Shd, (Shd)?"b11-8 in 4-F are different services":"single service", Number_of_Ids, signal_link);
- printbuf(desc, indent+1, NULL, 0);
- if (ILS == 0) {
- // read Id list
- for(j = 0; ((j < Number_of_Ids) && ((i+2+(j*2)) < figlen)); j++) {
- // ETSI EN 300 401 8.1.15:
- // The IdLQ shall not apply to the first entry in the Id list when OE = "0" and
- // when the version number of the type 0 field is set to "0" (using the C/N flag, see clause 5.2.2.1)
- // ... , the first entry in the Id list of each Service linking field shall be
- // the SId that applies to the service in the ensemble.
- if (((j == 0) && (oe == 0) && (cn == 0)) ||
- (IdLQ == 0)) {
- sprintf(desc, "DAB SId 0x%X", ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
- }
- else if (IdLQ == 1) {
- sprintf(desc, "RDS PI 0x%X", ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
- }
- else if (IdLQ == 2) {
- sprintf(desc, "AM-FM service 0x%X", ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
- }
- else { // IdLQ == 3
- sprintf(desc, "invalid ILS IdLQ configuration");
- }
- printbuf(desc, indent+2, NULL, 0);
- }
- // check deadlink
- if ((Number_of_Ids == 0) && (IdLQ == 1)) {
- sprintf(desc, "deadlink");
- printbuf(desc, indent+2, NULL, 0);
- }
- i += (Number_of_Ids * 2) + 1;
- }
- else { // pd == 0 && ILS == 1
- // read Id list
- for(j = 0; ((j < Number_of_Ids) && ((i+3+(j*3)) < figlen)); j++) {
- // ETSI EN 300 401 8.1.15:
- // The IdLQ shall not apply to the first entry in the Id list when OE = "0" and
- // when the version number of the type 0 field is set to "0" (using the C/N flag, see clause 5.2.2.1)
- // ... , the first entry in the Id list of each Service linking field shall be
- // the SId that applies to the service in the ensemble.
- if (((j == 0) && (oe == 0) && (cn == 0)) ||
- (IdLQ == 0)) {
- sprintf(desc, "DAB SId ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
- }
- else if (IdLQ == 1) {
- sprintf(desc, "RDS PI ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
- }
- else if (IdLQ == 2) {
- sprintf(desc, "AM-FM service ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
- }
- else { // IdLQ == 3
- sprintf(desc, "DRM/AMSS service ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
- }
- printbuf(desc, indent+2, NULL, 0);
- }
- // check deadlink
- if ((Number_of_Ids == 0) && (IdLQ == 1)) {
- sprintf(desc, "deadlink");
- printbuf(desc, indent+2, NULL, 0);
- }
- i += (Number_of_Ids * 3) + 1;
- }
- }
- else { // pd == 1
- sprintf(desc, "Id list flag=%d, LA=%d %s, S/H=%d %s, ILS=%d %s, LSN=%d, database key=0x%04x, Number of Ids=%d%s",
- Id_list_flag, LA, (LA)?"active":"inactive", SH, (SH)?"Hard":"Soft", ILS, (ILS)?"international":"national", LSN, key, Number_of_Ids, signal_link);
- printbuf(desc, indent+1, NULL, 0);
- if (Number_of_Ids > 0) {
- // read Id list
- for(j = 0; ((j < Number_of_Ids) && ((i+4+(j*4)) < figlen)); j++) {
- sprintf(desc, "SId 0x%X",
- ((f[i+1+(j*4)] << 24) | (f[i+2+(j*4)] << 16) | (f[i+3+(j*4)] << 8) | f[i+4+(j*4)]));
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- i += (Number_of_Ids * 4) + 1;
- }
- }
- }
- }
- }
- break;
- case 8: // FIG 0/8 Service component global definition
- { // ETSI EN 300 401 6.3.5
- uint32_t SId;
- uint16_t SCId;
- uint8_t i = 1, Rfa, SCIdS, SubChId, FIDCId;
- char tmpbuf[256];
- bool Ext_flag, LS_flag, MSC_FIC_flag;
-
- while (i < (figlen - (2 + (2 * pd)))) {
- // iterate over service component global definition
- if (pd == 0) {
- // Programme services, 16 bit SId
- SId = (f[i] << 8) | f[i+1];
- i += 2;
- }
- else {
- // Data services, 32 bit SId
- SId = ((uint32_t)f[i] << 24) | ((uint32_t)f[i+1] << 16) |
- ((uint32_t)f[i+2] << 8) | (uint32_t)f[i+3];
- i += 4;
- }
- Ext_flag = f[i] >> 7;
- Rfa = (f[i] >> 4) & 0x7;
- SCIdS = f[i] & 0x0F;
- 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);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", SCIdS=0x%X", SCIdS);
- strcat(desc, tmpbuf);
- i++;
- if (i < figlen) {
- LS_flag = f[i] >> 7;
- sprintf(tmpbuf, ", L/S flag=%d %s", LS_flag, (LS_flag)?"Long form":"Short form");
- strcat(desc, tmpbuf);
- if (LS_flag == 0) {
- // Short form
- if (i < (figlen - Ext_flag)) {
- MSC_FIC_flag = (f[i] >> 6) & 0x01;
- if (MSC_FIC_flag == 0) {
- // MSC in stream mode and SubChId identifies the sub-channel
- SubChId = f[i] & 0x3F;
- sprintf(tmpbuf, ", MSC/FIC flag=%d MSC, SubChId=0x%X", MSC_FIC_flag, SubChId);
- strcat(desc, tmpbuf);
- }
- else {
- // FIC and FIDCId identifies the component
- FIDCId = f[i] & 0x3F;
- sprintf(tmpbuf, ", MSC/FIC flag=%d FIC, FIDCId=0x%X", MSC_FIC_flag, FIDCId);
- strcat(desc, tmpbuf);
- }
- if (Ext_flag == 1) {
- // Rfa field present
- Rfa = f[i+1];
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- }
- }
- i += (1 + Ext_flag);
- }
- else {
- // Long form
- if (i < (figlen - 1)) {
- Rfa = (f[i] >> 4) & 0x07;
- SCId = (((uint16_t)f[i] & 0x0F) << 8) | (uint16_t)f[i+1];
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", SCId=0x%X", SCId);
- strcat(desc, tmpbuf);
- }
- i += 2;
- }
- }
- printbuf(desc, indent+1, NULL, 0);
- }
- }
- break;
- case 9: // FIG 0/9 Country, LTO and International table
- { // ETSI EN 300 401 8.1.3.2
- uint32_t SId;
- uint8_t i = 1, j, key, Number_of_services, ECC;
- int8_t LTO;
- char tmpbuf[256];
- bool Ext_flag;
-
- if (i < (figlen - 2)) {
- // get Ensemble LTO, ECC and International Table Id
- key = ((uint8_t)oe << 1) | (uint8_t)pd;
- Ext_flag = f[i] >> 7;
- LTO_uniq = (f[i]>> 6) & 0x01;
- Ensemble_LTO = f[i] & 0x3F;
- if (Ensemble_LTO & 0x20) {
- // negative Ensemble LTO
- Ensemble_LTO |= 0xC0;
- }
- sprintf(desc, "Ext flag=%d extended field %s, LTO uniq=%d %s, Ensemble LTO=0x%X %s%d:%02d",
- Ext_flag, Ext_flag?"present":"absent", LTO_uniq,
- LTO_uniq?"several time zones":"one time zone (time specified by Ensemble LTO)",
- (Ensemble_LTO & 0x3F), (Ensemble_LTO >= 0)?"":"-" , abs(Ensemble_LTO) >> 1, (Ensemble_LTO & 0x01) * 30);
- if (abs(Ensemble_LTO) > 24) {
- sprintf(tmpbuf, " out of range -12 hours to +12 hours");
- strcat(desc, tmpbuf);
- }
- Ensemble_ECC = f[i+1];
- International_Table_Id = f[i+2];
- sprintf(tmpbuf, ", Ensemble ECC=0x%X, International Table Id=0x%X, database key=0x%x",
- Ensemble_ECC, International_Table_Id, key);
- strcat(desc, tmpbuf);
- printbuf(desc, indent+1, NULL, 0);
- i += 3;
- if (Ext_flag == 1) {
- // extended field present
- while (i < figlen) {
- // iterate over extended sub-field
- Number_of_services = f[i] >> 6;
- LTO = f[i] & 0x3F;
- if (LTO & 0x20) {
- // negative LTO
- LTO |= 0xC0;
- }
- sprintf(desc, "Number of services=%d, LTO=0x%X %s%d:%02d",
- Number_of_services, (LTO & 0x3F), (LTO >= 0)?"":"-" , abs(LTO) >> 1, (LTO & 0x01) * 30);
- if (abs(LTO) > 24) {
- sprintf(tmpbuf, " out of range -12 hours to +12 hours");
- strcat(desc, tmpbuf);
- }
- // CEI Change Event Indication
- if ((Number_of_services == 0) && (LTO == 0) /* && (Ext_flag == 1) */) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
- }
- i++;
- if (pd == 0) {
- // Programme services, 16 bit SId
- if (i < figlen) {
- ECC = f[i];
- sprintf(tmpbuf, ", ECC=0x%X", ECC);
- strcat(desc, tmpbuf);
- printbuf(desc, indent+2, NULL, 0);
- i++;
- for(j = i; ((j < (i + (Number_of_services * 2))) && (j < figlen)); j += 2) {
- // iterate over SId
- SId = ((uint32_t)f[j] << 8) | (uint32_t)f[j+1];
- sprintf(desc, "SId 0x%X", SId);
- printbuf(desc, indent+3, NULL, 0);
- }
- i += (Number_of_services * 2);
- }
- }
- else {
- // Data services, 32 bit SId
- printbuf(desc, indent+2, NULL, 0);
- for(j = i; ((j < (i + (Number_of_services * 4))) && (j < figlen)); j += 4) {
- // iterate over SId
- SId = ((uint32_t)f[j] << 24) | ((uint32_t)f[j+1] << 16) |
- ((uint32_t)f[j+2] << 8) | (uint32_t)f[j+3];
- sprintf(desc, "SId 0x%X", SId);
- printbuf(desc, indent+3, NULL, 0);
- }
- i += (Number_of_services * 4);
- }
- }
- }
- }
- }
- break;
- case 10: // FIG 0/10 Date and time
- { // ETSI EN 300 401 8.1.3.1
- char dateStr[256];
- dateStr[0] = 0;
-
- //bool RFU = f[1] >> 7;
-
- uint32_t MJD = (((uint32_t)f[1] & 0x7F) << 10) |
- ((uint32_t)(f[2]) << 2) |
- (f[3] >> 6);
- sprintfMJD(dateStr, MJD);
-
- bool LSI = f[3] & 0x20;
- bool ConfInd = f[3] & 0x10;
- wm_decoder.push_confind_bit(ConfInd);
- bool UTC = f[3] & 0x8;
-
- uint8_t hours = ((f[3] & 0x7) << 2) |
- ( f[4] >> 6);
+ figs.push_back(figtype, fig0.ext(), figlen);
- uint8_t minutes = f[4] & 0x3f;
-
- if (UTC) {
- uint8_t seconds = f[5] >> 2;
- uint16_t milliseconds = ((uint16_t)(f[5] & 0x2) << 8) | f[6];
-
- sprintf(desc, "FIG %d/%d(long): MJD=0x%X %s, LSI %u, ConfInd %u, UTC Time: %02d:%02d:%02d.%d",
- figtype, ext, MJD, dateStr, LSI, ConfInd, hours, minutes, seconds, milliseconds);
- printbuf(desc, indent+1, NULL, 0);
- }
- else {
- sprintf(desc, "FIG %d/%d(short): MJD=0x%X %s, LSI %u, ConfInd %u, UTC Time: %02d:%02d",
- figtype, ext, MJD, dateStr, LSI, ConfInd, hours, minutes);
- printbuf(desc, indent+1, NULL, 0);
- }
- }
- break;
- case 11: // FIG 0/11 Region definition
- { // ETSI EN 300 401 8.1.16.1
- Lat_Lng gps_pos = {0, 0};
- int16_t Latitude_coarse, Longitude_coarse;
- uint16_t Region_Id, Extent_Latitude, Extent_Longitude, key;
- uint8_t i = 1, j, k, GATy, Rfu, Length_TII_list, Rfa, MainId, Length_SubId_list, SubId;
- int8_t bit_pos;
- char tmpbuf[256];
- bool GE_flag;
-
- while (i < (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]);
- key = ((uint16_t)oe << 12) | ((uint16_t)pd << 11) | Region_Id;
- i += 2;
- if (GATy == 0) {
- // TII list
- sprintf(desc, "GATy=%d Geographical area defined by a TII list, G/E flag=%d %s coverage area, RegionId=0x%X, database key=0x%X",
- GATy, GE_flag, GE_flag?"Global":"Ensemble", Region_Id, key);
- if (i < figlen) {
- Rfu = f[i] >> 5;
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- Length_TII_list = f[i] & 0x1F;
- sprintf(tmpbuf, ", Length of TII list=%d", Length_TII_list);
- strcat(desc, tmpbuf);
- if (Length_TII_list == 0) {
- strcat(desc, ", CEI");
- }
- printbuf(desc, indent+1, NULL, 0);
- i++;
-
- for(j = 0;(i < (figlen - 1)) && (j < Length_TII_list); j++) {
- // iterate over Transmitter group
- Rfa = f[i] >> 7;
- MainId = f[i] & 0x7F;
- if (Rfa != 0) {
- sprintf(desc, "Rfa=%d invalid value, MainId=0x%X",
- Rfa, MainId);
- }
- else {
- sprintf(desc, "MainId=0x%X", MainId);
- }
- // check MainId value
- if ((Mode_Identity == 1) || (Mode_Identity == 2) || (Mode_Identity == 4)) {
- if (MainId > 69) {
- // The coding range shall be 0 to 69 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
- }
- }
- else if (Mode_Identity == 3) {
- if (MainId > 5) {
- // The coding range shall be 0 to 5 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
- }
- }
- Rfa = f[i+1] >> 5;
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- Length_SubId_list = f[i+1] & 0x1F;
- sprintf(tmpbuf, ", Length of SubId=%d", Length_SubId_list);
- strcat(desc, tmpbuf);
- printbuf(desc, indent+2, NULL, 0);
- i += 2;
-
- bit_pos = 3;
- SubId = 0;
- for(k = 0;(i < figlen) && (k < Length_SubId_list); k++) {
- // iterate SubId
- if (bit_pos >= 0) {
- SubId |= (f[i] >> bit_pos) & 0x1F;
- sprintf(desc, "SubId=0x%X", SubId);
- // check SubId value
- if ((SubId == 0) || (SubId > 23)) {
- strcat(desc, " invalid value");
- }
- printbuf(desc, indent+3, NULL, 0);
- bit_pos -= 5;
- SubId = 0;
- }
- if (bit_pos < 0) {
- SubId = (f[i] << abs(bit_pos)) & 0x1F;
- bit_pos += 8;
- i++;
- }
- }
- if (bit_pos > 3) {
- // jump padding
- i++;
- }
- if (k < Length_SubId_list) {
- sprintf(desc, "%d SubId missing, fig length too short !", (Length_SubId_list - k));
- printbuf(desc, indent+3, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
- }
- if (j < Length_TII_list) {
- sprintf(desc, "%d Transmitter group missing, fig length too short !", (Length_TII_list - j));
- printbuf(desc, indent+2, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
- }
- }
- else if (GATy == 1) {
- // Coordinates
- sprintf(desc, "GATy=%d Geographical area defined as a spherical rectangle by the geographical co-ordinates of one corner and its latitude and longitude extents, G/E flag=%d %s coverage area, RegionId=0x%X, database key=0x%X",
- GATy, GE_flag, GE_flag?"Global":"Ensemble", Region_Id, key);
- if (i < (figlen - 6)) {
- Latitude_coarse = ((int16_t)f[i] << 8) | ((uint16_t)f[i+1]);
- Longitude_coarse = ((int16_t)f[i+2] << 8) | ((uint16_t)f[i+3]);
- gps_pos.latitude = ((double)Latitude_coarse) * 90 / 32768;
- gps_pos.longitude = ((double)Latitude_coarse) * 180 / 32768;
- sprintf(tmpbuf, ", Lat Lng coarse=0x%X 0x%X => %f, %f",
- Latitude_coarse, Longitude_coarse, gps_pos.latitude, gps_pos.longitude);
- strcat(desc, tmpbuf);
- Extent_Latitude = ((uint16_t)f[i+4] << 4) | ((uint16_t)(f[i+5] >> 4));
- Extent_Longitude = ((uint16_t)(f[i+5] & 0x0F) << 8) | ((uint16_t)f[i+6]);
- gps_pos.latitude += ((double)Extent_Latitude) * 90 / 32768;
- gps_pos.longitude += ((double)Extent_Longitude) * 180 / 32768;
- sprintf(tmpbuf, ", Extent Lat Lng=0x%X 0x%X => %f, %f",
- Extent_Latitude, Extent_Longitude, gps_pos.latitude, gps_pos.longitude);
- strcat(desc, tmpbuf);
- }
- else {
- sprintf(tmpbuf, ", Coordinates missing, fig length too short !");
- strcat(desc, tmpbuf);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
- printbuf(desc, indent+1, NULL, 0);
- i += 7;
- }
- else {
- // Rfu
- sprintf(desc, "GATy=%d reserved for future use of the geographical, G/E flag=%d %s coverage area, RegionId=0x%X, database key=0x%X, stop Region definition iteration %d/%d",
- GATy, GE_flag, GE_flag?"Global":"Ensemble", Region_Id, key, i, figlen);
- printbuf(desc, indent+1, NULL, 0);
- // stop Region definition iteration
- i = figlen;
- }
- }
- }
- break;
- case 13: // FIG 0/13 User application information
- { // ETSI EN 300 401 8.1.20
- uint32_t SId;
- uint8_t SCIdS;
- uint8_t No;
-
- int k = 1;
-
- if (pd == 0) { // Programme services, 16 bit SId
- SId = (f[k] << 8) |
- f[k+1];
- k+=2;
-
- SCIdS = f[k] >> 4;
- No = f[k] & 0x0F;
- k++;
- }
- else { // Data services, 32 bit SId
- SId = (f[k] << 24) |
- (f[k+1] << 16) |
- (f[k+2] << 8) |
- f[k+3];
- k+=4;
-
- SCIdS = f[k] >> 4;
- No = f[k] & 0x0F;
- k++;
-
- }
-
- sprintf(desc, "FIG %d/%d: SId=0x%X SCIdS=%u No=%u",
- figtype, ext, SId, SCIdS, No);
- printbuf(desc, indent+1, NULL, 0);
-
- for (int numapp = 0; numapp < No; numapp++) {
- uint16_t user_app_type = ((f[k] << 8) |
- (f[k+1] & 0xE0)) >> 5;
- uint8_t user_app_len = f[k+1] & 0x1F;
- k+=2;
-
- sprintf(desc, "User Application %d '%s'; length %u",
- user_app_type,
- get_fig_0_13_userapp(user_app_type).c_str(),
- user_app_len);
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- break;
- case 14: // FIG 0/14 FEC sub-channel organization
- { // ETSI EN 300 401 6.2.2
- uint8_t i = 1, SubChId, FEC_scheme;
-
- while (i < figlen) {
- // iterate over Sub-channel
- SubChId = f[i] >> 2;
- 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++;
- }
- }
- break;
- case 16: // FIG 0/16 Programme Number & OE Programme Number
- { // ETSI EN 300 401 8.1.4 & 8.1.10.3
- uint16_t SId, PNum, New_SId, New_PNum;
- uint8_t i = 1, Rfa, Rfu;
- char tmpbuf[256];
- bool Continuation_flag, Update_flag;
-
- while (i < (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]);
- Rfa = f[i+4] >> 6;
- Rfu = (f[i+4] >> 2) & 0x0F;
- Continuation_flag = (f[i+4] >> 1) & 0x01;
- Update_flag = f[i+4] & 0x01;
-
- sprintf(desc, "SId=0x%X, PNum=0x%X ", SId, PNum);
- // Append PNum decoded string
- strcatPNum(desc, PNum);
-
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
-
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=0x%X invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
-
- sprintf(tmpbuf, ", Continuation flag=%d the programme will %s, Update flag=%d %sre-direction",
- Continuation_flag, Continuation_flag?"be interrupted but continued later":"not be subject to a planned interruption",
- Update_flag, Update_flag?"":"no ");
- strcat(desc, tmpbuf);
- i += 5;
-
- if (Update_flag != 0) {
- // In the case of a re-direction, the New SId and New PNum shall be appended
- if (i < (figlen - 1)) {
- New_SId = ((uint16_t)f[i] << 8) | ((uint16_t)f[i+1]);
- sprintf(tmpbuf, ", New SId=0x%X", New_SId);
- strcat(desc, tmpbuf);
- if (i < (figlen - 3)) {
- New_PNum = ((uint16_t)f[i+2] << 8) | ((uint16_t)f[i+3]);
- sprintf(tmpbuf, ", New PNum=0x%X ", New_PNum);
- strcat(desc, tmpbuf);
- // Append New_PNum decoded string
- strcatPNum(desc, New_PNum);
- }
- else {
- sprintf(tmpbuf, ", missing New PNum !");
- strcat(desc, tmpbuf);
- }
- }
- else {
- sprintf(tmpbuf, ", missing New SId and New PNum !");
- strcat(desc, tmpbuf);
- }
- i += 4;
- }
-
- printbuf(desc, indent+1, NULL, 0);
- }
- }
- break;
- case 17: // FIG 0/17 Programme Type
- { // ETSI EN 300 401 8.1.5
- uint16_t SId;
- uint8_t i = 1, Rfa, Language, Int_code, Comp_code;
- char tmpbuf[256];
- bool SD_flag, PS_flag, L_flag, CC_flag, Rfu;
- while (i < (figlen - 3)) {
- // iterate over announcement support
- SId = (f[i] << 8) | f[i+1];
- SD_flag = (f[i+2] >> 7);
- PS_flag = ((f[i+2] >> 6) & 0x01);
- L_flag = ((f[i+2] >> 5) & 0x01);
- CC_flag = ((f[i+2] >> 4) & 0x01);
- Rfa = (f[i+2] & 0x0F);
- sprintf(desc, "SId=0x%X, S/D=%d Programme Type codes and language (when present), %srepresent the current programme contents, P/S=%d %s service component, L flag=%d language field %s, CC flag=%d complementary code and preceding Rfa and Rfu fields %s",
- SId, SD_flag, SD_flag?"":"may not ", PS_flag, PS_flag?"secondary":"primary",
- L_flag, L_flag?"present":"absent", CC_flag, CC_flag?"present":"absent");
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- i += 3;
- if (L_flag != 0) {
- if (i < figlen) {
- Language = f[i];
- sprintf(tmpbuf, ", Language=0x%X %s", Language,
- fig0_5.Language_to_char(Language));
- strcat(desc, tmpbuf);
- }
- else {
- sprintf(tmpbuf, ", Language= invalid FIG length");
- strcat(desc, tmpbuf);
- }
- i++;
- }
- if (i < figlen) {
- Rfa = f[i] >> 6;
- Rfu = (f[i] >> 5) & 0x01;
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- Int_code = f[i] & 0x1F;
- sprintf(tmpbuf, ", Int code=0x%X %s", Int_code, get_programme_type_str(International_Table_Id , Int_code));
- strcat(desc, tmpbuf);
- i++;
- }
- else {
- sprintf(tmpbuf, ", Int code= invalid FIG length");
- strcat(desc, tmpbuf);
- }
- if (CC_flag != 0) {
- if (i < figlen) {
- Rfa = f[i] >> 6;
- Rfu = (f[i] >> 5) & 0x01;
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- Comp_code = f[i] & 0x1F;
- sprintf(tmpbuf, ", Comp code=0x%X %s", Comp_code, get_programme_type_str(International_Table_Id , Comp_code));
- strcat(desc, tmpbuf);
- i++;
- }
- else {
- sprintf(tmpbuf, ", Comp code= invalid FIG length");
- strcat(desc, tmpbuf);
- }
- }
- printbuf(desc, indent+1, NULL, 0);
- }
- }
- break;
- case 18: // FIG 0/18 Announcement support
- { // ETSI EN 300 401 8.1.6.1
- uint32_t key;
- uint16_t SId, Asu_flags;
- uint8_t i = 1, j, Rfa, Number_clusters;
- char tmpbuf[256];
-
- while (i < (figlen - 4)) {
- // iterate over announcement support
- // SId, Asu flags, Rfa, Number of clusters
- SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- Asu_flags = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3];
- Rfa = (f[i+4] >> 5);
- Number_clusters = (f[i+4] & 0x1F);
- sprintf(desc, "SId=0x%X, Asu flags=0x%04x", SId, Asu_flags);
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Number of clusters=%d", Number_clusters);
- strcat(desc, tmpbuf);
- key = ((uint32_t)oe << 17) | ((uint32_t)pd << 16) | (uint32_t)SId;
- sprintf(tmpbuf, ", database key=0x%05x", key);
- strcat(desc, tmpbuf);
- // CEI Change Event Indication
- if ((Number_clusters == 0) && (Asu_flags == 0)) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
- }
- printbuf(desc, indent+1, NULL, 0);
- i += 5;
-
- for(j = 0; (j < Number_clusters) && (i < figlen); j++) {
- // iterate over Cluster Id
- sprintf(desc, "Cluster Id=0x%X", f[i]);
- printbuf(desc, indent+2, NULL, 0);
- i++;
- }
- if (j < Number_clusters) {
- sprintf(desc, "missing Cluster Id, fig length too short !");
- printbuf(desc, indent+1, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
-
- // decode announcement support types
- for(j = 0; j < 16; j++) {
- if (Asu_flags & (1 << j)) {
- sprintf(desc, "Announcement support=%s", announcement_types_str[j]);
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- }
- }
- break;
- case 19: // FIG 0/19 Announcement switching
- { // ETSI EN 300 401 8.1.6.2
- uint16_t Asw_flags;
- uint8_t i = 1, j, Cluster_Id, SubChId, Rfa, RegionId_LP;
- char tmpbuf[256];
- bool New_flag, Region_flag;
-
- while (i < (figlen - 3)) {
- // iterate over announcement switching
- // Cluster Id, Asw flags, New flag, Region flag,
- // SubChId, Rfa, Region Id Lower Part
- Cluster_Id = f[i];
- 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;
- SubChId = (f[i+3] & 0x3F);
- sprintf(desc, "Cluster Id=0x%02x, Asw flags=0x%04x, New flag=%d %s, Region flag=%d last byte %s, SubChId=%d",
- Cluster_Id, Asw_flags, New_flag, (New_flag)?"new":"repeat", Region_flag, (Region_flag)?"present":"absent", SubChId);
- if (Region_flag) {
- if (i < (figlen - 4)) {
- // read region lower part
- Rfa = (f[i+4] >> 6);
- RegionId_LP = (f[i+4] & 0x3F);
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Region Lower Part=0x%02x", RegionId_LP);
- strcat(desc, tmpbuf);
- }
- else {
- sprintf(tmpbuf, "missing Region Lower Part, fig length too short !");
- strcat(desc, tmpbuf);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
- }
- printbuf(desc, indent+1, NULL, 0);
- // decode announcement switching types
- for(j = 0; j < 16; j++) {
- if (Asw_flags & (1 << j)) {
- sprintf(desc, "Announcement switching=%s", announcement_types_str[j]);
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- i += (4 + Region_flag);
- }
- }
- break;
- case 21: // FIG 0/21 Frequency Information
- { // ETSI EN 300 401 8.1.8
- float freq;
- uint32_t ifreq;
- uint64_t key;
- uint16_t RegionId, Id_field;
- uint8_t i = 1, j, k, Length_FI_list, RandM, Length_Freq_list, Control_field;
- uint8_t Control_field_trans_mode, Id_field2;
- char tmpbuf[256];
- bool Continuity_flag;
-
- while (i < (figlen - 1)) {
- // iterate over frequency information
- // decode RegionId, Length of FI list
- RegionId = (f[i] << 3) | (f[i+1] >> 5);
- Length_FI_list = (f[i+1] & 0x1F);
- sprintf(desc, "RegionId=0x%03x", RegionId);
- printbuf(desc, indent+1, NULL, 0);
- i += 2;
- if ((i + Length_FI_list) <= figlen) {
- j = i;
- while ((j + 2) < (i + Length_FI_list)) {
- // iterate over FI list x
- // decode Id field, R&M, Continuity flag, Length of Freq list
- Id_field = (f[j] << 8) | f[j+1];
- RandM = f[j+2] >> 4;
- Continuity_flag = (f[j+2] >> 3) & 0x01;
- Length_Freq_list = f[j+2] & 0x07;
- sprintf(desc, "Id_field=");
- switch (RandM) {
- case 0x0:
- case 0x1:
- strcat(desc, "EId");
- break;
- case 0x6:
- strcat(desc, "DRM Service Id");
- break;
- case 0x8:
- strcat(desc, "RDS PI");
- break;
- case 0x9:
- case 0xa:
- case 0xc:
- strcat(desc, "Dummy");
- break;
- case 0xe:
- strcat(desc, "AMSS Service Id");
- break;
- default:
- strcat(desc, "invalid");
- break;
- }
- sprintf(tmpbuf, "=0x%X, R&M=0x%1x", Id_field, RandM);
- strcat(desc, tmpbuf);
- switch (RandM) {
- case 0x0:
- strcat(desc, "=DAB ensemble, no local windows");
- break;
- case 0x6:
- strcat(desc, "=DRM");
- break;
- case 0x8:
- strcat(desc, "=FM with RDS");
- break;
- case 0x9:
- strcat(desc, "=FM without RDS");
- break;
- case 0xa:
- strcat(desc, "=AM (MW in 9 kHz steps & LW)");
- break;
- case 0xc:
- strcat(desc, "=AM (MW in 5 kHz steps & SW)");
- break;
- case 0xe:
- strcat(desc, "=AMSS");
- break;
- default:
- strcat(desc, "=Rfu");
- break;
- }
- sprintf(tmpbuf, ", Continuity flag=%d", Continuity_flag);
- strcat(desc, tmpbuf);
- if ((oe == 0) || ((oe == 1) && (RandM != 0x6) && \
- ((RandM < 0x8) || (RandM > 0xa)) && (RandM != 0xc) && (RandM != 0xe))) {
- if (Continuity_flag == 0) {
- switch (RandM) {
- case 0x0:
- case 0x1:
- strcat(desc, "=continuous output not expected");
- break;
- case 0x6:
- strcat(desc, "=no compensating time delay on DRM audio signal");
- break;
- case 0x8:
- case 0x9:
- strcat(desc, "=no compensating time delay on FM audio signal");
- break;
- case 0xa:
- case 0xc:
- case 0xe:
- strcat(desc, "=no compensating time delay on AM audio signal");
- break;
- default:
- strcat(desc, "=Rfu");
- break;
- }
- }
- else { // Continuity_flag == 1
- switch (RandM) {
- case 0x0:
- case 0x1:
- strcat(desc, "=continuous output possible");
- break;
- case 0x6:
- strcat(desc, "=compensating time delay on DRM audio signal");
- break;
- case 0x8:
- case 0x9:
- strcat(desc, "=compensating time delay on FM audio signal");
- break;
- case 0xa:
- case 0xc:
- case 0xe:
- strcat(desc, "=compensating time delay on AM audio signal");
- break;
- default:
- strcat(desc, "=Rfu");
- break;
- }
- }
- }
- else { // oe == 1
- strcat(desc, "=reserved for future addition");
- }
- key = ((uint64_t)oe << 32) | ((uint64_t)pd << 31) | \
- ((uint64_t)RegionId << 20) | ((uint64_t)Id_field << 4) | \
- (uint64_t)RandM;
- sprintf(tmpbuf, ", database key=0x%09" PRId64, key);
- // CEI Change Event Indication
- if (Length_Freq_list == 0) {
- strcat(tmpbuf, ", CEI");
- }
- strcat(desc, tmpbuf);
- printbuf(desc, indent+2, NULL, 0);
- j += 3; // add header
-
- k = j;
- switch (RandM) {
- case 0x0:
- case 0x1:
- while((k + 2) < (j + Length_Freq_list)) {
- // iteration over Freq list
- ifreq = (((uint32_t)(f[k] & 0x07) << 16) | ((uint32_t)f[k+1] << 8) | (uint32_t)f[k+2]) * 16;
- if (ifreq != 0) {
- Control_field = (f[k] >> 3);
- Control_field_trans_mode = (Control_field >> 1) & 0x07;
- if ((Control_field & 0x10) == 0) {
- sprintf(desc, "%d KHz, ", ifreq);
- if ((Control_field & 0x01) == 0) {
- strcat(desc, "geographically adjacent area, ");
- }
- else { // (Control_field & 0x01) == 1
- strcat(desc, "no geographically adjacent area, ");
- }
- if (Control_field_trans_mode == 0) {
- strcat(desc, "no transmission mode signalled");
- }
- else if (Control_field_trans_mode <= 4) {
- sprintf(tmpbuf, "transmission mode %d", Control_field_trans_mode);
- strcat(desc, tmpbuf);
- }
- else { // Control_field_trans_mode > 4
- sprintf(tmpbuf, "invalid transmission mode 0x%x", Control_field_trans_mode);
- strcat(desc, tmpbuf);
- }
- }
- else { // (Control_field & 0x10) == 0x10
- sprintf(desc, "%d KHz, invalid Control field b23 0x%x", ifreq, Control_field);
- }
- }
- else {
- sprintf(desc, "Frequency not to be used (0)");
- }
- printbuf(desc, indent+3, NULL, 0);
- k += 3;
- }
- break;
- case 0x8:
- case 0x9:
- case 0xa:
- while(k < (j + Length_Freq_list)) {
- // iteration over Freq list
- if (f[k] != 0) { // freq != 0
- if (RandM == 0xa) {
- if (f[k] < 16) {
- ifreq = (144 + ((uint32_t)f[k] * 9));
- }
- else { // f[k] >= 16
- ifreq = (387 + ((uint32_t)f[k] * 9));
- }
- sprintf(desc, "%d KHz", ifreq);
- }
- else { // RandM == 8 or 9
- freq = (87.5 + ((float)f[k] * 0.1));
- sprintf(desc, "%.1f MHz", freq);
- }
- }
- else {
- sprintf(desc, "Frequency not to be used (0)");
- }
- printbuf(desc, indent+3, NULL, 0);
- k++;
- }
- break;
- case 0xc:
- while((k + 1) < (j + Length_Freq_list)) {
- // iteration over Freq list
- ifreq = (((uint32_t)f[k] << 8) | (uint32_t)f[k+1]) * 5;
- if (ifreq != 0) {
- sprintf(desc, "%d KHz", ifreq);
- }
- else {
- sprintf(desc, "Frequency not to be used (0)");
- }
- printbuf(desc, indent+3, NULL, 0);
- k += 2;
- }
- break;
- case 0x6:
- case 0xe:
- while((k + 2) < (j + Length_Freq_list)) {
- // iteration over Freq list
- Id_field2 = f[k];
- ifreq = ((((uint32_t)f[k+1] & 0x7f) << 8) | (uint32_t)f[k+2]);
- if (ifreq != 0) {
- sprintf(desc, "%d KHz", ifreq);
- }
- else {
- sprintf(desc, "Frequency not to be used (0)");
- }
- if (RandM == 0x6) {
- sprintf(tmpbuf, ", DRM Service Id 0x%X", Id_field2);
- strcat(desc, tmpbuf);
- }
- else if (RandM == 0xe) {
- sprintf(tmpbuf, ", AMSS Service Id 0x%X", Id_field2);
- strcat(desc, tmpbuf);
- }
- if ((f[k+1] & 0x80) == 0x80) {
- sprintf(tmpbuf, ", invalid Rfu b15 set to 1 instead of 0");
- strcat(desc, tmpbuf);
- }
- printbuf(desc, indent+3, NULL, 0);
- k += 3;
- }
- break;
- default:
- break;
- }
- j += Length_Freq_list;
- }
- i += Length_FI_list;
- }
- }
- }
- break;
- case 22: // FIG 0/22 Transmitter Identification Information (TII) database
- { // ETSI EN 300 401 8.1.9
- Lat_Lng gps_pos = {0, 0};
- double latitude_sub, longitude_sub;
- int16_t Latitude_coarse, Longitude_coarse;
- uint16_t key, TD;
- int16_t Latitude_offset, Longitude_offset;
- uint8_t i = 1, j, MainId = 0, Rfu, Nb_SubId_fields, SubId;
- uint8_t Latitude_fine, Longitude_fine;
- char tmpbuf[256];
- bool MS;
-
- while (i < figlen) {
- // iterate over Transmitter Identification Information (TII) fields
- MS = f[i] >> 7;
- MainId = f[i] & 0x7F;
- key = (oe << 8) | (pd << 7) | MainId;
- sprintf(desc, "M/S=%d %sidentifier, MainId=0x%X",
- MS, MS?"Sub-":"Main ", MainId);
- // check MainId value
- if ((Mode_Identity == 1) || (Mode_Identity == 2) || (Mode_Identity == 4)) {
- if (MainId > 69) {
- // The coding range shall be 0 to 69 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
- }
- }
- else if (Mode_Identity == 3) {
- if (MainId > 5) {
- // The coding range shall be 0 to 5 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
- }
- }
- // print database key
- sprintf(tmpbuf, ", database key=0x%X", key);
- strcat(desc, tmpbuf);
- i++;
- if (MS == 0) {
- // Main identifier
-
- if (i < (figlen - 4)) {
- Latitude_coarse = (f[i] << 8) | f[i+1];
- Longitude_coarse = (f[i+2] << 8) | f[i+3];
- Latitude_fine = f[i+4] >> 4;
- Longitude_fine = f[i+4] & 0x0F;
- gps_pos.latitude = (double)((int32_t)((((int32_t)Latitude_coarse) << 4) | (uint32_t)Latitude_fine)) * 90 / 524288;
- gps_pos.longitude = (double)((int32_t)((((int32_t)Longitude_coarse) << 4) | (uint32_t)Longitude_fine)) * 180 / 524288;
- fig0_22_key_Lat_Lng[key] = gps_pos;
- sprintf(tmpbuf, ", Lat Lng coarse=0x%X 0x%X, Lat Lng fine=0x%X 0x%X => Lat Lng=%f, %f",
- Latitude_coarse, Longitude_coarse, Latitude_fine, Longitude_fine,
- gps_pos.latitude, gps_pos.longitude);
- strcat(desc, tmpbuf);
- i += 5;
- }
- else {
- strcat(desc, ", invalid length of Latitude Longitude coarse fine");
- }
- printbuf(desc, indent+1, NULL, 0);
- }
- else { // MS == 1
- // Sub-identifier
-
- if (i < figlen) {
- Rfu = f[i] >> 3;
- Nb_SubId_fields = f[i] & 0x07;
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Number of SubId fields=%d%s",
- Nb_SubId_fields, (Nb_SubId_fields == 0)?", CEI":"");
- strcat(desc, tmpbuf);
- printbuf(desc, indent+1, NULL, 0);
- i++;
-
- for(j = i; ((j < (i + (Nb_SubId_fields * 6))) && (j < (figlen - 5))); j += 6) {
- // iterate over SubId fields
- SubId = f[j] >> 3;
- sprintf(desc, "SubId=0x%X", SubId);
- // check SubId value
- if ((SubId == 0) || (SubId > 23)) {
- strcat(desc, " invalid value");
- }
-
- TD = ((f[j] & 0x03) << 8) | f[j+1];
- Latitude_offset = (f[j+2] << 8) | f[j+3];
- Longitude_offset = (f[j+4] << 8) | f[j+5];
- sprintf(tmpbuf, ", TD=%d us, Lat Lng offset=0x%X 0x%X",
- TD, Latitude_offset, Longitude_offset);
- strcat(desc, tmpbuf);
-
- if (fig0_22_key_Lat_Lng.count(key) > 0) {
- // latitude longitude available in database for Main Identifier
- latitude_sub = (90 * (double)Latitude_offset / 524288) + fig0_22_key_Lat_Lng[key].latitude;
- longitude_sub = (180 * (double)Longitude_offset / 524288) + fig0_22_key_Lat_Lng[key].longitude;
- sprintf(tmpbuf, " => Lat Lng=%f, %f", latitude_sub, longitude_sub);
- strcat(desc, tmpbuf);
- }
- else {
- // latitude longitude not available in database for Main Identifier
- latitude_sub = 90 * (double)Latitude_offset / 524288;
- longitude_sub = 180 * (double)Longitude_offset / 524288;
- sprintf(tmpbuf, " => Lat Lng=%f, %f wrong value because Main identifier latitude/longitude not available in database", latitude_sub, longitude_sub);
- strcat(desc, tmpbuf);
- }
- printbuf(desc, indent+2, NULL, 0);
- }
- i += (Nb_SubId_fields * 6);
- }
- else {
- strcat(desc, ", invalid fig length or Number of SubId fields length");
- printbuf(desc, indent+1, NULL, 0);
- }
- }
- }
- }
- break;
- case 24: // FIG 0/24 OE Services
- { // ETSI EN 300 401 8.1.10.2
- uint64_t key;
- uint32_t SId;
- uint16_t EId;
- uint8_t i = 1, j, Number_of_EIds, CAId;
- char tmpbuf[256];
- bool Rfa;
-
- while (i < (figlen - (((uint8_t)pd + 1) * 2))) {
- // iterate over other ensembles services
- if (pd == 0) {
- SId = ((uint32_t)f[i] << 8) | (uint32_t)f[i+1];
- i += 2;
- }
- else { // pd == 1
- SId = ((uint32_t)f[i] << 24) | ((uint32_t)f[i+1] << 16) |
- ((uint32_t)f[i+2] << 8) | (uint32_t)f[i+3];
- i += 4;
- }
- Rfa = (f[i] >> 7);
- CAId = (f[i] >> 4);
- Number_of_EIds = (f[i] & 0x0f);
- key = ((uint64_t)oe << 33) | ((uint64_t)pd << 32) | \
- (uint64_t)SId;
- if (pd == 0) {
- sprintf(desc, "SId=0x%X, CAId=%d, Number of EId=%d, database key=%09" PRId64, SId, CAId, Number_of_EIds, key);
- }
- else { // pd == 1
- sprintf(desc, "SId=0x%X, CAId=%d, Number of EId=%d, database key=%09" PRId64, SId, CAId, Number_of_EIds, key);
- }
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- // CEI Change Event Indication
- if (Number_of_EIds == 0) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
- }
- printbuf(desc, indent+1, NULL, 0);
- i++;
-
- for(j = i; ((j < (i + (Number_of_EIds * 2))) && (j < figlen)); j += 2) {
- // iterate over EIds
- EId = ((uint16_t)f[j] <<8) | (uint16_t)f[j+1];
- sprintf(desc, "EId 0x%04x", EId);
- printbuf(desc, indent+2, NULL, 0);
- }
- i += (Number_of_EIds * 2);
- }
- }
- break;
- case 25: // FIG 0/25 OE Announcement support
- { // ETSI EN 300 401 8.1.10.5.1
- uint32_t key;
- uint16_t SId, Asu_flags, EId;
- uint8_t i = 1, j, Rfu, Number_EIds;
- char tmpbuf[256];
-
- while (i < (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];
- Asu_flags = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3];
- Rfu = (f[i+4] >> 4);
- Number_EIds = (f[i+4] & 0x0F);
- sprintf(desc, "SId=0x%X, Asu flags=0x%X", SId, Asu_flags);
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Number of EIds=%d", Number_EIds);
- strcat(desc, tmpbuf);
- key = ((uint32_t)oe << 17) | ((uint32_t)pd << 16) | (uint32_t)SId;
- sprintf(tmpbuf, ", database key=0x%05x", key);
- strcat(desc, tmpbuf);
- // CEI Change Event Indication
- if (Number_EIds == 0) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
- }
- printbuf(desc, indent+1, NULL, 0);
- i += 5;
-
- for(j = 0; (j < Number_EIds) && (i < (figlen - 1)); j++) {
- // iterate over EIds
- EId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- sprintf(desc, "EId=0x%X", EId);
- printbuf(desc, indent+2, NULL, 0);
- i += 2;
- }
- if (j < Number_EIds) {
- sprintf(desc, "missing EId, fig length too short !");
- printbuf(desc, indent+1, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
-
- // decode OE announcement support types
- for(j = 0; j < 16; j++) {
- if (Asu_flags & (1 << j)) {
- sprintf(desc, "OE Announcement support=%s", announcement_types_str[j]);
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- }
- }
- break;
- case 26: // FIG 0/26 OE Announcement switching
- { // ETSI EN 300 401 8.1.10.5.2
- uint16_t Asw_flags, EId_Other_Ensemble;
- uint8_t i = 1, j, Rfa, Cluster_Id_Current_Ensemble, Region_Id_Current_Ensemble;
- uint8_t Cluster_Id_Other_Ensemble, Region_Id_Other_Ensemble;
- bool New_flag, Region_flag;
- char tmpbuf[256];
-
- while (i < (figlen - 6)) {
- // iterate over other ensembles announcement switching
- Cluster_Id_Current_Ensemble = f[i];
- 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;
- Region_Id_Current_Ensemble = f[i+3] & 0x3F;
- EId_Other_Ensemble = ((uint16_t)f[i+4] << 8) | (uint16_t)f[i+5];
- Cluster_Id_Other_Ensemble = f[i+6];
- sprintf(desc, "Cluster Id Current Ensemble=0x%X, Asw flags=0x%X, New flag=%d %s announcement, Region flag=%d last byte %s, Region Id Current Ensemble=0x%X, EId Other Ensemble=0x%X, Cluster Id Other Ensemble=0x%X",
- Cluster_Id_Current_Ensemble, Asw_flags, New_flag, New_flag?"newly introduced":"repeated",
- Region_flag, Region_flag?"present":"absent. The announcement concerns the whole service area",
- Region_Id_Current_Ensemble, EId_Other_Ensemble, Cluster_Id_Other_Ensemble);
- i += 7;
- if (Region_flag != 0) {
- if (i < figlen) {
- // get Region Id Other Ensemble
- Rfa = (f[i] >> 6);
- Region_Id_Other_Ensemble = f[i] & 0x3F;
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Region Id Other Ensemble=0x%X", Region_Id_Other_Ensemble);
- strcat(desc, tmpbuf);
- }
- else {
- sprintf(tmpbuf, "missing Region Id Other Ensemble, fig length too short !");
- strcat(desc, tmpbuf);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
- i++;
- }
- printbuf(desc, indent+1, NULL, 0);
- // decode announcement switching types
- for(j = 0; j < 16; j++) {
- if (Asw_flags & (1 << j)) {
- sprintf(desc, "Announcement switching=%s", announcement_types_str[j]);
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- }
- }
- break;
- case 27: // FIG 0/27 FM Announcement support
- { // ETSI EN 300 401 8.1.11.2.1
- uint16_t SId, PI;
- uint8_t i = 1, j, Rfu, Number_PI_codes, key;
- char tmpbuf[256];
-
- while (i < (figlen - 2)) {
- // iterate over FM announcement support
- SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- Rfu = f[i+2] >> 4;
- Number_PI_codes = f[i+2] & 0x0F;
- key = (oe << 5) | (pd << 4) | Number_PI_codes;
- sprintf(desc, "SId=0x%X", SId);
- if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Number of PI codes=%d", Number_PI_codes);
- strcat(desc, tmpbuf);
- if (Number_PI_codes > 12) {
- strcat(desc, " above maximum value of 12");
- fprintf(stderr, "WARNING: FIG %d/%d Number of PI codes=%d > 12 (maximum value)\n", figtype, ext, Number_PI_codes);
- }
- sprintf(tmpbuf, ", database key=0x%02X", key);
- strcat(desc, tmpbuf);
- // CEI Change Event Indication
- if (Number_PI_codes == 0) {
- // The Change Event Indication (CEI) is signalled by the Number of PI codes field = 0
- strcat(desc, ", CEI");
- }
- printbuf(desc, indent+1, NULL, 0);
- i += 3;
- for(j = 0; (j < Number_PI_codes) && (i < (figlen - 1)); j++) {
- // iterate over PI
- PI = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- sprintf(desc, "PI=0x%X", PI);
- printbuf(desc, indent+2, NULL, 0);
- i += 2;
- }
- if (j != Number_PI_codes) {
- sprintf(desc, "fig length too short !");
- printbuf(desc, indent+2, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, ext, figlen);
- }
- }
- }
- break;
- case 28: // FIG 0/28 FM Announcement switching
- { // ETSI EN 300 401 8.1.11.2.2
- uint16_t PI;
- uint8_t i = 1, Cluster_Id_Current_Ensemble, Region_Id_Current_Ensemble;
- bool New_flag, Rfa;
- char tmpbuf[256];
-
- while (i < (figlen - 3)) {
- // iterate over FM announcement switching
- Cluster_Id_Current_Ensemble = f[i];
- New_flag = f[i+1] >> 7;
- Rfa = (f[i+1] >> 6) & 0x01;
- Region_Id_Current_Ensemble = f[i+1] & 0x3F;
- PI = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3];
- sprintf(desc, "Cluster Id Current Ensemble=0x%X", Cluster_Id_Current_Ensemble);
- if (Cluster_Id_Current_Ensemble == 0) {
- strcat(desc, " invalid value");
- fprintf(stderr, "WARNING: FIG %d/%d Cluster Id Current Ensemble invalid value 0\n", figtype, ext);
- }
- sprintf(tmpbuf, ", New flag=%d %s announcement",
- New_flag, New_flag?"newly introduced":"repeated");
- strcat(desc, tmpbuf);
- if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
- }
- sprintf(tmpbuf, ", Region Id Current Ensemble=0x%X, PI=0x%X", Region_Id_Current_Ensemble, PI);
- strcat(desc, tmpbuf);
- printbuf(desc, indent+1, NULL, 0);
- i += 4;
- }
- }
- break;
- case 31: // FIG 0/31 FIC re-direction
- { // ETSI EN 300 401 8.1.12
- uint32_t FIG_type0_flag_field = 0, flag_field;
- uint8_t i = 1, j, FIG_type1_flag_field = 0, FIG_type2_flag_field = 0;
-
- if (i < (figlen - 5)) {
- // Read FIC re-direction
- FIG_type0_flag_field = ((uint32_t)f[i] << 24) | ((uint32_t)f[i+1] << 16) |
- ((uint32_t)f[i+2] << 8) | (uint32_t)f[i+3];
- FIG_type1_flag_field = f[i+4];
- FIG_type2_flag_field = f[i+5];
-
- 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);
-
- for(j = 0; j < 32; j++) {
- // iterate over FIG type 0 re-direction
- flag_field = FIG_type0_flag_field & ((uint32_t)1 << j);
- if ((flag_field != 0) && ((j <= 5) || (j == 8) ||
- (j == 10) || (j == 13) || (j == 14) ||
- (j == 19) || (j == 26) || (j == 28))) {
- sprintf(desc, "oe=%d FIG 0/%d carried in AIC, invalid configuration, shall always be carried entirely in the FIC",
- oe, j);
- printbuf(desc, indent+2, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d FIG re-direction of oe=%d FIG0/%d not allowed\n", figtype, ext, oe, j);
- }
- else if ((flag_field != 0) && ((j == 21) || (j == 24))) {
- sprintf(desc, "oe=%d FIG 0/%d carried in AIC, same shall be carried in FIC", oe, j);
- printbuf(desc, indent+2, NULL, 0);
- }
- else if (flag_field != 0) {
- if (oe == 0) {
- sprintf(desc, "oe=%d FIG 0/%d carried in AIC, same shall be carried in FIC", oe, j);
- }
- else { // oe == 1
- sprintf(desc, "oe=%d FIG 0/%d carried in AIC, may be carried entirely in AIC", oe, j);
- }
- printbuf(desc, indent+2, NULL, 0);
- }
- }
-
- for(j = 0; j < 8; j++) {
- // iterate over FIG type 1 re-direction
- flag_field = FIG_type1_flag_field & ((uint32_t)1 << j);
- if (flag_field != 0) {
- if (oe == 0) {
- sprintf(desc, "oe=%d FIG 1/%d carried in AIC, same shall be carried in FIC", oe, j);
- }
- else { // oe == 1
- sprintf(desc, "oe=%d FIG 1/%d carried in AIC, may be carried entirely in AIC", oe, j);
- }
- printbuf(desc, indent+2, NULL, 0);
- }
- }
-
- for(j = 0; j < 8; j++) {
- // iterate over FIG type 2 re-direction
- flag_field = FIG_type2_flag_field & ((uint32_t)1 << j);
- if (flag_field != 0) {
- if (oe == 0) {
- sprintf(desc, "oe=%d FIG 2/%d carried in AIC, same shall be carried in FIC", oe, j);
- }
- else { // oe == 1
- sprintf(desc, "oe=%d FIG 2/%d carried in AIC, may be carried entirely in AIC", oe, j);
- }
- printbuf(desc, indent+2, NULL, 0);
- }
- }
- }
- if (figlen != 7) {
- fprintf(stderr, "WARNING: FIG %d/%d invalid length %d, expecting 7\n", figtype, ext, figlen);
- }
- }
- break;
- }
+ fig0_select(fig0, indent);
}
break;
@@ -3033,131 +853,4 @@ void decodeFIG(FIGalyser &figs,
}
}
-// get_programme_type_str return the programme type string from international table Id and programme type
-const char *get_programme_type_str(size_t int_table_Id, size_t pty) {
- if ((int_table_Id - 1) < INTERNATIONAL_TABLE_SIZE) {
- if (pty < PROGRAMME_TYPE_CODES_SIZE) {
- return Programme_type_codes_str[int_table_Id - 1][pty];
- }
- else {
- return "invalid programme type";
- }
- }
- else {
- return "unknown international table Id";
- }
-}
-
-// strcatPNum decode Programme_Number into string and append it to dest_str
-// Programme_Number: this 16-bit field shall define the date and time at which
-// a programme begins or will be continued. This field is coded in the same way
-// as the RDS "Programme Item Number (PIN)" feature (EN 62106).
-char *strcatPNum(char *dest_str, uint16_t Programme_Number) {
- uint8_t day, hour, minute;
- char tempbuf[256];
-
- minute = (uint8_t)(Programme_Number & 0x003F);
- hour = (uint8_t)((Programme_Number >> 6) & 0x001F);
- day = (uint8_t)((Programme_Number >> 11) & 0x001F);
- if (day != 0) {
- sprintf(tempbuf, "day of month=%d time=%02d:%02d", day, hour, minute);
- }
- else { // day == 0
- // Special codes are allowed when the date part of the PNum field
- // signals date = "0". In this case, the hours and minutes part of
- // the field shall contain a special code, as follows
- if ((hour == 0) && (minute == 0)) {
- sprintf(tempbuf, "Status code: no meaningful PNum is currently provided");
- }
- else if ((hour == 0) && (minute == 1)) {
- sprintf(tempbuf, "Blank code: the current programme is not worth recording");
- }
- else if ((hour == 0) && (minute == 2)) {
- sprintf(tempbuf, "Interrupt code: the interrupt is unplanned (for example a traffic announcement)");
- }
- else {
- sprintf(tempbuf, "invalid value");
- }
- }
- return strcat(dest_str, tempbuf);
-}
-
-// sprintfMJD: convert MJD (Modified Julian Date) into date string
-int sprintfMJD(char *dst, int mjd) {
- // EN 62106 Annex G
- // These formulas are applicable between the inclusive dates: 1st March 1900 to 28th February 2100
- int y, m, k;
- struct tm timeDate;
-
- memset(&timeDate, 0, sizeof(struct tm));
-
- // find Y, M, D from MJD
- y = (int)(((double)mjd - 15078.2) / 365.25);
- m = (int)(((double)mjd - 14956.1 - (int)((double)y * 365.25)) / 30.6001);
- timeDate.tm_mday = mjd - 14956 - (int)((double)y * 365.25) - (int)((double)m * 30.6001);
- if ((m == 14) || (m == 15)) {
- k = 1;
- }
- else {
- k = 0;
- }
- timeDate.tm_year = y + k;
- timeDate.tm_mon = (m - 1 - (k * 12)) - 1;
-
- // find WD from MJD
- timeDate.tm_wday = (((mjd + 2) % 7) + 1) % 7;
-
- //timeDate.tm_yday = 0; // Number of days since the first day of January not calculated
- timeDate.tm_isdst = -1; // No time print then information not available
-
- // print date string
- if ((timeDate.tm_mday < 0) || (timeDate.tm_mon < 0) || (timeDate.tm_year < 0)) {
- return sprintf(dst, "invalid MJD mday=%d mon=%d year=%d", timeDate.tm_mday, timeDate.tm_mon, timeDate.tm_year);
- }
- return strftime(dst, 256, "%a %b %d %Y", &timeDate);
-}
-
-void printinfo(string header,
- int indent_level,
- int min_verb)
-{
- if (verbosity >= min_verb) {
- for (int i = 0; i < indent_level; i++) {
- printf("\t");
- }
- printf("%s\n", header.c_str());
- }
-}
-
-void printbuf(string header,
- int indent_level,
- uint8_t* buffer,
- size_t size,
- string desc)
-{
- if (verbosity > 0) {
- for (int i = 0; i < indent_level; i++) {
- printf("\t");
- }
-
- printf("%s", header.c_str());
-
- if (verbosity > 1) {
- if (size != 0) {
- printf(": ");
- }
-
- for (size_t i = 0; i < size; i++) {
- printf("%02x ", buffer[i]);
- }
- }
-
- if (desc != "") {
- printf(" [%s] ", desc.c_str());
- }
-
- printf("\n");
- }
-}
-