/*
 * SFM_Area.h
 *
 *  Created on: 2025年8月28日
 *      Author: hisun
 */

#ifndef MSCP_SFM_SFM_AREA_H_
#define MSCP_SFM_SFM_AREA_H_
#include "CM_Mutex.h"
#include "MSCP_APP_Interface.h"
#include "CM_Sem.h"
#include "CM_MultiThread.h"
#include "CM_MQ.h"
#include "PFM_Log.h"
#include "CFM_Net.h"
#include "CM_Convert.h"
#include "DFM_DRV.h"

extern CM_UINT32 g_MSCP_AreaCount;


/**
 * 区域数据中状态部分结构
 * 1字节板卡ID
 * 1字节区域状态
 * 1字节2x状态
 * 4字节周期号
 */
#define AREA_DATA_STATE_LEN          (7)

#define MSCP_AREA_OVER_TIME (g_PFM_Cfg.CYC_TIME) 	/*区域协程判断数据超时时间*/

typedef enum{
    ENUM_AREA_MSG_SLAVE = 0,
    ENUM_AREA_MSG_MASTER,
    ENUM_AREA_MSG_ERROR
}ENUM_AREA_MSG_T;

typedef enum{
    ENUM_2x2_AREA_MSG_DATA = 0,
}ENUM_2x2_AREA_MSG_T;

typedef struct
{
    CM_SEM_T m_Start;  	 /* 2x状态切换开始信号量 */
    CM_SEM_T m_Stop;   	 /* 2x状态切换结束信号量 */
    CM_MUTEX_T mutex;    /**< 互斥信号量 */
    CM_MQ_Struct_T LogMsgQ; /**< 日志消息队列 */
}STRU_AREA_THREAD_T;

/*2x状态切换线程参数*/
typedef struct
{
    CM_UINT32 SysCyc;		/**< 系统区域周期号 */

    /*区域状态*/
    ENUM_AREA_STATE_T LocalAreaState;  	   /**< 本区域状态*/
    ENUM_AREA_STATE_T LastLocalAreaState;   /**< 本上一周期的区域状态*/
    ENUM_AREA_STATE_T AnotherAreaState;     /* 另一区域状态*/
    ENUM_AREA_STATE_T LastAnotherAreaState;   /* 另一区域上一周期状态*/

    /* 记录区域状态发送板卡ID（与脉冲比较）*/
    CM_UINT8 AnotherBoardID;

    /* 2x状态 */
    ENUM_2x2_STATE_T Local2x2State;         /**< 本系2x热备状态 */
    ENUM_2x2_STATE_T Partner2x2State;       /**< 对系2x热备状态 */

    /* 时间同步标志*/
    CM_UINT8 TimeSyncFlag_Area;
    CM_UINT8 TimeSyncFlag_2x2;

    /* 接收周期号*/
    CM_UINT32 RxAreaSysCyc;
    CM_UINT32 Rx2x2DataSysCyc;

    /* 区域接收完成标志位*/
    CM_UINT8 AreaRecved;
    CM_UINT8 AreaAppRecved;
    
    CM_UINT8 AllInterrupt;      /* 脉冲与udp均中断标志*/

    CM_UINT8 RCFollowFlag;      /* 周期末交给应用进行跟随，返回失败*/

    /*脉冲信号*/
    ENUM_PULSE_TYPE_T pulse;       /* 另一区域脉冲，设置时通过板卡ID区分A系还是B系*/
    ENUM_PULSE_TYPE_T pulseA;       /* 另一区域脉冲，设置时通过板卡ID区分A系还是B系*/
    ENUM_PULSE_TYPE_T pulseB;       /* 另一区域脉冲，设置时通过板卡ID区分A系还是B系*/

    /*主系通信失败，备系成功标志*/
    CM_UINT8 flag_Mf_Ss;

    /* 允许升主标志*/
    CM_UINT8 isAllowed;         /* 0u不允许升主，1u允许升主（计数足够）*/
    /* 升主计数*/
    CM_UINT32 WaitCounter;
    /* 倒切按钮状态*/
    ENUM_SWITCH_MODE_T AreaSwitchMode;
    /* 亚健康标志，0亚健康，1正常（脉冲与UDP接收状态不一致，亚健康，以UDP接收状态为准，且可维持备用，仅不能备升主用）*/
    CM_UINT8 healthFlag[3];     /* 记录最近三周期脉冲与通信健康状况，0为当前周期，1为上周期，2为上上周期，值0亚健康，1健康*/
}STRU_AREA_STATE_CTRL_T;

/**
 * 发送起始信号量
 */
void SFM_AREA_Thread_PostStart(void);
/**
 * 等待结束信号量
 */
void SFM_AREA_Thread_WaitStop(void);
/**
* @brief 时间同步失败清空消息队列
* @param 无
* @return 无
*/
void SFM_AREA_ClearRcvMsgQ(void);
/**
* @brief 时间同步失败清空消息队列
* @param 无
* @return 无
*/
void SFM_2X2_AREA_ClearRcvMsgQ(void);
/**
 * 初始化
 */
void SFM_Area_Init(void);
/**
* @brief 区域发送
* @param Data 发送报文指针
* @param DataLen 发送报文长度
* param msgType 报文类型
* @details
* @see :: s_2x2_Recv
* @see :: SFM_FrameSave
*/
void SFM_AREA_Send(IN const CM_UINT8 *Data, IN CM_UINT32 DataLen, IN ENUM_AREA_MSG_T msgType);
/**
* @brief 区域发送
* @param Data 发送报文指针
* @param DataLen 发送报文长度
* param msgType 报文类型
* @details
* @see :: s_2x2_Recv
* @see :: SFM_FrameSave
*/
void SFM_2x2_AREA_Send(IN const CM_UINT8 *Data, IN CM_UINT32 DataLen, IN ENUM_2x2_AREA_MSG_T msgType);
/**
 * 获取区域数据缓冲区指针
 */
CM_UINT32 SFM_GetAreaData(OUT CM_UINT8** data);
/* 区域状态切换 必须在2x线程结束后进行*/
void SFM_Area_State_Transition(void);
/*日志转换*/
void SFM_AREA_LOG_Transition(void);
/*协程状态控制接口*/
STRU_AREA_STATE_CTRL_T* SFM_Area_BackPointer_Ctrl(void);
/* 根据状态设置脉冲*/
void SFM_SetPulse(ENUM_AREA_STATE_T state);
/* 根据状态设置主备用灯*/
void SFM_SetAreaLed(ENUM_AREA_STATE_T state);
/* 获取接收到的周期号*/
CM_UINT32 SFM_Area_GetRxSysCount();
/* 获取区域周期号*/
CM_UINT32 SFM_Area_GetSysCount(void);
/**
 * @brief 周期末区域同步
 * @param CI_Buf CI待发送区域数据
 * @param buf_len CI_Buf待发送数据长度
 * @param buf_size CI_Buf缓冲区最大容量
 * */
void SFM_Area_EndProc(CM_UINT8* CI_Buf, CM_INT32 buf_len, CM_UINT32 buf_size);
/**
 * @brief 同步周期号
 */
void SFM_Area_UpdateCYC(void);





#endif /* MSCP_SFM_SFM_AREA_H_ */
