Android下的遥控器DIY

https://blog.csdn.net/mike8825/article/details/80955992中,介绍了几种红外方案,这里拿spi的方式来diy一个遥控器。

如果内核版本是v4.14,直接编译kernel4.14/drivers/media/rc/ir-spi.c文件,调试下,应该就可以用了。这里稍微改造了ir-spi.c,更加容易移植。

dts参考配置

记的打开平台的dma模式(在https://blog.csdn.net/mike8825/article/details/80955992已说明原因)

&spi1 {
    status = "okay";
	sprd,dma-mode = <1>;
	sprd,spi-mode = <3>;
		irled@0 {
			compatible = "ir-spi-led";
			reg = <0x0>;
			spi-max-frequency = <5000000>;
			duty-cycle = /bits/ 8 <60>;
	}; 
};

如果mos管是低电平导通,加上led-active-low;

ir-spi.c 

// SPDX-License-Identifier: GPL-2.0
// SPI driven IR LED device driver
//
// Copyright (c) 2016 Samsung Electronics Co., Ltd.
// Copyright (c) Andi Shyti <andi@etezian.org>
 
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
//#include <media/rc-core.h>
 
#define IR_SPI_DRIVER_NAME		"ir-spi"
#define IR_SPI_DEFAULT_FREQUENCY	38000
#define IR_SPI_MAX_BUFSIZE		4096*4
#define	TX_IR				_IOW(0xf5, 0, int)
#define	SET_TX_CARRIER			_IOW(0xf5, 1, int)
 
struct ir_spi_data {
	u32 freq;
	bool negated;
 
	u16 tx_buf[IR_SPI_MAX_BUFSIZE];
	u16 pulse;
	u16 space;
 
	struct spi_device *spi;
	struct regulator *regulator;
};
 
struct ir_spi_data idata;
 
static int ir_spi_open(struct inode *inode, struct file *file)
{
	return 0;
}
 
static ssize_t ir_spi_tx(struct file *file, const char __user * user_buf,
			 size_t count, loff_t * ppos)
{
	int i;
	int ret;
	unsigned int len = 0;
	int *buffer;
	struct spi_transfer xfer;
	pr_info("ir_spi_tx start\n");
	buffer= memdup_user(user_buf, count);
	count /= sizeof(int);
 
	/* convert the pulse/space signal to raw binary signal */
	for (i = 0; i < count; i++) {
		unsigned int periods;
		int j;
		u16 val;
		periods = DIV_ROUND_CLOSEST(buffer[i] * idata.freq, 1000000);
		pr_debug("i=%d periods=%d\n",i,periods);
		if (len>= IR_SPI_MAX_BUFSIZE){
			pr_info("len=%d\n",len);
			return -EINVAL;
		}
 
		/*
		 * the first value in buffer is a pulse, so that 0, 2, 4, ...
		 * contain a pulse duration. On the contrary, 1, 3, 5, ...
		 * contain a space duration.
		 */
		val = (i % 2) ? idata.space : idata.pulse;
		for (j = 0; j < periods; j++)
			idata.tx_buf[len++] = val;
	}
 
	memset(&xfer, 0, sizeof(xfer));
	
	xfer.speed_hz = idata.freq * 16;
	xfer.len = len * sizeof(*idata.tx_buf);
	xfer.tx_buf = idata.tx_buf;
	xfer.bits_per_word = 16;

	ret = regulator_enable(idata.regulator);
	if (ret)
		return ret;
	ret = spi_sync_transfer(idata.spi, &xfer, 1);
	if (ret)
		dev_err(&idata.spi->dev, "unable to deliver the signal\n");
	regulator_disable(idata.regulator);
	kfree(buffer);
	pr_info("ir_spi_tx stop\n");
	return ret ? ret : count*sizeof(int);
}
 
static long ir_spi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int ret;
	switch (cmd) {
	case SET_TX_CARRIER:
		if (get_user(idata.freq,(unsigned int __user *)arg)){
			return -EFAULT;
		}
		idata.spi->max_speed_hz = idata.freq*16;
		idata.spi->bits_per_word = 16;
		ret = spi_setup(idata.spi);
		if(ret<0){
			dev_err(&idata.spi->dev, "set up spi speed fail\n");
			return ret;
		}
		break;
	default:
		return -ENOIOCTLCMD;
	}
	return 0;
}
 
static int ir_spi_set_duty_cycle(u32 duty_cycle)
{
	int bits = (duty_cycle * 15) / 100;
 
	idata.pulse = GENMASK(bits, 0);
 
	if (idata.negated) {
		idata.pulse = ~idata.pulse;
		idata.space = 0xffff;
	} else {
		idata.space = 0;
	}
 
	return 0;
}
 
static int ir_spi_release(struct inode *node, struct file *filp)
{
	return 0;
}
 
static struct file_operations ir_spi_fops = {
	.owner = THIS_MODULE,
	.open = ir_spi_open,
	.unlocked_ioctl = ir_spi_ioctl,
	.write = ir_spi_tx,
	.release = ir_spi_release,
};
 
static struct miscdevice ir_spi_dev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = IR_SPI_DRIVER_NAME,
	.fops = &ir_spi_fops,
};
 
static int ir_spi_probe(struct spi_device *spi)
{
	int ret;
	u8 dc;
	idata.spi= spi;
	idata.regulator = devm_regulator_get(&spi->dev, "irda_regulator");
	if (IS_ERR(idata.regulator))
		pr_err("could no found irda regu_regulator %ld",
		       PTR_ERR(idata.regulator));
 
	idata.negated =
	    of_property_read_bool(spi->dev.of_node, "led-active-low");
	ret = of_property_read_u8(spi->dev.of_node, "duty-cycle", &dc);
	if (ret)
		dc = 50;
	ir_spi_set_duty_cycle(dc);
 
	idata.freq = IR_SPI_DEFAULT_FREQUENCY;
	ret = misc_register(&ir_spi_dev);
	return 0;
}
 
static int ir_spi_remove(struct spi_device *spi)
{
	return 0;
}
 
static const struct of_device_id ir_spi_of_match[] = {
	{.compatible = "ir-spi-led"},
	{},
};
 
static struct spi_driver ir_spi_driver = {
	.probe = ir_spi_probe,
	.remove = ir_spi_remove,
	.driver = {
		   .name = IR_SPI_DRIVER_NAME,
		   .of_match_table = ir_spi_of_match,
		   },
};
 
module_spi_driver(ir_spi_driver);
 
MODULE_AUTHOR("Andi Shyti <andi@etezian.org>");
MODULE_DESCRIPTION("SPI IR LED");
MODULE_LICENSE("GPL v2");

hardware/libhardware/modules/consumerir/consumerir.c 

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "ConsumerIrHal"

#include <errno.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include <log/log.h>

#include <hardware/consumerir.h>
#include <hardware/hardware.h>
#define	TX_IR				_IOW(0xf5, 0, int)
#define	SET_TX_CARRIER			_IOW(0xf5, 1, int)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static const consumerir_freq_range_t consumerir_freqs[] = {
	{.min = 30000,.max = 30000},
	{.min = 33000,.max = 33000},
	{.min = 36000,.max = 36000},
	{.min = 38000,.max = 38000},
	{.min = 40000,.max = 40000},
	{.min = 56000,.max = 56000},
};

static int consumerir_transmit(struct consumerir_device *dev __unused,
			       int carrier_freq, const int pattern[],
			       int pattern_len)
{
	int fd;
	int ret;
	int length;
	int freq;
	fd = open("/dev/ir-spi", O_RDWR);
	if (fd < 0) {
		ALOGE("open /dev/ir-spi error");
		return -1;
	}
	freq = carrier_freq;
	ret = ioctl(fd, SET_TX_CARRIER, &freq);
	if (ret < 0)
		ALOGE("set ir freq fail\n");
	length = pattern_len * sizeof(int);
	ret = write(fd, pattern, length);
	if (ret != length) {
		ALOGE("consumerir_transmit fail ret=%d length=%d\n", ret,
		      length);
	} else {
		ALOGE("consumerir_transmit ok\n");
	}

	return 0;
}

static int consumerir_get_num_carrier_freqs(struct consumerir_device *dev
					    __unused)
{
	return ARRAY_SIZE(consumerir_freqs);
}

static int consumerir_get_carrier_freqs(struct consumerir_device *dev __unused,
					size_t len,
					consumerir_freq_range_t * ranges)
{
	size_t to_copy = ARRAY_SIZE(consumerir_freqs);

	to_copy = len < to_copy ? len : to_copy;
	memcpy(ranges, consumerir_freqs,
	       to_copy * sizeof(consumerir_freq_range_t));
	return to_copy;
}

static int consumerir_close(hw_device_t * dev)
{
	free(dev);
	return 0;
}

/*
 * Generic device handling
 */
static int consumerir_open(const hw_module_t * module, const char *name,
			   hw_device_t ** device)
{
	if (strcmp(name, CONSUMERIR_TRANSMITTER) != 0) {
		return -EINVAL;
	}
	if (device == NULL) {
		ALOGE("NULL device on open");
		return -EINVAL;
	}

	consumerir_device_t *dev = malloc(sizeof(consumerir_device_t));
	memset(dev, 0, sizeof(consumerir_device_t));

	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (struct hw_module_t *)module;
	dev->common.close = consumerir_close;

	dev->transmit = consumerir_transmit;
	dev->get_num_carrier_freqs = consumerir_get_num_carrier_freqs;
	dev->get_carrier_freqs = consumerir_get_carrier_freqs;

	*device = (hw_device_t *) dev;
	return 0;
}

static struct hw_module_methods_t consumerir_module_methods = {
	.open = consumerir_open,
};

consumerir_module_t HAL_MODULE_INFO_SYM = {
	.common = {
		   .tag = HARDWARE_MODULE_TAG,
		   .module_api_version = CONSUMERIR_MODULE_API_VERSION_1_0,
		   .hal_api_version = HARDWARE_HAL_API_VERSION,
		   .id = CONSUMERIR_HARDWARE_MODULE_ID,
		   .name = "Demo IR HAL",
		   .author = "The Android Open Source Project",
		   .methods = &consumerir_module_methods,
		   },
};

其他的修改见 https://blog.csdn.net/mike8825/article/details/79670891,不再描述。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 开发 Android 空调遥控器涉及以下几个方面的工作: 1. 界面设计:首先要设计一个用户友好的界面,确保用户能够轻松理解和使用遥控器功能。界面应该包括温度调节、风速选择、模式选择、定时开关机等功能。 2. 通信协议:需要与空调进行通信,以发送控制指令和接收状态信息。可以使用红外线技术或 Wi-Fi 等无线技术实现通信。对于红外线通信,需要调研并找到特定空调品牌和型号的红外线控制指令集。对于 Wi-Fi 通信,需要设计与空调通信的网络协议。 3. 状态更新和同步:在用户调节遥控器参数后,需要及时将设置的参数发送给空调,并确保空调收到指令后做出相应的操作。同时,还需要定期从空调读取当前的工作状态,例如温度、风速等,并更新到遥控器界面上,便于用户实时监控和调节。 4. 兼容性考虑:考虑到不同品牌和型号的空调具有不同的控制方式和功能设置,开发时需要充分考虑兼容性。可以通过提供用户可自定义的参数配置功能,让用户可以在遥控器上选择对应的空调品牌和型号,以及支持的功能,从而适配各种空调设备。 5. 其他功能增强:最后,可以考虑为遥控器增加一些实用的功能,例如支持语音控制、场景模式设置、设备联动等,以提升用户体验。 总体而言,开发 Android 空调遥控器需要通过界面设计、通信协议、状态更新、兼容性考虑和功能增强等多个方面的工作来实现。这些工作需要结合具体的需求和技术要求进行设计和开发,最终提供给用户一个方便、易用且功能丰富的空调遥控器应用。 ### 回答2: Android空调遥控器开发是基于Android操作系统的智能设备遥控应用程序。该应用程序可以与用户的空调设备进行无线连接,通过无线信号与空调设备进行通信,并模拟空调遥控器的功能,实现远程控制空调设备的操作。 在进行Android空调遥控器开发时,首先需要实现与空调设备的无线连接功能。可以利用蓝牙、红外线或者Wi-Fi等通信方式实现设备连接。通过与空调设备建立连接之后,可以获取设备的状态和参数信息,从而实现对空调设备的遥控操作。用户可以通过触摸屏幕上的操作按钮或者滑动条,调节空调的温度、风速、模式等参数,同时也可以进行定时、定位、控制多个空调等特殊功能。 在开发过程中,需要使用Android开发工具,如Android Studio,并结合空调设备的通信协议,编写相应的代码实现连接和与空调设备的通信。此外,还需要设计应用程序的用户界面,包括各种操作按钮和界面布局等。应用程序还应该具备良好的用户体验,保证操作的简单易懂和流畅性能。 Android空调遥控器的开发可以带来许多便利性和舒适性。用户可以随时随地通过手机对家中的空调设备进行远程控制,无需亲临现场进行操作。而且可以利用智能手机的多媒体功能,进行更加个性化的设置和控制。 总之,Android空调遥控器开发是一项基于Android操作系统的智能设备遥控应用程序的开发工作。通过与空调设备的无线连接和通信,实现对空调设备的遥控操作,提供更加方便和舒适的使用体验。 ### 回答3: 开发 Android 空调遥控器是为了实现通过手机控制空调的功能。首先,我们需要设计一个用户友好的界面,包括一些基本的控制按钮,如开、关、调温、调风等。通过与空调的通信接口,我们可以将用户在手机上的操作指令传输到空调设备上。 在开发过程中,我们需要注意以下几点: 1. 兼容性:确保该遥控器应用程序能够支持主流的 Android 手机和智能设备。 2. 连接性:通过蓝牙、Wi-Fi 或红外线技术,实现手机与空调之间的无线连接。 3. 控制功能:在应用程序中提供各种必要的控制功能,如调节温度、调整风向、设置定时功能等。 4. 数据传输安全性:确保用户在使用手机遥控器时的数据传输是安全的,防止他人恶意干扰。 5. 自定义设置:为用户提供自定义选项,使他们能够根据自己的需求进行个性化设置,如添加多个设备、命名等。 6. 易于使用:设计简单直观的用户界面,使用户能够轻松地理解和操作。 通过上述开发,用户将能够通过他们的 Android 手机方便地操控空调,无需再去寻找遥控器或靠近空调设备。这将为用户带来更多的便利性和舒适感。随着智能家居的发展,这样的应用程序也能与其他智能设备进行连接,实现更智能化的家庭控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值