]> git.kernelconcepts.de Git - rdstmc.git/blob - decoder/tmc.c
Make CC optional (so cross CC will override)
[rdstmc.git] / decoder / tmc.c
1 /*
2  * Copyright (C) 2009, 2010 by Nils Faerber <nils.faerber@kernelconcepts.de>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version
7  * 2 of the License, or (at your option) any later version.
8  *
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <time.h>
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <limits.h>
19
20 #include <sqlite3.h>
21
22 #include "rds.h"
23 #include "bitstream.h"
24 #include "tmc.h"
25 #include "tmc_consts.h"
26
27 // #define DEBUG 1
28
29 static struct TMC_info tmc_info;
30 static struct TMC_msg cur_tmc_msg;
31 static char tmc_msg_str[4096];
32 static char *tmc_msg_ptr = tmc_msg_str;
33
34 static struct _TMC_Private {
35         void (*tmc_sid_cb)(char *sid_text, void *user_data);
36         void *tmc_sid_cb_data;
37         void (*tmc_msg_cb)(char *msg, void *user_data);
38         void *tmc_msg_cb_data;
39 } _tmc_private;
40
41 void tmc_init(void)
42 {
43         memset(&_tmc_private, 0, sizeof(struct _TMC_Private));
44 }
45
46 void tmc_set_sid_cb(void (*tmc_sid_cb)(char *sid_text, void *user_data), void *user_data)
47 {
48         _tmc_private.tmc_sid_cb = tmc_sid_cb;
49         _tmc_private.tmc_sid_cb_data = user_data;
50 }
51
52 static void reset_msg_buf(void)
53 {
54         tmc_msg_ptr = tmc_msg_str;
55         memset(tmc_msg_str, 0, 4096);
56 }
57
58 void tmc_set_msg_cb(void (*tmc_msg_cb)(char *msg, void *user_data), void *user_data)
59 {
60         reset_msg_buf();
61         _tmc_private.tmc_msg_cb = tmc_msg_cb;
62         _tmc_private.tmc_msg_cb_data = user_data;
63 }
64
65 void interpret_tmc(int event, int location, int extent, int CI, int direction)
66 {
67 char sql[256]="";
68 sqlite3_stmt *ppstmt;
69 int neg_off=0, pos_off=0, lin_ref=0;
70 char road_nr[256]="", fst_name[256]="";
71 char rdir1[256]="", rdir2[256]="";
72 char last_name[256]="";
73 char evt_str[256]="";
74 char type_str1[128]="";
75 char type_str2[128]="";
76 char typechr;
77 int typenr, subtype;
78
79         if (CI != cur_tmc_msg.CI || CI == -1) {
80                 //printf("GF evt=%d loc=%d ext=%d CI=%d dir=%d", event, location, extent, CI, direction);
81                 //printf("ev=%d ", event);
82                 snprintf(sql, 256, "select ROADNUMBER,FIRST_NAME,NEGATIVE_OFFSET,POSITIVE_OFFSET,LINEAR_REFERENCE,TYPE,SUBTYPE from lcl where LOCATIONCODE=%d", location);
83                 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
84                 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
85 #ifdef DEBUG
86                         printf("lcl.db failed to get location %d event %d\n", location, event);
87 #endif
88                         // return; // we cannot do much without location
89                 } else {
90                         neg_off = sqlite3_column_int(ppstmt, 2);
91                         pos_off = sqlite3_column_int(ppstmt, 3);
92                         lin_ref = sqlite3_column_int(ppstmt, 4);
93                         strncpy(road_nr, (char *)sqlite3_column_text(ppstmt, 0), 255);
94                         strncpy(fst_name, (char *)sqlite3_column_text(ppstmt, 1), 255);
95                         strncpy(type_str1, (char *)sqlite3_column_text(ppstmt, 5), 128);
96                         subtype = sqlite3_column_int(ppstmt, 6);
97                         typechr = type_str1[0];
98                         typenr = atoi(&type_str1[1]);
99                         // printf(" type=%c %d stype=%d\n", typechr, typenr, subtype);
100                         snprintf(sql, 256, "select SNATDESC from lcl_supc where CLASS='%c' AND TCD=%d AND STCD=%d", typechr, typenr, subtype);
101                         sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
102                         if (sqlite3_step(ppstmt) != SQLITE_ROW) {
103 #ifdef DEBUG
104                                 printf("lcl.db failed to get suptype %c %d stype=%d\n", typechr, typenr, subtype);
105 #endif
106                         } else {
107                                 strncpy(type_str1, (char *)sqlite3_column_text(ppstmt, 0), 128);                        
108                         }
109                         if (lin_ref != 0) {
110                                 snprintf(sql, 256, "select FIRST_NAME,SECOND_NAME from lcl where LOCATIONCODE=%d", lin_ref);
111                                 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
112                                 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
113 #ifdef DEBUG
114                                         printf("lcl.db failed to get linear ref %d\n", lin_ref);
115 #endif
116                                 } else {
117                                         if (!direction) {
118                                                 strncpy(rdir1, (char *)sqlite3_column_text(ppstmt, 1), 255);
119                                                 strncpy(rdir2, (char *)sqlite3_column_text(ppstmt, 0), 255);
120                                         } else {
121                                                 strncpy(rdir1, (char *)sqlite3_column_text(ppstmt, 0), 255);
122                                                 strncpy(rdir2, (char *)sqlite3_column_text(ppstmt, 1), 255);
123                                         }
124                                 }
125                         }
126                         if (extent > 0) {
127                                 // printf("%s ab %s ", road_nr, fst_name);
128                                 if (direction) {
129                                         /* neg */
130                                         while (extent--) {
131                                                 snprintf(sql, 256, "select ROADNUMBER,FIRST_NAME,NEGATIVE_OFFSET,POSITIVE_OFFSET,TYPE,SUBTYPE from lcl where LOCATIONCODE=%d", neg_off);
132                                                 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
133                                                 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
134 #ifdef DEBUG
135                                                         printf("lcl.db failed to get location %d\n", location);
136 #endif
137                                                         break;
138                                                 } else
139                                                         neg_off = sqlite3_column_int(ppstmt, 2);
140                                         }
141                                         //printf("bis %s\n", (char *)sqlite3_column_text(ppstmt, 1));
142                                 } else {
143                                         /* pos */
144                                         while (extent--) {
145                                                 snprintf(sql, 256, "select ROADNUMBER,FIRST_NAME,NEGATIVE_OFFSET,POSITIVE_OFFSET,TYPE,SUBTYPE from lcl where LOCATIONCODE=%d", pos_off);
146                                                 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
147                                                 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
148 #ifdef DEBUG
149                                                         printf("lcl.db failed to get location %d\n", location);
150 #endif
151                                                         break;
152                                                 } else
153                                                         pos_off = sqlite3_column_int(ppstmt, 3);
154                                         }
155                                         //printf("bis %s\n", (char *)sqlite3_column_text(ppstmt, 1));
156                                 }
157                                 strncpy(last_name, (char *)sqlite3_column_text(ppstmt, 1), 255);
158                                 extent=1;
159                                 strncpy(type_str2, (char *)sqlite3_column_text(ppstmt, 4), 128);
160                                 subtype = sqlite3_column_int(ppstmt, 5);
161                                 typechr = type_str2[0];
162                                 typenr = atoi(&type_str2[1]);
163                                 // printf(" type=%c %d stype=%d\n", typechr, typenr, subtype);
164                                 snprintf(sql, 256, "select SNATDESC from lcl_supc where CLASS='%c' AND TCD=%d AND STCD=%d", typechr, typenr, subtype);
165                                 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
166                                 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
167 #ifdef DEBUG
168                                         printf("lcl.db failed to get suptype %c %d stype=%d\n", typechr, typenr, subtype);
169 #endif
170                                 } else {
171                                         strncpy(type_str2, (char *)sqlite3_column_text(ppstmt, 0), 128);
172                                 }
173                         }
174                 }
175                 snprintf(sql, 256, "select TEXT_DE_NOQUANT from evl where CODE=%d", event);
176                 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
177                 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
178 #ifdef DEBUG
179                         printf("lcl.db failed to get event %d\n", event);
180 #endif
181                 } else {
182                         strncpy(evt_str, (char *)sqlite3_column_text(ppstmt, 0), 255);
183                 }
184                 if (CI != -1)
185                         cur_tmc_msg.CI = CI;
186
187                 // here goes the message ;)
188                 if (lin_ref != 0)
189                         tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s %s - %s,\n", road_nr, rdir1, rdir2);
190                 if (location == 64777) {
191                         tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s\n", evt_str);
192                 } else {
193                         if (extent)
194                                 if (direction)
195                                         tmc_msg_ptr += sprintf(tmc_msg_ptr, "zwischen %s %s und %s %s\n%s\n", type_str1, fst_name, type_str2, last_name, evt_str);
196                                 else
197                                         tmc_msg_ptr += sprintf(tmc_msg_ptr, "zwischen %s %s und %s %s\n%s\n", type_str2, last_name, type_str1, fst_name, evt_str);
198                         else
199                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, "in Höhe %s %s\n%s\n", type_str1, fst_name, evt_str);
200                 }
201         }
202 }
203
204 void parse_tmc_single(unsigned short *rdsgroup)
205 {
206 unsigned short event = cur_tmc_msg.msgs[0][1] & 0x7FF;
207 unsigned short location = cur_tmc_msg.msgs[0][2];
208 unsigned char extent = (cur_tmc_msg.msgs[0][1] & ((0x07) << 11)) >> 11;
209 unsigned char dir = (cur_tmc_msg.msgs[0][1] & ((0x01) << 14)) >> 14;
210 static unsigned short oevent=0;
211 static unsigned short olocation=0;
212
213 #ifdef DEBUG
214         printf(" single group\n");
215 #endif
216         if (olocation != location && oevent != event) {
217                 interpret_tmc(event, location, extent, -1, dir);
218                 olocation = location;
219                 oevent = event;
220                 if (_tmc_private.tmc_msg_cb != NULL) {
221                         _tmc_private.tmc_msg_cb(tmc_msg_str, _tmc_private.tmc_msg_cb_data);
222                 }
223                 reset_msg_buf();
224         }
225 }
226
227 char *replace_str(char *str, char *orig, char *rep)
228 {
229 static char buffer[4096];
230 char *p;
231
232         if(!(p = strstr(str, orig)))  // Is 'orig' even in 'str'?
233                 return str;
234
235         strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
236         buffer[p-str] = '\0';
237
238         sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
239
240 return buffer;
241 }
242
243 void interpret_tmc_multi(void)
244 {
245 int i;
246 unsigned short event = cur_tmc_msg.msgs[0][1] & 0x7FF;
247 unsigned short location = cur_tmc_msg.msgs[0][2];
248 unsigned char extent = (cur_tmc_msg.msgs[0][1] & (0x07 << 11)) >> 11;
249 unsigned char dir = (cur_tmc_msg.msgs[0][1] & (0x01 << 14)) >> 14;
250 unsigned char label;
251 unsigned short aevent;
252 char sql[256]="";
253 sqlite3_stmt *ppstmt;
254 char evt_str[256]="";
255 char lofrstr[16]="";
256 unsigned char ext_buf[256];
257
258 #ifdef DEBUG
259         printf("interpret_tmc_multi: sz=%d\n", cur_tmc_msg.msgsz);
260         for (i=0; i<cur_tmc_msg.msgsz; i++) {
261                 printf(" #%d 0x%04x 0x%04x 0x%04x\n", i, cur_tmc_msg.msgs[i][0], cur_tmc_msg.msgs[i][1], cur_tmc_msg.msgs[i][2]);
262         }
263
264         printf("TMC event=%d loc=%d ext=%d dir=%d\n", event, location, extent, dir);
265 #endif
266
267         interpret_tmc(event, location, extent, -1, dir);
268
269
270         for (i=0; i < cur_tmc_msg.msgsz; i++) {
271                 ext_buf[i*4] = (cur_tmc_msg.msgs[i+1][1] & 0xff00) >> 8;
272                 ext_buf[(i*4)+1] = cur_tmc_msg.msgs[i+1][1] & 0xff;
273                 ext_buf[(i*4)+2] = (cur_tmc_msg.msgs[i+1][2] & 0xff00) >> 8;
274                 ext_buf[(i*4)+3] = cur_tmc_msg.msgs[i+1][2] & 0xff;
275         };
276         bitstream_start(ext_buf, cur_tmc_msg.msgsz*4);
277
278         bitstream_get_next_bits(4);
279
280         while (bitstream_bits_remaining() > 0) {
281                 label = bitstream_get_next_bits(4);
282 #ifdef DEBUG
283                 if (OutputFlags & RDS_OUTPUT_TMC) {
284                         printf("o  '%s' %x\n", EVNT_LABEL[label], label);
285                 }
286 #endif
287                 if (label == 0) {
288                         unsigned char dur=0;
289
290                         dur = bitstream_get_next_bits(3);
291                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " dur=%d\n", dur);
292                 }
293                 if (label == 1) {
294                         unsigned char ctrlcd=0;
295
296                         ctrlcd = bitstream_get_next_bits(3);
297                         if (ctrlcd == 2)
298                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, "in beiden Richtungen\n");
299                         else
300                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ctrlcd=%d\n", ctrlcd);
301                 }
302                 if (label == 2) {
303                         unsigned int lofr=0;
304
305                         lofr = bitstream_get_next_bits(5);
306                         if (lofr == 0) {
307                                 printf("shit - more than 100km\n");
308                                 strcpy(lofrstr, ">100 km");
309                         }
310                         if (lofr>0 && lofr<11) {
311                                 printf("lofr = %dkm\n", lofr);
312                                 sprintf(lofrstr, "%d km", lofr);
313                         }
314                         if (lofr>10 && lofr<16) {
315                                 printf("lofr = %dkm\n", 12 + ((lofr-11)*2));
316                                 sprintf(lofrstr, "%d km", 12 + ((lofr-11)*2));
317                         }
318                         if (lofr>15 && lofr<32)
319                                 printf("lofr = %dkm\n", 25 + ((lofr-16)*5));
320                                 sprintf(lofrstr, "%d km", 25 + ((lofr-16)*5));
321                 }
322                 if (label == 3) {
323                         unsigned int slim=0;
324
325                         slim = bitstream_get_next_bits(5);
326                         if (slim > 0)
327                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " slim = %d km/h\n", slim*5);
328                 }
329                 if (label == 4) {
330                         unsigned int quant5=0;
331
332                         quant5 = bitstream_get_next_bits(5);
333                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " quant5 = %d km\n", quant5);
334                 }
335                 if (label == 5) {
336                         unsigned int quant8=0;
337
338                         quant8 = bitstream_get_next_bits(8);
339                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " quant8 = %d km\n", quant8);
340                 }
341                 if (label == 6) {
342                         unsigned char supinfo=0;
343
344                         supinfo = bitstream_get_next_bits(8);
345 #ifdef DEBUG
346                         printf(" supinfo = %d\n", supinfo);
347 #endif
348                         snprintf(sql, 256, "select TEXT_DE from ev_sup where CODE=%d", supinfo);
349                         sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
350                         if (sqlite3_step(ppstmt) != SQLITE_ROW) {
351 #ifdef DEBUG
352                                 printf("lcl.db failed to get ev_sup %d\n", supinfo);
353 #endif
354                         } else {
355                                 strncpy(evt_str, (char *)sqlite3_column_text(ppstmt, 0), 255);
356                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s\n", evt_str);
357                         }
358                 }
359                 if (label == 7) {
360                         unsigned int stime=0;
361
362                         stime = bitstream_get_next_bits(8);
363                         // printf(" stime = %d\n", stime);
364                         if (stime < 96) {
365                                 stime *= 15; // 15 min internval
366                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab %02d:%02d\n", (stime / 60), (stime % 60));
367                         } else if (stime < 201) {
368                                 stime -= 96;
369                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab %d Tage, %d:00 Uhr\n", (stime / 24), (stime % 24));
370                         } else if (stime < 232) {
371                                 stime -= 201;
372                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab dem %d.\n", stime+1);
373                         } else {
374                                 stime -= 232;
375                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab %s. %s\n", (stime % 2) ? "31":"15", monthname[stime / 2]);
376                         }
377                 }
378                 if (label == 8) {
379                         unsigned int etime=0;
380
381                         etime = bitstream_get_next_bits(8);
382                         // printf(" etime = %d\n", etime);
383                         if (etime < 96) {
384                                 etime *= 15; // 15 min internval
385                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis vor. %02d:%02d\n", (etime / 60), (etime % 60));
386                         } else if (etime < 201) {
387                                 etime -= 96;
388                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis %d Tage, %d:00 Uhr\n", (etime / 24), (etime % 24));
389                         } else if (etime < 232) {
390                                 etime -= 201;
391                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis zum %d.\n", etime+1);
392                         } else {
393                                 etime -= 232;
394                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis etwa %s. %s\n", (etime % 2) ? "31":"15", monthname[etime / 2]);
395                         }
396                 }
397                 if (label == 9) {
398                         aevent = bitstream_get_next_bits(11);
399 #ifdef DEBUG
400                         printf(" aevent = %d ", aevent);
401 #endif
402                         snprintf(sql, 256, "select TEXT_DE_NOQUANT from evl where CODE=%d", aevent);
403                         sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
404                         if (sqlite3_step(ppstmt) != SQLITE_ROW) {
405 #ifdef DEBUG
406                                 printf("-lcl.db failed to get event %d\n", aevent);
407 #endif
408                         } else {
409                                 strncpy(evt_str, (char *)sqlite3_column_text(ppstmt, 0), 255);
410                                 if (strlen(lofrstr) != 0 && strstr(evt_str,"(L)")!=NULL) {
411                                         replace_str(evt_str, "(L)", lofrstr);
412                                 }
413                                 tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s\n", evt_str);
414                         }
415                 }
416                 if (label == 10) {
417                         unsigned char div;
418
419                         div = bitstream_get_next_bits(16);
420                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " div = %d\n", div);
421                 }
422                 if (label == 11) {
423                         unsigned char dest;
424
425                         dest = bitstream_get_next_bits(16);
426                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " dest = %d\n", dest);
427                 }
428                 if (label == 12) {
429                         unsigned char res;
430
431                         res = bitstream_get_next_bits(16);
432                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " res = %d\n", res);
433                 }
434                 if (label == 13) {
435                         unsigned char clink;
436
437                         clink = bitstream_get_next_bits(16);
438                         tmc_msg_ptr += sprintf(tmc_msg_ptr, " clink = %d\n", clink);
439                 }
440                 if (label == 14) {
441                         // tmc_msg_ptr += sprintf(tmc_msg_ptr, " seperator\n");
442                 }
443                 if (label == 15) {
444 #ifdef DEBUG
445                         printf(" res\n");
446 #endif
447                 }
448         }
449 #ifdef DEBUGx
450         if (cur_tmc_msg.msgsz > 2) {
451                 for (i=2; i<cur_tmc_msg.msgsz; i++) {
452                         printf(" #%d 0x%04x 0x%04x 0x%04x\n", i, cur_tmc_msg.msgs[i][0], cur_tmc_msg.msgs[i][1], cur_tmc_msg.msgs[i][2]);
453                 }
454         }
455 #endif
456         if (_tmc_private.tmc_msg_cb != NULL) {
457                 _tmc_private.tmc_msg_cb(tmc_msg_str, _tmc_private.tmc_msg_cb_data);
458         }
459         reset_msg_buf();
460 }
461
462 void parse_tmc_multi(unsigned short *rdsgroup)
463 {
464 unsigned char GSI = (rdsgroup[2] & 0x3000) >> 12;
465 static unsigned char oGSI = 0;
466 #ifdef DEBUG
467 unsigned char CI = rdsgroup[1] & 0x07;
468 #endif
469
470 #ifdef DEBUG
471         printf(" multi CI=%d ", CI);
472 #endif
473         if (rdsgroup[2] & 0x8000) {
474                 if (cur_tmc_msg.msgsz > 0) {
475                         interpret_tmc_multi();
476                         cur_tmc_msg.msgsz = 0;
477                 }
478 #ifdef DEBUG
479                 printf(" #1 GSI=%d\n", GSI);
480 #endif
481                 oGSI = 0;
482                 memset(&cur_tmc_msg.msgs, 0, 6*3*sizeof(short));
483                 cur_tmc_msg.msgs[0][0] = rdsgroup[1];
484                 cur_tmc_msg.msgs[0][1] = rdsgroup[2];
485                 cur_tmc_msg.msgs[0][2] = rdsgroup[3];
486                 //msgsz = 1;
487         } else {
488                 if (rdsgroup[2] & 0x4000) {
489                         // printf(" #2 GSI=%d\n", GSI);
490                         cur_tmc_msg.msgs[1][0] = rdsgroup[1];
491                         cur_tmc_msg.msgs[1][1] = rdsgroup[2];
492                         cur_tmc_msg.msgs[1][2] = rdsgroup[3];
493                         cur_tmc_msg.msgsz = 2;
494                 } else {
495                         if (oGSI == 0) {
496                                 oGSI = GSI;
497                         }
498                         // printf(" #%d GSI=%d (oGSI=%d)\n", 2+(oGSI-GSI), GSI, oGSI);
499                         cur_tmc_msg.msgs[2+(oGSI-GSI)][0] = rdsgroup[1];
500                         cur_tmc_msg.msgs[2+(oGSI-GSI)][1] = rdsgroup[2];
501                         cur_tmc_msg.msgs[2+(oGSI-GSI)][2] = rdsgroup[3];
502                         cur_tmc_msg.msgsz = 2+(oGSI-GSI);
503                 }
504         }
505         // printf("  0x%04x 0x%04x\n", rdsgroup[2], rdsgroup[3]);
506 }
507
508 enum TMCtype { TMC_GROUP=0,  TMC_SINGLE,  TMC_SYSTEM,  TMC_TUNING };
509
510 void decode_tmc(unsigned short *rdsgroup)
511 {
512 unsigned char X4 = (rdsgroup[1] & 0x10) >> 4;
513 unsigned char X3 = (rdsgroup[1] & 0x08) >> 3;
514 unsigned char X0X2 = rdsgroup[1] & 0x07;
515 //static unsigned char tmc_provider[9] = "";
516
517         if (X4 == 0) { // User message
518                 if (X3 == 1) { // single group msg
519                         parse_tmc_single(rdsgroup);
520                 } else { // multi group msg
521                         if (X0X2 > 0) {
522                                 parse_tmc_multi(rdsgroup);
523                         }
524 #ifdef DEBUG
525                         else
526                                 printf("err... X0X2(CI) = %d\n", X0X2);
527 #endif
528                 }
529         } else {
530                 if (X3 == 1) {
531                         //printf(" tuning?\n");
532                 } else {
533                         // printf(" system ");
534                         if (X0X2 == 4) {
535                                 tmc_info.provider_str[0] = (rdsgroup[2] & 0xff00) >> 8;
536                                 tmc_info.provider_str[1] = rdsgroup[2] & 0xff;
537                                 tmc_info.provider_str[2] = (rdsgroup[3] & 0xff00) >> 8;
538                                 tmc_info.provider_str[3] = rdsgroup[3] & 0xff;
539                                 if (_tmc_private.tmc_sid_cb != NULL)
540                                         _tmc_private.tmc_sid_cb(tmc_info.provider_str, _tmc_private.tmc_sid_cb_data);
541                                 if (OutputFlags & RDS_OUTPUT_TMC)
542                                         printf("provider = '%s'\n", tmc_info.provider_str);
543                         } else if (X0X2 == 5) {
544                                 tmc_info.provider_str[4] = (rdsgroup[2] & 0xff00) >> 8;
545                                 tmc_info.provider_str[5] = rdsgroup[2] & 0xff;
546                                 tmc_info.provider_str[6] = (rdsgroup[3] & 0xff00) >> 8;
547                                 tmc_info.provider_str[7] = rdsgroup[3] & 0xff;
548                                 if (_tmc_private.tmc_sid_cb != NULL)
549                                         _tmc_private.tmc_sid_cb(tmc_info.provider_str, _tmc_private.tmc_sid_cb_data);
550                                 if (OutputFlags & RDS_OUTPUT_TMC)
551                                         printf("provider = '%s'\n", tmc_info.provider_str);
552                         }
553 #ifdef DEBUG
554                          else
555                                 printf("X0X2(CI)=%d \n", X0X2);
556 #endif
557                 }
558         }
559 }
560