Files
AC707N/SDK/cpu/components/rdec.c
T

148 lines
3.7 KiB
C

#include "cpu.h"
#include "rdec.h"
#include "clock.h"
#include "gpio.h"
const static u8 rdec_index_table[] = {IRQ_RDECx_IDX_LIST};
static void (*rdec_cb_table[RDEC_MAX_NUM])(u32 tid);
/* AT(.gptimer.text.cache.L1) */
___interrupt
static void rdec0_irq()
{
/* RDEC0->CON |= BIT(RDEC_CPND); */
if (rdec_cb_table[0]) {
rdec_cb_table[0](0);
}
}
static void (* const rdecx_irq_table[])(void) = {
rdec0_irq,
};
_INLINE_ static RDEC *rdec_id2rdec(u32 id)
{
ASSERT(id < RDEC_MAX_NUM, "func:%s(),line:%d, rdecx max num %d", __func__, __LINE__, RDEC_MAX_NUM);
return (RDEC_REG_BASE_ADDR + id * RDEC_REG_OFFSET);
}
u32 rdec_init(const struct rdec_config *cfg)
{
u32 id = cfg->rdec_x;
ASSERT(id < RDEC_MAX_NUM, "func:%s(),line:%d, rdecx max num %d", __func__, __LINE__, RDEC_MAX_NUM);
u32 con = 0;
u32 smp = 0;
u32 rdec_spnd = clk_get("lsb") / RDEC_FREQ / 16; //计算采样频率
SFR(con, RDEC_SPND, 16, rdec_spnd); //设置采样频率
if (cfg->irq_cb) {
rdec_cb_table[id] = cfg->irq_cb;
request_irq(rdec_index_table[id], cfg->irq_priority, rdecx_irq_table[id], 0);
}
if (cfg->work_mode == RDEC_WORK_AUTO) {
con &= ~BIT(RDEC_INT_MODE);
unrequest_irq(rdec_index_table[id]); //防止意外注册了中断
} else if (cfg->work_mode == RDEC_WORK_TIMER) {
con |= BIT(RDEC_INT_MODE);
smp = RDEC_TIME * RDEC_FREQ / 1000000 - 1; //T = (smp+1)/sr_clk
} else if (cfg->work_mode == RDEC_WORK_INTR) {
con &= ~BIT(RDEC_INT_MODE);
}
SFR(con, RDEC_MODE, 2, cfg->phase_mode); //设置phase模式
con &= ~BIT(RDEC_POL); //设置极性翻转
con &= ~BIT(RDEC_EN); //初始化默认关闭
gpio_set_function(IO_PORT_SPILT(cfg->rdec_a), PORT_FUNC_RDEC0_PORTA + 2 * id);
gpio_set_function(IO_PORT_SPILT(cfg->rdec_b), PORT_FUNC_RDEC0_PORTB + 2 * id);
RDEC *RDECx = rdec_id2rdec(id);
RDECx->SMP = 0;
RDECx->CON = BIT(RDEC_CPND);
RDECx->SMP = smp;
RDECx->CON = con;
return id;
}
u32 rdec_start(u32 id)
{
RDEC *RDECx = rdec_id2rdec(id);
RDECx->CON |= BIT(RDEC_EN);
return 0;
}
u32 rdec_pause(u32 id)
{
RDEC *RDECx = rdec_id2rdec(id);
RDECx->CON &= ~BIT(RDEC_EN);
return 0;
}
u32 rdec_resume(u32 id)
{
RDEC *RDECx = rdec_id2rdec(id);
RDECx->CON |= BIT(RDEC_EN);
return 0;
}
int rdec_get_value(u32 id)
{
s8 data = 0;
RDEC *RDECx = rdec_id2rdec(id);
if (RDECx->CON & BIT(RDEC_PND)) {
RDECx->CON |= BIT(RDEC_CPND);
asm("csync");
data = RDECx->DAT;
}
return data;
}
void rdec_dump()
{
for (u8 id = RDEC_0; id < RDEC_MAX_NUM; id++) {
RDEC *RDECx = rdec_id2rdec(id);
printf("RDEC%d->CON:0x%x\n", id, RDECx->CON);
printf("RDEC%d->SMP:0x%x\n", id, RDECx->SMP);
}
}
struct _rdec_reg {
u32 con;
u32 smp;
};
static struct _rdec_reg rdec_reg[RDEC_MAX_NUM] AT_VOLATILE_RAM_BSS_LOWPOWER;
static u8 rdec_enter_deepsleep(void)
{
for (u32 i = 0; i < RDEC_MAX_NUM; i++) {
RDEC *RDECx = (RDEC *)rdec_id2rdec(i);
if (RDECx->CON == 0) {
rdec_reg[i].con = 0;
continue;
}
rdec_reg[i].con = RDECx->CON;
rdec_reg[i].smp = RDECx->SMP;
}
return 0;
}
AT_VOLATILE_CACHE_CODE_LOWPOWER
static u8 rdec_exit_deepsleep(void)
{
for (u32 i = 0; i < RDEC_MAX_NUM; i++) {
RDEC *RDECx = (RDEC *)(RDEC_REG_BASE_ADDR + i * RDEC_REG_OFFSET);
if (rdec_reg[i].con == 0) {
continue;
}
RDECx->CON = rdec_reg[i].con;
RDECx->SMP = rdec_reg[i].smp;
}
return 0;
}
DEEPSLEEP_TARGET_REGISTER(rdec) = {
.name = "rdec",
.enter = rdec_enter_deepsleep,
.exit = rdec_exit_deepsleep,
};