samples: drivers: add led_is31fl3733 sample to demonstrate usage

Add sample to demonstrate usage of IS31FL3733 LED using the LED API.
This led matrix controller has several custom APIs to expose
functionality not available within the standard led API, such as
limiting LED current.

Signed-off-by: Daniel DeGrasse <daniel@degrasse.com>
This commit is contained in:
Daniel DeGrasse 2023-04-07 23:58:35 -05:00 committed by Fabio Baltieri
parent 85a41ae88a
commit 351cb4bafe
7 changed files with 244 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(is31fl3733_matrix)
target_sources(app PRIVATE src/main.c)

View file

@ -0,0 +1,20 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2023 Daniel DeGrasse <daniel@degrasse.com>
source "Kconfig.zephyr"
config LED_ROW_COUNT
int "Number of rows in IS31FL3733 matrix"
default 12
help
Set this to match the number of SW LED sink connections
wired up to your IS31FL3733 LED driver. The sample will only attempt
to drive LEDs within this range.
config LED_COLUMN_COUNT
int "Number of columns in IS31FL3733 matrix"
default 16
help
Set this to match the number of CS LED source connections wired up
to your IS31FL3733 LED driver. The sample will only attempt to drive
LEDs within this range.

View file

@ -0,0 +1,35 @@
.. _is31fl3733:
IS31FL3733 LED Matrix Driver Demo Application
#############################################
Overview
********
This sample controls a matrix of up to 192 LEDs. The sample performs the
following test steps in an infinite loop:
- Set all LEDs to full brightness with `led_write_channels` API
- Disable upper quadrant of LED array with `led_write_channels` API
- Dim each LED in sequence using `led_set_brightness` API
- Toggle each LED in sequency using `led_on` and `led_off` APIs
- Toggle between low or high current limit using `is31fl3733_current_limit`
API, and repeat the above tests
Sample Configuration
====================
The number of LEDs can be limited using the following sample specific Kconfigs:
- `CONFIG_LED_ROW_COUNT`
- `CONFIG_LED_COLUMN_COUNT`
Building and Running
********************
This sample can be run on any board with an IS31FL3733 LED driver connected via
I2C, and a node with the `issi,is31fl3733` compatible present in its devicetree.
This sample provides a DTS overlay for the :ref:`frdm_k22f` board
(:file:`boards/frdm_k22f.overlay`). It assumes that the IS31FL3733 LED
controller is connected to I2C0, at address 0x50. The SDB GPIO should be
connected to PTC2 (A3 on the arduino header)

View file

@ -0,0 +1,13 @@
/*
* Copyright 2023 Daniel DeGrasse <daniel@degrasse.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
&i2c0 {
led_ctrl1: is31fl3733@50 {
reg = <0x50>;
compatible = "issi,is31fl3733";
sdb-gpios = <&gpioc 2 GPIO_ACTIVE_HIGH>;
};
};

View file

@ -0,0 +1,4 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2022 Daniel DeGrasse <daniel@degrasse.com>
CONFIG_LED=y
CONFIG_GPIO=y

View file

@ -0,0 +1,8 @@
sample:
description: Demonstration of the IS31FL3733 LED driver
name: IS31FL3733 sample
tests:
sample.drivers.led.is31fl3733:
filter: dt_compat_enabled("issi,is31fl3733")
tags: LED
depends_on: i2c

View file

@ -0,0 +1,156 @@
/*
* Copyright 2023 Daniel DeGrasse <daniel@degrasse.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/led.h>
#include <zephyr/drivers/led/is31fl3733.h>
#include <string.h>
#define HW_ROW_COUNT 12
#define HW_COL_COUNT 16
/* LED matrix is addressed using a row major format */
#define LED_MATRIX_COORD(x, y) ((x) * HW_COL_COUNT) + (y)
static uint8_t led_state[HW_COL_COUNT * HW_ROW_COUNT];
static int led_channel_write(const struct device *led)
{
int ret;
uint32_t led_idx;
/* Set all LEDs to full brightness */
printk("Set all LEDs to full brightness\n");
memset(led_state, 0, sizeof(led_state));
for (uint8_t row = 0; row < CONFIG_LED_ROW_COUNT; row++) {
for (uint8_t col = 0; col < CONFIG_LED_COLUMN_COUNT; col++) {
led_idx = LED_MATRIX_COORD(row, col);
led_state[led_idx] = 0xFF;
}
}
ret = led_write_channels(led, 0, sizeof(led_state), led_state);
if (ret) {
printk("Error: could not write LED channels (%d)\n", ret);
return ret;
}
k_msleep(1000);
/* Disable quadrant of LED display */
printk("Disable LED quadrant\n");
for (uint8_t row = 0; row < CONFIG_LED_ROW_COUNT / 2; row++) {
for (uint8_t col = 0; col < CONFIG_LED_COLUMN_COUNT / 2; col++) {
led_idx = LED_MATRIX_COORD(row, col);
led_state[led_idx] = 0x00;
}
}
ret = led_write_channels(led, 0,
((CONFIG_LED_ROW_COUNT / 2) * HW_COL_COUNT), led_state);
if (ret) {
printk("Error: could not write LED channels (%d)\n", ret);
return ret;
}
k_msleep(1000);
return 0;
}
static int led_brightness(const struct device *led)
{
int ret;
uint8_t row, col;
/* Set LED brightness to low value sequentially */
printk("Set LEDs to half brightness sequentially\n");
for (row = 0; row < CONFIG_LED_ROW_COUNT; row++) {
for (col = 0; col < CONFIG_LED_COLUMN_COUNT; col++) {
ret = led_set_brightness(led, LED_MATRIX_COORD(row, col),
50);
if (ret < 0) {
printk("Error: could not enable led "
"at [%d, %d]: (%d)\n",
row, col, ret);
return ret;
}
k_msleep(100);
}
}
return 0;
}
static int led_on_off(const struct device *led)
{
int ret;
uint8_t row, col;
printk("Toggle each led\n");
/* Turn on each led for a short duration */
for (row = 0; row < CONFIG_LED_ROW_COUNT; row++) {
for (col = 0; col < CONFIG_LED_COLUMN_COUNT; col++) {
ret = led_off(led, LED_MATRIX_COORD(row, col));
if (ret < 0) {
printk("Error: could not disable led "
"at [%d, %d]: (%d)\n",
row, col, ret);
return ret;
}
k_msleep(100);
ret = led_on(led, LED_MATRIX_COORD(row, col));
if (ret < 0) {
printk("Error: could not enable led "
"at [%d, %d]: (%d)\n",
row, col, ret);
return ret;
}
}
}
k_msleep(500);
return 0;
}
const struct device *led_dev = DEVICE_DT_GET_ONE(issi_is31fl3733);
void main(void)
{
int ret;
int current_limit = 0xFF;
if (!device_is_ready(led_dev)) {
printk("Error- LED device is not ready\n");
return;
}
while (1) {
ret = led_channel_write(led_dev);
if (ret < 0) {
return;
}
ret = led_brightness(led_dev);
if (ret < 0) {
return;
}
ret = led_on_off(led_dev);
if (ret < 0) {
return;
}
if (current_limit == 0xFF) {
/* Select lower current limt */
printk("Restarting sample with lower current limit\n");
current_limit = 0x3F;
ret = is31fl3733_current_limit(led_dev, current_limit);
if (ret) {
printk("Could not set LED current limit (%d)\n", ret);
return;
}
} else {
/* Select higher current limt */
printk("Restarting sample with higher current limit\n");
current_limit = 0xFF;
ret = is31fl3733_current_limit(led_dev, current_limit);
if (ret) {
printk("Could not set LED current limit (%d)\n", ret);
return;
}
}
}
}