diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/rds.c | 51 |
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 */ |
29 | static uint16_t pi_code; | 34 | static uint16_t pi_code; |
30 | static uint16_t pi_last; | 35 | static uint16_t pi_last; |
31 | /* program service name */ | 36 | /* program service name */ |
32 | static char ps_data[9]; | 37 | static char ps_data[9]; |
33 | static char ps_copy[9]; | 38 | static char ps_copy[9]; |
34 | static int ps_segment; | 39 | static long ps_segment_timeout[4]; |
40 | static int ps_segment;// bitmap of received segments | ||
35 | /* radio text */ | 41 | /* radio text */ |
36 | static char rt_data[65]; | 42 | static char rt_data[65]; |
37 | static char rt_copy[65]; | 43 | static char rt_copy[65]; |
38 | static int rt_segment; | 44 | static long rt_segment_timeout[16]; |
45 | static int rt_segment;// bitmap of received segments | ||
39 | static int rt_abflag; | 46 | static int rt_abflag; |
40 | /* date/time */ | 47 | /* date/time */ |
41 | static time_t ct_data; | 48 | static 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 */ |