@@ -22,6 +22,98 @@ namespace rds {
2222 { BLOCK_TYPE_D, 0b0110110100 }
2323 };
2424
25+ std::map<uint16_t , const char *> THREE_LETTER_CALLS = {
26+ { 0x99A5 , " KBW" },
27+ { 0x99A6 , " KCY" },
28+ { 0x9990 , " KDB" },
29+ { 0x99A7 , " KDF" },
30+ { 0x9950 , " KEX" },
31+ { 0x9951 , " KFH" },
32+ { 0x9952 , " KFI" },
33+ { 0x9953 , " KGA" },
34+ { 0x9991 , " KGB" },
35+ { 0x9954 , " KGO" },
36+ { 0x9955 , " KGU" },
37+ { 0x9956 , " KGW" },
38+ { 0x9957 , " KGY" },
39+ { 0x99AA , " KHQ" },
40+ { 0x9958 , " KID" },
41+ { 0x9959 , " KIT" },
42+ { 0x995A , " KJR" },
43+ { 0x995B , " KLO" },
44+ { 0x995C , " KLZ" },
45+ { 0x995D , " KMA" },
46+ { 0x995E , " KMJ" },
47+ { 0x995F , " KNX" },
48+ { 0x9960 , " KOA" },
49+ { 0x99AB , " KOB" },
50+ { 0x9992 , " KOY" },
51+ { 0x9993 , " KPQ" },
52+ { 0x9964 , " KQV" },
53+ { 0x9994 , " KSD" },
54+ { 0x9965 , " KSL" },
55+ { 0x9966 , " KUJ" },
56+ { 0x9995 , " KUT" },
57+ { 0x9967 , " KVI" },
58+ { 0x9968 , " KWG" },
59+ { 0x9996 , " KXL" },
60+ { 0x9997 , " KXO" },
61+ { 0x996B , " KYW" },
62+ { 0x9999 , " WBT" },
63+ { 0x996D , " WBZ" },
64+ { 0x996E , " WDZ" },
65+ { 0x996F , " WEW" },
66+ { 0x999A , " WGH" },
67+ { 0x9971 , " WGL" },
68+ { 0x9972 , " WGN" },
69+ { 0x9973 , " WGR" },
70+ { 0x999B , " WGY" },
71+ { 0x9975 , " WHA" },
72+ { 0x9976 , " WHB" },
73+ { 0x9977 , " WHK" },
74+ { 0x9978 , " WHO" },
75+ { 0x999C , " WHP" },
76+ { 0x999D , " WIL" },
77+ { 0x997A , " WIP" },
78+ { 0x99B3 , " WIS" },
79+ { 0x997B , " WJR" },
80+ { 0x99B4 , " WJW" },
81+ { 0x99B5 , " WJZ" },
82+ { 0x997C , " WKY" },
83+ { 0x997D , " WLS" },
84+ { 0x997E , " WLW" },
85+ { 0x999E , " WMC" },
86+ { 0x999F , " WMT" },
87+ { 0x9981 , " WOC" },
88+ { 0x99A0 , " WOI" },
89+ { 0x9983 , " WOL" },
90+ { 0x9984 , " WOR" },
91+ { 0x99A1 , " WOW" },
92+ { 0x99B9 , " WRC" },
93+ { 0x99A2 , " WRR" },
94+ { 0x99A3 , " WSB" },
95+ { 0x99A4 , " WSM" },
96+ { 0x9988 , " WWJ" },
97+ { 0x9989 , " WWL" }
98+ };
99+
100+ std::map<uint16_t , const char *> NAT_LOC_LINKED_STATIONS = {
101+ { 0xB01 , " NPR-1" },
102+ { 0xB02 , " CBC - Radio One" },
103+ { 0xB03 , " CBC - Radio Two" },
104+ { 0xB04 , " Radio-Canada - Première Chaîne" },
105+ { 0xB05 , " Radio-Canada - Espace Musique" },
106+ { 0xB06 , " CBC" },
107+ { 0xB07 , " CBC" },
108+ { 0xB08 , " CBC" },
109+ { 0xB09 , " CBC" },
110+ { 0xB0A , " NPR-2" },
111+ { 0xB0B , " NPR-3" },
112+ { 0xB0C , " NPR-4" },
113+ { 0xB0D , " NPR-5" },
114+ { 0xB0E , " NPR-6" }
115+ };
116+
25117 // 9876543210
26118 const uint16_t LFSR_POLY = 0b0110111001 ;
27119 const uint16_t IN_POLY = 0b1100011011 ;
@@ -146,7 +238,7 @@ namespace rds {
146238 countryCode = (blocks[BLOCK_TYPE_A] >> 22 ) & 0xF ;
147239 programCoverage = (AreaCoverage)((blocks[BLOCK_TYPE_A] >> 18 ) & 0xF );
148240 programRefNumber = (blocks[BLOCK_TYPE_A] >> 10 ) & 0xFF ;
149- decodeCallsign ();
241+ callsign = decodeCallsign (piCode );
150242
151243 // Update timeout
152244 blockALastUpdate = std::chrono::high_resolution_clock::now ();;
@@ -287,7 +379,7 @@ namespace rds {
287379 // Decode block B
288380 decodeBlockB ();
289381
290- // flog::debug("RDS Group {}{}", groupType, (groupVer == GROUP_VER_A) ? 'A':'B');
382+ flog::debug (" RDS Group {}{}" , groupType, (groupVer == GROUP_VER_A) ? ' A' :' B' );
291383
292384 // Decode depending on group type
293385 switch (groupType) {
@@ -305,14 +397,14 @@ namespace rds {
305397 }
306398 }
307399
308- void Decoder::decodeCallsign ( ) {
400+ std::string Decoder::base26ToCall ( uint16_t pi ) {
309401 // Determin first better based on offset
310- bool w = (piCode >= 21672 );
311- callsign = w ? ' W ' : ' K ' ;
402+ bool w = (pi >= 21672 );
403+ std::string callsign ( w ? " W " : " K " ) ;
312404
313405 // Base25 decode the rest
314406 std::string restStr;
315- int rest = piCode - (w ? 21672 : 4096 );
407+ int rest = pi - (w ? 21672 : 4096 );
316408 while (rest) {
317409 restStr += ' A' + (rest % 26 );
318410 rest /= 26 ;
@@ -322,6 +414,49 @@ namespace rds {
322414 for (int i = restStr.size () - 1 ; i >= 0 ; i--) {
323415 callsign += restStr[i];
324416 }
417+
418+ return callsign;
419+ }
420+
421+ std::string Decoder::decodeCallsign (uint16_t pi) {
422+ if ((pi >> 8 ) == 0xAF ) {
423+ // AFXY -> XY00
424+ return base26ToCall ((pi & 0xFF ) << 8 );
425+ }
426+ else if ((pi >> 12 ) == 0xA ) {
427+ // AXYZ -> X0YZ
428+ return base26ToCall ((((pi >> 8 ) & 0xF ) << 12 ) | (pi & 0xFF ));
429+ }
430+ else if (pi >= 0x9950 && pi <= 0x9EFF ) {
431+ // 3 letter callsigns
432+ if (THREE_LETTER_CALLS.find (pi) != THREE_LETTER_CALLS.end ()) {
433+ return THREE_LETTER_CALLS[pi];
434+ }
435+ else {
436+ return " Not Assigned" ;
437+ }
438+ }
439+ else if (pi >= 0x1000 && pi <= 0x994F ) {
440+ // Normal encoding
441+ if ((pi & 0xFF ) == 0 || ((pi >> 8 ) & 0xF ) == 0 ) {
442+ return " Not Assigned" ;
443+ }
444+ else {
445+ return base26ToCall (pi);
446+ }
447+ }
448+ else if (pi >= 0xB000 && pi <= 0xEFFF ) {
449+ uint16_t _pi = ((pi >> 12 ) << 8 ) | (pi & 0xFF );
450+ if (NAT_LOC_LINKED_STATIONS.find (_pi) != NAT_LOC_LINKED_STATIONS.end ()) {
451+ return NAT_LOC_LINKED_STATIONS[_pi];
452+ }
453+ else {
454+ return " Not Assigned" ;
455+ }
456+ }
457+ else {
458+ return " Not Assigned" ;
459+ }
325460 }
326461
327462 bool Decoder::blockAValid () {
0 commit comments