From 6830d35b449141305f137f78f09c2b879bfb9b33 Mon Sep 17 00:00:00 2001 From: Christopher Peplin Date: Sun, 29 Dec 2013 11:34:10 -0500 Subject: Clean up bitfield API a bit. --- src/bitfield/bitfield.h | 65 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 13 deletions(-) (limited to 'src/bitfield/bitfield.h') diff --git a/src/bitfield/bitfield.h b/src/bitfield/bitfield.h index ce68b949..bf5c9b7d 100644 --- a/src/bitfield/bitfield.h +++ b/src/bitfield/bitfield.h @@ -8,20 +8,57 @@ extern "C" { #endif -typedef enum { - ENDIANNESS_LITTLE_ENDIAN, - ENDIANNESS_BIG_ENDIAN -} Endianness; - uint8_t getNibble(const uint8_t nibble_index, const uint8_t data[], - const uint8_t length, Endianness endianness); + const uint8_t length); uint8_t getByte(const uint8_t byte_index, const uint8_t data[], - const uint8_t length, Endianness endianness); + const uint8_t length); + +/* Public: Copy a range of bits from one bit array to another. + * + * The range does not need to be byte aligned, and the source and destination do + * not have to be the same size (as long as the desitnation has enough room to + * fit the range). + * + * A bit array with regards to this function always has the leftmost bit in byte + * 0, i.e. bit index is the leftmost bit of byte 0. Endianness does not matter. + * + * Thanks to + * http://stackoverflow.com/questions/3534535/whats-a-time-efficient-algorithm-to-copy-unaligned-bit-arrays + * for the implementation of the algorithm. + * + * source_origin - the source array. + * source_length - the total length of the source array in bytes, + * for range checking. + * source_offset - an offset in bits to start the copy from the source array. + * Specify 0 to start from source_origin. + * bit_count - the number of bits to copy. + * destination_origin - the destination array. + * desitnation_length - the total length of the destination array in bytes, + * for range checking. + * destination_offset - an offset in bits to start placing the copied range into + * the destination array. Specify 0 to start from the beginning of the + * destination. If you are copying a range not aligned on a byte, you + * probably want to set this to a positive offset to right the resulting + * bits in the destination. + * + * Returns true if the copy was successful and false if the range exceeded the + * size of the source or destination, or if the range size negative or 0. + */ +bool copyBits(const uint8_t* source_origin, const uint16_t source_length, + const uint16_t source_offset, uint16_t bit_count, + uint8_t* destination_origin, const uint16_t destination_length, + const uint16_t destination_offset); + +bool copyBitsRightAligned(const uint8_t source[], const uint16_t source_length, + const uint16_t offset, const uint16_t bit_count, + uint8_t* destination, const uint16_t destination_length); -void getBits(const uint16_t start_index, const uint16_t field_size, - const uint8_t data[], const uint8_t length, Endianness endianness, - uint8_t* result); +// TODO using uint64_t everywhere for CAN message payload is kind of cute, but +// in actuality a CAN message may have a smaller payload, and it makes all of +// these functions not applicable to other data sizes. It's also fairly +// inefficient on 32-bit platforms. how much work is it to switch vi-firmware +// to using uint8_t*? /* Public: Reads a subset of bits from a byte array. * @@ -55,7 +92,8 @@ void getBits(const uint16_t start_index, const uint16_t field_size, * * Returns the value of the requested bit field. */ -uint64_t getBitField(uint64_t data, const uint16_t startPos, const uint16_t numBits, bool bigEndian); +uint64_t getBitField(uint64_t data, const uint16_t startPos, + const uint16_t numBits, bool bigEndian); /* Public: Set the bit field in the given data array to the new value. * @@ -63,7 +101,8 @@ uint64_t getBitField(uint64_t data, const uint16_t startPos, const uint16_t numB * value - the value to set in the bit field. * startPos - the starting index of the bit field (beginning from 0). */ -void setBitField(uint64_t* data, uint64_t value, int startPos, int numBits); +void setBitField(uint64_t* data, uint64_t value, const uint16_t startPos, + const uint16_t numBits); /* Public: Retreive the nth byte out of 8 bytes in a uint64_t. * @@ -72,7 +111,7 @@ void setBitField(uint64_t* data, uint64_t value, int startPos, int numBits); * * Returns the requested byte from the source bytes. */ -uint8_t nthByte(uint64_t source, int byteNum); +uint8_t nthByte(const uint64_t source, const uint16_t byteNum); #ifdef __cplusplus } -- cgit 1.2.3-korg