KT24-1110_65E-HA-651B/cpu/br25/irflt.c
2024-11-10 18:44:17 +08:00

313 lines
8.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "asm/includes.h"
#include "asm/irflt.h"
#include "timer.h"
#include "generic/gpio.h"
#define ir_log log_d
//红外定时器定义
#define IR_TIMER TIMER5
#define IR_IRQ_TIME_IDX IRQ_TIME5_IDX
#define IR_TIME_REG JL_TIMER5
#define IRFLT_OUTPUT_TIMER_SEL(x) SFR(JL_IOMAP->CON0, 5, 3, x)
IR_CODE ir_code; ///<红外遥控信息
static u8 cmp_start = 0;
static const u16 timer_div[] = {
/*0000*/ 1,
/*0001*/ 4,
/*0010*/ 16,
/*0011*/ 64,
/*0100*/ 2,
/*0101*/ 8,
/*0110*/ 32,
/*0111*/ 128,
/*1000*/ 256,
/*1001*/ 4 * 256,
/*1010*/ 16 * 256,
/*1011*/ 64 * 256,
/*1100*/ 2 * 256,
/*1101*/ 8 * 256,
/*1110*/ 32 * 256,
/*1111*/ 128 * 256,
};
/*----------------------------------------------------------------------------*/
/**@brief time1红外中断服务函数
@param void
@param void
@return void
@note void timer1_ir_isr(void)
*/
/*----------------------------------------------------------------------------*/
___interrupt
void timer_ir_isr(void)
{
IR_TIME_REG->CON |= BIT(14);
u16 bCap1 = IR_TIME_REG->PRD;
IR_TIME_REG->CNT = 0;
u8 cap = bCap1 / ir_code.timer_pad;
ir_code.boverflow = 0;
if (cmp_start < 3) {
return;
}
/* putchar('0' + (cap/10)); */
/* putchar('0' + (cap%10)); */
if (cap <= 1) {
ir_code.wData >>= 1;
ir_code.bState++;
} else if (cap == 2) {
ir_code.wData >>= 1;
ir_code.wData |= 0x8000;
ir_code.bState++;
}
if (ir_code.bState == 16) {
ir_code.wUserCode = ir_code.wData;
}
if (ir_code.bState == 33) {
ir_code.bState = 1;
}
}
/*----------------------------------------------------------------------------*/
/**@brief ir按键初始化
@param void
@param void
@return void
@note void set_ir_clk(void)
((cnt - 1)* 分频数)/lsb_clk = 1ms
*/
/*----------------------------------------------------------------------------*/
/* #define APP_TIMER_CLK clk_get("timer")//选osc时钟源 */
#define APP_TIMER_CLK 12000000L //pll12m
#define TIMER_UNIT_MS 1
#define MAX_TIME_CNT 0x07ff //分频准确范围,更具实际情况调整
#define MIN_TIME_CNT 0x0030
void set_ir_clk(void)
{
u32 prd_cnt;
u8 index;
for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) {
prd_cnt = TIMER_UNIT_MS * (APP_TIMER_CLK / 1000) / timer_div[index];
if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) {
break;
}
}
ir_code.timer_pad = prd_cnt;
cmp_start = 0;
request_irq(IR_IRQ_TIME_IDX, 5, timer_ir_isr, 0);
/* IR_TIME_REG->CON = ((index << 4) | BIT(3) | BIT(1) | BIT(0));//选择osc时钟 */
JL_IOMAP->CON0 |= BIT(21);//这里已选了timer5,时钟源选io信号里的pll_12m,不是所有的timer都可选pll,修改请看文档
IR_TIME_REG->CON = ((index << 4) | BIT(2) | BIT(1) | BIT(0));
}
/*----------------------------------------------------------------------------*/
/**@brief 获取ir按键值
@param void
@param void
@return void
@note void get_irkey_value(void)
*/
/*----------------------------------------------------------------------------*/
u8 get_irflt_value(void)
{
u8 tkey = 0xff;
if (ir_code.bState != 32) {
return tkey;
}
if ((((u8 *)&ir_code.wData)[0] ^ ((u8 *)&ir_code.wData)[1]) == 0xff) {
tkey = (u8)ir_code.wData;
} else {
ir_code.bState = 0;
}
return tkey;
}
static u8 ir_io_level = 0;
static u8 ir_io = 0;
void ir_input_io_sel(u8 port)
{
//选择input channel1输入
// IOMC2[13 : 8]
// 0 ~ 15: PA0 ~ PA15
//16 ~ 31: PB0 ~ PB15
//32 ~ 47: PC0 ~ PC15
//48 ~ 55: PD0 ~ PD7
ir_io = port;
gpio_irflt_in(port);
gpio_set_direction(port, 1);
gpio_set_die(port, 1);
gpio_set_pull_up(port, 1);
gpio_set_pull_down(port, 0);
}
void ir_output_timer_sel()
{
IRFLT_OUTPUT_TIMER_SEL(IR_TIMER);
}
static void ir_timeout(void *priv)
{
ir_code.boverflow++;
if (ir_code.boverflow > 56) { //56*2ms ~= 112ms
ir_code.boverflow = 56;
ir_code.bState = 0;
}
cmp_start ++;
if (cmp_start > 3) {
cmp_start = 3;
}
}
void ir_timeout_set(void)
{
sys_s_hi_timer_add(NULL, ir_timeout, 2); //2ms
}
static u8 ir_io_sus = 0;
u8 ir_io_suspend(void)
{
if (ir_io_sus) {
return 1;
}
if (ir_code.boverflow < 7) { //14ms内红外接收有可能在忙碌
return 1;
}
ir_io_level = gpio_read(ir_io);
IR_TIME_REG->CON |= BIT(14);
IR_TIME_REG->CON &= ~(0b11 << 0);
ir_io_sus = 1;
return 0;
}
u8 ir_io_resume(void)
{
if (!ir_io_sus) {
return 0;
}
ir_io_sus = 0;
gpio_set_direction(ir_io, 1);
gpio_set_die(ir_io, 1);
gpio_set_pull_up(ir_io, 1);
gpio_set_pull_down(ir_io, 0);
delay(10);
if ((ir_io_level) && (ir_io_level != (gpio_read(ir_io)))) {
ir_code.boverflow = 0;
}
cmp_start = 0;
IR_TIME_REG->CNT = 0;
IR_TIME_REG->CON |= BIT(14);
IR_TIME_REG->CON |= (0b11 << 0);
return 0;
}
void irflt_config()
{
JL_IR->RFLT_CON = 0;
/* JL_IR->RFLT_CON |= BIT(7); //256 div */
/* JL_IR->RFLT_CON |= BIT(3); //osc 24m */
JL_IR->RFLT_CON |= BIT(7) | BIT(4); //512 div
JL_IR->RFLT_CON |= BIT(3) | BIT(2); //PLL_48m兼容省晶振
JL_IR->RFLT_CON |= BIT(0); //irflt enable
set_ir_clk();
}
void log_irflt_info()
{
ir_log("IOMC0 = 0x%x", JL_IOMAP->CON0);
ir_log("IOMC2 = 0x%x", JL_IOMAP->CON2);
ir_log("RFLT_CON = 0x%x", JL_IR->RFLT_CON);
ir_log("IR_TIME_REG = 0x%x", IR_TIME_REG->CON);
}
static u32 prd_1us = 0;
static u32 send_cnt = 0;
static u32 send_val = 0;
___interrupt
void timer5_isr(void)
{
JL_TIMER5->CON |= BIT(14);
send_cnt ++;
if (send_cnt % 2) {
return;
}
u32 cnt = send_cnt / 2;
if (cnt == 1) {
JL_TIMER5->PRD = prd_1us * 5060;
JL_TIMER5->PWM = prd_1us * 4500;
JL_TIMER5->CNT = JL_TIMER5->PRD;
} else if (cnt == 34) {
JL_TIMER5->CON &= ~BIT(0);
send_cnt = 0;
return;
} else if (send_val & BIT(33 - cnt)) {
JL_TIMER5->PRD = prd_1us * 2240;
JL_TIMER5->PWM = prd_1us * 1680;
JL_TIMER5->CNT = JL_TIMER5->PRD;
} else {
JL_TIMER5->PRD = prd_1us * 1120;
JL_TIMER5->PWM = prd_1us * 560;
JL_TIMER5->CNT = JL_TIMER5->PRD;
}
}
void timer5_send_ir_init(u32 port)
{
u32 src_clk = 12000000;
JL_IOMAP->CON0 |= BIT(21);//timer的io输入选择内部pll_12m,不是所有的timer的io输入都可选pll,修改请看文档
JL_TIMER5->CON = 0;
JL_TIMER5->CON |= (0b01 << 2); //时钟源选择timer io
JL_TIMER5->CON |= (0b0001 << 4); //时钟源4分频
JL_TIMER5->CON |= BIT(9); //波形反向
prd_1us = (src_clk / (4 * 1000000)); //1us的计数值
request_irq(IRQ_TIME5_IDX, 5, timer5_isr, 0);
if ((IO_PORTB_07 == port) || (IO_PORTA_03 == port)) {//硬件iobr25的timer5有两个硬件IO口
gpio_set_die(port, 1);
gpio_set_pull_up(port, 0);
gpio_set_pull_down(port, 0);
gpio_set_direction(port, 0);
JL_TIMER5->CON |= BIT(8); //PWM使能
} else {
gpio_output_channle(port, CH2_T5_PWM_OUT); //任意IO使用outputchannel
}
}
void timer5_send_ir_data(u32 ir_data)
{
send_val = ir_data;
send_cnt = 0;
JL_TIMER5->PRD = prd_1us * 9560; //设置周期 = 1us * 9605 = 9605us
JL_TIMER5->PWM = prd_1us * 560; //设置高电平时间
JL_TIMER5->CNT = JL_TIMER5->PRD; //计数值先给满起一次pend后JL_TIMER->PWM寄存器才有效
JL_TIMER5->CON |= BIT(0); //使能timer模块
}
void timer5_send_ir_test(void)
{
/* timer5_send_ir_init(IO_PORTB_07); */
timer5_send_ir_init(IO_PORTA_02);
extern void wdt_clr();
while (1) {
wdt_clr();
timer5_send_ir_data(0x6699aa55);
os_time_dly(100);
}
}