This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new d5eda10cad5 drivers/leds: Add support for KTD2052
d5eda10cad5 is described below

commit d5eda10cad580119efc54b5642824545d3da4d16
Author: Joshua Lange <jla...@2g-eng.com>
AuthorDate: Mon Apr 14 12:56:52 2025 -0500

    drivers/leds: Add support for KTD2052
    
    This commit adds support for the KTD2052 LED driver chip.
    
    Signed-off-by: Tyler Bennett <tbenn...@2g-eng.com>
---
 .../components/drivers/character/leds/index.rst    |   1 +
 .../components/drivers/character/leds/ktd2052.rst  | 116 ++++
 drivers/leds/Kconfig                               |   7 +
 drivers/leds/Make.defs                             |   6 +
 drivers/leds/ktd2052.c                             | 753 +++++++++++++++++++++
 include/nuttx/leds/ktd2052.h                       | 149 ++++
 6 files changed, 1032 insertions(+)

diff --git a/Documentation/components/drivers/character/leds/index.rst 
b/Documentation/components/drivers/character/leds/index.rst
index 1aef9f97958..88887a9052b 100644
--- a/Documentation/components/drivers/character/leds/index.rst
+++ b/Documentation/components/drivers/character/leds/index.rst
@@ -7,3 +7,4 @@ LEDS
 
   userled.rst
   ws2812.rst
+  ktd2052.rst
diff --git a/Documentation/components/drivers/character/leds/ktd2052.rst 
b/Documentation/components/drivers/character/leds/ktd2052.rst
new file mode 100644
index 00000000000..20eae82508f
--- /dev/null
+++ b/Documentation/components/drivers/character/leds/ktd2052.rst
@@ -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.
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 15dcb5f664c..def6776d887 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -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
diff --git a/drivers/leds/Make.defs b/drivers/leds/Make.defs
index 0d4611e2257..7567f1d5e27 100644
--- a/drivers/leds/Make.defs
+++ b/drivers/leds/Make.defs
@@ -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
diff --git a/drivers/leds/ktd2052.c b/drivers/leds/ktd2052.c
new file mode 100644
index 00000000000..4303760e34d
--- /dev/null
+++ b/drivers/leds/ktd2052.c
@@ -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 = &reg_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, &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, &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,
+                           &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, &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 */
diff --git a/include/nuttx/leds/ktd2052.h b/include/nuttx/leds/ktd2052.h
new file mode 100644
index 00000000000..9ab1659dcd0
--- /dev/null
+++ b/include/nuttx/leds/ktd2052.h
@@ -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 */

Reply via email to