summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/rds.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/firmware/drivers/rds.c b/firmware/drivers/rds.c
index eb14cfb009..df766094de 100644
--- a/firmware/drivers/rds.c
+++ b/firmware/drivers/rds.c
@@ -22,20 +22,27 @@
22#include <stdint.h> 22#include <stdint.h>
23#include <string.h> 23#include <string.h>
24#include <strlcpy.h> 24#include <strlcpy.h>
25#include <kernel.h>
25#include "rds.h" 26#include "rds.h"
26#include "time.h" 27#include "time.h"
27 28
29// timeout before segment obsolescence
30#define PS_SEGMENT_TIMEOUT (HZ / 2)
31#define RT_SEGMENT_TIMEOUT (10 * HZ)
32
28/* programme identification */ 33/* programme identification */
29static uint16_t pi_code; 34static uint16_t pi_code;
30static uint16_t pi_last; 35static uint16_t pi_last;
31/* program service name */ 36/* program service name */
32static char ps_data[9]; 37static char ps_data[9];
33static char ps_copy[9]; 38static char ps_copy[9];
34static int ps_segment; 39static long ps_segment_timeout[4];
40static int ps_segment;// bitmap of received segments
35/* radio text */ 41/* radio text */
36static char rt_data[65]; 42static char rt_data[65];
37static char rt_copy[65]; 43static char rt_copy[65];
38static int rt_segment; 44static long rt_segment_timeout[16];
45static int rt_segment;// bitmap of received segments
39static int rt_abflag; 46static int rt_abflag;
40/* date/time */ 47/* date/time */
41static time_t ct_data; 48static time_t ct_data;
@@ -95,22 +102,21 @@ static bool handle_group0(uint16_t data[4])
95{ 102{
96 int segment, pos; 103 int segment, pos;
97 104
98 segment = data[1] & 3; 105 /* remove obsolete segments */
106 for(int i = 0; i < 4; i++)
107 if(TIME_AFTER(current_tick, ps_segment_timeout[i]))
108 ps_segment &= ~(1 << i);
99 109
100 /* reset parsing if not in expected order */ 110 segment = data[1] & 3;
101 if (segment != ps_segment) {
102 ps_segment = 0;
103 if (segment != 0) {
104 return false;
105 }
106 }
107 111
108 /* store data */ 112 /* store data */
109 pos = segment * 2; 113 pos = segment * 2;
110 ps_data[pos++] = (data[3] >> 8) & 0xFF; 114 ps_data[pos++] = (data[3] >> 8) & 0xFF;
111 ps_data[pos++] = (data[3] >> 0) & 0xFF; 115 ps_data[pos++] = (data[3] >> 0) & 0xFF;
112 if (++ps_segment == 4) { 116 ps_segment |= 1 << segment;
113 ps_data[pos] = '\0'; 117 ps_segment_timeout[segment] = current_tick + PS_SEGMENT_TIMEOUT;
118 if (ps_segment == 0xf) {
119 ps_data[8] = '\0';
114 if (strcmp(ps_copy, ps_data) != 0) { 120 if (strcmp(ps_copy, ps_data) != 0) {
115 /* we got an updated message */ 121 /* we got an updated message */
116 strcpy(ps_copy, ps_data); 122 strcpy(ps_copy, ps_data);
@@ -143,21 +149,25 @@ static bool handle_group2(uint16_t data[4])
143{ 149{
144 int abflag, segment, version, pos; 150 int abflag, segment, version, pos;
145 bool done; 151 bool done;
152
153 /* remove obsolete segments */
154 for(int i = 0; i < 16; i++)
155 if(TIME_AFTER(current_tick, rt_segment_timeout[i]))
156 rt_segment &= ~(1 << i);
146 157
147 /* reset parsing if not in expected order */ 158 /* reset parsing if the message type changed */
148 abflag = (data[1] >> 4) & 1; 159 abflag = (data[1] >> 4) & 1;
149 segment = data[1] & 0xF; 160 segment = data[1] & 0xF;
150 if ((abflag != rt_abflag) || (segment != rt_segment)) { 161 if (abflag != rt_abflag) {
151 rt_abflag = abflag; 162 rt_abflag = abflag;
152 rt_segment = 0; 163 rt_segment = 0;
153 if (segment != 0) {
154 return false;
155 }
156 } 164 }
157 165
166 rt_segment |= 1 << segment;
167 rt_segment_timeout[segment] = current_tick + RT_SEGMENT_TIMEOUT;
168
158 /* store data */ 169 /* store data */
159 version = (data[1] >> 11) & 1; 170 version = (data[1] >> 11) & 1;
160 done = false;
161 if (version == 0) { 171 if (version == 0) {
162 pos = segment * 4; 172 pos = segment * 4;
163 done = done || handle_rt(pos++, (data[2] >> 8) & 0xFF); 173 done = done || handle_rt(pos++, (data[2] >> 8) & 0xFF);
@@ -169,7 +179,10 @@ static bool handle_group2(uint16_t data[4])
169 done = done || handle_rt(pos++, (data[3] >> 8) & 0xFF); 179 done = done || handle_rt(pos++, (data[3] >> 8) & 0xFF);
170 done = done || handle_rt(pos++, (data[3] >> 0) & 0xFF); 180 done = done || handle_rt(pos++, (data[3] >> 0) & 0xFF);
171 } 181 }
172 if ((++rt_segment == 16) || done) { 182 /* there are two cases for completion:
183 * - we got all 16 segments
184 * - we found a end of line AND we got all segments before it */
185 if (rt_segment == 0xffff || (done && rt_segment == (1 << segment) - 1)) {
173 rt_data[pos] = '\0'; 186 rt_data[pos] = '\0';
174 if (strcmp(rt_copy, rt_data) != 0) { 187 if (strcmp(rt_copy, rt_data) != 0) {
175 /* we got an updated message */ 188 /* we got an updated message */