#include <stdint.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <hw/inout.h>
#include <time.h>
#include <fcntl.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>
#include <sys/mman.h>

#include <forksafe_mutex.h>
#include <pthread.h>
#include <threads.h>

#include <net/if.h>
#include <sys/ioctl.h>
#include <devctl.h>

#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if_media.h>
#include <net/if_ether.h>

/*双系脉冲通信信号类型定义*/
typedef enum {     //占空比-频率
    ABSynMsgType_0,//0.0-0,ErrorDuty-ErrorFrequency固定为驱动程序检测到以下故障中的一种：a、未收到有效的PWM信号(包含：无PWM信号、信号参数不符合预设的范围)
    ABSynMsgType_1,//0.5-200 固定为驱动程序检测到以下故障中的一种：a、发送端的MsgType不是规定的枚举类型;
    ABSynMsgType_2,//0.5-300 固定为驱动程序检测到以下故障中的一种：a、双系PWM信号使能标志没有周期翻转(main函数跑飞);
    ABSynMsgType_3,//0.5-400 平台自由确定其含义
    ABSynMsgType_4,//0.5-500 平台自由确定其含义
    ABSynMsgType_5,//0.5-600 平台自由确定其含义
    ABSynMsgType_6,//0.5-700 平台自由确定其含义
    ABSynMsgType_7,//0.5-800 平台自由确定其含义
    ABSynMsgType_MAX = 0x08
} ABSynMsgType;

struct SCapInfo{
    uint8_t vaild;//0无效 1有效
    uint8_t isLocked;//1锁定
    uint32_t capCount;
    uint32_t cap1StartTime;      //first rising
    uint32_t cap1CurrentTime;      //first falling
    uint32_t cycle;         //周期
    uint32_t pulseWidth;    //脉宽
    float dutyCycle;        //占空比
    float fre;           //频率
};


#define  READ_PHY_REG   0x400U

typedef struct {
		uint8_t  phy_id;
        uint8_t  phy_reg;
        uint16_t phy_data;
}phy_access_t;


#define IMX_GPIO0_BASE                         0x5D080000
#define IMX_GPIO1_BASE                         0x5D090000
#define IMX_GPIO2_BASE                         0x5D0A0000
#define IMX_GPIO3_BASE                         0x5D0B0000
#define IMX_GPIO4_BASE                         0x5D0C0000
#define IMX_GPIO5_BASE                         0x5D0D0000
#define IMX_GPIO6_BASE                         0x5D0E0000
#define IMX_GPIO7_BASE                         0x5D0F0000

#define IMX_GPIO_DR            0x0U
#define IMX_GPIO_GDIR          0x4U
#define IMX_GPIO_PSR           0x8U
/*20250707--zhangzhongqi add*/
#define IMX_GPIO_ICR1          0xCU
#define IMX_GPIO_ICR2          0x10U
#define IMX_GPIO_IMR           0x14U
#define IMX_GPIO_ISR           0x18U
#define IMX_GPIO_EDGE_SEL      0x1CU
#define IMX_GPIO_SIZE          0x20U


#define IMX_GPIO0_IRQ          168
#define IMX_GPIO1_IRQ          169

/*timer regisger */
#define IMX_GPT0_BASE    	0x5D140000
#define IMX_GPT_SIZE     	0x10000
#define IMX_GPT0_IRQ     	112
#define GPT_CR              0x00U
#define GPT_PR              0x04U
#define GPT_SR              0x08U
#define GPT_IR              0x0cU
#define GPT_OCR1            0x10U
#define GPT_CNT             0x24U

#define OFF    0
#define GREEN  1
#define RED    2
#define YELLOW 3

extern char drv_vsr[4];

int imx8_gpio_init(void);
int imx8_input_collect(int channel);
int imx8_output(int channel, int level);
int imx8_gpio_release(void);
int imx8_led_REA_REB(int light);
int imx8_led_R_E(int light);
int imx8_led_M_S(int light);

unsigned int imx8_read_cpuid(void);
int imx8_dcdc_1_ctrl(int level);
int imx8_dcdc_2_ctrl(int level);
unsigned int imx8_Safe_gate_overvoltage_state_1(void);
unsigned int imx8_Safe_gate_undervoltage_state_1(void);
unsigned int imx8_Safe_gate_overvoltage_state_2(void);
unsigned int imx8_Safe_gate_undervoltage_state_2(void);
unsigned int imx8_ethernet_switch_state_1_1(void);
unsigned int imx8_ethernet_switch_state_1_2(void);
unsigned int imx8_ethernet_switch_state_2_1(void);
unsigned int imx8_ethernet_switch_state_2_2(void);
unsigned int imx8_24V_voltage_state(void);
unsigned int imx8_5V_overvoltage_state(void);
unsigned int imx8_5V_undervoltage_state(void);
unsigned char imx8_read_boardID(void);
int imx8_switch_button(void);
int imx8_safty_ethernet_off(void);



int imx8_create_timer_pthread_25(void);
int imx8_create_timer_pthread(void);
const struct sigevent *handler_25 (void *not_used, int id);
const struct sigevent *handler (void *not_used, int id);
void* timer_25( void * arg);
void* timer( void * arg);

/*  函数功能：创建脉冲检测中断线程
 *  输入参数：void
 *  输出参数：无。
 *  返回值    ：无。
 *  使用注意：板级初始化之后调用一次该函数启动功能。
 */
int imx8_create_gpio_irq_pthread(void);
/*  函数功能：发送双系硬通信信号。
 *  输入参数：MsgType：硬通信的信息：ABSynMsgType_0..ABSynMsgType_7
 *  输出参数：无。
 *  返回值    ：无。
 *  使用注意：倒切方案由于硬件限制，发送频率不高于500Hz,最大使用ABSynMsgType_4。
 */
void drvSetABSynMsg(ABSynMsgType MsgType);
/*  函数功能：获取对系双通道硬通信信号。
 *  输入参数：无。
 *  输出参数：pMsgType[0]:对方A系发出的硬通信信息:ABSynMsgType_0..ABSynMsgType_15
 *         pMsgType[1]：对方B系发出的硬通信信息：ABSynMsgType_0..ABSynMsgType_15
 *         pPulseCnt[0]:收到对方A系发出的脉冲计数,如果此数为0，说明对方A系停止输出脉冲
 *         pPulseCnt[1]:收到对方B系发出的脉冲计数,如果此数为0，说明对方B系停止输出脉冲
 *  返回值    ：无。
 */
void drvGetABSynMsg(ABSynMsgType *pMsgType,uint32_t* pPulseCnt);
/*  函数功能：双系心跳信号功能开启。
 *  输入参数：无。
 *  输出参数：无。
 *  返回值    ：无。
 *  使用注意：板级初始化之后调用一次该函数启动功能。
 */
void drvStartABSynSwitch(void);

/*  函数功能：双系心跳信号功能关闭
 *  输入参数：无。
 *  输出参数：无。
 *  返回值    ：无。
 *  使用注意：
 */
void drvStopABSynSwitch(void);

/*  函数功能：获取双系硬通信的反馈。
 *  输入参数：无。
 *  输出参数：pABSynMsgType *pMsgType,   采集到的type信息
 *  返回值    ：UINT8,
 *            0x00,正常。
 *            0x81,命令与反馈不一致
 *            0x82,指针为空
 *  使用注意：发送与采集间隔至少为40ms。
 */
uint8_t drvFeedbackkABSynMsg(ABSynMsgType *pMsgType);

/*  函数功能：获取当前系间信号脉冲的最大误差值。
 *  输入参数：uint8_t index
 *  输出参数：无
 *  返回值    ：float -- 误差百分比。
 */
float drvGetSyncSigErr(ABSynMsgType msgType);

/*  函数功能：查询当前各通道收到的外部脉冲个数。
 *  输入参数：无。
 *  输出参数： uint8_t index -- 通道索引：0-自身反馈通道 1-对方A系通道 2-对方B系通道
 *          uint32_t* pPulseCnt -- 外部存储变量地址
 *  返回值    ：uint8_t 0-成功   1-失败：入参错误。
 */
uint8_t drvCheckABSynPulCnt(uint8_t index,uint32_t* pPulseCnt);


/************************************************************************/
/*
* @brief 读取phy寄存器相关维护信息
*
* 该函数通过创建套接字并发送SIOCGDRVSPEC控制命令，读取指定网络接口的PHY寄存器状态
*
* @param[in]
* 	const char* fecx 需要检查的网络接口名称（如"fec0","fec1"）
* 	uint16_t infoLen - 寄存器信息数组长度，此长度应该大于等于12
* @param[out]
*   uint16_t * Info - 寄存器信息数组存储首地址
* @return rtn 返回状态
*   - n: n为实际读取的寄存器个数
*   - -1: 链路异常或操作失败
*
*/
int drvPhyRegInfoUpdate(const char* fecx,uint16_t *Info,uint16_t infoLen);

/************************************************************************/
/*
* @brief 通过PHY寄存器检查指定网卡链路状态
*
* 该函数通过创建套接字并发送SIOCGDRVSPEC控制命令，读取指定网络接口的PHY寄存器状态，
* 根据寄存器值的特定位判断链路是否正常。
*
* @param[in] fecx 需要检查的网络接口名称（如"fec0","fec1"）
* @return rtn 返回状态
*   - 0: 链路状态正常（PHY寄存器bit2为1）
*   - -1: 链路异常或操作失败
*
* @note 函数执行流程：
*   1. 创建UDP套接字
*   2. 配置phycmd控制结构体：
*      - ifd_name: 网络接口名称
*      - ifd_cmd: 使用READ_PHY_REG命令
*      - phy_id: PHY地址7
*      - phy_reg: 寄存器地址1（状态寄存器）
*   3. 通过devctl发送控制命令
*   4. 解析phy_data寄存器值的bit2判断链路状态
*/
int phytool(const char* fecx);
