SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
rdsparser.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include "rdsparser.h"
20 #include "rdstmc.h"
21 
22 #include <QDebug>
23 #include <string.h>
24 #include <sstream>
25 #include <iostream>
26 #include <cmath>
27 #include <cstring>
28 #include "boost/format.hpp"
29 
30 
31 const unsigned int RDSParser::offset_pos[5] = {0,1,2,3,2};
32 const unsigned int RDSParser::offset_word[5] = {252,408,360,436,848};
33 const unsigned int RDSParser::syndrome[5] = {383,14,303,663,748};
34 const char * const RDSParser::offset_name[] = {"A","B","C","D","C'"};
35 
36 /* page 77, Annex F in the standard */
37 const std::string RDSParser::pty_table[32] = {
38  "None",
39  "News",
40  "Current Affairs",
41  "Information",
42  "Sport",
43  "Education",
44  "Drama",
45  "Cultures",
46  "Science",
47  "Varied Speech",
48  "Pop Music",
49  "Rock Music",
50  "Easy Listening",
51  "Light Classics M",
52  "Serious Classics",
53  "Other Music",
54  "Weather & Metr",
55  "Finance",
56  "Children’s Progs",
57  "Social Affairs",
58  "Religion",
59  "Phone In",
60  "Travel & Touring",
61  "Leisure & Hobby",
62  "Jazz Music",
63  "Country Music",
64  "National Music",
65  "Oldies Music",
66  "Folk Music",
67  "Documentary",
68  "Alarm Test",
69  "Alarm-Alarm!"
70 };
71 
72 /* page 71, Annex D, table D.1 in the standard */
73 const std::string RDSParser::pi_country_codes[15][5] = {
74  {"DE","GR","MA","__","MD"},
75  {"DZ","CY","CZ","IE","EE"},
76  {"AD","SM","PL","TR","__"},
77  {"IL","CH","VA","MK","__"},
78  {"IT","JO","SK","__","__"},
79  {"BE","FI","SY","__","UA"},
80  {"RU","LU","TN","__","__"},
81  {"PS","BG","__","NL","PT"},
82  {"AL","DK","LI","LV","SI"},
83  {"AT","GI","IS","LB","__"},
84  {"HU","IQ","MC","__","__"},
85  {"MT","GB","LT","HR","__"},
86  {"DE","LY","YU","__","__"},
87  {"__","RO","ES","SE","__"},
88  {"EG","FR","NO","BY","BA"}
89 };
90 
91 /* page 72, Annex D, table D.2 in the standard */
92 const std::string RDSParser::coverage_area_codes[16] = {
93  "Local",
94  "International",
95  "National",
96  "Supra-regional",
97  "Regional 1",
98  "Regional 2",
99  "Regional 3",
100  "Regional 4",
101  "Regional 5",
102  "Regional 6",
103  "Regional 7",
104  "Regional 8",
105  "Regional 9",
106  "Regional 10",
107  "Regional 11",
108  "Regional 12"
109 };
110 
111 const std::string RDSParser::rds_group_acronyms[16] = {
112  "BASIC",
113  "PIN/SL",
114  "RT",
115  "AID",
116  "CT",
117  "TDC",
118  "IH",
119  "RP",
120  "TMC",
121  "EWS",
122  "___",
123  "___",
124  "___",
125  "___",
126  "EON",
127  "___"
128 };
129 
130 const std::string RDSParser::rds_group_acronym_tags[16] = {
131  "BAS",
132  "PIN",
133  "TXT",
134  "AID",
135  "TIM",
136  "TDC",
137  "IH_",
138  "RP_",
139  "TMC",
140  "EWS",
141  "___",
142  "___",
143  "___",
144  "___",
145  "EON",
146  "___"
147 };
148 
149 /* page 74, Annex E, table E.1 in the standard: that's the ASCII table!!! */
150 
151 /* see page 84, Annex J in the standard */
152 const std::string RDSParser::language_codes[44] = {
153  "N/A",
154  "Albanian",
155  "Breton",
156  "Catalan",
157  "Croatian",
158  "Welsh",
159  "Czech",
160  "Danish",
161  "German",
162  "English",
163  "Spanish",
164  "Esperanto",
165  "Estonian",
166  "Basque",
167  "Faroese",
168  "French",
169  "Frisian",
170  "Irish",
171  "Gaelic",
172  "Galician",
173  "Icelandic",
174  "Italian",
175  "Lappish",
176  "Latin",
177  "Latvian",
178  "Luxembourgian",
179  "Lithuanian",
180  "Hungarian",
181  "Maltese",
182  "Dutch",
183  "Norwegian",
184  "Occitan",
185  "Polish",
186  "Portuguese",
187  "Romanian",
188  "Romansh",
189  "Serbian",
190  "Slovak",
191  "Slovene",
192  "Finnish",
193  "Swedish",
194  "Turkish",
195  "Flemish",
196  "Walloon"
197 };
198 
199 /* see page 12 in ISO 14819-1 */
200 const std::string RDSParser::tmc_duration[8][2] =
201 {
202  {"no duration given", "no duration given"},
203  {"15 minutes", "next few hours"},
204  {"30 minutes", "rest of the day"},
205  {"1 hour", "until tomorrow evening"},
206  {"2 hours", "rest of the week"},
207  {"3 hours", "end of next week"},
208  {"4 hours", "end of the month"},
209  {"rest of the day", "long period"}
210 };
211 
212 /* optional message content, data field lengths and labels
213  * see page 15 in ISO 14819-1 */
214 const int RDSParser::optional_content_lengths[16] = {3,3,5,5,5,8,8,8,8,11,16,16,16,16,0,0};
215 
216 const std::string RDSParser::label_descriptions[16] = {
217  "Duration",
218  "Control code",
219  "Length of route affected",
220  "Speed limit advice",
221  "Quantifier",
222  "Quantifier",
223  "Supplementary information code",
224  "Explicit start time",
225  "Explicit stop time",
226  "Additional event",
227  "Detailed diversion instructions",
228  "Destination",
229  "RFU (Reserved for future use)",
230  "Cross linkage to source of problem, or another route",
231  "Separator",
232  "RFU (Reserved for future use)"
233 };
234 
236 {
237  clearAllFields();
238 }
239 
241 {
242 }
243 
245 {
246  m_pi_updated = false;
247  m_g0_updated = false;
248  m_g0_af_updated = false;
249  m_g1_updated = false;
250  m_g2_updated = false;
251  m_g3_updated = false;
252  m_g4_updated = false;
253  m_g5_updated = false;
254  m_g6_updated = false;
255  m_g7_updated = false;
256  m_g8_updated = false;
257  m_g9_updated = false;
258  m_g10_updated = false;
259  m_g11_updated = false;
260  m_g12_updated = false;
261  m_g13_updated = false;
262  m_g14_updated = false;
263  m_g14_data_available = false;
264  m_g15_updated = false;
265  radiotext_AB_flag = false;
266  debug = false;
267  log = false;
268 }
269 
271 {
272  // PI data
273  m_pi_count = 0;
275  m_pi_program_type = 0;
278  m_pi_traffic_program = false;
281 
282  // Group 00 data
283  m_g0_count = 0;
284  std::memset(m_g0_program_service_name, ' ', sizeof(m_g0_program_service_name));
286  m_g0_psn_bitmap = 0;
288  m_g0_music_speech = false;
289  m_g0_mono_stereo = false;
290  m_g0_artificial_head = false;
291  m_g0_compressed = false;
292  m_g0_static_pty = false;
293  m_g0_alt_freq.clear();
294 
295  // Group 01 data
296  m_g1_count = 0;
298  m_g1_country_index = -1;
299  m_g1_language_index = -1;
300  m_g1_pin_day = 0;
301  m_g1_pin_hour = 0;
302  m_g1_pin_minute = 0;
303 
304  // Group 02 data
305  m_g2_count = 0;
306  std::memset(m_g2_radiotext, ' ', sizeof(m_g2_radiotext));
307  m_g2_radiotext[sizeof(m_g2_radiotext) - 1] = '\0';
308 
309  // Group 03 data
310  m_g3_count = 0;
311  m_g3_groupB = false;
312  m_g3_appGroup = 0;
313  m_g3_message = 0;
314  m_g3_aid = 0;
315 
316 
317  // Group 04 data
318  m_g4_count = 0;
319  m_g4_hours = 0;
320  m_g4_minutes = 0;
321  m_g4_seconds = 0;
322  m_g4_year = 0;
323  m_g4_month = 0;
324  m_g4_day = 0;
326 
327  // Group 05..07 data
328  m_g5_count = 0;
329  m_g6_count = 0;
330  m_g7_count = 0;
331 
332  // Group 08 data
333  m_g8_count = 0;
335  m_g8_dp_ci = 0;
336  m_g8_sign = false;
337  m_g8_extent = 0;
338  m_g8_event = 0;
339  m_g8_location = 0;
340  m_g8_label_index = -1;
341  m_g8_content = 0;
342 
343  // Group 09 data
344  m_g9_varA = 0;
345  m_g9_cA = 0;
346  m_g9_dA = 0;
347  m_g9_varB = 0;
348  m_g9_dB = 0;
349 
350  // Group 10..13 data
351  m_g9_count = 0;
352  m_g10_count = 0;
353  m_g11_count = 0;
354  m_g12_count = 0;
355  m_g13_count = 0;
356 
357  // Group 14
358  m_g14_count = 0;
360  m_g14_alt_freqs.clear();
361  m_g14_mapped_freqs.clear();
362  std::memset(m_g14_program_service_name, ' ', sizeof(m_g14_program_service_name));
363  m_g14_program_service_name[8] = '\0';
364  m_g14_alt_freq_set.clear();
365  m_g14_mapped_freq_set.clear();
366  m_g14_psn_counter = 0;
367 
368  // Group 15
369  m_g15_count = 0;
370 
372 }
373 
374 void RDSParser::parseGroup(unsigned int *group)
375 {
376  unsigned int group_type = (unsigned int)((group[1] >> 12) & 0xf);
377  bool ab = (group[1] >> 11 ) & 0x1;
378 
379  /*
380  qDebug() << "RDSParser::parseGroup:"
381  << " type: " << group_type << (ab ? 'B' :'A')
382  << " (" << rds_group_acronyms[group_type].c_str() << ")";*/
383 
384  m_pi_count++;
385  m_pi_updated = true;
386 
387  m_pi_program_identification = group[0]; // "PI"
388  m_pi_traffic_program = (group[1] >> 10) & 0x01; // "TP"
389  m_pi_program_type = (group[1] >> 5) & 0x1f; // "PTY"
392 
393  /*
394  std::string pistring = str(boost::format("%04X") % m_pi_program_identification);
395 
396  qDebug() << "RDSParser::parseGroup:"
397  << " PI:" << pistring.c_str()
398  << " - " << "PTY:" << pty_table[m_pi_program_type].c_str()
399  << " (country:" << (pi_country_codes[m_pi_country_identification - 1][0]).c_str()
400  << "/" << (pi_country_codes[m_pi_country_identification - 1][1]).c_str()
401  << "/" << (pi_country_codes[m_pi_country_identification - 1][2]).c_str()
402  << "/" << (pi_country_codes[m_pi_country_identification - 1][3]).c_str()
403  << "/" << (pi_country_codes[m_pi_country_identification - 1][4]).c_str()
404  << ", area:" << coverage_area_codes[m_pi_area_coverage_index].c_str()
405  << ", program:" << int(pi_program_reference_number) << ")";*/
406 
407  switch (group_type) {
408  case 0:
409  decode_type0(group, ab);
410  break;
411  case 1:
412  decode_type1(group, ab);
413  break;
414  case 2:
415  decode_type2(group, ab);
416  break;
417  case 3:
418  decode_type3(group, ab);
419  break;
420  case 4:
421  decode_type4(group, ab);
422  break;
423  case 5:
424  decode_type5(group, ab);
425  break;
426  case 6:
427  decode_type6(group, ab);
428  break;
429  case 7:
430  decode_type7(group, ab);
431  break;
432  case 8:
433  decode_type8(group, ab);
434  break;
435  case 9:
436  decode_type9(group, ab);
437  break;
438  case 10:
439  decode_type10(group, ab);
440  break;
441  case 11:
442  decode_type11(group, ab);
443  break;
444  case 12:
445  decode_type12(group, ab);
446  break;
447  case 13:
448  decode_type13(group, ab);
449  break;
450  case 14:
451  decode_type14(group, ab);
452  break;
453  case 15:
454  decode_type15(group, ab);
455  break;
456  }
457 
458  /*
459  #define HEX(a) std::hex << std::setfill('0') << std::setw(4) << long(a) << std::dec
460  for(int i = 0; i < 4; i++) {
461  dout << " " << HEX(group[i]);
462  }
463  dout << std::endl;*/
464 }
465 
466 /* BASIC TUNING: see page 21 of the standard */
467 void RDSParser::decode_type0(unsigned int *group, bool B)
468 {
469  unsigned int af_code_1 = 0;
470  unsigned int af_code_2 = 0;
471  unsigned int no_af = 0;
472  double af_1 = 0;
473  double af_2 = 0;
474 
475  m_g0_count++;
476  m_g0_updated = true;
477 
478  m_pi_traffic_program = (group[1] >> 10) & 0x01; // "TP"
479  m_g0_traffic_announcement = (group[1] >> 4) & 0x01; // "TA"
480  m_g0_music_speech = (group[1] >> 3) & 0x01; // "MuSp"
481 
482  bool decoder_control_bit = (group[1] >> 2) & 0x01; // "DI"
483  unsigned char segment_address = group[1] & 0x03; // "DI segment"
484 
485  if (segment_address == 0)
486  {
487  std::memset(m_g0_program_service_name, ' ', sizeof(m_g0_program_service_name));
489  m_g0_psn_bitmap = 0;
490  }
491 
492  m_g0_program_service_name[segment_address * 2] = (group[3] >> 8) & 0xff;
493  m_g0_program_service_name[segment_address * 2 + 1] = group[3] & 0xff;
494  m_g0_psn_bitmap |= 1<<segment_address;
495 
496  /* see page 41, table 9 of the standard */
497  switch (segment_address)
498  {
499  case 0:
500  m_g0_mono_stereo = decoder_control_bit;
501  break;
502  case 1:
503  m_g0_artificial_head = decoder_control_bit;
504  break;
505  case 2:
506  m_g0_compressed = decoder_control_bit;
507  break;
508  case 3:
509  m_g0_static_pty = decoder_control_bit;
510  break;
511  default:
512  break;
513  }
514 
515  /* unused
516  flagstring[0] = m_pi_traffic_program ? '1' : '0';
517  flagstring[1] = m_g0_traffic_announcement ? '1' : '0';
518  flagstring[2] = m_g0_music_speech ? '1' : '0';
519  flagstring[3] = m_g0_mono_stereo ? '1' : '0';
520  flagstring[4] = m_g0_artificial_head ? '1' : '0';
521  flagstring[5] = m_g0_compressed ? '1' : '0';
522  flagstring[6] = m_g0_static_pty ? '1' : '0';*/
523 
524  static std::string af_string;
525 
526  if (!B)
527  { // type 0A
528  af_code_1 = int(group[2] >> 8) & 0xff;
529  af_code_2 = int(group[2]) & 0xff;
530  af_1 = decode_af(af_code_1);
531  af_2 = decode_af(af_code_2);
532 
533  if (af_1)
534  {
535  // @TODO: Find proper header or STL on OSX
536  auto res = m_g0_alt_freq.insert(af_1/1e3);
537  m_g0_af_updated = m_g0_af_updated || res.second;
538  no_af += 1;
539  }
540 
541  if (af_2)
542  {
543  // @TODO: Find proper header or STL on OSX
544  auto res = m_g0_alt_freq.insert(af_2/1e3);
545  m_g0_af_updated = m_g0_af_updated || res.second;
546  no_af += 2;
547  }
548 
549  /*
550  std::string af1_string;
551  std::string af2_string;
552 
553  // only AF1 => no_af==1, only AF2 => no_af==2, both AF1 and AF2 => no_af==3
554  if(no_af)
555  {
556  if(af_1 > 80e3) {
557  af1_string = str(boost::format("%2.2fMHz") % (af_1/1e3));
558  } else if((af_1<2e3)&&(af_1>100)) {
559  af1_string = str(boost::format("%ikHz") % int(af_1));
560  }
561 
562  if(af_2 > 80e3) {
563  af2_string = str(boost::format("%2.2fMHz") % (af_2/1e3));
564  } else if ((af_2 < 2e3) && (af_2 > 100)) {
565  af2_string = str(boost::format("%ikHz") % int(af_2));
566  }
567  }
568 
569  if(no_af == 1) {
570  af_string = af1_string;
571  } else if(no_af == 2) {
572  af_string = af2_string;
573  } else if(no_af == 3) {
574  af_string = str(boost::format("%s, %s") % af1_string %af2_string);
575  }*/
576  }
577 
578  /*
579  qDebug() << "RDSParser::decode_type0: "
580  << "\"" << std::string(m_g0_program_service_name, 8).c_str()
581  << "\" -" << (m_pi_traffic_program ? "TP" : "!TP")
582  << '-' << (m_g0_traffic_announcement ? "TA" : "!TA")
583  << '-' << (m_g0_music_speech ? "Music" : "Speech")
584  << '-' << (m_g0_mono_stereo ? "MONO" : "STEREO")
585  << " - AF:" << af_string.c_str();*/
586 }
587 
588 double RDSParser::decode_af(unsigned int af_code)
589 {
590  static bool vhf_or_lfmf = 0; // 0 = vhf, 1 = lf/mf
591  double alt_frequency = 0; // in kHz
592 
593  if ((af_code == 0) || // not to be used
594  ( af_code == 205) || // filler code
595  ((af_code >= 206) && (af_code <= 223)) || // not assigned
596  ( af_code == 224) || // No AF exists
597  ( af_code >= 251)) // not assigned
598  {
599  alt_frequency = 0;
600  }
601 
602  if ((af_code >= 225) && (af_code <= 249)) // VHF frequencies follow
603  {
604  alt_frequency = 0;
605  vhf_or_lfmf = 1;
606  }
607 
608  if (af_code == 250) // an LF/MF frequency follows
609  {
610  alt_frequency = 0;
611  vhf_or_lfmf = 0;
612  }
613 
614  if ((af_code > 0) && (af_code < 205) && vhf_or_lfmf) {
615  alt_frequency = 100.0 * (af_code + 875); // VHF (87.6-107.9MHz)
616  }
617  else if ((af_code > 0) && (af_code < 16) && !vhf_or_lfmf) {
618  alt_frequency = 153.0 + (af_code - 1) * 9; // LF (153-279kHz)
619  }
620  else if ((af_code > 15) && (af_code < 136) && !vhf_or_lfmf) {
621  alt_frequency = 531.0 + (af_code - 16) * 9 + 531; // MF (531-1602kHz)
622  }
623 
624  return alt_frequency;
625 }
626 
627 void RDSParser::decode_type1(unsigned int *group, bool B)
628 {
629  int ecc = 0;
630  int paging = 0;
631  char country_code = (group[0] >> 12) & 0x0f;
632  char radio_paging_codes = group[1] & 0x1f;
633  int variant_code = (group[2] >> 12) & 0x7;
634  unsigned int slow_labelling = group[2] & 0xfff;
635  m_g1_pin_day = (unsigned int)((group[3] >> 11) & 0x1f);
636  m_g1_pin_hour = (unsigned int)((group[3] >> 6) & 0x1f);
637  m_g1_pin_minute = (unsigned int) (group[3] & 0x3f);
638 
639  m_g1_count++;
640 
641  if (radio_paging_codes) {
642  //qDebug() << "RDSParser::decode_type1: paging codes: " << int(radio_paging_codes) << " ";
643  }
644 
646  m_g1_updated = true;
647  /*
648  std::string s = str(boost::format("program item: %id, %i, %i ") % day % hour % minute);
649  qDebug() << "RDSParser::decode_type1: " << s.c_str();*/
650  }
651 
652  if (!B)
653  {
654  switch (variant_code)
655  {
656  case 0: // paging + ecc
657  paging = (slow_labelling >> 8) & 0x0f;
658  ecc = slow_labelling & 0xff;
659  if (paging) {
660  //qDebug() << "RDSParser::decode_type1: " << "paging: " << paging << " ";
661  }
662  if ((ecc > 223) && (ecc < 229)) {
663  m_g1_updated = true;
664  m_g1_country_page_index = country_code - 1;
665  m_g1_country_index = ecc - 224;
666  /*
667  qDebug() << "RDSParser::decode_type1: " << "extended country code: "
668  << (pi_country_codes[country_code-1][ecc-224]).c_str();*/
669  } else {
670  qDebug() << "RDSParser::decode_type1: " << "invalid extended country code: " << ecc;
671  }
672  break;
673  case 1: // TMC identification
674  //qDebug() << "RDSParser::decode_type1: TMC identification code received";
675  break;
676  case 2: // Paging identification
677  //qDebug() << "RDSParser::decode_type1: Paging identification code received";
678  break;
679  case 3: // language codes
680  if (slow_labelling < 44) {
681  m_g1_updated = true;
682  m_g1_language_index = slow_labelling;
683  //qDebug() << "RDSParser::decode_type1: " << "language: " << language_codes[slow_labelling].c_str();
684  } else {
685  qDebug() << "RDSParser::decode_type1: " << "language: invalid language code " << slow_labelling;
686  }
687  break;
688  default:
689  break;
690  }
691  }
692 }
693 
694 void RDSParser::decode_type2(unsigned int *group, bool B)
695 {
696  unsigned char text_segment_address_code = group[1] & 0x0f;
697 
698  m_g2_updated = true;
699  m_g2_count++;
700 
701  // when the A/B flag is toggled, flush your current radiotext
702  if (radiotext_AB_flag != ((group[1] >> 4) & 0x01))
703  {
704  std::memset(m_g2_radiotext, ' ', sizeof(m_g2_radiotext));
705  m_g2_radiotext[sizeof(m_g2_radiotext) - 1] = '\0';
706  }
707 
708  radiotext_AB_flag = (group[1] >> 4) & 0x01;
709 
710  if (!B)
711  {
712  m_g2_radiotext[text_segment_address_code * 4 ] = (group[2] >> 8) & 0xff;
713  m_g2_radiotext[text_segment_address_code * 4 + 1] = group[2] & 0xff;
714  m_g2_radiotext[text_segment_address_code * 4 + 2] = (group[3] >> 8) & 0xff;
715  m_g2_radiotext[text_segment_address_code * 4 + 3] = group[3] & 0xff;
716  }
717  else
718  {
719  m_g2_radiotext[text_segment_address_code * 2 ] = (group[3] >> 8) & 0xff;
720  m_g2_radiotext[text_segment_address_code * 2 + 1] = group[3] & 0xff;
721  }
722 
723  /*
724  qDebug() << "RDSParser::decode_type2: " << "Radio Text " << (radiotext_AB_flag ? 'B' : 'A')
725  << ": " << std::string(m_g2_radiotext, sizeof(m_g2_radiotext)).c_str();*/
726 }
727 
728 void RDSParser::decode_type3(unsigned int *group, bool B)
729 {
730  if (B) {
731  qDebug() << "RDSParser::decode_type3: type 3B not implemented yet";
732  return;
733  }
734 
735  int application_group = (group[1] >> 1) & 0xf;
736  int group_type = group[1] & 0x1;
737  int message = group[2];
738  int aid = group[3];
739 
740 
741  m_g3_updated = true;
742  m_g3_count++;
743 
744  /*
745  qDebug() << "RDSParser::decode_type3: aid group: " << application_group
746  << " " << (group_type ? 'B' : 'A');*/
747 
748  if ((application_group == 8) && (group_type == 0))
749  { // 8A
750  int variant_code = (message >> 14) & 0x3;
751 
752  if (variant_code == 0)
753  {
754 // int ltn = (message >> 6) & 0x3f; // location table number
755 // bool afi = (message >> 5) & 0x1; // alternative freq. indicator
756 // bool M = (message >> 4) & 0x1; // mode of transmission
757 // bool I = (message >> 3) & 0x1; // international
758 // bool N = (message >> 2) & 0x1; // national
759 // bool R = (message >> 1) & 0x1; // regional
760 // bool U = message & 0x1; // urban
761 
762  /*
763  qDebug() << "RDSParser::decode_type3: location table: " << ltn << " - "
764  << (afi ? "AFI-ON" : "AFI-OFF") << " - "
765  << (M ? "enhanced mode" : "basic mode") << " - "
766  << (I ? "international " : "")
767  << (N ? "national " : "")
768  << (R ? "regional " : "")
769  << (U ? "urban" : "")
770  << " aid: " << aid;*/
771  }
772  else if (variant_code==1)
773  {
774 // int G = (message >> 12) & 0x3; // gap
775 // int sid = (message >> 6) & 0x3f; // service identifier
776 // int gap_no[4] = {3, 5, 8, 11};
777  /*
778  qDebug() << "RDSParser::decode_type3: gap: " << gap_no[G] << " groups, SID: "
779  << sid << " ";*/
780  }
781  }
782 
783  m_g3_groupB = group_type;
784  m_g3_appGroup = application_group;
785  m_g3_message = message;
786  m_g3_aid = aid;
787 
788  //qDebug() << "RDSParser::decode_type3: message: " << message << " - aid: " << aid;
789 }
790 
791 void RDSParser::decode_type4(unsigned int *group, bool B)
792 {
793  if (B)
794  {
795  qDebug() << "RDSParser::decode_type4: type 4B not implemented yet";
796  return;
797  }
798 
799  m_g4_updated = true;
800  m_g4_count++;
801 
802  m_g4_hours = ((group[2] & 0x1) << 4) | ((group[3] >> 12) & 0x0f);
803  m_g4_minutes = (group[3] >> 6) & 0x3f;
804  m_g4_local_time_offset = .5 * (group[3] & 0x1f);
805 
806  if ((group[3] >> 5) & 0x1) {
808  }
809 
810  double modified_julian_date = ((group[1] & 0x03) << 15) | ((group[2] >> 1) & 0x7fff);
811 
812  m_g4_year = int((modified_julian_date - 15078.2) / 365.25);
813  m_g4_month = int((modified_julian_date - 14956.1 - int(m_g4_year * 365.25)) / 30.6001);
814  m_g4_day = modified_julian_date - 14956 - int(m_g4_year * 365.25) - int(m_g4_month * 30.6001);
815  bool K = ((m_g4_month == 14) || (m_g4_month == 15)) ? 1 : 0;
816  m_g4_year += K;
817  m_g4_month -= 1 + K * 12;
818 
819  /*
820  std::string time = str(boost::format("%02i.%02i.%4i, %02i:%02i (%+.1fh)")\
821  % m_g4_day % m_g4_month % (1900 + m_g4_year) % m_g4_hours % m_g4_minutes % m_g4_local_time_offset);
822 
823  qDebug() << "RDSParser::decode_type4: Clocktime: " << time.c_str();*/
824 
825  //send_message(5,time);
826 }
827 
828 void RDSParser::decode_type5(unsigned int *group, bool B) {
829  (void) group;
830  (void) B;
831  qDebug() << "RDSParser::decode_type5: type5 not implemented yet";
832  m_g5_updated = true;
833  m_g5_count++;
834 }
835 
836 void RDSParser::decode_type6(unsigned int *group, bool B) {
837  (void) group;
838  (void) B;
839  qDebug() << "RDSParser::decode_type6: type 6 not implemented yet";
840  m_g6_updated = true;
841  m_g6_count++;
842 }
843 
844 void RDSParser::decode_type7(unsigned int *group, bool B) {
845  (void) group;
846  (void) B;
847  qDebug() << "RDSParser::decode_type7: type 7 not implemented yet";
848  m_g7_updated = true;
849  m_g7_count++;
850 }
851 
852 void RDSParser::decode_type8(unsigned int *group, bool B)
853 {
854  if (B)
855  {
856  qDebug() << "RDSParser::decode_type8: type 8B not implemented yet";
857  return;
858  }
859 
860  m_g8_updated = true;
861  m_g8_count++;
862 
863  bool T = (group[1] >> 4) & 0x1; // 0 = user message, 1 = tuning info
864  bool F = (group[1] >> 3) & 0x1; // 0 = multi-group, 1 = single-group
865  bool D = (group[2] >> 15) & 0x1; // 1 = diversion recommended
867 
868  static unsigned long int free_format[4];
869  static int no_groups = 0;
870 
871  if (T)
872  { // tuning info
873  qDebug() << "RDSParser::decode_type8: #tuning info# ";
874  int variant = group[1] & 0xf;
875 
876  if((variant > 3) && (variant < 10)) {
877  qDebug() << "RDSParser::decode_type8: variant: " << variant << " - "
878  << group[2] << " " << group[3];
879  } else {
880  qDebug() << "RDSParser::decode_type8: invalid variant: " << variant;
881  }
882 
883  }
884  else if (F || D)
885  { // single-group or 1st of multi-group
886  m_g8_dp_ci = group[1] & 0x7; // duration & persistence or continuity index
887  m_g8_sign = (group[2] >> 14) & 0x1; // event direction, 0 = +, 1 = -
888  m_g8_extent = (group[2] >> 11) & 0x7; // number of segments affected
889  m_g8_event = group[2] & 0x7ff; // event code, defined in ISO 14819-2
890  m_g8_location = group[3]; // location code, defined in ISO 14819-3
891 
892  qDebug() << "RDSParser::decode_type8: #user msg# " << (D ? "diversion recommended, " : "");
893 
894  if (F) {
895  qDebug() << "RDSParser::decode_type8: single-grp, duration:" << (tmc_duration[m_g8_dp_ci][0]).c_str();
896  } else {
897  qDebug() << "RDSParser::decode_type8: multi-grp, continuity index:" << m_g8_dp_ci;
898  }
899 
900  int event_line = RDSTMC::get_tmc_event_code_index(m_g8_event, 1);
901 
902  qDebug() << "RDSParser::decode_type8: extent:" << (m_g8_sign ? "-" : "") << m_g8_extent + 1 << " segments"
903  << ", event" << m_g8_event << ":" << RDSTMC::get_tmc_events(event_line, 1).c_str()
904  << ", location:" << m_g8_location;
905 
906  }
907  else
908  { // 2nd or more of multi-group
909  unsigned int ci = group[1] & 0x7; // countinuity index
910  bool sg = (group[2] >> 14) & 0x1; // second group
911  unsigned int gsi = (group[2] >> 12) & 0x3; // group sequence
912 
913  qDebug() << "RDSParser::decode_type8: #user msg# multi-grp, continuity index:" << ci
914  << (sg ? ", second group" : "") << ", gsi:" << gsi;
915 
916  qDebug() << "RDSParser::decode_type8: free format: " << (group[2] & 0xfff) << " "
917  << group[3];
918  // it's not clear if gsi=N-2 when gs=true
919 
920  if (sg) {
921  no_groups = gsi;
922  }
923 
924  free_format[gsi] = ((group[2] & 0xfff) << 12) | group[3];
925 
926  if (gsi == 0) {
927  decode_optional_content(no_groups, free_format);
928  }
929  }
930 }
931 
932 void RDSParser::decode_optional_content(int no_groups, unsigned long int *free_format)
933 {
934  int content_length = 0;
935  int ff_pointer = 0;
936 
937  if (no_groups == 0)
938  {
939  int i = 0;
940 // for (int i = no_groups; i == 0; i--) i is always 0 if no_groups is 0 and exit else skip
941 // {
942  ff_pointer = 12 + 16;
943 
944  while(ff_pointer >= 7) // ff_pointer must be >= 0 and is decreased by 7 in the loop
945  {
946  ff_pointer -= 4;
947  m_g8_label_index = (free_format[i] && ((0xf << ff_pointer) != 0)) ? 1 : 0;
948  content_length = 3; // optional_content_lengths[m_g8_label_index]; // always 3
949  ff_pointer -= content_length;
950  m_g8_content = (free_format[i] && ((int(std::pow(2, content_length) - 1) << ff_pointer) != 0)) ? 1 : 0;
951 
952  qDebug() << "RDSParser::decode_optional_content:"
953  << " TMC optional content (" << label_descriptions[m_g8_label_index].c_str() << ")"
954  << ": " << m_g8_content;
955  }
956  }
957 }
958 
959 void RDSParser::decode_type9(unsigned int *group, bool B){
960 
961  if (B)
962  {
963  m_g9_varB = group[1] & 0x1f;
964  m_g9_dB = group[3];
965  }
966  else
967  {
968  m_g9_varA = group[1] & 0x1f;
969  m_g9_cA = group[2];
970  m_g9_dA = group[3];
971  }
972 
973  m_g9_updated = true;
974  m_g9_count++;
975 }
976 
977 void RDSParser::decode_type10(unsigned int *group, bool B)
978 {
979  (void) group;
980  (void) B;
981  qDebug() << "RDSParser::decode_type10: type 10 not implemented yet";
982  m_g10_updated = true;
983  m_g10_count++;
984 }
985 
986 void RDSParser::decode_type11(unsigned int *group, bool B)
987 {
988  (void) group;
989  (void) B;
990  qDebug() << "RDSParser::decode_type11: type 11 not implemented yet";
991  m_g11_updated = true;
992  m_g11_count++;
993 }
994 
995 void RDSParser::decode_type12(unsigned int *group, bool B)
996 {
997  (void) group;
998  (void) B;
999  qDebug() << "RDSParser::decode_type12: type 12 not implemented yet";
1000  m_g12_updated = true;
1001  m_g12_count++;
1002 }
1003 
1004 void RDSParser::decode_type13(unsigned int *group, bool B)
1005 {
1006  (void) group;
1007  (void) B;
1008  qDebug() << "RDSParser::decode_type13: type 13 not implemented yet";
1009  m_g13_updated = true;
1010  m_g13_count++;
1011 }
1012 
1013 void RDSParser::decode_type14(unsigned int *group, bool B)
1014 {
1015  char variant_code = group[1] & 0x0f;
1016  unsigned int information = group[2];
1017  unsigned int pi_on = group[3];
1018 
1019  bool ta_on = 0;
1020  double af_1 = 0;
1021  double af_2 = 0;
1022 
1023  m_g14_updated = true;
1024  m_g14_count++;
1025 
1026  if (!B)
1027  {
1028  switch (variant_code)
1029  {
1030  case 0: // PS(ON)
1031  case 1: // PS(ON)
1032  case 2: // PS(ON)
1033  case 3: // PS(ON)
1034  {
1035  m_g14_program_service_name[variant_code * 2 ] = (information >> 8) & 0xff;
1036  m_g14_program_service_name[variant_code * 2 + 1] = information & 0xff;
1038  //qDebug() << "RDSParser::decode_type14: PS(ON): \"" << std::string(m_g14_program_service_name, 8).c_str() << "\"";
1039  break;
1040  }
1041  case 4: // AF
1042  {
1043  af_1 = 100.0 * (((information >> 8) & 0xff) + 875);
1044  af_2 = 100.0 * ((information & 0xff) + 875);
1045  m_g14_alt_freq_set.insert(af_1/1000.0);
1046  m_g14_alt_freq_set.insert(af_2/1000.0);
1047  /*
1048  std::string s = str(boost::format("AF:%3.2fMHz %3.2fMHz") % (af_1/1000) % (af_2/1000));
1049  qDebug() << "RDSParser::decode_type14: " << s.c_str();*/
1050  break;
1051  }
1052  case 5: // mapped frequencies
1053  case 6: // mapped frequencies
1054  case 7: // mapped frequencies
1055  case 8: // mapped frequencies
1056  {
1057  af_1 = 100.0 * (((information >> 8) & 0xff) + 875);
1058  af_2 = 100.0 * ((information & 0xff) + 875);
1059  m_g14_mapped_freq_set.insert(af_2/1000.0);
1060  /*
1061  std::string s = str(boost::format("TN:%3.2fMHz - ON:%3.2fMHz") % (af_1/1000) % (af_2/1000));
1062  qDebug() << "RDSParser::decode_type14: " << s.c_str();*/
1063  break;
1064  }
1065  case 9: // mapped frequencies (AM)
1066  {
1067  af_1 = 100.0 * (((information >> 8) & 0xff) + 875);
1068  af_2 = 9.0 * ((information & 0xff) - 16) + 531;
1069  m_g14_mapped_freq_set.insert(af_2/1000.0);
1070  /*
1071  std::string s = str(boost::format("TN:%3.2fMHz - ON:%ikHz") % (af_1/1000) % int(af_2));
1072  qDebug() << "RDSParser::decode_type14: " << s.c_str();*/
1073  break;
1074  }
1075  case 10: // unallocated
1076  break;
1077  case 11: // unallocated
1078  break;
1079  case 12: // linkage information
1080  {
1081  if (m_g14_psn_counter == 4)
1082  {
1083  //qDebug("RDSParser::decode_type14: m_g14_psn_updated: %d", m_g14_psn_counter);
1084  std::pair<psns_map_t::iterator, bool> ret = m_g14_program_service_names.insert(psns_map_kv_t(pi_on, std::string(m_g14_program_service_name)));
1085  std::memset(m_g14_program_service_name, ' ', sizeof(m_g14_program_service_name));
1086  m_g14_program_service_name[8] = '\0';
1087  m_g14_psn_counter = 0;
1088  m_g14_data_available = ret.second;
1089  }
1090 
1091  if (m_g14_alt_freq_set.size() > 0)
1092  {
1093  //qDebug("RDSParser::decode_type14: m_g14_alt_freq_set updated");
1094 
1095  std::pair<freqs_map_t::iterator, bool> retMap;
1096  std::pair<freqs_set_t::iterator, bool> retSet;
1097  bool updated = false;
1098 
1099  freqs_map_t::iterator mIt = m_g14_alt_freqs.find(pi_on);
1100 
1101  if (mIt == m_g14_alt_freqs.end()) // key does not exist yet => insert the whole set
1102  {
1103  retMap = m_g14_alt_freqs.insert(freqs_map_kv_t(pi_on, m_g14_alt_freq_set));
1104  updated |= retMap.second;
1105  }
1106  else // merge sets
1107  {
1108  freqs_set_t::iterator sIt = m_g14_alt_freq_set.begin();
1109  const freqs_set_t::iterator sItEnd = m_g14_alt_freq_set.end();
1110 
1111  for (; sIt != sItEnd; ++sIt)
1112  {
1113  retSet = (mIt->second).insert(*sIt);
1114  updated |= retSet.second;
1115  }
1116  }
1117 
1118  m_g14_alt_freq_set.clear();
1119  m_g14_data_available |= updated;
1120  }
1121 
1122  if (m_g14_mapped_freq_set.size() > 0)
1123  {
1124  //qDebug("RDSParser::decode_type14: m_g14_mapped_freq_set updated");
1125 
1126  std::pair<freqs_map_t::iterator, bool> retMap;
1127  std::pair<freqs_set_t::iterator, bool> retSet;
1128  bool updated = false;
1129 
1130  freqs_map_t::iterator mIt = m_g14_mapped_freqs.find(pi_on);
1131 
1132  if (mIt == m_g14_mapped_freqs.end()) // key does not exist yet => insert the whole set
1133  {
1134  retMap = m_g14_mapped_freqs.insert(freqs_map_kv_t(pi_on, m_g14_mapped_freq_set));
1135  updated |= retMap.second;
1136  }
1137  else // merge sets
1138  {
1139  freqs_set_t::iterator sIt = m_g14_mapped_freq_set.begin();
1140  const freqs_set_t::iterator sItEnd = m_g14_mapped_freq_set.end();
1141 
1142  for (; sIt != sItEnd; ++sIt)
1143  {
1144  retSet = (mIt->second).insert(*sIt);
1145  updated |= retSet.second;
1146  }
1147  }
1148 
1149  m_g14_mapped_freq_set.clear();
1150  m_g14_data_available |= updated;
1151  }
1152 
1153  /*
1154  std::string s = str(boost::format("Linkage information: %x%x") % ((information >> 8) & 0xff) % (information & 0xff));
1155  qDebug() << "RDSParser::decode_type14: " << s.c_str();*/
1156  break;
1157  }
1158  case 13: // PTY(ON), TA(ON)
1159  {
1160  ta_on = information & 0x01;
1161  //qDebug() << "RDSParser::decode_type14: PTY(ON):" << pty_table[int(pty_on)].c_str();
1162  if(ta_on) {
1163  qDebug() << "RDSParser::decode_type14: - TA";
1164  }
1165  break;
1166  }
1167  case 14: // PIN(ON)
1168  {
1169  /*
1170  std::string s = str(boost::format("PIN(ON):%x%x") % ((information >> 8) & 0xff) % (information & 0xff));
1171  qDebug() << "RDSParser::decode_type14: " << s.c_str();*/
1172  break;
1173  }
1174  case 15: // Reserved for broadcasters use
1175  break;
1176  default:
1177  //qDebug() << "RDSParser::decode_type14: invalid variant code:" << variant_code;
1178  break;
1179  }
1180  }
1181 
1182  /*
1183  if (pi_on)
1184  {
1185  std::string pistring = str(boost::format("%04X") % pi_on);
1186  qDebug() << "RDSParser::decode_type14: PI(ON):" << pistring.c_str();
1187 
1188  if (tp_on) {
1189  qDebug() << "RDSParser::decode_type14: TP(ON)";
1190  }
1191  }*/
1192 }
1193 
1194 void RDSParser::decode_type15(unsigned int *group, bool B)
1195 {
1196  (void) group;
1197  (void) B;
1198  qDebug() << "RDSParser::decode_type5: type 15 not implemented yet";
1199  m_g15_updated = true;
1200  m_g15_count++;
1201 }
1202 
unsigned int m_g0_count
Definition: rdsparser.h:58
unsigned int m_g6_count
Definition: rdsparser.h:108
unsigned int m_g8_event
Definition: rdsparser.h:118
unsigned int m_pi_program_identification
Definition: rdsparser.h:49
static const std::string rds_group_acronyms[16]
Definition: rdsparser.h:166
void decode_type0(unsigned int *group, bool B)
Definition: rdsparser.cpp:467
unsigned int m_g14_count
Definition: rdsparser.h:144
int m_g8_content
Definition: rdsparser.h:121
bool m_g11_updated
Definition: rdsparser.h:134
unsigned int m_pi_count
Definition: rdsparser.h:48
unsigned int m_g9_cA
Definition: rdsparser.h:127
bool m_g0_mono_stereo
Definition: rdsparser.h:63
unsigned int m_g4_seconds
Definition: rdsparser.h:97
void parseGroup(unsigned int *group)
Definition: rdsparser.cpp:374
unsigned int m_g2_count
Definition: rdsparser.h:81
bool log
Definition: rdsparser.h:198
bool m_g3_groupB
Definition: rdsparser.h:87
unsigned int m_g9_dB
Definition: rdsparser.h:130
void decode_type8(unsigned int *group, bool B)
Definition: rdsparser.cpp:852
unsigned int m_g9_dA
Definition: rdsparser.h:128
bool m_g10_updated
Definition: rdsparser.h:133
void clearAllFields()
Definition: rdsparser.cpp:270
static const std::string pty_table[32]
Definition: rdsparser.h:163
unsigned int m_g9_count
Definition: rdsparser.h:125
bool m_g1_updated
Definition: rdsparser.h:70
bool m_g7_updated
Definition: rdsparser.h:106
unsigned int m_g4_year
Definition: rdsparser.h:98
void decode_type12(unsigned int *group, bool B)
Definition: rdsparser.cpp:995
bool m_g6_updated
Definition: rdsparser.h:105
bool m_g0_compressed
Definition: rdsparser.h:65
std::set< double > m_g14_mapped_freq_set
Definition: rdsparser.h:150
psns_map_t m_g14_program_service_names
key: PI, value: PSN
Definition: rdsparser.h:145
void decode_type14(unsigned int *group, bool B)
Definition: rdsparser.cpp:1013
char m_g0_program_service_name[8+1]
Definition: rdsparser.h:59
unsigned int m_g10_count
Definition: rdsparser.h:137
bool debug
Definition: rdsparser.h:197
bool m_pi_traffic_program
Definition: rdsparser.h:51
unsigned int m_g14_psn_counter
Definition: rdsparser.h:151
bool m_g14_updated
Definition: rdsparser.h:143
void decode_type11(unsigned int *group, bool B)
Definition: rdsparser.cpp:986
freqs_map_t m_g14_mapped_freqs
key: PI, value: set of mapped frequencies (MHz)
Definition: rdsparser.h:147
bool m_g9_updated
Definition: rdsparser.h:124
bool m_g8_diversion_recommended
Definition: rdsparser.h:114
freqs_map_t m_g14_alt_freqs
key: PI, value: set of alternate frequencies (MHz)
Definition: rdsparser.h:146
void decode_type3(unsigned int *group, bool B)
Definition: rdsparser.cpp:728
static const unsigned int offset_pos[5]
Definition: rdsparser.h:159
unsigned char pi_country_identification
Definition: rdsparser.h:193
void decode_type1(unsigned int *group, bool B)
Definition: rdsparser.cpp:627
unsigned int m_g1_count
Definition: rdsparser.h:71
unsigned char m_pi_program_type
Definition: rdsparser.h:50
void decode_type9(unsigned int *group, bool B)
Definition: rdsparser.cpp:959
bool m_g2_updated
Definition: rdsparser.h:80
void decode_type10(unsigned int *group, bool B)
Definition: rdsparser.cpp:977
unsigned int m_g8_location
Definition: rdsparser.h:119
std::set< double > m_g14_alt_freq_set
Definition: rdsparser.h:149
unsigned int m_g1_pin_minute
Definition: rdsparser.h:77
unsigned int m_g8_extent
Definition: rdsparser.h:117
static const std::string rds_group_acronym_tags[16]
Definition: rdsparser.h:167
bool m_g14_data_available
Definition: rdsparser.h:152
static const std::string label_descriptions[16]
Definition: rdsparser.h:171
static const unsigned int syndrome[5]
Definition: rdsparser.h:161
static const std::string language_codes[44]
Definition: rdsparser.h:168
unsigned int m_g1_pin_day
Definition: rdsparser.h:75
bool m_g0_traffic_announcement
Definition: rdsparser.h:61
unsigned int m_g9_varB
Definition: rdsparser.h:129
unsigned int m_g11_count
Definition: rdsparser.h:138
int m_g1_country_index
negative if not received
Definition: rdsparser.h:73
bool m_g0_updated
Definition: rdsparser.h:56
unsigned int m_g4_minutes
Definition: rdsparser.h:96
void decode_type2(unsigned int *group, bool B)
Definition: rdsparser.cpp:694
unsigned char m_g0_psn_bitmap
Definition: rdsparser.h:60
unsigned char pi_program_reference_number
Definition: rdsparser.h:194
std::set< double > m_g0_alt_freq
Definition: rdsparser.h:67
unsigned int m_g7_count
Definition: rdsparser.h:109
unsigned int m_g4_month
Definition: rdsparser.h:99
char m_g2_radiotext[64+1]
Definition: rdsparser.h:82
double decode_af(unsigned int)
Definition: rdsparser.cpp:588
static const std::string pi_country_codes[15][5]
Definition: rdsparser.h:164
static const unsigned int offset_word[5]
Definition: rdsparser.h:160
int32_t i
Definition: decimators.h:244
bool m_g0_af_updated
Definition: rdsparser.h:57
unsigned int m_g8_dp_ci
Definition: rdsparser.h:115
unsigned int m_g3_appGroup
Definition: rdsparser.h:88
void decode_type13(unsigned int *group, bool B)
Definition: rdsparser.cpp:1004
unsigned int m_g8_count
Definition: rdsparser.h:113
static const std::string coverage_area_codes[16]
Definition: rdsparser.h:165
unsigned int m_g9_varA
Definition: rdsparser.h:126
static const char *const offset_name[]
Definition: rdsparser.h:162
int m_g8_label_index
negative if not received
Definition: rdsparser.h:120
bool radiotext_AB_flag
Definition: rdsparser.h:196
static const int optional_content_lengths[16]
Definition: rdsparser.h:170
unsigned int m_g3_message
Definition: rdsparser.h:89
std::pair< unsigned int, std::string > psns_map_kv_t
Definition: rdsparser.h:30
unsigned int m_g4_day
Definition: rdsparser.h:100
bool m_g5_updated
Definition: rdsparser.h:104
bool m_pi_updated
Definition: rdsparser.h:47
bool m_g3_updated
Definition: rdsparser.h:85
int m_g1_language_index
negative if not received
Definition: rdsparser.h:74
static int get_tmc_event_code_index(unsigned int i, unsigned int j)
Definition: rdstmc.cpp:3703
unsigned int m_g12_count
Definition: rdsparser.h:139
unsigned int m_g5_count
Definition: rdsparser.h:107
unsigned int m_g1_pin_hour
Definition: rdsparser.h:76
int m_pi_area_coverage_index
Definition: rdsparser.h:53
bool m_g8_updated
Definition: rdsparser.h:112
unsigned int m_g15_count
Definition: rdsparser.h:156
bool m_g4_updated
Definition: rdsparser.h:93
bool m_g0_music_speech
Definition: rdsparser.h:62
unsigned int m_g3_aid
Definition: rdsparser.h:90
bool m_g0_static_pty
Definition: rdsparser.h:66
void decode_type6(unsigned int *group, bool B)
Definition: rdsparser.cpp:836
unsigned int m_g3_count
Definition: rdsparser.h:86
unsigned int m_g4_count
Definition: rdsparser.h:94
static const std::string tmc_duration[8][2]
Definition: rdsparser.h:169
void clearUpdateFlags()
Definition: rdsparser.cpp:244
int m_g1_country_page_index
negative if not received
Definition: rdsparser.h:72
bool m_g8_sign
Definition: rdsparser.h:116
void decode_type4(unsigned int *group, bool B)
Definition: rdsparser.cpp:791
int m_pi_country_identification
Definition: rdsparser.h:52
unsigned int m_g13_count
Definition: rdsparser.h:140
bool m_g15_updated
Definition: rdsparser.h:155
char m_g14_program_service_name[8+1]
Definition: rdsparser.h:148
double m_g4_local_time_offset
Definition: rdsparser.h:101
void decode_type7(unsigned int *group, bool B)
Definition: rdsparser.cpp:844
static std::string get_tmc_events(unsigned int i, unsigned int j)
Definition: rdstmc.cpp:3698
unsigned int m_g4_hours
Definition: rdsparser.h:95
void decode_optional_content(int, unsigned long int *)
Definition: rdsparser.cpp:932
std::pair< unsigned int, std::set< double > > freqs_map_kv_t
Definition: rdsparser.h:32
void decode_type15(unsigned int *group, bool B)
Definition: rdsparser.cpp:1194
void decode_type5(unsigned int *group, bool B)
Definition: rdsparser.cpp:828
bool m_g12_updated
Definition: rdsparser.h:135
bool m_g0_artificial_head
Definition: rdsparser.h:64
bool m_g13_updated
Definition: rdsparser.h:136