339 lines
9.6 KiB
C
339 lines
9.6 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 "iot_sg.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_gpio_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "iot_sg_sta_ext_mf.h"
|
|
|
|
#if IOT_SMART_GRID_EXT_MF_ENABLE
|
|
|
|
/* define power meter multi function signal input GPIO port */
|
|
#define IOT_SG_STA_EXT_MF_GPIO (GPIO_MULTI_PULSE)
|
|
/* define MF interrupt input pin pulse effective time */
|
|
#define IOT_SG_STA_EXT_MF_VALID_PULSE_TIME_US (500)
|
|
/* define unsigned int max value for improve exec efficiency */
|
|
#define IOT_SG_STA_EXT_MF_UINT32_MAX (~((unsigned int)0))
|
|
/* define second pulse cycle 10 min */
|
|
#define IOT_SG_STA_EXT_MF_SECOND_PULSE_COUNT (10 * 60)
|
|
|
|
#define IOT_SG_STA_EXT_MF_TIME_INTERVAL(start, end) \
|
|
((end) > (start) ? \
|
|
(end) - (start) : \
|
|
IOT_SG_STA_EXT_MF_UINT32_MAX - (start) + (end))
|
|
|
|
static void iot_sg_sta_ext_mf_gpio_interrupt_handle(int arg)
|
|
{
|
|
uint8_t gpio_value = 0;
|
|
uint32_t ticks = 0, interval = 0;
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
|
|
(void)arg;
|
|
if (!mf_glb) {
|
|
return;
|
|
}
|
|
gpio_value = (uint8_t)iot_gpio_value_get(mf_glb->gpio_num);
|
|
if (gpio_value == ERR_FAIL) {
|
|
return;
|
|
}
|
|
ticks = iot_gpio_get_trigger_ticks(mf_glb->gpio_num);
|
|
|
|
if (gpio_value) {
|
|
mf_glb->rising_ticks = ticks;
|
|
mf_glb->tick_valid = 1;
|
|
return;
|
|
} else {
|
|
if (!mf_glb->tick_valid) {
|
|
return;
|
|
}
|
|
/* step: calc high-level duration, check if pulse valid */
|
|
interval = IOT_SG_STA_EXT_MF_TIME_INTERVAL(mf_glb->rising_ticks, ticks);
|
|
if (interval < IOT_SG_STA_EXT_MF_VALID_PULSE_TIME_US) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
mf_glb->pulse_count++;
|
|
mf_glb->last_ticks = mf_glb->rising_ticks;
|
|
if (mf_glb->mode == IOT_SG_STA_EXT_MF_MODE_PPS_CYCLE) {
|
|
if (!mf_glb->info.sec_pulse.valid) {
|
|
mf_glb->info.sec_pulse.valid = 1;
|
|
mf_glb->info.sec_pulse.start_tick = mf_glb->rising_ticks;
|
|
}
|
|
if (mf_glb->pulse_count >= IOT_SG_STA_EXT_MF_SECOND_PULSE_COUNT) {
|
|
mf_glb->info.sec_pulse.complete = 1;
|
|
iot_gpio_interrupt_enable(mf_glb->gpio_num, 0);
|
|
}
|
|
} else {
|
|
if (mf_glb->info.pulse.index < mf_glb->info.pulse.buffer_cnt) {
|
|
mf_glb->info.pulse.buffer[mf_glb->info.pulse.index] =
|
|
mf_glb->rising_ticks;
|
|
mf_glb->info.pulse.index += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void iot_sg_sta_ext_mf_refresh()
|
|
{
|
|
uint32_t total = 0, cycle = 0;
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
iot_sg_sta_ext_pulse_info_t *pulse = &mf_glb->info.pulse;
|
|
iot_sg_sta_ext_sec_pulse_info_t *sec_pulse = &mf_glb->info.sec_pulse;
|
|
|
|
if (!mf_glb) {
|
|
return;
|
|
}
|
|
if (!mf_glb->running) {
|
|
return;
|
|
}
|
|
if (mf_glb->mode == IOT_SG_STA_EXT_MF_MODE_PPS_CYCLE) {
|
|
if (sec_pulse->complete) {
|
|
total = IOT_SG_STA_EXT_MF_TIME_INTERVAL(
|
|
mf_glb->info.sec_pulse.start_tick, mf_glb->last_ticks);
|
|
cycle = total / (IOT_SG_STA_EXT_MF_SECOND_PULSE_COUNT - 1);
|
|
if (sec_pulse->callback) {
|
|
sec_pulse->complete = 0;
|
|
mf_glb->running = 0;
|
|
sec_pulse->callback(cycle);
|
|
}
|
|
}
|
|
} else if (mf_glb->mode == IOT_SG_STA_EXT_MF_MODE_PULSE_COUNT) {
|
|
if (pulse->pending) {
|
|
pulse->pending = 0;
|
|
iot_gpio_interrupt_enable(mf_glb->gpio_num, 1);
|
|
} else if (pulse->remain_time) {
|
|
pulse->remain_time--;
|
|
if (!pulse->remain_time) {
|
|
iot_sg_sta_ext_mf_stop();
|
|
}
|
|
}
|
|
}
|
|
iot_sg_printf("%s count %lu\n", __FUNCTION__, mf_glb->pulse_count);
|
|
}
|
|
|
|
uint32_t iot_sg_sta_ext_mf_init()
|
|
{
|
|
uint8_t reason = 0;
|
|
uint32_t ret = ERR_OK;
|
|
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = NULL;
|
|
|
|
if (!sta_glb) {
|
|
ret = ERR_NOT_READY;
|
|
goto out;
|
|
}
|
|
mf_glb = sta_glb->mf;
|
|
if (mf_glb) {
|
|
goto out;
|
|
}
|
|
sta_glb->mf = os_mem_malloc(IOT_SMART_GRID_MID, sizeof(*mf_glb));
|
|
if (!sta_glb->mf) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
mf_glb = sta_glb->mf;
|
|
os_mem_set(mf_glb, 0, sizeof(*mf_glb));
|
|
mf_glb->gpio_num = iot_board_get_gpio(IOT_SG_STA_EXT_MF_GPIO);
|
|
if (mf_glb->gpio_num == GPIO_NO_VALID) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
ret = iot_gpio_open_as_interrupt(mf_glb->gpio_num);
|
|
if (ret) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
ret = iot_gpio_interrupt_config(mf_glb->gpio_num, GPIO_INT_EDGE_BOTH,
|
|
iot_sg_sta_ext_mf_gpio_interrupt_handle, 0, GPIO_INT_FUNC_GET_TICKS);
|
|
if (ret) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
iot_sg_printf("%s gpio %lu\n", __FUNCTION__, mf_glb->gpio_num);
|
|
|
|
out:
|
|
if (reason) {
|
|
iot_sg_printf("%s failed %lu\n", __FUNCTION__, reason);
|
|
iot_gpio_close(mf_glb->gpio_num);
|
|
mf_glb->gpio_num = GPIO_NO_VALID;
|
|
os_mem_free(p_sg_glb->desc.sta->mf);
|
|
p_sg_glb->desc.sta->mf = NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void iot_sg_sta_ext_mf_deinit()
|
|
{
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
|
|
iot_sg_printf("%s\n", __FUNCTION__);
|
|
if (mf_glb) {
|
|
if (mf_glb->gpio_num != GPIO_NO_VALID) {
|
|
iot_gpio_close(mf_glb->gpio_num);
|
|
}
|
|
os_mem_free(mf_glb);
|
|
p_sg_glb->desc.sta->mf = NULL;
|
|
}
|
|
}
|
|
|
|
uint32_t iot_sg_sta_ext_mf_start_second_pulse_monitor(
|
|
iot_sg_sta_ext_mf_sec_pulse_finish_handle callback)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
|
|
if (!mf_glb) {
|
|
ret = ERR_NOT_READY;
|
|
goto out;
|
|
}
|
|
if (mf_glb->running) {
|
|
ret = ERR_BUSY;
|
|
goto out;
|
|
}
|
|
|
|
mf_glb->mode = IOT_SG_STA_EXT_MF_MODE_PPS_CYCLE;
|
|
mf_glb->pulse_count = 0;
|
|
mf_glb->tick_valid = 0;
|
|
mf_glb->rising_ticks = 0;
|
|
os_mem_set(&mf_glb->info, 0, sizeof(mf_glb->info));
|
|
mf_glb->info.sec_pulse.callback = callback;
|
|
iot_gpio_interrupt_enable(mf_glb->gpio_num, 1);
|
|
mf_glb->running = 1;
|
|
iot_sg_printf("%s\n", __FUNCTION__);
|
|
out:
|
|
if (ret) {
|
|
iot_sg_printf("%s failed %d\n", __FUNCTION__, ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint32_t iot_sg_sta_ext_mf_start_pulse_monitor(
|
|
uint32_t *buffer, uint32_t buffer_count, uint32_t exec_time,
|
|
iot_sg_sta_ext_mf_pulse_finish_handle callback)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
|
|
IOT_ASSERT(buffer || (buffer == NULL && buffer_count == 0));
|
|
if (!mf_glb) {
|
|
ret = ERR_NOT_READY;
|
|
goto out;
|
|
}
|
|
if (mf_glb->running) {
|
|
ret = ERR_BUSY;
|
|
goto out;
|
|
}
|
|
|
|
mf_glb->mode = IOT_SG_STA_EXT_MF_MODE_PULSE_COUNT;
|
|
mf_glb->pulse_count = 0;
|
|
mf_glb->tick_valid = 0;
|
|
mf_glb->rising_ticks = 0;
|
|
os_mem_set(&mf_glb->info, 0, sizeof(mf_glb->info));
|
|
mf_glb->info.pulse.buffer = buffer;
|
|
mf_glb->info.pulse.buffer_cnt = buffer_count;
|
|
mf_glb->info.pulse.callback = callback;
|
|
mf_glb->info.pulse.remain_time = exec_time;
|
|
if (!exec_time) {
|
|
iot_gpio_interrupt_enable(mf_glb->gpio_num, 1);
|
|
} else {
|
|
mf_glb->info.pulse.pending = 1;
|
|
}
|
|
mf_glb->running = 1;
|
|
iot_sg_printf("%s\n", __FUNCTION__);
|
|
out:
|
|
if (ret) {
|
|
iot_sg_printf("%s failed %d\n", __FUNCTION__, ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void iot_sg_sta_ext_mf_stop()
|
|
{
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
|
|
if (!mf_glb) {
|
|
return;
|
|
}
|
|
if (mf_glb->mode == IOT_SG_STA_EXT_MF_MODE_PULSE_COUNT) {
|
|
mf_glb->info.pulse.pending = 0;
|
|
}
|
|
if (mf_glb->running) {
|
|
iot_sg_printf("%s\n", __FUNCTION__);
|
|
iot_gpio_interrupt_enable(mf_glb->gpio_num, 0);
|
|
mf_glb->running = 0;
|
|
if (mf_glb->mode == IOT_SG_STA_EXT_MF_MODE_PULSE_COUNT) {
|
|
mf_glb->info.pulse.remain_time = 0;
|
|
if (mf_glb->info.pulse.callback) {
|
|
mf_glb->info.pulse.callback(mf_glb->pulse_count);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uint8_t iot_sg_sta_ext_mf_is_running()
|
|
{
|
|
uint8_t running = 0;
|
|
iot_sg_sta_ext_mf_glb_t *mf_glb = p_sg_glb->desc.sta->mf;
|
|
|
|
if (mf_glb) {
|
|
running = mf_glb->running;
|
|
}
|
|
return running;
|
|
}
|
|
|
|
#else
|
|
|
|
void iot_sg_sta_ext_mf_refresh()
|
|
{
|
|
}
|
|
|
|
uint32_t iot_sg_sta_ext_mf_init()
|
|
{
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
void iot_sg_sta_ext_mf_deinit()
|
|
{
|
|
}
|
|
|
|
uint32_t iot_sg_sta_ext_mf_start_second_pulse_monitor(
|
|
iot_sg_sta_ext_mf_sec_pulse_finish_handle callback)
|
|
{
|
|
(void)callback;
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
uint32_t iot_sg_sta_ext_mf_start_pulse_monitor(
|
|
uint32_t *buffer, uint32_t buffer_count, uint32_t exec_time,
|
|
iot_sg_sta_ext_mf_pulse_finish_handle callback)
|
|
{
|
|
(void)buffer;
|
|
(void)buffer_count;
|
|
(void)exec_time;
|
|
(void)callback;
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
void iot_sg_sta_ext_mf_stop()
|
|
{
|
|
}
|
|
|
|
uint8_t iot_sg_sta_ext_mf_is_running()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif
|