412 lines
12 KiB
C
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
|