7.3.5. 设计说明

7.3.5.1. 源码说明

CIR模块的源码位于 bsp/artinchip/:

  • bsp/artinchip/drv/cir/drv_cir.c,cir driver层接口实现

  • bsp/artinchip/include/drv/drv_cir.h,cir driver层接口头文件

  • bsp/artinchip/drv/cir/nec_decoder.c,NEC协议编解码实现

  • bsp/artinchip/drv/cir/rc5_decoder.c,RC5协议编解码实现

  • bsp/artinchip/drv/cir/ir_raw.c,编解码调用及注册接口实现

  • bsp/artinchip/drv/cir/ir_raw.h,编解码调用及注册接口头文件

  • bsp/artinchip/hal/cir/hal_cir.c,cir hal层接口实现

  • bsp/artinchip/include/hal/hal_cir.h,cir hal层接口头文件及寄存器定义

7.3.5.2. 模块架构

linux内核中rc的基本框架如下图所示:

../../../_images/rc_arch.png

红外信号的编码和解码工作由CIR协议负责完成。在完成编码后,应用层需要发送的信号被编码为一系列的带有宽度的高低电平(pulse/space),CIR driver在发送端就是需要将这一系列的pulse/space写入发送FIFO发送出去。在接收红外信号时,CIR driver需要将接收到的一系列高低电平送入到CIR协议进行解码,最终将解码得到的scancode返回给driver层,最终送给app程序完成红外信号的接收。所以,CIR驱动的主要任务有:

  1. 将编码得到的高低电平信号以游码的形式写入TX-FIFO,发送红外信号

  2. 将CIR模块接收的RX-FIFO中的游码正确表示为高低电平的形式,相邻的高电平或低电平需要进行合并。

  3. 根据用户空间传递的红外参数,对CIR的底层寄存器进行配置,如配置载波频率,配置占空比等

由于红外信号的数据量都很少,所以在红外信号的发送端,一般是利用循环将所有的数据一次性全部发送出去,而不会采用中断或DMA的方式。在红外信号的接收端,一般是采用中断的方式进行数据的接收,在接收完成后,调用相应的CIR协议解码函数进行解码。

CIR模块理论上可以支持任何的红外协议,对不同红外协议的支持可以通过对载波配置寄存器的设置来实现。luban-lite中目前提供了NEC和RC5协议的编解码,默认配置的是NEC协议。

7.3.5.3. 关键流程设计

7.3.5.3.1. 初始化流程

CIR模块的初始化流程如下:

  1. 释放clock和reset信号

  2. 设置噪声阈值,接收激活阈值,空闲阈值等底层配置

  3. 设置TX-FIFO和RX-FIFO的阈值

  4. 将所选择的CIR协议注册到cir_raw_handler_list链表

7.3.5.3.2. 中断处理流程

CIR模块使能RX的溢出中断、RXFIFO可用中断、接收完成中断。

中断执行流程如下:

../../../_images/interrupt_flow1.png

7.3.5.3.3. CIR协议注册

cir的driver层驱动定义了一个全局链表cir_raw_handler_list,在系统启动时,会根据menuconfig中所选择的红外协议进行注册,实际就是将红外协议添加到链表cir_raw_handler_list,可将NEC和RC5协议同时注册到链表。应用层的代码通过 rt_device_control 设置将要使用的红外协议。在对数据进行编解码时,会查找cir_raw_handler_list链表上是否已注册要使用的红外协议,如已注册,则调用协议的编解码函数。

7.3.5.4. 数据结构设计

7.3.5.4.1. driver层数据结构

typedef struct aic_cir
{
    struct rt_device    dev;
    aic_cir_ctrl_t      aic_cir_ctrl;
    cir_config_t        config;
} aic_cir_t;

7.3.5.4.2. hal层数据结构

typedef enum {
    CIR_EVENT_RECEIVE_COMPLETE,
    CIR_EVENT_ERROR,
} cir_event_t;

typedef struct aic_cir_ctrl aic_cir_ctrl_t;
struct aic_cir_ctrl {
    unsigned long       cir_base;
    uint8_t             irq_num;
    uint8_t             clk_idx;
    void (*callback)(aic_cir_ctrl_t *aic_cir_ctrl, cir_event_t event,
                     void *arg);
    void                *arg;
    uint8_t             tx_data[128];
    uint8_t             rx_data[128];
    uint32_t            rx_idx;
    uint8_t             rx_level;
    uint8_t             rx_flag; /* Indicates if rxfifo has received data */
};

7.3.5.5. 接口设计

7.3.5.5.1. driver层接口设计

7.3.5.5.1.1. drv_cir_init

函数原型

rt_err_t drv_cir_init(rt_device_t pdev)

功能说明

CIR模块初始化

参数定义

pdev: 指向CIR设备的指针

返回值

执行成功返回RT_EOK

注意事项

7.3.5.5.1.2. drv_cir_open

函数原型

rt_err_t drv_cir_open(rt_device_t pdev, rt_uint16_t oflag)

功能说明

打开红外模块

参数定义

pdev: 指向CIR设备的指针
oflag: 打开设备时设置的标志

返回值

执行成功返回RT_EOK,否则返回-RT_EINVAL

注意事项

oflag可设置的值:
RT_DEVICE_FLAG_WRONLY
RT_DEVICE_FLAG_RDONLY
RT_DEVICE_FLAG_RDWR
RT_DEVICE_FLAG_INT_RX
设置RT_DEVICE_FLAG_RDONLY时,必须同时设置RT_DEVICE_FLAG_INT_RX

7.3.5.5.1.3. drv_cir_close

函数原型

rt_err_t drv_cir_close(rt_device_t pdev)

功能说明

关闭红外模块

参数定义

pdev: 指向CIR设备的指针

返回值

执行成功返回RT_EOK

注意事项

7.3.5.5.1.4. drv_cir_read

函数原型

rt_size_t drv_cir_read(rt_device_t pdev, rt_off_t pos, void *buffer, rt_size_t size)

功能说明

读取CIR接收到的红外信号

参数定义

pdev: 指向CIR设备的指针
buffer: 指向接收数据的指针
size: 读取的数据字节数

返回值

执行成功返回0

注意事项

7.3.5.5.2. hal层接口设计

7.3.5.5.2.1. hal_cir_set_tx_carrier

函数原型

int hal_cir_set_tx_carrier(aic_cir_ctrl_t * aic_cir_ctrl, uint8_t protocol, uint32_t tx_duty);

功能说明

设置CIR的发送载波参数

参数定义

aic_cir_ctrl: 指向aic_cir_ctrl_t的指针
protocol: 使用的CIR协议
tx_duty: 协议的占空比

返回值

执行成功返回0

注意事项

protocol取值: NEC, 0; RC5, 1
tx_duty: 若占空比为33%,则tx_duty设置为33

7.3.5.5.2.2. hal_cir_send_data

函数原型

void hal_cir_send_data(aic_cir_ctrl_t * aic_cir_ctrl, uint8_t * tx_data, uint32_t size);

功能说明

CIR发送数据

参数定义

aic_cir_ctrl: 指向aic_cir_ctrl_t的指针
tx_data: 指向要发送的数据指针
size: 发送的数据字节数

返回值

执行成功返回0

注意事项

7.3.5.5.2.3. hal_cir_set_rx_sample_clock

函数原型

void hal_cir_set_rx_sample_clock(aic_cir_ctrl_t * aic_cir_ctrl, uint8_t protocol);

功能说明

设置CIR接收采样时钟

参数定义

aic_cir_ctrl: 指向aic_cir_ctrl_t的指针
protocol: 使用的CIR协议

返回值

执行成功返回0

注意事项