2 * Copyright (C) 2009, 2010 by Nils Faerber <nils.faerber@kernelconcepts.de>
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.
23 #include "bitstream.h"
25 #include "tmc_consts.h"
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;
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;
43 memset(&_tmc_private, 0, sizeof(struct _TMC_Private));
46 void tmc_set_sid_cb(void (*tmc_sid_cb)(char *sid_text, void *user_data), void *user_data)
48 _tmc_private.tmc_sid_cb = tmc_sid_cb;
49 _tmc_private.tmc_sid_cb_data = user_data;
52 static void reset_msg_buf(void)
54 tmc_msg_ptr = tmc_msg_str;
55 memset(tmc_msg_str, 0, 4096);
58 void tmc_set_msg_cb(void (*tmc_msg_cb)(char *msg, void *user_data), void *user_data)
61 _tmc_private.tmc_msg_cb = tmc_msg_cb;
62 _tmc_private.tmc_msg_cb_data = user_data;
65 void interpret_tmc(int event, int location, int extent, int CI, int direction)
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]="";
74 char type_str1[128]="";
75 char type_str2[128]="";
79 //fprintf(stderr, "mCI=%d CI=%d\n", cur_tmc_msg.CI, CI);
80 if (CI != cur_tmc_msg.CI || CI == -1) {
82 printf("GF evt=%d loc=%d ext=%d CI=%d dir=%d", event, location, extent, CI, direction);
83 printf("ev=%d ", event);
85 snprintf(sql, 256, "select ROADNUMBER,FIRST_NAME,NEGATIVE_OFFSET,POSITIVE_OFFSET,LINEAR_REFERENCE,TYPE,SUBTYPE from lcl where LOCATIONCODE=%d", location);
86 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
87 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
89 printf("lcl.db failed to get location %d event %d\n", location, event);
91 // return; // we cannot do much without location
93 neg_off = sqlite3_column_int(ppstmt, 2);
94 pos_off = sqlite3_column_int(ppstmt, 3);
95 lin_ref = sqlite3_column_int(ppstmt, 4);
96 strncpy(road_nr, (char *)sqlite3_column_text(ppstmt, 0), 255);
97 strncpy(fst_name, (char *)sqlite3_column_text(ppstmt, 1), 255);
98 strncpy(type_str1, (char *)sqlite3_column_text(ppstmt, 5), 128);
99 subtype = sqlite3_column_int(ppstmt, 6);
100 typechr = type_str1[0];
101 typenr = atoi(&type_str1[1]);
103 printf(" type=%c %d stype=%d\n", typechr, typenr, subtype);
105 snprintf(sql, 256, "select SNATDESC from lcl_supc where CLASS='%c' AND TCD=%d AND STCD=%d", typechr, typenr, subtype);
106 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
107 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
109 printf("lcl.db failed to get suptype %c %d stype=%d\n", typechr, typenr, subtype);
112 strncpy(type_str1, (char *)sqlite3_column_text(ppstmt, 0), 128);
115 snprintf(sql, 256, "select FIRST_NAME,SECOND_NAME from lcl where LOCATIONCODE=%d", lin_ref);
116 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
117 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
119 printf("lcl.db failed to get linear ref %d\n", lin_ref);
123 strncpy(rdir1, (char *)sqlite3_column_text(ppstmt, 1), 255);
124 strncpy(rdir2, (char *)sqlite3_column_text(ppstmt, 0), 255);
126 strncpy(rdir1, (char *)sqlite3_column_text(ppstmt, 0), 255);
127 strncpy(rdir2, (char *)sqlite3_column_text(ppstmt, 1), 255);
132 // printf("%s ab %s ", road_nr, fst_name);
136 snprintf(sql, 256, "select ROADNUMBER,FIRST_NAME,NEGATIVE_OFFSET,POSITIVE_OFFSET,TYPE,SUBTYPE from lcl where LOCATIONCODE=%d", neg_off);
137 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
138 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
140 printf("lcl.db failed to get location %d\n", location);
144 neg_off = sqlite3_column_int(ppstmt, 2);
146 //printf("bis %s\n", (char *)sqlite3_column_text(ppstmt, 1));
150 snprintf(sql, 256, "select ROADNUMBER,FIRST_NAME,NEGATIVE_OFFSET,POSITIVE_OFFSET,TYPE,SUBTYPE from lcl where LOCATIONCODE=%d", pos_off);
151 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
152 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
154 printf("lcl.db failed to get location %d\n", location);
158 pos_off = sqlite3_column_int(ppstmt, 3);
160 //printf("bis %s\n", (char *)sqlite3_column_text(ppstmt, 1));
162 strncpy(last_name, (char *)sqlite3_column_text(ppstmt, 1), 255);
164 strncpy(type_str2, (char *)sqlite3_column_text(ppstmt, 4), 128);
165 subtype = sqlite3_column_int(ppstmt, 5);
166 typechr = type_str2[0];
167 typenr = atoi(&type_str2[1]);
168 // printf(" type=%c %d stype=%d\n", typechr, typenr, subtype);
169 snprintf(sql, 256, "select SNATDESC from lcl_supc where CLASS='%c' AND TCD=%d AND STCD=%d", typechr, typenr, subtype);
170 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
171 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
173 printf("lcl.db failed to get suptype %c %d stype=%d\n", typechr, typenr, subtype);
176 strncpy(type_str2, (char *)sqlite3_column_text(ppstmt, 0), 128);
180 snprintf(sql, 256, "select TEXT_DE_NOQUANT from evl where CODE=%d", event);
181 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
182 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
184 printf("lcl.db failed to get event %d\n", event);
187 strncpy(evt_str, (char *)sqlite3_column_text(ppstmt, 0), 255);
192 // here goes the message ;)
194 tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s %s - %s,\n", road_nr, rdir1, rdir2);
195 if (location == 64777) {
196 tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s\n", evt_str);
200 printf("dir=%d\n", direction);
203 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);
205 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);
207 tmc_msg_ptr += sprintf(tmc_msg_ptr, "in Höhe %s %s\n%s\n", type_str1, fst_name, evt_str);
212 void parse_tmc_single(unsigned short *rdsgroup)
214 unsigned short event = cur_tmc_msg.msgs[0][1] & 0x7FF;
215 unsigned short location = cur_tmc_msg.msgs[0][2];
216 unsigned char extent = (cur_tmc_msg.msgs[0][1] & ((0x07) << 11)) >> 11;
217 unsigned char dir = (cur_tmc_msg.msgs[0][1] & ((0x01) << 14)) >> 14;
218 static unsigned short oevent=0;
219 static unsigned short olocation=0;
222 printf(" single group\n");
224 if (olocation != location && oevent != event) {
225 interpret_tmc(event, location, extent, -1, dir);
226 olocation = location;
228 if (_tmc_private.tmc_msg_cb != NULL) {
229 _tmc_private.tmc_msg_cb(tmc_msg_str, _tmc_private.tmc_msg_cb_data);
235 char *replace_str(char *str, char *orig, char *rep)
237 static char buffer[4096];
240 if(!(p = strstr(str, orig))) // Is 'orig' even in 'str'?
243 strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
244 buffer[p-str] = '\0';
246 sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
251 void interpret_tmc_multi(void)
254 unsigned short event = cur_tmc_msg.msgs[0][1] & 0x7FF;
255 unsigned short location = cur_tmc_msg.msgs[0][2];
256 unsigned char extent = (cur_tmc_msg.msgs[0][1] & (0x07 << 11)) >> 11;
257 unsigned char dir = (cur_tmc_msg.msgs[0][1] & (0x01 << 14)) >> 14;
259 unsigned short aevent;
261 sqlite3_stmt *ppstmt;
262 char evt_str[256]="";
264 unsigned char ext_buf[256];
267 printf("interpret_tmc_multi: sz=%d\n", cur_tmc_msg.msgsz);
268 for (i=0; i<cur_tmc_msg.msgsz; i++) {
269 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]);
272 printf("TMC event=%d loc=%d ext=%d dir=%d\n", event, location, extent, dir);
275 interpret_tmc(event, location, extent, -1, dir);
278 for (i=0; i < cur_tmc_msg.msgsz; i++) {
279 ext_buf[i*4] = (cur_tmc_msg.msgs[i+1][1] & 0xff00) >> 8;
280 ext_buf[(i*4)+1] = cur_tmc_msg.msgs[i+1][1] & 0xff;
281 ext_buf[(i*4)+2] = (cur_tmc_msg.msgs[i+1][2] & 0xff00) >> 8;
282 ext_buf[(i*4)+3] = cur_tmc_msg.msgs[i+1][2] & 0xff;
284 bitstream_start(ext_buf, cur_tmc_msg.msgsz*4);
286 bitstream_get_next_bits(4);
288 while (bitstream_bits_remaining() > 0) {
289 label = bitstream_get_next_bits(4);
291 if (OutputFlags & RDS_OUTPUT_TMC) {
292 printf("o '%s' %x\n", EVNT_LABEL[label], label);
298 dur = bitstream_get_next_bits(3);
299 tmc_msg_ptr += sprintf(tmc_msg_ptr, " dur=%d\n", dur);
302 unsigned char ctrlcd=0;
304 ctrlcd = bitstream_get_next_bits(3);
306 tmc_msg_ptr += sprintf(tmc_msg_ptr, "in beiden Richtungen\n");
308 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ctrlcd=%d\n", ctrlcd);
313 lofr = bitstream_get_next_bits(5);
315 printf("shit - more than 100km\n");
316 strcpy(lofrstr, ">100 km");
318 if (lofr>0 && lofr<11) {
319 printf("lofr = %dkm\n", lofr);
320 sprintf(lofrstr, "%d km", lofr);
322 if (lofr>10 && lofr<16) {
323 printf("lofr = %dkm\n", 12 + ((lofr-11)*2));
324 sprintf(lofrstr, "%d km", 12 + ((lofr-11)*2));
326 if (lofr>15 && lofr<32)
327 printf("lofr = %dkm\n", 25 + ((lofr-16)*5));
328 sprintf(lofrstr, "%d km", 25 + ((lofr-16)*5));
333 slim = bitstream_get_next_bits(5);
335 tmc_msg_ptr += sprintf(tmc_msg_ptr, " slim = %d km/h\n", slim*5);
338 unsigned int quant5=0;
340 quant5 = bitstream_get_next_bits(5);
341 tmc_msg_ptr += sprintf(tmc_msg_ptr, " quant5 = %d km\n", quant5);
344 unsigned int quant8=0;
346 quant8 = bitstream_get_next_bits(8);
347 tmc_msg_ptr += sprintf(tmc_msg_ptr, " quant8 = %d km\n", quant8);
350 unsigned char supinfo=0;
352 supinfo = bitstream_get_next_bits(8);
354 printf(" supinfo = %d\n", supinfo);
356 snprintf(sql, 256, "select TEXT_DE from ev_sup where CODE=%d", supinfo);
357 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
358 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
360 printf("lcl.db failed to get ev_sup %d\n", supinfo);
363 strncpy(evt_str, (char *)sqlite3_column_text(ppstmt, 0), 255);
364 tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s\n", evt_str);
368 unsigned int stime=0;
370 stime = bitstream_get_next_bits(8);
371 // printf(" stime = %d\n", stime);
373 stime *= 15; // 15 min internval
374 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab %02d:%02d\n", (stime / 60), (stime % 60));
375 } else if (stime < 201) {
377 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab %d Tage, %d:00 Uhr\n", (stime / 24), (stime % 24));
378 } else if (stime < 232) {
380 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab dem %d.\n", stime+1);
383 tmc_msg_ptr += sprintf(tmc_msg_ptr, " ab %s. %s\n", (stime % 2) ? "31":"15", monthname[stime / 2]);
387 unsigned int etime=0;
389 etime = bitstream_get_next_bits(8);
390 // printf(" etime = %d\n", etime);
392 etime *= 15; // 15 min internval
393 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis vor. %02d:%02d\n", (etime / 60), (etime % 60));
394 } else if (etime < 201) {
396 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis %d Tage, %d:00 Uhr\n", (etime / 24), (etime % 24));
397 } else if (etime < 232) {
399 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis zum %d.\n", etime+1);
402 tmc_msg_ptr += sprintf(tmc_msg_ptr, " bis etwa %s. %s\n", (etime % 2) ? "31":"15", monthname[etime / 2]);
406 aevent = bitstream_get_next_bits(11);
408 printf(" aevent = %d ", aevent);
410 snprintf(sql, 256, "select TEXT_DE_NOQUANT from evl where CODE=%d", aevent);
411 sqlite3_prepare(lcl_db, sql, 256, &ppstmt, NULL);
412 if (sqlite3_step(ppstmt) != SQLITE_ROW) {
414 printf("-lcl.db failed to get event %d\n", aevent);
417 strncpy(evt_str, (char *)sqlite3_column_text(ppstmt, 0), 255);
418 // printf("(L)='%s'\n", evt_str);
419 if (strlen(lofrstr) != 0 && strstr(evt_str,"(L)")!=NULL) {
420 replace_str(evt_str, "(L)", lofrstr);
422 tmc_msg_ptr += sprintf(tmc_msg_ptr, "%s\n", evt_str);
428 div = bitstream_get_next_bits(16);
429 tmc_msg_ptr += sprintf(tmc_msg_ptr, " div = %d\n", div);
434 dest = bitstream_get_next_bits(16);
435 tmc_msg_ptr += sprintf(tmc_msg_ptr, " dest = %d\n", dest);
440 res = bitstream_get_next_bits(16);
441 tmc_msg_ptr += sprintf(tmc_msg_ptr, " res = %d\n", res);
446 clink = bitstream_get_next_bits(16);
447 tmc_msg_ptr += sprintf(tmc_msg_ptr, " clink = %d\n", clink);
450 // tmc_msg_ptr += sprintf(tmc_msg_ptr, " seperator\n");
459 if (cur_tmc_msg.msgsz > 2) {
460 for (i=2; i<cur_tmc_msg.msgsz; i++) {
461 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]);
465 if (_tmc_private.tmc_msg_cb != NULL) {
466 _tmc_private.tmc_msg_cb(tmc_msg_str, _tmc_private.tmc_msg_cb_data);
471 void parse_tmc_multi(unsigned short *rdsgroup)
473 unsigned char GSI = (rdsgroup[2] & 0x3000) >> 12;
474 static unsigned char oGSI = 0;
476 unsigned char CI = rdsgroup[1] & 0x07;
480 printf(" multi CI=%d ", CI);
482 if (rdsgroup[2] & 0x8000) {
483 if (cur_tmc_msg.msgsz > 0) {
484 interpret_tmc_multi();
485 cur_tmc_msg.msgsz = 0;
488 printf(" #1 GSI=%d\n", GSI);
491 memset(&cur_tmc_msg.msgs, 0, 6*3*sizeof(short));
492 cur_tmc_msg.msgs[0][0] = rdsgroup[1];
493 cur_tmc_msg.msgs[0][1] = rdsgroup[2];
494 cur_tmc_msg.msgs[0][2] = rdsgroup[3];
497 if (rdsgroup[2] & 0x4000) {
498 // printf(" #2 GSI=%d\n", GSI);
499 cur_tmc_msg.msgs[1][0] = rdsgroup[1];
500 cur_tmc_msg.msgs[1][1] = rdsgroup[2];
501 cur_tmc_msg.msgs[1][2] = rdsgroup[3];
502 cur_tmc_msg.msgsz = 2;
507 // printf(" #%d GSI=%d (oGSI=%d)\n", 2+(oGSI-GSI), GSI, oGSI);
508 cur_tmc_msg.msgs[2+(oGSI-GSI)][0] = rdsgroup[1];
509 cur_tmc_msg.msgs[2+(oGSI-GSI)][1] = rdsgroup[2];
510 cur_tmc_msg.msgs[2+(oGSI-GSI)][2] = rdsgroup[3];
511 cur_tmc_msg.msgsz = 2+(oGSI-GSI);
514 // printf(" 0x%04x 0x%04x\n", rdsgroup[2], rdsgroup[3]);
517 // enum TMCtype { TMC_GROUP=0, TMC_SINGLE, TMC_SYSTEM, TMC_TUNING };
519 void decode_tmc(unsigned short *rdsgroup)
521 unsigned char X4 = (rdsgroup[1] & 0x10) >> 4;
522 unsigned char X3 = (rdsgroup[1] & 0x08) >> 3;
523 unsigned char X0X2 = rdsgroup[1] & 0x07;
524 //static unsigned char tmc_provider[9] = "";
526 if (X4 == 0) { // User message
527 if (X3 == 1) { // single group msg
528 parse_tmc_single(rdsgroup);
529 } else { // multi group msg
531 parse_tmc_multi(rdsgroup);
535 printf("err... X0X2(CI) = %d\n", X0X2);
540 //printf(" tuning?\n");
542 // printf(" system ");
544 tmc_info.provider_str[0] = (rdsgroup[2] & 0xff00) >> 8;
545 tmc_info.provider_str[1] = rdsgroup[2] & 0xff;
546 tmc_info.provider_str[2] = (rdsgroup[3] & 0xff00) >> 8;
547 tmc_info.provider_str[3] = 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 } else if (X0X2 == 5) {
553 tmc_info.provider_str[4] = (rdsgroup[2] & 0xff00) >> 8;
554 tmc_info.provider_str[5] = rdsgroup[2] & 0xff;
555 tmc_info.provider_str[6] = (rdsgroup[3] & 0xff00) >> 8;
556 tmc_info.provider_str[7] = rdsgroup[3] & 0xff;
557 if (_tmc_private.tmc_sid_cb != NULL)
558 _tmc_private.tmc_sid_cb(tmc_info.provider_str, _tmc_private.tmc_sid_cb_data);
559 if (OutputFlags & RDS_OUTPUT_TMC)
560 printf("provider = '%s'\n", tmc_info.provider_str);
564 printf("X0X2(CI)=%d \n", X0X2);