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:
parent
85a41ae88a
commit
351cb4bafe
8
samples/drivers/led_is31fl3733/CMakeLists.txt
Normal file
8
samples/drivers/led_is31fl3733/CMakeLists.txt
Normal 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)
|
20
samples/drivers/led_is31fl3733/Kconfig
Normal file
20
samples/drivers/led_is31fl3733/Kconfig
Normal 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.
|
35
samples/drivers/led_is31fl3733/README.rst
Normal file
35
samples/drivers/led_is31fl3733/README.rst
Normal 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)
|
13
samples/drivers/led_is31fl3733/boards/frdm_k22f.overlay
Normal file
13
samples/drivers/led_is31fl3733/boards/frdm_k22f.overlay
Normal 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>;
|
||||
};
|
||||
};
|
4
samples/drivers/led_is31fl3733/prj.conf
Normal file
4
samples/drivers/led_is31fl3733/prj.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2022 Daniel DeGrasse <daniel@degrasse.com>
|
||||
CONFIG_LED=y
|
||||
CONFIG_GPIO=y
|
8
samples/drivers/led_is31fl3733/sample.yaml
Normal file
8
samples/drivers/led_is31fl3733/sample.yaml
Normal 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
|
156
samples/drivers/led_is31fl3733/src/main.c
Normal file
156
samples/drivers/led_is31fl3733/src/main.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue