Compare commits
No commits in common. "fc2f57e4cb7bacc0910f98dd23890eba9a6e4063" and "6250786c661d862e8c8228bd870e4b362fcfc4c0" have entirely different histories.
fc2f57e4cb
...
6250786c66
19 changed files with 10 additions and 2312 deletions
|
@ -1,4 +1,2 @@
|
||||||
# Copyright (c) 2024 PM
|
# Copyright (c) 2024 PM
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
add_subdirectory(drivers)
|
|
||||||
|
|
2
Kconfig
2
Kconfig
|
@ -5,5 +5,5 @@
|
||||||
# as the module Kconfig entry point (see zephyr/module.yml). You can browse
|
# as the module Kconfig entry point (see zephyr/module.yml). You can browse
|
||||||
# module options by going to Zephyr -> Modules in Kconfig.
|
# module options by going to Zephyr -> Modules in Kconfig.
|
||||||
|
|
||||||
rsource "drivers/Kconfig"
|
# rsource "drivers/Kconfig"
|
||||||
# rsource "lib/Kconfig"
|
# rsource "lib/Kconfig"
|
|
@ -10,9 +10,6 @@ CONFIG_I2C_SHELL=y
|
||||||
CONFIG_INPUT_SHELL=y
|
CONFIG_INPUT_SHELL=y
|
||||||
CONFIG_LV_Z_SHELL=y
|
CONFIG_LV_Z_SHELL=y
|
||||||
|
|
||||||
CONFIG_SENSOR_SHELL=y
|
|
||||||
# CONFIG_SENSOR_SHELL_BATTERY=y
|
|
||||||
|
|
||||||
# LVGL
|
# LVGL
|
||||||
CONFIG_LVGL=y
|
CONFIG_LVGL=y
|
||||||
CONFIG_LV_COLOR_DEPTH_32=y
|
CONFIG_LV_COLOR_DEPTH_32=y
|
||||||
|
|
|
@ -12,14 +12,11 @@
|
||||||
#include <lvgl_input_device.h>
|
#include <lvgl_input_device.h>
|
||||||
|
|
||||||
#include <zephyr/drivers/display.h>
|
#include <zephyr/drivers/display.h>
|
||||||
#include <zephyr/drivers/sensor.h>
|
|
||||||
#include <zephyr/input/input.h>
|
#include <zephyr/input/input.h>
|
||||||
#include <zephyr/random/random.h>
|
#include <zephyr/random/random.h>
|
||||||
|
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
#include "../../drivers/sensor/mlx90640/mlx90640.h"
|
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL);
|
LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL);
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
|
@ -29,7 +26,6 @@ int main(void)
|
||||||
|
|
||||||
char count_str[11] = {0};
|
char count_str[11] = {0};
|
||||||
const struct device *display_dev;
|
const struct device *display_dev;
|
||||||
const struct device *ir_dev;
|
|
||||||
|
|
||||||
display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
|
display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
|
||||||
if (!device_is_ready(display_dev))
|
if (!device_is_ready(display_dev))
|
||||||
|
@ -51,64 +47,33 @@ int main(void)
|
||||||
lv_obj_t *ir_image = lv_canvas_create(lv_scr_act());
|
lv_obj_t *ir_image = lv_canvas_create(lv_scr_act());
|
||||||
lv_canvas_set_buffer(ir_image, cbuf, 32, 24, LV_IMG_CF_TRUE_COLOR);
|
lv_canvas_set_buffer(ir_image, cbuf, 32, 24, LV_IMG_CF_TRUE_COLOR);
|
||||||
|
|
||||||
lv_canvas_fill_bg(ir_image, lv_color_make(0x40, 0x40, 0x40), LV_OPA_COVER);
|
lv_canvas_fill_bg(ir_image, lv_color_make(0x40,0x40,0x40), LV_OPA_COVER);
|
||||||
|
|
||||||
lv_obj_set_size(ir_image, 32, 24);
|
lv_obj_set_size(ir_image, 32, 24);
|
||||||
lv_obj_align(ir_image, LV_ALIGN_TOP_LEFT, 4, 4);
|
lv_obj_align(ir_image, LV_ALIGN_TOP_LEFT, 4, 4);
|
||||||
lv_img_set_pivot(ir_image, 0, 0);
|
lv_img_set_pivot(ir_image, 0, 0);
|
||||||
// lv_img_set_zoom(ir_image, 256 * 2);
|
lv_img_set_zoom(ir_image, 256 * 8);
|
||||||
lv_img_set_zoom(ir_image, 256 * 12);
|
|
||||||
lv_img_set_antialias(ir_image, false);
|
lv_img_set_antialias(ir_image, false);
|
||||||
|
|
||||||
lv_timer_handler();
|
lv_timer_handler();
|
||||||
display_blanking_off(display_dev);
|
display_blanking_off(display_dev);
|
||||||
|
|
||||||
ir_dev = DEVICE_DT_GET(DT_NODELABEL(mlx90640_mlx90640_elecrow_i2c));
|
|
||||||
if (!device_is_ready(ir_dev))
|
|
||||||
{
|
|
||||||
printf("Device %s not ready\n", ir_dev->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_color32_t color;
|
lv_color32_t color;
|
||||||
float *temps = ((struct mlx90640_data *)ir_dev->data)->temps;
|
|
||||||
int64_t reftime = k_uptime_get();
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
sensor_sample_fetch(ir_dev);
|
|
||||||
mlx90640_calculate_to(ir_dev, 0.8, ((struct mlx90640_data *)ir_dev->data)->ta - 8.0f); // Tr = Ta - 8.0 from PDF
|
|
||||||
|
|
||||||
for (int y = 0; y < 24; y++)
|
for (int y = 0; y < 24; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < 32; x++)
|
for (int x = 0; x < 32; x++)
|
||||||
{
|
{
|
||||||
if (temps[y * 32 + x] < 0)
|
color.ch.red = (color.ch.red + 11) % 255;
|
||||||
{
|
color.ch.green = (color.ch.green + 17) % 255;
|
||||||
color = lv_color_black();
|
color.ch.blue = (color.ch.blue + 13) % 255;
|
||||||
}
|
|
||||||
else if (temps[y * 32 + x] > 64)
|
|
||||||
{
|
|
||||||
color = lv_color_white();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color.ch.red = (uint8_t)(temps[y * 32 + x] * 4);
|
|
||||||
color.ch.green = color.ch.red;
|
|
||||||
color.ch.blue = color.ch.red;
|
|
||||||
}
|
|
||||||
lv_canvas_set_px_color(ir_image, x, y, color);
|
lv_canvas_set_px_color(ir_image, x, y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_timer_handler();
|
int delay = lv_timer_handler_run_in_period(100);
|
||||||
|
k_msleep(delay);
|
||||||
int64_t elapsed = k_uptime_delta(&reftime);
|
|
||||||
printf("took %d ms", (uint32_t)elapsed);
|
|
||||||
|
|
||||||
if (elapsed < 100)
|
|
||||||
{
|
|
||||||
k_msleep(100 - elapsed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
if SHIELD_MLX90640_ELECROW_I2C
|
|
||||||
|
|
||||||
config SENSOR
|
|
||||||
default y
|
|
||||||
|
|
||||||
config MLX90640
|
|
||||||
default y
|
|
||||||
|
|
||||||
endif # SHIELD_MLX90640_ELECROW_I2C
|
|
|
@ -1,6 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
config SHIELD_MLX90640_ELECROW_I2C
|
|
||||||
def_bool $(shields_list_contains,mlx90640_elecrow_i2c)
|
|
|
@ -1,15 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 PM
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
&i2c0 {
|
|
||||||
status = "okay";
|
|
||||||
|
|
||||||
mlx90640_mlx90640_elecrow_i2c: mlx90640@33 {
|
|
||||||
compatible = "melexis,mlx90640";
|
|
||||||
reg = <0x33>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -82,7 +82,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
&i2c0 {
|
&i2c0 {
|
||||||
clock-frequency = <I2C_BITRATE_FAST>;
|
clock-frequency = <I2C_BITRATE_STANDARD>;
|
||||||
pinctrl-0 = <&i2c0_default>;
|
pinctrl-0 = <&i2c0_default>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
CONFIG_BOARD_ELECROW_ESP_TERMINAL=y
|
CONFIG_BOARD_ELECROW_ESP_TERMINAL=y
|
||||||
CONFIG_SOC_SERIES_ESP32S3=y
|
CONFIG_SOC_SERIES_ESP32S3=y
|
||||||
|
|
||||||
# increased for LVGL
|
CONFIG_MAIN_STACK_SIZE=8192 # increased for LVGL
|
||||||
CONFIG_MAIN_STACK_SIZE=8192
|
|
||||||
|
|
||||||
CONFIG_CONSOLE=y
|
CONFIG_CONSOLE=y
|
||||||
CONFIG_SERIAL=y
|
CONFIG_SERIAL=y
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
add_subdirectory_ifdef(CONFIG_SENSOR sensor)
|
|
|
@ -1,6 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
menu "Drivers"
|
|
||||||
rsource "sensor/Kconfig"
|
|
||||||
endmenu
|
|
|
@ -1,4 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
add_subdirectory_ifdef(CONFIG_MLX90640 mlx90640)
|
|
|
@ -1,6 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
if SENSOR
|
|
||||||
rsource "mlx90640/Kconfig"
|
|
||||||
endif # SENSOR
|
|
|
@ -1,7 +0,0 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
zephyr_library()
|
|
||||||
|
|
||||||
zephyr_library_sources(mlx90640.c)
|
|
||||||
# zephyr_library_sources_ifdef(CONFIG_MLX90640_TRIGGER mlx90640_trigger.c)
|
|
||||||
# zephyr_library_sources(vendor/functions/MLX90640.c)
|
|
|
@ -1,55 +0,0 @@
|
||||||
# MLX90640 infrared thermopile sensor configuration options
|
|
||||||
|
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
# menuconfig MLX90640
|
|
||||||
config MLX90640
|
|
||||||
bool "MLX90640 Infrared Thermopile Sensor"
|
|
||||||
default y
|
|
||||||
depends on DT_HAS_MELEXIS_MLX90640_ENABLED
|
|
||||||
select I2C
|
|
||||||
help
|
|
||||||
Enable driver for MLX90640 infrared thermopile sensor.
|
|
||||||
|
|
||||||
# if MLX90640
|
|
||||||
|
|
||||||
# choice
|
|
||||||
# prompt "Trigger mode"
|
|
||||||
# default MLX90640_TRIGGER_NONE
|
|
||||||
# help
|
|
||||||
# Specify the type of triggering used by the driver.
|
|
||||||
|
|
||||||
# config MLX90640_TRIGGER_NONE
|
|
||||||
# bool "No trigger"
|
|
||||||
|
|
||||||
# config MLX90640_TRIGGER_GLOBAL_THREAD
|
|
||||||
# bool "Use global thread"
|
|
||||||
# depends on GPIO
|
|
||||||
# select MLX90640_TRIGGER
|
|
||||||
|
|
||||||
# config MLX90640_TRIGGER_OWN_THREAD
|
|
||||||
# bool "Use own thread"
|
|
||||||
# depends on GPIO
|
|
||||||
# select MLX90640_TRIGGER
|
|
||||||
|
|
||||||
# endchoice
|
|
||||||
|
|
||||||
# config MLX90640_TRIGGER
|
|
||||||
# bool
|
|
||||||
|
|
||||||
# config MLX90640_THREAD_PRIORITY
|
|
||||||
# int "Thread priority"
|
|
||||||
# depends on MLX90640_TRIGGER_OWN_THREAD
|
|
||||||
# default 10
|
|
||||||
# help
|
|
||||||
# Priority of thread used by the driver to handle interrupts.
|
|
||||||
|
|
||||||
# config MLX90640_THREAD_STACK_SIZE
|
|
||||||
# int "Thread stack size"
|
|
||||||
# depends on MLX90640_TRIGGER_OWN_THREAD
|
|
||||||
# default 1024
|
|
||||||
# help
|
|
||||||
# Stack size of thread used by the driver to handle interrupts.
|
|
||||||
|
|
||||||
# endif # MLX90640
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,146 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 PM
|
|
||||||
*
|
|
||||||
* using code from Melexis https://github.com/melexis/mlx90640-library,
|
|
||||||
* commit f6be7ca1d4a55146b705f3d347f84b773b29cc86 under Apache-2.0
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ZEPHYR_DRIVERS_SENSOR_MLX90640_MLX90640_H_
|
|
||||||
#define ZEPHYR_DRIVERS_SENSOR_MLX90640_MLX90640_H_
|
|
||||||
|
|
||||||
#include <zephyr/device.h>
|
|
||||||
#include <zephyr/drivers/gpio.h>
|
|
||||||
#include <zephyr/drivers/i2c.h>
|
|
||||||
#include <zephyr/sys/util.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int16_t kVdd;
|
|
||||||
int16_t vdd25;
|
|
||||||
float KvPTAT;
|
|
||||||
float KtPTAT;
|
|
||||||
uint16_t vPTAT25;
|
|
||||||
float alphaPTAT;
|
|
||||||
int16_t gainEE;
|
|
||||||
float tgc;
|
|
||||||
float cpKv;
|
|
||||||
float cpKta;
|
|
||||||
uint8_t resolutionEE;
|
|
||||||
uint8_t calibrationModeEE;
|
|
||||||
float KsTa;
|
|
||||||
float ksTo[5];
|
|
||||||
int16_t ct[5];
|
|
||||||
uint16_t alpha[768];
|
|
||||||
uint8_t alphaScale;
|
|
||||||
int16_t offset[768];
|
|
||||||
int8_t kta[768];
|
|
||||||
uint8_t ktaScale;
|
|
||||||
int8_t kv[768];
|
|
||||||
uint8_t kvScale;
|
|
||||||
float cpAlpha[2];
|
|
||||||
int16_t cpOffset[2];
|
|
||||||
float ilChessC[3];
|
|
||||||
uint16_t brokenPixels[5];
|
|
||||||
uint16_t outlierPixels[5];
|
|
||||||
} mlx90640_params;
|
|
||||||
|
|
||||||
enum mlx90640_refresh_rate
|
|
||||||
{
|
|
||||||
MLX90640_REFRESH_0_5 = 0,
|
|
||||||
MLX90640_REFRESH_1 = 1,
|
|
||||||
MLX90640_REFRESH_2 = 2,
|
|
||||||
MLX90640_REFRESH_4 = 3,
|
|
||||||
MLX90640_REFRESH_8 = 4,
|
|
||||||
MLX90640_REFRESH_16 = 5,
|
|
||||||
MLX90640_REFRESH_32 = 6,
|
|
||||||
MLX90640_REFRESH_64 = 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mlx90640_adc_resolution
|
|
||||||
{
|
|
||||||
MLX90640_ADC_RES_16 = 0,
|
|
||||||
MLX90640_ADC_RES_17 = 1,
|
|
||||||
MLX90640_ADC_RES_18 = 2,
|
|
||||||
MLX90640_ADC_RES_19 = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mlx90640_reading_pattern
|
|
||||||
{
|
|
||||||
MLX90640_PATTERN_INTERLEAVED = 0,
|
|
||||||
MLX90640_PATTERN_CHESS = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mlx90640_config
|
|
||||||
{
|
|
||||||
const struct i2c_dt_spec i2c;
|
|
||||||
const enum mlx90640_refresh_rate refresh_rate;
|
|
||||||
const enum mlx90640_adc_resolution adc_resolution;
|
|
||||||
const enum mlx90640_reading_pattern reading_pattern;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mlx90640_data
|
|
||||||
{
|
|
||||||
float temps[768];
|
|
||||||
float vdd;
|
|
||||||
float ta;
|
|
||||||
uint16_t raw_data[833]; // 768 px + 64 metadata + 1 status
|
|
||||||
mlx90640_params params;
|
|
||||||
|
|
||||||
#ifdef CONFIG_MLX90640_TRIGGER
|
|
||||||
const struct device *dev;
|
|
||||||
struct gpio_callback gpio_cb;
|
|
||||||
|
|
||||||
sensor_trigger_handler_t drdy_handler;
|
|
||||||
const struct sensor_trigger *drdy_trigger;
|
|
||||||
|
|
||||||
sensor_trigger_handler_t th_handler;
|
|
||||||
const struct sensor_trigger *th_trigger;
|
|
||||||
|
|
||||||
#if defined(CONFIG_MLX90640_TRIGGER_OWN_THREAD)
|
|
||||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_MLX90640_THREAD_STACK_SIZE);
|
|
||||||
struct k_sem gpio_sem;
|
|
||||||
struct k_thread thread;
|
|
||||||
#elif defined(CONFIG_MLX90640_TRIGGER_GLOBAL_THREAD)
|
|
||||||
struct k_work work;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* CONFIG_MLX90640_TRIGGER */
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef CONFIG_MLX90640_TRIGGER
|
|
||||||
int mlx90640_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr,
|
|
||||||
const struct sensor_value *val);
|
|
||||||
|
|
||||||
int mlx90640_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler);
|
|
||||||
|
|
||||||
int mlx90640_init_interrupt(const struct device *dev);
|
|
||||||
#endif /* CONFIG_MLX90640_TRIGGER */
|
|
||||||
|
|
||||||
// data
|
|
||||||
int mlx90640_synch_frame(const struct device *dev);
|
|
||||||
int mlx90640_trigger_measurement(const struct device *dev);
|
|
||||||
int mlx90640_get_frame_data(const struct device *dev);
|
|
||||||
|
|
||||||
// process
|
|
||||||
float mlx90640_get_vdd(const struct device *dev);
|
|
||||||
float mlx90640_get_ta(const struct device *dev);
|
|
||||||
|
|
||||||
// void mlx90640_get_image(const struct device *dev);
|
|
||||||
// or!
|
|
||||||
void mlx90640_calculate_to(const struct device *dev, float emissivity, float tr);
|
|
||||||
|
|
||||||
// optional /
|
|
||||||
void mlx90640_bad_pixels_correction(const struct device *dev, int mode);
|
|
||||||
|
|
||||||
int mlx90640_set_adc_resolution(const struct device *dev, enum mlx90640_adc_resolution res);
|
|
||||||
enum mlx90640_adc_resolution mlx90640_get_adc_resolution(const struct device *dev);
|
|
||||||
|
|
||||||
int mlx90640_set_refresh_rate(const struct device *dev, enum mlx90640_refresh_rate res);
|
|
||||||
enum mlx90640_refresh_rate mlx90640_get_refresh_rate(const struct device *dev);
|
|
||||||
|
|
||||||
int mlx90640_set_reading_pattern(const struct device *dev, enum mlx90640_reading_pattern res);
|
|
||||||
enum mlx90640_reading_pattern mlx90640_get_reading_pattern(const struct device *dev);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,213 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017-2019 Phytec Messtechnik GmbH
|
|
||||||
* Copyright (c) 2017 Benedict Ohl (Benedict-Ohl@web.de)
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <zephyr/device.h>
|
|
||||||
#include <zephyr/drivers/gpio.h>
|
|
||||||
#include <zephyr/drivers/i2c.h>
|
|
||||||
#include <zephyr/sys/util.h>
|
|
||||||
#include <zephyr/kernel.h>
|
|
||||||
#include <zephyr/drivers/sensor.h>
|
|
||||||
#include "amg88xx.h"
|
|
||||||
|
|
||||||
extern struct amg88xx_data amg88xx_driver;
|
|
||||||
|
|
||||||
#include <zephyr/logging/log.h>
|
|
||||||
LOG_MODULE_DECLARE(AMG88XX, CONFIG_SENSOR_LOG_LEVEL);
|
|
||||||
|
|
||||||
static inline void amg88xx_setup_int(const struct amg88xx_config *cfg,
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
unsigned int flags = enable
|
|
||||||
? GPIO_INT_EDGE_TO_ACTIVE
|
|
||||||
: GPIO_INT_DISABLE;
|
|
||||||
|
|
||||||
gpio_pin_interrupt_configure_dt(&cfg->int_gpio, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int amg88xx_attr_set(const struct device *dev,
|
|
||||||
enum sensor_channel chan,
|
|
||||||
enum sensor_attribute attr,
|
|
||||||
const struct sensor_value *val)
|
|
||||||
{
|
|
||||||
const struct amg88xx_config *config = dev->config;
|
|
||||||
int16_t int_level = (val->val1 * 1000000 + val->val2) /
|
|
||||||
AMG88XX_TREG_LSB_SCALING;
|
|
||||||
uint8_t intl_reg;
|
|
||||||
uint8_t inth_reg;
|
|
||||||
|
|
||||||
if (!config->int_gpio.port) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (i2c_reg_write_byte_dt(&config->i2c,
|
|
||||||
intl_reg, (uint8_t)int_level)) {
|
|
||||||
LOG_DBG("Failed to set INTxL attribute!");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_reg_write_byte_dt(&config->i2c,
|
|
||||||
inth_reg, (uint8_t)(int_level >> 8))) {
|
|
||||||
LOG_DBG("Failed to set INTxH attribute!");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amg88xx_gpio_callback(const struct device *dev,
|
|
||||||
struct gpio_callback *cb, uint32_t pins)
|
|
||||||
{
|
|
||||||
struct amg88xx_data *drv_data =
|
|
||||||
CONTAINER_OF(cb, struct amg88xx_data, gpio_cb);
|
|
||||||
const struct amg88xx_config *config = drv_data->dev->config;
|
|
||||||
|
|
||||||
amg88xx_setup_int(config, false);
|
|
||||||
|
|
||||||
#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(const struct device *dev)
|
|
||||||
{
|
|
||||||
struct amg88xx_data *drv_data = dev->data;
|
|
||||||
const struct amg88xx_config *config = dev->config;
|
|
||||||
uint8_t status;
|
|
||||||
|
|
||||||
if (i2c_reg_read_byte_dt(&config->i2c,
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
amg88xx_setup_int(config, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_AMG88XX_TRIGGER_OWN_THREAD
|
|
||||||
static void amg88xx_thread(void *p1, void *p2, void *p3)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(p2);
|
|
||||||
ARG_UNUSED(p3);
|
|
||||||
|
|
||||||
struct amg88xx_data *drv_data = p1;
|
|
||||||
|
|
||||||
while (42) {
|
|
||||||
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
|
||||||
amg88xx_thread_cb(drv_data->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(const struct device *dev,
|
|
||||||
const struct sensor_trigger *trig,
|
|
||||||
sensor_trigger_handler_t handler)
|
|
||||||
{
|
|
||||||
struct amg88xx_data *drv_data = dev->data;
|
|
||||||
const struct amg88xx_config *config = dev->config;
|
|
||||||
|
|
||||||
if (!config->int_gpio.port) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_reg_write_byte_dt(&config->i2c,
|
|
||||||
AMG88XX_INTC, AMG88XX_INTC_DISABLED)) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
amg88xx_setup_int(config, false);
|
|
||||||
|
|
||||||
if (trig->type == SENSOR_TRIG_THRESHOLD) {
|
|
||||||
drv_data->th_handler = handler;
|
|
||||||
drv_data->th_trigger = trig;
|
|
||||||
} else {
|
|
||||||
LOG_ERR("Unsupported sensor trigger");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
amg88xx_setup_int(config, true);
|
|
||||||
|
|
||||||
if (i2c_reg_write_byte_dt(&config->i2c,
|
|
||||||
AMG88XX_INTC, AMG88XX_INTC_ABS_MODE)) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int amg88xx_init_interrupt(const struct device *dev)
|
|
||||||
{
|
|
||||||
struct amg88xx_data *drv_data = dev->data;
|
|
||||||
const struct amg88xx_config *config = dev->config;
|
|
||||||
|
|
||||||
if (!gpio_is_ready_dt(&config->int_gpio)) {
|
|
||||||
LOG_ERR("%s: device %s is not ready", dev->name,
|
|
||||||
config->int_gpio.port->name);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT | config->int_gpio.dt_flags);
|
|
||||||
|
|
||||||
gpio_init_callback(&drv_data->gpio_cb,
|
|
||||||
amg88xx_gpio_callback,
|
|
||||||
BIT(config->int_gpio.pin));
|
|
||||||
|
|
||||||
if (gpio_add_callback(config->int_gpio.port, &drv_data->gpio_cb) < 0) {
|
|
||||||
LOG_DBG("Failed to set gpio callback!");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
drv_data->dev = dev;
|
|
||||||
|
|
||||||
#if defined(CONFIG_AMG88XX_TRIGGER_OWN_THREAD)
|
|
||||||
k_sem_init(&drv_data->gpio_sem, 0, K_SEM_MAX_LIMIT);
|
|
||||||
|
|
||||||
k_thread_create(&drv_data->thread, drv_data->thread_stack,
|
|
||||||
CONFIG_AMG88XX_THREAD_STACK_SIZE,
|
|
||||||
amg88xx_thread, drv_data,
|
|
||||||
NULL, NULL, K_PRIO_COOP(CONFIG_AMG88XX_THREAD_PRIORITY),
|
|
||||||
0, K_NO_WAIT);
|
|
||||||
#elif defined(CONFIG_AMG88XX_TRIGGER_GLOBAL_THREAD)
|
|
||||||
drv_data->work.handler = amg88xx_work_cb;
|
|
||||||
#endif
|
|
||||||
amg88xx_setup_int(config, true);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
# Copyright (c) 2024 PM
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
description: Melexis MLX90640 32x24 (768) pixel infrared array sensor
|
|
||||||
|
|
||||||
compatible: "melexis,mlx90640"
|
|
||||||
|
|
||||||
include: [sensor-device.yaml, i2c-device.yaml]
|
|
||||||
|
|
||||||
properties:
|
|
||||||
refresh-rate:
|
|
||||||
type: int
|
|
||||||
default: 2
|
|
||||||
enum:
|
|
||||||
- 0 # 0.5HZ
|
|
||||||
- 1 # 1HZ
|
|
||||||
- 2 # 2HZ
|
|
||||||
- 3 # 4HZ
|
|
||||||
- 4 # 8HZ
|
|
||||||
- 5 # 16HZ
|
|
||||||
- 6 # 32HZ
|
|
||||||
- 7 # 64HZ
|
|
||||||
description:
|
|
||||||
Refresh rate of the sensor itself.
|
|
||||||
The I2C must be configured to keep up with the data flow.
|
|
||||||
This configures the rate for subfields, i.e. the full frame rate is half of this value.
|
|
||||||
|
|
||||||
adc-resolution:
|
|
||||||
type: int
|
|
||||||
default: 2
|
|
||||||
enum:
|
|
||||||
- 0 # 16BIT
|
|
||||||
- 1 # 17BIT
|
|
||||||
- 2 # 18BIT
|
|
||||||
- 3 # 19BIT
|
|
||||||
description:
|
|
||||||
ADC resolution.
|
|
||||||
|
|
||||||
reading-pattern:
|
|
||||||
type: int
|
|
||||||
default: 1
|
|
||||||
enum:
|
|
||||||
- 0 # CHESS
|
|
||||||
- 1 # INTERLEAVE
|
|
||||||
description:
|
|
||||||
Reading pattern.
|
|
||||||
The sensor can be read in either line-interleaved subfields (similar to a TV video)
|
|
||||||
or a pixel alternating "chess board" pattern.
|
|
Loading…
Reference in a new issue