blob: 6be6d7aca4e8b0219c77463f4d74b2f86d886305 [file] [log] [blame]
Harald Welte2230c132011-01-19 10:10:16 +01001
2#include <stdint.h>
3
Pablo Neira Ayuso83419342011-03-22 16:36:13 +01004#include <osmocom/core/bits.h>
Harald Welte2230c132011-01-19 10:10:16 +01005
Harald Welteba6988b2011-08-17 12:46:48 +02006/*! \addtogroup bits
7 * @{
8 */
9
10/*! \file bits.c
11 * \brief Osmocom bit level support code
12 */
13
14
15/*! \brief convert unpacked bits to packed bits, return length in bytes
16 * \param[out] out output buffer of packed bits
17 * \param[in] in input buffer of unpacked bits
18 * \param[in] num_bits number of bits
19 */
Harald Welte2230c132011-01-19 10:10:16 +010020int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits)
21{
22 unsigned int i;
23 uint8_t curbyte = 0;
24 pbit_t *outptr = out;
25
26 for (i = 0; i < num_bits; i++) {
27 uint8_t bitnum = 7 - (i % 8);
28
29 curbyte |= (in[i] << bitnum);
30
Christian Vogelc7f84e92011-01-22 22:48:37 +010031 if(i % 8 == 7){
Harald Welte2230c132011-01-19 10:10:16 +010032 *outptr++ = curbyte;
33 curbyte = 0;
34 }
35 }
36 /* we have a non-modulo-8 bitcount */
37 if (i % 8)
38 *outptr++ = curbyte;
39
40 return outptr - out;
41}
42
Harald Welteba6988b2011-08-17 12:46:48 +020043/*! \brief convert packed bits to unpacked bits, return length in bytes
44 * \param[out] out output buffer of unpacked bits
45 * \param[in] in input buffer of packed bits
46 * \param[in] num_bits number of bits
47 */
Harald Welte2230c132011-01-19 10:10:16 +010048int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
49{
50 unsigned int i;
51 ubit_t *cur = out;
52 ubit_t *limit = out + num_bits;
53
54 for (i = 0; i < (num_bits/8)+1; i++) {
55 pbit_t byte = in[i];
56 *cur++ = (byte >> 7) & 1;
57 if (cur >= limit)
58 break;
59 *cur++ = (byte >> 6) & 1;
60 if (cur >= limit)
61 break;
62 *cur++ = (byte >> 5) & 1;
63 if (cur >= limit)
64 break;
65 *cur++ = (byte >> 4) & 1;
66 if (cur >= limit)
67 break;
68 *cur++ = (byte >> 3) & 1;
69 if (cur >= limit)
70 break;
71 *cur++ = (byte >> 2) & 1;
72 if (cur >= limit)
73 break;
74 *cur++ = (byte >> 1) & 1;
75 if (cur >= limit)
76 break;
77 *cur++ = (byte >> 0) & 1;
78 if (cur >= limit)
79 break;
80 }
81 return cur - out;
82}
Sylvain Munautaeb10772011-01-21 12:22:30 +010083
Harald Welteba6988b2011-08-17 12:46:48 +020084/*! \brief convert unpacked bits to packed bits (extended options)
85 * \param[out] out output buffer of packed bits
86 * \param[in] out_ofs offset into output buffer
87 * \param[in] in input buffer of unpacked bits
88 * \param[in] in_ofs offset into input buffer
89 * \param[in] num_bits number of bits
90 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
91 * \returns length in bytes (max written offset of output buffer + 1)
92 */
Sylvain Munautaeb10772011-01-21 12:22:30 +010093int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
94 const ubit_t *in, unsigned int in_ofs,
95 unsigned int num_bits, int lsb_mode)
96{
97 int i, op, bn;
98 for (i=0; i<num_bits; i++) {
99 op = out_ofs + i;
100 bn = lsb_mode ? (op&7) : (7-(op&7));
101 if (in[in_ofs+i])
102 out[op>>3] |= 1 << bn;
103 else
104 out[op>>3] &= ~(1 << bn);
105 }
106 return ((out_ofs + num_bits - 1) >> 3) + 1;
107}
108
Harald Welteba6988b2011-08-17 12:46:48 +0200109/*! \brief convert packed bits to unpacked bits (extended options)
110 * \param[out] out output buffer of unpacked bits
111 * \param[in] out_ofs offset into output buffer
112 * \param[in] in input buffer of packed bits
113 * \param[in] in_ofs offset into input buffer
114 * \param[in] num_bits number of bits
115 * \param[in] lsb_mode Encode bits in LSB orde instead of MSB
116 * \returns length in bytes (max written offset of output buffer + 1)
117 */
Sylvain Munautaeb10772011-01-21 12:22:30 +0100118int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
119 const pbit_t *in, unsigned int in_ofs,
120 unsigned int num_bits, int lsb_mode)
121{
122 int i, ip, bn;
123 for (i=0; i<num_bits; i++) {
124 ip = in_ofs + i;
125 bn = lsb_mode ? (ip&7) : (7-(ip&7));
126 out[out_ofs+i] = !!(in[ip>>3] & (1<<bn));
127 }
128 return out_ofs + num_bits;
129}
Harald Welteba6988b2011-08-17 12:46:48 +0200130
Harald Weltede6e4982012-12-06 21:25:27 +0100131/*! \brief generalized bit reversal function
132 * \param[in] x the 32bit value to be reversed
133 * \param[in] k the type of reversal requested
134 * \returns the reversed 32bit dword
135 *
136 * This function reverses the bit order within a 32bit word. Depending
137 * on "k", it either reverses all bits in a 32bit dword, or the bytes in
138 * the dword, or the bits in each byte of a dword, or simply swaps the
139 * two 16bit words in a dword. See Chapter 7 "Hackers Delight"
140 */
Harald Welte712691d2011-09-01 14:47:31 +0200141uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k)
142{
143 if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
144 if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
145 if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
146 if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
147 if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
148
149 return x;
150}
151
Harald Weltede6e4982012-12-06 21:25:27 +0100152/*! \brief reverse the bit-order in each byte of a dword
153 * \param[in] x 32bit input value
154 * \returns 32bit value where bits of each byte have been reversed
155 *
156 * See Chapter 7 "Hackers Delight"
157 */
Harald Welte712691d2011-09-01 14:47:31 +0200158uint32_t osmo_revbytebits_32(uint32_t x)
159{
160 x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
161 x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
162 x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
163
164 return x;
165}
166
Harald Weltede6e4982012-12-06 21:25:27 +0100167/*! \brief reverse the bit order in a byte
168 * \param[in] x 8bit input value
169 * \returns 8bit value where bits order has been reversed
170 *
171 * See Chapter 7 "Hackers Delight"
172 */
Harald Welte712691d2011-09-01 14:47:31 +0200173uint32_t osmo_revbytebits_8(uint8_t x)
174{
175 x = (x & 0x55) << 1 | (x & 0xAA) >> 1;
176 x = (x & 0x33) << 2 | (x & 0xCC) >> 2;
177 x = (x & 0x0F) << 4 | (x & 0xF0) >> 4;
178
179 return x;
180}
181
Harald Weltede6e4982012-12-06 21:25:27 +0100182/*! \brief reverse bit-order of each byte in a buffer
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100183 * \param[in] buf buffer containing bytes to be bit-reversed
184 * \param[in] len length of buffer in bytes
Harald Weltede6e4982012-12-06 21:25:27 +0100185 *
186 * This function reverses the bits in each byte of the buffer
187 */
Harald Welte712691d2011-09-01 14:47:31 +0200188void osmo_revbytebits_buf(uint8_t *buf, int len)
189{
190 unsigned int i;
191 unsigned int unaligned_cnt;
192 int len_remain = len;
193
194 unaligned_cnt = ((unsigned long)buf & 3);
195 for (i = 0; i < unaligned_cnt; i++) {
196 buf[i] = osmo_revbytebits_8(buf[i]);
197 len_remain--;
198 if (len_remain <= 0)
199 return;
200 }
201
Sylvain Munaut01e06042013-01-03 09:36:16 +0100202 for (i = unaligned_cnt; i + 3 < len; i += 4) {
Harald Welte712691d2011-09-01 14:47:31 +0200203 uint32_t *cur = (uint32_t *) (buf + i);
204 *cur = osmo_revbytebits_32(*cur);
205 len_remain -= 4;
206 }
207
208 for (i = len - len_remain; i < len; i++) {
209 buf[i] = osmo_revbytebits_8(buf[i]);
210 len_remain--;
211 }
212}
213
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200214/*! @} */