Squashed commit of the following:

drivers/lcd:  Rename ft80x_base.c to just ft80x.c.  Add logic to notify FT80X clients of events via signals.
    drivers/lcd:  Trivial updates to naming.  Add some new definitions.
This commit is contained in:
Gregory Nutt 2018-02-17 18:30:24 -06:00
parent 758e94f7a7
commit eb3663721e
4 changed files with 228 additions and 24 deletions

View File

@ -44,7 +44,7 @@ endif
# Include support for Graphics LCD drivers
ifeq ($(CONFIG_LCD_FT80X),y)
CSRCS += ft80x_base.c
CSRCS += ft80x.c
ifeq ($(CONFIG_LCD_FT80X_SPI),y)
CSRCS += ft80x_spi.c
else ifeq ($(CONFIG_LCD_FT80X_I2C),y)

View File

@ -1,5 +1,5 @@
/**************************************************************************************
* drivers/lcd/ft80x_base.c
* drivers/lcd/ft80x.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -53,12 +53,13 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/semaphore.h>
#include <nuttx/signal.h>
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/fs/fs.h>
@ -91,6 +92,8 @@
* Private Function Prototypes
****************************************************************************/
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);
static int ft80x_interrupt(int irq, FAR void *context, FAR void *arg);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
@ -139,6 +142,39 @@ static const struct file_operations g_ft80x_fops =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_notify
*
* Description:
* Notify any registered client of the FT80x event
*
****************************************************************************/
static void ft80x_notify(FAR struct ft80x_dev_s *priv,
enum ft80x_notify_e event, int arg)
{
FAR struct ft80x_eventinfo_s *info = &priv->notify[event];
#ifdef CONFIG_CAN_PASS_STRUCTS
union sigval value;
#endif
/* Are notifications enabled for this event? */
if (info->enable)
{
DEBUGASSERT(info->signo > 0 && GOOD_SIGNAL(info->signo) && info->pid > 0);
/* Yes.. Signal the client */
#ifdef CONFIG_CAN_PASS_STRUCTS
value.sival_int = arg;
(void)nxsig_queue(info->pid, info->signo, value);
#else
(void)nxsig_queue(info->pid, info->signo, (FAR void *)arg);
#endif
}
}
/****************************************************************************
* Name: ft80x_interrupt_work
*
@ -151,9 +187,20 @@ static void ft80x_interrupt_work(FAR void *arg)
{
FAR struct ft80x_dev_s *priv = (FAR struct ft80x_dev_s *)arg;
uint32_t intflags;
uint32_t regval;
int ret;
DEBUGASSERT(priv != NULL);
/* Get exclusive access to the device structures */
do
{
ret = nxsem_wait(&priv->exclsem);
DEBUGASSERT(ret == OK || ret == -EINTR);
}
while (ret < 0);
/* Get the set of pending interrupts. Note that simply reading this
* register is sufficient to clear all pending interrupts.
*/
@ -171,6 +218,7 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Display swap occurred */
lcdinfo("Display swap occurred\n");
ft80x_notify(priv, FT80X_NOTIFY_SWAP, 0);
}
if ((intflags & FT80X_INT_TOUCH) != 0)
@ -178,6 +226,7 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Touch-screen touch detected */
lcdinfo("Touch-screen touch detected\n");
ft80x_notify(priv, FT80X_NOTIFY_TOUCH, 0);
}
if ((intflags & FT80X_INT_TAG) != 0)
@ -185,6 +234,12 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Touch-screen tag value change */
lcdinfo("Touch-screen tag value change\n");
#ifdef CONFIG_LCD_FT800
regval = ft80x_read_word(priv, FT80X_REG_TOUCH_TAG);
#else
regval = ft80x_read_word(priv, FT80X_REG_CTOUCH_TAG);
#endif
ft80x_notify(priv, FT80X_NOTIFY_TAG, (int)(regval & TOUCH_TAG_MASK));
}
if ((intflags & FT80X_INT_SOUND) != 0)
@ -192,6 +247,7 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Sound effect ended */
lcdinfo(" Sound effect ended\n");
ft80x_notify(priv, FT80X_NOTIFY_SOUND, 0);
}
if ((intflags & FT80X_INT_PLAYBACK) != 0)
@ -199,6 +255,7 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Audio playback ended */
lcdinfo("Audio playback ended\n");
ft80x_notify(priv, FT80X_NOTIFY_PLAYBACK, 0);
}
if ((intflags & FT80X_INT_CMDEMPTY) != 0)
@ -206,6 +263,7 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Command FIFO empty */
lcdinfo("Command FIFO empty\n");
ft80x_notify(priv, FT80X_NOTIFY_CMDEMPTY, 0);
}
if ((intflags & FT80X_INT_CMDFLAG) != 0)
@ -213,6 +271,7 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Command FIFO flag */
lcdinfo("Command FIFO flag\n");
ft80x_notify(priv, FT80X_NOTIFY_CMDFLAG, 0);
}
if ((intflags & FT80X_INT_CONVCOMPLETE) != 0)
@ -220,12 +279,14 @@ static void ft80x_interrupt_work(FAR void *arg)
/* Touch-screen conversions completed */
lcdinfo(" Touch-screen conversions completed\n");
ft80x_notify(priv, FT80X_NOTIFY_CONVCOMPLETE, 0);
}
/* Re-enable interrupts */
DEBUGASSERT(priv->lower != NULL && priv->lower->enable != NULL);
priv->lower->enable(priv->lower, true);
nxsem_post(&priv->exclsem);
}
/****************************************************************************
@ -247,8 +308,9 @@ static int ft80x_interrupt(int irq, FAR void *context, FAR void *arg)
work_queue(HPWORK, &priv->intwork, ft80x_interrupt_work, priv, 0);
/* Disable further interrupts for the GPIO interrupt source.
* REVISIT: This assumes that interrupts will pend until re-enabled.
* In certain implementations, this can cause a loss of interrupts.
* REVISIT: This assumes that GPIO interrupts will pend until re-enabled.
* In certain implementations, that assumption is not true and could cause
* a loss of interrupts.
*/
DEBUGASSERT(priv->lower != NULL && priv->lower->enable != NULL);
@ -522,18 +584,18 @@ static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* FALLTHROUGH */
/* FT80X_IOC_APPENDDL:
* Description: Write additional display list entries to the FT80x
* display list memory at the current display list offset.
* This IOCTL command permits display lists to be completed
* incrementally, starting with FT80X_IOC_CREATEDL and
* finishing the display list using FT80XIO_APPENDDL.
* Argument: A reference to a display list structure instance. See
* struct ft80x_displaylist_s.
* Returns: None
*/
/* FT80X_IOC_APPENDDL:
* Description: Write additional display list entries to the FT80x
* display list memory at the current display list offset.
* This IOCTL command permits display lists to be completed
* incrementally, starting with FT80X_IOC_CREATEDL and
* finishing the display list using FT80XIO_APPENDDL.
* Argument: A reference to a display list structure instance. See
* struct ft80x_displaylist_s.
* Returns: None
*/
case FT80X_IOC_APPENDDL:
case FT80X_IOC_APPENDDL:
{
FAR struct ft80x_displaylist_s *dl =
(FAR struct ft80x_displaylist_s *)((uintptr_t)arg);
@ -617,6 +679,72 @@ static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
/* FT80X_IOC_EVENTNOTIFY:
* Description: Setup to receive a signal when an event occurs.
* Argument: A reference to an instance of struct ft80x_notify_s.
* Returns: None
*/
case FT80X_IOC_EVENTNOTIFY:
{
FAR struct ft80x_notify_s *notify =
(FAR struct ft80x_notify_s *)((uintptr_t)arg);
if (notify == NULL || !GOOD_SIGNO(notify->signo) || notify->pid < 0 ||
(unsigned int)notify->event >= FT80X_INT_NEVENTS)
{
ret = -EINVAL;
}
else
{
FAR struct ft80x_eventinfo_s *info = &priv->notify[notify->event];
uint32_t regval;
/* Are we enabling or disabling */
if (notify->enable)
{
/* Make sure that arguments are valid for the enable */
if (notify->signo == 0 || notify->pid == 0)
{
ret = -EINVAL;
}
else
{
/* Setup the new notification information */
info->signo = notify->signo;
info->pid = notify->pid;
info->enable = true;
/* Enable interrupts associated with the event */
regval = ft80x_read_word(priv, FT80X_REG_INT_MASK);
regval |= (1 << notify->event);
ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
ret = OK;
}
}
else
{
/* Disable the notification */
info->signo = 0;
info->pid = 0;
info->enable = false;
/* Disable interrupts associated with the event */
regval = ft80x_read_word(priv, FT80X_REG_INT_MASK);
regval &= ~(1 << notify->event);
ft80x_write_word(priv, FT80X_REG_INT_MASK, regval);
ret = OK;
}
}
}
break;
/* Unrecognized IOCTL command */
default:
@ -968,7 +1096,7 @@ int ft80x_register(FAR struct i2c_master_s *i2c,
*/
ft80x_write_word(priv, FT80X_REG_INT_MASK, 0);
ft80x_write_word(priv, FT80X_REG_INT_EN, 1);
ft80x_write_word(priv, FT80X_REG_INT_EN, FT80X_INT_ENABLE);
lower->enable(lower, true);
/* Register the FT80x character driver */
@ -983,7 +1111,7 @@ int ft80x_register(FAR struct i2c_master_s *i2c,
errout_with_interrupts:
lower->enable(lower, false);
ft80x_write_word(priv, FT80X_REG_INT_EN, 0);
ft80x_write_word(priv, FT80X_REG_INT_EN, FT80X_INT_DISABLE);
lower->attach(lower, NULL, NULL);
errout_with_sem:

View File

@ -237,7 +237,12 @@
/* FT80x Register Bit Definitions **********************************************************/
/* FT80X_REG_ID */
#define ID_MASK 0xff /* Bits 0-7: Register ID */
/* FT80X_REG_DLSWAP */
#define DLSWAP_LINE 1 /* Bits 0-1: 1=Graphics engine will render
* the screen immediately after current line.
* May cause a tearing effect.
@ -246,17 +251,26 @@
* the screen immediately after the current
* frame is scanned out (recommended).
*/
/* FT80X_REG_TOUCH_TAG */
#define TOUCH_TAG_MASK 0xff /* Bits 0-7: Tag of touched graphic object */
/* Interrupts ******************************************************************************/
/* The interrupt output pin is enabled by REG_INT_EN. When REG_INT_EN is 0, INT_N is
* tri-state (pulled to high by external pull-up resistor). When REG_INT_EN is 1, INT_N is
/* The interrupt output pin is enabled by REG_INT_EN. When REG_INT_EN is 0, INT_N is
* tri-state (pulled to high by external pull-up resistor). When REG_INT_EN is 1, INT_N is
* driven low when any of the interrupt flags in REG_INT_FLAGS are high, after masking with
* REG_INT_MASK. Writing a 1 in any bit of REG_INT_MASK will enable the correspond
* interrupt. Each bit in REG_INT_FLAGS is set by a corresponding interrupt source.
* REG_INT_MASK. Writing a '1' in any bit of REG_INT_MASK will enable the correspond
* interrupt. Each bit in REG_INT_FLAGS is set by a corresponding interrupt source.
* REG_INT_FLAGS is readable by the host at any time, and clears when read.
*/
/* FT80X_REG_INT_EN */
#define FT80X_INT_ENABLE (0) /* Bit 0: 0=Interrupts disabled */
#define FT80X_INT_DISABLE (1 << 0) /* 1=Interrupts enabled */
/* FT80X_REG_INT_FLAGS and FT80X_REG_INT_MASK */
#define FT80X_INT_SWAP (1 << 0) /* Bit 0: Display swap occurred */
#define FT80X_INT_TOUCH (1 << 1) /* Bit 1: Touch-screen touch detected */
#define FT80X_INT_TAG (1 << 2) /* Bit 2: Touch-screen tag value change */
@ -266,6 +280,9 @@
#define FT80X_INT_CMDFLAG (1 << 6) /* Bit 6: Command FIFO flag */
#define FT80X_INT_CONVCOMPLETE (1 << 7) /* Bit 7: Touch-screen conversions completed */
#define FT80X_INT_NEVENTS 8
#define FT80X_INT(n) (1 << (n))
/*******************************************************************************************
* Public Types
*******************************************************************************************/
@ -368,6 +385,15 @@ struct ft80x_i2cwrite_s
/* Write data follows */
};
/* This structure describes one signal notification */
struct ft80x_eventinfo_s
{
uint8_t signo; /* Notify using this signal number */
bool enable; /* True: enable notification; false: disable */
int16_t pid; /* Send the notification to this task */
};
/* This structure describes the overall state of the FT80x driver */
struct spi_dev_s; /* Forward reference */
@ -375,12 +401,17 @@ struct i2c_master_s; /* Forward reference */
struct ft80x_dev_s
{
/* Cached interface instances */
#ifdef CONFIG_LCD_FT80X_SPI
FAR struct spi_dev_s *spi; /* Cached SPI device reference */
#else
FAR struct i2c_master_s *i2c; /* Cached SPI device reference */
#endif
FAR const struct ft80x_config_s *lower; /* Cached lower half instance */
/* Internal driver logic */
struct work_s intwork; /* Support back end interrupt processing */
uint32_t frequency; /* Effective frequency */
sem_t exclsem; /* Mutual exclusion semaphore */
@ -388,6 +419,10 @@ struct ft80x_dev_s
uint8_t crefs; /* Number of open references */
bool unlinked; /* True if the driver has been unlinked */
#endif
/* Event notification support */
struct ft80x_eventinfo_s notify[FT80X_INT_NEVENTS];
};
/****************************************************************************

View File

@ -62,6 +62,11 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration */
#ifdef CONFIG_DISABLE_SIGNALS
# error Signal support is required by this driver
#endif
/* FT80x IOCTL commands:
*
@ -116,16 +121,28 @@
* Returns: The 32-bit value read from the display list.
*
* FT80X_IOC_GETTRACKER:
* Description: After CMD_TRACK has been issued, the coprocessor will update
* Description: After CMD_TRACK has been issued, the co-processor will update
* the TRACKER register with new position data.
* Argument: A pointer to a writable uint32_t memory location.
* Returns: The new content of the tracker register.
*
* FT80X_IOC_EVENTNOTIFY:
* Description: Setup to receive a signal when there is a change in any
* touch tag value. Additional information may be provided in
* the signinfo.si_val file of the notification:
*
* For touch tag events, siginfo.si_value will indicate the
* touch tag. For the FT801 in extended mode, it will
* indicate only the tag value for TOUCH0.
* Argument: A reference to an instance of struct ft80x_notify_s.
* Returns: None
*/
#define FT80X_IOC_CREATEDL _LCDIOC(FT80X_NIOCTL_BASE + 0)
#define FT80X_IOC_APPENDDL _LCDIOC(FT80X_NIOCTL_BASE + 1)
#define FT80X_IOC_GETRESULT32 _LCDIOC(FT80X_NIOCTL_BASE + 2)
#define FT80X_IOC_GETTRACKER _LCDIOC(FT80X_NIOCTL_BASE + 3)
#define FT80X_IOC_EVENTNOTIFY _LCDIOC(FT80X_NIOCTL_BASE + 4)
/* Host commands. 3 word commands. The first word begins with 0b01, the next two are zero */
@ -1037,6 +1054,30 @@ struct ft80x_result32_s
uint32_t value; /* 32-bit value read from display list + offset */
};
/* This structure is used with the FT80X_IOC_EVENTNOTIFY IOCTL command to describe
* the requested event notification.
*/
enum ft80x_notify_e
{
FT80X_NOTIFY_SWAP = 0, /* Bit 0: Display swap occurred */
FT80X_NOTIFY_TOUCH, /* Touch-screen touch detected */
FT80X_NOTIFY_TAG, /* Touch-screen tag value change */
FT80X_NOTIFY_SOUND, /* Sound effect ended */
FT80X_NOTIFY_PLAYBACK, /* Audio playback ended */
FT80X_NOTIFY_CMDEMPTY, /* Bit 5: Command FIFO empty */
FT80X_NOTIFY_CMDFLAG, /* Command FIFO flag */
FT80X_NOTIFY_CONVCOMPLETE /* Touch-screen conversions completed */
};
struct ft80x_notify_s
{
int signo; /* Notify using this signal number */
pid_t pid; /* Send the notification to this task */
enum ft80x_notify_e event; /* Notify on this event */
bool enable; /* True: enable notification; false: disable */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/