summaryrefslogtreecommitdiff
path: root/mac/pbproc/src/fsm_rx_beacon.c
blob: ff1ee61c58c49ba70feada4b0b3b8fc35775f0d4 (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
/* Cesar project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    mac/pbproc/src/fsm_rx_beacon.c
 * \brief   FSM RX beacon part.
 * \ingroup mac_pbproc
 */
#include "common/std.h"

#include "pbproc.h"
#include "inc/context.h"
#include "inc/fsm_handle_fc.h"

#include "inc/fsm_rx_beacon.h"

void
pbproc_frbe_init (pbproc_t *ctx)
{
    dbg_assert (ctx);
    ctx->fsm.states[PBPROC_FSM_STATE_RX_BEACON].access_cb =
        pbproc_frbe__rx_beacon__access;
}

void
pbproc_frbe__handle (pbproc_t *ctx, u32 rx_date,
                     const pbproc_fc_beacon_t *beacon)
{
    dbg_assert (ctx);
    dbg_assert (beacon);
    /* Compute number of symbol. */
    tonemap_t *tm =
        &ctx->config->tonemask_info.tonemap_robo[PHY_MOD_MINI_ROBO];
    uint bits_per_pb = tonemap_bits_per_pb (tm->fecrate, PHY_PB_SIZE_136);
    uint symb_nb = (1 * bits_per_pb + tm->bits_per_symbol - 1) /
        tm->bits_per_symbol;
    /* Unlock the hardware. */
    phy_rx_prepare (ctx->phy, false, PHY_MOD_MINI_ROBO, PHY_FEC_RATE_NONE,
                    PHY_PB_SIZE_NONE, PHY_GIL_NONE, 0, symb_nb);
    /* Program PB DMA. */
    dbg_assert (ctx->rx_pool_size >= 1);
    phy_pbdma_start (ctx->phy, true, NULL, NULL, 1, 1, 1,
                     &ctx->rx_pool_head->phy_pb);
    /* Wait. */
    pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_RX_BEACON);
    /* Save received beacon parameters. */
    pbproc_rx_beacon_params_t *params = (void *) (ctx->rx_pool_head->data
                                                  + MAC_PB136_BYTES);
    params->preamble_sysdate = phy_rx_sysdate (ctx->phy);
    params->preamble_date = rx_date;
    params->bts = beacon->bts_msb8 << 24 | beacon->bts_lsb24;
    params->bto[0] = beacon->bto0;
    params->bto[1] = beacon->bto1_msb8 << 8 | beacon->bto1_lsb8;
    params->bto[2] = beacon->bto2;
    params->bto[3] = beacon->bto3_msb8 << 8 | beacon->bto3_lsb8;
    params->snid = beacon->snid;
    params->access = beacon->access;
    ctx->recv_mpdu.rx_beacon_params = params;
    /* Prepare for next. */
    const bool hybrid = true;
    u32 flp_tck = ctx->times[hybrid].pre_fcs_tck
        + MAC_PAYLOAD_TCK (symb_nb, MAC_DX567_TCK)
        + MAC_B2BIFS_TCK;
    ca_access_vcs_restart (ctx->ca, rx_date, flp_tck, PBPROC_ANTICIP_TCK,
                           false);
}

void
pbproc_frbe__rx_beacon__access (pbproc_t *ctx)
{
    /* Unchain used PB. */
    pb_t *head = ctx->rx_pool_head;
    if (ctx->rx_pool_tail == head)
    {
        ctx->rx_pool_head = NULL;
        dbg_invalid_ptr (ctx->rx_pool_tail);
        ctx->rx_pool_size = 0;
    }
    else
    {
        ctx->rx_pool_head = head->next;
        ctx->rx_pool_size--;
    }
    /* Give the received beacon to upper layer. */
    PBPROC_TRACE (FRBE_RX_BEACON_CB);
    dbg_assert (ctx->rx_beacon_cb);
    ctx->rx_beacon_cb (ctx->user_data, (pb_beacon_t *) head,
                       ctx->recv_mpdu.rx_beacon_params);
    /* Done. */
    pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
}