mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
196 lines
4.3 KiB
C
196 lines
4.3 KiB
C
/*
|
|
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: zrq <ruiqi.zheng@artinchip.com>
|
|
*/
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <drivers/rt_inputcapture.h>
|
|
#include <drivers/pm.h>
|
|
|
|
#define LOG_TAG "CAP"
|
|
#include "aic_core.h"
|
|
#include "aic_hal_clk.h"
|
|
|
|
#include "hal_cap.h"
|
|
|
|
struct aic_cap {
|
|
struct rt_inputcapture_device rtdev;
|
|
struct aic_cap_data *data;
|
|
};
|
|
|
|
static struct aic_cap *g_cap[AIC_CAP_CH_NUM];
|
|
static struct aic_cap_data g_cap_info[] = {
|
|
#ifdef AIC_USING_CAP0
|
|
{.id = 0,
|
|
.flt_sel = AIC_CAP0_FLT_SEL,
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_CAP1
|
|
{.id = 1,
|
|
.flt_sel = AIC_CAP1_FLT_SEL,
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_CAP2
|
|
{.id = 2,
|
|
.flt_sel = AIC_CAP2_FLT_SEL,
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_CAP3
|
|
{.id = 3,
|
|
.flt_sel = AIC_CAP3_FLT_SEL,
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_CAP4
|
|
{.id = 4,
|
|
.flt_sel = AIC_CAP4_FLT_SEL,
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_CAP5
|
|
{.id = 5,
|
|
.flt_sel = AIC_CAP5_FLT_SEL,
|
|
},
|
|
#endif
|
|
};
|
|
|
|
static rt_err_t aic_cap_init(struct rt_inputcapture_device *capture)
|
|
{
|
|
struct aic_cap *aic_capture;
|
|
|
|
RT_ASSERT(capture != RT_NULL);
|
|
|
|
aic_capture = (struct aic_cap *)capture;
|
|
|
|
hal_cap_ch_init(aic_capture->data->id);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t aic_cap_open(struct rt_inputcapture_device *capture)
|
|
{
|
|
struct aic_cap *aic_capture;
|
|
|
|
RT_ASSERT(capture != RT_NULL);
|
|
|
|
aic_capture = (struct aic_cap *)capture;
|
|
|
|
hal_cap_in_config(aic_capture->data->id);
|
|
hal_cap_in_flt_sel(aic_capture->data->id, aic_capture->data->flt_sel);
|
|
hal_cap_cnt_start(aic_capture->data->id);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t aic_cap_close(struct rt_inputcapture_device *capture)
|
|
{
|
|
struct aic_cap *aic_capture;
|
|
|
|
RT_ASSERT(capture != RT_NULL);
|
|
|
|
aic_capture = (struct aic_cap *)capture;
|
|
|
|
hal_cap_int_enable(aic_capture->data->id, 0);
|
|
hal_cap_cnt_stop(aic_capture->data->id);
|
|
hal_cap_disable(aic_capture->data->id);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t aic_cap_get_pulsewidth(struct rt_inputcapture_device *capture, rt_uint32_t *pulsewidth_us)
|
|
{
|
|
struct aic_cap *aic_capture;
|
|
|
|
RT_ASSERT(capture != RT_NULL);
|
|
|
|
aic_capture = (struct aic_cap *)capture;
|
|
|
|
aic_capture->data->freq = round((float)PWMCS_CLK_RATE / (float)hal_cap_reg2(aic_capture->data->id));
|
|
aic_capture->data->duty = (float)hal_cap_reg1(aic_capture->data->id) * 100 / (float)hal_cap_reg2(aic_capture->data->id);
|
|
|
|
aic_capture->rtdev.parent.user_data = (void *)aic_capture->data;
|
|
|
|
*pulsewidth_us = hal_cap_reg2(aic_capture->data->id) / (PWMCS_CLK_RATE / 1000000);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static struct rt_inputcapture_ops aic_input_ops =
|
|
{
|
|
.init = aic_cap_init,
|
|
.open = aic_cap_open,
|
|
.close = aic_cap_close,
|
|
.get_pulsewidth = aic_cap_get_pulsewidth,
|
|
};
|
|
|
|
irqreturn_t aic_cap_irq(int irq, void *arg)
|
|
{
|
|
u32 stat;
|
|
|
|
for (int i = 0; i < AIC_CAP_CH_NUM; i++) {
|
|
stat = hal_cap_int_flg(i);
|
|
if (stat & CAP_EVENT3_FLG) {
|
|
rt_hw_inputcapture_isr(&g_cap[i]->rtdev, 0);
|
|
hal_cap_clr_flg(i, CAP_EVENT3_FLG);
|
|
}
|
|
}
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static rt_err_t aic_cap_probe(struct aic_cap_data *pdata)
|
|
{
|
|
struct aic_cap *cap;
|
|
rt_err_t ret = RT_EOK;
|
|
char aic_cap_device_name[10] = "";
|
|
|
|
cap = (struct aic_cap *)malloc(sizeof(struct aic_cap));
|
|
if (!cap) {
|
|
LOG_E("Failed to malloc(%d)\n", (u32)sizeof(struct aic_cap));
|
|
return -RT_ENOMEM;
|
|
}
|
|
|
|
cap->data = pdata;
|
|
cap->rtdev.ops = &aic_input_ops;
|
|
|
|
/* store the pointer */
|
|
g_cap[cap->data->id] = cap;
|
|
|
|
snprintf(aic_cap_device_name, 10, "cap%d", cap->data->id);
|
|
|
|
ret = rt_device_inputcapture_register(&cap->rtdev, aic_cap_device_name, NULL);
|
|
if (ret == RT_EOK) {
|
|
LOG_I("ArtInChip %s loaded", aic_cap_device_name);
|
|
} else {
|
|
LOG_E("%s register failed", aic_cap_device_name);
|
|
goto err;
|
|
}
|
|
|
|
return ret;
|
|
|
|
err:
|
|
if (cap)
|
|
free(cap);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int drv_cap_init(void)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
u32 i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(g_cap_info); i++) {
|
|
ret = aic_cap_probe(&g_cap_info[i]);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
hal_cap_init();
|
|
aicos_request_irq(PWMCS_CAP_IRQn, aic_cap_irq, 0, NULL, NULL);
|
|
|
|
return ret;
|
|
}
|
|
INIT_DEVICE_EXPORT(drv_cap_init);
|