/***************************************************************************** * 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 /* 标准C库头文件. */ #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_net.h" #include "pd_dau.h" #include "pd_dbg.h" /* Private typedef -----------------------------------------------------------*/ typedef struct { uint32_t ASPR[DAU_ADJ_POINT_SUM]; // 校准分段点 uint32_t AFR[DAU_ADJ_POINT_SUM]; // 校准系数 } dau_adj_port_t; typedef struct { dau_adj_port_t port[PD_DAU_PORT_SUM]; } dau_adj_t; /* Private define ------------------------------------------------------------*/ #define DAU_ADJ_FILE "adj.cfg" #define DAU_ADJ_FILE_BAK "./bak/adj.cfg" #define DAU_CODE 0x0701 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ dau_ctrl_t dau_ctrl; dau_t *dau[PD_DAU_SUM]; /* DAU 端口类型分类 */ static const char *dau_port_type_str[PD_PORT_TYPE_COUNT] = { "", "uhf", "ae", "tev", "hf" }; extern dau_port_func_t uhf_func; extern dau_port_func_t hf_func; /* Private function prototypes -----------------------------------------------*/ extern int32_t _dau_add(uint8_t unit, uint8_t port_num); extern void _dau_del(uint8_t unit); /* 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; } /* 配置端口模式. */ CMD(dau_port_type, dau_port_type_cmd, "port-type (uhf|ae|tev|hf)", "DAU port type\n" "UHF\n" "AE\n" "TEV\n" "HF\n") { dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; uint8_t port_type = 0; uint32_t temp = 0; /* 取出端口号. */ if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } for(port_type = PD_PORT_TYPE_UHF; port_type < PD_PORT_TYPE_COUNT; port_type++) { if (strncmp(argv[0], dau_port_type_str[port_type], strlen(dau_port_type_str[port_type]))) { continue; } dau_node = dau[unit]; temp = (port_type << DAU_CR_PT_Pos); if (is_system_init) { MODIFY_REG(dau_node->reg->reg_port[port].CR, DAU_CR_PT_Msk, temp); } pd_config.config_port[unit][port].port_type = port_type; if (PD_PORT_TYPE_UHF == port_type) { dau_node->port_func[port] = &uhf_func; } else if (PD_PORT_TYPE_AE == port_type) { dau_node->port_func[port] = &uhf_func; } else if (PD_PORT_TYPE_HF == port_type) { dau_node->port_func[port] = &hf_func; } else { dau_node->port_func[port] = &uhf_func; } } return CMD_SUCCESS; } /* 通道滤波类型. */ CMD(dau_filter_type, dau_filter_type_cmd, "filtrate-type (none|ff|fr|lf|hf)", "Port filtrate type\n" "None\n" "Full frequency \n" "Full frequency resistor\n" "Low frequency\n" "High frequency\n") { dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; uint8_t filter = 0; uint8_t filter_csg = 0; uint32_t temp = 0; /* 取出端口号. */ if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } if (0 == strncmp(argv[0], "hf", 2)) { filter = PD_FILTER_TYPE_HF; filter_csg = CSG_FILTER_TYPE_HF; } else if (0 == strncmp(argv[0], "lf", 2)) { filter = PD_FILTER_TYPE_LF; filter_csg = CSG_FILTER_TYPE_LF; } else if (0 == strncmp(argv[0], "fr", 2)) { filter = PD_FILTER_TYPE_FR; filter_csg = CSG_FILTER_TYPE_FR; } else if (0 == strncmp(argv[0], "ff", 2)) { filter = PD_FILTER_TYPE_FF; filter_csg = CSG_FILTER_TYPE_FF; } else { filter = 0; } dau_node = dau[unit]; temp = (filter << DAU_CR_FT_Pos); if (is_system_init) { MODIFY_REG(dau_node->reg->reg_port[port].CR, DAU_CR_FT_Msk, temp); } pd_config.config_port[unit][port].filter = filter_csg; pd_config.config_real[unit][port].filter_cfg = filter_csg; 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; } /* 显示 DAU 校准系数. */ CMD(show_dau_vaule, show_dau_vaule_cmd, "show dau vaule", "Show\n" "DAU\n" "Vaule\n") { uint8_t unit = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_show_value(unit); } return CMD_SUCCESS; } /* 显示 DAU 校准系数. */ CMD(show_dau_adj_all, show_dau_adj_all_cmd, "show dau adj", "Show\n" "DAU\n" "ADJ\n") { uint8_t unit = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_show_adj(unit); } return CMD_SUCCESS; } /* 显示 DAU 全局寄存器. */ CMD(show_dau_reg_all, show_dau_reg_all_cmd, "show dau reg", "Show\n" "DAU\n" "Reg\n") { uint8_t unit = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_show_reg(unit); } return CMD_SUCCESS; } /* 显示 DAU 全局寄存器. */ CMD(show_dau_reg_port, show_dau_reg_port_cmd, "show dau port <1-8>", "Show\n" "DAU\n" "Port Reg\n" "Port number") { uint8_t vport = 0; uint8_t unit = 0; uint8_t port = 0; vport = strtol(argv[0], NULL, 10); /* 取出端口号. */ if (dau_vport_to_port(vport, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } dau_show_reg_port(unit, port); return CMD_SUCCESS; } /* DAU 测试函数. */ void *_dau_test_handle(void *arg) { dau_t *dau_node = NULL; uint32_t i, j, k; uint8_t bank = 0; uint8_t temp = 0; while(!dau_is_valid(dau[0])) { sleep(1); } dau_node = dau[0]; for(i = 0; i < PD_DAU_PORT_SUM; i++) { for(j = 0; j < PD_PRPS_NUM_MAX; j++) { if ((j & 0xff) == temp) { dau_node->PRPS->bank[bank].time[j][i] = j << 5; dau_node->PRPS->bank[bank].data[j][i] = -200; } else { dau_node->PRPS->bank[bank].time[j][i] = 0; dau_node->PRPS->bank[bank].data[j][i] = -750; } } } for(i = 0; i < PD_DAU_PORT_SUM; i++) { for(j = 0; j < PD_PHASE_NUM; j++) { for(k = 0; k < PD_TREND_PHASE_POINT_CNT; k++) { dau_node->original->point[j][i].data[k] = (k * 3) - 800; } } } dau_node->reg->reg_global.GPFPCR = 50; dau_node->reg->reg_global.GPFPCCR = 2000000; while(1) { /* 轮询间隔 */ sleep(1); bank = !bank; temp += 8; for(i = 0; i < PD_DAU_PORT_SUM; i++) { for(j = 0; j < PD_PRPS_NUM_MAX; j++) { if ((j & 0xff) == temp) { dau_node->PRPS->bank[bank].time[j][i] = j << 5; dau_node->PRPS->bank[bank].data[j][i] = -200; } else { dau_node->PRPS->bank[bank].time[j][i] = 0; dau_node->PRPS->bank[bank].data[j][i] = -750; } } } dau_node->reg->reg_global.GSDPCR++; dau_node->reg->reg_global.GPFPCR = 50; } return NULL; } /* 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; } /* 初始化 DAU 结构体. */ dau_node->is_del = FALSE; dau_node->reg = 0; dau_node->PRPS = 0; dau_node->original = 0; dau_node->is_connect = FALSE; dau[unit] = dau_node; } dau_node->unit = unit; dau_node->port_num = port_num; 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_del = TRUE; dau_node->is_valid = FALSE; } /* 发送数据到后台通讯进程. */ int32_t _dau_msg_send_csg(uint32_t type, void *data) { int32_t fifo_id; pd_csg_msg_t up_msg; /* 封装消息. */ up_msg.type = type; up_msg.data = data; if (PD_PROTOCOL_LAND == pd_config.config.protocol_type) { if (PD_SEND_TYPE_PRPS == type) { fifo_id = csg.fifo_prps_id; } else if (PD_SEND_TYPE_TREND == type) { fifo_id = csg.fifo_trend_id; } else if (PD_SEND_TYPE_EVENT == type) { fifo_id = csg.fifo_event_id; } } else if (PD_PROTOCOL_CSG == pd_config.config.protocol_type) { if (PD_SEND_TYPE_PRPS == type) { fifo_id = net.fifo_prps_id; } else if (PD_SEND_TYPE_TREND == type) { fifo_id = net.fifo_trend_id; } else if (PD_SEND_TYPE_EVENT == type) { fifo_id = net.fifo_event_id; } } if (fifo_id <= 0) return E_NONE; /* 发送消息 */ if (fifo_write(fifo_id, (void*)(&up_msg), sizeof(pd_csg_msg_t)) != sizeof(pd_csg_msg_t)) { DBG(DBG_M_PD_DAU_ERR, "DAU write ERROR! type=%d\r\n", type); return E_ERROR; } return E_NONE; } /* 实时数据降噪处理. */ void _dau_sec_data_real(void) { struct timeval now; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; /* 申请 PRPS 数据空间. */ pd_data.real = XMALLOC_Q(MTYPE_CSG, sizeof(pd_prps_point_t)); if (!pd_data.real) { return; } /* 自动 / 手动降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_real) { continue; } dau_node->port_func[port]->denoise_real(unit, port); } } /* 关联降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_real_r) { continue; } dau_node->port_func[port]->denoise_real_r(unit, port); } } /* 降噪数据统计 (PRPS 显示). */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_real_state) { continue; } dau_node->port_func[port]->denoise_real_state(unit, port); } } pd_data.real->index = dau_ctrl.real_idx++; gettimeofday(&now, NULL); pd_data.real->utc = now.tv_sec; pd_data.real->ms = now.tv_usec / 1000; } /* PRPS 实时图谱数据发送 */ void _dau_sec_data_real_send(void) { if (_dau_msg_send_csg(PD_SEND_TYPE_PRPS, pd_data.real) != E_NONE) { XFREE(MTYPE_CSG, pd_data.real); } } /* PRPS 数据事件处理 */ void _dau_sec_data_event(void) { static uint8_t data_cnt = 0; // 保证丢包时能正确统计事件. dau_t *dau_node = NULL; uint8_t event_cnt = 0; uint8_t is_send = FALSE; uint8_t unit = 0; uint8_t port = 0; event_cnt = dau[0]->reg->reg_global.GSDPCR % DAU_EVENT_SUM; /* 申请数据空间. */ if (NULL == pd_data.event) { pd_data.event = XMALLOC_Q(MTYPE_CSG, sizeof(pd_event_t)); if (!pd_data.event) { return; } /* 初始化 */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->event_init) { continue; } dau_node->port_func[port]->event_init(unit, port); } } } /* 事件处理 */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->event) { continue; } dau_node->port_func[port]->event(unit, port, event_cnt); if (pd_data.event->port[unit][port].type != PD_EVENT_TYPE_NONE) { dau_ctrl.event_index[unit][port]++; is_send = TRUE; } } } /* 上送后台 */ data_cnt++; if (data_cnt >= DAU_EVENT_SUM || event_cnt == (DAU_EVENT_SUM - 1)) { if (is_send) { if (_dau_msg_send_csg(PD_SEND_TYPE_EVENT, pd_data.event) != E_NONE) { XFREE(MTYPE_CSG, pd_data.event); } } else { /* 没有事件产生要释放内存 */ XFREE(MTYPE_CSG, pd_data.event); } /* 发送给后台后, 地址清零. */ pd_data.event = NULL; data_cnt = 0; } } /* 趋势数据处理. */ void _dau_sec_data_trend(void) { dau_t *dau_node = NULL; uint16_t trend_sec = 0; uint8_t unit = 0; uint8_t port = 0; /* 趋势计算计数 */ trend_sec = dau[0]->reg->reg_global.GSDPCR % pd_config.config.trend_period; /* 申请数据空间. */ if (NULL == pd_data.trend_prpd) { pd_data.trend_prpd = XMALLOC(MTYPE_CSG, sizeof(pd_trend_prpd_t)); if (!pd_data.trend_prpd) { return; } /* 初始化 */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->trend_init) { continue; } dau_node->port_func[port]->trend_init(unit, port); } } } /* 数据处理 */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->trend) { continue; } dau_node->port_func[port]->trend(unit, port, trend_sec); } } /* 通知趋势线程处理后续数据 */ if (trend_sec == (pd_config.config.trend_period - 1)) { pd_data.trend_col.utc = pd_data.real->utc; pd_data.trend_col.index = dau_ctrl.trend_idx++; memcpy(&pd_data.trend.col, &pd_data.trend_col, sizeof(pd_trend_col_t)); pd_data.trend.prpd = pd_data.trend_prpd; pd_data.trend_prpd = NULL; pthread_mutex_unlock(&dau_ctrl.mutex); } } /* 1s prps 数据处理. */ void _dau_sec_data_process(void) { static uint8_t data_cnt = 0; /* 上电非稳定期间的数据丢弃 */ if (data_cnt < 3) { data_cnt++; return; } /* 实时数据降噪处理. */ _dau_sec_data_real(); /* 事件计算 */ _dau_sec_data_event(); /* 趋势数据处理 */ _dau_sec_data_trend(); /* 实时数据发送处理. */ _dau_sec_data_real_send(); } /* DAU 数据处理函数. */ void *_dau_sec_data_handle(void *arg) { uint32_t *time = NULL; int16_t *data = NULL; uint8_t bank = 0; uint32_t i = 0; uint32_t j = 0; uint32_t period = 0; uint32_t prps_cnt = 0; /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while(1) { /* 轮询间隔 */ usleep(100000); if (!dau_is_valid(dau[0])) { continue; } /* 判断工频周期是否更新, 更新后才处理数据 */ if (period == dau[0]->reg->reg_global.GSDPCR) { continue; } period = dau[0]->reg->reg_global.GSDPCR; //struct timeval tv; //gettimeofday(&tv, NULL); // 获取当前时间 //printf("Seconds: %ld, Microseconds: %ld\n", tv.tv_sec, tv.tv_usec); /* 确定 bank */ bank = (period & 0x1) ? 1 : 0; //printf("#D0 %lld %d %d %d\r\n", dau[0]->reg->reg_global.GPFPCR, dau[0]->reg->reg_global.reserved0, period, bank); /* 复制数据 */ prps_cnt = dau[0]->reg->reg_global.GPFPCR << 8; time = (uint32_t*)(dau[0]->PRPS->bank[bank].time); data = (int16_t*)(dau[0]->PRPS->bank[bank].data); for(i = 0; i < dau[0]->port_num; i++) { dau[0]->port_state[i].prps_fre_cnt = dau[0]->reg->reg_global.GPFPCR; for(j = 0; j < prps_cnt; j++) { dau[0]->port_state[i].prps[j].time = time[i + (j << 3)]; dau[0]->port_state[i].prps[j].data = data[i + (j << 3)]; #if 0 if (((j & 0xff) == 128) && 0 == i) dau[0]->port_state[i].prps[j] = 1000; else if(((j & 0x1ff) == 64) && 0 == i) dau[0]->port_state[i].prps[j] = 3000; #endif } } /* 数据处理 */ _dau_sec_data_process(); } return NULL; } /* 趋势原始数据排序 */ void _dau_trend_original_sort(uint8_t unit) { dau_t *dau_node = dau[unit]; int16_t *point = NULL; int16_t *point_bak = NULL; uint8_t port = 0; uint32_t i = 0; for(port = 0; port < dau_node->port_num; port++) { for(i = 0; i < PD_PHASE_NUM; i++) { point = dau_node->original->point[i][port].data; point_bak = pd_data.trend.original.port[unit][port].data[i]; memcpy(point_bak, point, PD_TREND_PHASE_POINT_CNT * sizeof(int16_t)); } } } /* 趋势数据处理函数. */ void *_dau_trend_handle(void *arg) { dau_t *dau_node = NULL; uint8_t unit = 0; /* 等待初始化完成 */ while (!is_system_init) { sleep(1); } while (1) { /* 等待趋势数据 */ pthread_mutex_lock(&dau_ctrl.mutex); if (PD_DEV_TYPE_UHF == device_info.type_s) { /* 原始数据处理 */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } _dau_trend_original_sort(unit); } } //buf_print_16(pd_data.trend.prpd->port[0][0].data, 65536); if (_dau_msg_send_csg(PD_SEND_TYPE_TREND, pd_data.trend.prpd) != E_NONE) { XFREE(MTYPE_CSG, pd_data.trend.prpd); } } return NULL; } /* 读通道校准系数. */ int32_t _dau_param_adj_get(uint8_t unit) { dau_adj_t adj; int fd = 0; ssize_t len = 0; uint8_t port = 0; fd = open(DAU_ADJ_FILE, O_RDWR | O_CREAT, 0777); if (fd < 0 ) { DBG(DBG_M_PD_DAU_ERR, "Open %s ERROR!\r\n", DAU_ADJ_FILE); return E_SYS_CALL; } len = read(fd, &adj, sizeof(dau_adj_t)); if (len <= 0) { DBG(DBG_M_PD_DAU_ERR, "Read %s len %d!\r\n", DAU_ADJ_FILE, len); memset(&adj, 0, sizeof(dau_adj_t)); } for(port = 0; port < PD_DAU_PORT_SUM; port++) { /* 4G 单元控制特殊处理, 后期修改掉 */ dau[unit]->reg->reg_port[port].ASPR[0] = adj.port[port].ASPR[0]; dau[unit]->reg->reg_port[port].AFR[0] = adj.port[port].AFR[0]; //memcpy(dau[unit]->reg->reg_port[port].ASPR, &(adj.port[port]), sizeof(dau_adj_port_t)); } close(fd); return E_NONE; } /* dau 寄存器物理地址映射 */ int32_t _dau_reg_map(uint8_t unit) { if (dau_ctrl.fd_mmu != 0) { return E_NONE; } dau_ctrl.fd_mmu = open("/dev/mem", O_RDWR); /* 映射寄存器 */ dau[unit]->reg = (dau_reg_t*)mmap(0, DAU_MEM_REG_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, dau_ctrl.fd_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; } /* 映射 PRPS 数据物理地址 */ dau[unit]->PRPS = (dau_prps_t*)mmap(0, DAU_MEM_PRPS_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, dau_ctrl.fd_mmu, DAU_MEM_PRPS_ADDR); if (dau[unit]->PRPS < 0) { DBG(DBG_M_PD_DAU_ERR, "DAU mmap PRPS ERROR!\r\n"); return E_MEM; } /* 映射原始数据物理地址 */ dau[unit]->original = (dau_original_t*)mmap(0, DAU_MEM_ORIGINAL_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, dau_ctrl.fd_mmu, DAU_MEM_ORIGINAL_ADDR); if (dau[unit]->original < 0) { DBG(DBG_M_PD_DAU_ERR, "DAU mmap original ERROR!\r\n"); return E_MEM; } return E_NONE; } /* 启动 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[i]->reg->reg_global.GSCR = 0xFFFF0000 | DAU_CODE; dau[i]->reg->reg_global.GSDPCR = 0; /* 读通道校准系数. */ LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_param_adj_get(i)); /* 全局配置下发 */ dau_pps_mode_set(); dau_sync_mode_set(); dau_sync_fre_set(); dau_trend_inv_set(); /* 将端口配置同步到 DAU. */ for (j = 0; j < dau[i]->port_num; j++) { dau_port_filter_set(i, j); dau_port_type_set(i, j); dau[i]->port_state[j].denoise_auto = pd_config.config_port[i][j].denoise_auto; dau[i]->port_state[j].denoise_variance = pd_config.config_port[i][j].denoise_variance; } /* 等待连接成功. */ if (DAU_CODE == ((dau[i]->reg->reg_global.GSCR & DAU_GSCR_CODE_Msk) >> DAU_GSCR_CODE_Pos)) { dau[i]->is_connect = TRUE; } else { DBG(DBG_M_PD_DAU_ERR, "DAU start ERROR!\r\n"); return E_ERROR; } } 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 || dau_node->is_del) { continue; } 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; char str[5] ={0}; field = pd_config.config_port[unit][port].port_type; vty_out(vty, " port-type %s%s", dau_port_type_str[field], VTY_NEWLINE); field = pd_config.config_port[unit][port].filter; switch(field) { case CSG_FILTER_TYPE_HF: snprintf(str, 5, "hf"); break; case CSG_FILTER_TYPE_LF: snprintf(str, 5, "lf"); break; case CSG_FILTER_TYPE_FR: snprintf(str, 5, "fr"); break; case CSG_FILTER_TYPE_FF: snprintf(str, 5, "ff"); break; default: snprintf(str, 5, "none"); break; } vty_out(vty, " filtrate-type %s%s", str, 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(PORT_NODE, &dau_port_type_cmd); cmd_install_element(PORT_NODE, &dau_filter_type_cmd); cmd_install_element(COMMON_NODE, &show_dau_status_all_cmd); cmd_install_element(COMMON_NODE, &show_dau_vaule_cmd); cmd_install_element(COMMON_NODE, &show_dau_adj_all_cmd); cmd_install_element(COMMON_NODE, &show_dau_reg_all_cmd); cmd_install_element(COMMON_NODE, &show_dau_reg_port_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; /* 初始化线程锁, 用于发包线程与首保线程同步. */ pthread_mutex_init(&dau_ctrl.mutex, NULL); pthread_mutex_lock(&dau_ctrl.mutex); /* 启动 DAU */ _dau_start(); /* 初始化趋势数据处理线程. */ /* 配置线程RR调度, 优先级25 */ pthread_attr_init(&attr); param.sched_priority = 25; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _dau_trend_handle, NULL); if (rv != 0) { log_err(LOG_DAU, "PD can't create DAU data pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_TREND_DATA", pid); } pthread_attr_destroy(&attr); /* 初始化 DAU 报文处理线程. */ /* 配置线程RR调度, 优先级80 */ pthread_attr_init(&attr); param.sched_priority = 80; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _dau_sec_data_handle, NULL); if (rv != 0) { log_err(LOG_DAU, "PD can't create DAU data pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_DAU_DATA", pid); } pthread_attr_destroy(&attr); /* 初始化 DAU 测试线程. */ /* 配置线程RR调度, 优先级25 */ pthread_attr_init(&attr); param.sched_priority = 25; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _dau_test_handle, NULL); if (rv != 0) { log_err(LOG_DAU, "PD can't create DAU data pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_DAU_TEST", pid); } pthread_attr_destroy(&attr); return E_NONE; } /* 将 unit port 转换成 vport. */ int32_t dau_port_to_vport(uint8_t unit, uint8_t port) { uint8_t i = 0; uint8_t vport = 0; if (unit >= 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; } /* 端口配置刷新对外接口. */ int32_t dau_port_filter_set(uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint32_t temp = 0; if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { return E_BAD_PARAM; } if (port >= dau_node->port_num) { return E_BAD_PARAM; } temp = pd_config.config_real[unit][port].filter_cfg; switch(temp) { case CSG_FILTER_TYPE_FF: temp = PD_FILTER_TYPE_FF; break; case CSG_FILTER_TYPE_FR: temp = PD_FILTER_TYPE_FR; break; case CSG_FILTER_TYPE_LF: temp = PD_FILTER_TYPE_LF; break; case CSG_FILTER_TYPE_HF: temp = PD_FILTER_TYPE_HF; break; default: return E_BAD_PARAM; } temp = (temp << DAU_CR_FT_Pos); MODIFY_REG(dau_node->reg->reg_port[port].CR, DAU_CR_FT_Msk, temp); return E_NONE; } /* 端口类型设置. */ int32_t dau_port_type_set(uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint32_t temp = 0; if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { return E_BAD_PARAM; } if (port >= dau_node->port_num) { return E_BAD_PARAM; } temp = (pd_config.config_port[unit][port].port_type << DAU_CR_PT_Pos); MODIFY_REG(dau_node->reg->reg_port[port].CR, DAU_CR_PT_Msk, temp); if (PD_PORT_TYPE_UHF == pd_config.config_port[unit][port].port_type) { dau_node->port_func[port] = &uhf_func; } else if(PD_PORT_TYPE_AE == pd_config.config_port[unit][port].port_type) { dau_node->port_func[port] = &uhf_func; } else if(PD_PORT_TYPE_HF == pd_config.config_port[unit][port].port_type) { dau_node->port_func[port] = &hf_func; } else { dau_node->port_func[port] = &uhf_func; } return E_NONE; } /* PPS 主备模式配置 */ int32_t dau_pps_mode_set(void) { dau_t *dau_node = NULL; uint8_t unit = 0; uint32_t temp = 0; /* 自动 / 手动降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } temp = (pd_config.config.pps_mode << DAU_GCR_PPS_Pos); MODIFY_REG(dau_node->reg->reg_global.GCR, DAU_GCR_PPS_Msk, temp); } return E_NONE; } /* 同步模式配置 */ int32_t dau_sync_mode_set(void) { dau_t *dau_node = NULL; uint8_t unit = 0; uint32_t temp = 0; /* 自动 / 手动降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } temp = (pd_config.config.sync_mode << DAU_GCR_SYNC_Pos); MODIFY_REG(dau_node->reg->reg_global.GCR, DAU_GCR_SYNC_Msk, temp); } return E_NONE; } /* 内同步频率配置 */ int32_t dau_sync_fre_set(void) { dau_t *dau_node = NULL; uint8_t unit = 0; uint32_t temp = 0; /* 自动 / 手动降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } temp = (pd_config.config.power_frequency << DAU_GCR_OFRE_Pos); MODIFY_REG(dau_node->reg->reg_global.GCR, DAU_GCR_OFRE_Msk, temp); } return E_NONE; } /* 趋势间隔配置 */ int32_t dau_trend_inv_set(void) { dau_t *dau_node = NULL; uint8_t unit = 0; uint32_t temp = 0; /* 自动 / 手动降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } temp = ((pd_config.config.trend_period / 60) << DAU_GCR_TREND_Pos); MODIFY_REG(dau_node->reg->reg_global.GCR, DAU_GCR_TREND_Msk, temp); } return E_NONE; } /* 获取工频同步状态. */ int32_t dau_power_frequency_state_get(void) { dau_t *dau_node = NULL; uint8_t i = 0; for(i = 0; i < PD_DAU_SUM; i++) { dau_node = dau[i]; if (!dau_is_valid(dau_node)) { continue; } if (!((dau_node->reg->reg_global.GSR & DAU_GSR_SYNC_Msk) >> DAU_GSR_SYNC_Pos)) { return FALSE; } } return TRUE; } /* 获取工频周期. */ float dau_power_frequency_get(void) { dau_t *dau_node = NULL; float temp = 100000000.00; dau_node = dau[0]; if (!dau_is_valid(dau_node)) { return 0; } return dau_node->reg->reg_global.GPFPCCR ? (temp / dau_node->reg->reg_global.GPFPCCR) : 0; } /* 获取在线状态 */ uint8_t dau_connect_get(void) { dau_t *dau_node = NULL; dau_node = dau[0]; if (!dau_is_valid(dau_node)) { return 0; } return dau[0]->is_connect; } /* 获取端口状态寄存器. */ int32_t dau_param_adj_save(void) { dau_t *dau_node = NULL; dau_adj_t adj; int fd = 0; ssize_t len = 0; uint8_t port = 0; char cmd[128] = {0}; int32_t rv = E_NONE; dau_node = dau[0]; if (!dau_is_valid(dau_node)) { return E_NOT_FOUND; } /* 保存备份文件 */ snprintf(cmd, 128, "cp -rf %s %s", DAU_ADJ_FILE, DAU_ADJ_FILE_BAK); system(cmd); 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[0]->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); 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 版本号 */ char* dau_version_get(uint8_t unit, char *ver) { dau_t *dau_node = NULL; int major, minor; dau_node = dau[unit]; if (!dau_node) { return NULL; } major = (dau_node->reg->reg_global.GSCR & DAU_GSCR_PRIMARY_Msk) >> DAU_GSCR_PRIMARY_Pos; minor = (dau_node->reg->reg_global.GSCR & DAU_GSCR_SECONDARY_Msk) >> DAU_GSCR_SECONDARY_Pos; sprintf(ver, "%d.%d", major, minor); return ver; } /* 显示 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(" Version: %d.%d\r\n", (dau_node->reg->reg_global.GSCR & DAU_GSCR_PRIMARY_Msk) >> DAU_GSCR_PRIMARY_Pos, (dau_node->reg->reg_global.GSCR & DAU_GSCR_SECONDARY_Msk) >> DAU_GSCR_SECONDARY_Pos); printh(" Mode: %s\r\n", (dau_node->reg->reg_global.GSR & DAU_GSR_MODE_Msk) >> DAU_GSR_MODE_Pos ? "master" : "slave"); printh(" Synchronization: %s\r\n", (dau_node->reg->reg_global.GSR & DAU_GSR_SYNC_Msk) >> DAU_GSR_SYNC_Pos ? "valid" : "invalid"); printh(" Power frequency period: %.2f\r\n", dau_power_frequency_get()); printh(" Power frequency count: %d\r\n", dau_node->reg->reg_global.GSDPCR); printh(" Valid: %d\r\n\n", dau_node->is_valid); return; } /* 显示 DAU 状态. */ void dau_show_value(uint8_t unit) { dau_t *dau_node = NULL; uint8_t i = 0; 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 "); for(i = 0; i < dau_node->port_num; i++) { printh("%-05d ", dau_node->reg->reg_port[i].AVRO); } printh("\r\n "); for(i = 0; i < dau_node->port_num; i++) { printh("%-05d ", (dau_node->reg->reg_port[i].AVRP & DAU_AVRP_AVR_Msk) >> DAU_AVRP_AVR_Pos); } printh("\r\n "); for(i = 0; i < dau_node->port_num; i++) { printh("%-05d ", (dau_node->reg->reg_port[i].AVRP & DAU_AVRP_AVRA_Msk) >> DAU_AVRP_AVRA_Pos); } printh("\r\n\n"); return; } /* 显示 DAU 校准系数. */ void dau_show_adj(uint8_t unit) { dau_t *dau_node = NULL; dau_reg_port_t *reg = NULL; uint8_t port = 0; dau_node = dau[unit]; if (!dau_node) { return; } printh("DAU %d: \r\n", unit + 1); for(port = 0; port < dau_node->port_num; port++) { reg = &dau_node->reg->reg_port[port]; printh("%d | %05d %05d %05d | %05d %05d %05d | %05d %05d %05d |", port + 1, reg->AFR[0] & 0xFFFF, reg->AFR[0] >> 16, reg->ASPR[0], reg->AFR[1] & 0xFFFF, reg->AFR[1] >> 16, reg->ASPR[1], reg->AFR[2] & 0xFFFF, reg->AFR[2] >> 16, reg->ASPR[2]); printh(" %05d %05d %05d | %05d %05d %05d |\r\n", reg->AFR[3] & 0xFFFF, reg->AFR[3] >> 16, reg->ASPR[3], reg->AFR[4] & 0xFFFF, reg->AFR[4] >> 16, reg->ASPR[4]); } printh("\r\n"); } /* 显示 DAU 全局寄存器. */ void dau_show_reg(uint8_t unit) { dau_t *dau_node = NULL; uint32_t *reg = NULL; uint8_t num = 8; uint8_t row = 0; uint8_t col = 0; uint8_t i = 0; uint8_t j = 0; dau_node = dau[unit]; if (!dau_node) { return; } /* 每行显示 16 个寄存器, 计算需要多少行 */ row = num >> 4; if (num & 0x0f) { row++; } printh("DAU %d: \r\n", unit + 1); for(i = 0; i < row; i++) { /* 计算有多少列 */ col = num - (i << 4); col = col > 16 ? 16 : col; printh("R "); for(j = 0; j < col; j++) { printh("%-08x ", (i << 4) + j); } /* 打印寄存器值 */ reg = &dau_node->reg->reg_global.GSCR; reg += (i << 4); printh("\r\nV "); for(j = 0; j < col; j++) { printh("%08x ", reg[j]); } printh("\r\n\n"); } } /* 显示 DAU 端口寄存器. */ void dau_show_reg_port(uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint32_t *reg = NULL; uint8_t num = 36; uint8_t row = 0; uint8_t col = 0; uint8_t i = 0; uint8_t j = 0; dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { return; } /* 每行显示 16 个寄存器, 计算需要多少行 */ row = num >> 4; if (num & 0x0f) { row++; } printh("DAU %d port %d: \r\n", unit + 1, port + 1); for(i = 0; i < row; i++) { /* 计算有多少列 */ col = num - (i << 4); col = col > 16 ? 16 : col; printh("R "); for(j = 0; j < col; j++) { printh("%-08x ", (i << 4) + j); } reg = &dau_node->reg->reg_port[port].CR; reg += (i << 4); printh("\r\nV "); for(j = 0; j < col; j++) { printh("%08x ", reg[j]); } printh("\r\n\n"); } } #endif /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****/