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

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

commit 1a0032105d8b8eab2a8f2b1a559d24bfa9e5dc99
Author: raiden00pl <[email protected]>
AuthorDate: Wed Sep 23 11:58:19 2026 +0200

    drivers/ioexpander/sx1509: implement the pin PWM operation
    
    Implement ioe_setpwm for the SX1509 by mapping the duty cycle to the
    LED driver ON intensity of the pin.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 drivers/ioexpander/sx1509.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/drivers/ioexpander/sx1509.c b/drivers/ioexpander/sx1509.c
index a1be7bdd878..e2824c489c3 100644
--- a/drivers/ioexpander/sx1509.c
+++ b/drivers/ioexpander/sx1509.c
@@ -84,6 +84,10 @@ static int sx1509_readpin(FAR struct ioexpander_dev_s *dev, 
uint8_t pin,
              FAR bool *value);
 static int sx1509_readbuf(FAR struct ioexpander_dev_s *dev, uint8_t pin,
              FAR bool *value);
+#ifdef CONFIG_IOEXPANDER_PWM
+static int sx1509_setpwm(FAR struct ioexpander_dev_s *dev, uint8_t pin,
+             uint16_t duty);
+#endif
 #ifdef CONFIG_IOEXPANDER_INT_ENABLE
 static FAR void *sx1509_attach(FAR struct ioexpander_dev_s *dev,
              ioe_pinset_t pinset, ioe_callback_t callback, FAR void *arg);
@@ -146,9 +150,12 @@ static const struct ioexpander_ops_s g_sx1509_ops =
   , sx1509_attach
   , sx1509_detach
 #endif
+#ifdef CONFIG_IOEXPANDER_PWM
+  , sx1509_setpwm
+#endif
 };
 
-#ifdef CONFIG_USERLED_EFFECTS
+#if defined(CONFIG_SX1509_LED_ENABLE) || defined(CONFIG_IOEXPANDER_PWM)
 /* LED driver registers:
  *   TON, ION, OFF, TRISE, TFALL
  */
@@ -664,6 +671,66 @@ static int sx1509_readbuf(FAR struct ioexpander_dev_s 
*dev, uint8_t pin,
   return ret;
 }
 
+#ifdef CONFIG_IOEXPANDER_PWM
+/****************************************************************************
+ * Name: sx1509_setpwm
+ *
+ * Description:
+ *   Set the pin PWM duty cycle.  The pin must be configured as a LED
+ *   driver output; the duty cycle is mapped to the LED driver ON
+ *   intensity. Optional.
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   pin  - The index of the pin to alter in this call
+ *   duty - The duty cycle, where 0 is off and 0xffff is fully on
+ *
+ * Returned Value:
+ *   0 on success, else a negative error code
+ *
+ ****************************************************************************/
+
+static int sx1509_setpwm(FAR struct ioexpander_dev_s *dev, uint8_t pin,
+                         uint16_t duty)
+{
+  FAR struct sx1509_dev_s *priv = (FAR struct sx1509_dev_s *)dev;
+  uint8_t buf[2];
+  int ret;
+
+  if (pin >= SX1509_NR_GPIO_MAX)
+    {
+      return -EINVAL;
+    }
+
+  /* Get exclusive access to the SX1509 */
+
+  ret = nxmutex_lock(&priv->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Set the ON intensity and drive the pin active only for a non-zero
+   * duty cycle.
+   */
+
+  buf[0] = g_sx1509_led_regs[pin][SX1509_LEDREGS_ION];
+  buf[1] = duty >> 8;
+
+  ret = sx1509_write(priv, buf, 2);
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
+  ret = sx1509_setbit(priv, SX1509_REGDATA_A, pin, duty > 0);
+
+errout:
+  nxmutex_unlock(&priv->lock);
+  return ret;
+}
+#endif
+
 #ifdef CONFIG_SX1509_INT_ENABLE
 /****************************************************************************
  * Name: sx1509_attach
@@ -1355,4 +1422,5 @@ int sx1509_leds_initialize(FAR struct ioexpander_dev_s 
*ioe,
 
   return userled_register(devname, &priv->userleds);
 }
+
 #endif

Reply via email to