168 lines
3.8 KiB
C
168 lines
3.8 KiB
C
/*
|
|
* libzvbi -- Error correction functions
|
|
*
|
|
* Copyright (C) 2001, 2002, 2003, 2004, 2007 Michael H. Schimek
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
/* $Id: hamm.c,v 1.10 2008/02/19 00:35:20 mschimek Exp $ */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <limits.h> /* CHAR_BIT */
|
|
|
|
#include "hamm.h"
|
|
#include "hamm-tables.h"
|
|
|
|
/**
|
|
* @ingroup Error
|
|
*
|
|
* @param p Array of unsigned bytes.
|
|
* @param n Size of array.
|
|
*
|
|
* Of each byte of the array, changes the most significant
|
|
* bit to make the number of set bits odd.
|
|
*
|
|
* @since 0.2.12
|
|
*/
|
|
void
|
|
vbi_par (uint8_t * p,
|
|
unsigned int n)
|
|
{
|
|
while (n-- > 0) {
|
|
uint8_t c = *p;
|
|
|
|
/* if 0 == (inv_par[] & 32) change msb of *p. */
|
|
*p++ = c ^ (128 & ~(_vbi_hamm24_inv_par[0][c] << 2));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @ingroup Error
|
|
* @param p Array of unsigned bytes.
|
|
* @param n Size of array.
|
|
*
|
|
* Tests the parity and clears the most significant bit of
|
|
* each byte of the array.
|
|
*
|
|
* @return
|
|
* A negative value if any byte of the array had even
|
|
* parity (sum of bits modulo 2 is 0).
|
|
*
|
|
* @since 0.2.12
|
|
*/
|
|
int
|
|
vbi_unpar (uint8_t * p,
|
|
unsigned int n)
|
|
{
|
|
int r = 0;
|
|
|
|
while (n-- > 0) {
|
|
uint8_t c = *p;
|
|
|
|
/* if 0 == (inv_par[] & 32) set msb of r. */
|
|
r |= ~ _vbi_hamm24_inv_par[0][c]
|
|
<< (sizeof (int) * CHAR_BIT - 1 - 5);
|
|
|
|
*p++ = c & 127;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* @ingroup Error
|
|
* @param p A Hamming 24/18 protected 24 bit word will be stored here,
|
|
* last significant byte first, lsb first transmitted.
|
|
* @param c Integer between 0 ... 1 << 18 - 1.
|
|
*
|
|
* Encodes an 18 bit word with Hamming 24/18 protection
|
|
* as specified in ETS 300 706, Section 8.3.
|
|
*
|
|
* @since 0.2.27
|
|
*/
|
|
void
|
|
vbi_ham24p (uint8_t * p,
|
|
unsigned int c)
|
|
{
|
|
unsigned int D5_D11;
|
|
unsigned int D12_D18;
|
|
unsigned int P5, P6;
|
|
unsigned int Byte_0;
|
|
|
|
Byte_0 = (_vbi_hamm24_fwd_0 [(c >> 0) & 0xFF]
|
|
^ _vbi_hamm24_fwd_1 [(c >> 8) & 0xFF]
|
|
^ _vbi_hamm24_fwd_2 [(c >> 16) & 0x03]);
|
|
p[0] = Byte_0;
|
|
|
|
D5_D11 = (c >> 4) & 0x7F;
|
|
D12_D18 = (c >> 11) & 0x7F;
|
|
|
|
P5 = 0x80 & ~(_vbi_hamm24_inv_par[0][D12_D18] << 2);
|
|
p[1] = D5_D11 | P5;
|
|
|
|
P6 = 0x80 & ((_vbi_hamm24_inv_par[0][Byte_0]
|
|
^ _vbi_hamm24_inv_par[0][D5_D11]) << 2);
|
|
p[2] = D12_D18 | P6;
|
|
}
|
|
|
|
/**
|
|
* @ingroup Error
|
|
* @param p Pointer to a Hamming 24/18 protected 24 bit word,
|
|
* last significant byte first, lsb first transmitted.
|
|
*
|
|
* Decodes a Hamming 24/18 protected byte triplet
|
|
* as specified in ETS 300 706, Section 8.3.
|
|
*
|
|
* @return
|
|
* Triplet data bits D18 [msb] ... D1 [lsb] or a negative value
|
|
* if the triplet contained incorrectable errors.
|
|
*
|
|
* @since 0.2.12
|
|
*/
|
|
int
|
|
vbi_unham24p (const uint8_t * p)
|
|
{
|
|
unsigned int D1_D4;
|
|
unsigned int D5_D11;
|
|
unsigned int D12_D18;
|
|
unsigned int ABCDEF;
|
|
int32_t d;
|
|
|
|
D1_D4 = _vbi_hamm24_inv_d1_d4[p[0] >> 2];
|
|
D5_D11 = p[1] & 0x7F;
|
|
D12_D18 = p[2] & 0x7F;
|
|
|
|
d = D1_D4 | (D5_D11 << 4) | (D12_D18 << 11);
|
|
|
|
ABCDEF = (_vbi_hamm24_inv_par[0][p[0]]
|
|
^ _vbi_hamm24_inv_par[1][p[1]]
|
|
^ _vbi_hamm24_inv_par[2][p[2]]);
|
|
|
|
/* Correct single bit error, set MSB on double bit error. */
|
|
return d ^ (int) _vbi_hamm24_inv_err[ABCDEF];
|
|
}
|
|
|
|
/*
|
|
Local variables:
|
|
c-set-style: K&R
|
|
c-basic-offset: 8
|
|
End:
|
|
*/
|