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

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

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

void
pbproc_fsm_init (pbproc_t *ctx)
{
    uint i;
    dbg_assert (ctx);
    ctx->fsm.current_state = PBPROC_FSM_STATE_IDLE;
    for (i = 0; i < PBPROC_FSM_STATE_NB; i++)
    {
        ctx->fsm.states[i].rx_fc_cb =
            (pbproc_fsm_rx_fc_cb_t) pbproc_fsm_unexpected;
        ctx->fsm.states[i].access_cb = pbproc_fsm_unexpected;
        ctx->fsm.states[i].access_conf_cb = pbproc_fsm_unexpected;
    }
    ctx->fsm.deferred_cb = NULL;
}

bool
pbproc_fsm_handle_rx_fc_event (pbproc_t *ctx, u32 rx_date, const u32 *fc_av)
{
    dbg_assert (ctx);
    dbg_assert (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
    PBPROC_TRACE (FSM_RX_FC, phy_date (ctx->phy), rx_date,
                  fc_av ? fc_av[0] & PBPROC_FC_DT_MASK
                  : PBPROC_FC_DT_MASK + 1);
    ctx->fsm.states[ctx->fsm.current_state].
        rx_fc_cb (ctx, rx_date, (const pbproc_fc_t *) fc_av);
    return ctx->fsm.deferred_cb != NULL;
}

bool
pbproc_fsm_handle_access_event (pbproc_t *ctx)
{
    dbg_assert (ctx);
    dbg_assert (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
    PBPROC_TRACE (FSM_ACCESS, phy_date (ctx->phy));
    ctx->fsm.states[ctx->fsm.current_state].access_cb (ctx);
    return ctx->fsm.deferred_cb != NULL;
}

bool
pbproc_fsm_handle_access_conf_event (pbproc_t *ctx)
{
    dbg_assert (ctx);
    dbg_assert (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
    PBPROC_TRACE (FSM_ACCESS_CONF, phy_date (ctx->phy));
    ctx->fsm.states[ctx->fsm.current_state].access_conf_cb (ctx);
    return ctx->fsm.deferred_cb != NULL;
}

bool
pbproc_fsm_handle_pbdma_event (pbproc_t *ctx, u32 status_word)
{
    dbg_assert (ctx);
    dbg_assert (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
    PBPROC_TRACE (FSM_PBDMA, phy_date (ctx->phy), status_word);
    /* Handled as an ACCESS event. */
    ctx->pbdma_status = PHY_PBDMA_STATUS (status_word);
    ctx->fsm.states[ctx->fsm.current_state].access_cb (ctx);
    return ctx->fsm.deferred_cb != NULL;
}

bool
pbproc_fsm_handle_tx_false_alarm_event (pbproc_t *ctx)
{
    // TODO
    return false;
}

void
pbproc_fsm_handle_deferred (pbproc_t *ctx)
{
    pbproc_fsm_deferred_cb_t cb;
    dbg_assert (ctx);
    dbg_assert (ctx->fsm.deferred_cb);
    PBPROC_TRACE (FSM_DEFERRED, phy_date (ctx->phy));
    cb = ctx->fsm.deferred_cb;
    ctx->fsm.deferred_cb = NULL;
    cb (ctx);
    dbg_assert (!ctx->fsm.deferred_cb);
}

void
pbproc_fsm_change_state (pbproc_t *ctx, pbproc_fsm_state_t state)
{
    dbg_assert (ctx);
    dbg_assert (state < PBPROC_FSM_STATE_NB);
    PBPROC_TRACE (FSM_CHANGE_STATE, state);
    ctx->fsm.current_state = state;
}

void
pbproc_fsm_schedule_deferred (pbproc_t *ctx,
                              pbproc_fsm_deferred_cb_t deferred_cb)
{
    dbg_assert (ctx);
    dbg_assert (deferred_cb);
    dbg_assert (!ctx->fsm.deferred_cb);
    PBPROC_TRACE (FSM_SCHEDULE_DEFERRED);
    ctx->fsm.deferred_cb = deferred_cb;
}

void
pbproc_fsm_unexpected (pbproc_t *ctx)
{
    PBPROC_TRACE (FSM_UNEXPECTED);
    dbg_fatal ("unexpected event");
}