1 Star 0 Fork 14

jsonrock / homemaster-driver

forked from adai.design / homemaster-driver 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
platform_light.c 8.87 KB
一键复制 编辑 原始数据 按行查看 历史
adai.design 提交于 2018-06-17 16:27 . 删除线程读取模式
//
// Created by Yun Zeng on 2018/4/14.
// 光照强度传感器 TSL2560
//
#include "platform_light.h"
#include "master.h"
#include <linux/i2c.h>
#include <linux/delay.h>
#include "platform_light_reg.h"
// I2C 驱动设备信息
//struct i2c_adapter* tsl2561_dev = NULL;
//struct i2c_client* tsl2561_client = NULL;
static struct i2c_board_info __initdata board_info = {
.type = "tsl2561", .addr = TSL2561_ADDR_FLOAT,
};
// TSL2560 设备相关
typedef struct tsl2561InfoType {
struct i2c_adapter* dev;
struct i2c_client* client;
tsl2561GainType gain;
tsl2561IntegrationTimeType integration;
uint8_t buffer[10];
light_recv_callback callback;
}tsl2561InfoType;
static tsl2561InfoType tsl2561Info;
static inline int tsl2561_get_data(uint16_t *full_spectrum, uint16_t *infrared) {
i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
switch (tsl2561Info.integration) {
case TSL2561_INTEGRATIONTIME_13MS:
msleep(20);
break;
case TSL2561_INTEGRATIONTIME_101MS:
msleep(150);
break;
case TSL2561_INTEGRATIONTIME_402MS:
msleep(450);
break;
}
*full_spectrum = (uint16_t) i2c_smbus_read_word_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
*infrared = (uint16_t) i2c_smbus_read_word_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
return 0;
}
// 根据测量的数值计算可见光强度 lux
static uint32_t tsl2561_calculate_lux(uint16_t broadband, uint16_t ir) {
unsigned long chScale;
unsigned long channel1;
unsigned long channel0;
uint16_t clipThreshold;
unsigned long ratio1 = 0;
unsigned long ratio;
unsigned int b, m;
long temp;
uint32_t lux;
// Make sure the sensor isn't saturated!
switch (tsl2561Info.integration) {
case TSL2561_INTEGRATIONTIME_13MS:
clipThreshold = TSL2561_CLIPPING_13MS;
break;
case TSL2561_INTEGRATIONTIME_101MS:
clipThreshold = TSL2561_CLIPPING_101MS;
break;
case TSL2561_INTEGRATIONTIME_402MS:
clipThreshold = TSL2561_CLIPPING_402MS;
break;
default:
clipThreshold = TSL2561_CLIPPING_402MS;
break;
}
if ((broadband > clipThreshold) || (ir > clipThreshold)) {
return 0;
}
switch (tsl2561Info.integration) {
case TSL2561_INTEGRATIONTIME_13MS:
chScale = TSL2561_LUX_CHSCALE_TINT0;
break;
case TSL2561_INTEGRATIONTIME_101MS:
chScale = TSL2561_LUX_CHSCALE_TINT1;
break;
case TSL2561_INTEGRATIONTIME_402MS:
chScale = (1 << TSL2561_LUX_CHSCALE);
break;
default:
chScale = (1 << TSL2561_LUX_CHSCALE);
break;
}
if (!tsl2561Info.gain) chScale = chScale << 4;
channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE;
channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE;
// find the ratio of the channel values (Channel1/Channel0)
if (channel0 != 0) ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE + 1)) / channel0;
// round the ratio value
ratio = (ratio1 + 1) >> 1;
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T)) {
b = TSL2561_LUX_B1T;
m = TSL2561_LUX_M1T;
} else if (ratio <= TSL2561_LUX_K2T) {
b = TSL2561_LUX_B2T;
m = TSL2561_LUX_M2T;
} else if (ratio <= TSL2561_LUX_K3T) {
b = TSL2561_LUX_B3T;
m = TSL2561_LUX_M3T;
} else if (ratio <= TSL2561_LUX_K4T) {
b = TSL2561_LUX_B4T;
m = TSL2561_LUX_M4T;
} else if (ratio <= TSL2561_LUX_K5T) {
b = TSL2561_LUX_B5T;
m = TSL2561_LUX_M5T;
} else if (ratio <= TSL2561_LUX_K6T) {
b = TSL2561_LUX_B6T;
m = TSL2561_LUX_M6T;
} else if (ratio <= TSL2561_LUX_K7T) {
b = TSL2561_LUX_B7T;
m = TSL2561_LUX_M7T;
} else if (ratio > TSL2561_LUX_K8T) {
b = TSL2561_LUX_B8T;
m = TSL2561_LUX_M8T;
}
temp = ((channel0 * b) - (channel1 * m));
// do not allow negative lux value
if (temp < 0) {
temp = 0;
}
temp += (1 << (TSL2561_LUX_LUXSCALE - 1));
lux = temp >> TSL2561_LUX_LUXSCALE;
return lux;
}
int tsl2561_set_integration_time(tsl2561IntegrationTimeType time) {
int rc;
i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
rc = i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | tsl2561Info.gain);
i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
if (rc != 0) {
return -1;
}
// printk(MASTER_DEV_NAME ": light integration rc(%d)\n", rc);
return 0;
}
int tsl2561_set_gain(tsl2561GainType gain) {
int rc;
i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
rc = i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, gain | tsl2561Info.integration);
i2c_smbus_write_byte_data(tsl2561Info.client, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
if (rc != 0) {
return -1;
}
tsl2561Info.gain = gain;
// printk(MASTER_DEV_NAME ": light gain rc(%d)\n", rc);
return 0;
}
int tsl2561_get_light(uint16_t *full_spectrum, uint16_t *infrared, uint32_t *lux, int autogain) {
int rc=1;
uint16_t fs, ir, hi, lo;
if (autogain == 0) {
rc = tsl2561_get_data(full_spectrum, infrared);
*lux = tsl2561_calculate_lux(*full_spectrum, *infrared);
return rc;
}
// auto gain requested
switch(tsl2561Info.integration) {
case TSL2561_INTEGRATIONTIME_13MS:
hi = TSL2561_AGC_THI_13MS;
lo = TSL2561_AGC_TLO_13MS;
break;
case TSL2561_INTEGRATIONTIME_101MS:
hi = TSL2561_AGC_THI_101MS;
lo = TSL2561_AGC_TLO_101MS;
break;
case TSL2561_INTEGRATIONTIME_402MS:
hi = TSL2561_AGC_THI_402MS;
lo = TSL2561_AGC_TLO_402MS;
break;
default:
hi = TSL2561_AGC_THI_402MS;
lo = TSL2561_AGC_TLO_402MS;
break;
}
rc = tsl2561_get_data(&fs, &ir);
if(rc != 0) {
return -1;
}
// light too low with this gain
if ((fs < lo) && (tsl2561Info.gain == TSL2561_GAIN_1X)) {
tsl2561_set_gain(TSL2561_GAIN_16X);
rc = tsl2561_get_data(&fs, &ir);
if(rc != 0) {
return -1;
} else {
*full_spectrum = fs;
*infrared = ir;
*lux = tsl2561_calculate_lux(*full_spectrum, *infrared);
return 0;
}
}
// light too high with this gain
if ((fs > hi) && (tsl2561Info.gain == TSL2561_GAIN_16X)) {
tsl2561_set_gain(TSL2561_GAIN_1X);
rc = tsl2561_get_data(&fs, &ir);
if(rc != 0) {
return -1;
} else {
*full_spectrum = fs;
*infrared = ir;
*lux = tsl2561_calculate_lux(*full_spectrum, *infrared);
return 0;
}
}
*full_spectrum = fs;
*infrared = ir;
*lux = tsl2561_calculate_lux(*full_spectrum, *infrared);
return 0;
}
// 写入指令,读取光照强度传感器的值
int32_t platform_light_write(uint8_t *data, uint16_t len) {
int rc;
uint16_t broadband, infrared;
uint32_t lux;
tsl2561_set_gain(TSL2561_GAIN_1X);
tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_101MS);
rc = tsl2561_get_light(&broadband, &infrared, &lux, 1);
//printk(MASTER_DEV_NAME ": tsl2561 broadband(%d) infrared(%d) lux(%d)\n", broadband, infrared, lux);
if (tsl2561Info.callback != NULL) {
platform_light_data_typedef light = {
.lux = cpu_to_be32(lux),
.infrared = cpu_to_be16(infrared),
};
tsl2561Info.callback(&light);
}
return 0;
}
int platform_light_init(light_recv_callback callback) {
tsl2561Info.dev = i2c_get_adapter(0);
tsl2561Info.client = i2c_new_device(tsl2561Info.dev, &board_info);
if (tsl2561Info.client == NULL) {
printk(MASTER_DEV_NAME ": tsl2561 client init() error\n");
return -1;
}
memset(tsl2561Info.buffer, 0x00, sizeof(tsl2561Info.buffer));
tsl2561_set_integration_time(TSL2561_INTEGRATIONTIME_402MS);
tsl2561_set_gain(TSL2561_GAIN_16X);
tsl2561Info.callback = callback;
return 0;
}
int platform_light_exit(void) {
if (tsl2561Info.client != NULL) {
i2c_unregister_device(tsl2561Info.client);
}
tsl2561Info.callback = NULL;
return 0;
}
C
1
https://gitee.com/w_enhao/homemaster-driver.git
git@gitee.com:w_enhao/homemaster-driver.git
w_enhao
homemaster-driver
homemaster-driver
master

搜索帮助