diff options
-rw-r--r-- | include/osmocom/core/bits.h | 5 | ||||
-rw-r--r-- | src/bits.c | 48 | ||||
-rw-r--r-- | tests/bits/bitrev_test.c | 25 | ||||
-rw-r--r-- | tests/bits/bitrev_test.ok | 105 |
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); @@ -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 |