aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/802_15_4/wireless_uart/fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/examples/802_15_4/wireless_uart/fsm.c')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/examples/802_15_4/wireless_uart/fsm.c601
1 files changed, 601 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/802_15_4/wireless_uart/fsm.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/802_15_4/wireless_uart/fsm.c
new file mode 100644
index 0000000..843cd26
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/802_15_4/wireless_uart/fsm.c
@@ -0,0 +1,601 @@
+/**
+ * Copyright (c) 2016 - 2018 Nordic Semiconductor ASA and Luxoft Global Operations Gmbh.
+ *
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "config.h"
+
+#include "fsm.h"
+#include "uart.h"
+#if (CONFIG_SECURE == 1)
+#include "security.h"
+#endif
+#include "sys_fsm.h"
+#include "sys_utils.h"
+#include "sys_memory_manager.h"
+#include "sys_debug.h"
+#include "sys_task_scheduler.h"
+#include "boards.h"
+#include "nrf_gpio.h"
+#include <stdint.h>
+#include <stddef.h>
+
+typedef struct
+{
+ mac_payload_descriptor_t payload_descr;
+ uint8_t length;
+} fsm_frame_item_t;
+
+typedef enum
+{
+ S_INITIAL,
+ S_SETTING_CH,
+ S_SETTING_SHORT_ADDR,
+ S_SETTING_EXT_ADDR,
+ S_SETTING_PAN_ID,
+ S_SETTING_RX_ON_IDLE,
+ S_SETTING_SECURITY,
+ S_WORKING,
+} fsm_states_t;
+
+typedef enum
+{
+ GU_SET_SUCCESS,
+ GU_SEND_SUCCESS,
+ GU_UART_TX_DATA_AVAILABLE,
+ GU_RADIO_TX_IDLE,
+ GU_UART_TX_IDLE,
+} fsm_guards_t;
+
+typedef enum
+{
+ A_CHANNEL_SET,
+ A_SHORT_ADDR_SET,
+ A_EXT_ADDR_SET,
+ A_PAN_ID_SET,
+ A_RX_ON_IDLE_SET,
+ A_CONFIG_COMPLETE,
+ A_RADIO_TX_START,
+ A_RADIO_TX_RESTART,
+ A_UART_TX_START,
+ A_UART_TX_IDLE_SET,
+#if (CONFIG_SECURE == 1)
+ A_SECURITY_SET
+#endif
+} fsm_actions_t;
+
+typedef void (* fsm_action_t)(void *);
+typedef bool (* fsm_guard_t)(void *);
+typedef void (* app_action_t)(void);
+
+typedef void (* store_data_handler_t)(fsm_event_data_t *);
+
+// prototypes
+static void fsm_action(sys_fsm_action_id_t action_id, void * p_data);
+static bool fsm_guard(sys_fsm_guard_id_t guard_id, void * p_data);
+
+static void a_channel_set(void * p_data);
+static void a_short_addr_set(void * p_data);
+static void a_ext_addr_set(void * p_data);
+static void a_pan_id_set(void * p_data);
+static void a_rx_on_idle_set(void * p_data);
+static void a_config_complete(void * p_data);
+static void a_radio_tx_start(void * p_data);
+static void a_radio_tx_restart(void * p_data);
+static void a_uart_tx_start(void * p_data);
+static void a_uart_tx_idle_set(void * p_data);
+#if (CONFIG_SECURE == 1)
+static void a_security_set(void * p_data);
+#endif
+
+static bool gu_set_success(void * p_data);
+static bool gu_send_success(void * p_data);
+static bool gu_uart_tx_data_available(void * p_data);
+static bool gu_radio_tx_idle(void * p_data);
+static bool gu_uart_tx_idle(void * p_data);
+
+static bool frames_available(void);
+
+static void mlme_set_conf_store(fsm_event_data_t * p_data);
+static void mcps_data_ind_store(fsm_event_data_t * p_data);
+static void mcps_data_conf_store(fsm_event_data_t * p_data);
+
+static void mcps_data_conf(mcps_data_conf_t * conf);
+static void mlme_set_conf(mlme_set_conf_t * conf);
+
+static const sys_fsm_transition_t m_transition_table[] =
+{
+ SYS_FSM_STATE ( S_WORKING ),
+ SYS_FSM_TRANSITION( E_SET_DONE, SYS_FSM_ALWAYS, A_CONFIG_COMPLETE, SYS_FSM_SAME_STATE ),
+ SYS_FSM_TRANSITION( E_UART_TX_DONE, GU_UART_TX_DATA_AVAILABLE, A_UART_TX_START, SYS_FSM_SAME_STATE ),
+ SYS_FSM_TRANSITION( E_UART_TX_DONE, SYS_FSM_OTHERWISE, A_UART_TX_IDLE_SET, SYS_FSM_SAME_STATE ),
+ SYS_FSM_TRANSITION( E_UART_RX_DONE, GU_RADIO_TX_IDLE, A_RADIO_TX_START, SYS_FSM_SAME_STATE ),
+ SYS_FSM_TRANSITION( E_RADIO_RX_DONE, GU_UART_TX_IDLE, A_UART_TX_START, SYS_FSM_SAME_STATE ),
+ SYS_FSM_TRANSITION( E_RADIO_TX_DONE, GU_SEND_SUCCESS, A_RADIO_TX_START, SYS_FSM_SAME_STATE ),
+ SYS_FSM_TRANSITION( E_RADIO_TX_DONE, SYS_FSM_OTHERWISE, A_RADIO_TX_RESTART, SYS_FSM_SAME_STATE ),
+
+ SYS_FSM_STATE ( S_INITIAL ),
+ SYS_FSM_TRANSITION( E_START_CONFIG, SYS_FSM_ALWAYS, A_CHANNEL_SET, S_SETTING_CH ),
+
+ SYS_FSM_STATE ( S_SETTING_CH ),
+ SYS_FSM_TRANSITION( E_SET_DONE, GU_SET_SUCCESS, A_SHORT_ADDR_SET, S_SETTING_SHORT_ADDR ),
+
+ SYS_FSM_STATE ( S_SETTING_SHORT_ADDR ),
+ SYS_FSM_TRANSITION( E_SET_DONE, GU_SET_SUCCESS, A_EXT_ADDR_SET, S_SETTING_EXT_ADDR ),
+
+ SYS_FSM_STATE ( S_SETTING_EXT_ADDR ),
+ SYS_FSM_TRANSITION( E_SET_DONE, GU_SET_SUCCESS, A_PAN_ID_SET, S_SETTING_PAN_ID ),
+#if (CONFIG_SECURE == 1)
+ SYS_FSM_STATE ( S_SETTING_PAN_ID ),
+ SYS_FSM_TRANSITION( E_SET_DONE, GU_SET_SUCCESS, A_RX_ON_IDLE_SET, S_SETTING_RX_ON_IDLE ),
+
+ SYS_FSM_STATE ( S_SETTING_RX_ON_IDLE ),
+ SYS_FSM_TRANSITION( E_SET_DONE, GU_SET_SUCCESS, A_SECURITY_SET, S_WORKING ),
+#else
+ SYS_FSM_STATE ( S_SETTING_PAN_ID ),
+ SYS_FSM_TRANSITION( E_SET_DONE, GU_SET_SUCCESS, A_RX_ON_IDLE_SET, S_WORKING ),
+#endif
+};
+
+static const sys_fsm_const_descriptor_t m_fsm_descriptor =
+{
+ FSM_DEBUG_NAME("wi-art fsm")
+
+ /* Pointer to the transition table.*/
+ .transition_table = m_transition_table,
+
+ /* Number of transitions in the transition table. */
+ .transitions_amount = ARRAY_SIZE(m_transition_table),
+
+ /* Initial state ID. */
+ .initial_state = S_INITIAL,
+
+ /* Pointer to the guard condition function */
+ .guard = fsm_guard,
+
+ /* Pointer to the action function */
+ .action = fsm_action
+};
+
+static sys_fsm_t m_fsm;
+static mlme_set_req_t * mp_set_req;
+static mlme_set_conf_t m_set_conf;
+static mcps_data_req_t m_data_req;
+static mcps_data_conf_t m_data_conf;
+static bool m_uart_tx_idle = true;
+static bool m_radio_tx_idle = true;
+static uint8_t m_radio_tx_buffer[PHY_MAX_PACKET_SIZE + MAC_MAX_MHR_SIZE];
+static sequence_number_t tx_sequence_number = 0;
+#if (CONFIG_SECURE == 1)
+static uint8_t m_radio_tx_buffer_shadow[MAX_MSDU_SIZE + MAX_APP_SEQUENCE_NUMBER_SIZE];
+#endif
+static uint8_t m_events = 0;
+static store_data_handler_t event_data_store[EVENTS_AMOUNT] =
+{
+ NULL, // E_START_CONFIG
+ mlme_set_conf_store, // E_SET_DONE
+ mcps_data_ind_store, // E_RADIO_RX_DONE
+ mcps_data_conf_store, // E_RADIO_TX_DONE
+ NULL, // E_UART_RX_DONE
+ NULL, // E_UART_TX_DONE
+ NULL, // E_SECURITY_SET
+};
+static fsm_frame_item_t m_radio_rx_array[CONFIG_POOL_SIZE / (PHY_MAX_PACKET_SIZE + PHY_MAX_HEADER_SIZE) + 1U];
+static size_t m_radio_rx_array_read_index = 0;
+static size_t m_radio_rx_array_write_index = 0;
+
+static const fsm_guard_t m_fsm_guards[] =
+{
+ gu_set_success,
+ gu_send_success,
+ gu_uart_tx_data_available,
+ gu_radio_tx_idle,
+ gu_uart_tx_idle,
+};
+
+static const fsm_action_t m_fsm_actions[] =
+{
+ a_channel_set,
+ a_short_addr_set,
+ a_ext_addr_set,
+ a_pan_id_set,
+ a_rx_on_idle_set,
+ a_config_complete,
+ a_radio_tx_start,
+ a_radio_tx_restart,
+ a_uart_tx_start,
+ a_uart_tx_idle_set,
+#if (CONFIG_SECURE == 1)
+ a_security_set,
+#endif
+};
+
+static void fsm_action(sys_fsm_action_id_t action_id, void * p_data)
+{
+ m_fsm_actions[action_id](p_data);
+}
+
+static bool fsm_guard(sys_fsm_guard_id_t guard_id, void * p_data)
+{
+ return m_fsm_guards[guard_id](p_data);
+}
+
+/* guards */
+
+static bool gu_set_success(void * p_data)
+{
+ if (m_set_conf.status != MAC_SUCCESS)
+ {
+ ASSERT_INFO(0, "Failed to set attribute %02x\n", m_set_conf.pib_attribute.mlme_id);
+ return false;
+ }
+
+ return true;
+}
+
+static bool gu_send_success(void * p_data)
+{
+ return m_data_conf.status == MAC_SUCCESS;
+}
+
+static bool gu_uart_tx_data_available(void * p_data)
+{
+ return frames_available();
+}
+
+static bool gu_radio_tx_idle(void * p_data)
+{
+ return m_radio_tx_idle;
+}
+
+static bool gu_uart_tx_idle(void * p_data)
+{
+ return m_uart_tx_idle;
+}
+
+
+/* actions */
+
+static void a_channel_set(void * p_data)
+{
+ const pib_id_t pib_id =
+ {
+ .plme_id = PHY_CURRENT_CHANNEL_ID,
+ };
+ mp_set_req = (mlme_set_req_t *)sys_mm_alloc(sizeof(mlme_set_req_t));
+ ASSERT(mp_set_req != NULL);
+ mp_set_req->value = (uint8_t *)sys_mm_alloc(mlme_pib_attr_size_calc(pib_id, 0));
+ ASSERT(mp_set_req->value != NULL);
+
+ uint8_t channel = CONFIG_TEST_CHANNEL;
+ mp_set_req->pib_attribute.plme_id = PHY_CURRENT_CHANNEL_ID;
+ mp_set_req->pib_attribute_idx = 0;
+ memcpy(mp_set_req->value, &channel, sizeof(channel));
+ mlme_set_req(mp_set_req, mlme_set_conf);
+}
+
+static void a_short_addr_set(void * p_data)
+{
+ const pib_id_t pib_id =
+ {
+ .mlme_id = MAC_SHORT_ADDRESS,
+ };
+ mp_set_req = (mlme_set_req_t *)sys_mm_alloc(sizeof(mlme_set_req_t));
+ ASSERT(mp_set_req != NULL);
+ mp_set_req->value = (uint8_t *)sys_mm_alloc(mlme_pib_attr_size_calc(pib_id, 0));
+ ASSERT(mp_set_req->value != NULL);
+
+ mp_set_req->pib_attribute.mlme_id = MAC_SHORT_ADDRESS;
+ uint16_t address = CONFIG_DEVICE_SHORT_ADDRESS;
+ memcpy(mp_set_req->value, &address, sizeof(uint16_t));
+ mp_set_req->pib_attribute_idx = 0;
+ mlme_set_req(mp_set_req, mlme_set_conf);
+}
+
+static void a_ext_addr_set(void * p_data)
+{
+ const pib_id_t pib_id =
+ {
+ .mlme_id = MAC_EXTENDED_ADDRESS,
+ };
+ mp_set_req = (mlme_set_req_t *)sys_mm_alloc(sizeof(mlme_set_req_t));
+ ASSERT(mp_set_req != NULL);
+ mp_set_req->value = (uint8_t *)sys_mm_alloc(mlme_pib_attr_size_calc(pib_id, 0));
+ ASSERT(mp_set_req->value != NULL);
+
+ mp_set_req->pib_attribute.mlme_id = MAC_EXTENDED_ADDRESS;
+
+ // sum is for device address uniqueness
+ uint64_t address = CONFIG_IEEE_ADDRESS + CONFIG_DEVICE_SHORT_ADDRESS;
+ memcpy(mp_set_req->value, &address, sizeof(uint64_t));
+ mp_set_req->pib_attribute_idx = 0;
+ mlme_set_req(mp_set_req, mlme_set_conf);
+}
+
+static void a_pan_id_set(void * p_data)
+{
+ const pib_id_t pib_id =
+ {
+ .mlme_id = MAC_PAN_ID,
+ };
+ mp_set_req = (mlme_set_req_t *)sys_mm_alloc(sizeof(mlme_set_req_t));
+ ASSERT(mp_set_req != NULL);
+ mp_set_req->value = (uint8_t *)sys_mm_alloc(mlme_pib_attr_size_calc(pib_id, 0));
+ ASSERT(mp_set_req->value != NULL);
+
+ mp_set_req->pib_attribute.mlme_id = MAC_PAN_ID;
+
+ uint16_t panid = CONFIG_PAN_ID;
+ memcpy(mp_set_req->value, &panid, sizeof(uint16_t));
+ mp_set_req->pib_attribute_idx = 0;
+ mlme_set_req(mp_set_req, mlme_set_conf);
+}
+
+static void a_rx_on_idle_set(void * p_data)
+{
+ const pib_id_t pib_id =
+ {
+ .mlme_id = MAC_RX_ON_WHEN_IDLE,
+ };
+ mp_set_req = (mlme_set_req_t *)sys_mm_alloc(sizeof(mlme_set_req_t));
+ ASSERT(mp_set_req != NULL);
+ mp_set_req->value = (uint8_t *)sys_mm_alloc(mlme_pib_attr_size_calc(pib_id, 0));
+ ASSERT(mp_set_req->value != NULL);
+
+ mp_set_req->pib_attribute.mlme_id = MAC_RX_ON_WHEN_IDLE;
+ uint8_t rx_on = 1;
+ memcpy(mp_set_req->value, &rx_on, sizeof(uint8_t));
+ mlme_set_req(mp_set_req, mlme_set_conf);
+}
+
+static void a_radio_tx_start(void * p_data)
+{
+ m_radio_tx_idle = false;
+
+ const hal_uart_descriptor_t * p_descr = uart_descr_get();
+ size_t sz = hal_uart_read_buffer_size_get(p_descr);
+
+ LEDS_OFF(BIT(CONFIG_UPSTREAM_PIN));
+
+ if (sz > MAX_MSDU_SIZE)
+ {
+ sz = MAX_MSDU_SIZE;
+ }
+
+ if (sz > 0)
+ {
+ hal_uart_read(p_descr, &m_radio_tx_buffer[PAYLOAD_START_POSITION], sz);
+ memcpy(&m_radio_tx_buffer[COUNTER_POSITION], &tx_sequence_number, MAX_APP_SEQUENCE_NUMBER_SIZE);
+#if (CONFIG_SECURE == 1)
+ memcpy(m_radio_tx_buffer_shadow, &m_radio_tx_buffer[COUNTER_POSITION],
+ sz + MAX_APP_SEQUENCE_NUMBER_SIZE);
+#endif
+
+ m_data_req.dst_addr_mode = MAC_ADDR_SHORT;
+ m_data_req.dst_addr.short_address = CONFIG_OTHER_ADDRESS;
+ m_data_req.dst_pan_id = CONFIG_PAN_ID;
+ m_data_req.src_addr_mode = MAC_ADDR_SHORT;
+ m_data_req.msdu = (uint8_t *)&m_radio_tx_buffer[MAC_MAX_MHR_SIZE];
+ m_data_req.msdu_length = sz + MAX_APP_SEQUENCE_NUMBER_SIZE;
+ m_data_req.msdu_handle++;
+ m_data_req.tx_options.ack = true;
+ m_data_req.tx_options.gts = false;
+ m_data_req.tx_options.indirect = false;
+#if (CONFIG_SECURE == 1)
+ m_data_req.security_level = CONFIG_DATA_SECURITY_LEVEL;
+ m_data_req.key_id_mode = 0;
+#endif
+ mcps_data_req(&m_data_req, mcps_data_conf);
+
+ LEDS_ON(BIT(CONFIG_UPSTREAM_PIN));
+ }
+ else
+ {
+ m_radio_tx_idle = true;
+ }
+}
+
+static void a_config_complete(void * p_data)
+{
+ LEDS_ON(BIT(CONFIG_INIT_DONE_PIN));
+}
+
+static void a_radio_tx_restart(void * p_data)
+{
+#if (CONFIG_SECURE == 1)
+ /** This is necessary because data in m_radio_tx_buffer had been already ciphered. */
+ memcpy(&m_radio_tx_buffer[COUNTER_POSITION], m_radio_tx_buffer_shadow, m_data_req.msdu_length);
+#endif
+ m_data_req.msdu_handle++;
+ mcps_data_req(&m_data_req, mcps_data_conf);
+ LEDS_ON(BIT(CONFIG_UPSTREAM_PIN));
+}
+
+static bool frames_available(void)
+{
+ return m_radio_rx_array_read_index != m_radio_rx_array_write_index;
+}
+
+static void frame_store(fsm_frame_item_t * p_frame)
+{
+ m_radio_rx_array[m_radio_rx_array_write_index++] = *p_frame;
+ if (m_radio_rx_array_write_index == ARRAY_SIZE(m_radio_rx_array))
+ {
+ m_radio_rx_array_write_index = 0;
+ }
+ ASSERT(frames_available());
+}
+
+static fsm_frame_item_t * next_frame_get(void)
+{
+ ASSERT(frames_available());
+ fsm_frame_item_t * result = &m_radio_rx_array[m_radio_rx_array_read_index++];
+ if (m_radio_rx_array_read_index == ARRAY_SIZE(m_radio_rx_array))
+ {
+ m_radio_rx_array_read_index = 0;
+ }
+ return result;
+}
+
+static void a_uart_tx_start(void * p_data)
+{
+ ASSERT(frames_available());
+
+ fsm_frame_item_t * p_fsm_frame = next_frame_get();
+ const hal_uart_descriptor_t * p_uart_descr = uart_descr_get();
+
+ hal_uart_write(p_uart_descr,
+ p_fsm_frame->payload_descr.p_payload + MAX_APP_SEQUENCE_NUMBER_SIZE,
+ p_fsm_frame->length - MAX_APP_SEQUENCE_NUMBER_SIZE);
+
+ mac_mem_msdu_free(&p_fsm_frame->payload_descr);
+
+ m_uart_tx_idle = false;
+
+ LEDS_ON(BIT(CONFIG_DOWNSTREAM_PIN));
+
+ (void)p_data;
+}
+
+static void a_uart_tx_idle_set(void * p_data)
+{
+ m_uart_tx_idle = true;
+}
+
+#if (CONFIG_SECURE == 1)
+static void a_security_set(void * p_data)
+{
+ security_tables_init();
+ fsm_event_post(E_SECURITY_SET, NULL);
+}
+#endif
+
+
+/* callback functions */
+
+static void mlme_set_conf(mlme_set_conf_t * conf)
+{
+ fsm_event_data_t data =
+ {
+ .mlme_set = conf,
+ };
+ fsm_event_post(E_SET_DONE, &data);
+
+ sys_mm_free(mp_set_req->value);
+ sys_mm_free(mp_set_req);
+}
+
+static void mcps_data_conf(mcps_data_conf_t * conf)
+{
+ fsm_event_data_t data =
+ {
+ .mcps_data_conf = conf
+ };
+ if (conf->status == MAC_SUCCESS)
+ {
+ tx_sequence_number++;
+ }
+ fsm_event_post(E_RADIO_TX_DONE, &data);
+ LEDS_OFF(BIT(CONFIG_UPSTREAM_PIN));
+}
+
+
+/* storing functions */
+
+static void mlme_set_conf_store(fsm_event_data_t * p_data)
+{
+ if (p_data != NULL)
+ {
+ m_set_conf = *p_data->mlme_set;
+ }
+}
+
+static void mcps_data_ind_store(fsm_event_data_t * p_data)
+{
+ mcps_data_ind_t * p_frame = p_data->mcps_data_ind;
+ fsm_frame_item_t fsm_frame;
+
+ fsm_frame.payload_descr = p_frame->msdu;
+ fsm_frame.length = p_frame->msdu_length;
+ frame_store(&fsm_frame);
+}
+
+static void mcps_data_conf_store(fsm_event_data_t * p_data)
+{
+ m_data_conf = *p_data->mcps_data_conf;
+}
+
+/* interface functions */
+
+void fsm_init(void)
+{
+ sys_fsm_init(&m_fsm, &m_fsm_descriptor);
+ m_radio_rx_array_read_index = 0;
+ m_radio_rx_array_write_index = 0;
+}
+
+void fsm_event_post(fsm_events_t event, fsm_event_data_t * p_data)
+{
+ m_events |= BIT(event);
+ if (event_data_store[event] != NULL)
+ {
+ event_data_store[event](p_data);
+ }
+
+ sys_task_post(APP_TASK_ID);
+}
+
+void fsm_event_scheduler_run(void)
+{
+ for (uint8_t event_id = 0; event_id < EVENTS_AMOUNT; event_id++)
+ {
+ uint8_t mask = BIT(event_id);
+ if (m_events & mask)
+ {
+ m_events ^= mask;
+ sys_fsm_event_post(&m_fsm, (fsm_events_t)event_id, NULL);
+ }
+ }
+
+ if (m_events)
+ {
+ sys_task_post(APP_TASK_ID);
+ }
+}
+