summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc/src/fsm_top.c
blob: 1a26d1be239a0e7f60f08f7bf9cc2386c905b030 (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
/* Maria project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    mac/pbproc/src/fsm_top.c
 * \brief   FSM top part, handle idle and generic transitions.
 * \ingroup mac_pbproc
 */
#include "common/std.h"

#include "hal/gpio/gpio.h"
#include "hal/watchdog/watchdog.h"

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

#include "mac/pbproc/inc/fsm_tx_rts_cts.h"
#include "mac/pbproc/inc/fsm_tx_data.h"
#include "mac/pbproc/inc/fsm_tx_sound.h"
#include "mac/pbproc/inc/fsm_handle_fc.h"
#include "mac/pbproc/inc/prep_mpdu.h"
#include "mac/pbproc/inc/pbproc.h"

#include "mac/pbproc/inc/fsm_top.h"

void
pbproc_ftop_init (pbproc_t *ctx)
{
    dbg_assert (ctx);
    ctx->fsm.states[PBPROC_FSM_STATE_IDLE].rx_fc_cb =
        pbproc_ftop__idle__rx_fc;
    ctx->fsm.states[PBPROC_FSM_STATE_IDLE].access_cb =
        pbproc_ftop__idle__access;
}

void ARCH_ILRAM
pbproc_ftop__idle__rx_fc (pbproc_t *ctx, u32 rx_date,
                          const pbproc_fc_t *fc_av)
{
    dbg_claim (ctx);
    ctx->access = *ca_access_get_param (ctx->ca);
    /* Backoff. */
    pbproc_backoff_lost (ctx);
    /* Easy... */
    pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
}

void ARCH_ILRAM
pbproc_ftop__idle__access (pbproc_t *ctx)
{
    dbg_claim (ctx);
    ca_access_hold (ctx->ca);
    ctx->access = *ca_access_get_param (ctx->ca);
    if (!ctx->activated)
    {
        /* Give up we are leaving. */
        pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
    }
    else if (ctx->access.mfs == NULL)
    {
        PBPROC_TRACE (FTOP_AIFS);
        phy_rx_activate (ctx->phy, true, 0, false);
        ca_backoff_cancel (ctx->ca);
        ctx->alloc = *ca_access_aifs (ctx->ca);
        ctx->times = ctx->times_array[ctx->alloc.hybrid];
        /* Change RX parameters. */
        phy_rx_param (ctx->phy, PHY_FC_MODE (ctx->alloc.hybrid,
                                             ctx->config->fc_symbols_nb));
        /* Reset traffic indicator. */
        GPIO_SET (LED_TRAFFIC, 0);
        /* Toggle live indicator. */
        GPIO_TOGGLE (LED_PBPROC_ALIVE);
        /* Trigger watchdog event. */
        hal_watchdog_trigger (HAL_WATCHDOG_EVENT_PBPROC);
        /* Return to IDLE state. */
        pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
    }
    else
    {
        if (ctx->access.prp && !phy_access_backoff_prp_won (ctx->phy))
        {
            PBPROC_TRACE (FTOP_PRP_LOST);
            /* PRP lost, someone is supposed to start transmission.  If no
             * delimiter is received, we should infer a collision.  Do not
             * use our backoff, the backoff procedure is not entered. */
            ca_backoff_cancel (ctx->ca);
            ca_access_vcs_restart (ctx->ca, phy_date (), ctx->times.eifs_tck,
                                   PBPROC_ANTICIP_TCK, true);
            ctx->stats.prp_lost++;
            dbg_claim (ctx->fsm.current_state == PBPROC_FSM_STATE_IDLE);
        }
        else
        {
            /* PRP won or no PRP. */
            if (ctx->access.mfs->beacon)
                pbproc_prep_beacon (ctx);
            else
                pbproc_prep_mpdu (ctx);
            if (!ctx->prep_mpdu.valid)
            {
                PBPROC_TRACE (FTOP_TX_INVALID);
                ca_access_defer (ctx->ca, ctx->access.access_date,
                                 PBPROC_ANTICIP_TCK);
                /* Return to IDLE state. */
                pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
            }
            else
            {
                PBPROC_TRACE (FTOP_TX, ctx->prep_mpdu.main_mfs,
                              ctx->prep_mpdu.dtei, ctx->prep_mpdu.lid,
                              ctx->prep_mpdu.tx_date, ctx->prep_mpdu.flp_tck,
                              ctx->prep_mpdu.pb_nb_total);
                if (ctx->prep_mpdu.rts_cts)
                {
                    //pbproc_ftrc__handle (ctx);
                }
                else if (ctx->prep_mpdu.sound_reason_code != TONEMAP_SRC_NULL)
                {
                    pbproc_ftso__handle (ctx);
                }
                else
                {
                    pbproc_ftda__handle (ctx);
                }
            }
        }
    }
}