1 /*
2  *  libzvbi -- Error correction functions
3  *
4  *  Copyright (C) 2001, 2002, 2003, 2004, 2007 Michael H. Schimek
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library 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 GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public
17  *  License along with this library; if not, write to the
18  *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA  02110-1301  USA.
20  */
21 
22 /* $Id: hamm.h,v 1.16 2013-07-10 11:37:13 mschimek Exp $ */
23 
24 #ifndef __ZVBI_HAMM_H__
25 #define __ZVBI_HAMM_H__
26 
27 #include <inttypes.h>		/* uintN_t */
28 #include "macros.h"
29 
30 VBI_BEGIN_DECLS
31 
32 /* Public */
33 
34 extern const uint8_t		_vbi_bit_reverse [256];
35 extern const uint8_t		_vbi_hamm8_fwd [16];
36 extern const int8_t		_vbi_hamm8_inv [256];
37 extern const int8_t		_vbi_hamm24_inv_par [3][256];
38 
39 /**
40  * @addtogroup Error Error correction functions
41  * @ingroup Raw
42  * @brief Helper functions to decode sliced VBI data.
43  * @{
44  */
45 
46 /**
47  * @param c Unsigned byte.
48  *
49  * Reverses the bits of the argument.
50  *
51  * @returns
52  * Data bits 0 [msb] ... 7 [lsb].
53  *
54  * @since 0.2.12
55  */
56 _vbi_inline unsigned int
vbi_rev8(unsigned int c)57 vbi_rev8			(unsigned int		c)
58 {
59 	return _vbi_bit_reverse[(uint8_t) c];
60 }
61 
62 /**
63  * @param c Unsigned 16 bit word.
64  *
65  * Reverses (or "reflects") the bits of the argument.
66  *
67  * @returns
68  * Data bits 0 [msb] ... 15 [lsb].
69  *
70  * @since 0.2.12
71  */
72 _vbi_inline unsigned int
vbi_rev16(unsigned int c)73 vbi_rev16			(unsigned int		c)
74 {
75 	return _vbi_bit_reverse[(uint8_t) c] * 256
76 		+ _vbi_bit_reverse[(uint8_t)(c >> 8)];
77 }
78 
79 /**
80  * @param p Pointer to a 16 bit word, last significant
81  *   byte first.
82  *
83  * Reverses (or "reflects") the bits of the argument.
84  *
85  * @returns
86  * Data bits 0 [msb] ... 15 [lsb].
87  *
88  * @since 0.2.12
89  */
90 _vbi_inline unsigned int
vbi_rev16p(const uint8_t * p)91 vbi_rev16p			(const uint8_t *	p)
92 {
93 	return _vbi_bit_reverse[p[0]] * 256
94 		+ _vbi_bit_reverse[p[1]];
95 }
96 
97 /**
98  * @param c Unsigned byte.
99  *
100  * @returns
101  * Changes the most significant bit of the byte
102  * to make the number of set bits odd.
103  *
104  * @since 0.2.12
105  */
106 _vbi_inline unsigned int
vbi_par8(unsigned int c)107 vbi_par8			(unsigned int		c)
108 {
109 	c &= 255;
110 
111 	/* if 0 == (inv_par[] & 32) change bit 7 of c. */
112 	c ^= 128 & ~(_vbi_hamm24_inv_par[0][c] << 2);
113 
114 	return c;
115 }
116 
117 /**
118  * @param c Unsigned byte.
119  *
120  * @returns
121  * If the byte has odd parity (sum of bits modulo 2 is 1) the
122  * byte AND 127, otherwise a negative value.
123  *
124  * @since 0.2.12
125  */
126 _vbi_inline int
vbi_unpar8(unsigned int c)127 vbi_unpar8			(unsigned int		c)
128 {
129 /* Disabled until someone finds a reliable way
130    to test for cmov support at compile time. */
131 #if 0
132 	int r = c & 127;
133 
134 	/* This saves cache flushes and an explicit branch. */
135 	__asm__ (" testb	%1,%1\n"
136 		 " cmovp	%2,%0\n"
137 		 : "+&a" (r) : "c" (c), "rm" (-1));
138 	return r;
139 #endif
140 	if (_vbi_hamm24_inv_par[0][(uint8_t) c] & 32) {
141 		return c & 127;
142 	} else {
143 		/* The idea is to OR results together to find a parity
144 		   error in a sequence, rather than a test and branch on
145 		   each byte. */
146 		return -1;
147 	}
148 }
149 
150 extern void
151 vbi_par				(uint8_t *		p,
152 				 unsigned int		n);
153 extern int
154 vbi_unpar			(uint8_t *		p,
155 				 unsigned int		n);
156 
157 /**
158  * @param c Integer between 0 ... 15.
159  *
160  * Encodes a nibble with Hamming 8/4 protection
161  * as specified in EN 300 706, Section 8.2.
162  *
163  * @returns
164  * Hamming encoded unsigned byte, lsb first transmitted.
165  *
166  * @since 0.2.12
167  */
168 _vbi_inline unsigned int
vbi_ham8(unsigned int c)169 vbi_ham8			(unsigned int		c)
170 {
171 	return _vbi_hamm8_fwd[c & 15];
172 }
173 
174 /**
175  * @param c Hamming 8/4 protected byte, lsb first transmitted.
176  *
177  * Decodes a Hamming 8/4 protected byte
178  * as specified in EN 300 706, Section 8.2.
179  *
180  * @returns
181  * Data bits (D4 [msb] ... D1 [lsb]) or a negative
182  * value if the byte contained uncorrectable errors.
183  *
184  * @since 0.2.12
185  */
186 _vbi_inline int
vbi_unham8(unsigned int c)187 vbi_unham8			(unsigned int		c)
188 {
189 	return _vbi_hamm8_inv[(uint8_t) c];
190 }
191 
192 /**
193  * @param p Pointer to a Hamming 8/4 protected 16 bit word,
194  *   last significant byte first, lsb first transmitted.
195  *
196  * Decodes a Hamming 8/4 protected byte pair
197  * as specified in EN 300 706, Section 8.2.
198  *
199  * @returns
200  * Data bits D4 [msb] ... D1 of first byte and D4 ... D1 [lsb]
201  * of second byte, or a negative value if any of the bytes
202  * contained uncorrectable errors.
203  *
204  * @since 0.2.12
205  */
206 _vbi_inline int
vbi_unham16p(const uint8_t * p)207 vbi_unham16p			(const uint8_t *	p)
208 {
209 	return ((int) _vbi_hamm8_inv[p[0]])
210 	  | (((int) _vbi_hamm8_inv[p[1]]) << 4);
211 }
212 
213 extern void
214 vbi_ham24p			(uint8_t *		p,
215 				 unsigned int		c);
216 extern int
217 vbi_unham24p			(const uint8_t *	p)
218   _vbi_pure;
219 
220 /** @} */
221 
222 /* Private */
223 
224 VBI_END_DECLS
225 
226 #endif /* __ZVBI_HAMM_H__ */
227 
228 /*
229 Local variables:
230 c-set-style: K&R
231 c-basic-offset: 8
232 End:
233 */
234