Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
19941: drivers/lcd: add MCU-driven low-level parallel interface r=benpicco a=gschorcht

### Contribution description

The PR extends the LCD driver by a low-level interface for MCU-driven implementations of the MCU 8080 16-/8-bit parallel interface, allowing the MCU to use special peripherals for the interface, such as the FMC for STM32 MCUs, which is significantly faster than the integrated GPIO-driven parallel interface implementation of the LCD driver.

### Testing procedure

~Once PR RIOT-OS#19938 and PR RIOT-OS#19939 are merged, a PRs for these board can be pushed that allow to test this PR.~

Use either PR RIOT-OS#19943 or PR RIOT-OS#19944 on top of this PR to test, e.g. with PR RIOT-OS#19943:
```
BOARD=stm32f723e-disco make -j8 -C tests/drivers/st77xx flash
```

### Issues/PRs references


Co-authored-by: Gunar Schorcht <[email protected]>
  • Loading branch information
bors[bot] and gschorcht authored Oct 5, 2023
2 parents b8e415c + e0a76c5 commit dd62f41
Show file tree
Hide file tree
Showing 12 changed files with 558 additions and 228 deletions.
123 changes: 119 additions & 4 deletions drivers/include/lcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ void lcd_ll_release(lcd_t *dev);
*
* @param[in] dev device descriptor
* @param[in] cmd command code
* @param[in] data command data to the device
* @param[in] len length of the command data
* @param[in] data command data to the device or NULL for commands without data
* @param[in] len length of the command data or 0 for commands without data
*/
void lcd_ll_write_cmd(lcd_t *dev, uint8_t cmd, const uint8_t *data,
size_t len);
Expand All @@ -279,6 +279,18 @@ void lcd_ll_write_cmd(lcd_t *dev, uint8_t cmd, const uint8_t *data,
* @param[in] len length of the returned data
*/
void lcd_ll_read_cmd(lcd_t *dev, uint8_t cmd, uint8_t *data, size_t len);

/**
* @brief Set the LCD work area
*
* @param[in] dev Pointer to the selected driver
* @param[in] x1 x coordinate of the first corner
* @param[in] x2 x coordinate of the opposite corner
* @param[in] y1 y coordinate of the first corner
* @param[in] y2 y coordinate of the opposite corner
*
*/
void lcd_ll_set_area(lcd_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2);
/** @} */

/**
Expand Down Expand Up @@ -338,8 +350,8 @@ void lcd_pixmap(lcd_t *dev, uint16_t x1, uint16_t x2, uint16_t y1,
*
* @param[in] dev device descriptor
* @param[in] cmd command code
* @param[in] data command data to the device
* @param[in] len length of the command data
* @param[in] data command data to the device or NULL for commands without data
* @param[in] len length of the command data or 0 for commands without data
*/
void lcd_write_cmd(lcd_t *dev, uint8_t cmd, const uint8_t *data,
size_t len);
Expand Down Expand Up @@ -375,6 +387,109 @@ void lcd_invert_on(lcd_t *dev);
void lcd_invert_off(lcd_t *dev);
/** @} */

#if MODULE_LCD_PARALLEL || DOXYGEN
/**
* @name Low-level MCU 8080 8-/16-bit parallel interface
*
* The low-level MCU 8080 8-/16-bit parallel interface (low-level parallel
* interface for short) is used when the LCD device is connected via a parallel
* interface. Either the GPIO-driven low-level parallel interface provided by
* this LCD driver or a low-level parallel interface implemented by the MCU,
* such as the STM32 FMC peripheral, can be used. If the MCU provides its
* own implementation of the low-level parallel interface, it can be used
* by implementing the following low-level parallel interface driver functions,
* enabling the `lcd_parallel_ll_mcu` module and defining the
* @ref lcd_ll_par_driver variable of type @ref lcd_ll_par_driver_t.
*
* @{
*/

/**
* @brief Low-level MCU 8080 8-/16-bit parallel interface driver
*
* If the MCU-driven low-level parallel interface is enabled by
* module `lcd_ll_parallel_mcu`, the implementation of the MCU low-level
* parallel interface has to define a variable @ref lcd_ll_par_driver of this
* type. All or a set of members have to point to the low-level parallel
* interface functions implemented by the MCU. For functions that are not
* implemented by the MCU, the members have to be set to the corresponding
* GPIO-driven low-level parallel interface functions provided by the LCD
* driver.
*/
typedef struct {
/**
* @brief Initialize the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
*/
void (*init)(lcd_t *dev);

/**
* @brief Set the data direction of the low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] output set to output mode if true and to input mode otherwise
*/
void (*set_data_dir)(lcd_t *dev, bool output);

/**
* @brief Write command using the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cmd command
* @param[in] cont operation is continued
*/
void (*cmd_start)(lcd_t *dev, uint8_t cmd, bool cont);

/**
* @brief Write a byte using the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
* @param[in] out byte to be written
*/
void (*write_byte)(lcd_t *dev, bool cont, uint8_t out);

/**
* @brief Read a byte using the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
*
* @return byte read
*/
uint8_t (*read_byte)(lcd_t *dev, bool cont);

#if MODULE_LCD_PARALLEL_16BIT || DOXYGEN
/**
* @brief Write a word using the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
* @param[in] out word to be written
*/
void (*write_word)(lcd_t *dev, bool cont, uint16_t out);

/**
* @brief Read a word using the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
*
* @return word read
*/
uint16_t (*read_word)(lcd_t *dev, bool cont);
#endif
} lcd_ll_par_driver_t;

/**
* @brief Low-level parallel interface driver instance
*/
extern const lcd_ll_par_driver_t lcd_ll_par_driver;

/** @} */
#endif

#ifdef __cplusplus
}
#endif
Expand Down
20 changes: 17 additions & 3 deletions drivers/lcd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ config MODULE_LCD
depends on TEST_KCONFIG
select MODULE_PERIPH_GPIO

if MODULE_LCD

config MODULE_LCD_MULTI_CNTRL
bool
help
Expand All @@ -21,25 +23,31 @@ config MODULE_LCD_SPI
default y if !MODULE_LCD_PARALLEL && !MODULE_LCD_PARALLEL_16BIT
default y if HAVE_LCD_SPI
depends on HAS_PERIPH_SPI
depends on MODULE_LCD
select MODULE_PERIPH_SPI
help
SPI serial interface is used

config MODULE_LCD_PARALLEL
bool
default y if HAVE_LCD_PARALLEL || HAVE_LCD_PARALLEL_16BIT
depends on MODULE_LCD
help
MCU 8080 8-/16-bit parallel interface is used

config MODULE_LCD_PARALLEL_16BIT
bool
default y if HAVE_LCD_PARALLEL_16BIT
depends on MODULE_LCD
help
MCU 8080 16-bit paralell interface is used

config MODULE_LCD_PARALLEL_LL_MCU
bool
default y if HAVE_LCD_PARALLEL_LL_MCU
depends on MODULE_LCD_PARALLEL
help
MCU 8080 8-/16-bit low-level parallel interface is provided by the MCU.

endif

config HAVE_LCD_SPI
bool
help
Expand All @@ -58,6 +66,12 @@ config HAVE_LCD_PARALLEL_16BIT
Indicates that a display with MCU 8080 16-bit parallel interface
is present

config HAVE_LCD_PARALLEL_LL_MCU
bool
help
Indicates that the MCU provides the MCU 8080 8-/16-bit low-level
parallel interface implementation.

menuconfig KCONFIG_USEMODULE_LCD
bool "Configure LCD driver"
depends on USEMODULE_LCD
Expand Down
2 changes: 1 addition & 1 deletion drivers/lcd/Makefile.dep
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FEATURES_REQUIRED += periph_gpio

ifneq (,$(filter lcd_parallel_16bit,$(USEMODULE)))
ifneq (,$(filter lcd_parallel_%,$(USEMODULE)))
USEMODULE += lcd_parallel
endif

Expand Down
1 change: 1 addition & 0 deletions drivers/lcd/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ PSEUDOMODULES += lcd_multi_cntrl
PSEUDOMODULES += lcd_spi
PSEUDOMODULES += lcd_parallel
PSEUDOMODULES += lcd_parallel_16bit
PSEUDOMODULES += lcd_parallel_ll_mcu

USEMODULE_INCLUDES_lcd := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_lcd)
1 change: 1 addition & 0 deletions drivers/lcd/include/lcd_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extern "C" {
*/
#define LCD_CMD_SWRESET 0x01 /**< Software reset */
#define LCD_CMD_RDDIDIF 0x04 /**< Read display ID */
#define LCD_CMD_RDDST 0x09 /**< Read display status */
#define LCD_CMD_SLPIN 0x10 /**< Enter sleep mode */
#define LCD_CMD_SLPOUT 0x11 /**< Sleep out */
#define LCD_CMD_NORON 0x13 /**< Normal display mode on */
Expand Down
100 changes: 100 additions & 0 deletions drivers/lcd/include/lcd_ll_par_gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2023 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

#if !DOXYGEN /* hide from documentation */

/**
* @ingroup drivers_lcd
*
* @brief GPIO-driven low-level parallel interface implementation
*
* @{
* @file
* @author Gunar Schorcht <[email protected]>
*/

#ifndef LCD_LL_PAR_GPIO_H
#define LCD_LL_PAR_GPIO_H

#include <assert.h>

#include "lcd.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Initialize the GPIOs of the GPIO-driven low-level parallel interface
*
* @param[in] dev device descriptor
*/

void lcd_ll_par_gpio_init(lcd_t *dev);

/**
* @brief Set the direction of the data GPIOs of the low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] output set to output mode if true and to input mode otherwise
*/
void lcd_ll_par_gpio_set_data_dir(lcd_t *dev, bool output);

/**
* @brief Write command using the MCU-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cmd command
* @param[in] cont operation is continued
*/
void lcd_ll_par_gpio_cmd_start(lcd_t *dev, uint8_t cmd, bool cont);

/**
* @brief Write a byte to the GPIO-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
* @param[in] out byte to be written
*/
void lcd_ll_par_gpio_write_byte(lcd_t *dev, bool cont, uint8_t out);

/**
* @brief Write a word to the GPIO-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
* @param[in] out word to be written
*/
void lcd_ll_par_gpio_write_word(lcd_t *dev, bool cont, uint16_t out);

/**
* @brief Read a byte from the GPIO-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
*
* @return read byte
*/
uint8_t lcd_ll_par_gpio_read_byte(lcd_t *dev, bool cont);

/**
* @brief Read a word from the GPIO-driven low-level parallel interface
*
* @param[in] dev device descriptor
* @param[in] cont operation is continued
*
* @return read word
*/
uint16_t lcd_ll_par_gpio_read_word(lcd_t *dev, bool cont);

#ifdef __cplusplus
}
#endif
#endif /* LCD_LL_PAR_GPIO_H */
/** @} */
#endif /* !DOXYGEN */
Loading

0 comments on commit dd62f41

Please sign in to comment.