/* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file src/test_dur.c * \brief HAL PHY duration functions test. * \ingroup test */ #include "common/std.h" #include "hal/phy/maximus/dur/inc/maximus_dur.h" #include "mac/common/timings.h" #include "lib/test.h" /** * Count the number of one bits in a sequence, see below. * \param m number of number in sequence * \return number of one bits * * How many one bits is there in a given sequence: 0, 1, 2... (2^n)-1? * * Each bits was half of the time 0 and half of the time 1, therefore, * the answer is n * 2^n / 2. * * How to generalise for any 0 to m-1 sequence? * * Decompose the sequence into sequences of decreasing power of 2 * length, do not forget the extra one MSB bits for each sequence * except the first one. * * For example, the number of one bits in the sequence 0, 1, 2... 127, * 128... 191, 192... 199 is * * 7 * 2^7 / 2 + 6 * 2^6 / 2 + 1 * 2^6 + 3 * 2^3 / 2 + 2 * 2^3 * -----1----- -----2----- ---2'-- -----3----- ---3'-- * * 1: the first 0 to 127 sequence, * 2: the second 128 to 191 sequence, * 2': do not forget second sequence msb bits, * 3: the third 192 to 199 sequence, * 3': do not forget third sequence msb bits. */ static uint bits_in_sequence (uint m) { int i; u32 btest; uint msb; uint ones; dbg_assert (m < (1 << 16)); msb = 0; ones = 0; for (i = 15, btest = 1 << 15; i >= 0; i--, btest >>= 1) { if (m & btest) { ones += msb * btest; ones += i * btest / 2; msb++; } } return ones; } static const uint default_tonemask_carriers[] = { /* 0-70 are OFF AM broadcast band and lower */ /* 71-73 are OFF Between AM and 160-meter band */ 85, /* 74-85 are OFF 160 meter amateur band */ 139, /* 86-139 are ON HomePlug carriers */ 167, /* 140-167 are OFF 80 meter amateur band */ 214, /* 168-214 are ON HomePlug carriers */ 225, /* 215-225 are OFF 5 MHz amateur band */ 282, /* 226-282 are ON HomePlug Carriers */ 302, /* 283-302 are OFF 40 meter amateur band */ 409, /* 303-409 are ON HomePlug carriers */ 419, /* 410-419 are OFF 30 meter amateur band */ 569, /* 420-569 are ON HomePlug carriers */ 591, /* 570-591 are OFF 20 meter amateur band */ 736, /* 592-736 are ON HomePlug carriers */ 748, /* 737-748 are OFF 17 meter amateur band */ 856, /* 749-856 are ON HomePlug carriers */ 882, /* 857-882 are OFF 15 meter amateur band */ 1015, /* 883-1015 are ON HomePlug Carriers */ 1027, /* 1016-1027 are OFF 12 meter amateur band */ 1143, /* 1028-1143 are ON HomePlug Carriers */ 1535, /* 1144-1535 are OFF 10 meter amateur band */ }; const uint default_tonemask_carrier_nb = 917; static void default_tonemask (u8 *tonemask) { uint i, j; uint dtc_idx = 0; dbg_assert (default_tonemask_carriers[0] > PHY_CARRIER_OFFSET); uint dtc_stop = default_tonemask_carriers[dtc_idx] - PHY_CARRIER_OFFSET; bool dtc_on = false; for (i = 0; i < PHY_TONEMASK_SIZE; i++) { tonemask[i] = 0; for (j = 0; j < 8; j++) { if (i * 8 + j > dtc_stop) { dtc_on = !dtc_on; dtc_stop = default_tonemask_carriers[++dtc_idx] - PHY_CARRIER_OFFSET; } if (dtc_on) tonemask[i] |= 1 << j; } } } static void dur_basic_test_case (test_t t) { uint i, j; u8 tonemask[PHY_TONEMASK_SIZE]; u8 tonemap[PHY_TONEMAP_SIZE]; blk_t tonemap_desc, tonemap_desc2; test_case_begin (t, "basic"); /* Initialise block descriptors. */ tonemap_desc.next = &tonemap_desc2; tonemap_desc.data = tonemap; dbg_invalid_ptr (tonemap_desc2.next); tonemap_desc2.data = tonemap + BLK_SIZE; test_begin (t, "bits_in_sequence") { /* Need a different way of counting to test anything... */ test_fail_unless (bits_in_sequence (200) == 732); } test_end; test_begin (t, "carrier_nb") { uint bits_ref, bits; /* Generated tone masks. */ for (i = 0; i < 256 - PHY_CARRIER_NB / 8; i++) { bits_ref = bits_in_sequence (i + PHY_CARRIER_NB / 8) - bits_in_sequence (i) + PHY_CARRIER_NB % 8; for (j = 0; j < PHY_CARRIER_NB / 8; j++) tonemask[j] = i + j; if (PHY_CARRIER_NB % 8) tonemask[j] = (1 << (PHY_CARRIER_NB % 8)) - 1; bits = maximus_dur_carrier_nb (tonemask); test_fail_unless (bits == bits_ref, "mismatch for %d: %d != %d", i, bits, bits_ref); } /* Default tone mask. */ bits_ref = default_tonemask_carrier_nb; default_tonemask (tonemask); bits = maximus_dur_carrier_nb (tonemask); test_fail_unless (bits == bits_ref, "mismatch for default: %d != %d", bits, bits_ref); } test_end; test_begin (t, "robo bits_per_symbol") { test_fail_unless (maximus_dur_bits_per_symbol ( PHY_MOD_ROBO, tonemask, NULL, 400) == 200); test_fail_unless (maximus_dur_bits_per_symbol ( PHY_MOD_ROBO, tonemask, NULL, 403) == 200); test_fail_unless (maximus_dur_bits_per_symbol ( PHY_MOD_HS_ROBO, tonemask, NULL, 400) == 400); test_fail_unless (maximus_dur_bits_per_symbol ( PHY_MOD_HS_ROBO, tonemask, NULL, 401) == 400); test_fail_unless (maximus_dur_bits_per_symbol ( PHY_MOD_MINI_ROBO, tonemask, NULL, 300) == 120); } test_end; test_begin (t, "tm bits_per_symbol") { /* Mix of modulations. * 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2... */ uint mod = 0; uint bits, bits_ref; default_tonemask (tonemask); for (i = 0; i < PHY_TONEMAP_SIZE; i++) tonemap[i] = 0; for (i = 0; i < PHY_TONEMASK_SIZE; i++) { for (j = 0; j < 8; j++) { if (tonemask[i] & (1 << j)) tonemap[i * 4 + j / 2] |= (mod++ % 8) << (4 * (j % 2)); } } dbg_assert (mod == default_tonemask_carrier_nb); dbg_assert (default_tonemask_carrier_nb % 8 == 5); bits_ref = default_tonemask_carrier_nb / 8 * (0 + 1 + 2 + 3 + 4 + 6 + 8 + 10) + (0 + 1 + 2 + 3 + 4); bits = maximus_dur_bits_per_symbol (PHY_MOD_TM, tonemask, &tonemap_desc, default_tonemask_carrier_nb); test_fail_unless (bits == bits_ref, "mismatch for mix: %d != %d", bits, bits_ref); /* Maximum modulations. */ for (i = 0; i < PHY_CARRIER_NB / 2; i++) tonemap[i] = 0x77; if (PHY_CARRIER_NB % 2) tonemap[i] = 0x07; bits_ref = default_tonemask_carrier_nb * 10; bits = maximus_dur_bits_per_symbol (PHY_MOD_TM, tonemask, &tonemap_desc, default_tonemask_carrier_nb); test_fail_unless (bits == bits_ref, "mismatch for max: %d != %d", bits, bits_ref); } test_end; test_begin (t, "symbol_nb") { test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_136, 136 * 8 * 2, 1) == 1); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_136, 136 * 8 / 16 * 21, 1) == 1); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_520, 520 * 8 * 2, 1) == 1); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_520, 520 * 8 / 16 * 21, 1) == 1); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_136, 136 * 2, 1) == 8); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_136, 136 / 16 * 21, 1) == 9); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_520, 520 * 2, 1) == 8); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_520, 520 / 16 * 21, 1) == 9); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_520, 520 * 8 * 2, 10) == 10); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_520, 520 * 8 / 16 * 21, 10) == 10); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_520, 2 * 520 * 8 * 2, 10) == 5); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_520, 2 * 520 * 8 / 16 * 21, 10) == 5); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_1_2, PHY_PB_SIZE_520, 2 * 520 * 8 * 2 - 10, 10) == 6); test_fail_unless ( maximus_dur_symbol_nb (PHY_FEC_RATE_16_21, PHY_PB_SIZE_520, 2 * 520 * 8 / 16 * 21 - 10, 10) == 6); } test_end; test_begin (t, "data_tck") { test_fail_unless (maximus_dur_data_tck (PHY_GIL_417, 1) == MAC_DX567_TCK); test_fail_unless (maximus_dur_data_tck (PHY_GIL_567, 1) == MAC_DX567_TCK); test_fail_unless (maximus_dur_data_tck (PHY_GIL_3534, 1) == MAC_DX567_TCK); test_fail_unless (maximus_dur_data_tck (PHY_GIL_417, 2) == MAC_DX567_TCK * 2); test_fail_unless (maximus_dur_data_tck (PHY_GIL_567, 2) == MAC_DX567_TCK * 2); test_fail_unless (maximus_dur_data_tck (PHY_GIL_3534, 2) == MAC_DX567_TCK * 2); test_fail_unless (maximus_dur_data_tck (PHY_GIL_417, 3) == MAC_DX567_TCK * 2 + MAC_DX417_TCK); test_fail_unless (maximus_dur_data_tck (PHY_GIL_567, 3) == MAC_DX567_TCK * 2 + MAC_DX567_TCK); test_fail_unless (maximus_dur_data_tck (PHY_GIL_3534, 3) == MAC_DX567_TCK * 2 + MAC_DX3534_TCK); test_fail_unless (maximus_dur_data_tck (PHY_GIL_417, 4) == MAC_DX567_TCK * 2 + MAC_DX417_TCK * 2); test_fail_unless (maximus_dur_data_tck (PHY_GIL_567, 4) == MAC_DX567_TCK * 2 + MAC_DX567_TCK * 2); test_fail_unless (maximus_dur_data_tck (PHY_GIL_3534, 4) == MAC_DX567_TCK * 2 + MAC_DX3534_TCK * 2); } test_end; } void dur_test_suite (test_t t) { test_suite_begin (t, "dur"); dur_basic_test_case (t); } int main (int argc, char **argv) { test_t t; test_init (t, argc, argv); dur_test_suite (t); test_result (t); return test_nb_failed (t) == 0 ? 0 : 1; }