blob: 4c67bddb4fd5693c515a8231e6656f73a69ab82a [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 Welte712691d2011-09-01 14:47:31 +0200131/* generalized bit reversal function, Chapter 7 "Hackers Delight" */
132uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k)
133{
134 if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
135 if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
136 if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
137 if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
138 if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
139
140 return x;
141}
142
143/* generalized bit reversal function, Chapter 7 "Hackers Delight" */
144uint32_t osmo_revbytebits_32(uint32_t x)
145{
146 x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
147 x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
148 x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
149
150 return x;
151}
152
153uint32_t osmo_revbytebits_8(uint8_t x)
154{
155 x = (x & 0x55) << 1 | (x & 0xAA) >> 1;
156 x = (x & 0x33) << 2 | (x & 0xCC) >> 2;
157 x = (x & 0x0F) << 4 | (x & 0xF0) >> 4;
158
159 return x;
160}
161
162void osmo_revbytebits_buf(uint8_t *buf, int len)
163{
164 unsigned int i;
165 unsigned int unaligned_cnt;
166 int len_remain = len;
167
168 unaligned_cnt = ((unsigned long)buf & 3);
169 for (i = 0; i < unaligned_cnt; i++) {
170 buf[i] = osmo_revbytebits_8(buf[i]);
171 len_remain--;
172 if (len_remain <= 0)
173 return;
174 }
175
176 for (i = unaligned_cnt; i < len; i += 4) {
177 uint32_t *cur = (uint32_t *) (buf + i);
178 *cur = osmo_revbytebits_32(*cur);
179 len_remain -= 4;
180 }
181
182 for (i = len - len_remain; i < len; i++) {
183 buf[i] = osmo_revbytebits_8(buf[i]);
184 len_remain--;
185 }
186}
187
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200188/*! @} */