summaryrefslogtreecommitdiffstats
path: root/src/bitfield/bitfield.h
diff options
context:
space:
mode:
authorChristopher Peplin <chris.peplin@rhubarbtech.com>2013-12-29 11:34:10 -0500
committerChristopher Peplin <chris.peplin@rhubarbtech.com>2013-12-29 11:34:10 -0500
commit6830d35b449141305f137f78f09c2b879bfb9b33 (patch)
tree3674285c457282211f612daa2cbd27d331f81475 /src/bitfield/bitfield.h
parent20bb0f507694482d7e0c6a381e3025544aa9cb5a (diff)
Clean up bitfield API a bit.
Diffstat (limited to 'src/bitfield/bitfield.h')
-rw-r--r--src/bitfield/bitfield.h65
1 files changed, 52 insertions, 13 deletions
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
}