summaryrefslogtreecommitdiff
path: root/cesar/ce/rx/src/measure.c
blob: 3bca62ac35c5a383c314365352705197482ea28d (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
/* Cesar project {{{
 *
 * Copyright (C) 2009 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    ce/rx/src/measure.c
 * \brief   Receive and pre-process measures from the SAR (implementation).
 * \ingroup ce_rx
 */
#include "common/std.h"

#include "hal/phy/pbdma.h"
#include "ce/rx/inc/measure.h"
#include "ce/rx/inc/rx.h"
#include "lib/utils.h"
#include "ce/debug/gpio/gpio.h"

/**
 * Destructor for a measure.
 */
void
ce_rx_measure_cache_destructor (void *object)
{
    /* Check parameters. */
    dbg_assert (object);

    ce_rx_measure_mbox_t *measure = (ce_rx_measure_mbox_t *) object;
    if (measure->chan_data_count)
        blk_release_desc_range_nb ((blk_t *) measure->chan_data,
                                   measure->chan_data_count);
}

void
ce_rx_measure_sar_cb (void *data, pbproc_rx_params_t *rx_params,
                      uint total_pb_count, pb_t *chan_data,
                      uint chan_data_count, u8 false_pb_count,
                      u32 ber_sum)
{
    /* Check parameter required for test. */
    dbg_assert (rx_params);

    ce_debug_gpio_event (CE_DEBUG_GPIO_EVENT_CE_RX_SAR_CB, true);

    /* Only handle measures for a "valid" STA. */
    if (MAC_TEI_IS_STA (rx_params->tei) && !rx_params->multi_net_bcast)
    {
        /* Check all parameters. */
        dbg_assert (data);
        /* We must have something to do. */
        dbg_assert (chan_data || total_pb_count);

        /* Get the context of the CE RX. */
        ce_rx_t *ce_rx = (ce_rx_t *) data;

        /* Only get measure if:
           - this is a channel data
             or
           - there is some room left in the mailbox (i.e. there is not too
           much measures in the mailbox). */
        if (chan_data || (mbox_peek (&ce_rx->measure_mbox)
                          < CE_RX_MEASURE_MBOX_MAX_SIZE))
        {
            /* Trace it. */
            CE_RX_TRACE_VERBOSE (SAR_CB, rx_params->tei, chan_data_count, total_pb_count);

            /* Allocate a measure. */
            ce_rx_measure_mbox_t *measure = slab_alloc (&ce_rx->measure_cache);

            /* Copy needed information. */
            measure->rx_params = *rx_params;
            measure->total_pb_count = total_pb_count;
            measure->false_pb_count = false_pb_count;
            measure->ber_sum = ber_sum;

            /* Any channel data? */
            measure->chan_data_count = chan_data_count;
            if (chan_data_count)
            {
                dbg_assert (chan_data);
                measure->chan_data = (phy_chandata_t *) chan_data;
            }
            else
            {
                dbg_invalid_ptr (measure->chan_data);
            }

            /* Add the measure to the mailbox. */
            mbox_put (&ce_rx->measure_mbox, &measure->mbox_node);
            /* Wake up the CE RX. */
            ce_rx_work_add (ce_rx, CE_RX_WORK_FLAG_MEASURE);
        }
    }
    ce_debug_gpio_event (CE_DEBUG_GPIO_EVENT_CE_RX_SAR_CB, false);
}

void
ce_rx_measure_init (ce_rx_t *ce_rx, sar_t *sar, pbproc_t *pbproc)
{
    /* Check parameter. */
    dbg_assert (ce_rx);
    /* Do not check "sar", we do not use it directly (otherwise, there will be
     * assert during tests. */

    /* Initialize mailbox. */
    mbox_init (&ce_rx->measure_mbox);
    /* Initialize allocator for the mailbox. */
    slab_cache_init (&ce_rx->measure_cache, "ce_rx_measure",
                     sizeof (ce_rx_measure_mbox_t),
                     &ce_rx_measure_cache_destructor);
    /* Register our callback to get measures. */
    sar_init_measure_context (sar, ce_rx);
    sar_init_measurement_cb (sar, ce_rx_measure_sar_cb);

    /* Ask the PBProc to give us the channel data. */
    /* Create channel data configuration for the whole NOISE NRJ with the
     * division. */
    uint i;
    static phy_chandata_conf_t conf[CE_RX_MEASURE_CONF_SIZE];
    for (i = 0; i < CE_RX_MEASURE_CONF_SIZE; i++)
    {
        conf[i].type = PHY_CHANDATA_TYPE_NRJ;
        conf[i].size = BLK_SIZE / 4;
        conf[i].address = conf[i].size * i;
        conf[i].div = CE_RX_PBDMA_DIVIDE;
        conf[i].last = 0;
    }
    conf[CE_RX_MEASURE_CONF_SIZE - 1].last = 1;
    /* Send it to the PBProc. */
    pbproc_set_chandata_conf (pbproc, conf, CE_RX_MEASURE_CONF_SIZE, false);
}

void
ce_rx_measure_uninit (ce_rx_t *ce_rx)
{
    /* Check parameters. */
    dbg_assert (ce_rx);

    /* Empty MBox. */
    mbox_node_t *node = mbox_try_get (&ce_rx->measure_mbox);
    ce_rx_measure_mbox_t *measure;
    while (node)
    {
        /* Convert. */
        measure = PARENT_OF (ce_rx_measure_mbox_t, mbox_node, node);
        /* Delete. */
        slab_release (measure);
        /* Get next. */
        node = mbox_try_get (&ce_rx->measure_mbox);
    }
    mbox_uninit (&ce_rx->measure_mbox);
}