14 Star 59 Fork 14

adai.design / homemaster-driver

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
platform_infrared.c 7.38 KB
一键复制 编辑 原始数据 按行查看 历史
adai.design 提交于 2018-11-03 16:51 . OLED初始化LOGO显示修改
//
// Created by Yun Zeng on 2018/4/17.
// 红外遥控发射
//
#include "platform_infrared.h"
#include "master.h"
#include <linux/gpio.h>
#include <linux/interrupt.h>
//#define INFRARED_INPUT_ENABLE
#ifdef INFRARED_INPUT_ENABLE
#define INFRARED_INPUT_PIN 1
#define INFRARED_INPUT_NAME "infrared_input_pin"
#endif
#define INFRARED_OUTPUT_PIN 19
#define INFRARED_OUTPUT_NAME "infrared_output_pin"
#define INFRARED_BUFFER_SIZE 1024
typedef struct {
// 红外接收相关
int read_inter;
struct timeval rev_interval;
struct hrtimer rev_timer;
int rev_buffer[INFRARED_BUFFER_SIZE];
int rev_cnt;
// 红外发送相关
struct hrtimer send_timer;
int send_buffer[INFRARED_BUFFER_SIZE];
int send_cnt;
int send_len;
int send_state;
}infraredInfoType;
static infraredInfoType infraredInfo;
// 红外码发射
static enum hrtimer_restart infrared_send_handler(struct hrtimer *timer) {
//printk(INFRARED_DEV_NAME ": send handler");
static int vflag = 0;
if (vflag ==0) {
vflag = 1;
hrtimer_forward_now(&infraredInfo.send_timer, ktime_set(0, 8680));
} else {
vflag = 0;
hrtimer_forward_now(&infraredInfo.send_timer, ktime_set(0, 17520));
}
if (infraredInfo.send_cnt >= infraredInfo.send_len) {
infraredInfo.send_cnt = 0;
infraredInfo.send_len = 0;
gpio_set_value(INFRARED_OUTPUT_PIN, 0);
return HRTIMER_NORESTART;
}
if (infraredInfo.send_buffer[infraredInfo.send_cnt] == 0) {
infraredInfo.send_cnt ++;
}
if (infraredInfo.send_buffer[infraredInfo.send_cnt] > 0) {
infraredInfo.send_buffer[infraredInfo.send_cnt] -= 1;
// 翻转
if (vflag == 0) {
gpio_set_value(INFRARED_OUTPUT_PIN, 0);
} else {
gpio_set_value(INFRARED_OUTPUT_PIN, 1);
}
} else if(infraredInfo.send_buffer[infraredInfo.send_cnt] <= 0) {
infraredInfo.send_buffer[infraredInfo.send_cnt] += 1;
gpio_set_value(INFRARED_OUTPUT_PIN, 0);
}
return HRTIMER_RESTART;
}
#ifdef INFRARED_INPUT_ENABLE
// 正在接收红外码
irqreturn_t infrared_input_handler(int irqno, void *dev_id) {
struct timeval time;
int time_interval;
infraredInfo.rev_cnt += 1;
if (infraredInfo.rev_cnt > INFRARED_BUFFER_SIZE) {
infraredInfo.rev_cnt = 0;
}
do_gettimeofday(&time);
if (infraredInfo.rev_cnt > 1) {
time_interval = (int) ((time.tv_sec - infraredInfo.rev_interval.tv_sec) * 1000000 + (time.tv_usec - infraredInfo.rev_interval.tv_usec));
if (gpio_get_value(INFRARED_INPUT_PIN) == 0) {
infraredInfo.rev_buffer[infraredInfo.rev_cnt] = -time_interval;
} else {
infraredInfo.rev_buffer[infraredInfo.rev_cnt] = time_interval;
}
}
// 超过300ms没有收到数据,即为红外接收完成
if (infraredInfo.rev_timer.state == HRTIMER_STATE_INACTIVE) {
hrtimer_start(&infraredInfo.rev_timer, ktime_set(0, 300000000), HRTIMER_MODE_REL);
} else {
hrtimer_forward_now(&(infraredInfo.rev_timer), ktime_set(0, 300000000));
}
infraredInfo.rev_interval.tv_sec = time.tv_sec;
infraredInfo.rev_interval.tv_usec = time.tv_usec;
return IRQ_HANDLED;
}
// 红外码接收完成
static enum hrtimer_restart infrared_rev_handler(struct hrtimer *timer) {
int i;
printk(MASTER_DEV_NAME ": rev len(%d)\n", infraredInfo.rev_cnt);
for(i=0; i<infraredInfo.rev_cnt; i++) {
printk("%d,", infraredInfo.rev_buffer[i]);
}
printk("\n");
uint8_t ifbuffer[14] = {0x00};
int offset = 0;
// 转换编码
for(i=6; i< infraredInfo.rev_cnt; i+=2) {
if (infraredInfo.rev_buffer[i] < -3000 && i == 0) {
printk("S");
} else if (infraredInfo.rev_buffer[i] < -4000) {
printk("S");
} else if (infraredInfo.rev_buffer[i+1] < -1000 && infraredInfo.rev_buffer[i+1] > -2000) {
int x = 7 - offset % 8;
int y = offset / 8;
ifbuffer[y] |= (0x01 << x);
offset += 1;
printk("1");
} else if (infraredInfo.rev_buffer[i+1] < 0 && infraredInfo.rev_buffer[i+1] > -1000) {
printk("0");
offset += 1;
} else {
printk("L ");
}
if (offset % 8 == 0) {
printk(" ");
}
}
printk("\n");
uint8_t check = 0x00;
for (i=0; i<13; i++) {
printk("%02x", ifbuffer[i]);
check += ifbuffer[i];
}
printk("%02x", ifbuffer[13]);
printk(" [%02x]", check);
printk("\n");
printk("\n");
infraredInfo.rev_cnt = 0;
return HRTIMER_NORESTART;
}
#endif
// 将要发送的红外码写入到发送缓冲区
int32_t platform_infrared_write(uint8_t *data, uint16_t len) {
int i;
if (data == NULL || len % 2 != 0
|| len / 2 > sizeof(infraredInfo.send_buffer)/sizeof(infraredInfo.send_buffer[0])) {
return -1;
}
infraredInfo.send_len = len/2;
memset(infraredInfo.send_buffer, 0x00, sizeof(infraredInfo.send_buffer)/sizeof(infraredInfo.send_buffer[0]));
printk(MASTER_DEV_NAME ": infrared send(");
for (i=0; i<infraredInfo.send_len; i++) {
infraredInfo.send_buffer[i] = (int16_t)(be16_to_cpu(*(int16_t *)&data[i*2]));
printk("%d,", infraredInfo.send_buffer[i]);
}
printk(")\n");
// 发射
gpio_set_value(INFRARED_OUTPUT_PIN, 0);
hrtimer_start(&infraredInfo.send_timer, ktime_set(0, 400000), HRTIMER_MODE_REL);
return 0;
}
// 初始化引脚、定时器等
int platform_infrared_init(master_dev_typedef *dev) {
int result;
#ifdef INFRARED_INPUT_ENABLE
// 输入部分
result = gpio_request(INFRARED_INPUT_PIN, INFRARED_INPUT_NAME);
if (result < 0) {
printk(MASTER_DEV_NAME ": gpio request(%d) failed\n", INFRARED_INPUT_PIN);
return -1;
}
gpio_direction_input(INFRARED_INPUT_PIN);
// gpio req
infraredInfo.read_inter = gpio_to_irq(INFRARED_INPUT_PIN);
result = request_irq(infraredInfo.read_inter,
infrared_input_handler,
IRQF_TRIGGER_MASK | IRQF_SHARED,
"infrared_input_inter",
&dev->devno);
if (result < 0) {
gpio_free(INFRARED_INPUT_PIN);
printk(MASTER_DEV_NAME ": gpio_to_irq(%d) failed\n", INFRARED_INPUT_PIN);
return -1;
}
printk(MASTER_DEV_NAME ": gpio irq enabled interrupt(%d)\n", infraredInfo.read_inter);
hrtimer_init(&infraredInfo.rev_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
infraredInfo.rev_timer.function = infrared_rev_handler;
#endif
// 输出部分
result = gpio_request(INFRARED_OUTPUT_PIN, INFRARED_OUTPUT_NAME);
if (result < 0) {
printk(MASTER_DEV_NAME ": gpio request(%d) failed\n", INFRARED_OUTPUT_PIN);
return 0;
}
gpio_direction_output(INFRARED_OUTPUT_PIN, 0);
hrtimer_init(&infraredInfo.send_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
infraredInfo.send_timer.function = infrared_send_handler;
infraredInfo.rev_cnt = 0;
return 0;
}
int platform_infrared_exit(master_dev_typedef *dev) {
#ifdef INFRARED_INPUT_ENABLE
hrtimer_cancel(&infraredInfo.rev_timer);
gpio_free(INFRARED_INPUT_PIN);
disable_irq(infraredInfo.read_inter);
free_irq(infraredInfo.read_inter, &dev->devno);
#endif
hrtimer_cancel(&infraredInfo.send_timer);
gpio_free(INFRARED_OUTPUT_PIN);
return 0;
}
C
1
https://gitee.com/adaidesigner/homemaster-driver.git
git@gitee.com:adaidesigner/homemaster-driver.git
adaidesigner
homemaster-driver
homemaster-driver
master

搜索帮助