Files
kunlun/plc/halmac/zc/zc_1/hw_zc_cmn.c
2024-09-28 14:24:04 +08:00

412 lines
12 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "mac_sys_reg.h"
#include "hw_reg_api.h"
#include "os_types.h"
#include "os_mem_api.h"
#include "plc_protocol.h"
#include "iot_config_api.h"
#include "iot_io_api.h"
#include "iot_board_api.h"
#include "iot_gpio_api.h"
#include "iot_errno_api.h"
#include "mac_zc_hw.h"
#include "hw_zc_cmn.h"
#include "mac_zc.h"
#include "gpio_mtx.h"
#if MAC_ZC_ENABLE
void mac_zc_hw_cap_set_period(uint8_t is_half_period)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
REG_FIELD_SET(CFG_ZC_CAP_HALF_PERIOD, tmp, !!is_half_period);
RGF_MAC_WRITE_REG(CFG_ZC_CAP_ADDR, tmp);
#else
(void)is_half_period;
#endif
}
void mac_zc_hw_cap_set_interval(uint16_t cap_interval_cnt)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
/* set mac zc hw N+1 period interval capture zc timestamp */
REG_FIELD_SET(CFG_ZC_CAP_INTERVAL, tmp, cap_interval_cnt);
RGF_MAC_WRITE_REG(CFG_ZC_CAP_ADDR, tmp);
#else
(void)cap_interval_cnt;
#endif
}
void mac_zc_hw_cap_set_watermark(uint8_t depth)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
/* set mac zc hw N+1 cnt capture generate interrupt */
REG_FIELD_SET(CFG_ZC_INT_NUM, tmp, depth);
RGF_MAC_WRITE_REG(CFG_ZC_CAP_ADDR, tmp);
#else
(void)depth;
#endif
}
uint32_t mac_zc_hw_cap_get_watermark(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
return REG_FIELD_GET(CFG_ZC_INT_NUM, RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR));
#else
return 0;
#endif
}
void mac_zc_hw_cap_set_edge(uint8_t is_fall_edge)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
REG_FIELD_SET(CFG_ZC_FALL, tmp, !!is_fall_edge);
RGF_MAC_WRITE_REG(CFG_ZC_CAP_ADDR, tmp);
#else
(void)is_fall_edge;
#endif
}
uint8_t mac_zc_hw_cap_get_edge(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
tmp = REG_FIELD_GET(CFG_ZC_FALL, tmp);
return (tmp ? MAC_ZC_HW_CAP_EDGE_FALL : MAC_ZC_HW_CAP_EDGE_RISE);
#else
return MAC_ZC_HW_CAP_EDGE_FALL;
#endif
}
void mac_zc_hw_capx_enable(uint8_t cap_bitmap, uint8_t enable)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
enable = !!enable;
if ((1 << MAC_ZC_HW_CAP0) & cap_bitmap) {
REG_FIELD_SET(CFG_ZC_CAP_ENABLE, tmp, enable);
}
if ((1 << MAC_ZC_HW_CAP1) & cap_bitmap) {
REG_FIELD_SET(CFG_ZC1_CAP_ENABLE, tmp, enable);
}
if ((1 << MAC_ZC_HW_CAP2) & cap_bitmap) {
REG_FIELD_SET(CFG_ZC2_CAP_ENABLE, tmp, enable);
}
RGF_MAC_WRITE_REG(CFG_ZC_CAP_ADDR, tmp);
#else
(void)cap_bitmap;
(void)enable;
#endif
}
void mac_zc_hw_capx_trig(uint8_t cap_bitmap)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_CAP_ADDR);
if ((1 << MAC_ZC_HW_CAP0) & cap_bitmap) {
REG_FIELD_SET(CFG_ZC_TRIG, tmp, 1);
}
if ((1 << MAC_ZC_HW_CAP1) & cap_bitmap) {
REG_FIELD_SET(CFG_ZC1_TRIG, tmp, 1);
}
if ((1 << MAC_ZC_HW_CAP2) & cap_bitmap) {
REG_FIELD_SET(CFG_ZC2_TRIG, tmp, 1);
}
RGF_MAC_WRITE_REG(CFG_ZC_CAP_ADDR, tmp);
#else
(void)cap_bitmap;
#endif
}
void mac_zc_hw_gen_set_phase_sel_mtx(uint8_t zc_gen_phase_sel)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_GEN_CTRL_ADDR);
/* value: 0~2. 0: use zc_detect0, 1: use zc_detect1, 2: use zc_detect2*/
REG_FIELD_SET(CFG_ZC_GEN_PHASE_SEL, tmp, zc_gen_phase_sel);
RGF_MAC_WRITE_REG(CFG_ZC_GEN_CTRL_ADDR, tmp);
#else
(void)zc_gen_phase_sel;
#endif
}
/* return detect num */
uint32_t mac_zc_hw_gen_get_phase_sel_mtx(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_GEN_CTRL_ADDR);
return REG_FIELD_GET(CFG_ZC_GEN_PHASE_SEL, tmp);
#else
return MAC_ZC_HW_DETECT0;
#endif
}
void mac_zc_hw_gen_set_gen_sel_mtx(uint8_t zc_gen_sel)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_GEN_CTRL_ADDR);
REG_FIELD_SET(CFG_ZC_GEN_SEL, tmp, zc_gen_sel);
RGF_MAC_WRITE_REG(CFG_ZC_GEN_CTRL_ADDR, tmp);
#else
(void)zc_gen_sel;
#endif
}
void mac_zc_hw_gen_set_ctrl_period(uint8_t is_half_period)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_GEN_CTRL_ADDR);
REG_FIELD_SET(CFG_ZC_GEN_HALF_PERIOD, tmp, is_half_period);
RGF_MAC_WRITE_REG(CFG_ZC_GEN_CTRL_ADDR, tmp);
#else
(void)is_half_period;
#endif
}
void mac_zc_hw_gen_set_ctrl_dur(uint32_t dur_ntb)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_GEN_CTRL_ADDR);
REG_FIELD_SET(CFG_ZC_DUR, tmp, dur_ntb);
RGF_MAC_WRITE_REG(CFG_ZC_GEN_CTRL_ADDR, tmp);
#else
(void)dur_ntb;
#endif
}
void mac_zc_hw_gen_set_offset(uint32_t offset_ntb, uint8_t offset_lr)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_GEN_OFFSET_ADDR);
REG_FIELD_SET(CFG_ZC_GEN_OFFSET, tmp, offset_ntb);
REG_FIELD_SET(CFG_ZC_GEN_OFFSET_LEFT, tmp, offset_lr);
RGF_MAC_WRITE_REG(CFG_ZC_GEN_OFFSET_ADDR, tmp);
#else
(void)offset_ntb;
(void)offset_lr;
#endif
}
void mac_zc_hw_set_vibrate_protect_dur(uint32_t dur_ntb)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_LCT_TRACK_CTRL_ADDR);
REG_FIELD_SET(CFG_ZC_VIBRATE_PROTECT, tmp, dur_ntb);
RGF_MAC_WRITE_REG(CFG_ZC_LCT_TRACK_CTRL_ADDR, tmp);
#else
(void)dur_ntb;
#endif
}
void mac_zc_hw_ac_track_trig(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp;
tmp = RGF_MAC_READ_REG(CFG_ZC_LCT_TRACK_CTRL_ADDR);
REG_FIELD_SET(CFG_HW_AC_TRACK_EN, tmp , 1);
REG_FIELD_SET(CFG_HW_AC_TRACK_TRIG, tmp, 1);
RGF_MAC_WRITE_REG(CFG_ZC_LCT_TRACK_CTRL_ADDR, tmp);
#endif
}
uint8_t mac_zc_hw_get_curr_cap_edge(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t tmp = 0x400;
/* get cap edge from mac debug bus */
RGF_MAC_WRITE_REG(CFG_MAC_DBG_CTRL1_ADDR, tmp);
tmp = RGF_MAC_READ_REG(CFG_MAC_DBG_BUS_ADDR);
return (uint8_t)(((tmp >> MAC_DBG_REG_CAP_EDGE_BIT) & 0x1) ?
MAC_ZC_HW_CAP_EDGE_RISE : MAC_ZC_HW_CAP_EDGE_FALL);
#else
return MAC_ZC_HW_CAP_EDGE_FALL;
#endif
}
uint32_t* mac_zc_hw_get_ts_base_addr(uint8_t cap_id)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
switch (cap_id) {
case MAC_ZC_HW_CAP0:
return (uint32_t*)(RGF_MAC_BASEADDR + CFG_ZC0_TS0_ADDR);
case MAC_ZC_HW_CAP1:
return (uint32_t*)(RGF_MAC_BASEADDR + CFG_ZC1_TS0_ADDR);
case MAC_ZC_HW_CAP2:
return (uint32_t*)(RGF_MAC_BASEADDR + CFG_ZC2_TS0_ADDR);
default:
IOT_ASSERT(0);
return NULL;
}
#else
(void)cap_id;
return NULL;
#endif
}
uint32_t mac_zc_hw_get_zc_period(uint8_t cap_id)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
switch (cap_id) {
case MAC_ZC_HW_CAP0:
return RGF_MAC_READ_REG(CFG_ZC0_PERIOD_ADDR);
case MAC_ZC_HW_CAP1:
return RGF_MAC_READ_REG(CFG_ZC1_PERIOD_ADDR);
case MAC_ZC_HW_CAP2:
return RGF_MAC_READ_REG(CFG_ZC2_PERIOD_ADDR);
default:
IOT_ASSERT(0);
return 0;
}
#else
(void)cap_id;
return 0;
#endif
}
void IRAM_ATTR mac_zc_hw_fix_map_gpio2sig(uint8_t gpio, uint8_t signal)
{
#if (HW_PLATFORM >= HW_PLATFORM_FPGA)
gpio_mtx_sig_in(signal, gpio, 1);
#else
(void)gpio;
(void)signal;
#endif
}
/* TODO: for war, calibration base on capx reg timestamp0~7.
* if not war, return capx reg timestamp7 value.
*/
uint32_t mac_zc_hw_get_last_zc_ts(uint8_t cap_id)
{
uint8_t i, j;
uint32_t cur_zc;
uint32_t data_ptr[MAC_ZC_HW_INT_NUM_MAX + 1] = {0};
mac_zc_hw_get_cap_data(data_ptr, cap_id, MAC_ZC_HW_INT_NUM_MAX + 1);
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
//TODO: use iot_snprintf()
iot_printf("[zc_hw]cap:%d=", cap_id);
for (i = MAC_ZC_HW_INT_NUM_MAX + 1; i > 0; i--) {
iot_printf(" %u", data_ptr[i - 1]);
}
iot_printf("\n");
#endif
for (i = MAC_ZC_HW_INT_NUM_MAX; i > 0; i--) {
if (data_ptr[i] != 0) {
/* find last !0 zc point */
break;
}
}
if (i == 0) {
cur_zc = data_ptr[0];
} else {
/* if bounce value, get the avg one */
if ((data_ptr[i] - data_ptr[0]) < MAC_ZC_HW_DEBOUNCE_NTB) {
cur_zc = mac_zc_get_ntb_mid(data_ptr[0], data_ptr[i]);
} else {
/* note: last version just get cur_zc in this method when cap_id
* is cap0 and cap2.
* In 2019/7/13's testing I find cap1's corresponding phase zc data is
* lag one cycle after trainning. According to the log, find the hw
* cap output is correct. Just the cur_zc method for cap1 is special.
* So it return wrong cur_zc which lag one cycle.
*/
for (j = i - 1; j > 0; j--) {
if((data_ptr[i] - data_ptr[j]) > MAC_ZC_HW_DEBOUNCE_NTB)
break;
}
cur_zc = mac_zc_get_ntb_mid(data_ptr[j + 1], data_ptr[i]);
}
}
return cur_zc;
}
/* init hw map info */
void mac_zc_hw_load_phase_map_def(mac_zc_hw_map_info_t *phase_map,
uint8_t phase_id)
{
IOT_ASSERT(phase_map && (phase_id < MAC_ZC_PHASE_CNT));
switch (phase_id) {
case MAC_ZC_PHASE_A:
phase_map->cap_id = MAC_ZC_HW_CAP0;
phase_map->signal = MAC_ZC_HW_SIG0_ID;
phase_map->gpio = iot_board_get_gpio(GPIO_PA_ZC);
phase_map->gpio_ext = iot_board_get_gpio(GPIO_PA_ZC_EXT);
break;
case MAC_ZC_PHASE_B:
phase_map->cap_id = MAC_ZC_HW_CAP1;
phase_map->signal = MAC_ZC_HW_SIG1_ID;
phase_map->gpio = iot_board_get_gpio(GPIO_PB_ZC);
phase_map->gpio_ext = iot_board_get_gpio(GPIO_PB_ZC_EXT);
break;
case MAC_ZC_PHASE_C:
phase_map->cap_id = MAC_ZC_HW_CAP2;
phase_map->signal = MAC_ZC_HW_SIG2_ID;
phase_map->gpio = iot_board_get_gpio(GPIO_PC_ZC);
phase_map->gpio_ext = iot_board_get_gpio(GPIO_PC_ZC_EXT);
break;
default:
break;
}
phase_map->phase_id = phase_id;
if ((0 != phase_map->gpio) && (GPIO_NO_VALID != phase_map->gpio)) {
if (ERR_OK != iot_gpio_open_as_input(phase_map->gpio)) {
iot_printf("[WARN]zc:open gpio:%u fail\n",
phase_map->gpio);
}
/* init gpio & signal map */
mac_zc_hw_fix_map_gpio2sig(phase_map->gpio, phase_map->signal);
}
if ((0 != phase_map->gpio_ext) && (GPIO_NO_VALID != phase_map->gpio_ext)) {
if (ERR_OK != iot_gpio_open_as_input(phase_map->gpio_ext)) {
iot_printf("[WARN]zc:open gpio_ext:%u fail\n",
phase_map->gpio_ext);
}
}
iot_printf("zc:[gpio:%u-%u sig:%u cap:%u phs_id:%u]\n",
phase_map->gpio, phase_map->gpio_ext,
phase_map->signal, phase_map->cap_id, phase_map->phase_id);
}
#endif