summaryrefslogtreecommitdiff
path: root/cesar/ce/rx/bitloading/src/intervals.c
blob: 3798d09cd6f6adbc877f59864688f162615dee9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* Cesar project {{{
 *
 * Copyright (C) 2009 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    ce/rx/bitloading/src/intervals.c
 * \brief   CE/RX Intervals related functions.
 * \ingroup ce_rx_bl
 */

#include "common/std.h"
#include "lib/blk.h"
#include "mac/common/tonemap.h"
#include "mac/common/timings.h"
#include "ce/rx/bitloading/inc/bitloading.h"
#include "ce/rx/bitloading/intervals.h"
#include "ce/rx/bitloading/inc/intervals.h"
#include "ce/rx/cp/inc/cp.h"
#include "ce_rx_bl_fsm_defs.h"

bool
ce_rx_bl_intervals_measure_to_date (pbproc_rx_params_t *rx_param,
                                    u16 *start_date_atu,
                                    u16 *end_date_atu)
{
    dbg_assert (rx_param);
    dbg_assert (start_date_atu);
    dbg_assert (end_date_atu);

    /* Can't have beacon period start NTB > preamble start. */
    if (less_mod2p32 (rx_param->preamble_ntb,
                      rx_param->beacon_period_start_ntb))
        return false;

    /* Estimate the start date.
     * As we don't know how in which mode we are, we take an average of hybrid
     * and AV modes. */
    u32 average_tck = ((MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK)
                       + (MAC_PREAMBLE_TCK + MAC_FC_AV_TCK)) / 2;
    *start_date_atu = MAC_TCK_TO_ATU (
        ABS ((s32) (rx_param->preamble_ntb - rx_param->beacon_period_start_ntb))
        + average_tck);

    /* Estimate the end date. */
    *end_date_atu = *start_date_atu + MAC_TCK_TO_ATU (rx_param->fl_tck);

    /* Check we didn't have overflowed. */
    dbg_assert (*start_date_atu < *end_date_atu);
    return true;
}

int
ce_rx_bl_intervals_measure_to_interval (tonemaps_t *tms,
                                        u16 mea_start,
                                        u16 mea_end)
{
    dbg_assert (tms);
    dbg_assert (tms->intervals);
    dbg_assert (mea_start < mea_end);

    tonemap_intervals_t *ints = tms->intervals;

    if (ints->intervals_nb <= 1)
        return -1;

    /* We take the middle of the measure and see in which interval it is
     * supposed to be. */
    u16 mea_middle = (mea_start + mea_end) / 2;

    /* Measure middle is contained in this interval. */
    u8 int_num = tonemap_interval_find (tms, mea_middle);

    /* If we are not located in an interval, the measure is after the last
     * offset (our beacon period may not be perfect). We may consider this
     * measure as global. */
    if (int_num >= ints->intervals_nb)
        return -1;

    /* Get the start/end date of this interval. */
    /* We remove 1 because the date correspond to the next interval. */
    u16 int_end = ints->interval[int_num].end_offset_atu - 1;
    u16 int_start;
    if (int_num == 0)
        int_start = 0;
    else
        int_start = ints->interval[int_num - 1].end_offset_atu;
    dbg_assert (int_start < int_end);

    /* Check the measure didn't shifted too much. */
    if (mea_end > int_end
        && mea_end - int_end > mac_interval_measure_shift_tolerance_)
        return -1;
    if (mea_start < int_start
        && int_start - mea_start > mac_interval_measure_shift_tolerance_)
        return -1;

    return int_num;
}

void
ce_rx_bl_intervals_update_tmi (sta_t *sta, const bsu_aclf_bp_t bp_tck)
{
    dbg_assert (sta);
    dbg_assert (sta->intervals);

    int i;
    u8 res;
    ce_rx_bitloading_intervals_t *its = sta->intervals;

    u16 bp_atu = MAC_TCK_TO_ATU (bp_tck);
    int total_ints = mac_interval_fsm_count_
        * mac_interval_repetition_count_;

    mac_interval_clear (sta->rx_tonemaps);
    for (i = 0; i < total_ints - 1; i++)
    {
        res = mac_interval_append (
            sta->rx_tonemaps,
            bp_atu * (i + 1) / total_ints,
            its->tmi[i % mac_interval_fsm_count_]);
        dbg_assert (res == i + 1);
    }
    /* Last interval duration is increased to fit with max theoretical beacon
     * period duration. */
    res = mac_interval_append (
        sta->rx_tonemaps,
        bp_atu + MAC_TCK_TO_ATU (HPAV_BEACON_BTO_MAX_TCK),
        its->tmi[(total_ints - 1) % mac_interval_fsm_count_]);
    dbg_assert (res == total_ints);
    mac_interval_commit_changes (sta->rx_tonemaps);
}

void
ce_rx_bl_intervals_reset (ce_rx_t *ce_rx, sta_t *sta, int fsm_id)
{
    dbg_assert (ce_rx);
    dbg_assert (ce_rx->aclf);
    dbg_assert (sta);
    dbg_assert (sta->intervals);
    dbg_assert (sta->rx_tonemaps);
    dbg_assert (fsm_id >= 0 && fsm_id <= mac_interval_fsm_count_);

    ce_rx_bitloading_t *bl = sta->intervals->intervals[fsm_id];
    u8 *tmi = &sta->intervals->tmi[fsm_id];
    /* Mark the intervals TMI to be released if this fsm has negotiated
     * it's own tone map. */
    if (*tmi != sta->rx_tonemaps->default_tmi
        && TONEMAP_INDEX_IS_NEGOTIATED (*tmi))
        tonemap_disable (sta->rx_tonemaps, *tmi);

    /* Set sound flag for this interval. */
    *tmi = 0xFE;

    /* Reset high PB error rate counter. */
    bl->high_pb_error_rate_frame_counter = 0;
    /* Reset BER sliding means. */
    ce_rx_bl_ber_sliding_mean_reset (bl);

    /* Rebuild intervals.  */
    ce_rx_bl_intervals_update_tmi (sta, ce_rx->aclf->beacon_period_tck);
    /* Send refresh TMI list with intervals. */
    ce_rx_cp_send_mme_refresh_tmi_list (ce_rx, sta);
}