mirror of
https://github.com/apache/nuttx.git
synced 2025-12-08 10:55:51 +08:00
drivers/leds: Add support for KTD2052
This commit adds support for the KTD2052 LED driver chip. Signed-off-by: Tyler Bennett <tbennett@2g-eng.com>
This commit is contained in:
committed by
Alan C. Assis
parent
e5b138dee0
commit
d5eda10cad
@@ -7,3 +7,4 @@ LEDS
|
||||
|
||||
userled.rst
|
||||
ws2812.rst
|
||||
ktd2052.rst
|
||||
|
||||
116
Documentation/components/drivers/character/leds/ktd2052.rst
Normal file
116
Documentation/components/drivers/character/leds/ktd2052.rst
Normal file
@@ -0,0 +1,116 @@
|
||||
=======
|
||||
KTD2052
|
||||
=======
|
||||
|
||||
This is a driver for the Kinetic Technologies KTD2052, a 4-module (12-channel)
|
||||
RGB LED driver with an I2C interface. This driver exposes the KTD2052's
|
||||
functionality as a standard NuttX character device.
|
||||
|
||||
Driver Configuration
|
||||
====================
|
||||
|
||||
This driver depends on I2C being enabled and configured for your board.
|
||||
To use the driver, enable the following option in menuconfig:
|
||||
|
||||
- ``Device Drivers -> LED Support -> KTD2052 I2C LED Driver``
|
||||
(``CONFIG_KTD2052``)
|
||||
|
||||
Driver Usage
|
||||
============
|
||||
|
||||
The driver is registered as a character device, typically at a path like
|
||||
``/dev/leds0``.
|
||||
|
||||
Initialization
|
||||
--------------
|
||||
|
||||
To use the driver, board-specific logic must call ``ktd2052_register``
|
||||
during the board initialization sequence. This function takes the device path,
|
||||
an I2C master instance, the I2C address of the device, and the I2C frequency.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <nuttx/leds/ktd2052.h>
|
||||
|
||||
/* In your board's initialization logic */
|
||||
FAR struct i2c_master_s *i2c; /* I2C bus instance */
|
||||
/* ... */
|
||||
ktd2052_register("/dev/leds0", i2c, 0x74, 400000);
|
||||
|
||||
|
||||
Application Interface
|
||||
---------------------
|
||||
|
||||
An application can interact with the device by opening the device path and
|
||||
using standard ``read()``, ``write()``, and ``ioctl()`` calls. The device will
|
||||
automatically be taken out of shutdown mode as soon as it is opened.
|
||||
|
||||
**write()**
|
||||
|
||||
The ``write()`` call provides a simple way to set the raw current
|
||||
values for one or more connected RGB modules. The buffer should contain a
|
||||
sequence of Red, Green, and Blue current values for each module, starting with
|
||||
module 1. The device's output current is linear between values of 0 (no current)
|
||||
and 192 (full scale current). Setting a value above 192 will result in full
|
||||
scale current output. Full scale current is either 24mA in normal mode or 1.5mA
|
||||
in night mode. Writes to the device using the ``write()`` call will always start
|
||||
at module 1. The entire string can be updated by repeatedly calling ``write()``
|
||||
without needing to first seek back to 0. Partial writes are supported.
|
||||
|
||||
- **Buffer Format**: ``[R1, G1, B1, R2, G2, B2, R3, G3, B3, R4, G4, B4]``
|
||||
- **Buffer Length**: 1 to 12 bytes.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Example: Set module 1 to red and module 2 to blue */
|
||||
uint8_t colors[6] = { 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0 };
|
||||
int fd = open("/dev/leds0", O_WRONLY);
|
||||
write(fd, colors, sizeof(colors));
|
||||
close(fd);
|
||||
|
||||
**read()**
|
||||
|
||||
The ``read()`` call retrieves status information from the device.
|
||||
|
||||
- Reading 1 byte returns the contents of the MONITOR Register.
|
||||
- Reading 2 bytes returns the MONITOR Register followed by the CONTROL Register.
|
||||
|
||||
The MONITOR register bits are defined in ``nuttx/leds/ktd2052.h``.
|
||||
|
||||
**ioctl()**
|
||||
|
||||
For more advanced control, the driver implements several ``ioctl`` commands,
|
||||
defined in ``nuttx/leds/ktd2052.h``.
|
||||
|
||||
- ``KTDIOSETRGB``
|
||||
Set the color for a single RGB module.
|
||||
|
||||
- **Argument**: A pointer to a ``uint8_t[4]`` array:
|
||||
``{module number [1-4], r, g, b}``.
|
||||
|
||||
- ``KTDIOSETMODE``
|
||||
Configure the operating mode of the device. See the CONTROL register in the
|
||||
device datasheet for additional information on available modes.
|
||||
|
||||
- **Argument**: A pointer to a ``struct ktd2052_mode_s``.
|
||||
|
||||
- ``KTDIOSETPATTERN``
|
||||
Configure the hardware pattern generator. See the device datasheet for
|
||||
additional information on using the hardware pattern generator.
|
||||
|
||||
- **Argument**: A pointer to a ``struct ktd2052_pattern_s``.
|
||||
|
||||
- ``KTDIOSETSLOTS``
|
||||
Configure which RGB modules are active in each pattern slot.
|
||||
|
||||
- **Argument**: A pointer to a ``struct ktd2052_slots_s``.
|
||||
|
||||
- ``KTDIOGETMONITOR``
|
||||
Read the MONITOR register.
|
||||
|
||||
- **Argument**: A pointer to a ``uint8_t`` to store the result.
|
||||
|
||||
- ``KTDIOSETWDOG``
|
||||
Feed the pattern generator watchdog timer.
|
||||
|
||||
- **Argument**: A ``uint8_t`` value for the watchdog cycle count to set.
|
||||
@@ -57,6 +57,13 @@ config LEDS_APA102
|
||||
---help---
|
||||
Enable support for the APA102 LED Strip driver.
|
||||
|
||||
config KTD2052
|
||||
bool "KTD2052 I2C LED Driver"
|
||||
default n
|
||||
select I2C
|
||||
---help---
|
||||
Enable support for the KTD2052 LED driver
|
||||
|
||||
config LEDS_MAX7219
|
||||
bool "MAX7219 Numeric Display"
|
||||
default n
|
||||
|
||||
@@ -37,6 +37,12 @@ ifeq ($(CONFIG_LEDS_APA102),y)
|
||||
LEDVPATH = :leds
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_KTD2052),y)
|
||||
CSRCS += ktd2052.c
|
||||
LEDDEPATH = --dep-path leds
|
||||
LEDVPATH = :leds
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LEDS_MAX7219),y)
|
||||
CSRCS += max7219.c
|
||||
LEDDEPATH = --dep-path leds
|
||||
|
||||
753
drivers/leds/ktd2052.c
Normal file
753
drivers/leds/ktd2052.c
Normal file
@@ -0,0 +1,753 @@
|
||||
/****************************************************************************
|
||||
* drivers/leds/ktd2052.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/leds/ktd2052.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_KTD2052)
|
||||
|
||||
/* Register Addresses */
|
||||
#define KTD2052_ID_REG 0x00
|
||||
#define KTD2052_MONITOR_REG 0x01
|
||||
#define KTD2052_CONTROL_REG 0x02
|
||||
#define KTD2052_IRED1_REG 0x03
|
||||
#define KTD2052_IGRN1_REG 0x04
|
||||
#define KTD2052_IBLU1_REG 0x05
|
||||
#define KTD2052_IRED2_REG 0x06
|
||||
#define KTD2052_IGRN2_REG 0x07
|
||||
#define KTD2052_IBLU2_REG 0x08
|
||||
#define KTD2052_IRED3_REG 0x09
|
||||
#define KTD2052_IGRN3_REG 0x0a
|
||||
#define KTD2052_IBLU3_REG 0x0b
|
||||
#define KTD2052_IRED4_REG 0x0c
|
||||
#define KTD2052_IGRN4_REG 0x0d
|
||||
#define KTD2052_IBLU4_REG 0x0e
|
||||
#define KTD2052_PG_CNTL_REG 0x0f
|
||||
#define KTD2052_PG_FADE_REG 0x10
|
||||
#define KTD2052_PG_RGB1_REG 0x11
|
||||
#define KTD2052_PG_RGB2_REG 0x12
|
||||
#define KTD2052_PG_RGB3_REG 0x13
|
||||
#define KTD2052_PG_RGB4_REG 0x14
|
||||
#define KTD2052_PG_WD_REG 0x15
|
||||
|
||||
/* Control Register Definitions */
|
||||
#define CONTROL_BE_EN (0x01 << 5)
|
||||
|
||||
/* Pattern Generator Control Register Bits */
|
||||
#define PG_MODE_OFF (0x00 << 6)
|
||||
#define PG_MODE_4SLOTS (0x01 << 6)
|
||||
#define PG_MODE_6SLOTS (0x02 << 6)
|
||||
#define PG_MODE_8SLOTS (0x03 << 6)
|
||||
|
||||
/* Private Data Structure */
|
||||
|
||||
struct ktd2052_dev_s
|
||||
{
|
||||
FAR struct i2c_master_s *i2c;
|
||||
uint8_t addr;
|
||||
uint8_t frequency;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_write_regs(FAR struct ktd2052_dev_s *priv,
|
||||
uint8_t reg_addr,
|
||||
const uint8_t *reg_vals,
|
||||
uint8_t count);
|
||||
static int ktd2052_read_reg(FAR struct ktd2052_dev_s *priv, uint8_t reg_addr,
|
||||
uint8_t *reg_val);
|
||||
static int ktd2052_write_watchdog(FAR struct ktd2052_dev_s *priv,
|
||||
uint8_t value);
|
||||
|
||||
static int ktd2052_open(FAR struct file *filep);
|
||||
static int ktd2052_close(FAR struct file *filep);
|
||||
static ssize_t ktd2052_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t ktd2052_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
static int ktd2052_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Driver Operations Structure
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_ktd2052_fops =
|
||||
{
|
||||
ktd2052_open, /* open */
|
||||
ktd2052_close, /* close */
|
||||
ktd2052_read, /* read */
|
||||
ktd2052_write, /* write */
|
||||
NULL, /* seek */
|
||||
ktd2052_ioctl, /* ioctl */
|
||||
NULL /* poll */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_write_regs
|
||||
*
|
||||
* Description:
|
||||
* Write one or more registers to device
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* reg_addr - Starting device register address to write
|
||||
* reg_val - Pointer to register value(s)
|
||||
* count - Number of registers to write
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_write_regs(FAR struct ktd2052_dev_s *priv,
|
||||
uint8_t reg_addr,
|
||||
const uint8_t *reg_vals,
|
||||
uint8_t count)
|
||||
{
|
||||
struct i2c_msg_s msg[1];
|
||||
uint8_t buf[count + 1];
|
||||
int ret;
|
||||
|
||||
buf[0] = reg_addr;
|
||||
memcpy(&buf[1], reg_vals, count);
|
||||
|
||||
msg[0].frequency = priv->frequency;
|
||||
msg[0].addr = priv->addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].buffer = buf;
|
||||
msg[0].length = count + 1;
|
||||
|
||||
ret = I2C_TRANSFER(priv->i2c, msg, 1);
|
||||
return ret < 0 ? ret : OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_read_reg
|
||||
*
|
||||
* Description:
|
||||
* Read a single register from device
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* reg_addr - Device register address to read
|
||||
* reg_val - Pointer to location where register value will be stored
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_read_reg(FAR struct ktd2052_dev_s *priv, uint8_t reg_addr,
|
||||
uint8_t *reg_val)
|
||||
{
|
||||
struct i2c_msg_s msg[2];
|
||||
int ret;
|
||||
|
||||
msg[0].frequency = priv->frequency;
|
||||
msg[0].addr = priv->addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].buffer = ®_addr;
|
||||
msg[0].length = 1;
|
||||
|
||||
msg[1].frequency = priv->frequency;
|
||||
msg[1].addr = priv->addr;
|
||||
msg[1].flags = I2C_M_READ;
|
||||
msg[1].buffer = reg_val;
|
||||
msg[1].length = 1;
|
||||
|
||||
ret = I2C_TRANSFER(priv->i2c, msg, 2);
|
||||
return ret < 0 ? ret : OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_write_watchdog
|
||||
*
|
||||
* Description:
|
||||
* Set watchdog timer value
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* value - watchdog value in number of cycles
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_write_watchdog(FAR struct ktd2052_dev_s *priv,
|
||||
uint8_t value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Watchdog register requires two writes */
|
||||
|
||||
ret = ktd2052_write_regs(priv, KTD2052_PG_WD_REG, &value, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ktd2052_write_regs(priv, KTD2052_PG_WD_REG, &value, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the KTD2052 device
|
||||
*
|
||||
* Input Parameters:
|
||||
* i2c - An instance of the I2C interface to communicate with KTD2052
|
||||
* addr - The I2C address of the KTD2052 (default: 0x74)
|
||||
* freq - The I2C frequency to use for the KTD2052
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR
|
||||
struct ktd2052_dev_s *ktd2052_initialize(FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr, uint32_t freq)
|
||||
{
|
||||
FAR struct ktd2052_dev_s *priv;
|
||||
uint8_t reg_val;
|
||||
int ret;
|
||||
|
||||
/* Allocate device structure */
|
||||
|
||||
priv = (FAR struct ktd2052_dev_s *)kmm_malloc(
|
||||
sizeof(struct ktd2052_dev_s));
|
||||
if (!priv)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize structure */
|
||||
|
||||
priv->i2c = i2c;
|
||||
priv->addr = addr;
|
||||
priv->frequency = freq;
|
||||
|
||||
/* Verify device by reading ID register */
|
||||
|
||||
ret = ktd2052_read_reg(priv, KTD2052_ID_REG, ®_val);
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Verify vendor ID (bits 7:5 should be 101) */
|
||||
|
||||
if ((reg_val & 0xe0) != 0xa0)
|
||||
{
|
||||
kmm_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_set_rgb
|
||||
*
|
||||
* Description:
|
||||
* Set RGB LED color and brightness for a specific module
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* module - RGB module number (1-4)
|
||||
* rgb - array of uint8_t; red, green, and blue LED current
|
||||
* (0-192 for 0-24mA)
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_set_rgb(FAR struct ktd2052_dev_s *priv, uint8_t module,
|
||||
const uint8_t *rgb)
|
||||
{
|
||||
int ret;
|
||||
uint8_t base_reg;
|
||||
|
||||
if (module < 1 || module > 4)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Calculate base register for the module */
|
||||
|
||||
base_reg = KTD2052_IRED1_REG + ((module - 1) * 3);
|
||||
|
||||
/* Write RGB values */
|
||||
|
||||
ret = ktd2052_write_regs(priv, base_reg, rgb, 3);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_set_mode
|
||||
*
|
||||
* Description:
|
||||
* Set the operating mode of the device
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* mode - Operating mode (0=off, 1=night mode, 2=normal mode)
|
||||
* bright_extend - Enable BrightExtend feature
|
||||
* temp_limit - Temperature limit (0=135C, 1=120C, 2=105C, 3=90C)
|
||||
* fade_rate - Fade rate (0-7, slower with increasing value)
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_set_mode(FAR struct ktd2052_dev_s *priv, uint8_t mode,
|
||||
bool bright_extend, uint8_t temp_limit,
|
||||
uint8_t fade_rate)
|
||||
{
|
||||
uint8_t reg_val = 0;
|
||||
|
||||
/* Validate parameters */
|
||||
|
||||
if (mode > 2 || temp_limit > 3 || fade_rate > 7)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Build control register value */
|
||||
|
||||
reg_val = (mode << 6) |
|
||||
(bright_extend ? CONTROL_BE_EN : 0) |
|
||||
(temp_limit << 3) |
|
||||
fade_rate;
|
||||
|
||||
return ktd2052_write_regs(priv, KTD2052_CONTROL_REG, ®_val, 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_setup_pattern
|
||||
*
|
||||
* Description:
|
||||
* Configure the pattern generator
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* slots - Number of pattern slots (4, 6, or 8)
|
||||
* duration - Duration for each slot (0-7, longer with increasing value)
|
||||
* fade_rate1 - Secondary fade rate (0-7)
|
||||
* watchdog - Number of pattern cycles (0-255, 255=infinite)
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_setup_pattern(FAR struct ktd2052_dev_s *priv,
|
||||
uint8_t slots,
|
||||
uint8_t duration,
|
||||
uint8_t fade_rate1,
|
||||
uint8_t watchdog)
|
||||
{
|
||||
uint8_t mode;
|
||||
uint8_t reg_val;
|
||||
int ret;
|
||||
|
||||
/* Convert slots to mode bits */
|
||||
|
||||
switch (slots)
|
||||
{
|
||||
case 4:
|
||||
mode = PG_MODE_4SLOTS;
|
||||
break;
|
||||
case 6:
|
||||
mode = PG_MODE_6SLOTS;
|
||||
break;
|
||||
case 8:
|
||||
mode = PG_MODE_8SLOTS;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Validate other parameters */
|
||||
|
||||
if (duration > 7 || fade_rate1 > 7)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg_val = mode | (duration << 3) | fade_rate1;
|
||||
|
||||
/* Configure pattern generator control register */
|
||||
|
||||
ret = ktd2052_write_regs(priv, KTD2052_PG_CNTL_REG,
|
||||
®_val, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set watchdog value */
|
||||
|
||||
return ktd2052_write_watchdog(priv, watchdog);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_set_pattern_slots
|
||||
*
|
||||
* Description:
|
||||
* Configure which RGB modules are active in each pattern slot
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Driver instance
|
||||
* module - RGB module number (1-4)
|
||||
* slots - Bit pattern for active slots (LSB = slot 0)
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_set_pattern_slots(FAR struct ktd2052_dev_s *priv,
|
||||
uint8_t module,
|
||||
uint8_t slots)
|
||||
{
|
||||
if (module < 1 || module > 4)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ktd2052_write_regs(priv,
|
||||
KTD2052_PG_RGB1_REG + (module - 1),
|
||||
&slots, 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_open
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ktd2052_dev_s *priv = inode->i_private;
|
||||
|
||||
/* Verify the device still exists (I2C bus check) */
|
||||
|
||||
uint8_t reg_val;
|
||||
int ret = ktd2052_read_reg(priv, KTD2052_ID_REG, ®_val);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set default device configuration */
|
||||
|
||||
ret = ktd2052_set_mode(priv, KTD2052_MODE_NORMAL, true,
|
||||
KTD2052_TEMP_LIMIT_90, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_close
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_close(FAR struct file *filep)
|
||||
{
|
||||
/* Nothing to do
|
||||
* Revisit: should device be put into shutdown mode here?
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_read
|
||||
*
|
||||
* Description:
|
||||
* Read will return the device's status monitor register, as well as the
|
||||
* control register if sufficient buffer space is provided.
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t ktd2052_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ktd2052_dev_s *priv = inode->i_private;
|
||||
ssize_t nread = 0;
|
||||
int ret;
|
||||
|
||||
if (buflen >= 1)
|
||||
{
|
||||
/* Read status register */
|
||||
|
||||
ret = ktd2052_read_reg(priv, KTD2052_MONITOR_REG,
|
||||
(uint8_t *)&buffer[0]);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
nread += 1;
|
||||
if (buflen >= 2)
|
||||
{
|
||||
/* Read control register */
|
||||
|
||||
ret = ktd2052_read_reg(priv, KTD2052_CONTROL_REG,
|
||||
(uint8_t *)&buffer[1]);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
nread += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_write
|
||||
*
|
||||
* Description:
|
||||
* Write will write directly to the RGB values for LED modules 1-4. Partial
|
||||
* writes are allowed. It expects 1-12 bytes in the format:
|
||||
* [red] [green] [blue] [red] [green] [blue] etc
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t ktd2052_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ktd2052_dev_s *priv = inode->i_private;
|
||||
int ret;
|
||||
|
||||
if (buflen <= 0 || buflen > 12)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set the RGB values */
|
||||
|
||||
ret = ktd2052_write_regs(priv, KTD2052_IRED1_REG,
|
||||
(const uint8_t *)&buffer[0], buflen);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return buflen;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
static int ktd2052_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ktd2052_dev_s *priv = inode->i_private;
|
||||
int ret = OK;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case KTDIOSETRGB:
|
||||
{
|
||||
/* Set RGB value of a single module. Expects pointer to 4-byte
|
||||
* uint8_t array (module number and r, g, b values)
|
||||
*/
|
||||
|
||||
FAR uint8_t *mrgb = (FAR uint8_t *)arg;
|
||||
if (mrgb == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ktd2052_set_rgb(priv, mrgb[0], &mrgb[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case KTDIOSETMODE:
|
||||
{
|
||||
/* Set operating mode */
|
||||
|
||||
FAR struct ktd2052_mode_s *mode = (FAR struct ktd2052_mode_s *)arg;
|
||||
if (mode == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ktd2052_set_mode(priv, mode->mode, mode->bright_extend,
|
||||
mode->temp_limit, mode->fade_rate);
|
||||
}
|
||||
break;
|
||||
|
||||
case KTDIOSETPATTERN:
|
||||
{
|
||||
/* Set pattern configuration */
|
||||
|
||||
FAR struct ktd2052_pattern_s *pattern =
|
||||
(FAR struct ktd2052_pattern_s *)arg;
|
||||
if (pattern == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ktd2052_setup_pattern(priv, pattern->slots,
|
||||
pattern->duration,
|
||||
pattern->fade_rate1,
|
||||
pattern->watchdog);
|
||||
}
|
||||
break;
|
||||
|
||||
case KTDIOSETSLOTS:
|
||||
{
|
||||
/* Set pattern slots for a module */
|
||||
|
||||
FAR struct ktd2052_slots_s *slots =
|
||||
(FAR struct ktd2052_slots_s *)arg;
|
||||
if (slots == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ktd2052_set_pattern_slots(priv, slots->module, slots->slots);
|
||||
}
|
||||
break;
|
||||
|
||||
case KTDIOGETMONITOR:
|
||||
{
|
||||
/* Get monitor register status */
|
||||
|
||||
FAR uint8_t *status = (FAR uint8_t *)arg;
|
||||
if (status == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ktd2052_read_reg(priv, KTD2052_MONITOR_REG, status);
|
||||
}
|
||||
break;
|
||||
|
||||
case KTDIOSETWDOG:
|
||||
{
|
||||
/* Update watchdog register */
|
||||
|
||||
uint8_t wd = (uint8_t)arg;
|
||||
ret = ktd2052_write_watchdog(priv, wd);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_register
|
||||
*
|
||||
* Description:
|
||||
* Register the KTD2052 character device as 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the driver to register. E.g., "/dev/leds0"
|
||||
* i2c - An instance of the I2C interface to communicate with KTD2052
|
||||
* addr - The I2C address of the KTD2052
|
||||
* freq - The I2C frequency to use for the KTD2052
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ktd2052_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr, uint32_t freq)
|
||||
{
|
||||
FAR struct ktd2052_dev_s *priv;
|
||||
int ret;
|
||||
|
||||
/* Initialize the device structure */
|
||||
|
||||
priv = ktd2052_initialize(i2c, addr, freq);
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Register the character driver */
|
||||
|
||||
ret = register_driver(devpath, &g_ktd2052_fops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_I2C && CONFIG_KTD2052 */
|
||||
149
include/nuttx/leds/ktd2052.h
Normal file
149
include/nuttx/leds/ktd2052.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/leds/ktd2052.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_LEDS_KTD2052_H
|
||||
#define __INCLUDE_NUTTX_LEDS_KTD2052_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Set RGB value for a single module */
|
||||
#define KTDIOSETRGB _ULEDIOC(0)
|
||||
|
||||
/* Set operating mode */
|
||||
#define KTDIOSETMODE _ULEDIOC(1)
|
||||
|
||||
/* Set pattern configuration */
|
||||
#define KTDIOSETPATTERN _ULEDIOC(2)
|
||||
|
||||
/* Set pattern slots for a module */
|
||||
#define KTDIOSETSLOTS _ULEDIOC(3)
|
||||
|
||||
/* Get monitor register status */
|
||||
#define KTDIOGETMONITOR _ULEDIOC(4)
|
||||
|
||||
/* Set watchdog value */
|
||||
#define KTDIOSETWDOG _ULEDIOC(5)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#define KTD2052_MODE_SHUTDOWN 0
|
||||
#define KTD2052_MODE_NIGHT 1
|
||||
#define KTD2052_MODE_NORMAL 2
|
||||
|
||||
#define KTD2052_TEMP_LIMIT_135 0
|
||||
#define KTD2052_TEMP_LIMIT_120 1
|
||||
#define KTD2052_TEMP_LIMIT_105 2
|
||||
#define KTD2052_TEMP_LIMIT_90 3
|
||||
|
||||
#define KTD2052_FADE_RATE_32MS 0
|
||||
#define KTD2052_FADE_RATE_63MS 1
|
||||
#define KTD2052_FADE_RATE_125MS 2
|
||||
#define KTD2052_FADE_RATE_250MS 3
|
||||
#define KTD2052_FADE_RATE_500MS 4
|
||||
#define KTD2052_FADE_RATE_1000MS 5
|
||||
#define KTD2052_FADE_RATE_2000MS 6
|
||||
#define KTD2052_FADE_RATE_4000MS 7
|
||||
|
||||
/* MONITOR status bits */
|
||||
|
||||
#define KTD2052_MONITOR_UV_OT_STAT 0x01 /* Under voltage/over temperature */
|
||||
#define KTD2052_MONITOR_COOL_STAT 0x02 /* CoolExtend is active */
|
||||
#define KTD2052_MONITOR_BE_STAT 0x04 /* BrightExtend is active */
|
||||
#define KTD2052_MONITOR_SC_STAT 0x08 /* Short circuit detected */
|
||||
|
||||
/* Structure for setting operating mode */
|
||||
|
||||
struct ktd2052_mode_s
|
||||
{
|
||||
uint8_t mode; /* 0=off, 1=night mode, 2=normal mode */
|
||||
bool bright_extend; /* Enable BrightExtend feature */
|
||||
uint8_t temp_limit; /* Temperature limit (0=135C to 3=90C) */
|
||||
uint8_t fade_rate; /* Fade rate (0-7) */
|
||||
};
|
||||
|
||||
/* Structure for configuring pattern generator */
|
||||
|
||||
struct ktd2052_pattern_s
|
||||
{
|
||||
uint8_t slots; /* Number of pattern slots (4, 6, or 8) */
|
||||
uint8_t duration; /* Duration for each slot (0-7) */
|
||||
uint8_t fade_rate1; /* Secondary fade rate (0-7) */
|
||||
uint8_t watchdog; /* Number of pattern cycles (0-255) */
|
||||
};
|
||||
|
||||
/* Structure for setting pattern slots */
|
||||
|
||||
struct ktd2052_slots_s
|
||||
{
|
||||
uint8_t module; /* RGB module number (1-4) */
|
||||
uint8_t slots; /* Bit pattern for active slots */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ktd2052_register
|
||||
*
|
||||
* Description:
|
||||
* Register the KTD2052 character device as 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the driver to register. E.g., "/dev/leds0"
|
||||
* i2c - An instance of the I2C interface to communicate with KTD2052
|
||||
* addr - The I2C address of the KTD2052
|
||||
* freq - The I2C frequency to use for the KTD2052
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ktd2052_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr, uint32_t freq);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_LEDS_KTD2052_H */
|
||||
Reference in New Issue
Block a user