From a903572ff6496a66821255fbfe35d91cc8396ffb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 23 Feb 2018 10:44:10 -0600 Subject: [PATCH] drivers/lcd: Add and IOCTL command to fade the backlight on and off. --- drivers/lcd/ft80x.c | 129 ++++++++++++++++++++++++++++++++++ include/nuttx/lcd/ft80x.h | 14 ++++ include/nuttx/lcd/lcd_ioctl.h | 2 +- 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/drivers/lcd/ft80x.c b/drivers/lcd/ft80x.c index c42b1ac35c..25f759f948 100644 --- a/drivers/lcd/ft80x.c +++ b/drivers/lcd/ft80x.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -90,10 +91,17 @@ # error No FT80x device configured #endif +#define MIN_FADE_DELAY 10 /* Milliseconds */ +#define MAX_FADE_DELAY 16700 /* Milliseconds */ +#define FADE_STEP_MSEC 10 /* Milliseconds */ + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ +static int ft80x_fade(FAR struct ft80x_dev_s *priv, + FAR const struct ft80x_fade_s *fade); + static void ft80x_notify(FAR struct ft80x_dev_s *priv, enum ft80x_notify_e event, int value); static void ft80x_interrupt_work(FAR void *arg); @@ -144,6 +152,103 @@ static const struct file_operations g_ft80x_fops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: ft80x_fade + * + * Description: + * Change the backlight intensity with a controllable fade. + * + ****************************************************************************/ + +static int ft80x_fade(FAR struct ft80x_dev_s *priv, + FAR const struct ft80x_fade_s *fade) +{ + systime_t start; + systime_t elapsed; + int32_t delay; + int32_t duty; + int16_t endduty; + int16_t delta; + + /* 0% corresponds to the value 0, but 100% corresponds to the value 128 */ + + endduty = (uint16_t)((uint16_t)fade->duty << 7) / 100; + + /* Get the change in duty from the current to the terminal duty. */ + + duty = (int32_t)(ft80x_read_byte(priv, FT80X_REG_PWM_DUTY) & 0x7f); + delta = endduty - (int16_t)duty; + + /* The "smoothness" of the steps will depend on the resolution of the + * system timer. The minimum delay is <= 2 * system_clock_period. + * + * We will try for a FADE_STEP_MSEC delay, but we will try to adapt to + * whatever we get is we are working close the system time resolution. + * For human factors reasons, any delay less than 100 MS or so should + * appear more or less smooth. + * + * The delay calculation should never overflow: + * + * Max delay: 16,700 msec (MAX_FADE_DELAY) + * Min clock period: 1 usec + * Max delay: 16,700,000 ticks + * INT32_MAX 2,147,483,647 + */ + + delay = MSEC2TICK((int32_t)fade->delay); + if (delay <= 0) + { + delay = 1; + } + + start = clock_systimer(); + + do + { + /* Wait for FADE_STEP_MSEC msec (or whatever we get) */ + + (void)nxsig_usleep(FADE_STEP_MSEC * 1000); + + /* Get the elapsed time */ + + elapsed = clock_systimer() - start; + if (elapsed > INT32_MAX || (int32_t)elapsed >= delay) + { + duty = endduty; + } + else + { + /* Interpolate to get the next PWM duty in the fade. This + * calculation should never overflow: + * + * Max delta: 128 + * Max elapsed: 16,700,000 ticks + * Max numerator: 2,137,600,000 + * Min denominator: 1 + * Max duty: 2,137,600,000 + * INT32_MAX 2,147,483,647 + */ + + duty += ((int32_t)delta * (int32_t)elapsed) / delay; + if (duty > 128) + { + duty = 128; + } + else if (duty < 0) + { + duty = 0; + } + } + + /* The set the new backlight PWM duty */ + + ft80x_write_byte(priv, FT80X_REG_PWM_DUTY, (uint8_t)duty); + } + while (duty != endduty); + + return OK; +} + /**************************************************************************** * Name: ft80x_notify * @@ -959,6 +1064,30 @@ static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } break; + /* FT80X_IOC_FADE: + * Description: Change the backlight intensity with a controllable + * fade. + * Argument: A reference to an instance of struct ft80x_fade_s. + * Returns: None. + */ + + case FT80X_IOC_FADE: + { + FAR const struct ft80x_fade_s *fade = + (FAR const struct ft80x_fade_s *)((uintptr_t)arg); + + if (fade == NULL || fade->duty > 100 || + fade->delay < MIN_FADE_DELAY || fade->delay > MAX_FADE_DELAY) + { + ret = -EINVAL; + } + else + { + ret = ft80x_fade(priv, fade); + } + } + break; + /* Unrecognized IOCTL command */ default: diff --git a/include/nuttx/lcd/ft80x.h b/include/nuttx/lcd/ft80x.h index 7ceef99ff5..8d7a9156e7 100644 --- a/include/nuttx/lcd/ft80x.h +++ b/include/nuttx/lcd/ft80x.h @@ -191,6 +191,11 @@ * indicate only the tag value for TOUCH0. * Argument: A reference to an instance of struct ft80x_notify_s. * Returns: None + * + * FT80X_IOC_FADE: + * Description: Change the backlight intensity with a controllable fade. + * Argument: A reference to an instance of struct ft80x_fade_s below. + * Returns: None. */ #define FT80X_IOC_CREATEDL _LCDIOC(FT80X_NIOCTL_BASE + 0) @@ -207,6 +212,7 @@ #define FT80X_IOC_PUTREG32 _LCDIOC(FT80X_NIOCTL_BASE + 11) #define FT80X_IOC_PUTREGS _LCDIOC(FT80X_NIOCTL_BASE + 12) #define FT80X_IOC_EVENTNOTIFY _LCDIOC(FT80X_NIOCTL_BASE + 13) +#define FT80X_IOC_FADE _LCDIOC(FT80X_NIOCTL_BASE + 14) /* FT80x Memory Map *************************************************************************/ @@ -1447,6 +1453,14 @@ struct ft80x_registers_s FAR uint32_t *value; /* A pointer to an array of 32-bit register values */ }; +/* Used with FT80X_IOC_FADE: */ + +struct ft80x_fade_s +{ + uint8_t duty ; /* Terminal backlight duty as a percentage (0-100) */ + uint16_t delay; /* Total number of milliseconds for the fade (10-16700)*/ +}; + /******************************************************************************************** * Public Function Prototypes ********************************************************************************************/ diff --git a/include/nuttx/lcd/lcd_ioctl.h b/include/nuttx/lcd/lcd_ioctl.h index 4c3c056c98..5d43e58227 100644 --- a/include/nuttx/lcd/lcd_ioctl.h +++ b/include/nuttx/lcd/lcd_ioctl.h @@ -50,7 +50,7 @@ /* IOCTL commands set aside for FT80x character driver */ -#define FT80X_NIOCTL_CMDS 14 +#define FT80X_NIOCTL_CMDS 15 #define FT80X_NIOCTL_BASE 0x0001 #endif /* __INCLUDE_NUTTX_INPUT_LCD_IOCTL_H */