drivers: sensors: add driver for amg88xx sensor
This patch adds the driver for Panasonic AMG88xx infrared array sensor. The driver was developed within the framework of a student internship in the development department. The task of the student was to implement the trigger part of the driver, transfer and visualization of the measured data. Signed-off-by: Johann Fischer <j.fischer@phytec.de>
This commit is contained in:
parent
3b1b05be7b
commit
476f05d2f8
7 changed files with 561 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
||||||
add_subdirectory_ifdef(CONFIG_ADXL362 adxl362)
|
add_subdirectory_ifdef(CONFIG_ADXL362 adxl362)
|
||||||
add_subdirectory_ifdef(CONFIG_AK8975 ak8975)
|
add_subdirectory_ifdef(CONFIG_AK8975 ak8975)
|
||||||
|
add_subdirectory_ifdef(CONFIG_AMG88XX amg88xx)
|
||||||
add_subdirectory_ifdef(CONFIG_APDS9960 apds9960)
|
add_subdirectory_ifdef(CONFIG_APDS9960 apds9960)
|
||||||
add_subdirectory_ifdef(CONFIG_BMA280 bma280)
|
add_subdirectory_ifdef(CONFIG_BMA280 bma280)
|
||||||
add_subdirectory_ifdef(CONFIG_BMC150_MAGN bmc150_magn)
|
add_subdirectory_ifdef(CONFIG_BMC150_MAGN bmc150_magn)
|
||||||
|
|
|
@ -42,6 +42,8 @@ source "drivers/sensor/adxl362/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/ak8975/Kconfig"
|
source "drivers/sensor/ak8975/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/sensor/amg88xx/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/apds9960/Kconfig"
|
source "drivers/sensor/apds9960/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/bma280/Kconfig"
|
source "drivers/sensor/bma280/Kconfig"
|
||||||
|
|
2
drivers/sensor/amg88xx/CMakeLists.txt
Normal file
2
drivers/sensor/amg88xx/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
zephyr_sources_ifdef(CONFIG_AMG88XX amg88xx.c)
|
||||||
|
zephyr_sources_ifdef(CONFIG_AMG88XX_TRIGGER amg88xx_trigger.c)
|
94
drivers/sensor/amg88xx/Kconfig
Normal file
94
drivers/sensor/amg88xx/Kconfig
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# Kconfig - AMG88XX infrared thermopile sensor configuration options
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017 Phytec Messtechnik GmbH
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
menuconfig AMG88XX
|
||||||
|
bool "AMG88XX Infrared Thermopile Sensor"
|
||||||
|
depends on I2C
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable driver for AMG88XX infrared thermopile sensor.
|
||||||
|
|
||||||
|
if AMG88XX
|
||||||
|
|
||||||
|
config AMG88XX_NAME
|
||||||
|
string "Driver name"
|
||||||
|
default "AMG88XX"
|
||||||
|
help
|
||||||
|
Device name identifying the AMG88XX sensor.
|
||||||
|
|
||||||
|
config AMG88XX_I2C_ADDR
|
||||||
|
hex "I2C address for AMG88XX Sensor"
|
||||||
|
default "0x68"
|
||||||
|
range 0x68 0x69
|
||||||
|
help
|
||||||
|
I2C address of the AMG88XX sensor.
|
||||||
|
|
||||||
|
0x68: AD-SELECT connected GND
|
||||||
|
0x69: AD-SELECT connected VDD
|
||||||
|
|
||||||
|
config AMG88XX_I2C_MASTER_DEV_NAME
|
||||||
|
string "I2C master where AMG88XX is connected"
|
||||||
|
default "I2C_0"
|
||||||
|
help
|
||||||
|
The I2C master device's name where the AMG88XX sensor is connected.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Trigger mode"
|
||||||
|
default AMG88XX_TRIGGER_NONE
|
||||||
|
help
|
||||||
|
Specify the type of triggering used by the driver.
|
||||||
|
|
||||||
|
config AMG88XX_TRIGGER_NONE
|
||||||
|
bool "No trigger"
|
||||||
|
|
||||||
|
config AMG88XX_TRIGGER_GLOBAL_THREAD
|
||||||
|
bool "Use global thread"
|
||||||
|
depends on GPIO
|
||||||
|
select AMG88XX_TRIGGER
|
||||||
|
|
||||||
|
config AMG88XX_TRIGGER_OWN_THREAD
|
||||||
|
bool "Use own thread"
|
||||||
|
depends on GPIO
|
||||||
|
select AMG88XX_TRIGGER
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config AMG88XX_TRIGGER
|
||||||
|
bool
|
||||||
|
|
||||||
|
config AMG88XX_GPIO_DEV_NAME
|
||||||
|
string "GPIO device"
|
||||||
|
default "GPIO_0"
|
||||||
|
depends on AMG88XX_TRIGGER
|
||||||
|
help
|
||||||
|
The GPIO device's name where the AMG88XX interrupt (alert) pin is
|
||||||
|
connected.
|
||||||
|
|
||||||
|
config AMG88XX_GPIO_PIN_NUM
|
||||||
|
int "Interrupt GPIO pin number"
|
||||||
|
default 0
|
||||||
|
depends on AMG88XX_TRIGGER
|
||||||
|
help
|
||||||
|
The GPIO pin number receiving the interrupt signal from the
|
||||||
|
AMG88XX sensor.
|
||||||
|
|
||||||
|
config AMG88XX_THREAD_PRIORITY
|
||||||
|
int "Thread priority"
|
||||||
|
depends on AMG88XX_TRIGGER_OWN_THREAD
|
||||||
|
default 10
|
||||||
|
help
|
||||||
|
Priority of thread used by the driver to handle interrupts.
|
||||||
|
|
||||||
|
config AMG88XX_THREAD_STACK_SIZE
|
||||||
|
int "Thread stack size"
|
||||||
|
depends on AMG88XX_TRIGGER_OWN_THREAD
|
||||||
|
default 1024
|
||||||
|
help
|
||||||
|
Stack size of thread used by the driver to handle interrupts.
|
||||||
|
|
||||||
|
endif #if AMG88XX
|
137
drivers/sensor/amg88xx/amg88xx.c
Normal file
137
drivers/sensor/amg88xx/amg88xx.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Phytec Messtechnik GmbH
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <device.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
#include <misc/byteorder.h>
|
||||||
|
#include <misc/util.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <sensor.h>
|
||||||
|
#include <misc/__assert.h>
|
||||||
|
|
||||||
|
#include "amg88xx.h"
|
||||||
|
|
||||||
|
static int amg88xx_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_TEMP);
|
||||||
|
|
||||||
|
if (i2c_burst_read(drv_data->i2c, CONFIG_AMG88XX_I2C_ADDR,
|
||||||
|
AMG88XX_OUTPUT_BASE,
|
||||||
|
(u8_t *)drv_data->sample,
|
||||||
|
sizeof(drv_data->sample))) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amg88xx_channel_get(struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
size_t len = ARRAY_SIZE(drv_data->sample);
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_TEMP) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t idx = 0; idx < len; idx++) {
|
||||||
|
/* fix negative values */
|
||||||
|
if (drv_data->sample[idx] & (1 << 11)) {
|
||||||
|
drv_data->sample[idx] |= 0xF000;
|
||||||
|
}
|
||||||
|
val[idx].val1 = (((s32_t)drv_data->sample[idx]) *
|
||||||
|
AMG88XX_TREG_LSB_SCALING) / 1000000;
|
||||||
|
val[idx].val2 = (((s32_t)drv_data->sample[idx]) *
|
||||||
|
AMG88XX_TREG_LSB_SCALING) % 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amg88xx_init_device(struct device *dev)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
u8_t tmp;
|
||||||
|
|
||||||
|
if (amg88xx_reg_read(drv_data, AMG88XX_PCLT, &tmp)) {
|
||||||
|
SYS_LOG_ERR("Failed to read Power mode");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LOG_DBG("Power mode 0x%02x", tmp);
|
||||||
|
if (tmp != AMG88XX_PCLT_NORMAL_MODE) {
|
||||||
|
if (amg88xx_reg_write(drv_data, AMG88XX_PCLT,
|
||||||
|
AMG88XX_PCLT_NORMAL_MODE)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
k_busy_wait(AMG88XX_WAIT_MODE_CHANGE_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amg88xx_reg_write(drv_data, AMG88XX_RST,
|
||||||
|
AMG88XX_RST_INITIAL_RST)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_busy_wait(AMG88XX_WAIT_INITIAL_RESET_US);
|
||||||
|
|
||||||
|
if (amg88xx_reg_write(drv_data, AMG88XX_FPSC, AMG88XX_FPSC_10FPS)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LOG_DBG("");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amg88xx_init(struct device *dev)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
drv_data->i2c = device_get_binding(CONFIG_AMG88XX_I2C_MASTER_DEV_NAME);
|
||||||
|
if (drv_data->i2c == NULL) {
|
||||||
|
SYS_LOG_ERR("Failed to get pointer to %s device!",
|
||||||
|
CONFIG_AMG88XX_I2C_MASTER_DEV_NAME);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amg88xx_init_device(dev) < 0) {
|
||||||
|
SYS_LOG_ERR("Failed to initialize device!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_AMG88XX_TRIGGER
|
||||||
|
if (amg88xx_init_interrupt(dev) < 0) {
|
||||||
|
SYS_LOG_ERR("Failed to initialize interrupt!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct amg88xx_data amg88xx_driver;
|
||||||
|
|
||||||
|
static const struct sensor_driver_api amg88xx_driver_api = {
|
||||||
|
#ifdef CONFIG_AMG88XX_TRIGGER
|
||||||
|
.attr_set = amg88xx_attr_set,
|
||||||
|
.trigger_set = amg88xx_trigger_set,
|
||||||
|
#endif
|
||||||
|
.sample_fetch = amg88xx_sample_fetch,
|
||||||
|
.channel_get = amg88xx_channel_get,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DEVICE_AND_API_INIT(amg88xx, CONFIG_AMG88XX_NAME, amg88xx_init,
|
||||||
|
&amg88xx_driver, NULL,
|
||||||
|
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
|
||||||
|
&amg88xx_driver_api);
|
144
drivers/sensor/amg88xx/amg88xx.h
Normal file
144
drivers/sensor/amg88xx/amg88xx.h
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Phytec Messtechnik GmbH
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SENSOR_AMG88XX
|
||||||
|
#define _SENSOR_AMG88XX
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
#include <misc/util.h>
|
||||||
|
|
||||||
|
#define AMG88XX_I2C_ADDRESS CONFIG_AMG88XX_I2C_ADDR
|
||||||
|
|
||||||
|
#define AMG88XX_PCLT 0x00 /* Setting Power control register */
|
||||||
|
#define AMG88XX_RST 0x01 /* Reset register */
|
||||||
|
#define AMG88XX_FPSC 0x02 /* Setting frame rate register */
|
||||||
|
#define AMG88XX_INTC 0x03 /* Setting interrupt control register */
|
||||||
|
#define AMG88XX_STAT 0x04 /* Status register */
|
||||||
|
#define AMG88XX_SCLR 0x05 /* Status clear register */
|
||||||
|
#define AMG88XX_AVE 0x07 /* Setting verage register */
|
||||||
|
#define AMG88XX_INTHL 0x08 /* Interrupt level upper limit [7:0] */
|
||||||
|
#define AMG88XX_INTHH 0x09 /* Interrupt level upper limit [11:8] */
|
||||||
|
#define AMG88XX_INTLL 0x0a /* Interrupt level lower limit [7:0] */
|
||||||
|
#define AMG88XX_INTLH 0x0b /* Interrupt level lower limit [11:8] */
|
||||||
|
#define AMG88XX_INTSL 0x0c /* Interrupt hysteresis level [7:0] */
|
||||||
|
#define AMG88XX_INTSH 0x0d /* Interrupt hysteresis level [11:8] */
|
||||||
|
#define AMG88XX_TTHL 0x0e /* Thermistor temperature data [7:0] */
|
||||||
|
#define AMG88XX_TTHH 0x0f /* Thermistor temperature data [10:8] */
|
||||||
|
#define AMG88XX_INT0 0x10 /* Pixel 1..8 Interrupt Result */
|
||||||
|
#define AMG88XX_INT1 0x11 /* Pixel 9..16 Interrupt Result */
|
||||||
|
#define AMG88XX_INT2 0x12 /* Pixel 17..24 Interrupt Result */
|
||||||
|
#define AMG88XX_INT3 0x13 /* Pixel 25..32 Interrupt Result */
|
||||||
|
#define AMG88XX_INT4 0x14 /* Pixel 33..40 Interrupt Result */
|
||||||
|
#define AMG88XX_INT5 0x15 /* Pixel 41..48 Interrupt Result */
|
||||||
|
#define AMG88XX_INT6 0x16 /* Pixel 49..56 Interrupt Result */
|
||||||
|
#define AMG88XX_INT7 0x17 /* Pixel 57..64 Interrupt Result */
|
||||||
|
|
||||||
|
#define AMG88XX_OUTPUT_BASE 0x80 /* Base address for the output values */
|
||||||
|
|
||||||
|
#define AMG88XX_PCLT_NORMAL_MODE 0x00
|
||||||
|
#define AMG88XX_PCLT_SLEEEP_MODE 0x10
|
||||||
|
#define AMG88XX_PCLT_STAND_BY_60S_MODE 0x20
|
||||||
|
#define AMG88XX_PCLT_STAND_BY_10S_MODE 0x21
|
||||||
|
|
||||||
|
#define AMG88XX_RST_FLAG_RST 0x30
|
||||||
|
#define AMG88XX_RST_INITIAL_RST 0x3F
|
||||||
|
|
||||||
|
#define AMG88XX_FPSC_10FPS 0x00
|
||||||
|
#define AMG88XX_FPSC_1FPS 0x01
|
||||||
|
|
||||||
|
#define AMG88XX_INTC_DISABLED 0x00
|
||||||
|
#define AMG88XX_INTC_DIFF_MODE 0x01
|
||||||
|
#define AMG88XX_INTC_ABS_MODE 0x03
|
||||||
|
|
||||||
|
#define AMG88XX_STAT_INTF_MASK 0x02
|
||||||
|
#define AMG88XX_STAT_OVF_IRS_MASK 0x04
|
||||||
|
|
||||||
|
#define AMG88XX_SCLR_INTCLR_MASK 0x02
|
||||||
|
#define AMG88XX_SCLR_OVS_CLR_MASK 0x04
|
||||||
|
|
||||||
|
#define AMG88XX_AVE_MAMOD_MASK 0x20
|
||||||
|
|
||||||
|
/* 1 LSB is equivalent to 0.25 degree Celsius scaled to micro degrees */
|
||||||
|
#define AMG88XX_TREG_LSB_SCALING 250000
|
||||||
|
|
||||||
|
#define AMG88XX_WAIT_MODE_CHANGE_US 50000
|
||||||
|
#define AMG88XX_WAIT_INITIAL_RESET_US 2000
|
||||||
|
|
||||||
|
struct amg88xx_data {
|
||||||
|
struct device *i2c;
|
||||||
|
s16_t sample[64];
|
||||||
|
|
||||||
|
#ifdef CONFIG_AMG88XX_TRIGGER
|
||||||
|
struct device *gpio;
|
||||||
|
struct gpio_callback gpio_cb;
|
||||||
|
|
||||||
|
sensor_trigger_handler_t drdy_handler;
|
||||||
|
struct sensor_trigger drdy_trigger;
|
||||||
|
|
||||||
|
sensor_trigger_handler_t th_handler;
|
||||||
|
struct sensor_trigger th_trigger;
|
||||||
|
|
||||||
|
#if defined(CONFIG_AMG88XX_TRIGGER_OWN_THREAD)
|
||||||
|
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_AMG88XX_THREAD_STACK_SIZE);
|
||||||
|
struct k_sem gpio_sem;
|
||||||
|
struct k_thread thread;
|
||||||
|
#elif defined(CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD)
|
||||||
|
struct k_work work;
|
||||||
|
struct device *dev;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_AMG88XX_TRIGGER */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int amg88xx_reg_read(struct amg88xx_data *drv_data,
|
||||||
|
u8_t reg, u8_t *val)
|
||||||
|
{
|
||||||
|
return i2c_reg_read_byte(drv_data->i2c, CONFIG_AMG88XX_I2C_ADDR,
|
||||||
|
reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int amg88xx_reg_write(struct amg88xx_data *drv_data,
|
||||||
|
u8_t reg, u8_t val)
|
||||||
|
{
|
||||||
|
return i2c_reg_write_byte(drv_data->i2c, CONFIG_AMG88XX_I2C_ADDR,
|
||||||
|
reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int amg88xx_reg_update(struct amg88xx_data *drv_data, u8_t reg,
|
||||||
|
u8_t mask, u8_t val)
|
||||||
|
{
|
||||||
|
return i2c_reg_update_byte(drv_data->i2c, CONFIG_AMG88XX_I2C_ADDR,
|
||||||
|
reg, mask, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_AMG88XX_TRIGGER
|
||||||
|
int amg88xx_reg_read(struct amg88xx_data *drv_data, u8_t reg, u8_t *val);
|
||||||
|
|
||||||
|
int amg88xx_reg_write(struct amg88xx_data *drv_data, u8_t reg, u8_t val);
|
||||||
|
|
||||||
|
int amg88xx_reg_update(struct amg88xx_data *drv_data, u8_t reg,
|
||||||
|
u8_t mask, u8_t val);
|
||||||
|
|
||||||
|
int amg88xx_attr_set(struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
const struct sensor_value *val);
|
||||||
|
|
||||||
|
int amg88xx_trigger_set(struct device *dev,
|
||||||
|
const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler);
|
||||||
|
|
||||||
|
int amg88xx_init_interrupt(struct device *dev);
|
||||||
|
#endif /* CONFIG_AMG88XX_TRIGGER */
|
||||||
|
|
||||||
|
#define SYS_LOG_DOMAIN "AMG88XX"
|
||||||
|
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
|
||||||
|
|
||||||
|
#include <logging/sys_log.h>
|
||||||
|
|
||||||
|
#endif
|
181
drivers/sensor/amg88xx/amg88xx_trigger.c
Normal file
181
drivers/sensor/amg88xx/amg88xx_trigger.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Phytec Messtechnik GmbH
|
||||||
|
* Copyright (c) 2017 Benedict Ohl (Benedict-Ohl@web.de)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
#include <misc/util.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <sensor.h>
|
||||||
|
#include "amg88xx.h"
|
||||||
|
|
||||||
|
extern struct amg88xx_data amg88xx_driver;
|
||||||
|
|
||||||
|
int amg88xx_attr_set(struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
const struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
s16_t int_level = (val->val1 * 1000000 + val->val2) /
|
||||||
|
AMG88XX_TREG_LSB_SCALING;
|
||||||
|
u8_t intl_reg;
|
||||||
|
u8_t inth_reg;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_TEMP) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LOG_DBG("set threshold to %d", int_level);
|
||||||
|
|
||||||
|
if (attr == SENSOR_ATTR_UPPER_THRESH) {
|
||||||
|
intl_reg = AMG88XX_INTHL;
|
||||||
|
inth_reg = AMG88XX_INTHH;
|
||||||
|
} else if (attr == SENSOR_ATTR_LOWER_THRESH) {
|
||||||
|
intl_reg = AMG88XX_INTLL;
|
||||||
|
inth_reg = AMG88XX_INTLH;
|
||||||
|
} else {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amg88xx_reg_write(drv_data, intl_reg, (u8_t)int_level)) {
|
||||||
|
SYS_LOG_DBG("Failed to set INTxL attribute!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amg88xx_reg_write(drv_data, inth_reg, (u8_t)(int_level >> 8))) {
|
||||||
|
SYS_LOG_DBG("Failed to set INTxH attribute!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amg88xx_gpio_callback(struct device *dev,
|
||||||
|
struct gpio_callback *cb, u32_t pins)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data =
|
||||||
|
CONTAINER_OF(cb, struct amg88xx_data, gpio_cb);
|
||||||
|
|
||||||
|
gpio_pin_disable_callback(dev, CONFIG_AMG88XX_GPIO_PIN_NUM);
|
||||||
|
|
||||||
|
#if defined(CONFIG_AMG88XX_TRIGGER_OWN_THREAD)
|
||||||
|
k_sem_give(&drv_data->gpio_sem);
|
||||||
|
#elif defined(CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD)
|
||||||
|
k_work_submit(&drv_data->work);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amg88xx_thread_cb(void *arg)
|
||||||
|
{
|
||||||
|
struct device *dev = arg;
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
u8_t status;
|
||||||
|
|
||||||
|
if (amg88xx_reg_read(drv_data, AMG88XX_STAT, &status) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv_data->drdy_handler != NULL) {
|
||||||
|
drv_data->drdy_handler(dev, &drv_data->drdy_trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv_data->th_handler != NULL) {
|
||||||
|
drv_data->th_handler(dev, &drv_data->th_trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_enable_callback(drv_data->gpio, CONFIG_AMG88XX_GPIO_PIN_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_AMG88XX_TRIGGER_OWN_THREAD
|
||||||
|
static void amg88xx_thread(int dev_ptr, int unused)
|
||||||
|
{
|
||||||
|
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
ARG_UNUSED(unused);
|
||||||
|
|
||||||
|
while (42) {
|
||||||
|
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
||||||
|
amg88xx_thread_cb(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD
|
||||||
|
static void amg88xx_work_cb(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data =
|
||||||
|
CONTAINER_OF(work, struct amg88xx_data, work);
|
||||||
|
amg88xx_thread_cb(drv_data->dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int amg88xx_trigger_set(struct device *dev,
|
||||||
|
const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
amg88xx_reg_write(drv_data, AMG88XX_INTC,
|
||||||
|
AMG88XX_INTC_DISABLED);
|
||||||
|
gpio_pin_disable_callback(drv_data->gpio, CONFIG_AMG88XX_GPIO_PIN_NUM);
|
||||||
|
|
||||||
|
if (trig->type == SENSOR_TRIG_THRESHOLD) {
|
||||||
|
drv_data->th_handler = handler;
|
||||||
|
drv_data->th_trigger = *trig;
|
||||||
|
} else {
|
||||||
|
SYS_LOG_ERR("Unsupported sensor trigger");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_enable_callback(drv_data->gpio, CONFIG_AMG88XX_GPIO_PIN_NUM);
|
||||||
|
amg88xx_reg_write(drv_data, AMG88XX_INTC,
|
||||||
|
AMG88XX_INTC_ABS_MODE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amg88xx_init_interrupt(struct device *dev)
|
||||||
|
{
|
||||||
|
struct amg88xx_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
/* setup gpio interrupt */
|
||||||
|
drv_data->gpio = device_get_binding(CONFIG_AMG88XX_GPIO_DEV_NAME);
|
||||||
|
if (drv_data->gpio == NULL) {
|
||||||
|
SYS_LOG_DBG("Failed to get pointer to %s device!",
|
||||||
|
CONFIG_AMG88XX_GPIO_DEV_NAME);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_configure(drv_data->gpio, CONFIG_AMG88XX_GPIO_PIN_NUM,
|
||||||
|
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
|
||||||
|
GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);
|
||||||
|
|
||||||
|
gpio_init_callback(&drv_data->gpio_cb,
|
||||||
|
amg88xx_gpio_callback,
|
||||||
|
BIT(CONFIG_AMG88XX_GPIO_PIN_NUM));
|
||||||
|
|
||||||
|
if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) {
|
||||||
|
SYS_LOG_DBG("Failed to set gpio callback!");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_AMG88XX_TRIGGER_OWN_THREAD)
|
||||||
|
k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
|
||||||
|
|
||||||
|
k_thread_create(&drv_data->thread, drv_data->thread_stack,
|
||||||
|
CONFIG_AMG88XX_THREAD_STACK_SIZE,
|
||||||
|
(k_thread_entry_t)amg88xx_thread, dev,
|
||||||
|
0, NULL, K_PRIO_COOP(CONFIG_AMG88XX_THREAD_PRIORITY),
|
||||||
|
0, 0);
|
||||||
|
#elif defined(CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD)
|
||||||
|
drv_data->work.handler = amg88xx_work_cb;
|
||||||
|
drv_data->dev = dev;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue