1 /*
2 * libzvbi - Teletext packet decoder, packet 8/30
3 *
4 * Copyright (C) 2003, 2004 Michael H. Schimek
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /* $Id: packet-830.c,v 1.4 2013/07/10 11:37:18 mschimek Exp $ */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <assert.h>
27 #include <errno.h>
28 #include "misc.h"
29 #include "bcd.h" /* vbi_lbcd2bin() */
30 #include "hamm.h" /* vbi_rev16p(), vbi_iham8() */
31 #include "packet-830.h"
32
33 /**
34 * @addtogroup Packet830 Teletext Packet 8/30 Decoder
35 * @ingroup LowDec
36 * @brief Functions to decode Teletext packet 8/30 (ETS 300 706).
37 *
38 * Teletext pages are transmitted in packets numbered 0 to 31. Packet
39 * 0 to 25 contain the text of the page, packet 26 to 29 additional
40 * information like Fastext links. Packet 30 and 31 are reserved for
41 * data transmissions unrelated to any page. Since each packet
42 * contains a magazine number 1 to 8 (the first digit of the Teletext
43 * page number) 16 logical channels can be distinguished. Packet 30
44 * with magazine number 8 carries a Country and Network Identifier,
45 * and either a local time (format 1) or PDC label (format 2).
46 *
47 * These are low level functions. See test/decode.c for a usage
48 * example.
49 *
50 * The @a vbi_decoder module can decode a full Teletext signal and
51 * provide the information transmitted in packet 8/30 as @c
52 * VBI_EVENT_NETWORK, @c VBI_EVENT_NETWORK_ID, @c VBI_EVENT_LOCAL_TIME
53 * and @c VBI_EVENT_PROG_ID. See examples/network.c and
54 * examples/pdc1.c.
55 */
56
57 /* Resources:
58 http://pdc.ro.nu/jd-code.html
59 */
60
61 /**
62 * @param cni CNI of type VBI_CNI_TYPE_8301 will be stored here.
63 * @param buffer Teletext packet as defined for @c VBI_SLICED_TELETEXT_B,
64 * i.e. 42 bytes without clock run-in and framing code.
65 *
66 * Decodes a Teletext packet 8/30 format 1 according to ETS 300 706
67 * section 9.8.1, returning the contained 16 bit Country and Network
68 * Identifier in @a *cni.
69 *
70 * @returns
71 * Always @c TRUE, no error checking possible. It may be prudent to
72 * wait for a second transmission of the received CNI to ensure
73 * correct reception.
74 *
75 * @since 0.2.34
76 */
77 vbi_bool
vbi_decode_teletext_8301_cni(unsigned int * cni,const uint8_t buffer[42])78 vbi_decode_teletext_8301_cni (unsigned int * cni,
79 const uint8_t buffer[42])
80 {
81 assert (NULL != cni);
82 assert (NULL != buffer);
83
84 *cni = vbi_rev16p (buffer + 9);
85
86 return TRUE;
87 }
88
89 /* Should use vbi_bcd2bin() but that function is limited to four BCD
90 digits in libzvbi 0.2 and cannot be changed for compatibility
91 reasons. */
92 static int
bcd2bin(int bcd)93 bcd2bin (int bcd)
94 {
95 unsigned int f;
96 int bin = 0;
97
98 for (f = 1; f < 100000; f = f * 10) {
99 bin += (bcd & 15) * f;
100 bcd >>= 4;
101 }
102
103 return bin;
104 }
105
106 /**
107 * @param time The current time in seconds since 1970-01-01 00:00 UTC
108 * will be stored here.
109 * @param seconds_east The offset of the local time of the intended
110 * audience of the program in seconds east of UTC will be stored here,
111 * including a daylight-saving time offset if daylight-saving is
112 * currently in effect in that time zone. To get the local time of the
113 * intended audience add @a seconds_east to @a time.
114 * @param buffer Teletext packet as defined for @c VBI_SLICED_TELETEXT_B,
115 * i.e. 42 bytes without clock run-in and framing code.
116 *
117 * Decodes a Teletext packet 8/30 format 1 according to ETS 300 706
118 * section 9.8.1, returning the current time in the UTC time zone and
119 * the time zone of the intended audience of the program.
120 *
121 * @returns
122 * On error the function returns @c FALSE:
123 * - The buffer contains uncorrectable errors or
124 * - The time is not representable as a time_t.
125 * In these cases @a *time and @a *seconds_east remain unchanged.
126 *
127 * @since 0.2.34
128 */
129 vbi_bool
vbi_decode_teletext_8301_local_time(time_t * time,int * seconds_east,const uint8_t buffer[42])130 vbi_decode_teletext_8301_local_time
131 (time_t * time,
132 int * seconds_east,
133 const uint8_t buffer[42])
134 {
135 int64_t mjd;
136 int64_t utc;
137 int64_t t;
138 int bcd;
139 int field;
140 int offset;
141
142 assert (NULL != time);
143 assert (NULL != seconds_east);
144 assert (NULL != buffer);
145
146 /* Modified Julian Date. */
147
148 bcd = (+ ((buffer[12] & 15) << 16)
149 + (buffer[13] << 8)
150 + buffer[14]
151 - 0x11111);
152 if (unlikely (!vbi_is_bcd (bcd))) {
153 errno = 0;
154 return FALSE;
155 }
156
157 mjd = bcd2bin (bcd);
158
159 /* UTC time. */
160
161 bcd = (+ (buffer[15] << 16)
162 + (buffer[16] << 8)
163 + buffer[17]
164 - 0x111111);
165 if (unlikely (!vbi_is_bcd (bcd))) {
166 errno = 0;
167 return FALSE;
168 }
169
170 utc = (bcd & 15) + ((bcd >> 4) & 15) * 10;
171 if (unlikely (utc > 60)) {
172 errno = 0;
173 return FALSE;
174 }
175
176 field = ((bcd >> 8) & 15) + ((bcd >> 12) & 15) * 10;
177 if (unlikely (field >= 60)) {
178 errno = 0;
179 return FALSE;
180 }
181 utc += field * 60;
182
183 field = ((bcd >> 16) & 15) + (bcd >> 20) * 10;
184 if (unlikely (field >= 24)) {
185 errno = 0;
186 return FALSE;
187 }
188 utc += field * 3600;
189
190 /* Local time offset in seconds east of UTC. */
191
192 offset = (buffer[11] & 0x3E) * (15 * 60);
193 if (buffer[11] & 0x40)
194 offset = -offset;
195
196 t = (mjd - 40587) * 86400 + utc;
197 if (t < TIME_MIN || t > TIME_MAX) {
198 errno = EOVERFLOW;
199 return FALSE;
200 }
201
202
203 *time = t;
204
205 *seconds_east = offset;
206
207 return TRUE;
208 }
209
210 /**
211 * @param cni CNI of type VBI_CNI_TYPE_8302 will be stored here.
212 * @param buffer Teletext packet as defined for @c VBI_SLICED_TELETEXT_B,
213 * i.e. 42 bytes without clock run-in and framing code.
214 *
215 * Decodes a Teletext packet 8/30 format 2 according to ETS 300 706
216 * section 9.8.2, returning the contained 16 bit Country and Network
217 * Identifier in @a *cni.
218 *
219 * @returns
220 * @c FALSE if the buffer contains uncorrectable errors. In this case
221 * @a *cni remains unchanged.
222 *
223 * @since 0.2.34
224 */
225 vbi_bool
vbi_decode_teletext_8302_cni(unsigned int * cni,const uint8_t buffer[42])226 vbi_decode_teletext_8302_cni (unsigned int * cni,
227 const uint8_t buffer[42])
228 {
229 int b[13];
230
231 assert (NULL != cni);
232 assert (NULL != buffer);
233
234 b[ 7] = vbi_unham16p (buffer + 10);
235 b[ 8] = vbi_unham16p (buffer + 12);
236 b[10] = vbi_unham16p (buffer + 16);
237 b[11] = vbi_unham16p (buffer + 18);
238
239 if (unlikely ((b[7] | b[8] | b[10] | b[11]) < 0))
240 return FALSE;
241
242 b[ 7] = vbi_rev8 (b[ 7]);
243 b[ 8] = vbi_rev8 (b[ 8]);
244 b[10] = vbi_rev8 (b[10]);
245 b[11] = vbi_rev8 (b[11]);
246
247 *cni = (+ ((b[ 7] & 0x0F) << 12)
248 + ((b[10] & 0x03) << 10)
249 + ((b[11] & 0xC0) << 2)
250 + (b[ 8] & 0xC0)
251 + (b[11] & 0x3F));
252
253 return TRUE;
254 }
255
256 /**
257 * @param pid PDC program ID will be stored here.
258 * @param buffer Teletext packet as defined for @c VBI_SLICED_TELETEXT_B,
259 * i.e. 42 bytes without clock run-in and framing code.
260 *
261 * Decodes a Teletext packet 8/30 format 2 according to ETS 300 231,
262 * and stores the contained PDC recording-control data in @a *pid.
263 *
264 * @returns
265 * @c FALSE if the buffer contains uncorrectable errors or invalid
266 * data. In this case @a *pid remains unchanged.
267 *
268 * @since 0.2.34
269 */
270 vbi_bool
vbi_decode_teletext_8302_pdc(vbi_program_id * pid,const uint8_t buffer[42])271 vbi_decode_teletext_8302_pdc (vbi_program_id * pid,
272 const uint8_t buffer[42])
273 {
274 uint8_t b[13];
275 unsigned int i;
276 int error;
277
278 assert (NULL != pid);
279 assert (NULL != buffer);
280
281 error = vbi_unham8 (buffer[9]);
282 b[ 6] = vbi_rev8 (error) >> 4;
283
284 for (i = 7; i <= 12; ++i) {
285 int t;
286
287 t = vbi_unham16p (buffer + i * 2 - 4);
288 error |= t;
289 b[i] = vbi_rev8 (t);
290 }
291
292 if (unlikely (error < 0))
293 return FALSE;
294
295 CLEAR (*pid);
296
297 pid->channel = VBI_PID_CHANNEL_LCI_0 + ((b[6] >> 2) & 3);
298
299 pid->cni_type = VBI_CNI_TYPE_8302;
300
301 pid->cni = (+ ((b[ 7] & 0x0F) << 12)
302 + ((b[10] & 0x03) << 10)
303 + ((b[11] & 0xC0) << 2)
304 + (b[ 8] & 0xC0)
305 + (b[11] & 0x3F));
306
307 pid->pil = (+ ((b[ 8] & 0x3F) << 14)
308 + (b[ 9] << 6)
309 + (b[10] >> 2));
310
311 pid->luf = (b[6] >> 1) & 1;
312 pid->mi = (b[7] >> 5) & 1;
313 pid->prf = (b[6] >> 0) & 1;
314
315 pid->pcs_audio = (b[7] >> 6) & 3;
316
317 pid->pty = b[12];
318
319 return TRUE;
320 }
321
322 /*
323 Local variables:
324 c-set-style: K&R
325 c-basic-offset: 8
326 End:
327 */
328