summaryrefslogtreecommitdiff
path: root/cesar/hal/phy/src/tx.c
blob: 98c8be716b86b9e0f1e06d71331cd10a7c5718f7 (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
/* Cesar project {{{
 *
 * Copyright (C) 2008 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    hal/phy/src/tx.c
 * \brief   HAL Phy TX functions.
 * \ingroup hal_phy
 */
#include "common/std.h"

#include "inc/context.h"
#include "inc/regs.h"
#include "hal/leon/itc2.h"

void
phy_tx_fc10 (phy_t *ctx, u32 fc_10)
{
    dbg_assert (ctx);
    dbg_assert (BF_CHECK (PHY_DSPSS_TX_FC_10__FC, fc_10));
    PHY_TRACE (TX_FC10, fc_10);
    /* Set FC 1.0, will be created later. */
    PHY_DSPSS_TX_FC_10 = BF_SHIFT (PHY_DSPSS_TX_FC_10__FC, fc_10)
        | BF_MASK (PHY_DSPSS_TX_FC_10__CRC);
    /* TODO: do it later. */
    PHY_PRATIC_IMMEDIATE_ACTION = PHY_PRATIC_ACTION__CREATE_FC_10;
}

void
phy_tx_param (phy_t *ctx, phy_fc_mode_t fc_mode, bool short_ppdu,
              phy_mod_t mod, phy_fecrate_t fecrate, phy_pb_size_t pb_size,
              phy_gil_t gil, uint tonemap_index)
{
    dbg_assert (ctx);
    dbg_assert (fc_mode < PHY_FC_MODE_NB
                && ((short_ppdu == false
                     && mod < PHY_MOD_NONE
                     && fecrate < PHY_FEC_RATE_NONE
                     && pb_size < PHY_PB_SIZE_NONE
                     && gil < PHY_GIL_NB
                     && BF_CHECK (PHY_DSPSS_TX_PARAM__TMBI, tonemap_index))
                    || short_ppdu == true));
    PHY_TRACE (TX_PARAM, fc_mode, short_ppdu, mod, fecrate, pb_size, gil,
               tonemap_index);
    if (short_ppdu)
    {
        PHY_DSPSS_TX_PARAM =
            BF_FILL (PHY_DSPSS_TX_PARAM,
                     (FC_MODE, fc_mode),
                     (SHORT_PPDU, 1))
            | PHY_DSPSS_TX_PARAM__DEFAULT;
        gil = PHY_GIL_567;
    }
    else
    {
        PHY_DSPSS_TX_PARAM =
            BF_FILL (PHY_DSPSS_TX_PARAM,
                     (PB_SIZE, pb_size),
                     (PB_RATE, fecrate),
                     (PB_MOD, mod),
                     (FC_MODE, fc_mode),
                     (SHORT_PPDU, 0),
                     (TMBI, tonemap_index))
            | PHY_DSPSS_TX_PARAM__DEFAULT;
    }
    static const uint gil_durations_table[] = {
        PHY_DSPSS_TX_GUARD_LENGTH__VALUE_417,
        PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567,
        PHY_DSPSS_TX_GUARD_LENGTH__VALUE_3534,
    };
    switch (fc_mode)
    {
    case PHY_FC_MODE_HYBRID_1:
        PHY_DSPSS_TX_GUARD_LENGTH_0 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_10;
        PHY_DSPSS_TX_GUARD_LENGTH_1 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV;
        PHY_DSPSS_TX_GUARD_LENGTH_2 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_3 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_4 = gil_durations_table[gil];
        break;
    case PHY_FC_MODE_HYBRID_2:
        PHY_DSPSS_TX_GUARD_LENGTH_0 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_10;
        PHY_DSPSS_TX_GUARD_LENGTH_1 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV;
        PHY_DSPSS_TX_GUARD_LENGTH_2 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV;
        PHY_DSPSS_TX_GUARD_LENGTH_3 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_4 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        break;
    case PHY_FC_MODE_AV_1:
        PHY_DSPSS_TX_GUARD_LENGTH_0 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV;
        PHY_DSPSS_TX_GUARD_LENGTH_1 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_2 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_3 = gil_durations_table[gil];
        PHY_DSPSS_TX_GUARD_LENGTH_4 = gil_durations_table[gil];
        break;
    case PHY_FC_MODE_AV_2:
        PHY_DSPSS_TX_GUARD_LENGTH_0 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV;
        PHY_DSPSS_TX_GUARD_LENGTH_1 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_FC_AV;
        PHY_DSPSS_TX_GUARD_LENGTH_2 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_3 =
            PHY_DSPSS_TX_GUARD_LENGTH__VALUE_567;
        PHY_DSPSS_TX_GUARD_LENGTH_4 = gil_durations_table[gil];
        break;
    default:
        dbg_assert_default ();
    }
    PHY_DSPSS_TX_GUARD_LENGTH_5 = gil_durations_table[gil];
}

void
phy_tx_frame (phy_t *ctx, u32 date, bool want_conf, bool stop_tx_on_prp_lost,
              const u32 fc_av[4])
{
    dbg_assert (ctx);
    dbg_assert (fc_av);
    PHY_TRACE (TX_FRAME, date, want_conf, stop_tx_on_prp_lost, fc_av[0]);
    /* Set FC. */
    PHY_DSPSS_TX_FC_AV_0 = fc_av[0];
    PHY_DSPSS_TX_FC_AV_1 = fc_av[1];
    PHY_DSPSS_TX_FC_AV_2 = fc_av[2];
    PHY_DSPSS_TX_FC_AV_3 = fc_av[3];
    /* TODO: stop_tx_on_prp_lost. */
    LEON_ITC2_CLEAR = 1 << LEON_ITC2_IT__PRATIC_ACCESS_CONF;
    if (want_conf)
        LEON_ITC2_MASK |= 1 << LEON_ITC2_IT__PRATIC_ACCESS_CONF;
    else
        LEON_ITC2_MASK &= ~(1 << LEON_ITC2_IT__PRATIC_ACCESS_CONF);
    /* Program TX. */
    PHY_PRATIC_TIMER_2_DATE = date;
    PHY_PRATIC_TIMER_2_CTRL = BF_SHIFT (PHY_PRATIC_TIMER_X_CTRL__ACTION,
                                        PHY_PRATIC_ACTION__START_TX)
        | BF_MASK (PHY_PRATIC_TIMER_X_CTRL__VALID);
}