summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/core/bits.h5
-rw-r--r--src/bits.c48
-rw-r--r--tests/bits/bitrev_test.c25
-rw-r--r--tests/bits/bitrev_test.ok105
4 files changed, 183 insertions, 0 deletions
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
index 3218330b..5535920e 100644
--- a/include/osmocom/core/bits.h
+++ b/include/osmocom/core/bits.h
@@ -41,6 +41,11 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits);
int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits);
+void osmo_nibble_shift_right(uint8_t *out, const uint8_t *in,
+ unsigned int num_nibbles);
+void osmo_nibble_shift_left_unal(uint8_t *out, const uint8_t *in,
+ unsigned int num_nibbles);
+
void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits);
void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits);
diff --git a/src/bits.c b/src/bits.c
index 569a10f0..0c77b279 100644
--- a/src/bits.c
+++ b/src/bits.c
@@ -61,6 +61,54 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits)
return outptr - out;
}
+/*! \brief Shift unaligned input to octet-aligned output
+ * \param[out] out output buffer, unaligned
+ * \param[in] in input buffer, octet-aligned
+ * \param[in] num_nibbles number of nibbles
+ */
+void osmo_nibble_shift_right(uint8_t *out, const uint8_t *in,
+ unsigned int num_nibbles)
+{
+ unsigned int i, num_whole_bytes = num_nibbles / 2;
+ if (!num_whole_bytes)
+ return;
+
+ /* first byte: upper nibble empty, lower nibble from src */
+ out[0] = (in[0] >> 4);
+
+ /* bytes 1.. */
+ for (i = 1; i < num_whole_bytes; i++)
+ out[i] = ((in[i - 1] & 0xF) << 4) | (in[i] >> 4);
+
+ /* shift the last nibble, in case there's an odd count */
+ i = num_whole_bytes;
+ if (num_nibbles & 1)
+ out[i] = ((in[i - 1] & 0xF) << 4) | (in[i] >> 4);
+ else
+ out[i] = (in[i - 1] & 0xF) << 4;
+}
+
+/*! \brief Shift unaligned input to octet-aligned output
+ * \param[out] out output buffer, octet-aligned
+ * \param[in] in input buffer, unaligned
+ * \param[in] num_nibbles number of nibbles
+ */
+void osmo_nibble_shift_left_unal(uint8_t *out, const uint8_t *in,
+ unsigned int num_nibbles)
+{
+ unsigned int i, num_whole_bytes = num_nibbles / 2;
+ if (!num_whole_bytes)
+ return;
+
+ for (i = 0; i < num_whole_bytes; i++)
+ out[i] = ((in[i] & 0xF) << 4) | (in[i + 1] >> 4);
+
+ /* shift the last nibble, in case there's an odd count */
+ i = num_whole_bytes;
+ if (num_nibbles & 1)
+ out[i] = (in[i] & 0xF) << 4;
+}
+
/*! \brief convert unpacked bits to soft bits
* \param[out] out output buffer of soft bits
* \param[in] in input buffer of unpacked bits
diff --git a/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 987f4d51..08f08278 100644
--- a/tests/bits/bitrev_test.c
+++ b/tests/bits/bitrev_test.c
@@ -205,6 +205,20 @@ check16(uint16_t test, enum END e)
printcheck16(e, test, test, (BE == e) ? s : NULL, print);
}
+static void sh_chk(const uint8_t *in, uint8_t len, unsigned int nib, bool r)
+{
+ uint8_t x[len];
+ if (r)
+ osmo_nibble_shift_right(x, in, nib);
+ else
+ osmo_nibble_shift_left_unal(x, in, nib);
+
+ printf("[%u] %s IN: %s, nibble %u:", len, r ? "R" : "L",
+ osmo_hexdump_nospc(in, len), nib);
+ /* do NOT combine those printfs: osmo_hexdump* use static buffer which
+ WILL screw things up in that case */
+ printf("\n OUT: %s\n", osmo_hexdump_nospc(x, nib/2));
+}
int main(int argc, char **argv)
{
@@ -274,5 +288,16 @@ int main(int argc, char **argv)
check16(0, BE);
check16(0, LE);
+ printf("running nibble tests...\n");
+
+ const uint8_t in1[] = { 0xF0, 0x0D, 0xCA, 0xFE, 0xDE, 0xAD, 0xBE, 0xEF },
+ in2[] = { 0xB0, 0x0B, 0xBA, 0xBE, 0xFA, 0xCE };
+
+ for (offs = 0; offs < 13; offs++) {
+ sh_chk(in1, ARRAY_SIZE(in1), offs, true);
+ sh_chk(in1, ARRAY_SIZE(in1), offs, false);
+ sh_chk(in2, ARRAY_SIZE(in2), offs, true);
+ sh_chk(in2, ARRAY_SIZE(in2), offs, false);
+ }
return 0;
}
diff --git a/tests/bits/bitrev_test.ok b/tests/bits/bitrev_test.ok
index 90cb295f..9fbb4d9c 100644
--- a/tests/bits/bitrev_test.ok
+++ b/tests/bits/bitrev_test.ok
@@ -53,3 +53,108 @@ running random tests...
24 LE OK
16 BE OK, storage OK
16 LE OK
+running nibble tests...
+[8] R IN: f00dcafedeadbeef, nibble 0:
+ OUT:
+[8] L IN: f00dcafedeadbeef, nibble 0:
+ OUT:
+[6] R IN: b00bbabeface, nibble 0:
+ OUT:
+[6] L IN: b00bbabeface, nibble 0:
+ OUT:
+[8] R IN: f00dcafedeadbeef, nibble 1:
+ OUT:
+[8] L IN: f00dcafedeadbeef, nibble 1:
+ OUT:
+[6] R IN: b00bbabeface, nibble 1:
+ OUT:
+[6] L IN: b00bbabeface, nibble 1:
+ OUT:
+[8] R IN: f00dcafedeadbeef, nibble 2:
+ OUT: 0f
+[8] L IN: f00dcafedeadbeef, nibble 2:
+ OUT: 00
+[6] R IN: b00bbabeface, nibble 2:
+ OUT: 0b
+[6] L IN: b00bbabeface, nibble 2:
+ OUT: 00
+[8] R IN: f00dcafedeadbeef, nibble 3:
+ OUT: 0f
+[8] L IN: f00dcafedeadbeef, nibble 3:
+ OUT: 00
+[6] R IN: b00bbabeface, nibble 3:
+ OUT: 0b
+[6] L IN: b00bbabeface, nibble 3:
+ OUT: 00
+[8] R IN: f00dcafedeadbeef, nibble 4:
+ OUT: 0f00
+[8] L IN: f00dcafedeadbeef, nibble 4:
+ OUT: 00dc
+[6] R IN: b00bbabeface, nibble 4:
+ OUT: 0b00
+[6] L IN: b00bbabeface, nibble 4:
+ OUT: 00bb
+[8] R IN: f00dcafedeadbeef, nibble 5:
+ OUT: 0f00
+[8] L IN: f00dcafedeadbeef, nibble 5:
+ OUT: 00dc
+[6] R IN: b00bbabeface, nibble 5:
+ OUT: 0b00
+[6] L IN: b00bbabeface, nibble 5:
+ OUT: 00bb
+[8] R IN: f00dcafedeadbeef, nibble 6:
+ OUT: 0f00dc
+[8] L IN: f00dcafedeadbeef, nibble 6:
+ OUT: 00dcaf
+[6] R IN: b00bbabeface, nibble 6:
+ OUT: 0b00bb
+[6] L IN: b00bbabeface, nibble 6:
+ OUT: 00bbab
+[8] R IN: f00dcafedeadbeef, nibble 7:
+ OUT: 0f00dc
+[8] L IN: f00dcafedeadbeef, nibble 7:
+ OUT: 00dcaf
+[6] R IN: b00bbabeface, nibble 7:
+ OUT: 0b00bb
+[6] L IN: b00bbabeface, nibble 7:
+ OUT: 00bbab
+[8] R IN: f00dcafedeadbeef, nibble 8:
+ OUT: 0f00dcaf
+[8] L IN: f00dcafedeadbeef, nibble 8:
+ OUT: 00dcafed
+[6] R IN: b00bbabeface, nibble 8:
+ OUT: 0b00bbab
+[6] L IN: b00bbabeface, nibble 8:
+ OUT: 00bbabef
+[8] R IN: f00dcafedeadbeef, nibble 9:
+ OUT: 0f00dcaf
+[8] L IN: f00dcafedeadbeef, nibble 9:
+ OUT: 00dcafed
+[6] R IN: b00bbabeface, nibble 9:
+ OUT: 0b00bbab
+[6] L IN: b00bbabeface, nibble 9:
+ OUT: 00bbabef
+[8] R IN: f00dcafedeadbeef, nibble 10:
+ OUT: 0f00dcafed
+[8] L IN: f00dcafedeadbeef, nibble 10:
+ OUT: 00dcafedea
+[6] R IN: b00bbabeface, nibble 10:
+ OUT: 0b00bbabef
+[6] L IN: b00bbabeface, nibble 10:
+ OUT: 00bbabefac
+[8] R IN: f00dcafedeadbeef, nibble 11:
+ OUT: 0f00dcafed
+[8] L IN: f00dcafedeadbeef, nibble 11:
+ OUT: 00dcafedea
+[6] R IN: b00bbabeface, nibble 11:
+ OUT: 0b00bbabef
+[6] L IN: b00bbabeface, nibble 11:
+ OUT: 00bbabefac
+[8] R IN: f00dcafedeadbeef, nibble 12:
+ OUT: 0f00dcafedea
+[8] L IN: f00dcafedeadbeef, nibble 12:
+ OUT: 00dcafedeadb
+[6] R IN: b00bbabeface, nibble 12:
+ OUT: 0b00bbabefac
+[6] L IN: b00bbabeface, nibble 12:
+ OUT: 00bbabeface0