Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions src/flex_decoder_biw.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ bool process_biw(uint32_t biw_raw, flex_frame_t* frame)
#ifdef DEBUG_BIW
debug_printf("Raw BIW: 0x%x, reversed: 0x%x\n", biw_raw, reverse_bits_32(biw_raw));
#endif
flex_val_result_t result = validateWord(&biw_raw, (TASK_VALIDATE_CHECKSUM | TASK_REPAIR_2));
flex_val_result_t result = validateWord(&biw_raw, TASK_VALIDATE_AND_REPAIR_2);
switch(result)
{
case VALIDATE_REPAIRED_1:
Expand Down Expand Up @@ -76,19 +76,19 @@ void parse_for_additional_biws(flex_frame_t* frame)
switch(frame->biw.eob_info)
{
case 3:
if(validateWord(&(frame->blocks[0].word[3]), TASK_REPAIR_2 | TASK_VALIDATE_CHECKSUM))
if(validateWord(&(frame->blocks[0].word[3]), TASK_VALIDATE_AND_REPAIR_2))
{
process_biw_extra(frame->blocks[0].word[3]);
}
/* fall through */
case 2:
if(validateWord(&(frame->blocks[0].word[2]), TASK_REPAIR_2 | TASK_VALIDATE_CHECKSUM))
if(validateWord(&(frame->blocks[0].word[2]), TASK_VALIDATE_AND_REPAIR_2))
{
process_biw_extra(frame->blocks[0].word[2]);
}
/* fall through */
case 1:
if(validateWord(&(frame->blocks[0].word[1]), TASK_REPAIR_2 | TASK_VALIDATE_CHECKSUM))
if(validateWord(&(frame->blocks[0].word[1]), TASK_VALIDATE_AND_REPAIR_2))
{
process_biw_extra(frame->blocks[0].word[1]);
}
Expand All @@ -106,40 +106,49 @@ void process_biw_extra(uint32_t biw_raw)
{
uint32_t type = (biw_raw) >> 20;
type = REVERSE_BITS_8((uint8_t)type) & 0x7;
uint8_t month, day, seconds, minutes, hour;
uint16_t year;

switch(type)
{
// local id
case 0x0:
#ifdef DEBUG
biw_raw >>= 17;
debug_printf("LOCAL ID SET: TIMEZONE=0x%x\n",
(uint8_t)REVERSE_BITS_8((uint8_t)biw_raw) & 0x1F);
debug_printf("WARNING: TIME NOT BEING HANDLED!\n");
#endif
break;
// MDY
case 0x1:
#ifdef DEBUG
{
biw_raw >>= 7;
month = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x0F;
uint8_t month = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x0F;
biw_raw >>= 5;
day = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x1F;
uint8_t day = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x1F;
biw_raw >>= 5;
year = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x1F;
uint16_t year = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x1F;
debug_printf("DATE SET: MONTH=%d, DAY=%d, YEAR=%d\n", month, day, year);
debug_printf("WARNING: TIME NOT BEING HANDLED!\n");
}
#endif
break;
// HMS
case 0x2:
#ifdef DEBUG
{
biw_raw >>= 6;
seconds = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x07;
uint8_t seconds = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x07;
seconds = (seconds * 7) + (seconds >> 1);
biw_raw >>= 6;
minutes = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x3F;
uint8_t minutes = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x3F;
biw_raw >>= 5;
hour = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x1F;
uint8_t hour = REVERSE_BITS_8((uint8_t)(biw_raw)) & 0x1F;
debug_printf("TIME SET: HOUR=%d, MIN=%d, SEC=%d\n", hour, minutes, seconds);
debug_printf("WARNING: TIME NOT BEING HANDLED!\n");
}
#endif
/* fall through */
// Spare / offset
case 0x3:
debug_printf("SPARE/OFFSET SET\n");
Expand Down
12 changes: 6 additions & 6 deletions src/flex_decoder_vectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ bool isAddressLong(uint32_t address_decoded)

uint32_t decodeAddress(flex_frame_t* frame, uint8_t addr_pos)
{
validateWord(getWord(frame, addr_pos), TASK_REPAIR_1 | TASK_REPAIR_2);
validateWord(getWord(frame, addr_pos + 1), TASK_REPAIR_1 | TASK_REPAIR_2);
validateWord(getWord(frame, addr_pos), TASK_REPAIR_BOTH);
validateWord(getWord(frame, addr_pos + 1), TASK_REPAIR_BOTH);

bool long_address = checkForLongAddress(frame, addr_pos);
uint32_t address = reverse_bits_32(*getWord(frame, addr_pos));
Expand Down Expand Up @@ -115,7 +115,7 @@ flex_vector_t decodeVector(flex_frame_t* frame, uint32_t vector_start, uint32_t
flex_vector_t vec;

if(VALIDATE_FAIL ==
validateWord(getWord(frame, vector_start), TASK_VALIDATE_CHECKSUM | TASK_REPAIR_2))
validateWord(getWord(frame, vector_start), TASK_VALIDATE_AND_REPAIR_2))
{
debug_printf("Irreparable vector discarded: %d, value: 0x%x\n", vector_start,
*getWord(frame, vector_start));
Expand Down Expand Up @@ -170,7 +170,7 @@ flex_vector_t decodeVector(flex_frame_t* frame, uint32_t vector_start, uint32_t

flex_alpha_msg_header_t decode_alpha_header(uint32_t first_word, uint32_t second_word)
{
flex_alpha_msg_header_t hdr;
flex_alpha_msg_header_t hdr = {0};

hdr.word = first_word;
hdr.fragmentcheck = REVERSE_BITS_8((uint8_t)(first_word >> 24)); // Reverse k0..k7
Expand Down Expand Up @@ -272,7 +272,7 @@ void decode_numeric_msg(flex_frame_t* frame, flex_vector_t* vec, uint8_t vec_ind
unsigned count = 4;
unsigned start_offset = 0;
unsigned bits_in_curr_word = 21;
unsigned char digit;
unsigned char digit = 0;

assert(frame && vec && msg);

Expand Down Expand Up @@ -461,7 +461,7 @@ void decode_binary_msg(flex_frame_t* frame, flex_vector_t* vec, uint8_t vec_inde
unsigned __attribute__((unused)) bits_per_symbol = 1;
unsigned __attribute__((unused)) signature;
unsigned count = 8;
unsigned char byte;
unsigned char byte = 0;

assert(frame && vec && msg);

Expand Down
5 changes: 5 additions & 0 deletions src/flex_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,14 @@ typedef enum

typedef enum
{
TASK_NONE = 0,
TASK_VALIDATE_CHECKSUM = (1 << 0),
TASK_REPAIR_1 = (1 << 1),
TASK_REPAIR_2 = (1 << 2),
/// Combined: validate BCH and attempt two-bit repair
TASK_VALIDATE_AND_REPAIR_2 = (TASK_VALIDATE_CHECKSUM | TASK_REPAIR_2),
/// Combined: attempt both one-bit and two-bit repair
TASK_REPAIR_BOTH = (TASK_REPAIR_1 | TASK_REPAIR_2),
} flex_val_task_t;

typedef enum
Expand Down
166 changes: 166 additions & 0 deletions test/bits_tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright © 2019 Embedded Artistry LLC.
* License: MIT. See LICENSE file for details.
*/

#include "flex_decoder.h"
#include "tests.h"

/* Tests for reverse_bits_32() */

static void test_reverse_bits_32_zero(void** state)
{
assert_int_equal(reverse_bits_32(0x00000000), 0x00000000);
}

static void test_reverse_bits_32_all_ones(void** state)
{
assert_int_equal(reverse_bits_32(0xFFFFFFFF), 0xFFFFFFFF);
}

static void test_reverse_bits_32_single_high_bit(void** state)
{
/* 0x80000000 = 1000...0000, reversed = 0000...0001 */
assert_int_equal(reverse_bits_32(0x80000000), 0x00000001);
}

static void test_reverse_bits_32_single_low_bit(void** state)
{
/* 0x00000001 = 0000...0001, reversed = 1000...0000 */
assert_int_equal(reverse_bits_32(0x00000001), 0x80000000);
}

static void test_reverse_bits_32_byte_pattern(void** state)
{
/*
* The function reverses all 32 bits (byte-swap + in-byte reversal).
* 0xAB = 1010 1011, reversed = 1101 0101 = 0xD5
* reverse_bits_32(0xAB000000) => 0x000000D5
*/
assert_int_equal(reverse_bits_32(0xAB000000), 0x000000D5);
}

static void test_reverse_bits_32_known_word(void** state)
{
/*
* reverse_bits_32(0x12345678):
* bytes: 0x78, 0x56, 0x34, 0x12
* 0x78 = 0111 1000 -> 0001 1110 = 0x1E
* 0x56 = 0101 0110 -> 0110 1010 = 0x6A
* 0x34 = 0011 0100 -> 0010 1100 = 0x2C
* 0x12 = 0001 0010 -> 0100 1000 = 0x48
* result: q[3]=0x1E, q[2]=0x6A, q[1]=0x2C, q[0]=0x48 => 0x1E6A2C48
*/
assert_int_equal(reverse_bits_32(0x12345678), 0x1E6A2C48);
}

static void test_reverse_bits_32_roundtrip(void** state)
{
/* Double-reversing should recover the original value */
uint32_t value = 0xDEADBEEF;
assert_int_equal(reverse_bits_32(reverse_bits_32(value)), value);
}

static void test_reverse_bits_32_alternating(void** state)
{
/*
* 0xAAAAAAAA = 1010 1010 ... repeated
* Reversed: 0101 0101 ... = 0x55555555
*/
assert_int_equal(reverse_bits_32(0xAAAAAAAA), 0x55555555);
assert_int_equal(reverse_bits_32(0x55555555), 0xAAAAAAAA);
}

/* Tests for count_set_bits() */

static void test_count_set_bits_zero(void** state)
{
assert_int_equal(count_set_bits(0x00000000), 0);
}

static void test_count_set_bits_all_ones(void** state)
{
assert_int_equal(count_set_bits(0xFFFFFFFF), 32);
}

static void test_count_set_bits_boundary_values(void** state)
{
/* Single bits at low and high ends */
assert_int_equal(count_set_bits(0x00000001), 1);
assert_int_equal(count_set_bits(0x80000000), 1);
/* Nibbles at low and high ends */
assert_int_equal(count_set_bits(0x0000000F), 4);
assert_int_equal(count_set_bits(0xF0000000), 4);
}

static void test_count_set_bits_byte(void** state)
{
assert_int_equal(count_set_bits(0x000000FF), 8);
}

static void test_count_set_bits_alternating(void** state)
{
/* 0xAAAAAAAA = 1010...1010 = 16 bits set */
assert_int_equal(count_set_bits(0xAAAAAAAA), 16);
/* 0x55555555 = 0101...0101 = 16 bits set */
assert_int_equal(count_set_bits(0x55555555), 16);
}

static void test_count_set_bits_known(void** state)
{
/* 0x12345678: count individual bytes
* 0x78 = 0111 1000 = 4 bits
* 0x56 = 0101 0110 = 4 bits
* 0x34 = 0011 0100 = 3 bits
* 0x12 = 0001 0010 = 2 bits
* total = 13 bits
*/
assert_int_equal(count_set_bits(0x12345678), 13);
}

/* Tests for REVERSE_BITS_8 macro */

static void test_reverse_bits_8_macro(void** state)
{
/*
* REVERSE_BITS_8 uses a 64-bit intermediate, so mask to 8 bits to isolate
* the reversed byte.
*/
/* 0x01 = 0000 0001 -> 1000 0000 = 0x80 */
assert_int_equal(REVERSE_BITS_8(0x01) & 0xFF, 0x80);
/* 0x80 = 1000 0000 -> 0000 0001 = 0x01 */
assert_int_equal(REVERSE_BITS_8(0x80) & 0xFF, 0x01);
/* 0x0F = 0000 1111 -> 1111 0000 = 0xF0 */
assert_int_equal(REVERSE_BITS_8(0x0F) & 0xFF, 0xF0);
/* 0xFF = 1111 1111 -> 1111 1111 = 0xFF */
assert_int_equal(REVERSE_BITS_8(0xFF) & 0xFF, 0xFF);
/* 0x00 = 0000 0000 -> 0000 0000 = 0x00 */
assert_int_equal(REVERSE_BITS_8(0x00) & 0xFF, 0x00);
/* 0xAB = 1010 1011 -> 1101 0101 = 0xD5 */
assert_int_equal(REVERSE_BITS_8(0xAB) & 0xFF, 0xD5);
}

#pragma mark - Public Functions -

int bits_tests(void)
{
const struct CMUnitTest bits_test_list[] = {
cmocka_unit_test(test_reverse_bits_32_zero),
cmocka_unit_test(test_reverse_bits_32_all_ones),
cmocka_unit_test(test_reverse_bits_32_single_high_bit),
cmocka_unit_test(test_reverse_bits_32_single_low_bit),
cmocka_unit_test(test_reverse_bits_32_byte_pattern),
cmocka_unit_test(test_reverse_bits_32_known_word),
cmocka_unit_test(test_reverse_bits_32_roundtrip),
cmocka_unit_test(test_reverse_bits_32_alternating),
cmocka_unit_test(test_count_set_bits_zero),
cmocka_unit_test(test_count_set_bits_all_ones),
cmocka_unit_test(test_count_set_bits_boundary_values),
cmocka_unit_test(test_count_set_bits_byte),
cmocka_unit_test(test_count_set_bits_alternating),
cmocka_unit_test(test_count_set_bits_known),
cmocka_unit_test(test_reverse_bits_8_macro),
};

return cmocka_run_group_tests(bits_test_list, NULL, NULL);
}
Loading