summaryrefslogtreecommitdiff
path: root/cesar/mac/common/src/tonemask.c
blob: 4652148eb30526e9004d57f5a8a794cda0ce22c4 (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
167
168
169
/* Cesar project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    mac/common/src/tonemask.c
 * \brief   Tonemask related functions.
 * \ingroup mac_common
 */
#include "common/std.h"
#include <stdio.h>

#include "tonemask.h"
#include "timings.h"
#include "config/mac/common/eoc/tonemask.h"

uint
tonemask_carrier_nb (const u32 *tonemask)
{
    uint i, j;
    uint carrier_nb = 0;
    const u32 *tk;
    u32 tkw;
    dbg_assert_ptr (tonemask);
    /* Count carriers. */
    tk = tonemask;
    for (i = 0; i < PHY_CARRIER_NB / 32; i++)
    {
        tkw = *tk++;
        for (j = 32; j; j--, tkw >>= 1)
        {
            if (!(tkw & 1))
                carrier_nb++;
        }
    }
    if (PHY_CARRIER_NB % 32 != 0)
    {
        tkw = *tk++;
        for (j = PHY_CARRIER_NB % 32; j; j--, tkw >>= 1)
        {
            if (!(tkw & 1))
                carrier_nb++;
        }
        dbg_assert ((tkw & (tkw + 1)) == 0);
    }
    return carrier_nb;
}

void
tonemask_update (tonemask_info_t *ti)
{
    dbg_assert (ti);
    ti->carrier_nb = tonemask_carrier_nb (ti->tonemask);
    /* Never enables more tones than hardware can support. */
    dbg_assert (ti->carrier_nb <= PHY_CARRIER_NB);
    /* Only a multiple of ncopies carriers is used, see HPAV 3.4.4.1.  This is
     * QPSK. */
    static const phy_gil_t robo_gil[] = {
        PHY_GIL_417, PHY_GIL_417, PHY_GIL_567 };
    static const uint robo_dx_tck[] = {
        MAC_DX417_TCK, MAC_DX417_TCK, MAC_DX567_TCK };
    static const phy_pb_size_t robo_pb_size[] = {
        PHY_PB_SIZE_520, PHY_PB_SIZE_520, PHY_PB_SIZE_136 };
    static const uint robo_nb_copies[] = { 4, 2, 5 };
    phy_mod_t m;
    for (m = PHY_MOD_ROBO; m < PHY_MOD_ROBO_NB; m++)
    {
        tonemap_t *tm = &ti->tonemap_robo[m];
        tm->cpf = true;
        tm->fecrate = PHY_FEC_RATE_1_2;
        tm->gil = robo_gil[m];
        uint bits_per_symbol = ti->carrier_nb / robo_nb_copies[m] * 2;
        tm->ble = tonemap_ble (bits_per_symbol, PHY_FEC_RATE_1_2,
                               TONEMAP_P_PBERROR_DEFAULT_UF32, robo_gil[m]);
        tm->tmdma_desc_head = NULL;
        tm->bits_per_symbol = bits_per_symbol;
        tm->bits_per_pb[PHY_PB_SIZE_136] = 0;
        tm->bits_per_pb[PHY_PB_SIZE_520] = 0;
        tm->bits_per_pb[robo_pb_size[m]] =
            tonemap_bits_per_pb (m, PHY_FEC_RATE_1_2, robo_pb_size[m],
                                 tm->bits_per_symbol);
        uint one_pb_symb_nb = CEIL_DIV (tm->bits_per_pb[robo_pb_size[m]],
                                        tm->bits_per_symbol);
        tm->one_pb_data_tck = MAC_PAYLOAD_TCK (one_pb_symb_nb,
                                               robo_dx_tck[m]);
        tm->phy_combo_params[PHY_PB_SIZE_136] = 0;
        tm->phy_combo_params[PHY_PB_SIZE_520] = 0;
        tm->phy_combo_params[robo_pb_size[m]] =
            PHY_COMBO_PARAMS (m, tm->fecrate, robo_pb_size[m]);
        tm->tcc_halfit = robo_pb_size[m] == PHY_PB_SIZE_136 ? 1
            : tonemap_tcc_halfit (tm->bits_per_symbol,
                                  tm->bits_per_pb[PHY_PB_SIZE_520],
                                  robo_gil[m]);
    }
}

uint
tonemask_default (u32 *tonemask)
{
#if (!CONFIG_MAC_COMMON_EOC_TONEMASK)
    /** HomePlug AV default tone mask carriers. */
    static const uint 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         */
    };
    /** HomePlug AV default tone mask carriers number. */
    static const uint carriers_nb = 917;
#else
    /** EoC default tone mask carriers. */
    static const uint carriers[] =
    {
        /* 0-73 are OFF */
        PHY_LAST_EOC_CARRIER_NB,  /* 74-1439 are ON */
        1535,                     /* 1440-1535 are OFF */
    };
    /** EoC default tone mask carriers number. */
    static const uint carriers_nb = PHY_LAST_EOC_CARRIER_NB-PHY_CARRIER_OFFSET+1;
#endif
    uint i, j;
    uint dtc_idx = 0;
    dbg_assert (carriers[0] > PHY_CARRIER_OFFSET);
    uint dtc_stop = carriers[dtc_idx] - PHY_CARRIER_OFFSET;
#if (!CONFIG_MAC_COMMON_EOC_TONEMASK)
    bool dtc_on = false;
#else
    bool dtc_on = true;
#endif
    dbg_assert_ptr (tonemask);
    /* Slow loop, but only done at boot time. */
    for (i = 0; i < PHY_TONEMASK_WORDS; i++)
    {
        tonemask[i] = BITS_ONES (32);
        for (j = 0; j < 32; j++)
        {
            if (i * 32 + j > dtc_stop)
            {
                dtc_on = !dtc_on;
                dtc_stop = carriers[++dtc_idx] - PHY_CARRIER_OFFSET;
            }
            if (dtc_on)
                tonemask[i] &= ~(1 << j);
        }
    }
    return carriers_nb;
}