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:
Dinesh Kumar K 2023-04-07 18:36:41 +05:30 committed by Anas Nashif
parent e57c6f9d2b
commit 3c8bd0bc2b
6 changed files with 182 additions and 49 deletions

View file

@ -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; \
\
@ -822,7 +870,20 @@ 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);
&grow_r502a_config_##index, POST_KERNEL, \
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

View file

@ -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 {

View file

@ -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,

View file

@ -25,4 +25,9 @@
int-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
};
};
led {
compatible = "hzgrow,r502a-led";
status = "okay";
};
};

View file

@ -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

View file

@ -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;