/* * @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 #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 *)®, 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; }