1 /*
2 * libzvbi -- Teletext packet 8/30 low level functions unit test
3 *
4 * Copyright (C) 2008 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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 /* $Id: test-packet-830.cc,v 1.1 2009/03/04 21:48:20 mschimek Exp $ */
23
24 #undef NDEBUG
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include "src/packet-830.h"
32 #include "src/hamm.h"
33 #include "test-pdc.h"
34
35 #define N_ELEMENTS(array) (sizeof (array) / sizeof (*(array)))
36
37 static const unsigned int
38 valid_cnis [] = {
39 0x0000, 0x0001, 0x0004, 0x0010, 0x0040, 0x0100,
40 0x0400, 0x1000, 0x4000, 0x5A5A, 0xA5A5, 0xFFFF
41 };
42
43 static const uint8_t
44 teletext_8302_sample [42] = {
45 0x15, 0xEA, 0x49, 0x15, 0x15, 0xEA, 0xEA, 0xEA, 0x5e,
46 0x15, 0x73, 0xEA, 0x9B,
47 /* 00010101 01110011 11101010 10011011
48 0 0 0 0 0 1 0 1 1 1 1 1 1 0 1 1
49 l0l1 a0a1 cccdcecf d3d4c6c7 bit 0 = LSB
50 r u l2l1 --m a2a1 c4c3c2c1 p2p1cAc9 }
51 3 2 1 0 3 2 1 0 3 2 1 0 3 2 1 0 } EN 300 231 Table 8
52 13 14 15 16 }
53 r=PRF, u=LUF, l=LCI, a=PCS, c=CNI, p=PIL/PTY, d=day,
54 m=MI/month/minute, h=hour. Compare test-vps.cc. */
55 0xEA, 0x49, 0x5E, 0x73,
56 /* 11101010 01001001 01011110 01110011
57 1 1 1 1 0 0 1 0 0 0 1 1 0 1 0 1
58 m3d0d1d2 h4m0m1m2 h0h1h2h3 m2m3m4m5
59 p6p5p4p3 pAp9p8p7 pEpDpCpB pIpHpGpF
60 3 2 1 0 3 2 1 0 3 2 1 0 3 2 1 0
61 17 18 19 20 */
62 0xA1, 0x49, 0xB6, 0x15, 0x64,
63 /* 10100001 01001001 10110110 00010101 01100100
64 1 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 1 0 0
65 cacbm0m1 c4c5c8c9 c0c1c2c3 p4p5p6p7 p0p1p2p3
66 c6c5pKpJ cCcBc8c7 cGcFcEcD p4p3p2p1 p8p7p6p5
67 3 2 1 0 3 2 1 0 3 2 1 0 3 2 1 0 3 2 1 0
68 21 22 23 24 25 */
69 0xC2, 0x52, 0xBA, 0x20, 0x52, 0xEF, 0xF4, 0xE5,
70 0x20, 0x52, 0xEF, 0x73, 0xE5, 0x6E, 0x20, 0x20,
71 0x20, 0x20, 0x20, 0x20
72 };
73
74 static const int
75 bad_mjd [] = {
76 0x00000,
77 0x01111,
78 0x10111,
79 0x11011,
80 0x11101,
81 0x11110,
82 0xAAAAB, /* 9999A */
83 0xAAABA,
84 0xAABAA,
85 0xABAAA,
86 0xBAAAA, /* A9999 */
87 0xFFFFF
88 };
89
90 static const int
91 bad_utc [] = {
92 0x000000,
93 0x011111,
94 0x101111,
95 0x110111,
96 0x111011,
97 0x111101,
98 0x111110,
99 0x11111B, /* 00000A */
100 0x111172, /* 000061 */
101 0x11117B, /* 00006A */
102 0x111181, /* 000070 */
103 0x111B11, /* 000A00 */
104 0x117111, /* 006000 */
105 0x351111, /* 240000 */
106 0x411111, /* 300000 */
107 0xFFFFFF
108 };
109
110 static void
assert_decode_teletext_8301_cni(unsigned int * cni,const uint8_t buffer[42])111 assert_decode_teletext_8301_cni (unsigned int * cni,
112 const uint8_t buffer[42])
113 {
114 uint8_t buffer2[42];
115 unsigned int cni2;
116
117 memcpy (buffer2, buffer, sizeof (buffer2));
118 memset_rand (cni, sizeof (cni));
119 cni2 = *cni;
120
121 assert (TRUE == vbi_decode_teletext_8301_cni (cni, buffer));
122 assert ((unsigned int) *cni <= 0xFFFF);
123 assert (0 == memcmp (buffer, buffer2, sizeof (buffer2)));
124 }
125
126 static void
encode_teletext_8301_cni(uint8_t buffer[42],unsigned int cni)127 encode_teletext_8301_cni (uint8_t buffer[42],
128 unsigned int cni)
129 {
130 /* EN 300 706 Section 9.8.1. */
131
132 /* -3: CRI, FRC. */
133 buffer[13 - 3 - 1] = vbi_rev16 (cni);
134 buffer[14 - 3 - 1] = vbi_rev16 (cni) >> 8;
135 }
136
137 static void
assert_decode_teletext_8301_local_time(time_t * time,int * seconds_east,const uint8_t buffer[42],vbi_bool exp_success=TRUE,time_t exp_time=ANY_TIME,int exp_seconds_east=0)138 assert_decode_teletext_8301_local_time
139 (time_t * time,
140 int * seconds_east,
141 const uint8_t buffer[42],
142 vbi_bool exp_success = TRUE,
143 time_t exp_time = ANY_TIME,
144 int exp_seconds_east = 0)
145 {
146 uint8_t buffer2[42];
147 time_t time2;
148 int seconds_east2;
149
150 memcpy (buffer2, buffer, sizeof (buffer2));
151 memset_rand (time, sizeof (*time));
152 time2 = *time;
153 memset_rand (seconds_east, sizeof (*seconds_east));
154 seconds_east2 = *seconds_east;
155
156 assert (exp_success
157 == vbi_decode_teletext_8301_local_time (time,
158 seconds_east,
159 buffer));
160 if (exp_success) {
161 if (ANY_TIME != exp_time) {
162 assert (exp_time == *time);
163 assert (exp_seconds_east == *seconds_east);
164 }
165 } else {
166 assert (*time == time2);
167 assert (*seconds_east == seconds_east2);
168 }
169
170 assert (0 == memcmp (buffer, buffer2, sizeof (buffer2)));
171 }
172
173 static void
assert_decode_teletext_8301_local_time(const uint8_t buffer[42],vbi_bool exp_success=TRUE,time_t exp_time=ANY_TIME,int exp_seconds_east=0)174 assert_decode_teletext_8301_local_time
175 (const uint8_t buffer[42],
176 vbi_bool exp_success = TRUE,
177 time_t exp_time = ANY_TIME,
178 int exp_seconds_east = 0)
179 {
180 time_t time;
181 int seconds_east;
182
183 assert_decode_teletext_8301_local_time (&time,
184 &seconds_east,
185 buffer,
186 exp_success,
187 exp_time,
188 exp_seconds_east);
189 }
190
191 static void
encode_teletext_8301_local_time(uint8_t buffer[42],int mjd,int utc,int seconds_east,bool add_one=TRUE)192 encode_teletext_8301_local_time (uint8_t buffer[42],
193 int mjd,
194 int utc,
195 int seconds_east,
196 bool add_one = TRUE)
197 {
198 buffer[15 - 3 - 1] =
199 ((abs (seconds_east / (30 * 60)) & 0x1F) << 1)
200 | ((seconds_east < 0) ? 0x40 : 0x00);
201
202 if (add_one)
203 mjd += 0x11111;
204 buffer[16 - 3 - 1] = mjd >> 16;
205 buffer[17 - 3 - 1] = mjd >> 8;
206 buffer[18 - 3 - 1] = mjd >> 0;
207
208 if (add_one)
209 utc += 0x111111;
210 buffer[19 - 3 - 1] = utc >> 16;
211 buffer[20 - 3 - 1] = utc >> 8;
212 buffer[21 - 3 - 1] = utc >> 0;
213 }
214
215 static void
assert_decode_teletext_8302_cni(unsigned int * cni,const uint8_t buffer[42],vbi_bool exp_success=TRUE)216 assert_decode_teletext_8302_cni (unsigned int * cni,
217 const uint8_t buffer[42],
218 vbi_bool exp_success = TRUE)
219 {
220 uint8_t buffer2[42];
221 unsigned int cni2;
222
223 memcpy (buffer2, buffer, sizeof (buffer2));
224 memset_rand (cni, sizeof (*cni));
225 cni2 = *cni;
226
227 assert (exp_success == vbi_decode_teletext_8302_cni (cni, buffer));
228 if (exp_success) {
229 assert ((unsigned int) *cni <= 0xFFFF);
230 } else {
231 assert (*cni == cni2);
232 }
233
234 assert (0 == memcmp (buffer, buffer2, sizeof (buffer2)));
235 }
236
237 static void
assert_decode_teletext_8302_pdc(test_pid * pid,const uint8_t buffer[42],vbi_bool exp_success=TRUE,const test_pid * exp_pid=NULL)238 assert_decode_teletext_8302_pdc (test_pid * pid,
239 const uint8_t buffer[42],
240 vbi_bool exp_success = TRUE,
241 const test_pid * exp_pid = NULL)
242 {
243 uint8_t buffer2[42];
244 test_pid pid2;
245
246 memcpy (buffer2, buffer, sizeof (buffer2));
247 pid->randomize ();
248 pid2 = *pid;
249
250 assert (exp_success == vbi_decode_teletext_8302_pdc (pid, buffer));
251 if (exp_success) {
252 unsigned int cni;
253
254 pid->assert_valid_ttx ();
255 assert_decode_teletext_8302_cni (&cni, buffer);
256 assert (cni == pid->cni);
257 if (NULL != exp_pid) {
258 assert (exp_pid->channel == pid->channel);
259 assert (exp_pid->cni == pid->cni);
260 assert (exp_pid->pil == pid->pil);
261 assert (exp_pid->luf == pid->luf);
262 assert (exp_pid->mi == pid->mi);
263 assert (exp_pid->prf == pid->prf);
264 assert (exp_pid->pcs_audio == pid->pcs_audio);
265 assert (exp_pid->pty == pid->pty);
266 }
267 } else {
268 assert (pid2 == *pid);
269 }
270
271 assert (0 == memcmp (buffer, buffer2, sizeof (buffer2)));
272 }
273
274 static void
encode_teletext_8302_pdc(uint8_t buffer[42],const test_pid * pid)275 encode_teletext_8302_pdc (uint8_t buffer[42],
276 const test_pid * pid)
277 {
278 unsigned int i;
279
280 memset_rand (buffer, 42);
281
282 /* EN 300 706 Section 9.8.2, EN 300 231 Section 8.2.1,
283 TR 300 231 Section 5. */
284
285 /* -3: CRI, FRC. */
286 buffer[13 - 3 - 1] = (+ ((pid->channel << 2) & 0xC)
287 + ((pid->luf << 1) & 0x2)
288 + ((pid->prf << 0) & 0x1));
289 buffer[14 - 3 - 1] = (+ ((pid->pcs_audio << 2) & 0xC)
290 + ((pid->mi << 1) & 0x2)
291 + ((buffer[14 - 3 - 1] ) & 0x1));
292 buffer[15 - 3 - 1] = pid->cni >> (16 - 4);
293 buffer[16 - 3 - 1] = (+ (((pid->cni >> (16 - 10)) << 2) & 0xC)
294 + (((pid->pil >> (20 - 2)) << 0) & 0x3));
295 buffer[17 - 3 - 1] = pid->pil >> (20 - 6);
296 buffer[18 - 3 - 1] = pid->pil >> (20 - 10);
297 buffer[19 - 3 - 1] = pid->pil >> (20 - 14);
298 buffer[20 - 3 - 1] = pid->pil >> (20 - 18);
299 buffer[21 - 3 - 1] = (+ (((pid->pil >> (20 - 20)) << 2) & 0xC)
300 + (((pid->cni >> (16 - 6)) << 0) & 0x3));
301 buffer[22 - 3 - 1] = (+ (((pid->cni >> (16 - 8)) << 2) & 0xC)
302 + (((pid->cni >> (16 - 12)) << 0) & 0x3));
303 buffer[23 - 3 - 1] = pid->cni >> (16 - 16);
304 buffer[24 - 3 - 1] = pid->pty >> (8 - 4);
305 buffer[25 - 3 - 1] = pid->pty >> (8 - 8);
306
307 for (i = 7; i <= 12; ++i)
308 buffer[i - 3 - 1] = vbi_ham8 (buffer[i - 3 - 1]);
309
310 for (i = 13; i <= 25; ++i) {
311 /* Transmitted MSB first, like VPS. */
312 int c = vbi_rev8 (buffer[i - 3 - 1]) >> 4;
313
314 buffer[i - 3 - 1] = vbi_ham8 (c);
315 }
316 }
317
318 int
main(void)319 main (void)
320 {
321 uint8_t buffer1[42];
322 test_pid pid1;
323 test_pid pid2;
324 time_t t1;
325 unsigned int cni;
326 unsigned int i;
327
328 for (i = 0; i < N_ELEMENTS (valid_cnis); ++i) {
329 memset_rand (buffer1, sizeof (buffer1));
330 encode_teletext_8301_cni (buffer1, valid_cnis[i]);
331 assert_decode_teletext_8301_cni (&cni, buffer1);
332 assert (cni == valid_cnis[i]);
333
334 pid1.randomize ();
335 pid1.cni = valid_cnis[i];
336 encode_teletext_8302_pdc (buffer1, &pid1);
337 assert_decode_teletext_8302_cni (&cni, buffer1);
338 assert (cni == valid_cnis[i]);
339
340 /* Single bit error. */
341 buffer1[15 - 3 - 1] ^= 0x04;
342 buffer1[22 - 3 - 1] ^= 0x02;
343 assert_decode_teletext_8302_cni (&cni, buffer1);
344 assert (cni == valid_cnis[i]);
345
346 /* Double bit error. */
347 buffer1[15 - 3 - 1] ^= 0x08;
348 assert_decode_teletext_8302_cni (&cni, buffer1, FALSE);
349 }
350
351 memset_rand (buffer1, sizeof (buffer1));
352 t1 = ztime ("19820131T000000");
353
354 encode_teletext_8301_local_time (buffer1, 0x00000, 0x000000, 0);
355 if (TIME_MIN < -2147483648.0) {
356 assert_decode_teletext_8301_local_time
357 (buffer1, TRUE, ztime ("18581117T000000"), 0);
358 } else {
359 /* Not representable as time_t. */
360 assert_decode_teletext_8301_local_time (buffer1, FALSE);
361 }
362
363 /* EN 300 706 Table 18: "Reference point". */
364 encode_teletext_8301_local_time (buffer1, 0x45000, 0x000000, 0);
365 assert_decode_teletext_8301_local_time (buffer1, TRUE, t1, 0);
366
367 /* 2000 is a leap year. */
368 encode_teletext_8301_local_time (buffer1, 0x51603, 0x213243, 0);
369 assert_decode_teletext_8301_local_time
370 (buffer1, TRUE, ztime ("20000229T213243"), 0);
371
372 /* +1 leap second. EN 300 706 Section 9.8.1 does not specify
373 if UDT counts leap seconds. We assume it does, which should
374 be safe because time_t ignores leap seconds. */
375 encode_teletext_8301_local_time (buffer1, 0x53735, 0x235959, 0);
376 assert_decode_teletext_8301_local_time
377 (buffer1, TRUE, ztime ("20051231T235959"), 0);
378 encode_teletext_8301_local_time (buffer1, 0x53735, 0x235960, 0);
379 assert_decode_teletext_8301_local_time
380 (buffer1, TRUE, ztime ("20060101T000000"), 0);
381 encode_teletext_8301_local_time (buffer1, 0x53736, 0x000000, 0);
382 assert_decode_teletext_8301_local_time
383 (buffer1, TRUE, ztime ("20060101T000000"), 0);
384
385 /* -1 leap second just skips 0x235959, not testable. */
386
387 encode_teletext_8301_local_time (buffer1, 0x99999, 0x235960, 0);
388 if (TIME_MAX > 4294967295.0) {
389 assert_decode_teletext_8301_local_time
390 (buffer1, TRUE, ztime ("21320901T000000"), 0);
391 } else {
392 /* Not representable as time_t. */
393 assert_decode_teletext_8301_local_time (buffer1, FALSE);
394 }
395
396 for (i = 0; i < N_ELEMENTS (bad_mjd); ++i) {
397 encode_teletext_8301_local_time (buffer1, bad_mjd[i],
398 0x111111, /* lto */ 0,
399 /* add_one */ FALSE);
400 assert_decode_teletext_8301_local_time (buffer1, FALSE);
401 }
402
403 for (i = 0; i < N_ELEMENTS (bad_utc); ++i) {
404 encode_teletext_8301_local_time (buffer1, 0x56111,
405 bad_utc[i], /* lto */ 0,
406 /* add_one */ FALSE);
407 assert_decode_teletext_8301_local_time (buffer1, FALSE);
408 }
409
410 for (i = 0; i <= 0x1F; ++i) {
411 encode_teletext_8301_local_time (buffer1, 0x45000, 0,
412 i * 30 * 60);
413 assert_decode_teletext_8301_local_time
414 (buffer1, TRUE, t1, i * 30 * 60);
415 buffer1[15 - 3 - 1] ^= 0x40;
416 assert_decode_teletext_8301_local_time
417 (buffer1, TRUE, t1, -i * 30 * 60);
418 }
419
420 for (i = 0; i < 1000; ++i) {
421 unsigned int j;
422
423 pid1.populate_ttx ();
424 encode_teletext_8302_pdc (buffer1, &pid1);
425
426 assert_decode_teletext_8302_cni (&cni, buffer1);
427 assert (cni == pid1.cni);
428
429 assert_decode_teletext_8302_pdc (&pid2, buffer1,
430 TRUE, &pid1);
431
432 memset_rand (buffer1, sizeof (buffer1));
433 for (j = 13; j <= 25; ++j) {
434 buffer1[j - 3 - 1] =
435 vbi_ham8 (buffer1[j - 3 - 1] & 0xF);
436 }
437 assert_decode_teletext_8302_pdc (&pid2, buffer1);
438 pid1 = pid2;
439 /* Single bit error. */
440 buffer1[14 - 3 - 1] ^= 0x02;
441 buffer1[23 - 3 - 1] ^= 0x80;
442 assert_decode_teletext_8302_pdc (&pid2, buffer1,
443 TRUE, &pid1);
444 /* Double bit error. */
445 buffer1[23 - 3 - 1] ^= 0x10;
446 assert_decode_teletext_8302_pdc (&pid2, buffer1, FALSE);
447 }
448
449 assert_decode_teletext_8302_pdc (&pid1, teletext_8302_sample);
450 assert (0 == pid1.channel);
451 assert (0xFDCB == pid1.cni);
452 assert (VBI_PIL (0x0A, 0x0F, 0x0C, 0x28) == pid1.pil);
453 assert (0 == pid1.luf);
454 assert (1 == pid1.mi);
455 assert (0 == pid1.prf);
456 assert (0x02 == pid1.pcs_audio);
457 assert (0x02 == pid1.pty);
458
459 return 0;
460 }
461
462 /*
463 Local variables:
464 c-set-style: K&R
465 c-basic-offset: 8
466 End:
467 */
468