blob: 4b413a3f194f1534fc92f2841be2b1b8e1c2ad56 [file] [log] [blame]
Harald Welte468b6432014-09-11 13:05:51 +08001/*
2 * (C) 2011 by Harald Welte <laforge@gnumonks.org>
3 * (C) 2011 by Sylvain Munaut <tnt@246tNt.com>
4 *
5 * All Rights Reserved
6 *
Harald Weltee08da972017-11-13 01:00:26 +09007 * SPDX-License-Identifier: GPL-2.0+
8 *
Harald Welte468b6432014-09-11 13:05:51 +08009 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
Harald Welte468b6432014-09-11 13:05:51 +080019 */
Harald Welte2230c132011-01-19 10:10:16 +010020
21#include <stdint.h>
22
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010023#include <osmocom/core/bits.h>
Harald Welte2230c132011-01-19 10:10:16 +010024
Harald Welteba6988b2011-08-17 12:46:48 +020025/*! \addtogroup bits
26 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020027 * Osmocom bit level support code.
28 *
Harald Welteef7a44e2017-10-16 14:18:17 +020029 * This module implements the notion of different bit-fields, such as
30 * - unpacked bits (\ref ubit_t), i.e. 1 bit per byte
31 * - packed bits (\ref pbit_t), i.e. 8 bits per byte
32 * - soft bits (\ref sbit_t), 1 bit per byte from -127 to 127
33 *
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020034 * \file bits.c */
Harald Welteba6988b2011-08-17 12:46:48 +020035
Neels Hofmeyr87e45502017-06-20 00:17:59 +020036/*! convert unpacked bits to packed bits, return length in bytes
Harald Welteba6988b2011-08-17 12:46:48 +020037 * \param[out] out output buffer of packed bits
38 * \param[in] in input buffer of unpacked bits
39 * \param[in] num_bits number of bits
40 */
Harald Welte2230c132011-01-19 10:10:16 +010041int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits)
42{
43 unsigned int i;
44 uint8_t curbyte = 0;
45 pbit_t *outptr = out;
46
47 for (i = 0; i < num_bits; i++) {
48 uint8_t bitnum = 7 - (i % 8);
49
50 curbyte |= (in[i] << bitnum);
51
Christian Vogelc7f84e92011-01-22 22:48:37 +010052 if(i % 8 == 7){
Harald Welte2230c132011-01-19 10:10:16 +010053 *outptr++ = curbyte;
54 curbyte = 0;
55 }
56 }
57 /* we have a non-modulo-8 bitcount */
58 if (i % 8)
59 *outptr++ = curbyte;
60
61 return outptr - out;
62}
63
Neels Hofmeyr87e45502017-06-20 00:17:59 +020064/*! Shift unaligned input to octet-aligned output
Maxe0a7d9e2016-06-17 17:58:52 +020065 * \param[out] out output buffer, unaligned
66 * \param[in] in input buffer, octet-aligned
67 * \param[in] num_nibbles number of nibbles
68 */
69void osmo_nibble_shift_right(uint8_t *out, const uint8_t *in,
70 unsigned int num_nibbles)
71{
72 unsigned int i, num_whole_bytes = num_nibbles / 2;
73 if (!num_whole_bytes)
74 return;
75
76 /* first byte: upper nibble empty, lower nibble from src */
77 out[0] = (in[0] >> 4);
78
79 /* bytes 1.. */
80 for (i = 1; i < num_whole_bytes; i++)
81 out[i] = ((in[i - 1] & 0xF) << 4) | (in[i] >> 4);
82
83 /* shift the last nibble, in case there's an odd count */
84 i = num_whole_bytes;
85 if (num_nibbles & 1)
86 out[i] = ((in[i - 1] & 0xF) << 4) | (in[i] >> 4);
87 else
88 out[i] = (in[i - 1] & 0xF) << 4;
89}
90
Neels Hofmeyr87e45502017-06-20 00:17:59 +020091/*! Shift unaligned input to octet-aligned output
Maxe0a7d9e2016-06-17 17:58:52 +020092 * \param[out] out output buffer, octet-aligned
93 * \param[in] in input buffer, unaligned
94 * \param[in] num_nibbles number of nibbles
95 */
96void osmo_nibble_shift_left_unal(uint8_t *out, const uint8_t *in,
97 unsigned int num_nibbles)
98{
99 unsigned int i, num_whole_bytes = num_nibbles / 2;
100 if (!num_whole_bytes)
101 return;
102
103 for (i = 0; i < num_whole_bytes; i++)
104 out[i] = ((in[i] & 0xF) << 4) | (in[i + 1] >> 4);
105
106 /* shift the last nibble, in case there's an odd count */
107 i = num_whole_bytes;
108 if (num_nibbles & 1)
109 out[i] = (in[i] & 0xF) << 4;
110}
111
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200112/*! convert unpacked bits to soft bits
Maxd8fb1422016-04-06 16:13:00 +0200113 * \param[out] out output buffer of soft bits
114 * \param[in] in input buffer of unpacked bits
115 * \param[in] num_bits number of bits
116 */
117void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits)
118{
119 unsigned int i;
120 for (i = 0; i < num_bits; i++)
121 out[i] = in[i] ? -127 : 127;
122}
123
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200124/*! convert soft bits to unpacked bits
Maxd8fb1422016-04-06 16:13:00 +0200125 * \param[out] out output buffer of unpacked bits
126 * \param[in] in input buffer of soft bits
127 * \param[in] num_bits number of bits
128 */
129void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits)
130{
131 unsigned int i;
132 for (i = 0; i < num_bits; i++)
133 out[i] = in[i] < 0;
134}
135
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200136/*! convert packed bits to unpacked bits, return length in bytes
Harald Welteba6988b2011-08-17 12:46:48 +0200137 * \param[out] out output buffer of unpacked bits
138 * \param[in] in input buffer of packed bits
139 * \param[in] num_bits number of bits
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200140 * \return number of bytes used in \ref out
Harald Welteba6988b2011-08-17 12:46:48 +0200141 */
Harald Welte2230c132011-01-19 10:10:16 +0100142int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
143{
144 unsigned int i;
145 ubit_t *cur = out;
146 ubit_t *limit = out + num_bits;
147
148 for (i = 0; i < (num_bits/8)+1; i++) {
149 pbit_t byte = in[i];
150 *cur++ = (byte >> 7) & 1;
151 if (cur >= limit)
152 break;
153 *cur++ = (byte >> 6) & 1;
154 if (cur >= limit)
155 break;
156 *cur++ = (byte >> 5) & 1;
157 if (cur >= limit)
158 break;
159 *cur++ = (byte >> 4) & 1;
160 if (cur >= limit)
161 break;
162 *cur++ = (byte >> 3) & 1;
163 if (cur >= limit)
164 break;
165 *cur++ = (byte >> 2) & 1;
166 if (cur >= limit)
167 break;
168 *cur++ = (byte >> 1) & 1;
169 if (cur >= limit)
170 break;
171 *cur++ = (byte >> 0) & 1;
172 if (cur >= limit)
173 break;
174 }
175 return cur - out;
176}
Sylvain Munautaeb10772011-01-21 12:22:30 +0100177
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200178/*! convert unpacked bits to packed bits (extended options)
Harald Welteba6988b2011-08-17 12:46:48 +0200179 * \param[out] out output buffer of packed bits
180 * \param[in] out_ofs offset into output buffer
181 * \param[in] in input buffer of unpacked bits
182 * \param[in] in_ofs offset into input buffer
183 * \param[in] num_bits number of bits
184 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
185 * \returns length in bytes (max written offset of output buffer + 1)
186 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100187int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
188 const ubit_t *in, unsigned int in_ofs,
189 unsigned int num_bits, int lsb_mode)
190{
191 int i, op, bn;
192 for (i=0; i<num_bits; i++) {
193 op = out_ofs + i;
194 bn = lsb_mode ? (op&7) : (7-(op&7));
195 if (in[in_ofs+i])
196 out[op>>3] |= 1 << bn;
197 else
198 out[op>>3] &= ~(1 << bn);
199 }
200 return ((out_ofs + num_bits - 1) >> 3) + 1;
201}
202
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200203/*! convert packed bits to unpacked bits (extended options)
Harald Welteba6988b2011-08-17 12:46:48 +0200204 * \param[out] out output buffer of unpacked bits
205 * \param[in] out_ofs offset into output buffer
206 * \param[in] in input buffer of packed bits
207 * \param[in] in_ofs offset into input buffer
208 * \param[in] num_bits number of bits
209 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
210 * \returns length in bytes (max written offset of output buffer + 1)
211 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100212int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
213 const pbit_t *in, unsigned int in_ofs,
214 unsigned int num_bits, int lsb_mode)
215{
216 int i, ip, bn;
217 for (i=0; i<num_bits; i++) {
218 ip = in_ofs + i;
219 bn = lsb_mode ? (ip&7) : (7-(ip&7));
220 out[out_ofs+i] = !!(in[ip>>3] & (1<<bn));
221 }
222 return out_ofs + num_bits;
223}
Harald Welteba6988b2011-08-17 12:46:48 +0200224
Harald Welte2ba641e2020-08-02 10:19:32 +0200225/* look-up table for bit-reversal within a byte. Generated using:
226 int i,k;
227 for (i = 0 ; i < 256 ; i++) {
228 uint8_t sample = 0 ;
229 for (k = 0; k<8; k++) {
230 if ( i & 1 << k ) sample |= 0x80 >> k;
231 }
232 flip_table[i] = sample;
233 }
234 */
235static const uint8_t flip_table[256] = {
236 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
237 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
238 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
239 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
240 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
241 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
242 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
243 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
244 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
245 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
246 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
247 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
248 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
249 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
250 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
251 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
252};
253
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200254/*! generalized bit reversal function
Harald Weltede6e4982012-12-06 21:25:27 +0100255 * \param[in] x the 32bit value to be reversed
256 * \param[in] k the type of reversal requested
257 * \returns the reversed 32bit dword
258 *
259 * This function reverses the bit order within a 32bit word. Depending
260 * on "k", it either reverses all bits in a 32bit dword, or the bytes in
261 * the dword, or the bits in each byte of a dword, or simply swaps the
262 * two 16bit words in a dword. See Chapter 7 "Hackers Delight"
263 */
Harald Welte712691d2011-09-01 14:47:31 +0200264uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k)
265{
266 if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
267 if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
268 if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
269 if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
270 if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
271
272 return x;
273}
274
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200275/*! reverse the bit-order in each byte of a dword
Harald Weltede6e4982012-12-06 21:25:27 +0100276 * \param[in] x 32bit input value
277 * \returns 32bit value where bits of each byte have been reversed
278 *
279 * See Chapter 7 "Hackers Delight"
280 */
Harald Welte712691d2011-09-01 14:47:31 +0200281uint32_t osmo_revbytebits_32(uint32_t x)
282{
283 x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
284 x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
285 x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
286
287 return x;
288}
289
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200290/*! reverse the bit order in a byte
Harald Weltede6e4982012-12-06 21:25:27 +0100291 * \param[in] x 8bit input value
292 * \returns 8bit value where bits order has been reversed
Harald Weltede6e4982012-12-06 21:25:27 +0100293 */
Harald Welte712691d2011-09-01 14:47:31 +0200294uint32_t osmo_revbytebits_8(uint8_t x)
295{
Harald Welte2ba641e2020-08-02 10:19:32 +0200296 return flip_table[x];
Harald Welte712691d2011-09-01 14:47:31 +0200297}
298
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200299/*! reverse bit-order of each byte in a buffer
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100300 * \param[in] buf buffer containing bytes to be bit-reversed
301 * \param[in] len length of buffer in bytes
Harald Weltede6e4982012-12-06 21:25:27 +0100302 *
303 * This function reverses the bits in each byte of the buffer
304 */
Harald Welte712691d2011-09-01 14:47:31 +0200305void osmo_revbytebits_buf(uint8_t *buf, int len)
306{
307 unsigned int i;
Harald Welte712691d2011-09-01 14:47:31 +0200308
Harald Welte2ba641e2020-08-02 10:19:32 +0200309 for (i = 0; i < len; i++)
310 buf[i] = flip_table[buf[i]];
Harald Welte712691d2011-09-01 14:47:31 +0200311}
312
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200313/*! @} */