blob: 569a10f039b119d00273aea1c03006b4030204ac [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 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
Harald Welte2230c132011-01-19 10:10:16 +010022
23#include <stdint.h>
24
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010025#include <osmocom/core/bits.h>
Harald Welte2230c132011-01-19 10:10:16 +010026
Harald Welteba6988b2011-08-17 12:46:48 +020027/*! \addtogroup bits
28 * @{
29 */
30
31/*! \file bits.c
32 * \brief Osmocom bit level support code
33 */
34
35
36/*! \brief convert unpacked bits to packed bits, return length in bytes
37 * \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
Maxd8fb1422016-04-06 16:13:00 +020064/*! \brief convert unpacked bits to soft bits
65 * \param[out] out output buffer of soft bits
66 * \param[in] in input buffer of unpacked bits
67 * \param[in] num_bits number of bits
68 */
69void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits)
70{
71 unsigned int i;
72 for (i = 0; i < num_bits; i++)
73 out[i] = in[i] ? -127 : 127;
74}
75
76/*! \brief convert soft bits to unpacked bits
77 * \param[out] out output buffer of unpacked bits
78 * \param[in] in input buffer of soft bits
79 * \param[in] num_bits number of bits
80 */
81void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits)
82{
83 unsigned int i;
84 for (i = 0; i < num_bits; i++)
85 out[i] = in[i] < 0;
86}
87
Harald Welteba6988b2011-08-17 12:46:48 +020088/*! \brief convert packed bits to unpacked bits, return length in bytes
89 * \param[out] out output buffer of unpacked bits
90 * \param[in] in input buffer of packed bits
91 * \param[in] num_bits number of bits
Harald Welte2d2e2cc2016-04-25 12:11:20 +020092 * \return number of bytes used in \ref out
Harald Welteba6988b2011-08-17 12:46:48 +020093 */
Harald Welte2230c132011-01-19 10:10:16 +010094int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
95{
96 unsigned int i;
97 ubit_t *cur = out;
98 ubit_t *limit = out + num_bits;
99
100 for (i = 0; i < (num_bits/8)+1; i++) {
101 pbit_t byte = in[i];
102 *cur++ = (byte >> 7) & 1;
103 if (cur >= limit)
104 break;
105 *cur++ = (byte >> 6) & 1;
106 if (cur >= limit)
107 break;
108 *cur++ = (byte >> 5) & 1;
109 if (cur >= limit)
110 break;
111 *cur++ = (byte >> 4) & 1;
112 if (cur >= limit)
113 break;
114 *cur++ = (byte >> 3) & 1;
115 if (cur >= limit)
116 break;
117 *cur++ = (byte >> 2) & 1;
118 if (cur >= limit)
119 break;
120 *cur++ = (byte >> 1) & 1;
121 if (cur >= limit)
122 break;
123 *cur++ = (byte >> 0) & 1;
124 if (cur >= limit)
125 break;
126 }
127 return cur - out;
128}
Sylvain Munautaeb10772011-01-21 12:22:30 +0100129
Harald Welteba6988b2011-08-17 12:46:48 +0200130/*! \brief convert unpacked bits to packed bits (extended options)
131 * \param[out] out output buffer of packed bits
132 * \param[in] out_ofs offset into output buffer
133 * \param[in] in input buffer of unpacked bits
134 * \param[in] in_ofs offset into input buffer
135 * \param[in] num_bits number of bits
136 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
137 * \returns length in bytes (max written offset of output buffer + 1)
138 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100139int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
140 const ubit_t *in, unsigned int in_ofs,
141 unsigned int num_bits, int lsb_mode)
142{
143 int i, op, bn;
144 for (i=0; i<num_bits; i++) {
145 op = out_ofs + i;
146 bn = lsb_mode ? (op&7) : (7-(op&7));
147 if (in[in_ofs+i])
148 out[op>>3] |= 1 << bn;
149 else
150 out[op>>3] &= ~(1 << bn);
151 }
152 return ((out_ofs + num_bits - 1) >> 3) + 1;
153}
154
Harald Welteba6988b2011-08-17 12:46:48 +0200155/*! \brief convert packed bits to unpacked bits (extended options)
156 * \param[out] out output buffer of unpacked bits
157 * \param[in] out_ofs offset into output buffer
158 * \param[in] in input buffer of packed bits
159 * \param[in] in_ofs offset into input buffer
160 * \param[in] num_bits number of bits
161 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
162 * \returns length in bytes (max written offset of output buffer + 1)
163 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100164int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
165 const pbit_t *in, unsigned int in_ofs,
166 unsigned int num_bits, int lsb_mode)
167{
168 int i, ip, bn;
169 for (i=0; i<num_bits; i++) {
170 ip = in_ofs + i;
171 bn = lsb_mode ? (ip&7) : (7-(ip&7));
172 out[out_ofs+i] = !!(in[ip>>3] & (1<<bn));
173 }
174 return out_ofs + num_bits;
175}
Harald Welteba6988b2011-08-17 12:46:48 +0200176
Harald Weltede6e4982012-12-06 21:25:27 +0100177/*! \brief generalized bit reversal function
178 * \param[in] x the 32bit value to be reversed
179 * \param[in] k the type of reversal requested
180 * \returns the reversed 32bit dword
181 *
182 * This function reverses the bit order within a 32bit word. Depending
183 * on "k", it either reverses all bits in a 32bit dword, or the bytes in
184 * the dword, or the bits in each byte of a dword, or simply swaps the
185 * two 16bit words in a dword. See Chapter 7 "Hackers Delight"
186 */
Harald Welte712691d2011-09-01 14:47:31 +0200187uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k)
188{
189 if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
190 if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
191 if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
192 if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
193 if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
194
195 return x;
196}
197
Harald Weltede6e4982012-12-06 21:25:27 +0100198/*! \brief reverse the bit-order in each byte of a dword
199 * \param[in] x 32bit input value
200 * \returns 32bit value where bits of each byte have been reversed
201 *
202 * See Chapter 7 "Hackers Delight"
203 */
Harald Welte712691d2011-09-01 14:47:31 +0200204uint32_t osmo_revbytebits_32(uint32_t x)
205{
206 x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
207 x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
208 x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
209
210 return x;
211}
212
Harald Weltede6e4982012-12-06 21:25:27 +0100213/*! \brief reverse the bit order in a byte
214 * \param[in] x 8bit input value
215 * \returns 8bit value where bits order has been reversed
216 *
217 * See Chapter 7 "Hackers Delight"
218 */
Harald Welte712691d2011-09-01 14:47:31 +0200219uint32_t osmo_revbytebits_8(uint8_t x)
220{
221 x = (x & 0x55) << 1 | (x & 0xAA) >> 1;
222 x = (x & 0x33) << 2 | (x & 0xCC) >> 2;
223 x = (x & 0x0F) << 4 | (x & 0xF0) >> 4;
224
225 return x;
226}
227
Harald Weltede6e4982012-12-06 21:25:27 +0100228/*! \brief reverse bit-order of each byte in a buffer
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100229 * \param[in] buf buffer containing bytes to be bit-reversed
230 * \param[in] len length of buffer in bytes
Harald Weltede6e4982012-12-06 21:25:27 +0100231 *
232 * This function reverses the bits in each byte of the buffer
233 */
Harald Welte712691d2011-09-01 14:47:31 +0200234void osmo_revbytebits_buf(uint8_t *buf, int len)
235{
236 unsigned int i;
237 unsigned int unaligned_cnt;
238 int len_remain = len;
239
240 unaligned_cnt = ((unsigned long)buf & 3);
241 for (i = 0; i < unaligned_cnt; i++) {
242 buf[i] = osmo_revbytebits_8(buf[i]);
243 len_remain--;
244 if (len_remain <= 0)
245 return;
246 }
247
Sylvain Munaut01e06042013-01-03 09:36:16 +0100248 for (i = unaligned_cnt; i + 3 < len; i += 4) {
Max08621a82016-01-21 17:16:56 +0100249 osmo_store32be(osmo_revbytebits_32(osmo_load32be(buf + i)), buf + i);
Harald Welte712691d2011-09-01 14:47:31 +0200250 len_remain -= 4;
251 }
252
253 for (i = len - len_remain; i < len; i++) {
254 buf[i] = osmo_revbytebits_8(buf[i]);
255 len_remain--;
256 }
257}
258
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200259/*! @} */