/*****************************************************************************
 * file    lib/process/pd_dau.c  
 * author  YuLiang
 * version 1.0.0
 * date    03-Feb-2023
 * brief   This file provides all the dau related operation functions.
 ******************************************************************************
 * Attention
 *
 * 
© COPYRIGHT(c) 2021 LandPower
 *
 * 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 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 LandPower nor the names of its contributors may be used to 
 *      endorse or promote products derived from this software without specific
 *      prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 *
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#ifdef CFG_DEV_TYPE_LAND_PD
#define _USE_MATH_DEFINES
/* 标准C库头文件. */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "vty.h"
#include "cmd.h"
#include "fifo.h"
#include "mtimer.h"
#include "hwgpio.h"
#include "main.h"
#include "pd_main.h"
#include "pd_csg.h"
#include "pd_dau.h"
#include "u-dma-buf-ioctl.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define DAU_CODE 0x0701
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
dau_ctrl_t dau_ctrl={0,0,};
dau_t *dau[PD_DAU_SUM];
int16_t test_data[20000];
/* Private function prototypes -----------------------------------------------*/
extern int32_t _dau_add(uint8_t unit, uint8_t port_num);
extern void _dau_del(uint8_t unit);
/* DAU 端口类型分类 */
//static const char *dau_port_type_str[PD_PORT_TYPE_COUNT] =
//{
//    "",
//    "uhf",
//};
/* DAU 端口状态分类. */
static const char *pd_port_status_str[PD_PORT_STATUS_COUNT] =
{
    "disable",
    "enable"
};
// /* Internal functions --------------------------------------------------------*/
// /* 添加 DAU 模块命令 */
// CMD(dau_add, 
//     dau_add_cmd,
//     "dau <1-1> port-num <1-8>",
//     "DAU\n"
//     "Unit id\n"
//     "Port\n"
//     "Port number\n")
// {
//     uint8_t unit = 0;
//     uint8_t port_num = 0;
    
//     unit = strtol(argv[0], NULL, 10) - 1;
//     port_num = strtol(argv[1], NULL, 10);
//     _dau_add(unit, port_num);
        
//     return CMD_SUCCESS;
// }
// /* 删除 DAU 模块命令 */
// CMD(no_dau_add, 
//     no_dau_add_cmd,
//     "no dau <1-1>",
//     "no\n"
//     "DAU\n"
//     "Unit id\n"
//     "Port\n"
//     "Port number\n")
// {
//     uint8_t unit = 0;
    
//     unit = strtol(argv[0], NULL, 10) - 1;
//     _dau_del(unit);
        
//     return CMD_SUCCESS;
// }
/* 显示 DAU 状态. */
CMD(show_dau_status_all,
    show_dau_status_all_cmd,
    "show dau",
    "Show\n"
    "DAU\n")
{
    uint8_t unit = 0;
    
    for(unit = 0; unit < PD_DAU_SUM; unit++)
    {
        dau_show(unit);
    }
    return CMD_SUCCESS;
}
/* 端口使能配置. */
CMD(pd_port_status,
    pd_port_status_cmd,
    "port-status (enable|disable)",
    "Port\n"
    "Status\n"
    "enable|disable\n")
{
    uint8_t port_status = 0;
    uint8_t unit = 0;
    uint8_t port = 0;
    uint32_t reg_value;
    dau_t * dau_node = NULL;
    int i=0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    dau_node = dau[unit];
    
    for(port_status = PD_PORT_DISABLE; port_status < PD_PORT_STATUS_COUNT; port_status++)
    {
        if (strncmp(argv[0], pd_port_status_str[port_status], strlen(pd_port_status_str[port_status])))
        {
            continue;
        }
        pd_config.config_port[unit][port].is_enbale = port_status;
        for(i=0; iis_connect == TRUE)
        {
            reg_value = dau_node->reg->reg_global.port_enable;
            if(port_status == PD_PORT_ENABLE)
            {
                SET_BIT(reg_value, 0x1<reg->reg_global.port_enable = reg_value;
            pd_config.config.ch_en_mask = reg_value;
        }
    }
    return CMD_SUCCESS;
}
/* 南瑞传输端口号设置. */
CMD(pd_port_sendnum,
    pd_port_sendnum_cmd,
    "sendport-num <0-32>",
    "Sendport\n"
    "Num\n"
    "Sendport number\n")
{
    uint8_t send_port_num = 0;
    uint8_t unit = 0;
    uint8_t port = 0;
    dau_t * dau_node = NULL;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    dau_node = dau[unit];
    
    send_port_num = strtol(argv[0], NULL, 10);
    pd_config.config_port[unit][port].send_port_num = send_port_num;
    if(dau_node->is_connect == TRUE)
    {
        dau_node->reg->reg_port[port].ch_send_num = send_port_num;
    }
    return CMD_SUCCESS;
}
CMD(pd_filter_frequency,
    pd_filter_frequency_cmd,
    "filter-frequency <0-32767>",
    "Filter\n"
    "Frequency\n"
    "Filter frequency\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].filter_frequency = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_rise_time,
    pd_rise_time_cmd,
    "rise-time <0-32767>",
    "Rise\n"
    "Time\n"
    "Rise time\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].rise_time = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_peak_time,
    pd_peak_time_cmd,
    "peak-time <0-32767>",
    "Peak\n"
    "Time\n"
    "Peak time\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].peak_time = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_fall_time,
    pd_fall_time_cmd,
    "fall-time <0-32767>",
    "Fall\n"
    "Time\n"
    "Fall time\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].fall_time = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_pulse_width,
    pd_pulse_width_cmd,
    "pulse-width <0-32767>",
    "Pulse\n"
    "Width\n"
    "Pulse width\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].pulse_width = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_peak_count,
    pd_peak_count_cmd,
    "peak-count <0-32767>",
    "Peak\n"
    "Count\n"
    "Peak count\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].peak_count = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_signal_envelope,
    pd_signal_envelope_cmd,
    "signal-envelope <0-32767>",
    "Signal\n"
    "Envelope\n"
    "Signal envelope\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].signal_envelope = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_signal_mean,
    pd_signal_mean_cmd,
    "signal-mean <0-32767>",
    "Signal\n"
    "Mean\n"
    "Signal mean\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].signal_mean = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_signal_variance,
    pd_signal_variance_cmd,
    "signal-variance <0-32767>",
    "Signal\n"
    "Variance\n"
    "Signal variance\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].signal_variance = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_primary_frequency,
    pd_primary_frequency_cmd,
    "primary-frequency <0-32767>",
    "Primary\n"
    "Frequency\n"
    "Primary frequency\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].primary_frequency = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_primary_freq_peak,
    pd_primary_freq_peak_cmd,
    "primary-freq-peak <0-32767>",
    "Primary\n"
    "Freq\n"
    "Peak\n"
    "Primary freq peak\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].primary_freq_peak = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_spectral_peak_count,
    pd_spectral_peak_count_cmd,
    "spectral-peak-count <0-32767>",
    "Spectral\n"
    "Peak\n"
    "Count\n"
    "Spectral peak count\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].spectral_peak_count = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_spectrum_mean,
    pd_spectrum_mean_cmd,
    "spectrum-mean <0-32767>",
    "Spectrum\n"
    "Mean\n"
    "Spectrum mean\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].spectrum_mean = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
CMD(pd_spectrum_variance,
    pd_spectrum_variance_cmd,
    "spectrum-variance <0-32767>",
    "Spectrum\n"
    "Variance\n"
    "Spectrum variance\n")
{
    uint8_t unit = 0;
    uint8_t port = 0;
    /* 取出端口号. */
    if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE)
    {
        return CMD_ERR_NO_MATCH;
    }
    pd_config.config_port[unit][port].spectrum_variance = strtol(argv[0], NULL, 10);
    return CMD_SUCCESS;
}
void time_get(uint32_t *timesVal, uint32_t *timeUsVal) 
{
    struct timeval tv = {0};
    struct tm tptr = {0};
    struct tm *p;
    // 获取当前系统时间
    if (gettimeofday(&tv, NULL) != 0) 
    {
        perror("gettimeofday失败");
        return; // 错误处理
    }
    // 将 tv.tv_sec 转换为 struct tm
    p = localtime(&tv.tv_sec);
    if (p == NULL) 
    {
        perror("localtime失败");
        return; // 错误处理
    }
    // 复制到 tptr(与 time_set 保持一致)
    tptr.tm_year = p->tm_year;
    tptr.tm_mon = p->tm_mon;
    tptr.tm_mday = p->tm_mday;
    tptr.tm_hour = p->tm_hour;
    tptr.tm_min = p->tm_min;
    tptr.tm_sec = p->tm_sec;
    // 转换为 time_t
    time_t timestamp = mktime(&tptr);
    if (timestamp == (time_t)-1) 
    {
        perror("mktime失败");
        return; // 错误处理
    }
    *timesVal = (uint32_t)timestamp;
    *timeUsVal = (uint32_t)tv.tv_usec;
}
/* DAU 模块添加处理函数 */
int32_t _dau_add(uint8_t unit, uint8_t port_num)
{
    dau_t *dau_node = dau[unit];
    DBG(DBG_M_PD_DAU, "Entry: unit %d port_num %d\r\n", unit, port_num);
    /* 申请配置节点空间. */
    if (!dau_node)
    {
        dau_node = XMALLOC(MTYPE_DAU, sizeof(dau_t));
        if (!dau_node)
        {
            dau_node = NULL;
            return E_MEM;
        }
    }
    else
    {
        return E_NONE;
    }
    
    /* 初始化 DAU 结构体. */
    dau_node->unit = unit;
    dau_node->port_num = port_num;
    dau_node->reg = NULL;
    dau_node->adc_data = NULL;
    dau_node->is_connect = FALSE;
    
    dau[unit] = dau_node;
    DBG(DBG_M_PD_DAU, "Leave\r\n");
    return E_NONE;
}
/* DAU 模块删除处理函数 */
void _dau_del(uint8_t unit)
{
    dau_t *dau_node = dau[unit];
    if (!dau_node)
    {
        return;
    }
    dau_node->is_valid = FALSE;
}
/* 发送数据到后台通讯进程. */
int32_t _dau_msg_send_csg(uint32_t type, void *data, uint8_t port_idx)
{
    uint32_t fifo_id;
    pd_csg_msg_t up_msg;
    
    /* 封装消息. */
    up_msg.type = type;
    up_msg.data = data;
    if (type == PD_SEND_TYPE_ORIGINAL_DATA)
    {
        fifo_id = csg.fifo_real_image_id[port_idx];
    }
    else if (type == PD_SEND_TYPE_TREND)
    {
        fifo_id = csg.fifo_trend_id;
    }
    else
    {
        return E_ERROR;
    }
    /* 发送消息 */
    if (fifo_write(fifo_id, (void*)(&up_msg), sizeof(pd_csg_msg_t)) != sizeof(pd_csg_msg_t))
    {
        printf("fifo %d write error\n", type);
        return E_ERROR;
    }
    return E_NONE;
}
wave_additional_data_t* _dau_get_wave_addtion_data(char *frame, uint32_t frame_len)
{
    if (NULL != frame || frame_len > ALL_ADDITIONAL_LEN)
        return (wave_additional_data_t*)(frame + (frame_len - ALL_ADDITIONAL_LEN) * sizeof(uint16_t));
    return NULL;
}
int _dau_write_channel_to_file(pd_original_port_t* channel, int channel_id) 
{
    int32_t data_size;
    static uint32_t times = 0;
    if (!channel) return -1;
    //if (access("/mnt/nfs/devlog/wave", F_OK) )
    if (times > 30)
        return 0;
    const char *dir_path = "/mnt/nfs/devlog";
    if (access(dir_path, F_OK) != 0)  
    {
        printf("Directory does not exist.\n");
        return -1;
    }
    
    // 生成文件名
    char filename[256];
    snprintf(filename, sizeof(filename), "%s/channel_%d_%02d.bin", dir_path, channel_id, times++);
    
    // 打开文件
    int file_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (file_fd == -1) 
    {
        perror("Failed to open file");
        return -1;
    }
    
    // 先写入通道结构体信息
    ssize_t bytes_written = write(file_fd, channel, sizeof(pd_original_port_t));
    if (bytes_written != sizeof(pd_original_port_t)) 
    {
        perror("Failed to write channel info");
        close(file_fd);
        return -1;
    }
    
    // 更新数据大小
     data_size = channel->single_frame_length * sizeof(uint16_t);
    
    // 写入通道数据
    for (int i = 0; i < channel->frame_numbers; i++)
    {
        uint32_t offset = i * channel->single_frame_length * sizeof(uint16_t);
        bytes_written = write(file_fd, channel->original_pointer + offset , data_size);
        if (bytes_written != (ssize_t)data_size) 
        {
            perror("Failed to write channel data");
            close(file_fd);
            return -1;
        }
    }
    
    close(file_fd);
    printf("Channel written to file: %s\n", filename);
    return 0;
}
/* 原始波形数据处理. */
void _dau_data_original(void)
{
    dau_t *dau_node = NULL;
    uint8_t unit = 0;
    uint8_t port = 0;
    //struct timeval tv = {0};
    uint64_t offset_addr = 0;
    // uint32_t time_s;
    // uint32_t time_us;
    pd_original_port_t *pd_original_port = NULL;
    // uint64_t sync_for_cpu = 1;
    // u_dma_buf_ioctl_sync_args sync_args;
    //static struct timespec trend_ts = {0};
    //static  pd_trend_t trend[PD_DAU_PORT_SUM] = {0};
    //pd_trend_t *ptrend = NULL;
    wave_additional_data_t *header = NULL;
    pd_trend_port_t *ptrend = NULL;
    static uint16_t count[PD_DAU_PORT_SUM][360] = {0};
    /* 数据处理 */
    for(unit = 0; unit < PD_DAU_SUM; unit++)
    {
        dau_node = dau[unit];
        if (!dau_is_valid(dau_node))
        {
            continue;
        }
        for(port = 0; port < PD_DAU_PORT_SUM; port++)
        {
            if(pd_config.config_port[unit][port].is_enbale == TRUE)
            {
                csg.new_data_flag[port] = TRUE;
                //gettimeofday(&tv, NULL);
                offset_addr = dau_node->reg->reg_port[port].data_start_addr;
                if(offset_addr >= DAU_MEM_ORIGINAL_LEN)
                {
                    DBG(DBG_M_PD_DAU_ERR, "dau %dport data addr over max area!\r\n",port);
                    continue;
                }
                /*申请原始数据内存*/
                pd_original_port = XMALLOC_Q(MTYPE_CSG, sizeof(pd_original_port_t));
                if (!pd_original_port)
                {
                    DBG(DBG_M_PD_DAU_ERR, "dau %dport data malloc failed!\r\n",port);
                    continue;
                }
                pd_original_port->data_vaild = dau_node->reg->reg_port[port].data_valid;
                pd_original_port->original_pointer = dau_node->adc_data + offset_addr;  //每个通道的波形数据起始映射地址赋值
                // printf("offset:%x\n",offset_addr);
                pd_original_port->interrupt_count++;
                pd_original_port->total_pulse_nums = dau_node->reg->reg_port[port].total_pulse_nums;
                pd_original_port->frame_numbers = dau_node->reg->reg_port[port].wave_nums;
                pd_original_port->single_frame_length = dau_node->reg->reg_port[port].signle_wave_length;
                pd_original_port->ground_noise = dau_node->reg->reg_port[port].ground_noise;
                pd_original_port->century_second = dau_node->reg->reg_global.b_time_epoch_sec;
                if(pd_original_port->single_frame_length != DEFAULT_SAMPLE_NUM)
                {
                    pd_original_port->data_vaild = FALSE;
                }
                
                //_dau_write_channel_to_file(pd_original_port, port);
                
                // time_get(&time_s, &time_us);
                // pd_original_port->century_second = time_s;
                // pd_original_port->nano_second = time_us * 1000;
                if(pd_original_port->data_vaild)
                {
                    // /* 设置同步区域(PL修改了数据) */
                    // sync_args.offset = offset_addr;
                    // if(pd_original_port->frame_numbers > 20)
                    // {
                    //     sync_args.size = 20*pd_original_port->single_frame_length;
                    // }
                    // else
                    // {
                    //     sync_args.size = pd_original_port->frame_numbers*pd_original_port->single_frame_length;
                    // }
                    // sync_args.flags = 0;
                    // SET_U_DMA_BUF_IOCTL_FLAGS_SYNC_DIR(&sync_args, 2); /* DMA_FROM_DEVICE */
                    // SET_U_DMA_BUF_IOCTL_FLAGS_SYNC_CMD(&sync_args, U_DMA_BUF_IOCTL_FLAGS_SYNC_CMD_FOR_CPU);
                    // if (ioctl(dau_ctrl.fd_data_mmu, U_DMA_BUF_IOCTL_SET_SYNC, &sync_args) < 0) {
                    //     perror("set sync area failed \n");
                    // }
                    // /* 在 PL 修改数据后,同步到 CPU */
                    // sync_for_cpu = 1;
                    // if (ioctl(dau_ctrl.fd_data_mmu, U_DMA_BUF_IOCTL_SET_SYNC_FOR_CPU, &sync_for_cpu) < 0) {
                    //     perror("sync CPU failed \n");
                    // }
                    
#if 0
                    struct timespec ts;
                    // 获取当前时间
                    if (clock_gettime(CLOCK_REALTIME, &ts) != 0) 
                    {
                        perror("clock_gettime");
                    }
                    //image_head->century_second = ts.tv_sec; 
                    //image_head->nanosecond = ts.tv_nsec;
#endif
                    
#if 1
                    if (pd_data.trend_port[port] == NULL)
                    {
                        pd_data.trend_port[port] = XMALLOC_Q(MTYPE_CSG, sizeof(pd_trend_port_t));
                        if (!pd_data.trend_port[port])
                        {
                            DBG(DBG_M_PD_DAU_ERR, "dau %dport data malloc failed!\r\n",port);
                            continue;
                        }
                        memset(pd_data.trend_port[port], 0, sizeof(pd_trend_port_t));
                    }
                    ptrend = pd_data.trend_port[port];
                    ptrend->pulse_num += pd_original_port->total_pulse_nums;
#endif
                    for (int i = 0; i < pd_original_port->frame_numbers; i++)
                    {
                        char *data_point = NULL;
                        data_point = (char*)(pd_original_port->original_pointer) + (i * pd_original_port->single_frame_length * sizeof(int16_t));
                        header = _dau_get_wave_addtion_data(data_point, pd_original_port->single_frame_length);
                            
                        DBG(DBG_M_PD_DAU_SEND, "port[%d]frame_numbers=%d total_pulse_nums=%d phase=%d,noise=%d,max=%d,pt_frame_num=%d,time=%ld %ld.%ld\r\n", port, pd_original_port->frame_numbers, 
                          pd_original_port->total_pulse_nums, header->phase, header->noise, header->max, header->pt_frame_num, pd_original_port->century_second, header->epoch_sec, header->nano_sec);
                        if (header->max > ptrend->pulse_max)
                            ptrend->pulse_max = header->max;
                        ptrend->pulse_avg += header->max;
                        ptrend->noise += abs(header->noise);
                        if (ptrend->century_second == 0)
                        {
                            ptrend->century_second = pd_original_port->century_second;
                        }
                        
                        if (header->phase >= 360)
                        {
                            DBG(DBG_M_PD_DAU_ERR,"phase error: %d\r\n", header->phase);
                        }
                        else
                        {
                            count[port][header->phase]++;
                        }
                    }
#if 1
                    //if (ptrend->century_second + pd_config.config.trend_up_period < header->epoch_sec)
                    if (ptrend->century_second + pd_config.config.trend_up_period < pd_original_port->century_second)
                    {
                        ptrend->pulse_avg /= (int32_t)ptrend->pulse_num;
                        ptrend->noise /= ptrend->pulse_num;
                        ptrend->port = port;
                        int max_count = 0;
                        int max_phase = 0;
                        for (int i = 0; i < 360; i++)
                        {
                            if (count[port][i] > max_count)
                            {
                                max_count = count[port][i];
                                max_phase = i;
                            }
                        }
                        ptrend->phase = max_phase;
                        DBG(DBG_M_PD_DAU, "port=%d pulse_num=%d pulse_max=%d pulse_avg=%d noise=%d phase=%d\r\n", 
                            port, ptrend->pulse_num, ptrend->pulse_max, ptrend->pulse_avg, ptrend->noise, ptrend->phase);
                        if (_dau_msg_send_csg(PD_SEND_TYPE_TREND, (void *)pd_data.trend_port[port], port) != E_NONE)
                        {
                            DBG(DBG_M_PD_DAU_ERR, "send dau %dport data to fifo err!\r\n",port);
                            XFREE(MTYPE_CSG, ptrend);
                        }
                        pd_data.trend_port[port] = NULL;
                        memset(count[port], 0, sizeof(count[port]));
                    }
#endif
                } 
                
                if (_dau_msg_send_csg(PD_SEND_TYPE_ORIGINAL_DATA, (void *)pd_original_port, port) != E_NONE)
                {
                    // DBG(DBG_M_PD_DAU_ERR, "send dau %dport data to fifo err!\r\n",port);
                    XFREE(MTYPE_CSG, pd_original_port);
                }
            }
        }
    }
}
int _dau_wait_irq(int fd)
{
    int ret = ioctl(fd, IOCTL_IRQ_WAIT);
    return ret;
}
int32_t _dau_interrupt_init(void)
{
    if (dau_ctrl.fd_adc_int != 0)
    {
        return E_NONE;
    }
    dau_ctrl.fd_adc_int = open("/dev/adc_interrupt_0", O_RDWR);
    return dau_ctrl.fd_adc_int;
}
// 判断是否为闰年
int is_leap_year(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 根据一年中的天数计算月日
void doy_to_date(struct tm *tmpr, uint16_t btime[]) {
    // 正常年份每月的天数
    int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    // 输入年份范围检查和默认值设置
    // 如果 btime[0] 不在 [10, 100] 范围内,则使用固定默认时间
    // if (btime[0] > 100 || btime[0] < 10) {
    //     tmpr->tm_year = 2010 - 1900; // 2010年
    //     tmpr->tm_mon = 1 - 1;       // 1月 (tm_mon 是 0-11)
    //     tmpr->tm_mday = 1;          // 1日
    //     tmpr->tm_hour = 0;
    //     tmpr->tm_min = 0;
    //     tmpr->tm_sec = 0;
    //     tmpr->tm_isdst = 0; // 不考虑夏令时
    //     return;
    // }
    int year = btime[0] + 2000;
    // 如果是闰年,二月有 29 天
    if (is_leap_year(year)) {
        days_in_month[1] = 29;
    }
    int remaining_days = btime[1]; // 一年中的第几天 (1-365或366)
    int mon = 0;                   // 月份 (0-11)
    int day = 0;                   // 日期 (1-31)
    // 循环查找月份和日期
    for (int i = 0; i < 12; i++) {
        if (remaining_days <= days_in_month[i]) {
            day = remaining_days;
            mon = i; // 0-11 表示月份
            break;
        }
        remaining_days -= days_in_month[i];
    }
    
    // 如果 remaining_days 经过循环后仍然大于 0,说明 btime[1] 超出了一年的天数范围
    // 可以在这里添加错误处理,例如设置一个无效日期或打印警告
    // if (remaining_days > 0) {
    //     tmpr->tm_year = 2010 - 1900; // 2010年
    //     tmpr->tm_mon = 1 - 1;       // 1月 (tm_mon 是 0-11)
    //     tmpr->tm_mday = 1;          // 1日
    //     tmpr->tm_hour = 0;
    //     tmpr->tm_min = 0;
    //     tmpr->tm_sec = 0;
    //     tmpr->tm_isdst = 0; // 不考虑夏令时
    //     return;
    // }
    tmpr->tm_year = year - 1900; // tm_year 是从 1900 年开始计算的年份差
    tmpr->tm_mon = mon;          // tm_mon 是 0-11
    tmpr->tm_mday = day;         // tm_mday 是 1-31
    tmpr->tm_hour = btime[2];
    tmpr->tm_min = btime[3];
    tmpr->tm_sec = btime[4];
    tmpr->tm_isdst = 0;        // 不考虑夏令时
}
/* DAU 数据处理函数. */
void *_dau_data_handle(void *arg)
{
    uint32_t i = 0;
    // uint16_t time[5];
    // uint32_t now_sec,last_sec;
    // struct tm tm_data = {0,};
    // int year,mon,day,hour,min,sec;
    // struct timeval start, end;
    /* 等待初始化完成 */
    while(!is_system_init)
    {
        usleep(100000);
    }
    // gettimeofday(&start, NULL);
    // last_sec = dau[0]->reg->reg_global.b_time_sec;
    while(1)
    {
        if (!dau_is_valid(dau[0]))
        {
            continue;
        }
        /* 等待 DAU 数据准备完成. */
        _dau_wait_irq(dau_ctrl.fd_adc_int);
        // gettimeofday(&end, NULL);
        // printf("int time:%ldus\n", (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec);
        // start = end;
        if(i < 3)
        {
            i++;
            continue;
        }
        // now_sec = dau[0]->reg->reg_global.b_time_sec;
        // if(now_sec != last_sec)
        // {
        //     time[0] = dau[0]->reg->reg_global.b_time_year;
        //     time[1] = dau[0]->reg->reg_global.b_time_day;
        //     time[2] = dau[0]->reg->reg_global.b_time_hour;
        //     time[3] = dau[0]->reg->reg_global.b_time_min;
        //     time[4] = now_sec;
        //     doy_to_date(&tm_data, time);
        //     year = tm_data.tm_year + 1900;
        //     mon = tm_data.tm_mon;
        //     day = tm_data.tm_mday;
        //     hour = tm_data.tm_hour;
        //     min = tm_data.tm_min;
        //     sec = tm_data.tm_sec;
        //     printf("year=%d,mon=%d,day=%d,hour=%d,min=%d,sec=%d\n",year,mon,day,hour,min,sec);
        // }
        // last_sec = now_sec;
        
        // /* 数据处理 */
        _dau_data_original();
    }
    return NULL;
}
/* dau 寄存器物理地址映射 */
int32_t _dau_reg_map(uint8_t unit)
{
    dau_ctrl.fd_reg_mmu = open("/dev/mem", O_RDWR|O_SYNC);
    dau_ctrl.fd_data_mmu = open("/dev/mem", O_RDWR|O_SYNC);
    /* 映射参数设置寄存器 */
    dau[unit]->reg = (dau_reg_t*)mmap(NULL, DAU_MEM_REG_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, dau_ctrl.fd_reg_mmu, DAU_MEM_REG_ADDR);
    if (dau[unit]->reg < 0)
    {
        DBG(DBG_M_PD_DAU_ERR, "DAU mmap reg ERROR!\r\n");
        return E_MEM;
    }
    /* 映射端口信息读取寄存器 */
    dau[unit]->adc_data = (char *)mmap(NULL, DAU_MEM_ORIGINAL_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, dau_ctrl.fd_data_mmu, DAU_MEM_ORIGINAL_ADDR);
    if (dau[unit]->adc_data < 0)
    {
        DBG(DBG_M_PD_DAU_ERR, "DAU mmap original ERROR!\r\n");
        return E_MEM;
    }
    return E_NONE;
}
void _dau_set_time(uint32_t tval)
{
    int i;
    for(i = 0; i < PD_DAU_SUM; i++)
    {
        if (!dau_is_valid(dau[i]))
        {
            continue;
        }
        //dau_t * dau_node = dau[0];
       
        //if (dau_node->is_connect == TRUE)
        {
            if (IS_BITMAP_SET(pd_config.config.pt_B_sync_mode, PD_BIT_BCODE))
            {
                dau[i]->reg->reg_global.ps_epoch_sec = tval;  
                printf("####Z#  time:%d\r\n", tval);
            }
        }
    }
}
void dau_mode_set(uint8_t unit)
{
    uint32_t ver_info;
    uint32_t reg_value;
    uint8_t idx = 0;
    ver_info = dau[unit]->reg->reg_global.ver_num;
    printf("ver_info=%08x\r\n",ver_info);
    dau[unit]->reg->reg_global.sample_nums = pd_config.config.trigger_sample_nums;                        //采样个数
    dau[unit]->reg->reg_global.sample_interrupt_intveal_us = pd_config.config.interrupt_interval;         //采样中断间隔2ms一次
    dau[unit]->reg->reg_global.trig_gap = pd_config.config.trig_gap;
    dau[unit]->reg->reg_global.trig_location = pd_config.config.trig_location;
    dau[unit]->reg->reg_global.trig_threshold = pd_config.config.trig_threshold;
    dau[unit]->reg->reg_global.pt_B_sync_mode = pd_config.config.pt_B_sync_mode;
    dau[unit]->reg->reg_global.mv_factor = DEFAULT_FACTOR_MV;  
    dau[unit]->reg->reg_global.irigB_polarity = pd_config.config.irigB_polarity;
    dau[unit]->reg->reg_global.ch_type = DEFAULT_CH_TYPE;
    dau[unit]->reg->reg_global.unit = DEFAULT_CH_UNIT;
    //dau_t * dau_node = dau[0];
   
    //if (dau_node->is_connect == TRUE)
    {
        if (IS_BITMAP_SET(pd_config.config.pt_B_sync_mode, PD_BIT_BCODE))
        {
            dau[unit]->reg->reg_global.ps_epoch_sec = time(NULL);  
            printf("####Z#  time:%ld\r\n", time(NULL));
        }
    }
    reg_value = dau[unit]->reg->reg_global.port_enable;
    for(idx=0; idxreg->reg_port[idx].ch_send_num = pd_config.config_port[unit][idx].send_port_num;
    }
    dau[unit]->reg->reg_global.port_enable = reg_value;
}
/* 启动 DUA */
int32_t _dau_start(void)
{
    uint8_t i = 0;
    // uint8_t j = 0; 
    /* DAU 上电. */
    //system("echo system_wrapper.bin > /sys/class/fpga_manager/fpga0/firmware");
    //sleep(3);
    /* 设置为有效 */
    for(i = 0; i < PD_DAU_SUM; i++)
    {
        if (!dau[i])
        {
            continue;
        }
        dau[i]->is_valid = TRUE;
    }
    for(i = 0; i < PD_DAU_SUM; i++)
    {
        if (!dau_is_valid(dau[i]))
        {
            continue;
        }
        /* 寄存器映射 */
        LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_reg_map(i));
        /* 全局配置下发 */
        dau_mode_set(i);
        /* 中断初始化 */
        _dau_interrupt_init();
        dau[i]->is_connect = TRUE;
    }
    return E_NONE;
}
// /* 配置保存函数. */
// int _dau_config_save(vty_t* vty)
// {
//     dau_t *dau_node = NULL;
//     int16_t i = 0;
//     uint8_t unit = 0;
    
//     /* 遍历所有 DAU. */
//     for (unit = 0; unit < PD_DAU_SUM; unit++)
//     {
//         dau_node = dau[unit]; 
//         if (!dau_node)
//         {
//             return FALSE;
//         }
        
//         vty_out(vty, "dau %d port-num %d%s", unit + 1, dau_node->port_num, VTY_NEWLINE);
//         i++;
//     }
//     return i;
// }
/* config模式配置保存函数: vty -- 相应的终端 */
int _dau_port_config_save(vty_t *vty, uint8_t unit, uint8_t port)
{
    uint8_t field = 0;
    
    field = pd_config.config_port[unit][port].is_enbale;
    vty_out(vty, "  port-status %s%s", pd_port_status_str[field], VTY_NEWLINE);
    field = pd_config.config_port[unit][port].send_port_num;
    vty_out(vty, "  sendport-num %u%s", field, VTY_NEWLINE);
    vty_out(vty, "  filter-frequency %d%s", pd_config.config_port[unit][port].filter_frequency, VTY_NEWLINE);
    vty_out(vty, "  rise-time %d%s", pd_config.config_port[unit][port].rise_time, VTY_NEWLINE);
    vty_out(vty, "  peak-time %d%s", pd_config.config_port[unit][port].peak_time, VTY_NEWLINE);
    vty_out(vty, "  fall-time %d%s", pd_config.config_port[unit][port].fall_time, VTY_NEWLINE);
    vty_out(vty, "  pulse-width %d%s", pd_config.config_port[unit][port].pulse_width, VTY_NEWLINE);
    vty_out(vty, "  peak-count %d%s", pd_config.config_port[unit][port].peak_count, VTY_NEWLINE);
    vty_out(vty, "  signal-envelope %d%s", pd_config.config_port[unit][port].signal_envelope, VTY_NEWLINE);
    vty_out(vty, "  signal-mean %f%s", pd_config.config_port[unit][port].signal_mean, VTY_NEWLINE);
    vty_out(vty, "  signal-variance %f%s", pd_config.config_port[unit][port].signal_variance, VTY_NEWLINE);
    vty_out(vty, "  primary-frequency %d%s", pd_config.config_port[unit][port].primary_frequency, VTY_NEWLINE);
    vty_out(vty, "  primary-freq-peak %d%s", pd_config.config_port[unit][port].primary_freq_peak, VTY_NEWLINE);
    vty_out(vty, "  spectral-peak-count %d%s", pd_config.config_port[unit][port].spectral_peak_count, VTY_NEWLINE);
    vty_out(vty, "  spectrum-mean %f%s", pd_config.config_port[unit][port].spectrum_mean, VTY_NEWLINE);
    vty_out(vty, "  spectrum-variance %f%s", pd_config.config_port[unit][port].spectrum_variance, VTY_NEWLINE);
    return E_NONE;
}
/* Interface functions -------------------------------------------------------*/
/* DAU 模块初始化. */
int32_t dau_handle_init(void)
{
    int32_t rv = 0;
    /* 注册命令行 */
    // cmd_install_element(CONFIG_NODE, &dau_add_cmd);
    // cmd_install_element(CONFIG_NODE, &no_dau_add_cmd);
    
    cmd_install_element(COMMON_NODE, &show_dau_status_all_cmd);
    cmd_install_element(PORT_NODE, &pd_port_status_cmd);
    cmd_install_element(PORT_NODE, &pd_port_sendnum_cmd);
    cmd_install_element(PORT_NODE, &pd_filter_frequency_cmd);
    cmd_install_element(PORT_NODE, &pd_rise_time_cmd);
    cmd_install_element(PORT_NODE, &pd_peak_time_cmd);
    cmd_install_element(PORT_NODE, &pd_fall_time_cmd);
    cmd_install_element(PORT_NODE, &pd_pulse_width_cmd);
    cmd_install_element(PORT_NODE, &pd_peak_count_cmd);
    cmd_install_element(PORT_NODE, &pd_signal_envelope_cmd);
    cmd_install_element(PORT_NODE, &pd_signal_mean_cmd);
    cmd_install_element(PORT_NODE, &pd_signal_variance_cmd);
    cmd_install_element(PORT_NODE, &pd_primary_frequency_cmd);
    cmd_install_element(PORT_NODE, &pd_primary_freq_peak_cmd);
    cmd_install_element(PORT_NODE, &pd_spectral_peak_count_cmd);
    cmd_install_element(PORT_NODE, &pd_spectrum_mean_cmd);
    cmd_install_element(PORT_NODE, &pd_spectrum_variance_cmd);
    
    // /* 注册配置保存函数 */
    // rv = cmd_config_node_config_register(CONFIG_PRI_DAU, _dau_config_save);
    // if (rv != E_NONE)
    // {
    //     log_err(LOG_DAU, "Command save register ERROR %d!", rv);
    //     return rv;
    // }
    rv = pd_port_cmd_config_register(PD_PORT_CMD_PRI_DAU, _dau_port_config_save);
    if (rv != E_NONE)
    {
        log_err(LOG_DAU, "DAU port command save register ERROR %d!", rv);
        return rv;
    }
    return E_NONE;
}
int32_t dau_handle_init_after(void)
{
    struct sched_param param;
    pthread_attr_t attr;
    pthread_t pid;
    int32_t rv = 0;
    // int i=0;
    // double sample_rate = 5e9;         // 5 GHz
    // double duration = 4e-6;           // 2 microseconds
    // double amplitude = 10000;         // 2 mV -> volts
    // double frequency = 600e6;         // 600 MHz
    // // 计算总采样点数
    // int num_samples = (int)(sample_rate * duration);
    // printf("Number of samples: %d\n", num_samples);
    // for(i=0; i= PD_DAU_SUM)
    {
        return E_BAD_PARAM;
    }
    for(i = 0; i < unit; i++)
    {
        if (!dau[i])
        {
            continue;
        }
    
        vport += dau[i]->port_num;
    }
    if (!dau[i])
    {
        return E_BAD_PARAM;
    }
    if (port >= dau[i]->port_num)
    {
        return E_BAD_PARAM;
    }
    return vport += port + 1;
}
/* 将 unit port 转换成 vport. */
int32_t dau_vport_to_port(uint8_t vport, uint8_t *unit, uint8_t *port)
{
    uint8_t i = 0;
    for(i = 0; i < PD_DAU_SUM; i++)
    {
        if (!dau[i])
        {
            continue;
        }
        if (vport <= dau[i]->port_num
            && vport != 0)
        {
            *unit = i;
            *port = vport - 1;
            return E_NONE;
        }
        else
        {
            vport -= dau[i]->port_num;
        }
    }
    return E_BAD_PARAM;
}
/* 获取在线状态 */
uint8_t dau_connect_get(void)
{
    return dau[0]->is_connect;
}
// /* 获取端口状态寄存器. */
// int32_t dau_param_adj_save(uint8_t unit)
// {
//     dau_adj_t adj;
//     int fd = 0;
//     ssize_t len = 0;
//     uint8_t port = 0;
//     char cmd[128] = {0};
//     int32_t rv = E_NONE;
//     fd = open(DAU_ADJ_FILE, O_RDWR | O_CREAT | O_CREAT, 0777);
//     if (fd < 0 )
//     {
//         DBG(DBG_M_PD_DAU_ERR, "Open %s ERROR!\r\n", DAU_ADJ_FILE);
//         return E_SYS_CALL;
//     }
//     for(port = 0; port < PD_DAU_PORT_SUM; port++)
//     {
//         memcpy(&(adj.port[port]), dau[unit]->reg->reg_port[port].ASPR, sizeof(dau_adj_port_t));
//     }
//     len = write(fd, &adj, sizeof(dau_adj_t));
//     if (len != sizeof(dau_adj_t))
//     {
//         DBG(DBG_M_PD_DAU_ERR, "Write %s len %d!\r\n", DAU_ADJ_FILE, len);
//         close(fd);
//         return E_SYS_CALL;
//     }
//     close(fd);
//     /* 保存备份文件 */
//     snprintf(cmd, 128, "cp -rf %s %s", DAU_ADJ_FILE, DAU_ADJ_FILE_BAK);
//     system(cmd);
//     system("sync");
    
//     return rv;
// }
/* 判断 DAU 是否有效. */
int32_t dau_is_valid(dau_t *dau_node)
{
    if (!dau_node)
    {
        return FALSE;
    }
    if (!dau_node->is_valid)
    {
        return FALSE;;
    }
    return TRUE;
}
/* 显示 DAU 状态. */
void dau_show(uint8_t unit)
{
    dau_t *dau_node = NULL;
    dau_node = dau[unit];
    if (!dau_node)
    {
        return;
    }
    printh("DAU %d: \r\n", unit + 1);
    printh("  Valid: %d\r\n\n", dau_node->is_valid);
    return;
}
/* 显示 DAU 状态. */
void dau_show_value(uint8_t unit)
{
    dau_t *dau_node = NULL;
    dau_node = dau[unit];
    if (!dau_is_valid(dau_node))
    {
        return;
    }
    printh("DAU %d: \r\n", unit + 1);
    printh("  1     2     3     4     5     6     7     8\r\n  ");
    return;
}
#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****/