blob: aa1175317023c0335aa7e7f95105bea20111665e [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 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
Harald Welte2230c132011-01-19 10:10:16 +010024
25#include <stdint.h>
26
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010027#include <osmocom/core/bits.h>
Harald Welte2230c132011-01-19 10:10:16 +010028
Harald Welteba6988b2011-08-17 12:46:48 +020029/*! \addtogroup bits
30 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020031 * Osmocom bit level support code.
32 *
Harald Welteef7a44e2017-10-16 14:18:17 +020033 * This module implements the notion of different bit-fields, such as
34 * - unpacked bits (\ref ubit_t), i.e. 1 bit per byte
35 * - packed bits (\ref pbit_t), i.e. 8 bits per byte
36 * - soft bits (\ref sbit_t), 1 bit per byte from -127 to 127
37 *
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020038 * \file bits.c */
Harald Welteba6988b2011-08-17 12:46:48 +020039
Neels Hofmeyr87e45502017-06-20 00:17:59 +020040/*! convert unpacked bits to packed bits, return length in bytes
Harald Welteba6988b2011-08-17 12:46:48 +020041 * \param[out] out output buffer of packed bits
42 * \param[in] in input buffer of unpacked bits
43 * \param[in] num_bits number of bits
44 */
Harald Welte2230c132011-01-19 10:10:16 +010045int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits)
46{
47 unsigned int i;
48 uint8_t curbyte = 0;
49 pbit_t *outptr = out;
50
51 for (i = 0; i < num_bits; i++) {
52 uint8_t bitnum = 7 - (i % 8);
53
54 curbyte |= (in[i] << bitnum);
55
Christian Vogelc7f84e92011-01-22 22:48:37 +010056 if(i % 8 == 7){
Harald Welte2230c132011-01-19 10:10:16 +010057 *outptr++ = curbyte;
58 curbyte = 0;
59 }
60 }
61 /* we have a non-modulo-8 bitcount */
62 if (i % 8)
63 *outptr++ = curbyte;
64
65 return outptr - out;
66}
67
Neels Hofmeyr87e45502017-06-20 00:17:59 +020068/*! Shift unaligned input to octet-aligned output
Maxe0a7d9e2016-06-17 17:58:52 +020069 * \param[out] out output buffer, unaligned
70 * \param[in] in input buffer, octet-aligned
71 * \param[in] num_nibbles number of nibbles
72 */
73void osmo_nibble_shift_right(uint8_t *out, const uint8_t *in,
74 unsigned int num_nibbles)
75{
76 unsigned int i, num_whole_bytes = num_nibbles / 2;
77 if (!num_whole_bytes)
78 return;
79
80 /* first byte: upper nibble empty, lower nibble from src */
81 out[0] = (in[0] >> 4);
82
83 /* bytes 1.. */
84 for (i = 1; i < num_whole_bytes; i++)
85 out[i] = ((in[i - 1] & 0xF) << 4) | (in[i] >> 4);
86
87 /* shift the last nibble, in case there's an odd count */
88 i = num_whole_bytes;
89 if (num_nibbles & 1)
90 out[i] = ((in[i - 1] & 0xF) << 4) | (in[i] >> 4);
91 else
92 out[i] = (in[i - 1] & 0xF) << 4;
93}
94
Neels Hofmeyr87e45502017-06-20 00:17:59 +020095/*! Shift unaligned input to octet-aligned output
Maxe0a7d9e2016-06-17 17:58:52 +020096 * \param[out] out output buffer, octet-aligned
97 * \param[in] in input buffer, unaligned
98 * \param[in] num_nibbles number of nibbles
99 */
100void osmo_nibble_shift_left_unal(uint8_t *out, const uint8_t *in,
101 unsigned int num_nibbles)
102{
103 unsigned int i, num_whole_bytes = num_nibbles / 2;
104 if (!num_whole_bytes)
105 return;
106
107 for (i = 0; i < num_whole_bytes; i++)
108 out[i] = ((in[i] & 0xF) << 4) | (in[i + 1] >> 4);
109
110 /* shift the last nibble, in case there's an odd count */
111 i = num_whole_bytes;
112 if (num_nibbles & 1)
113 out[i] = (in[i] & 0xF) << 4;
114}
115
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200116/*! convert unpacked bits to soft bits
Maxd8fb1422016-04-06 16:13:00 +0200117 * \param[out] out output buffer of soft bits
118 * \param[in] in input buffer of unpacked bits
119 * \param[in] num_bits number of bits
120 */
121void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits)
122{
123 unsigned int i;
124 for (i = 0; i < num_bits; i++)
125 out[i] = in[i] ? -127 : 127;
126}
127
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200128/*! convert soft bits to unpacked bits
Maxd8fb1422016-04-06 16:13:00 +0200129 * \param[out] out output buffer of unpacked bits
130 * \param[in] in input buffer of soft bits
131 * \param[in] num_bits number of bits
132 */
133void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits)
134{
135 unsigned int i;
136 for (i = 0; i < num_bits; i++)
137 out[i] = in[i] < 0;
138}
139
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200140/*! convert packed bits to unpacked bits, return length in bytes
Harald Welteba6988b2011-08-17 12:46:48 +0200141 * \param[out] out output buffer of unpacked bits
142 * \param[in] in input buffer of packed bits
143 * \param[in] num_bits number of bits
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200144 * \return number of bytes used in \ref out
Harald Welteba6988b2011-08-17 12:46:48 +0200145 */
Harald Welte2230c132011-01-19 10:10:16 +0100146int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
147{
148 unsigned int i;
149 ubit_t *cur = out;
150 ubit_t *limit = out + num_bits;
151
152 for (i = 0; i < (num_bits/8)+1; i++) {
153 pbit_t byte = in[i];
154 *cur++ = (byte >> 7) & 1;
155 if (cur >= limit)
156 break;
157 *cur++ = (byte >> 6) & 1;
158 if (cur >= limit)
159 break;
160 *cur++ = (byte >> 5) & 1;
161 if (cur >= limit)
162 break;
163 *cur++ = (byte >> 4) & 1;
164 if (cur >= limit)
165 break;
166 *cur++ = (byte >> 3) & 1;
167 if (cur >= limit)
168 break;
169 *cur++ = (byte >> 2) & 1;
170 if (cur >= limit)
171 break;
172 *cur++ = (byte >> 1) & 1;
173 if (cur >= limit)
174 break;
175 *cur++ = (byte >> 0) & 1;
176 if (cur >= limit)
177 break;
178 }
179 return cur - out;
180}
Sylvain Munautaeb10772011-01-21 12:22:30 +0100181
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200182/*! convert unpacked bits to packed bits (extended options)
Harald Welteba6988b2011-08-17 12:46:48 +0200183 * \param[out] out output buffer of packed bits
184 * \param[in] out_ofs offset into output buffer
185 * \param[in] in input buffer of unpacked bits
186 * \param[in] in_ofs offset into input buffer
187 * \param[in] num_bits number of bits
188 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
189 * \returns length in bytes (max written offset of output buffer + 1)
190 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100191int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
192 const ubit_t *in, unsigned int in_ofs,
193 unsigned int num_bits, int lsb_mode)
194{
195 int i, op, bn;
196 for (i=0; i<num_bits; i++) {
197 op = out_ofs + i;
198 bn = lsb_mode ? (op&7) : (7-(op&7));
199 if (in[in_ofs+i])
200 out[op>>3] |= 1 << bn;
201 else
202 out[op>>3] &= ~(1 << bn);
203 }
204 return ((out_ofs + num_bits - 1) >> 3) + 1;
205}
206
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200207/*! convert packed bits to unpacked bits (extended options)
Harald Welteba6988b2011-08-17 12:46:48 +0200208 * \param[out] out output buffer of unpacked bits
209 * \param[in] out_ofs offset into output buffer
210 * \param[in] in input buffer of packed bits
211 * \param[in] in_ofs offset into input buffer
212 * \param[in] num_bits number of bits
213 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
214 * \returns length in bytes (max written offset of output buffer + 1)
215 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100216int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
217 const pbit_t *in, unsigned int in_ofs,
218 unsigned int num_bits, int lsb_mode)
219{
220 int i, ip, bn;
221 for (i=0; i<num_bits; i++) {
222 ip = in_ofs + i;
223 bn = lsb_mode ? (ip&7) : (7-(ip&7));
224 out[out_ofs+i] = !!(in[ip>>3] & (1<<bn));
225 }
226 return out_ofs + num_bits;
227}
Harald Welteba6988b2011-08-17 12:46:48 +0200228
Harald Welte2ba641e2020-08-02 10:19:32 +0200229/* look-up table for bit-reversal within a byte. Generated using:
230 int i,k;
231 for (i = 0 ; i < 256 ; i++) {
232 uint8_t sample = 0 ;
233 for (k = 0; k<8; k++) {
234 if ( i & 1 << k ) sample |= 0x80 >> k;
235 }
236 flip_table[i] = sample;
237 }
238 */
239static const uint8_t flip_table[256] = {
240 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
241 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
242 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
243 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
244 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
245 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
246 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
247 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
248 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
249 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
250 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
251 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
252 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
253 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
254 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
255 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
256};
257
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200258/*! generalized bit reversal function
Harald Weltede6e4982012-12-06 21:25:27 +0100259 * \param[in] x the 32bit value to be reversed
260 * \param[in] k the type of reversal requested
261 * \returns the reversed 32bit dword
262 *
263 * This function reverses the bit order within a 32bit word. Depending
264 * on "k", it either reverses all bits in a 32bit dword, or the bytes in
265 * the dword, or the bits in each byte of a dword, or simply swaps the
266 * two 16bit words in a dword. See Chapter 7 "Hackers Delight"
267 */
Harald Welte712691d2011-09-01 14:47:31 +0200268uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k)
269{
270 if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
271 if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
272 if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
273 if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
274 if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
275
276 return x;
277}
278
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200279/*! reverse the bit-order in each byte of a dword
Harald Weltede6e4982012-12-06 21:25:27 +0100280 * \param[in] x 32bit input value
281 * \returns 32bit value where bits of each byte have been reversed
282 *
283 * See Chapter 7 "Hackers Delight"
284 */
Harald Welte712691d2011-09-01 14:47:31 +0200285uint32_t osmo_revbytebits_32(uint32_t x)
286{
287 x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
288 x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
289 x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
290
291 return x;
292}
293
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200294/*! reverse the bit order in a byte
Harald Weltede6e4982012-12-06 21:25:27 +0100295 * \param[in] x 8bit input value
296 * \returns 8bit value where bits order has been reversed
Harald Weltede6e4982012-12-06 21:25:27 +0100297 */
Harald Welte712691d2011-09-01 14:47:31 +0200298uint32_t osmo_revbytebits_8(uint8_t x)
299{
Harald Welte2ba641e2020-08-02 10:19:32 +0200300 return flip_table[x];
Harald Welte712691d2011-09-01 14:47:31 +0200301}
302
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200303/*! reverse bit-order of each byte in a buffer
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100304 * \param[in] buf buffer containing bytes to be bit-reversed
305 * \param[in] len length of buffer in bytes
Harald Weltede6e4982012-12-06 21:25:27 +0100306 *
307 * This function reverses the bits in each byte of the buffer
308 */
Harald Welte712691d2011-09-01 14:47:31 +0200309void osmo_revbytebits_buf(uint8_t *buf, int len)
310{
311 unsigned int i;
Harald Welte712691d2011-09-01 14:47:31 +0200312
Harald Welte2ba641e2020-08-02 10:19:32 +0200313 for (i = 0; i < len; i++)
314 buf[i] = flip_table[buf[i]];
Harald Welte712691d2011-09-01 14:47:31 +0200315}
316
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200317/*! @} */