mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
224 lines
5.8 KiB
C
224 lines
5.8 KiB
C
|
/*
|
||
|
* libzvbi -- BCD arithmetic for Teletext page numbers
|
||
|
*
|
||
|
* Copyright (C) 2001, 2002 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: bcd.h,v 1.19 2008-02-21 07:18:52 mschimek Exp $ */
|
||
|
|
||
|
#ifndef BCD_H
|
||
|
#define BCD_H
|
||
|
|
||
|
#include "misc.h"
|
||
|
|
||
|
/**
|
||
|
* @addtogroup BCD BCD arithmetic for Teletext page numbers
|
||
|
* @ingroup HiDec
|
||
|
*
|
||
|
* Teletext page numbers are expressed as packed binary coded decimal
|
||
|
* numbers in range 0x100 to 0x8FF. The bcd format encodes one decimal
|
||
|
* digit in every hex nibble (four bits) of the number. Page numbers
|
||
|
* containing digits 0xA to 0xF are reserved for various system purposes
|
||
|
* and not intended for display.
|
||
|
*/
|
||
|
|
||
|
/* Public */
|
||
|
|
||
|
/**
|
||
|
* @ingroup HiDec
|
||
|
*
|
||
|
* Teletext or Closed Caption page number. For Teletext pages
|
||
|
* this is a packed bcd number in range 0x100 ... 0x8FF. Page
|
||
|
* numbers containing digits 0xA to 0xF are reserved for various
|
||
|
* system purposes, these pages are not intended for display.
|
||
|
*
|
||
|
* Closed Caption page numbers between 1 ... 8 correspond
|
||
|
* to the four Caption and Text channels:
|
||
|
* <table>
|
||
|
* <tr><td>1</td><td>Caption 1</td><td>
|
||
|
* "Primary synchronous caption service [English]"</td></tr>
|
||
|
* <tr><td>2</td><td>Caption 2</td><td>
|
||
|
* "Special non-synchronous data that is intended to
|
||
|
* augment information carried in the program"</td></tr>
|
||
|
* <tr><td>3</td><td>Caption 3</td><td>
|
||
|
* "Secondary synchronous caption service, usually
|
||
|
* second language [Spanish, French]"</td></tr>
|
||
|
* <tr><td>4</td><td>Caption 4</td><td>
|
||
|
* "Special non-synchronous data similar to Caption 2"</td></tr>
|
||
|
* <tr><td>5</td><td>Text 1</td><td>
|
||
|
* "First text service, data usually not program related"</td></tr>
|
||
|
* <tr><td>6</td><td>Text 2</td><td>
|
||
|
* "Second text service, additional data usually not program related
|
||
|
* [ITV data]"</td></tr>
|
||
|
* <tr><td>7</td><td>Text 3</td><td>
|
||
|
* "Additional text channel"</td></tr>
|
||
|
* <tr><td>8</td><td>Text 4</td><td>
|
||
|
* "Additional text channel"</td></tr>
|
||
|
* </table>
|
||
|
*/
|
||
|
/* XXX unsigned? */
|
||
|
typedef int vbi_pgno;
|
||
|
|
||
|
/**
|
||
|
* @ingroup HiDec
|
||
|
*
|
||
|
* This is the subpage number only applicable to Teletext pages,
|
||
|
* a packed bcd number in range 0x00 ... 0x99. On special 'clock' pages
|
||
|
* (for example listing the current time in different time zones)
|
||
|
* it can assume values between 0x0000 ... 0x2359 expressing
|
||
|
* local time. These are not actually subpages.
|
||
|
*/
|
||
|
typedef int vbi_subno;
|
||
|
|
||
|
/**
|
||
|
* @ingroup HiDec
|
||
|
*/
|
||
|
#define VBI_ANY_SUBNO 0x3F7F
|
||
|
/**
|
||
|
* @ingroup HiDec
|
||
|
*/
|
||
|
#define VBI_NO_SUBNO 0x3F7F
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @param dec Decimal number.
|
||
|
*
|
||
|
* Converts a two's complement binary between 0 ... 999 to a
|
||
|
* packed bcd number in range 0x000 ... 0x999. Extra digits in
|
||
|
* the input will be discarded.
|
||
|
*
|
||
|
* @return
|
||
|
* BCD number.
|
||
|
*/
|
||
|
_vbi_inline unsigned int
|
||
|
vbi_dec2bcd(unsigned int dec)
|
||
|
{
|
||
|
return (dec % 10) + ((dec / 10) % 10) * 16 + ((dec / 100) % 10) * 256;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @since 0.2.28
|
||
|
*/
|
||
|
#define vbi_bin2bcd(n) vbi_dec2bcd(n)
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @param bcd BCD number.
|
||
|
*
|
||
|
* Converts a packed bcd number between 0x000 ... 0xFFF to a two's
|
||
|
* complement binary in range 0 ... 999. Extra digits in the input
|
||
|
* will be discarded.
|
||
|
*
|
||
|
* @return
|
||
|
* Decimal number. The result is undefined when the bcd number contains
|
||
|
* hex digits 0xA ... 0xF.
|
||
|
**/
|
||
|
_vbi_inline unsigned int
|
||
|
vbi_bcd2dec(unsigned int bcd)
|
||
|
{
|
||
|
return (bcd & 15) + ((bcd >> 4) & 15) * 10 + ((bcd >> 8) & 15) * 100;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @since 0.2.28
|
||
|
*/
|
||
|
#define vbi_bcd2bin(n) vbi_bcd2dec(n)
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @param a BCD number.
|
||
|
* @param b BCD number.
|
||
|
*
|
||
|
* Adds two packed bcd numbers, returning a packed bcd sum. Arguments
|
||
|
* and result are in range 0xF000 0000 ... 0x0999 9999, that
|
||
|
* is -10**7 ... +10**7 - 1 in decimal notation. To subtract you can
|
||
|
* add the 10's complement, e. g. -1 = 0xF999 9999.
|
||
|
*
|
||
|
* @return
|
||
|
* Packed bcd number. The result is undefined when any of the arguments
|
||
|
* contain hex digits 0xA ... 0xF.
|
||
|
*/
|
||
|
_vbi_inline unsigned int
|
||
|
vbi_add_bcd(unsigned int a, unsigned int b)
|
||
|
{
|
||
|
unsigned int t;
|
||
|
|
||
|
a += 0x06666666;
|
||
|
t = a + b;
|
||
|
b ^= a ^ t;
|
||
|
b = (~b & 0x11111110) >> 3;
|
||
|
b |= b * 2;
|
||
|
|
||
|
return t - b;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @param bcd BCD number.
|
||
|
*
|
||
|
* Tests if @a bcd forms a valid BCD number. The argument must be
|
||
|
* in range 0x0000 0000 ... 0x0999 9999.
|
||
|
*
|
||
|
* @return
|
||
|
* @c FALSE if @a bcd contains hex digits 0xA ... 0xF.
|
||
|
*/
|
||
|
_vbi_inline vbi_bool
|
||
|
vbi_is_bcd(unsigned int bcd)
|
||
|
{
|
||
|
static const unsigned int x = 0x06666666;
|
||
|
|
||
|
return (((bcd + x) ^ (bcd ^ x)) & 0x11111110) == 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @ingroup BCD
|
||
|
* @param bcd Unsigned BCD number.
|
||
|
* @param maximum Unsigned maximum value.
|
||
|
*
|
||
|
* Compares an unsigned packed bcd number digit-wise against a maximum
|
||
|
* value, for example 0x295959. @a maximum can contain digits 0x0
|
||
|
* ... 0xF.
|
||
|
*
|
||
|
* @return
|
||
|
* @c TRUE if any digit of @a bcd is greater than the
|
||
|
* corresponding digit of @a maximum.
|
||
|
*
|
||
|
* @since 0.2.28
|
||
|
*/
|
||
|
_vbi_inline vbi_bool
|
||
|
vbi_bcd_digits_greater (unsigned int bcd,
|
||
|
unsigned int maximum)
|
||
|
{
|
||
|
maximum ^= ~0;
|
||
|
|
||
|
return 0 != (((bcd + maximum) ^ bcd ^ maximum) & 0x11111110);
|
||
|
}
|
||
|
|
||
|
/* Private */
|
||
|
|
||
|
#endif /* BCD_H */
|
||
|
|
||
|
/*
|
||
|
Local variables:
|
||
|
c-set-style: K&R
|
||
|
c-basic-offset: 8
|
||
|
End:
|
||
|
*/
|