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