summaryrefslogtreecommitdiff
path: root/cesar/ce/rx/src/measure.c
blob: 816e2028356988a55dbdf4f1b832662be2c06356 (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
/* 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 "ce/rx/inc/measure.h"
#include "ce/rx/inc/rx.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)
        blk_release_desc_range_nb ((blk_t *) measure->chan_data,
                                   measure->chan_data_count);
}

bool
ce_rx_measure_sar_cb (void *data, pbproc_rx_params_t *rx_params,
                      uint pbm_count, blk_t **first_pbm, blk_t **last_pbm,
                      pb_t *chan_data, uint chan_data_count,
                      uint *pbm_blk_offset)
{
    /* Check needed parameters. */
    dbg_assert (data);

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

    /* Get channel data if they are some. */
    if (chan_data_count)
    {
        ce_rx_measure_add_chan_data (ce_rx, rx_params,
                                     (phy_chandata_t *) chan_data,
                                     chan_data_count);
    }
    if (pbm_count)
    {
        /* FIXME: for the moment, PB measurements are not needed and therefore,
         * ignored. */
        return false;
    }
    return 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. */
    /* Size of a measure per tone: 4 bytes. */
    const u8 measure_per_tone_size = sizeof (u32);
    /* Compute how many blocks we want. */
    const uint size = PHY_CARRIER_NB / (BLK_SIZE / measure_per_tone_size)
        + (PHY_CARRIER_NB % (BLK_SIZE / measure_per_tone_size) ? 1 : 0);
    /* Create channel data configuration for the whole NOISE NRJ with the
     * division. */
    uint i;
    phy_chandata_conf_t conf[size];
    for (i = 0; i < size; i++)
    {
        conf[i].type = PHY_CHANDATA_TYPE_NRJ;
        conf[i].size = BLK_SIZE / measure_per_tone_size;
        conf[i].address = conf[i].size * i;
        conf[i].div = CE_RX_PBDMA_DIVIDE;
        conf[i].last = 0;
    }
    conf[size - 1].last = 1;
    /* Send it to the PBProc. */
    pbproc_set_chandata_conf (pbproc, conf, size);
}

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);
}

void
ce_rx_measure_add_chan_data (ce_rx_t *ce_rx, pbproc_rx_params_t *rx_params,
                             phy_chandata_t *chan_data, uint chan_data_count)
{
    /* Check parameters. */
    dbg_assert (ce_rx);
    dbg_assert (rx_params);
    dbg_assert (chan_data);
    dbg_assert (chan_data_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->chan_data = chan_data;
    measure->chan_data_count = chan_data_count;
    /* 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);
}