epm/User/lib/src/data_analysis.c

351 lines
9.5 KiB
C

/*
* @Author: shenghao.xu
* @Date: 2023-04-04 08:38:59
* @LastEditors: shenghao.xu
* @LastEditTime: 2023-04-04 11:31:35
* @Description:
* email:545403892@qq.com
* Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
*/
#include <string.h>
#include "../inc/data_analysis.h"
#include "../inc/sqqueue.h"
#include "../inc/debug.h"
typedef uint8_t data_entry_t;
typedef void (*state_t)(uint8_t data_id, uint8_t sig, uint8_t ch);
typedef enum _event /* enumeration */
{
SD_SIG,
LD_SIG,
CHAR_SIG,
ED_SIG,
} sig_event;
typedef struct _fsm_t_
{
state_t current_state;
} fsm_t;
typedef struct _DATA_frm_t_
{
uint8_t sd_index;
struct
{
uint8_t data[DATA_LD_LEN_MAX];
uint8_t index;
uint16_t frm_len;
} ld; // length describe
uint16_t payload_len; // actually len of recvived data
uint8_t ed_index;
uint16_t last_enter_q_num; // record the num of frames has entered the queue
uint8_t locked;
uint8_t sig;
} data_frm_t;
#define TRAN(state) (fsm[data_id].current_state = (state_t)(state))
#define FSM_DISPATCH(data_id, sig, ch) (fsm[data_id].current_state((data_id), (sig), (ch)))
static fsm_t fsm[DATA_NUM] = {0};
static data_frm_t data_frm_array[DATA_NUM];
static data_reg_t data_reg_array[DATA_NUM];
static sqqueue_ctrl_t data_recv_sqq[DATA_NUM];
static void wait_sd_state(uint8_t data_id, uint8_t sig, uint8_t ch);
/************************************************************/
void lock_data(uint8_t data_id)
{
data_frm_array[data_id].locked = true;
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]);
}
data_frm_array[data_id].last_enter_q_num = 0;
data_frm_array[data_id].sd_index = 0;
data_frm_array[data_id].ed_index = 0;
data_frm_array[data_id].ld.frm_len = 0;
data_frm_array[data_id].payload_len = 0;
TRAN(wait_sd_state);
}
void unlock_data(uint8_t data_id)
{
TRAN(wait_sd_state);
data_frm_array[data_id].last_enter_q_num = 0;
data_frm_array[data_id].sd_index = 0;
data_frm_array[data_id].ed_index = 0;
data_frm_array[data_id].ld.frm_len = 0;
data_frm_array[data_id].payload_len = 0;
data_frm_array[data_id].locked = false;
}
static void end_state_handle(uint8_t data_id, uint8_t sig, uint8_t ch)
{
TRAN(wait_sd_state);
data_frm_array[data_id].ld.frm_len = 0;
data_frm_array[data_id].payload_len = 0;
data_frm_array[data_id].last_enter_q_num = 0;
if (data_reg_array[data_id].func_ptr != NULL)
{
(*(data_reg_array[data_id].func_ptr))();
}
}
static void wait_end_state(uint8_t data_id, uint8_t sig, uint8_t ch)
{
if (!data_reg_array[data_id].ed.valid)
{
if (data_frm_array[data_id].ld.frm_len == 0)
{
TRAN(wait_sd_state);
end_state_handle(data_id, sig, ch);
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]);
}
data_frm_array[data_id].last_enter_q_num = 0;
}
else
{
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
data_frm_array[data_id].last_enter_q_num++;
if (++data_frm_array[data_id].payload_len ==
data_frm_array[data_id].ld.frm_len)
{
end_state_handle(data_id, sig, ch);
}
}
else
{
lock_data(data_id);
}
}
}
else
{
if (data_frm_array[data_id].ld.frm_len == 0)
{
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
data_frm_array[data_id].last_enter_q_num++;
if (data_reg_array[data_id].ed.data[0] == ch)
{
end_state_handle(data_id, sig, ch);
}
}
else
{
lock_data(data_id);
}
}
else
{
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
data_frm_array[data_id].last_enter_q_num++;
if (++data_frm_array[data_id].payload_len >=
data_frm_array[data_id].ld.frm_len - data_reg_array[data_id].ld.pos)
{
if (data_reg_array[data_id].ed.data[0] == ch)
{
end_state_handle(data_id, sig, ch);
}
}
}
else
{
lock_data(data_id);
}
}
}
}
static void wait_ld_state(uint8_t data_id, uint8_t sig, uint8_t ch)
{
if (!data_reg_array[data_id].ld.valid)
{
TRAN(wait_end_state);
FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch);
return;
}
data_frm_array[data_id].ld.data[data_frm_array[data_id].ld.index++] = ch;
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
data_frm_array[data_id].last_enter_q_num++;
if (data_frm_array[data_id].ld.index == data_reg_array[data_id].ld.len)
{
if (data_reg_array[data_id].ld.little_endian == true)
{
data_frm_array[data_id].ld.frm_len =
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 1] * 256 +
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 2];
}
else
{
data_frm_array[data_id].ld.frm_len =
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 2] * 256 +
data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 1];
}
if (data_reg_array[data_id].ld.len == 1) // 只有1个字节长度的数据
{
data_frm_array[data_id].ld.frm_len = data_frm_array[data_id].ld.data[0];
}
if ((data_frm_array[data_id].ld.frm_len > data_reg_array[data_id].argu.len_max) || (data_frm_array[data_id].ld.frm_len < data_reg_array[data_id].argu.len_min))
{
data_frm_array[data_id].ld.index = 0;
TRAN(wait_sd_state);
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]);
}
data_frm_array[data_id].ld.frm_len = 0;
data_frm_array[data_id].last_enter_q_num = 0;
}
else
{
data_frm_array[data_id].ld.index = 0;
TRAN(wait_end_state);
}
}
}
else
{
lock_data(data_id);
}
}
static void wait_sd_state(uint8_t data_id, uint8_t sig, uint8_t ch)
{
if (!data_reg_array[data_id].sd.valid)
{
TRAN(wait_ld_state);
FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch);
return;
}
if (data_reg_array[data_id].sd.data[data_frm_array[data_id].sd_index++] == ch)
{
if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch))
{
data_frm_array[data_id].last_enter_q_num++;
if (data_frm_array[data_id].sd_index == data_reg_array[data_id].sd.len)
{
data_frm_array[data_id].sd_index = 0;
TRAN(wait_ld_state);
}
}
else
{
lock_data(data_id);
}
}
else
{
for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++)
{
data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]);
}
data_frm_array[data_id].sd_index = 0;
data_frm_array[data_id].last_enter_q_num = 0;
}
}
static void data_char_handle(uint8_t data_id, uint8_t ch)
{
if (data_reg_array[data_id].echo_en)
{
data_write(data_id, &ch, 1);
}
FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch);
}
data_interupt_cb_t data_fsm_init(uint8_t data_id)
{
TRAN(wait_sd_state);
data_reg_array[data_id].func_ptr = NULL;
memset(&data_frm_array[data_id], 0, sizeof(data_frm_t));
data_frm_array[data_id].sig = CHAR_SIG;
if (sqqueue_ctrl_init(&data_recv_sqq[data_id],
sizeof(data_entry_t),
DATA_BUF_RECV_SQQ_LEN) == false)
{
DBG_ASSERT(false __DBG_LINE);
}
return data_char_handle;
}
uint8_t data_read(uint8_t id, void *buffer, uint16_t len)
{
uint8_t i = 0;
data_entry_t e;
uint8_t *buf = (uint8_t *)buffer;
if (data_recv_sqq[id].get_len(&data_recv_sqq[id]) >= len)
{
for (i = 0; i < len; i++)
{
e = *((data_entry_t *)data_recv_sqq[id].del(&data_recv_sqq[id]));
buf[i] = e;
}
}
else
{
while ((data_recv_sqq[id].get_len(&data_recv_sqq[id]) != 0) && (i < len))
{
e = *((data_entry_t *)data_recv_sqq[id].del(&data_recv_sqq[id]));
buf[i++] = e;
}
}
if (data_frm_array[id].locked)
{
unlock_data(id);
}
return i;
}
void data_write(uint8_t id, uint8_t *const string, uint16_t len)
{
}
bool data_reg(uint8_t id, data_reg_t reg)
{
if (data_reg_array[id].func_ptr == NULL)
{
memcpy((void *)&data_reg_array[id], (void *)&reg, sizeof(reg));
return true;
}
else
{
return false;
}
}
void data_unreg(uint8_t id)
{
memset((void *)&data_reg_array[id], 0, sizeof(data_reg_t));
data_reg_array[id].func_ptr = NULL;
}