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 <raiden00@railab.me>
This commit is contained in:
raiden00pl 2026-09-23 11:58:19 +02:00 • committed by Xiang Xiao
parent c31b87ee1e
commit 1a0032105d

View file

@ -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