summaryrefslogtreecommitdiff
path: root/cesar/ce/rx/bitloading/fsm/src/fsm.c
blob: c24174d66e3f5bc80397e03cacd349d87514fa36 (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
/* Cesar project {{{
 *
 * Copyright (C) 2009 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    ce/rx/bitloading/fsm/src/fsm.c
 * \brief   CE RX Bit loading FSM internal functions.
 * \ingroup ce_rx
 *
 * Functions to work with the FSM: init, transition.
 */
#include "common/std.h"

#include "ce/rx/bitloading/fsm/fsm.h"
#include "inc/tables.h"
#include "ce/rx/inc/trace.h"
#include "ce/rx/bitloading/inc/intervals.h"
#include "ce/debug/gpio/gpio.h"

void
ce_rx_bl_fsm_handle_event (ce_rx_t *ce_rx, sta_t *sta, ce_rx_bl_fsm_event_type_t e,
                           ce_rx_bitloading_fsm_event_param_t data)
{
    /* Check parameters. */
    dbg_assert (sta);
    ce_rx_bl_fsm_state_t fsm = sta->ce_rx_bt.fsm;
    dbg_assert (fsm < CE_RX_BL_FSM_STATE_NB);
    dbg_assert (e < CE_RX_BL_FSM_EVENT_TYPE_NB);

    /* Get transition. */
    ce_rx_bl_fsm_transition_t tr = ce_rx_bl_fsm_transition_table[fsm][e];
    /* A non managed event is an error. */
    dbg_assert (tr);
    /* Run transition. */
    ce_rx_bl_fsm_branch_t br = tr (ce_rx, sta, data);
    dbg_assert (((br >> 16) & 0xff) == fsm);
    dbg_assert (((br >> 8) & 0xff) == e);
    sta->ce_rx_bt.fsm = br & 0xff;

    if (fsm != sta->ce_rx_bt.fsm)
        CE_RX_TRACE (FSM_FROM_TO, sta->tei, fsm, e, sta->ce_rx_bt.fsm);
    ce_debug_gpio_event
        (CE_DEBUG_GPIO_EVENT_CE_RX_BL_FSM_IDLE + sta->ce_rx_bt.fsm, true);
    ce_debug_gpio_event
        (CE_DEBUG_GPIO_EVENT_CE_RX_BL_MEASURE_NONE, false);
}

ce_rx_bl_fsm_event_type_t
ce_rx_bl_fsm_measure_to_event (sta_t *sta,
                               ce_rx_bitloading_fsm_event_param_t data)
{
    dbg_assert (sta);

    /* Prepare event types.
     * We create a array of two dimensions:
     * First dimension: is measure for intervals or global ?
     * Second dimension: Data, Sound complete or not. */
    int has_interval, type;
    static const ce_rx_bl_fsm_event_type_t event_tab[2][3] =
    {
        {
            CE_RX_BL_FSM_EVENT_TYPE_data,
            CE_RX_BL_FSM_EVENT_TYPE_sound,
            CE_RX_BL_FSM_EVENT_TYPE_sound_completed
        },
        {
            CE_RX_BL_FSM_EVENT_TYPE_interval_data,
            CE_RX_BL_FSM_EVENT_TYPE_interval_sound,
            CE_RX_BL_FSM_EVENT_TYPE_interval_sound_completed
        }
    };

    /* Get measure. */
    ce_rx_measure_mbox_t *measure = data.measure;
    dbg_assert (measure);

    /* Get interval information. */
    u16 start_date_atu, end_date_atu;
    /* Global by default. */
    has_interval = CE_RX_FSM_MEASURE_TO_EVENT_TYPE_GLOBAL;
    measure->fsm_id = -1;
    if (ce_rx_bl_intervals_measure_to_date (&measure->rx_params,
                                            &start_date_atu,
                                            &end_date_atu))
    {
        int interval;
        interval = ce_rx_bl_intervals_measure_to_interval (sta->rx_tonemaps,
                                                           start_date_atu,
                                                           end_date_atu);
        if (interval != -1)
        {
            /* We are on an interval. */
            has_interval = CE_RX_FSM_MEASURE_TO_EVENT_TYPE_INTERVAL;
            measure->fsm_id = interval % mac_interval_repetition_count_;
        }
    }

    /* Is this measure a Sound ? */
    if (measure->rx_params.sound)
    {
        if (measure->rx_params.sound_complete)
            type = CE_RX_FSM_MEASURE_TO_EVENT_TYPE_SOUND_COMPLETED;
        else
            type = CE_RX_FSM_MEASURE_TO_EVENT_TYPE_SOUND;
    }
    /* This is a data. */
    else
        type = CE_RX_FSM_MEASURE_TO_EVENT_TYPE_DATA;

    return event_tab[has_interval][type];
}