This commit adds a barbones FTDI FT80x driver. It is untested (I don't even have hardware yet and, hence, it is marked as EXPERIMENTAL

Squashed commit of the following:

    drivers/lcd:  Finishes off basic FT80X.  Still missing some niceties.
    drivers/lcd: Rethink FT80X display list interface.
    drivers/lcd:  More FT800x display list logic.  Still not complete.
    drivers/lcd:  Add some basic FT80x initialization logic.
    drivers/lcd:  Add ft80x display list IOCTL framework.  Still missing low level display list operations.
    drivers/lcd:  FT80x driver cannot be a standard LCD driver but must, instead, be a custom character driver.
    drivers/lcd:  Add FT800 co-processor commands and display list helpers.
    drivers/lcd:  Add SPI interface and framework for the initialization and the basic LCD driver.
    drivers/lcd:  Add beginnings of some FT80x implementation.
    drivers/lcd:  Add definitions for the FTDI FT801 part
    include/nuttx/lcd/ft800.h:  Add initial FT800 interface definition.
    drivers/lcd:  Add ft800 header file.
This commit is contained in:
Gregory Nutt 2018-02-17 11:59:07 -06:00
parent d040316143
commit 6a405ead67
9 changed files with 2755 additions and 27 deletions

View File

@ -1173,6 +1173,61 @@ config LCD_RA8875_EXTENDED
driver anyway.
endif # LCD_RA8875
config LCD_FT80X
bool "FTDI FT80x GUI Controller"
default n
depends on EXPERIMENTAL
---help---
Integrated LCD, Audio, Touchscreen controller driver for the FTDI
FT80x "EVE" series.
if LCD_FT80X
choice
prompt "FTDI FT80x part"
default LCD_FT800
config LCD_FT800
bool "FT800"
config LCD_FT801
bool "FT801"
endchoice # FTDI FT80x part
choice
prompt "FTDI FT80x Interface"
default LCD_FT80X_SPI
config LCD_FT80X_SPI
bool "SPI"
select SPI
config LCD_FT80X_I2C
bool "I2C"
select I2C
endchoice # FTDI FT80x Interface
config LCD_FT801_MULTITOUCH
bool "FT801 Multi-touch"
default n
depends on LCD_FT801
choice
prompt "Display size"
default LCD_FT80X_WQVGA
config LCD_FT80X_WQVGA
bool "WQVGA 480x272"
config LCD_FT80X_QVGA
bool "QVGA 320x240"
endchoice # Display size
endif # LCD_FT80X
endmenu # LCD Driver selection
endif # LCD

View File

@ -1,7 +1,7 @@
############################################################################
# drivers/lcd/Make.defs
#
# Copyright (C) 2010-2012, 2017 Gregory Nutt. All rights reserved.
# Copyright (C) 2010-2012, 2017-2018 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@ -43,6 +43,15 @@ endif
# Include support for Graphics LCD drivers
ifeq ($(CONFIG_LCD_FT80X),y)
CSRCS += ft80x_base.c
ifeq ($(CONFIG_LCD_FT80X_SPI),y)
CSRCS += ft80x_spi.c
else ifeq ($(CONFIG_LCD_FT80X_I2C),y)
CSRCS += ft80x_i2c.c
endif
endif
ifeq ($(CONFIG_LCD_P14201),y)
CSRCS += p14201.c
endif

448
drivers/lcd/ft80x.h Normal file
View File

@ -0,0 +1,448 @@
/*******************************************************************************************
* drivers/lcd/ft80x.h
* Definitions for the FTDI FT80x GUI
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
* - Document No.: FT_000792, "FT800 Embedded Video Engine", Datasheet Version 1.1,
* Clearance No.: FTDI# 334, Future Technology Devices International Ltd.
* - Document No.: FT_000986, "FT801 Embedded Video Engine Datasheet", Version 1.0,
* Clearance No.: FTDI#376, Future Technology Devices International Ltd.
* - Some definitions derive from FTDI sample code.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************************/
#ifndef __DRIVERS_LCD_FT80X_H
#define __DRIVERS_LCD_FT80X_H
/*******************************************************************************************
* Included Files
*******************************************************************************************/
/*******************************************************************************************
* Pre-processor Definitions
*******************************************************************************************/
/* FT80x Memory Map ************************************************************************/
/* Address region */
#define FT80X_RAM_G 0x000000 /* Main graphics RAM (256Kb) */
#define FT80X_ROM_CHIPID 0x0c0000 /* FT80x chip identification and revision
* information (4b):
* Byte [0:1] Chip ID: 0800 or 0801
* Byte [2:3] Version ID: 0100 */
#define FT80X_ROM_FONT 0x0bb23c /* Font table and bitmap (275Kb) */
#define FT80X_ROM_FONT_ADDR 0x0ffffc /* Font table pointer address (4b) */
#define FT80X_RAM_DL 0x100000 /* Display List RAM (8Kb) */
#define FT80X_RAM_PAL 0x102000 /* Palette RAM (1Kb) */
#define FT80X_REG 0x102400 /* Registers (380b) */
#define FT80X_RAM_CMD 0x108000 /* Command Buffer (4Kb) */
#ifdef CONFIG_LCD_FT801
# define FT80X_RAM_SCREENSHOT 0x1c2000 /* Screenshot readout buffer (2Kb) */
#endif
/* Memory buffer sizes */
#define FT80X_RAM_G_SIZE (256 * 1024)
#define FT80X_CMDFIFO_SIZE (4 * 1024)
#define FT80X_RAM_DL_SIZE (8 * 1024)
#define FT80X_RAM_PAL_SIZE (1 * 1024)
/* FT80x Register Addresses ****************************************************************/
#define FT80X_REG_ID 0x102400 /* Identification register, always reads as 7c */
#define FT80X_REG_FRAMES 0x102404 /* Frame counter, since reset */
#define FT80X_REG_CLOCK 0x102408 /* Clock cycles, since reset */
#define FT80X_REG_FREQUENCY 0x10240c /* Main clock frequency */
#if defined(CONFIG_LCD_FT800)
# define FT80X_REG_RENDERMODE 0x102410 /* Rendering mode: 0 = normal, 1 = single-line */
# define FT80X_REG_SNAPY 0x102414 /* Scan line select for RENDERMODE 1 */
# define FT80X_REG_SNAPSHOT 0x102418 /* Trigger for RENDERMODE 1 */
#elif defined(CONFIG_LCD_FT801)
# define FT80X_REG_SCREENSHOT_EN 0x102410 /* Set to enable screenshot mode */
# define FT80X_REG_SCREENSHOT_Y 0x102414 /* Y line number for screenshot */
# define FT80X_REG_SCREENSHOT_START 0x102418 /* Screenshot start trigger */
#endif
#define FT80X_REG_CPURESET 0x10241c /* Graphics, audio and touch engines reset
* control */
#define FT80X_REG_TAP_CRC 0x102420 /* Live video tap crc. Frame CRC is computed
* every DL SWAP. */
#define FT80X_REG_TAP_MASK 0x102424 /* Live video tap mask */
#define FT80X_REG_HCYCLE 0x102428 /* Horizontal total cycle count */
#define FT80X_REG_HOFFSET 0x10242c /* Horizontal display start offset */
#define FT80X_REG_HSIZE 0x102430 /* Horizontal display pixel count */
#define FT80X_REG_HSYNC0 0x102434 /* Horizontal sync fall offset */
#define FT80X_REG_HSYNC1 0x102438 /* Horizontal sync rise offset */
#define FT80X_REG_VCYCLE 0x10243c /* Vertical total cycle count */
#define FT80X_REG_VOFFSET 0x102440 /* Vertical display start offset */
#define FT80X_REG_VSIZE 0x102444 /* Vertical display line count */
#define FT80X_REG_VSYNC0 0x102448 /* Vertical sync fall offset */
#define FT80X_REG_VSYNC1 0x10244c /* Vertical sync rise offset */
#define FT80X_REG_DLSWAP 0x102450 /* Display list swap control */
#define FT80X_REG_ROTATE 0x102454 /* Screen 180 degree rotate */
#define FT80X_REG_OUTBITS 0x102458 /* Output bit resolution, 3x3x3 bits */
#define FT80X_REG_DITHER 0x10245c /* Output dither enable */
#define FT80X_REG_SWIZZLE 0x102460 /* Output RGB signal swizzle */
#define FT80X_REG_CSPREAD 0x102464 /* Output clock spreading enable */
#define FT80X_REG_PCLK_POL 0x102468 /* PCLK polarity: 0=rising edge, 1= falling edge */
#define FT80X_REG_PCLK 0x10246c /* PCLK frequency divider, 0 = disable */
#define FT80X_REG_TAG_X 0x102470 /* Tag query X coordinate */
#define FT80X_REG_TAG_Y 0x102474 /* Tag query Y coordinate */
#define FT80X_REG_TAG 0x102478 /* Tag query result */
#define FT80X_REG_VOL_PB 0x10247c /* Volume for playback */
#define FT80X_REG_VOL_SOUND 0x102480 /* Volume for synthesizer sound */
#define FT80X_REG_SOUND 0x102484 /* Sound effect select */
#define FT80X_REG_PLAY 0x102488 /* Start effect playback */
#define FT80X_REG_GPIO_DIR 0x10248c /* GPIO pin direction, 0=input, 1=output */
#define FT80X_REG_GPIO 0x102490 /* Pin value (bits 0,1,7); Drive strength
* (bits 2-6) */
/* 0x102494 Reserved */
#define FT80X_REG_INT_FLAGS 0x102498 /* Interrupt flags, clear by read */
#define FT80X_REG_INT_EN 0x10249c /* Global interrupt enable */
#define FT80X_REG_INT_MASK 0x1024a0 /* Interrupt enable mask */
#define FT80X_REG_PLAYBACK_START 0x1024a4 /* Audio playback RAM start address */
#define FT80X_REG_PLAYBACK_LENGTH 0x1024a8 /* Audio playback sample length (bytes) */
#define FT80X_REG_PLAYBACK_READPTR 0x1024ac /* Audio playback current read pointer */
#define FT80X_REG_PLAYBACK_FREQ 0x1024b0 /* Audio playback sampling frequency (Hz) */
#define FT80X_REG_PLAYBACK_FORMAT 0x1024b4 /* Audio playback format */
#define FT80X_REG_PLAYBACK_LOOP 0x1024b8 /* Audio playback loop enable */
#define FT80X_REG_PLAYBACK_PLAY 0x1024bc /* Start audio playback */
#define FT80X_REG_PWM_HZ 0x1024c0 /* BACKLIGHT PWM output frequency (Hz) */
#define FT80X_REG_PWM_DUTY 0x1024c4 /* BACKLIGHT PWM output duty cycle 0=0%,
* 128=100% */
#define FT80X_REG_MACRO_0 0x1024c8 /* Display list macro command 0 */
#define FT80X_REG_MACRO_1 0x1024cc /* Display list macro command 1 */
#if defined(CONFIG_LCD_FT800)
/* 0x1024d0 0x1024e0 Reserved */
#elif defined(CONFIG_LCD_FT801)
/* 0x1024d0 0x1024d4 Reserved */
# define FT80X_REG_SCREENSHOT_BUSY 0x1024d8 /* Screenshot ready flags */
/* 0x1024e0 Reserved */
#endif
#define FT80X_REG_CMD_READ 0x1024e4 /* Command buffer read pointer */
#define FT80X_REG_CMD_WRITE 0x1024e8 /* Command buffer write pointer */
#define FT80X_REG_CMD_DL 0x1024ec /* Command display list offset */
#define FT80X_REG_TOUCH_MODE 0x1024f0 /* Touch-screen sampling mode */
#if defined(CONFIG_LCD_FT800)
# define FT80X_REG_TOUCH_ADC_MODE 0x1024f4 /* Select single ended (low power) or
* differential (accurate) sampling */
# define FT80X_REG_TOUCH_CHARGE 0x1024f8 /* Touch-screen charge time, units of 6 clocks */
# define FT80X_REG_TOUCH_SETTLE 0x1024fc /* Touch-screen settle time, units of 6 clocks */
# define FT80X_REG_TOUCH_OVERSAMPLE 0x102500 /* Touch-screen oversample factor */
# define FT80X_REG_TOUCH_RZTHRESH 0x102504 /* Touch-screen resistance threshold */
# define FT80X_REG_TOUCH_RAW_XY 0x102508 /* Touch-screen raw (x-MSB16; y-LSB16) */
# define FT80X_REG_TOUCH_RZ 0x10250c /* Touch-screen resistance */
# define FT80X_REG_TOUCH_SCREEN_XY 0x102510 /* Touch-screen screen (x-MSB16; y-LSB16) */
# define FT80X_REG_TOUCH_TAG_XY 0x102514 /* Touch-screen screen (x-MSB16; y-LSB16)
* used for tag lookup */
# define FT80X_REG_TOUCH_TAG 0x102518 /* Touch-screen tag result */
# define FT80X_REG_TOUCH_TRANSFORM_A 0x10251c /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_TOUCH_TRANSFORM_B 0x102520 /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_TOUCH_TRANSFORM_C 0x102524 /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_TOUCH_TRANSFORM_D 0x102528 /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_TOUCH_TRANSFORM_E 0x10252c /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_TOUCH_TRANSFORM_F 0x102530 /* Touch-screen transform coefficient (s15.16) */
/* 0x102534 0x102470 Reserved */
# define FT80X_REG_TOUCH_DIRECT_XY 0x102574 /* Touch screen direct (x-MSB16; y-LSB16)
* conversions */
# define FT80X_REG_TOUCH_DIRECT_Z1Z2 0x102578 /* Touch screen direct (z1-MSB16; z2-LSB16)
* conversions */
#elif defined(CONFIG_LCD_FT801)
/* 0x1024d0 0x1024d4 Reserved */
# define FT80X_REG_CTOUCH_EXTENDED 0x1024f4 /* Set capacitive touch operation mode:
* 0: extended mode (multi-touch)
* 0: 1: FT800 compatibility mode (single touch) */
# define FT80X_REG_CTOUCH_REG 0x1024f8 /* CTPM configure register write
* Bits [7:0]: configure register address
* Bits [15:8]: configure register value */
/* 0x1024fc - 0x102504 Reserved */
# define FT80X_REG_CTOUCH_RAW_XY 0x102508 /* Compatibility mode: touch-screen raw
* (x-MSB16; y-LSB16) */
# define FT80X_REG_CTOUCH_TOUCH1_XY 0x102508 /* Extended mode: touch-screen screen data for touch 1
* (x-MSB16; y-LSB16) */
# define FT80X_REG_CTOUCH_TOUCH4_XY 0x10250c /* Extended mode: touch-screen screen Y data for touch 4 */
# define FT80X_REG_CTOUCH_SCREEN_XY 0x102510 /* Compatibility mode: touch-screen screen
* (x-MSB16; y-LSB16) */
# define FT80X_REG_CTOUCH_TOUCH0_XY 0x102510 /* Extended mode: touch-screen screen data for touch 0
* (x-MSB16; y-LSB16) */
# define FT80X_REG_CTOUCH_TAG_XY 0x102514 /* Touch-screen screen (x-MSB16; y-LSB16)
* used for tag lookup */
# define FT80X_REG_CTOUCH_TAG 0x102518 /* Touch-screen tag result */
# define FT80X_REG_CTOUCH_TRANSFORM_A 0x10251c /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_CTOUCH_TRANSFORM_B 0x102520 /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_CTOUCH_TRANSFORM_C 0x102524 /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_CTOUCH_TRANSFORM_D 0x102528 /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_CTOUCH_TRANSFORM_E 0x10252c /* Touch-screen transform coefficient (s15.16) */
# define FT80X_REG_CTOUCH_TRANSFORM_F 0x102530 /* Touch-screen transform coefficient (s15.16) */
/* 0x102534 Reserved */
# define FT80X_REG_CTOUCH_TOUCH4_X 0x102538 /* Extended mode: touch-screen screen X data for
* touch 4 */
/* 0x10253c 0x102450 Reserved */
# define FT80X_REG_SCREENSHOT_READ 0x102554 /* Set to enable readout of the screenshot of the
* selected Y line */
/* 0x10253c 0x102468 Reserved */
# define FT80X_REG_TRIM 0x10256c /* Internal relaxation clock trimming */
/* 0x102570 Reserved */
# define FT80X_REG_CTOUCH_DIRECT_XY 0x102574 /* Compatibility mode: Touch screen direct
* (x-MSB16; y-LSB16) conversions */
# define FT80X_REG_CTOUCH_TOUCH2_XY 0x102574 /* Extended mode: touch-screen screen data for
* touch 2 (x-MSB16; y-LSB16) */
# define FT80X_REG_CTOUCH_DIRECT_Z1Z2 0x102578 /* Compatibility mode: Touch screen direct
* (z1-MSB16; z2-LSB16) conversions */
# define FT80X_REG_CTOUCH_TOUCH3_XY 0x102578 /* Extended mode: touch-screen screen data for
* touch 3 (x-MSB16; y-LSB16) */
#endif
#define FT80X_REG_TRACKER 0x109000 /* Track register (Track value MSB16;
* Tag value - LSB8) */
/* FT80x Register Bit Definitions **********************************************************/
#define ID_MASK 0xff /* Bits 0-7: Register ID */
#define DLSWAP_LINE 1 /* Bits 0-1: 1=Graphics engine will render
* the screen immediately after current line.
* May cause a tearing effect.
*/
#define DLSWAP_FRAME 2 /* Bits 0-1: 2=Graphics engine will render
* the screen immediately after the current
* frame is scanned out (recommended).
*/
/*******************************************************************************************
* Public Types
*******************************************************************************************/
/* Host write command
*
* For a SPI write command write transaction, the host writes a zero bit followed by a one
* bit, followed by the 5-bit command, followed by two bytes of zero. All data is streamed
* with a single chip select.
*
* I2C data format is equivalent (with obvious differences in bus protocol)
*/
struct ft80x_hostwrite_s
{
uint8_t cmd; /* Bits 6-7: 01, Bits 0-5: command */
uint8_t pad1; /* Zero */
uint8_t pad2; /* Zero */
};
/* For SPI memory read transaction, the host sends two zero bits, followed by the 22-bit
* address. This is followed by a dummy byte. After the dummy byte, the FT80x responds to
* each host byte with read data bytes.
*
* For I2C memory read transaction, bytes are packed in the I2C protocol as follow:
*
* [start] <DEVICE ADDRESS + write bit>
* <00b+Address[21:16]>
* <Address[15:8]>
* <Address[7:0]>
* [restart] <DEVICE ADDRESS + read bit>
* <Read data byte 0>
* ....
* <Read data byte n> [stop]
*/
struct ft80x_spiread_s
{
uint8_t addrh; /* Bits 6-7: 00, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
uint8_t dummy; /* Dummy byte */
};
struct ft80x_i2cread_s
{
uint8_t addrh; /* Bits 6-7: 00, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
};
/* For SPI memory write transaction, the host sends a '1' bit and '0' bit, followed by the
* 22-bit address. This is followed by the write data.
*
* For I2C memory write transaction, bytes are packed in the I2C protocol as follow:
*
* [start] <DEVICE ADDRESS + write bit>
* <10b,Address[21:16]>
* <Address[15:8]>
* <Address[7:0]>
* <Write data byte 0>
* ....
* <Write data byte n> [stop]
*/
struct ft80x_spiwrite_s
{
uint8_t addrh; /* Bits 6-7: 10, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
/* Write data follows */
};
struct ft80x_spiwrite8_s
{
uint8_t addrh; /* Bits 6-7: 10, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
uint8_t data; /* 8-bit data follows */
};
struct ft80x_spiwrite16_s
{
uint8_t addrh; /* Bits 6-7: 10, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
uint8_t data[2]; /* 16-bit data follows */
};
struct ft80x_spiwrite32_s
{
uint8_t addrh; /* Bits 6-7: 10, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
uint8_t data[4]; /* 32-bit data follows */
};
struct ft80x_i2cwrite_s
{
uint8_t addrh; /* Bits 6-7: 10, Bits 0-5: Address[21:16] */
uint8_t addrm; /* Address[15:8] */
uint8_t addrl; /* Address[7:0] */
/* Write data follows */
};
/* This structure describes the overall state of the FT80x driver */
struct spi_dev_s; /* Forward reference */
struct i2c_master_s; /* Forward reference */
struct ft80x_dev_s
{
#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 */
uint32_t frequency; /* Effective frequency */
sem_t exclsem; /* Mutual exclusion semaphore */
uint8_t crefs; /* Open count */
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_host_command
*
* Description:
* Send a host command to the FT80x
*
* FFor a SPI write command write transaction, the host writes a zero bit
* followed by a one bit, followed by the 5-bit command, followed by two
* bytes of zero. All data is streamed with a single chip select.
*
****************************************************************************/
void ft80x_host_command(FAR struct ft80x_dev_s *priv, uint8_t cmd);
/****************************************************************************
* Name: ft80x_read_memory
*
* Description:
* Read from FT80X memory
*
* For SPI memory read transaction, the host sends two zero bits, followed
* by the 22-bit address. This is followed by a dummy byte. After the dummy
* byte, the FT80x responds to each host byte with read data bytes.
*
****************************************************************************/
void ft80x_read_memory(FAR struct ft80x_dev_s *priv, uint32_t addr,
FAR void *buffer, size_t buflen);
/****************************************************************************
* Name: ft80x_read_byte, ft80x_read_hword, ft80x_read_word
*
* Description:
* Read an 8-, 16-, or 32-bt bit value from FT80X memory
*
* For SPI memory read transaction, the host sends two zero bits, followed
* by the 22-bit address. This is followed by a dummy byte. After the dummy
* byte, the FT80x responds to each host byte with read data bytes.
*
****************************************************************************/
uint8_t ft80x_read_byte(FAR struct ft80x_dev_s *priv, uint32_t addr);
uint16_t ft80x_read_hword(FAR struct ft80x_dev_s *priv, uint32_t addr);
uint32_t ft80x_read_word(FAR struct ft80x_dev_s *priv, uint32_t addr);
/****************************************************************************
* Name: ft80x_write_memory
*
* Description:
* Write to FT80X memory
*
* For SPI memory write transaction, the host sends a '1' bit and '0' bit,
* followed by the 22-bit address. This is followed by the write data.
*
****************************************************************************/
void ft80x_write_memory(FAR struct ft80x_dev_s *priv, uint32_t addr,
FAR const void *buffer, size_t buflen);
/****************************************************************************
* Name: ft80x_write_byte, ft80x_write_hword, ft80x_write_word
*
* Description:
* Write an 8-, 16-, or 32-bt bit value to FT80X memory
*
* For SPI memory write transaction, the host sends a '1' bit and '0' bit,
* followed by the 22-bit address. This is followed by the write data.
*
****************************************************************************/
void ft80x_write_byte(FAR struct ft80x_dev_s *priv, uint32_t addr,
uint8_t data);
void ft80x_write_hword(FAR struct ft80x_dev_s *priv, uint32_t addr,
uint16_t data);
void ft80x_write_word(FAR struct ft80x_dev_s *priv, uint32_t addr,
uint32_t data);
#endif /* __DRIVERS_LCD_FT80X_H */

734
drivers/lcd/ft80x_base.c Normal file
View File

@ -0,0 +1,734 @@
/**************************************************************************************
* drivers/lcd/ft80x_base.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
* - Document No.: FT_000792, "FT800 Embedded Video Engine", Datasheet Version 1.1,
* Clearance No.: FTDI# 334, Future Technology Devices International Ltd.
* - Document No.: FT_000986, "FT801 Embedded Video Engine Datasheet", Version 1.0,
* Clearance No.: FTDI#376, Future Technology Devices International Ltd.
* - Application Note AN_240AN_240, "FT800 From the Ground Up", Version 1.1,
* Issue Date: 2014-06-09, Future Technology Devices International Ltd.
* - "FT800 Series Programmer Guide Guide", Version 2.1, Issue Date: 2016-09-19,
* Future Technology Devices International Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************************/
/**************************************************************************************
* Included Files
**************************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <poll.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/semaphore.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/spi/spi.h>
#include <nuttx/lcd/lcd.h>
#include <nuttx/lcd/ft80x.h>
#include <arch/irq.h>
#include "ft80x.h"
#ifdef CONFIG_LCD_FT80X
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_LCD_FT800)
# define DEVNAME "/dev/ft800"
# define ROMID 0x01000800
#elif defined(CONFIG_LCD_FT801)
# define DEVNAME "/dev/ft801"
# define ROMID 0x01000801
#else
# error No FT80x device configured
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Character driver methods */
static int ft80x_open(FAR struct file *filep);
static int ft80x_close(FAR struct file *filep);
static ssize_t ft80x_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t ft80x_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
#ifndef CONFIG_DISABLE_POLL
static int ft80x_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
#endif
/* Initialization */
static int ft80x_initialize(FAR struct ft80x_dev_s *priv);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations g_ft80x_fops =
{
ft80x_open, /* open */
ft80x_close, /* close */
ft80x_read, /* read */
ft80x_write, /* write */
NULL, /* seek */
ft80x_ioctl /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, ft80x_poll /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_open
*
* Description:
* This function is called whenever the PWM device is opened.
*
****************************************************************************/
static int ft80x_open(FAR struct file *filep)
{
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
uint8_t tmp;
int ret;
DEBUGASSERT(filep != NULL);
inode = filep->f_inode;
DEBUGASSERT(inode != NULL && inode->i_private != NULL);
priv = inode->i_private;
lcdinfo("crefs: %d\n", priv->crefs);
/* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->exclsem);
if (ret < 0)
{
goto errout;
}
/* Increment the count of references to the device */
tmp = priv->crefs + 1;
if (tmp == 0)
{
/* More than 255 opens; uint8_t overflows to zero */
ret = -EMFILE;
goto errout_with_sem;
}
/* Save the new open count */
priv->crefs = tmp;
ret = OK;
errout_with_sem:
nxsem_post(&priv->exclsem);
errout:
return ret;
}
/****************************************************************************
* Name: ft80x_close
*
* Description:
* This function is called when the PWM device is closed.
*
****************************************************************************/
static int ft80x_close(FAR struct file *filep)
{
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
int ret;
DEBUGASSERT(filep != NULL);
inode = filep->f_inode;
DEBUGASSERT(inode != NULL && inode->i_private != NULL);
priv = inode->i_private;
lcdinfo("crefs: %d\n", priv->crefs);
/* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->exclsem);
if (ret < 0)
{
goto errout;
}
/* Decrement the references to the driver. */
if (priv->crefs > 1)
{
priv->crefs--;
}
ret = OK;
nxsem_post(&priv->exclsem);
errout:
return ret;
}
/****************************************************************************
* Name: ft80x_read
****************************************************************************/
static ssize_t ft80x_read(FAR struct file *filep, FAR char *buffer,
size_t len)
{
/* Reading from the FT80X is an undefined operation and not support */
lcdinfo("buffer: %p len %lu\n", buffer, (unsigned long)len);
return 0; /* Return EOF */
}
/****************************************************************************
* Name: ft80x_write
****************************************************************************/
static ssize_t ft80x_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
{
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
int ret;
lcdinfo("buffer: %p len %lu\n", buffer, (unsigned long)len);
DEBUGASSERT(buffer != NULL && ((uintptr_t)buffer & 3) == 0 &&
len > 0 && (len & 3) == 0 && len <= FT80X_RAM_DL_SIZE);
DEBUGASSERT(filep != NULL);
inode = filep->f_inode;
DEBUGASSERT(inode != NULL && inode->i_private != NULL);
priv = inode->i_private;
if (buffer == NULL || ((uintptr_t)buffer & 3) != 0 ||
len == 0 || (len & 3) != 0 || len > FT80X_RAM_DL_SIZE)
{
return -EINVAL;
}
/* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* The write method is functionally equivalent to the FT80XIOC_PUTDISPLAYLIST
* IOCTL command: It simply copies the display list in the user buffer to
* the FT80x display list memory.
*/
ft80x_write_memory(priv, FT80X_RAM_DL, buffer, len);
nxsem_post(&priv->exclsem);
return len;
}
/****************************************************************************
* Name: ft80x_ioctl
*
* Description:
* The standard ioctl method. This is where ALL of the PWM work is done.
*
****************************************************************************/
static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
int ret;
DEBUGASSERT(filep != NULL);
inode = filep->f_inode;
DEBUGASSERT(inode != NULL && inode->i_private != NULL);
priv = inode->i_private;
lcdinfo("cmd: %d arg: %lu\n", cmd, arg);
/* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->exclsem);
if (ret < 0)
{
return ret;
}
/* Handle built-in ioctl commands */
switch (cmd)
{
/* FT80XIOC_PUTDISPLAYLIST:
* Description: Write a display list to the FT80x display list memory
* Argument: A reference to a display list structure instance.
* See struct ft80x_displaylist_s.
* Returns: None
*/
case FT80XIOC_PUTDISPLAYLIST:
{
FAR struct ft80x_displaylist_s *dl =
(FAR struct ft80x_displaylist_s *)((uintptr_t)arg);
if (dl == NULL || ((uintptr_t)&dl->cmd & 3) != 0 ||
dl->dlsize == 0 || (dl->dlsize & 3) != 0 ||
dl->dlsize > FT80X_RAM_DL_SIZE)
{
ret = -EINVAL;
}
else
{
/* This IOCTL command simply copies the display list
* provided into the FT80x display list memory.
*/
ft80x_write_memory(priv, FT80X_RAM_DL, &dl->cmd, dl->dlsize);
ret = OK;
}
}
break;
/* FT80XIOC_GETRESULT32:
* Description: Read a 32-bit value from the display list.
* Argument: A reference to an instance of struct ft80x_result32_s.
* Returns: The 32-bit value read from the display list.
*/
case FT80XIOC_GETRESULT32:
{
FAR struct ft80x_result32_s *result =
(FAR struct ft80x_result32_s *)((uintptr_t)arg);
if (result == NULL || ((uintptr_t)&result->offset & 3) != 0 ||
result->offset >= FT80X_RAM_DL_SIZE)
{
ret = -EINVAL;
}
else
{
result->value = ft80x_read_word(priv,
FT80X_RAM_DL + result->offset);
ret = OK;
}
}
break;
/* FT80XIOC_GETTRACKER:
* Description: After CMD_TRACK has been issued, the coprocessor
* 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.
*/
case FT80XIOC_GETTRACKER:
{
FAR uint32_t *tracker = (FAR uint32_t *)((uintptr_t)arg);
if (tracker == NULL)
{
ret = -EINVAL;
}
else
{
*tracker = ft80x_read_word(priv, FT80X_REG_TRACKER);
ret = OK;
}
}
break;
/* Unrecognized IOCTL command */
default:
lcderr("ERROR: Unrecognized cmd: %d arg: %ld\n", cmd, arg);
ret = -ENOTTY;
break;
}
nxsem_post(&priv->exclsem);
return ret;
}
/****************************************************************************
* Name: ft80x_poll
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
static int ft80x_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup)
{
#warning Missing logic
return -ENOSYS;
}
#endif
/****************************************************************************
* Name: ft80x_initialize
*
* Description:
* Initialize the FT80x
*
****************************************************************************/
static int ft80x_initialize(FAR struct ft80x_dev_s *priv)
{
uint8_t regval32;
uint8_t regval8;
/* To configure the display, load the timing control registers with values
* for the particular display. These registers control horizontal timing:
*
* - FT80X_REG_PCLK
* - FT80X_REG_PCLK_POL
* - FT80X_REG_HCYCLE
* - FT80X_REG_HOFFSET
* - FT80X_REG_HSIZE
* - FT80X_REG_HSYNC0
* - FT80X_REG_HSYNC1
*
* These registers control vertical timing:
*
* - FT80X_REG_VCYCLE
* - FT80X_REG_VOFFSET
* - FT80X_REG_VSIZE
* - FT80X_REG_VSYNC0
* - FT80X_REG_VSYNC1
*
* And the FT80X_REG_CSPREAD register changes color clock timing to reduce system
* noise.
*
* GPIO bit 7 is used for the display enable pin of the LCD module. By
* setting the direction of the GPIO bit to out direction, the display can
* be enabled by writing value of 1 into GPIO bit 7 or the display can be
* disabled by writing a value of 0 into GPIO bit 7. By default GPIO bit 7
* direction is output and the value is 0.
*/
/* Initialization Sequence from Power Down using PD_N pin:
*
* 1. Drive the PD_N pin high
* 2. Wait for at least 20ms
* 3. Execute "Initialization Sequence during the Boot up" from steps 1 to 9
*
* Initialization Sequence from Sleep Mode:
*
* 1. Send Host command "ACTIVE" to enable clock to FT800
* 2. Wait for at least 20ms
* 3. Execute "Initialization Sequence during Boot Up" from steps 5 to 8
*
* Initialization sequence from standby mode:
*
* Execute all the steps mentioned in "Initialization Sequence from Sleep
* Mode" except waiting for at least 20ms in step 2.
*/
DEBUGASSERT(priv->lower != NULL && priv->lower->pwrdown != NULL);
priv->lower->pwrdown(priv->lower, false);
up_mdelay(20);
/* Initialization Sequence during the boot up:
*
* 1. Use MCU SPI clock not more than 11MHz
* 2. Send Host command CLKEXT to FT800
* 3. Send Host command ACTIVE to enable clock to FT800.
* 4. Configure video timing registers, except FT80X_REG_PCLK
* 5. Write first display list
* 6. Write FT80X_REG_DLSWAP, FT800 swaps display list immediately
* 7. Enable back light control for display
* 8. Write FT80X_REG_PCLK, video output begins with the first display list
* 9. Use MCU SPI clock not more than 30MHz
*/
/* 1. Select the initial SPI frequency */
DEBUGASSERT(priv->lower->init_frequency <= 11000000);
priv->frequency = priv->lower->init_frequency;
/* 2. Send Host command CLKEXT to FT800
* 3. Send Host command ACTIVE to enable clock to FT800.
*/
ft80x_host_command(priv, FT80X_CMD_CLKEXT);
ft80x_host_command(priv, FT80X_CMD_ACTIVE);
/* Verify the chip ID */
regval32 = ft80x_read_word(priv, FT80X_REG_ID);
if ((regval32 & ID_MASK) != 0x7c)
{
lcderr("ERROR: Bad chip ID: %02x\n",
(unsigned int)(regval32 & ID_MASK));
return -ENODEV;
}
regval32 = ft80x_read_word(priv, FT80X_ROM_CHIPID);
if (regval32 != ROMID)
{
lcderr("ERROR: Bad ROM chip ID: %08lx\n", (unsigned long)regval32);
return -ENODEV;
}
/* 4. Configure video timing registers, except FT80X_REG_PCLK
*
* Once the FT800 is awake and the internal clock set and Device ID
* checked, the next task is to configure the LCD display parameters for
* the chosen display with the values determined in Section 2.3.3 above.
*
* a. Set FT80X_REG_PCLK to zero - This disables the pixel clock output while
* the LCD and other system parameters are configured
* b. Set the following registers with values for the chosen display.
* Typical WQVGA and QVGA values are shown:
*
* Register Description WQVGA QVGA 320 x 240
* 480x272 320x240
* FT80X_REG_PCLK_POL Pixel Clock Polarity 1 0
* FT80X_REG_HSIZE Image width in pixels 480 320
* FT80X_REG_HCYCLE Total number of clocks per line 548 408
* FT80X_REG_HOFFSET Horizontal image start 43 70
* (pixels from left)
* FT80X_REG_HSYNC0 Start of HSYNC pulse 0 0
* (falling edge)
* FT80X_REG_HSYNC1 End of HSYNC pulse 41 10
* (rising edge)
* FT80X_REG_VSIZE Image height in pixels 272 240
* FT80X_REG_VCYCLE Total number of lines per screen 292 263
* FT80X_REG_VOFFSET Vertical image start 12 13
* (lines from top)
* FT80X_REG_VSYNC0 Start of VSYNC pulse 0 0
* (falling edge)
* FT80X_REG_VSYNC1 End of VSYNC pulse 10 2
* (rising edge)
*
* c. Enable or disable FT80X_REG_CSPREAD with a value of 01h or 00h,
* respectively. Enabling FT80X_REG_CSPREAD will offset the R, G and B
* output bits so all they do not all change at the same time.
*/
ft80x_write_byte(priv, FT80X_REG_PCLK, 0);
#if defined(CONFIG_LCD_FT80X_WQVGA)
ft80x_write_hword(priv, FT80X_REG_HCYCLE, 548);
ft80x_write_hword(priv, FT80X_REG_HOFFSET, 43);
ft80x_write_hword(priv, FT80X_REG_HSYNC0, 0);
ft80x_write_hword(priv, FT80X_REG_HSYNC1, 41);
ft80x_write_hword(priv, FT80X_REG_VCYCLE, 292);
ft80x_write_hword(priv, FT80X_REG_VOFFSET, 12);
ft80x_write_hword(priv, FT80X_REG_VSYNC0, 0);
ft80x_write_hword(priv, FT80X_REG_VSYNC1, 10);
ft80x_write_byte(priv, FT80X_REG_SWIZZLE, 0);
ft80x_write_byte(priv, FT80X_REG_PCLK_POL, 1);
ft80x_write_byte(priv, FT80X_REG_CSPREAD, 1);
ft80x_write_hword(priv, FT80X_REG_HSIZE, 480);
ft80x_write_hword(priv, FT80X_REG_VSIZE, 272);
#elif defined(CONFIG_LCD_FT80X_QVGA)
ft80x_write_hword(priv, FT80X_REG_HCYCLE, 408);
ft80x_write_hword(priv, FT80X_REG_HOFFSET, 70);
ft80x_write_hword(priv, FT80X_REG_HSYNC0, 0);
ft80x_write_hword(priv, FT80X_REG_HSYNC1, 10);
ft80x_write_hword(priv, FT80X_REG_VCYCLE, 263);
ft80x_write_hword(priv, FT80X_REG_VOFFSET, 13);
ft80x_write_hword(priv, FT80X_REG_VSYNC0, 0);
ft80x_write_hword(priv, FT80X_REG_VSYNC1, 2);
ft80x_write_byte(priv, FT80X_REG_SWIZZLE, 0); /* REVISIT */
ft80x_write_byte(priv, FT80X_REG_PCLK_POL, 0);
ft80x_write_byte(priv, FT80X_REG_CSPREAD, 1);
ft80x_write_hword(priv, FT80X_REG_HSIZE, 320);
ft80x_write_hword(priv, FT80X_REG_VSIZE, 240);
#else
# error Unknown display size
#endif
/* 5. Write first display list */
ft80x_write_word(priv, FT80X_RAM_DL + 0, FT80X_CLEAR_COLOR_RGB(0,0,0));
ft80x_write_word(priv, FT80X_RAM_DL + 4, FT80X_CLEAR(1,1,1));
ft80x_write_word(priv, FT80X_RAM_DL + 8, FT80X_DISPLAY());
/* 6. Write FT80X_REG_DLSWAP, FT800 swaps display list immediately */
ft80x_write_byte(priv, FT80X_REG_DLSWAP, DLSWAP_FRAME);
/* GPIO bit 7 is used for the display enable pin of the LCD module. By
* setting the direction of the GPIO bit to out direction, the display can
* be enabled by writing value of 1 into GPIO bit 7 or the display can be
* disabled by writing a value of 0 into GPIO bit 7. By default GPIO bit 7
* direction is output and the value is 0.
*/
regval8 = ft80x_read_byte(priv, FT80X_REG_GPIO_DIR);
regval8 |= (1 << 7);
ft80x_write_byte(priv, FT80X_REG_GPIO_DIR, regval8);
regval8 = ft80x_read_byte(priv, FT80X_REG_GPIO);
regval8 |= (1 << 7);
ft80x_write_byte(priv, FT80X_REG_GPIO, regval8);
/* 7. Enable back light control for display */
#warning Missing logic
/* 8. Write FT80X_REG_PCLK, video output begins with the first display list */
ft80x_write_byte(priv, FT80X_REG_PCLK, 5);
/* 9. Use MCU SPI clock not more than 30MHz */
DEBUGASSERT(priv->lower->op_frequency <= 30000000);
priv->frequency = priv->lower->op_frequency;
return OK;
}
/**************************************************************************************
* Public Functions
**************************************************************************************/
/****************************************************************************
* Name: ft80x_register
*
* Description:
* Configure the ADS7843E to use the provided SPI device instance. This
* will register the driver as /dev/ft80x.
*
* Input Parameters:
* spi - An SPI driver instance
* i2c - An I2C master driver instance
* lower - Persistent board configuration data / lower half interface
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
#if defined(CONFIG_LCD_FT80X_SPI)
int ft80x_register(FAR struct spi_dev_s *spi,
FAR const struct ft80x_config_s *lower)
#elif defined(CONFIG_LCD_FT80X_I2C)
int ft80x_register(FAR struct i2c_master_s *i2c,
FAR const struct ft80x_config_s *lower)
#endif
{
FAR struct ft80x_dev_s *priv;
int ret;
#if defined(CONFIG_LCD_FT80X_SPI)
DEBUGASSERT(spi != NULL && lower != NULL);
#elif defined(CONFIG_LCD_FT80X_I2C)
DEBUGASSERT(i2c != NULL && lower != NULL);
#endif
/* Allocate the driver state structure */
priv = (FAR struct ft80x_dev_s *)kmm_zalloc(sizeof(struct ft80x_dev_s));
if (priv == NULL)
{
lcderr("ERROR: Failed to allocate state structure\n");
return -ENOMEM;
}
/* Save the lower level interface and configuration information */
priv->lower = lower;
#ifdef CONFIG_LCD_FT80X_SPI
/* Remember the SPI configuration */
priv->spi = spi;
#else
/* Remember the I2C configuration */
priv->i2c = i2c;
#endif
/* Initialize the mutual exclusion semaphore */
sem_init(&priv->exclsem, 0, 1);
/* Initialize the FT80x */
ret = ft80x_initialize(priv);
if (ret < 0)
{
goto errout_with_sem;
}
/* Register the FT80x character driver */
ret = register_driver(DEVNAME, &g_ft80x_fops, 0666, priv);
if (ret < 0)
{
goto errout_with_sem;
}
return OK;
errout_with_sem:
sem_destroy(&priv->exclsem);
return ret;
}
#endif /* CONFIG_LCD_FT80X */

363
drivers/lcd/ft80x_spi.c Normal file
View File

@ -0,0 +1,363 @@
/****************************************************************************
* drivers/lcd/ft80x_spi.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <unistd.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/lcd/ft80x.h>
#include <nuttx/spi/spi.h>
#include "ft80x.h"
#if defined(CONFIG_LCD_FT80X) && defined(CONFIG_LCD_FT80X_SPI)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_select
*
* Description:
* Select the FT80X part
*
****************************************************************************/
static void ft80x_select(FAR struct ft80x_dev_s *priv)
{
lcdinfo("Mode: %d Bits: 8 Frequency: %d\n",
CONFIG_FT80X_SPIMODE, CONFIG_FT80X_FREQUENCY);
DEBUGASSERT(priv != NULL);
/* Lock the SPI bus */
(void)SPI_LOCK(priv->spi, true);
/* Configure SPI for the FT80X */
SPI_SETMODE(priv->spi, SPIDEV_MODE0);
SPI_SETBITS(priv->spi, 8);
(void)SPI_HWFEATURES(priv->spi, 0);
(void)SPI_SETFREQUENCY(priv->spi, priv->frequency);
/* Select SPI device */
SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true);
}
/****************************************************************************
* Name: ft80x_deselect
*
* Description:
* De-select the FT80X part
*
****************************************************************************/
static void ft80x_deselect(FAR struct ft80x_dev_s *priv)
{
/* Des-select the FT80x device */
SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false);
/* Unlock bus */
(void)SPI_LOCK(priv->spi, false);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_host_command
*
* Description:
* Send a host command to the FT80x
*
* FFor a SPI write command write transaction, the host writes a zero bit
* followed by a one bit, followed by the 5-bit command, followed by two
* bytes of zero. All data is streamed with a single chip select.
*
****************************************************************************/
void ft80x_host_command(FAR struct ft80x_dev_s *priv, uint8_t cmd)
{
struct ft80x_hostwrite_s hostwrite;
DEBUGASSERT(priv != NULL && (cnd & 0xc0) == 0);
/* Format the host write command */
hostwrite.cmd = 0x40 | cmd;
hostwrite.pad1 = 0;
hostwrite.pad2 = 0;
/* Select the FT80x */
ft80x_select(priv);
/* Send the host write command */
SPI_SNDBLOCK(priv->spi, &hostwrite, sizeof(struct ft80x_hostwrite_s));
/* De-select the FT80x */
ft80x_deselect(priv);
}
/****************************************************************************
* Name: ft80x_read_memory
*
* Description:
* Read from FT80X memory
*
* For SPI memory read transaction, the host sends two zero bits, followed
* by the 22-bit address. This is followed by a dummy byte. After the dummy
* byte, the FT80x responds to each host byte with read data bytes.
*
****************************************************************************/
void ft80x_read_memory(FAR struct ft80x_dev_s *priv, uint32_t addr,
FAR void *buffer, size_t buflen)
{
struct ft80x_spiread_s spiread;
DEBUGASSERT(priv != NULL && (addr & 0xffc00000) == 0 &&
buffer != NULL && bulen > 0);
/* Format the read header */
spiread.addrh = (addr >> 16) & 0x3f;
spiread.addrm = (addr >> 8) & 0xff;
spiread.addrl = addr & 0xff;
spiread.dummy = 0xff;
/* Select the FT80x */
ft80x_select(priv);
/* Send the read header */
SPI_SNDBLOCK(priv->spi, &spiread, sizeof(struct ft80x_spiread_s));
/* Then read the FT80x memory into the user provided buffer */
SPI_RECVBLOCK(priv->spi, buffer, buflen);
/* De-select the FT80x */
ft80x_deselect(priv);
}
/****************************************************************************
* Name: ft80x_read_byte, ft80x_read_hword, ft80x_read_word
*
* Description:
* Read an 8-, 16-, or 32-bt bit value from FT80X memory
*
* For SPI memory read transaction, the host sends two zero bits, followed
* by the 22-bit address. This is followed by a dummy byte. After the dummy
* byte, the FT80x responds to each host byte with read data bytes.
*
****************************************************************************/
uint8_t ft80x_read_byte(FAR struct ft80x_dev_s *priv, uint32_t addr)
{
uint8_t data;
ft80x_read_memory(priv, addr, (FAR void *)&data, 1);
return data;
}
uint16_t ft80x_read_hword(FAR struct ft80x_dev_s *priv, uint32_t addr)
{
uint16_t data;
ft80x_read_memory(priv, addr, (FAR void *)&data, 2);
return data;
}
uint32_t ft80x_read_word(FAR struct ft80x_dev_s *priv, uint32_t addr)
{
uint32_t data;
ft80x_read_memory(priv, addr, (FAR void *)&data, 4);
return data;
}
/****************************************************************************
* Name: ft80x_write_memory
*
* Description:
* Write to FT80X memory
*
* For SPI memory write transaction, the host sends a '1' bit and '0' bit,
* followed by the 22-bit address. This is followed by the write data.
*
****************************************************************************/
void ft80x_write_memory(FAR struct ft80x_dev_s *priv, uint32_t addr,
FAR const void *buffer, size_t buflen)
{
struct ft80x_spiwrite_s spiwrite;
DEBUGASSERT(priv != NULL && (addr & 0xffc00000) == 0 &&
buffer != NULL && bulen > 0);
/* Format the write header */
spiwrite.addrh = 0x80 | ((addr >> 16) & 0x3f);
spiwrite.addrm = (addr >> 8) & 0xff;
spiwrite.addrl = addr & 0xff;
/* Select the FT80x */
ft80x_select(priv);
/* Send the write header */
SPI_SNDBLOCK(priv->spi, &spiwrite, sizeof(struct ft80x_spiwrite_s));
/* Then write to the FT80x memory from the user provided buffer */
SPI_SNDBLOCK(priv->spi, buffer, buflen);
/* De-select the FT80x */
ft80x_deselect(priv);
}
/****************************************************************************
* Name: ft80x_write_byte, ft80x_write_hword, ft80x_write_word
*
* Description:
* Write an 8-, 16-, or 32-bt bit value to FT80X memory
*
* For SPI memory write transaction, the host sends a '1' bit and '0' bit,
* followed by the 22-bit address. This is followed by the write data.
*
****************************************************************************/
void ft80x_write_byte(FAR struct ft80x_dev_s *priv, uint32_t addr,
uint8_t data)
{
struct ft80x_spiwrite8_s spiwrite;
DEBUGASSERT(priv != NULL && (addr & 0xffc00000) == 0);
/* Format the write header */
spiwrite.addrh = 0x80 | ((addr >> 16) & 0x3f);
spiwrite.addrm = (addr >> 8) & 0xff;
spiwrite.addrl = addr & 0xff;
spiwrite.data = data;
/* Select the FT80x */
ft80x_select(priv);
/* Send the write header and 8-bit data */
SPI_SNDBLOCK(priv->spi, &spiwrite, sizeof(struct ft80x_spiwrite8_s));
/* De-select the FT80x */
ft80x_deselect(priv);
}
void ft80x_write_hword(FAR struct ft80x_dev_s *priv, uint32_t addr,
uint16_t data)
{
struct ft80x_spiwrite16_s spiwrite;
DEBUGASSERT(priv != NULL && (addr & 0xffc00000) == 0);
/* Format the write header */
spiwrite.addrh = 0x80 | ((addr >> 16) & 0x3f);
spiwrite.addrm = (addr >> 8) & 0xff;
spiwrite.addrl = addr & 0xff;
spiwrite.data[0] = data & 0xff; /* Little endian */
spiwrite.data[1] = (data >> 8) & 0xff;
/* Select the FT80x */
ft80x_select(priv);
/* Send the write header and 16-bit data */
SPI_SNDBLOCK(priv->spi, &spiwrite, sizeof(struct ft80x_spiwrite16_s));
/* De-select the FT80x */
ft80x_deselect(priv);
}
void ft80x_write_word(FAR struct ft80x_dev_s *priv, uint32_t addr,
uint32_t data)
{
struct ft80x_spiwrite32_s spiwrite;
DEBUGASSERT(priv != NULL && (addr & 0xffc00000) == 0);
/* Format the write header */
spiwrite.addrh = 0x80 | ((addr >> 16) & 0x3f);
spiwrite.addrm = (addr >> 8) & 0xff;
spiwrite.addrl = addr & 0xff;
spiwrite.data[0] = data & 0xff; /* Little endian */
spiwrite.data[1] = (data >> 8) & 0xff;
spiwrite.data[2] = (data >> 16) & 0xff;
spiwrite.data[3] = (data >> 24) & 0xff;
/* Select the FT80x */
ft80x_select(priv);
/* Send the write header and 32-bit data */
SPI_SNDBLOCK(priv->spi, &spiwrite, sizeof(struct ft80x_spiwrite32_s));
/* De-select the FT80x */
ft80x_deselect(priv);
}
#endif /* CONFIG_LCD_FT80X && CONFIG_LCD_FT80X_SPI */

View File

@ -266,9 +266,8 @@ static int pwm_close(FAR struct file *filep)
lower->ops->shutdown(lower);
}
ret = OK;
//errout_with_sem:
ret = OK;
nxsem_post(&upper->exclsem);
errout:

View File

@ -1,7 +1,8 @@
/****************************************************************************
* include/nuttx/fs/ioctl.h
*
* Copyright (C) 2008, 2009, 2011-2014, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2008, 2009, 2011-2014, 2017-2018 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -67,29 +68,30 @@
#define _BATIOCBASE (0x0e00) /* Battery driver ioctl commands */
#define _QEIOCBASE (0x0f00) /* Quadrature encoder ioctl commands */
#define _AUDIOIOCBASE (0x1000) /* Audio ioctl commands */
#define _SLCDIOCBASE (0x1100) /* Segment LCD ioctl commands */
#define _WLIOCBASE (0x1200) /* Wireless modules ioctl network commands */
#define _WLCIOCBASE (0x1300) /* Wireless modules ioctl character driver commands */
#define _CFGDIOCBASE (0x1400) /* Config Data device (app config) ioctl commands */
#define _TCIOCBASE (0x1500) /* Timer ioctl commands */
#define _JOYBASE (0x1600) /* Joystick ioctl commands */
#define _PIPEBASE (0x1700) /* FIFO/pipe ioctl commands */
#define _RTCBASE (0x1800) /* RTC ioctl commands */
#define _RELAYBASE (0x1900) /* Relay devices ioctl commands */
#define _CANBASE (0x1a00) /* CAN ioctl commands */
#define _BTNBASE (0x1b00) /* Button ioctl commands */
#define _ULEDBASE (0x1c00) /* User LED ioctl commands */
#define _ZCBASE (0x1d00) /* Zero Cross ioctl commands */
#define _LOOPBASE (0x1e00) /* Loop device commands */
#define _MODEMBASE (0x1f00) /* Modem ioctl commands */
#define _I2CBASE (0x2000) /* I2C driver commands */
#define _SPIBASE (0x2100) /* SPI driver commands */
#define _GPIOBASE (0x2200) /* GPIO driver commands */
#define _CLIOCBASE (0x2300) /* Contactless modules ioctl commands */
#define _USBCBASE (0x2400) /* USB-C controller ioctl commands */
#define _MAC802154BASE (0x2500) /* 802.15.4 MAC ioctl commands */
#define _PWRBASE (0x2600) /* Power-related ioctl commands */
#define _FBIOCBASE (0x2700) /* Frame buffer character driver ioctl commands */
#define _LCDIOCBASE (0x1100) /* LCD character driver ioctl commands */
#define _SLCDIOCBASE (0x1200) /* Segment LCD ioctl commands */
#define _WLIOCBASE (0x1300) /* Wireless modules ioctl network commands */
#define _WLCIOCBASE (0x1400) /* Wireless modules ioctl character driver commands */
#define _CFGDIOCBASE (0x1500) /* Config Data device (app config) ioctl commands */
#define _TCIOCBASE (0x1600) /* Timer ioctl commands */
#define _JOYBASE (0x1700) /* Joystick ioctl commands */
#define _PIPEBASE (0x1800) /* FIFO/pipe ioctl commands */
#define _RTCBASE (0x1900) /* RTC ioctl commands */
#define _RELAYBASE (0x1a00) /* Relay devices ioctl commands */
#define _CANBASE (0x1b00) /* CAN ioctl commands */
#define _BTNBASE (0x1c00) /* Button ioctl commands */
#define _ULEDBASE (0x1d00) /* User LED ioctl commands */
#define _ZCBASE (0x1e00) /* Zero Cross ioctl commands */
#define _LOOPBASE (0x1f00) /* Loop device commands */
#define _MODEMBASE (0x2000) /* Modem ioctl commands */
#define _I2CBASE (0x2100) /* I2C driver commands */
#define _SPIBASE (0x2200) /* SPI driver commands */
#define _GPIOBASE (0x2300) /* GPIO driver commands */
#define _CLIOCBASE (0x2400) /* Contactless modules ioctl commands */
#define _USBCBASE (0x2500) /* USB-C controller ioctl commands */
#define _MAC802154BASE (0x2600) /* 802.15.4 MAC ioctl commands */
#define _PWRBASE (0x2700) /* Power-related ioctl commands */
#define _FBIOCBASE (0x2800) /* Frame buffer character driver ioctl commands */
/* boardctl() commands share the same number space */
@ -307,6 +309,12 @@
#define _AUDIOIOCVALID(c) (_IOC_TYPE(c)==_AUDIOIOCBASE)
#define _AUDIOIOC(nr) _IOC(_AUDIOIOCBASE,nr)
/* LCD character driver ioctl definitions ***********************************/
/* (see nuttx/include/lcd/slcd_codec.h */
#define _LCDIOCVALID(c) (_IOC_TYPE(c)==_LCDIOCBASE)
#define _LCDIOC(nr) _IOC(_LCDIOCBASE,nr)
/* Segment LCD driver ioctl definitions *************************************/
/* (see nuttx/include/lcd/slcd_codec.h */

1056
include/nuttx/lcd/ft80x.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
/************************************************************************************
* include/nuttx/input/slcd_ioctl.h
* IOCTL commands for segment LCDs
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __INCLUDE_NUTTX_INPUT_LCD_IOCTL_H
#define __INCLUDE_NUTTX_INPUT_LCD_IOCTL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/fs/ioctl.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* IOCTL commands set aside for FT80x character driver */
#define FT80X_NIOCTL_CMDS 3
#define FT80X_NIOCTL_BASE 0x0001
#endif /* __INCLUDE_NUTTX_INPUT_LCD_IOCTL_H */