You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1818 lines
43 KiB
C

2 days ago
/*****************************************************************************
* 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
*
* <h2><center>&copy; COPYRIGHT(c) 2021 LandPower</center></h2>
*
* 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 <sys/mman.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#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, &param);
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, &param);
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, &param);
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 ****/