]> git.kernelconcepts.de Git - rdstmc.git/blobdiff - decoder/rds.c
Add radio tuning test app
[rdstmc.git] / decoder / rds.c
index ef24cd32009860d9c3649a32c3530e98b26dc866..ca927b2e9c753364482100031e695b5332c656fe 100644 (file)
@@ -1,3 +1,13 @@
+/*
+ * Copyright (C) 2009, 2010 by Nils Faerber <nils.faerber@kernelconcepts.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -85,9 +95,11 @@ unsigned char offset;
 
        rb = read(rds_fd, rbuf, 3);
        if (rb <= 0)
-               exit(0); // just for testing
-       if (rb != 3)
+               return 0;
+       if (rb != 3) {
                printf("#read err rb=%d\n", rb);
+               return 0;
+       }
        block = rbuf[0] | (rbuf[1] << 8);
        offset = rbuf[2] & 0x07;
 
@@ -114,6 +126,7 @@ unsigned char offset;
        }
        if (OutputFlags & RDS_RECEIVE_INDICATOR)
                printf(".");
+
        return 0;
 }
 
@@ -125,9 +138,18 @@ enum RDSGroupType { GROUP_0A=0, GROUP_0B, GROUP_1A, GROUP_1B, GROUP_2A, GROUP_2B
                     GROUP_12A, GROUP_12B, GROUP_13A, GROUP_13B, GROUP_14A, GROUP_14B, 
                     GROUP_15A, GROUP_15B, GROUP_UNKNOWN };
 
+void rds_radio_retuned(void)
+{
+       memset(&rds_info, 0, sizeof(rds_info));
+       rds_info.LTN = -1;
+       memset(&rds_time, 0, sizeof(rds_time));
+}
+
 void rds_decode_group(unsigned short *rdsgroup)
 {
 static unsigned short ogrp[4];
+static unsigned char grp_decoded = 0;
+static unsigned char sname_rcvd = 0;
 unsigned char grp_type = (rdsgroup[1] >> 11);
 unsigned char offs;
 static unsigned char otextAB = 0, newtext = 0;
@@ -137,15 +159,19 @@ int local_time_off = 0;
 int day_code = 0;
 int year_, mon_, K;
 
-       if (ogrp[0] == rdsgroup[0] && ogrp[1] == rdsgroup[1] && ogrp[2] == rdsgroup[2] && ogrp[3] == rdsgroup[3])
-               return;
-       else {
+       /* we want to wait for at least two identical group transmits */
+       if (ogrp[0] != rdsgroup[0] || ogrp[1] != rdsgroup[1] || ogrp[2] != rdsgroup[2] || ogrp[3] != rdsgroup[3]) {
                ogrp[0] = rdsgroup[0];
                ogrp[1] = rdsgroup[1];
                ogrp[2] = rdsgroup[2];
                ogrp[3] = rdsgroup[3];
                //printf("grp: 0x%04x 0x%04x 0x%04x 0x%04x\n", rdsgroup[0], rdsgroup[1], rdsgroup[2], rdsgroup[3]);
+               grp_decoded = 0;
+               return;
        }
+       if (grp_decoded)
+               return;
+
        if (rds_info.PI != PI) {
                /* station change? */
                memset(&rds_info, 0, sizeof(rds_info));
@@ -154,6 +180,7 @@ int year_, mon_, K;
                rds_info.ccode = (PI & 0xf000) >> 12;
                rds_info.ptype = (PI & 0x0f00) >> 8;
                rds_info.pref = (PI & 0x00ff);
+               sname_rcvd = 0;
                if (rds_info.pref == 0) /* something is wrong here */
                        return;
                rds_info.PI = rdsgroup[0];
@@ -169,10 +196,20 @@ int year_, mon_, K;
                        float AF1=0, AF2=0;
 
                        offs = (rdsgroup[1] & 0x03);
+                       if (offs == 0)
+                               sname_rcvd = 0;
+                       if (offs == 1 && sname_rcvd == 0)
+                               sname_rcvd = 1;
+                       if (offs == 2 && sname_rcvd == 1)
+                               sname_rcvd = 2;
+                       if (offs == 3 && sname_rcvd == 2)
+                               sname_rcvd = 3;
                        rds_info.sname[offs*2] = ((rdsgroup[3] & 0xff00) >> 8);
                        rds_info.sname[(offs*2)+1] = rdsgroup[3] & 0x00ff;
-                       if (_rds_private.rds_sname_cb != NULL)
+                       if (_rds_private.rds_sname_cb != NULL && sname_rcvd == 3) {
                                _rds_private.rds_sname_cb(rds_info.sname, _rds_private.rds_sname_cb_data);
+                               sname_rcvd = 0;
+                       }
 
                        rds_info.TA = (rdsgroup[1] & 0x10) >> 4;
                        rds_info.TP = (rdsgroup[1] & 0x400) >> 10;
@@ -328,6 +365,16 @@ int year_, mon_, K;
                                                printf("urban ");
                                        printf("\n");
                                }
+                       } else if (rds_info.AID == 0x4bd7) {
+                               if (OutputFlags & RDS_OUTPUT_RDSINFO) {
+                                       printf("RT+\nG2 = 0x%04x\n", rdsgroup[2]);
+                                       printf("template = 0x%02x\n", (rdsgroup[2] & 0x00ff));
+                                       printf("SCB = 0x%02x\n", (rdsgroup[2] & 0x0f00)>>8);
+                                       printf("CB = 0x%02x\n", (rdsgroup[2] & 0x1000)>>12);
+                                       printf("rfu = 0x%02x\n", (rdsgroup[2] & 0xe000)>>13);
+                               }
+                       } else {
+                               printf("3A AID=0x%04x\n", rds_info.AID);
                        }
                        break;
                case GROUP_3B:
@@ -421,27 +468,40 @@ int year_, mon_, K;
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
                                printf("GRP10B\n");
                        break;
-               case GROUP_11A:
+               case GROUP_11A: /* Open Data Application ODA */
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
-                               printf("GRP11A\n");
+                               printf("GRP11A ODA: #1=0x%02x #2=0x%04x #3=0x%04x\n", rdsgroup[1] & 0x1f, rdsgroup[2], rdsgroup[3]);
+
+                       /* we previously got an RT+ identifier, try RT+ decoding */
+                       if (rds_info.AID == 0x4bd7) {
+                               printf("RT+\ntoggle: %s\n", (rdsgroup[1] & 0x10) ? "yes" : "no");
+                               printf("item running   : %s\n", (rdsgroup[1] & 0x08) ? "yes" : "no");
+                               printf("content type 1 : %d\n", (rdsgroup[1] & 0x07) << 3 | (rdsgroup[2] & 0x0e00) >> 13);
+                               printf("start marker 1 : %d\n", (rdsgroup[2] & 0x1f80) >> 7);
+                               printf("length marker 1: %d\n", (rdsgroup[2] & 0x007e) >> 1);
+                               printf("content type 2 : %d\n", (rdsgroup[1] & 0x01) << 4);
+                               printf("start marker 2 : %d\n", (rdsgroup[2] & 0x07e0) >> 5);
+                               printf("length marker 2: %d\n", (rdsgroup[2] & 0x001f));
+                       }
                        break;
-               case GROUP_11B:
+               case GROUP_11B: /* Open Data Application ODA */
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
                                printf("GRP11B\n");
+                       printf("11B ODA: #1=0x%02x PI=0x%04x #3=0x%04x\n", rdsgroup[1] & 0x1f, rdsgroup[2], rdsgroup[3]);
                        break;
-               case GROUP_12A:
+               case GROUP_12A: /* Open Data Application ODA */
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
                                printf("GRP12A\n");
                        break;
-               case GROUP_12B:
+               case GROUP_12B: /* Open Data Application ODA */
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
                                printf("GRP12B\n");
                        break;
-               case GROUP_13A:
+               case GROUP_13A: /* Open Data Application ODA or paging */
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
                                printf("GRP13A\n");
                        break;
-               case GROUP_13B:
+               case GROUP_13B: /* Open Data Application ODA */
                        if (OutputFlags & RDS_OUTPUT_UNKNGRP)
                                printf("GRP13B\n");
                        break;
@@ -494,5 +554,8 @@ int year_, mon_, K;
                                printf("unkn. RDS group %d\n", grp_type);
                        break;
        }
+
+       /* done with this group */
+       grp_decoded = 1;
 }