/* Cesar project {{{ * * Copyright (C) 2009 Spidcom * * <<>> * * }}} */ /** * \file ce/rx/bitloading/test/src/test_intervals.c * \brief Test CE RX BL intervals module. * \ingroup test */ #include "common/std.h" #include "lib/test.h" #include "lib/utils.h" #include "mac/common/interval.h" #include "mac/common/timings.h" #include "bsu/aclf/aclf.h" #include "ce/rx/bitloading/intervals.h" #include "ce/rx/bitloading/inc/intervals.h" #include "ce_rx_bl_fsm_defs.h" #include "mac/common/timings.h" #include "ce/rx/bitloading/fsm/fsm.h" /* Global CE/RX behavior stub. */ ce_rx_behavior_t ce_rx_behavior = CE_RX_BEHAVIOR_INTERVALS_ENABLE; /** * Test suite for intervals init and uninit. */ void test_suite_ce_rx_bl_intervals_init (test_t t) { test_case_begin (t, "Intervals init/uninit"); test_begin (t, "Intervals alloc") { ce_rx_bitloading_intervals_t *its = NULL; its = ce_rx_bl_intervals_alloc (42); test_fail_if (its == NULL); ce_rx_bl_intervals_free (its); } test_end; test_begin (t, "Intervals bit-loading init.") { ce_rx_bitloading_intervals_t *its = ce_rx_bl_intervals_alloc (42); int i; for (i = 0; i < ce_rx_bl_intervals_fsm_count_; i++) { ce_rx_bitloading_t *b = (ce_rx_bitloading_t *) blk_table_get (its->blk_table, i); test_fail_unless (b == its->intervals[i]); test_fail_unless (its->intervals[i]->fsm == CE_RX_BL_FSM_STATE_INTERVAL_TRACKING); test_fail_unless (its->tmi[i] == 42); } ce_rx_bl_intervals_free (its); } test_end; test_begin (t, "Initial FSM state of intervals is correct.") { test_fail_unless (CE_RX_BL_FSM_STATE_INTERVAL_TRACKING_COPY == CE_RX_BL_FSM_STATE_INTERVAL_TRACKING); } test_end; } void test_suite_ce_rx_bl_intervals_get_tmi_used_list (test_t t) { uint old_fsm_nb = ce_rx_bl_intervals_fsm_count_; uint old_repetition_nb = ce_rx_bl_intervals_repetition_count_; /* This tests only works if the number of intervals is known, so I prefer * to manage this locally. */ ce_rx_bl_intervals_fsm_count_ = 6; ce_rx_bl_intervals_repetition_count_ = 4; sta_t sta; sta.rx_tonemaps = tonemaps_alloc (); sta.intervals = ce_rx_bl_intervals_alloc (TONEMAP_INDEX_NEGOTIATED_FIRST); test_case_begin (t, "Get tonemaps used list"); test_begin (t, "Including default one.") { sta.rx_tonemaps->default_tmi = TONEMAP_INDEX_INITIAL_START; test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, true) != 0x00000010); sta.rx_tonemaps->default_tmi = 0; test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, true) != 0x00000011); sta.rx_tonemaps->default_tmi = 18; test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, true) != 0x00040010); sta.intervals->tmi[0] = 5; sta.intervals->tmi[2] = 31; test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, true) != 0x80040030); sta.intervals->tmi[2] = 29; test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, true) != 0x20040030); sta.intervals->tmi[4] = TONEMAP_INDEX_INTERVAL_UNAVAILABLE; test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, true) != 0x20040030); } test_end; test_begin (t, "Excluding default one.") { test_fail_if (ce_rx_bl_intervals_get_tmi_used_list (&sta, false) != 0x20000030); } test_end; /* Clean. */ tonemaps_release (sta.rx_tonemaps); ce_rx_bl_intervals_free (sta.intervals); ce_rx_bl_intervals_fsm_count_ = old_fsm_nb; ce_rx_bl_intervals_repetition_count_ = old_repetition_nb; } /** * Time transformation from pbproc information to ATU. */ void test_suite_ce_rx_bl_intervals_measure_to_date (test_t t) { test_case_begin (t, "Time transformation from pbproc timing to ATU"); s16 start = 0, end = 0; pbproc_rx_params_t rxp; test_begin (t, "Classic value") { rxp.preamble_ntb = 2000000; rxp.beacon_period_start_ntb = 1000000; rxp.fl_tck = 1000; ce_rx_bl_intervals_measure_to_date (&rxp, &start, &end); s16 computed_start = MAC_TCK_TO_ATU ( ((MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK) + (MAC_PREAMBLE_TCK + MAC_FC_AV_TCK)) / 2 + 1000000); test_fail_unless (computed_start == start); test_fail_unless (end == start + (s16) MAC_TCK_TO_ATU (rxp.fl_tck)); } test_end; test_begin (t, "Beacon period start after preamble") { rxp.preamble_ntb = 1000; rxp.beacon_period_start_ntb = 2000; rxp.fl_tck = 1000; ce_rx_bl_intervals_measure_to_date (&rxp, &start, &end); s16 computed_start = MAC_TCK_TO_ATU ( ((MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK) + (MAC_PREAMBLE_TCK + MAC_FC_AV_TCK)) / 2 + (s32) (1000 - 2000)); test_fail_unless (computed_start == start); test_fail_unless (end == start + (s16) MAC_TCK_TO_ATU (rxp.fl_tck)); } test_end; test_begin (t, "Overflowed counter value") { rxp.preamble_ntb = 1; rxp.beacon_period_start_ntb = 0xfffff000; rxp.fl_tck = 1000; ce_rx_bl_intervals_measure_to_date (&rxp, &start, &end); s16 computed_start = MAC_TCK_TO_ATU ( ((MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK) + (MAC_PREAMBLE_TCK + MAC_FC_AV_TCK)) / 2 + (s32) (1 - 0xfffff000)); test_fail_unless (computed_start == start); test_fail_unless (end == start + (s16) MAC_TCK_TO_ATU (rxp.fl_tck)); } test_end; } /* * Test suite for measure to interval computation. */ void test_suite_ce_rx_bl_intervals_measure_to_interval (test_t t) { test_case_begin (t, "Measure to interval"); test_begin (t, "Global measure") { tonemaps_t *tms = tonemaps_alloc (); int int_nb = 0; uint bp = MAC_TCK_TO_ATU (BSU_ACLF_BP_50HZ_TCK); int end_offset_atu = 0; do { end_offset_atu = ++int_nb * bp / 24; int_nb = mac_interval_append (tms, end_offset_atu, 51); } while (int_nb != 24); mac_interval_commit_changes (tms, 0); int i = ce_rx_bl_intervals_measure_to_interval (tms, bp / 4, bp / 2); test_fail_if (i != -1); tonemaps_release (tms); } test_end; test_begin (t, "Global measure no existing interval") { tonemaps_t *tms = tonemaps_alloc (); uint bp = MAC_TCK_TO_ATU (BSU_ACLF_BP_50HZ_TCK); /* No interval so the measure should be global. */ int i = ce_rx_bl_intervals_measure_to_interval (tms, 0, bp / 48); test_fail_if (i != -1); tonemaps_release (tms); } test_end; test_begin (t, "Measure position shift ok") { tonemaps_t *tms = tonemaps_alloc (); int int_nb = 0; uint bp = MAC_TCK_TO_ATU (BSU_ACLF_BP_50HZ_TCK); int end_offset_atu = 0; do { end_offset_atu = ++int_nb * bp / 24; int_nb = mac_interval_append (tms, end_offset_atu, 51); } while (int_nb != 24); mac_interval_commit_changes (tms, 0); int a; for (a = 0; a < 24; a++) { int i = ce_rx_bl_intervals_measure_to_interval ( tms, a == 0 ? 0 : a * bp / 24 - MAC_TCK_TO_ATU (MAC_TM_TOLERANCE_TCK), (a + 1) * bp / 24 + MAC_TCK_TO_ATU (MAC_TM_TOLERANCE_TCK) - 1); test_fail_if (i != a); } tonemaps_release (tms); } test_end; test_begin (t, "Measure position shift fail start") { tonemaps_t *tms = tonemaps_alloc (); int int_nb = 0; uint bp = MAC_TCK_TO_ATU (BSU_ACLF_BP_50HZ_TCK); int end_offset_atu = 0; do { end_offset_atu = ++int_nb * bp / 24; int_nb = mac_interval_append (tms, end_offset_atu, 51); } while (int_nb != 24); mac_interval_commit_changes (tms, 0); int i = ce_rx_bl_intervals_measure_to_interval ( tms, bp / 24 - MAC_TCK_TO_ATU (MAC_TM_TOLERANCE_TCK) - 1, 2 * bp / 24 + MAC_TCK_TO_ATU (MAC_TM_TOLERANCE_TCK) - 1); test_fail_if (i != -1); tonemaps_release (tms); } test_end; test_begin (t, "Measure position shift fail end") { tonemaps_t *tms = tonemaps_alloc (); int int_nb = 0; uint bp = MAC_TCK_TO_ATU (BSU_ACLF_BP_50HZ_TCK); int end_offset_atu = 0; do { end_offset_atu = ++int_nb * bp / 24; int_nb = mac_interval_append (tms, end_offset_atu, 51); } while (int_nb != 24); mac_interval_commit_changes (tms, 0); int i = ce_rx_bl_intervals_measure_to_interval ( tms, bp / 24 - MAC_TCK_TO_ATU (MAC_TM_TOLERANCE_TCK), 2 * bp / 24 + MAC_TCK_TO_ATU (MAC_TM_TOLERANCE_TCK)); test_fail_if (i != -1); tonemaps_release (tms); } test_end; } void test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( test_t t, int sound, bool intervals, bool mea_interval, bool src_interval, ce_rx_bl_fsm_event_type_t *event, int *fsm_id) { sta_t sta; tonemaps_t* tms; ce_rx_measure_mbox_t measure; ce_rx_bitloading_fsm_event_param_t data; int i; uint bp_tck, bp_atu; ce_rx_bitloading_init (&sta.ce_rx_bt); tms = tonemaps_alloc (); bp_tck = BSU_ACLF_BP_50HZ_TCK; bp_atu = MAC_TCK_TO_ATU (bp_tck); if (intervals) { for (i = 1; i <= 24; i++) mac_interval_append (tms, bp_atu * i / 24, i); mac_interval_commit_changes (tms, ce_rx_bl_intervals_fsm_count_); } sta.rx_tonemaps = tms; sta.intervals = NULL; data.measure = &measure; /* Configure measure. */ measure.rx_params.sound = sound; measure.rx_params.sound_complete = 0; if (src_interval) measure.rx_params.sound_src = TONEMAP_SRC_INTERVAL_UNAVAILABLE; else measure.rx_params.sound_src = TONEMAP_SRC_INITIAL; measure.rx_params.preamble_ntb = 0; measure.rx_params.beacon_period_start_ntb = 0; /* Measure is global. */ if (!mea_interval) measure.rx_params.fl_tck = bp_tck; /* Measure is located on an interval */ else measure.rx_params.fl_tck = bp_tck / 25; *event = ce_rx_bl_fsm_measure_to_event (&sta, data); *fsm_id = measure.fsm_id; /* Clean. */ tonemaps_release (tms); ce_rx_bitloading_uninit (&sta.ce_rx_bt); } void test_suite_ce_rx_bl_intervals_measure_to_event (test_t t) { ce_rx_bl_fsm_event_type_t out; int fsm_id; test_begin (t, "Measure to event conversion, sound, no interval, " "big measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 1, /* RX contains intervals ? */ false, /* Measure is positioned on an interval ? */ false, /* SRC is interval specific ? */ false, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_sound); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, sound, no interval, " "small measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 1, /* RX contains intervals ? */ false, /* Measure is positioned on an interval ? */ true, /* SRC is interval specific ? */ false, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_sound); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, sound, intervals, " "big measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 1, /* RX contains intervals ? */ true, /* Measure is positioned on an interval ? */ false, /* SRC is interval specific ? */ true, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_sound); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, sound, intervals, " "small measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 1, /* RX contains intervals ? */ true, /* Measure is positioned on an interval ? */ true, /* SRC is interval specific ? */ true, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_interval_sound); test_fail_if (fsm_id != 0); } test_end; test_begin (t, "Measure to event conversion, sound, intervals, " "small measure, SRC is global") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 1, /* RX contains intervals ? */ true, /* Measure is positioned on an interval ? */ true, /* SRC is interval specific ? */ false, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_sound); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, not sound, no interval, " "big measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 0, /* RX contains intervals ? */ false, /* Measure is positioned on an interval ? */ false, /* SRC is interval specific ? */ false, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_data); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, not sound, no interval, " "small measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 0, /* RX contains intervals ? */ false, /* Measure is positioned on an interval ? */ true, /* SRC is interval specific ? */ false, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_data); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, not sound, intervals, " "big measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 0, /* RX contains intervals ? */ true, /* Measure is positioned on an interval ? */ false, /* SRC is interval specific ? */ true, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_data); test_fail_if (fsm_id != -1); } test_end; test_begin (t, "Measure to event conversion, not sound, intervals, " "small measure") { test_suite_ce_rx_bl_intervals_measure_to_event_master_test ( t, /* Sound ? */ 0, /* RX contains intervals ? */ true, /* Measure is positioned on an interval ? */ true, /* SRC is interval specific ? */ true, &out, &fsm_id); test_fail_if (out != CE_RX_BL_FSM_EVENT_TYPE_interval_data); test_fail_if (fsm_id != 0); } test_end; } /* * Test suite for updating TMI of intervals. */ void test_suite_ce_rx_bl_intervals_update_tmi (test_t t) { test_case_begin (t, "Update TMI of intervals."); test_begin (t, "Check TMIs are correctly set") { int i; sta_t sta; sta_init (&sta, 42); sta.intervals = ce_rx_bl_intervals_alloc (0); for (i = 0; i < ce_rx_bl_intervals_fsm_count_; i++) sta.intervals->tmi[i] = i; ce_rx_bl_intervals_update_tmi (&sta, BSU_ACLF_BP_50HZ_TCK); tonemap_intervals_t *ints = sta.rx_tonemaps->intervals; test_fail_if (ints->intervals_nb != ce_rx_bl_intervals_fsm_count_ * ce_rx_bl_intervals_repetition_count_); for (i = 0; i < ints->intervals_nb; i++) test_fail_unless (i % ce_rx_bl_intervals_fsm_count_ == ints->interval[i].tmi); ce_rx_bl_intervals_free (sta.intervals); sta.intervals = NULL; sta_uninit (&sta); } test_end; test_begin (t, "Check end offset of intervals") { int i; uint j; sta_t sta; sta_init (&sta, 42); sta.intervals = ce_rx_bl_intervals_alloc (0); bsu_aclf_bp_t bp_th_tck[3] = {BSU_ACLF_BP_50HZ_TCK, BSU_ACLF_BP_55HZ_TCK, BSU_ACLF_BP_60HZ_TCK}; for (j = 0; j < COUNT (bp_th_tck); j++) { tonemap_intervals_t *ints = sta.rx_tonemaps->intervals; u16 bp_atu = MAC_TCK_TO_ATU (bp_th_tck[j] + HPAV_BEACON_BTO_MAX_TCK); ce_rx_bl_intervals_update_tmi (&sta, bp_th_tck[j]); for (i = 0; i < ints->intervals_nb; i++) test_fail_unless (bp_atu * (i + 1) / ints->intervals_nb == ints->interval[i].end_offset_atu); } ce_rx_bl_intervals_free (sta.intervals); sta.intervals = NULL; sta_uninit (&sta); } test_end; } void test_suite_ce_rx_bl_intervals_update_default_tm (test_t t) { test_case_begin (t, "Update global default tonemap."); uint old_fsm_nb = ce_rx_bl_intervals_fsm_count_; uint old_repetition_nb = ce_rx_bl_intervals_repetition_count_; sta_t sta; tonemap_t tm; int i; sta.rx_tonemaps = tonemaps_alloc (); sta.rx_tonemaps->tm[4] = &tm; sta.rx_tonemaps->tm[4]->released = 0; /* This tests only works if the number of intervals is known, so I prefer * to manage this locally. */ /* Start with one interval. */ ce_rx_bl_intervals_fsm_count_ = 1; ce_rx_bl_intervals_repetition_count_ = 1; sta.intervals = ce_rx_bl_intervals_alloc (4); test_begin (t, "One interval, not restarting.") { sta.rx_tonemaps->default_tmi = 0; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 4); sta.rx_tonemaps->default_tmi = 4; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 4); test_fail_if (sta.rx_tonemaps->tm[4]->released != 0); sta.intervals->tmi[0] = 5; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 5); test_fail_if (sta.rx_tonemaps->tm[4]->released != TONEMAP_RELEASE_TIMER_S); } test_end; sta.rx_tonemaps->default_tmi = 4; sta.rx_tonemaps->tm[4]->released = 0; test_begin (t, "One interval, restarting for a better tonemap.") { sta.intervals->tmi[0] = TONEMAP_SRC_INTERVAL_UNAVAILABLE; sta.intervals->intervals[0]->default_robo = false; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 4); test_fail_if (sta.rx_tonemaps->tm[4]->released != 0); } test_end; test_begin (t, "One interval, restarting for a worst tonemap.") { sta.intervals->intervals[0]->default_robo = true; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 0); test_fail_if (sta.rx_tonemaps->tm[4]->released != TONEMAP_RELEASE_TIMER_S); } test_end; /* Clean. */ sta.rx_tonemaps->tm[4]->released = 0; ce_rx_bl_intervals_free (sta.intervals); /* Now, test with several intervals. */ ce_rx_bl_intervals_fsm_count_ = 6; ce_rx_bl_intervals_repetition_count_ = 4; sta.intervals = ce_rx_bl_intervals_alloc (4); test_begin (t, "Several intervals, no one restarting.") { sta.rx_tonemaps->default_tmi = 0; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 4); sta.rx_tonemaps->default_tmi = 4; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 4); test_fail_if (sta.rx_tonemaps->tm[4]->released != 0); for (i = 0; i < ce_rx_bl_intervals_fsm_count_; i++) sta.intervals->tmi[i] = 5; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 5); test_fail_if (sta.rx_tonemaps->tm[4]->released != TONEMAP_RELEASE_TIMER_S); /* TODO: add cases of new tonemap calculation (see #3880). */ } test_end; sta.rx_tonemaps->default_tmi = 4; sta.rx_tonemaps->tm[4]->released = 0; test_begin (t, "Several intervals, one restarting for a better tonemap.") { /* TODO: This will change with new tonemap calculation (see #3880). */ sta.intervals->tmi[0] = TONEMAP_SRC_INTERVAL_UNAVAILABLE; sta.intervals->intervals[0]->default_robo = false; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 4); test_fail_if (sta.rx_tonemaps->tm[4]->released != 0); } test_end; test_begin (t, "Several intervals, one restarting for a worst tonemap.") { sta.intervals->tmi[1] = TONEMAP_SRC_INTERVAL_UNAVAILABLE; sta.intervals->intervals[1]->default_robo = true; ce_rx_bl_intervals_update_default_tm (&sta); test_fail_if (sta.rx_tonemaps->default_tmi != 0); test_fail_if (sta.rx_tonemaps->tm[4]->released != TONEMAP_RELEASE_TIMER_S); } test_end; /* Clean. */ sta.rx_tonemaps->tm[4] = NULL; tonemaps_release (sta.rx_tonemaps); ce_rx_bl_intervals_free (sta.intervals); ce_rx_bl_intervals_fsm_count_ = old_fsm_nb; ce_rx_bl_intervals_repetition_count_ = old_repetition_nb; } void test_suite_ce_rx_bl_intervals (test_t t) { /* Intervals init and uninit. */ test_suite_ce_rx_bl_intervals_init (t); /* Get used tonemap list. */ test_suite_ce_rx_bl_intervals_get_tmi_used_list (t); /* Time transformation from pbproc information to ATU. */ test_suite_ce_rx_bl_intervals_measure_to_date (t); /* Measure to interval computation. */ test_suite_ce_rx_bl_intervals_measure_to_interval (t); /* Measure to event computation */ test_suite_ce_rx_bl_intervals_measure_to_event (t); /* Updating TMI of intervals. */ test_suite_ce_rx_bl_intervals_update_tmi (t); /* Updating global default tonemap. */ test_suite_ce_rx_bl_intervals_update_default_tm (t); } int main (int argc, char **argv) { test_t t; test_init (t, argc, argv); test_suite_begin (t, "CE:RX:BL:interval"); /* Test intervals. */ test_suite_ce_rx_bl_intervals (t); /* Memory check. */ test_case_begin (t, "General"); test_begin (t, "Memory") { test_fail_unless (blk_check_memory ()); } test_end; /* Result. */ test_result (t); return (test_nb_failed (t) == 0 ? 0 : 1); }