drivers: sensor: grow_r502a: add built-in LED control
Add LED control attribute for sensor device's built-in LED using zephyr's led driver APIs. Signed-off-by: Dinesh Kumar K <dinesh@linumiz.com>
This commit is contained in:
parent
e57c6f9d2b
commit
3c8bd0bc2b
6 changed files with 182 additions and 49 deletions
|
|
@ -4,14 +4,13 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT hzgrow_r502a
|
||||
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/drivers/led.h>
|
||||
|
||||
#include <zephyr/drivers/sensor/grow_r502a.h>
|
||||
#include "grow_r502a.h"
|
||||
|
|
@ -105,7 +104,7 @@ static void uart_cb_handler(const struct device *dev, void *user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static int fps_led_control(const struct device *dev, struct led_params *led_control)
|
||||
static int fps_led_control(const struct device *dev, struct r502a_led_params *led_control)
|
||||
{
|
||||
union r502a_packet rx_packet = {0};
|
||||
char const led_ctrl_len = 5;
|
||||
|
|
@ -246,10 +245,10 @@ static int fps_get_image(const struct device *dev)
|
|||
union r502a_packet rx_packet = {0};
|
||||
char const get_img_len = 1;
|
||||
|
||||
struct led_params led_ctrl = {
|
||||
.ctrl_code = LED_CTRL_BREATHING,
|
||||
.color_idx = LED_COLOR_BLUE,
|
||||
.speed = LED_SPEED_HALF,
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_BREATHING,
|
||||
.color_idx = R502A_LED_COLOR_BLUE,
|
||||
.speed = R502A_LED_SPEED_HALF,
|
||||
.cycle = 0x01,
|
||||
};
|
||||
|
||||
|
|
@ -269,8 +268,8 @@ static int fps_get_image(const struct device *dev)
|
|||
fps_led_control(dev, &led_ctrl);
|
||||
LOG_DBG("Image taken");
|
||||
} else {
|
||||
led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS;
|
||||
led_ctrl.color_idx = LED_COLOR_RED;
|
||||
led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS;
|
||||
led_ctrl.color_idx = R502A_LED_COLOR_RED;
|
||||
fps_led_control(dev, &led_ctrl);
|
||||
LOG_ERR("Error getting image 0x%X", rx_packet.buf[R502A_CC_IDX]);
|
||||
return -EIO;
|
||||
|
|
@ -340,10 +339,10 @@ static int fps_store_model(const struct device *dev, uint16_t id)
|
|||
char const store_model_len = 4;
|
||||
int ret = 0;
|
||||
|
||||
struct led_params led_ctrl = {
|
||||
.ctrl_code = LED_CTRL_BREATHING,
|
||||
.color_idx = LED_COLOR_BLUE,
|
||||
.speed = LED_SPEED_HALF,
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_BREATHING,
|
||||
.color_idx = R502A_LED_COLOR_BLUE,
|
||||
.speed = R502A_LED_SPEED_HALF,
|
||||
.cycle = 0x01,
|
||||
};
|
||||
|
||||
|
|
@ -364,8 +363,8 @@ static int fps_store_model(const struct device *dev, uint16_t id)
|
|||
}
|
||||
|
||||
if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
|
||||
led_ctrl.color_idx = LED_COLOR_BLUE;
|
||||
led_ctrl.ctrl_code = LED_CTRL_FLASHING;
|
||||
led_ctrl.color_idx = R502A_LED_COLOR_BLUE;
|
||||
led_ctrl.ctrl_code = R502A_LED_CTRL_FLASHING;
|
||||
led_ctrl.cycle = 0x03;
|
||||
fps_led_control(dev, &led_ctrl);
|
||||
LOG_INF("Fingerprint stored! at ID #%d", id);
|
||||
|
|
@ -455,10 +454,10 @@ static int fps_search(const struct device *dev, struct sensor_value *val)
|
|||
char const search_len = 6;
|
||||
int ret = 0;
|
||||
|
||||
struct led_params led_ctrl = {
|
||||
.ctrl_code = LED_CTRL_BREATHING,
|
||||
.color_idx = LED_COLOR_BLUE,
|
||||
.speed = LED_SPEED_HALF,
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_BREATHING,
|
||||
.color_idx = R502A_LED_COLOR_BLUE,
|
||||
.speed = R502A_LED_SPEED_HALF,
|
||||
.cycle = 0x01,
|
||||
};
|
||||
|
||||
|
|
@ -480,23 +479,23 @@ static int fps_search(const struct device *dev, struct sensor_value *val)
|
|||
}
|
||||
|
||||
if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
|
||||
led_ctrl.ctrl_code = LED_CTRL_FLASHING;
|
||||
led_ctrl.color_idx = LED_COLOR_PURPLE;
|
||||
led_ctrl.ctrl_code = R502A_LED_CTRL_FLASHING;
|
||||
led_ctrl.color_idx = R502A_LED_COLOR_PURPLE;
|
||||
led_ctrl.cycle = 0x01;
|
||||
fps_led_control(dev, &led_ctrl);
|
||||
val->val1 = sys_get_be16(&rx_packet.data[1]);
|
||||
val->val2 = sys_get_be16(&rx_packet.data[3]);
|
||||
LOG_INF("Found a matching print! at ID #%d", val->val1);
|
||||
} else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND_CC) {
|
||||
led_ctrl.ctrl_code = LED_CTRL_BREATHING;
|
||||
led_ctrl.color_idx = LED_COLOR_RED;
|
||||
led_ctrl.ctrl_code = R502A_LED_CTRL_BREATHING;
|
||||
led_ctrl.color_idx = R502A_LED_COLOR_RED;
|
||||
led_ctrl.cycle = 0x02;
|
||||
fps_led_control(dev, &led_ctrl);
|
||||
LOG_ERR("Did not find a match");
|
||||
ret = -ENOENT;
|
||||
} else {
|
||||
led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS;
|
||||
led_ctrl.color_idx = LED_COLOR_RED;
|
||||
led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS;
|
||||
led_ctrl.color_idx = R502A_LED_COLOR_RED;
|
||||
fps_led_control(dev, &led_ctrl);
|
||||
LOG_ERR("Error searching for image 0x%X", rx_packet.buf[R502A_CC_IDX]);
|
||||
ret = -EIO;
|
||||
|
|
@ -549,10 +548,10 @@ static int fps_match_templates(const struct device *dev, struct sensor_value *va
|
|||
char const match_templates_len = 1;
|
||||
int ret = 0;
|
||||
|
||||
struct led_params led_ctrl = {
|
||||
.ctrl_code = LED_CTRL_BREATHING,
|
||||
.color_idx = LED_COLOR_BLUE,
|
||||
.speed = LED_SPEED_HALF,
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_BREATHING,
|
||||
.color_idx = R502A_LED_COLOR_BLUE,
|
||||
.speed = R502A_LED_SPEED_HALF,
|
||||
.cycle = 0x01,
|
||||
};
|
||||
|
||||
|
|
@ -581,8 +580,8 @@ static int fps_match_templates(const struct device *dev, struct sensor_value *va
|
|||
LOG_ERR("Fingerprint not matched");
|
||||
ret = -ENOENT;
|
||||
} else {
|
||||
led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS;
|
||||
led_ctrl.color_idx = LED_COLOR_RED;
|
||||
led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS;
|
||||
led_ctrl.color_idx = R502A_LED_COLOR_RED;
|
||||
fps_led_control(dev, &led_ctrl);
|
||||
LOG_ERR("Error Matching templates 0x%X",
|
||||
rx_packet.buf[R502A_CC_IDX]);
|
||||
|
|
@ -627,10 +626,10 @@ static int fps_init(const struct device *dev)
|
|||
struct grow_r502a_data *drv_data = dev->data;
|
||||
int ret;
|
||||
|
||||
struct led_params led_ctrl = {
|
||||
.ctrl_code = LED_CTRL_FLASHING,
|
||||
.color_idx = LED_COLOR_PURPLE,
|
||||
.speed = LED_SPEED_HALF,
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_FLASHING,
|
||||
.color_idx = R502A_LED_COLOR_PURPLE,
|
||||
.speed = R502A_LED_SPEED_HALF,
|
||||
.cycle = 0x02,
|
||||
};
|
||||
|
||||
|
|
@ -678,6 +677,8 @@ static int grow_r502a_channel_get(const struct device *dev, enum sensor_channel
|
|||
static int grow_r502a_attr_set(const struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr, const struct sensor_value *val)
|
||||
{
|
||||
struct grow_r502a_data *drv_data = dev->data;
|
||||
|
||||
if ((enum sensor_channel_grow_r502a)chan != SENSOR_CHAN_FINGERPRINT) {
|
||||
LOG_ERR("Channel not supported");
|
||||
return -ENOTSUP;
|
||||
|
|
@ -808,6 +809,53 @@ static const struct sensor_driver_api grow_r502a_api = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LED
|
||||
static int grow_r502a_led_set_color(const struct device *dev, uint32_t led,
|
||||
uint8_t num_colors, const uint8_t *color)
|
||||
{
|
||||
struct grow_r502a_data *drv_data = dev->data;
|
||||
|
||||
if (!(*color)) {
|
||||
LOG_ERR("invalid color code value");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
drv_data->led_color = *color;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int grow_r502a_led_on(const struct device *dev, uint32_t led)
|
||||
{
|
||||
struct grow_r502a_data *drv_data = dev->data;
|
||||
|
||||
if (!drv_data->led_color) {
|
||||
drv_data->led_color = R502A_LED_COLOR_BLUE;
|
||||
}
|
||||
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_ON_ALWAYS,
|
||||
.color_idx = drv_data->led_color,
|
||||
};
|
||||
|
||||
return fps_led_control(dev, &led_ctrl);
|
||||
}
|
||||
|
||||
static int grow_r502a_led_off(const struct device *dev, uint32_t led)
|
||||
{
|
||||
struct r502a_led_params led_ctrl = {
|
||||
.ctrl_code = R502A_LED_CTRL_OFF_ALWAYS,
|
||||
};
|
||||
|
||||
return fps_led_control(dev, &led_ctrl);
|
||||
}
|
||||
|
||||
static const struct led_driver_api grow_r502a_leds_api = {
|
||||
.set_color = grow_r502a_led_set_color,
|
||||
.on = grow_r502a_led_on,
|
||||
.off = grow_r502a_led_off,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define GROW_R502A_INIT(index) \
|
||||
static struct grow_r502a_data grow_r502a_data_##index; \
|
||||
\
|
||||
|
|
@ -823,6 +871,19 @@ static const struct sensor_driver_api grow_r502a_api = {
|
|||
\
|
||||
DEVICE_DT_INST_DEFINE(index, &grow_r502a_init, NULL, &grow_r502a_data_##index, \
|
||||
&grow_r502a_config_##index, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &grow_r502a_api);
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &grow_r502a_api); \
|
||||
|
||||
#define GROW_R502A_LED_INIT(index) \
|
||||
DEVICE_DT_INST_DEFINE(index, NULL, NULL, &grow_r502a_data_##index, \
|
||||
&grow_r502a_config_##index, POST_KERNEL, \
|
||||
CONFIG_LED_INIT_PRIORITY, &grow_r502a_leds_api); \
|
||||
|
||||
#define DT_DRV_COMPAT hzgrow_r502a
|
||||
DT_INST_FOREACH_STATUS_OKAY(GROW_R502A_INIT)
|
||||
#undef DT_DRV_COMPAT
|
||||
|
||||
#ifdef CONFIG_LED
|
||||
#define DT_DRV_COMPAT hzgrow_r502a_led
|
||||
DT_INST_FOREACH_STATUS_OKAY(GROW_R502A_LED_INIT)
|
||||
#undef DT_DRV_COMPAT
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -131,21 +131,40 @@
|
|||
#define R502A_DELAY 200
|
||||
#define R502A_RETRY_DELAY 5
|
||||
|
||||
#define LED_CTRL_BREATHING 0x01
|
||||
#define LED_CTRL_FLASHING 0x02
|
||||
#define LED_CTRL_ON_ALWAYS 0x03
|
||||
#define LED_CTRL_OFF_ALWAYS 0x04
|
||||
#define LED_CTRL_ON_GRADUALLY 0x05
|
||||
#define LED_CTRL_OFF_GRADUALLY 0x06
|
||||
/*LED glow control code*/
|
||||
enum r502a_led_ctrl_code {
|
||||
R502A_LED_CTRL_BREATHING = 0x01,
|
||||
R502A_LED_CTRL_FLASHING,
|
||||
R502A_LED_CTRL_ON_ALWAYS,
|
||||
R502A_LED_CTRL_OFF_ALWAYS,
|
||||
R502A_LED_CTRL_ON_GRADUALLY,
|
||||
R502A_LED_CTRL_OFF_GRADUALLY,
|
||||
};
|
||||
|
||||
#define LED_SPEED_HALF 0x50
|
||||
#define LED_SPEED_FULL 0xFF
|
||||
/* LED glow speed code
|
||||
* if needed, use desired speed between 0-255
|
||||
*/
|
||||
enum r502a_led_speed {
|
||||
R502A_LED_SPEED_MAX = 0x00,
|
||||
R502A_LED_SPEED_HALF = 0x50,
|
||||
R502A_LED_SPEED_MIN = 0xFF,
|
||||
};
|
||||
|
||||
#define LED_COLOR_RED 0x01
|
||||
#define LED_COLOR_BLUE 0x02
|
||||
#define LED_COLOR_PURPLE 0x03
|
||||
/* LED glowing cycle
|
||||
* if needed, use desired cycle count between 1-255
|
||||
*/
|
||||
enum r502a_led_cycle {
|
||||
R502A_LED_CYCLE_INFINITE = 0x00,
|
||||
R502A_LED_CYCLE_1,
|
||||
R502A_LED_CYCLE_2,
|
||||
R502A_LED_CYCLE_3,
|
||||
R502A_LED_CYCLE_4,
|
||||
R502A_LED_CYCLE_5,
|
||||
R502A_LED_CYCLE_255 = 0xFF,
|
||||
};
|
||||
|
||||
struct led_params {
|
||||
|
||||
struct r502a_led_params {
|
||||
uint8_t ctrl_code;
|
||||
uint8_t color_idx;
|
||||
uint8_t speed; /* Speed 0x00-0xff */
|
||||
|
|
@ -192,6 +211,7 @@ struct grow_r502a_data {
|
|||
struct k_sem uart_rx_sem;
|
||||
|
||||
uint16_t template_count;
|
||||
uint8_t led_color;
|
||||
};
|
||||
|
||||
struct grow_r502a_config {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@ extern "C" {
|
|||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
/*LED color code*/
|
||||
enum r502a_led_color_idx {
|
||||
R502A_LED_COLOR_RED = 0x01,
|
||||
R502A_LED_COLOR_BLUE,
|
||||
R502A_LED_COLOR_PURPLE,
|
||||
};
|
||||
|
||||
enum sensor_channel_grow_r502a {
|
||||
/** Fingerprint template count, ID number for enrolling and searching*/
|
||||
SENSOR_CHAN_FINGERPRINT = SENSOR_CHAN_PRIV_START,
|
||||
|
|
|
|||
|
|
@ -25,4 +25,9 @@
|
|||
int-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
led {
|
||||
compatible = "hzgrow,r502a-led";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@ CONFIG_SERIAL=y
|
|||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
|
||||
CONFIG_SENSOR=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_GROW_R502A_TRIGGER_OWN_THREAD=y
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/sensor/grow_r502a.h>
|
||||
#include <zephyr/drivers/led.h>
|
||||
|
||||
static bool enroll;
|
||||
static struct sensor_value fid_get, count, find, del;
|
||||
|
|
@ -79,6 +80,38 @@ static void template_count_get(const struct device *dev)
|
|||
printk("template count : %d\n", count.val1);
|
||||
}
|
||||
|
||||
static int r502a_led(void)
|
||||
{
|
||||
int ret;
|
||||
const int led_num = 0;
|
||||
const int led_color_a_inst = 1;
|
||||
uint8_t led_color = R502A_LED_COLOR_PURPLE;
|
||||
const struct device *led_dev = DEVICE_DT_GET_ONE(hzgrow_r502a_led);
|
||||
|
||||
if (led_dev == NULL) {
|
||||
printk("Error: no device found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!device_is_ready(led_dev)) {
|
||||
printk("Error: Device %s is not ready\n", led_dev->name);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = led_set_color(led_dev, led_num, led_color_a_inst, &led_color);
|
||||
if (ret != 0) {
|
||||
printk("led set color failed %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = led_on(led_dev, led_num);
|
||||
if (ret != 0) {
|
||||
printk("led on failed %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void trigger_handler(const struct device *dev,
|
||||
const struct sensor_trigger *trigger)
|
||||
{
|
||||
|
|
@ -106,6 +139,12 @@ int main(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = r502a_led();
|
||||
if (ret != 0) {
|
||||
printk("Error: device led failed to set %d", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template_count_get(dev);
|
||||
|
||||
del.val1 = 3;
|
||||
|
|
|
|||
Loading…
Reference in a new issue