mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/lcd: implement MCU 8080 16-bit parallel mode
This commit is contained in:
parent
8d1a93ab2f
commit
ad604fe6e2
@ -28,9 +28,6 @@
|
||||
* `lcd_parallel` and `lcd_parallel_16bit` modules are enabled at the same time.
|
||||
* In this case, please refer to the notes in @ref lcd_params_t.
|
||||
*
|
||||
* @warning MCU 8080 16-bit parallel interface (module `lcd_parallel_16bit`) is
|
||||
* not supported yet.
|
||||
*
|
||||
* The device requires colors to be send in big endian RGB-565 format. The
|
||||
* @ref CONFIG_LCD_LE_MODE compile time option can switch this, but only use this
|
||||
* when strictly necessary. This option will slow down the driver as it
|
||||
@ -85,6 +82,21 @@ extern "C" {
|
||||
#define LCD_MADCTL_MH 0x04 /**< Horizontal refresh direction */
|
||||
/** @} */
|
||||
|
||||
#if MODULE_LCD_PARALLEL || DOXYGEN
|
||||
/**
|
||||
* @brief Display interface modi
|
||||
*
|
||||
* This enumeration is only needed if the MCU 8080 8-/16-bit interfaces are
|
||||
* enabled by `lcd_parallel` or `lcd_parallel_16bit`. Otherwise the serial
|
||||
* SPI interface is implicitly assumed.
|
||||
*/
|
||||
typedef enum {
|
||||
LCD_IF_SPI, /**< SPI serial interface mode */
|
||||
LCD_IF_PARALLEL_8BIT, /**< MCU 8080 8-bit parallel interface mode */
|
||||
LCD_IF_PARALLEL_16BIT, /**< MCU 8080 16-bit parallel interface mode */
|
||||
} lcd_if_mode_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Device initialization parameters
|
||||
*
|
||||
@ -106,6 +118,7 @@ typedef struct {
|
||||
spi_mode_t spi_mode; /**< SPI mode */
|
||||
#endif
|
||||
#if MODULE_LCD_PARALLEL || DOXYGEN
|
||||
lcd_if_mode_t mode; /**< LCD driver interface mode */
|
||||
/* Interface parameters used for MCU 8080 8-bit parallel interface */
|
||||
gpio_t wrx_pin; /**< pin connected to the WRITE ENABLE line */
|
||||
gpio_t rdx_pin; /**< pin connected to the READ ENABLE line */
|
||||
@ -170,6 +183,9 @@ typedef struct {
|
||||
mutex_t lock; /**< Mutex used to lock the device in
|
||||
MCU 8080 parallel interface mode */
|
||||
#endif
|
||||
#if MODULE_LCD_PARALLEL_16BIT || DOXYGEN
|
||||
bool word_access; /**< indicates that a word access is active */
|
||||
#endif
|
||||
} lcd_t;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||
*/
|
||||
#define LCD_CMD_SWRESET 0x01 /**< Software reset */
|
||||
#define LCD_CMD_RDDIDIF 0x04 /**< Read display ID */
|
||||
#define LCD_CMD_SPLIN 0x10 /**< Enter sleep mode */
|
||||
#define LCD_CMD_SLPIN 0x10 /**< Enter sleep mode */
|
||||
#define LCD_CMD_SLPOUT 0x11 /**< Sleep out */
|
||||
#define LCD_CMD_NORON 0x13 /**< Normal display mode on */
|
||||
#define LCD_CMD_DINVOFF 0x20 /**< Display inversion off */
|
||||
@ -55,6 +55,8 @@ extern "C" {
|
||||
#define LCD_CMD_TEON 0x35 /**< Tearing Effect Line On */
|
||||
#define LCD_CMD_COLMOD 0x3A /**< Interface Pixel Format Set */
|
||||
#define LCD_CMD_PIXSET 0x3A /**< COLMOD: Pixel Format Set */
|
||||
#define LCD_CMD_RAMWRC 0x3c /**< Memory Write Continue */
|
||||
#define LCD_CMD_RAMRDC 0x3e /**< Memory Read Continue */
|
||||
#define LCD_CMD_WRDISBV 0x51 /**< Write Display Brightness */
|
||||
#define LCD_CMD_WRCTRLD 0x53 /**< Write Control Display */
|
||||
#define LCD_CMD_RDCTRLD 0x54 /**< Read Control Display */
|
||||
|
@ -40,10 +40,6 @@
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL)
|
||||
|
||||
#if MODULE_LCD_PARALLEL_16BIT
|
||||
#error "MCU 8080 16-bit parallel interface is not supported yet"
|
||||
#endif
|
||||
|
||||
static void lcd_ll_par_write_byte(lcd_t *dev, bool cont, uint8_t out)
|
||||
{
|
||||
if (gpio_is_valid(dev->params->cs_pin)) {
|
||||
@ -96,18 +92,77 @@ static uint8_t lcd_ll_par_read_byte(lcd_t *dev, bool cont)
|
||||
return in;
|
||||
}
|
||||
|
||||
static void lcd_ll_par_read_bytes(lcd_t *dev, bool cont,
|
||||
void *data, size_t len)
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
|
||||
static void lcd_ll_par_write_word(lcd_t *dev, bool cont, uint16_t out)
|
||||
{
|
||||
assert(len);
|
||||
|
||||
uint8_t *data_in = data;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
data_in[i] = lcd_ll_par_read_byte(dev, i == (len - 1) ? cont : true);
|
||||
if (gpio_is_valid(dev->params->cs_pin)) {
|
||||
gpio_clear(dev->params->cs_pin);
|
||||
}
|
||||
|
||||
gpio_clear(dev->params->wrx_pin);
|
||||
|
||||
gpio_write(dev->params->d0_pin, out & 0x0001);
|
||||
gpio_write(dev->params->d1_pin, out & 0x0002);
|
||||
gpio_write(dev->params->d2_pin, out & 0x0004);
|
||||
gpio_write(dev->params->d3_pin, out & 0x0008);
|
||||
gpio_write(dev->params->d4_pin, out & 0x0010);
|
||||
gpio_write(dev->params->d5_pin, out & 0x0020);
|
||||
gpio_write(dev->params->d6_pin, out & 0x0040);
|
||||
gpio_write(dev->params->d7_pin, out & 0x0080);
|
||||
gpio_write(dev->params->d8_pin, out & 0x0100);
|
||||
gpio_write(dev->params->d9_pin, out & 0x0200);
|
||||
gpio_write(dev->params->d10_pin, out & 0x0400);
|
||||
gpio_write(dev->params->d11_pin, out & 0x0800);
|
||||
gpio_write(dev->params->d12_pin, out & 0x1000);
|
||||
gpio_write(dev->params->d13_pin, out & 0x2000);
|
||||
gpio_write(dev->params->d14_pin, out & 0x4000);
|
||||
gpio_write(dev->params->d15_pin, out & 0x8000);
|
||||
|
||||
gpio_set(dev->params->wrx_pin);
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin) && !cont) {
|
||||
gpio_set(dev->params->cs_pin);
|
||||
};
|
||||
}
|
||||
|
||||
static uint16_t lcd_ll_par_read_word(lcd_t *dev, bool cont)
|
||||
{
|
||||
uint16_t in = 0;
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin)) {
|
||||
gpio_clear(dev->params->cs_pin);
|
||||
}
|
||||
|
||||
gpio_clear(dev->params->rdx_pin);
|
||||
|
||||
in |= gpio_read(dev->params->d0_pin) ? 0x0001 : 0;
|
||||
in |= gpio_read(dev->params->d1_pin) ? 0x0002 : 0;
|
||||
in |= gpio_read(dev->params->d2_pin) ? 0x0004 : 0;
|
||||
in |= gpio_read(dev->params->d3_pin) ? 0x0008 : 0;
|
||||
in |= gpio_read(dev->params->d4_pin) ? 0x0010 : 0;
|
||||
in |= gpio_read(dev->params->d5_pin) ? 0x0020 : 0;
|
||||
in |= gpio_read(dev->params->d6_pin) ? 0x0040 : 0;
|
||||
in |= gpio_read(dev->params->d7_pin) ? 0x0080 : 0;
|
||||
in |= gpio_read(dev->params->d8_pin) ? 0x01000 : 0;
|
||||
in |= gpio_read(dev->params->d9_pin) ? 0x02000 : 0;
|
||||
in |= gpio_read(dev->params->d10_pin) ? 0x0400 : 0;
|
||||
in |= gpio_read(dev->params->d11_pin) ? 0x0800 : 0;
|
||||
in |= gpio_read(dev->params->d12_pin) ? 0x1000 : 0;
|
||||
in |= gpio_read(dev->params->d13_pin) ? 0x2000 : 0;
|
||||
in |= gpio_read(dev->params->d14_pin) ? 0x4000 : 0;
|
||||
in |= gpio_read(dev->params->d15_pin) ? 0x8000 : 0;
|
||||
|
||||
gpio_set(dev->params->rdx_pin);
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin) && !cont) {
|
||||
gpio_set(dev->params->cs_pin);
|
||||
};
|
||||
|
||||
return in;
|
||||
}
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
|
||||
static void lcd_ll_par_write_bytes(lcd_t *dev, bool cont,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
@ -115,11 +170,49 @@ static void lcd_ll_par_write_bytes(lcd_t *dev, bool cont,
|
||||
|
||||
const uint8_t *data_out = data;
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
if (dev->word_access) {
|
||||
/* len has to be a multiple of two for word access */
|
||||
assert((len % 2) == 0);
|
||||
for (size_t i = 0; i < len; i += 2) {
|
||||
/* data[i] is the high byte and data[i+1] is the low byte in BE */
|
||||
uint16_t out_word = (data_out[i] << 8) + data_out[i + 1];
|
||||
lcd_ll_par_write_word(dev, i == (len - 2) ? cont : true, out_word);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
lcd_ll_par_write_byte(dev, i == (len - 1) ? cont : true, data_out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_ll_par_read_bytes(lcd_t *dev, bool cont,
|
||||
void *data, size_t len)
|
||||
{
|
||||
assert(len);
|
||||
|
||||
uint8_t *data_in = data;
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
if (dev->word_access) {
|
||||
/* len has to be a multiple of two for word access */
|
||||
assert((len % 2) == 0);
|
||||
for (size_t i = 0; i < len; i += 2) {
|
||||
uint16_t in_word = lcd_ll_par_read_word(dev, i == (len - 2) ? cont : true);
|
||||
data_in[i] = in_word >> 8; /* data[i] is the high byte in BE */
|
||||
data_in[i + 1] = in_word & 0xff; /* data[i+1] is the low byte in BE */
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
data_in[i] = lcd_ll_par_read_byte(dev, i == (len - 1) ? cont : true);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL) */
|
||||
|
||||
static inline void lcd_ll_write_byte(lcd_t *dev, bool cont, uint8_t data)
|
||||
@ -190,6 +283,18 @@ static inline void lcd_ll_read_bytes(lcd_t *dev, bool cont,
|
||||
gpio_init(dev->params->d5_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d6_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d7_pin, GPIO_IN);
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
if (dev->params->mode == LCD_IF_PARALLEL_16BIT) {
|
||||
gpio_init(dev->params->d8_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d9_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d10_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d11_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d12_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d13_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d14_pin, GPIO_IN);
|
||||
gpio_init(dev->params->d15_pin, GPIO_IN);
|
||||
}
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
|
||||
/* Dummy read */
|
||||
lcd_ll_par_read_byte(dev, true);
|
||||
@ -204,6 +309,18 @@ static inline void lcd_ll_read_bytes(lcd_t *dev, bool cont,
|
||||
gpio_init(dev->params->d5_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d6_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d7_pin, GPIO_OUT);
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
if (dev->params->mode == LCD_IF_PARALLEL_16BIT) {
|
||||
gpio_init(dev->params->d8_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d9_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d10_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d11_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d12_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d13_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d14_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d15_pin, GPIO_OUT);
|
||||
}
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
#else
|
||||
assert(false);
|
||||
#endif
|
||||
@ -217,6 +334,15 @@ static void lcd_ll_cmd_start(lcd_t *dev, uint8_t cmd, bool cont)
|
||||
gpio_clear(dev->params->dcx_pin);
|
||||
lcd_ll_write_byte(dev, cont, cmd);
|
||||
gpio_set(dev->params->dcx_pin);
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
/* only the RAMRD and RAMRDC commands use 16-bit data access */
|
||||
if (((cmd == LCD_CMD_RAMWR) || (cmd == LCD_CMD_RAMWRC) ||
|
||||
(cmd == LCD_CMD_RAMRD) || (cmd == LCD_CMD_RAMRDC)) &&
|
||||
(dev->params->mode == LCD_IF_PARALLEL_16BIT)) {
|
||||
dev->word_access = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lcd_ll_set_area_default(lcd_t *dev, uint16_t x1, uint16_t x2,
|
||||
@ -277,6 +403,11 @@ void lcd_ll_acquire(lcd_t *dev)
|
||||
|
||||
void lcd_ll_release(lcd_t *dev)
|
||||
{
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
/* reset word to byte access */
|
||||
dev->word_access = false;
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_LCD_SPI)
|
||||
if (dev->params->spi != SPI_UNDEF) {
|
||||
/* SPI serial interface is used */
|
||||
@ -307,7 +438,10 @@ void lcd_ll_write_cmd(lcd_t *dev, uint8_t cmd, const uint8_t *data,
|
||||
void lcd_ll_read_cmd(lcd_t *dev, uint8_t cmd, uint8_t *data, size_t len)
|
||||
{
|
||||
assert(len);
|
||||
lcd_ll_cmd_start(dev, cmd, len ? true : false);
|
||||
|
||||
DEBUG("[%s] command 0x%02x (%u) ", __func__, cmd, len);
|
||||
|
||||
lcd_ll_cmd_start(dev, cmd, true);
|
||||
lcd_ll_read_bytes(dev, false, data, len);
|
||||
}
|
||||
|
||||
@ -341,11 +475,6 @@ int lcd_init(lcd_t *dev, const lcd_params_t *params)
|
||||
gpio_init(dev->params->wrx_pin, GPIO_OUT);
|
||||
gpio_set(dev->params->wrx_pin);
|
||||
|
||||
if (gpio_is_valid(dev->params->wrx_pin)) {
|
||||
gpio_init(dev->params->wrx_pin, GPIO_OUT);
|
||||
gpio_set(dev->params->wrx_pin);
|
||||
}
|
||||
|
||||
if (gpio_is_valid(dev->params->rdx_pin)) {
|
||||
gpio_init(dev->params->rdx_pin, GPIO_OUT);
|
||||
gpio_set(dev->params->rdx_pin);
|
||||
@ -367,6 +496,27 @@ int lcd_init(lcd_t *dev, const lcd_params_t *params)
|
||||
gpio_init(dev->params->d5_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d6_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d7_pin, GPIO_OUT);
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
if (dev->params->mode == LCD_IF_PARALLEL_16BIT) {
|
||||
assert(gpio_is_valid(dev->params->d8_pin));
|
||||
assert(gpio_is_valid(dev->params->d9_pin));
|
||||
assert(gpio_is_valid(dev->params->d10_pin));
|
||||
assert(gpio_is_valid(dev->params->d11_pin));
|
||||
assert(gpio_is_valid(dev->params->d12_pin));
|
||||
assert(gpio_is_valid(dev->params->d13_pin));
|
||||
assert(gpio_is_valid(dev->params->d14_pin));
|
||||
assert(gpio_is_valid(dev->params->d15_pin));
|
||||
gpio_init(dev->params->d8_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d9_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d10_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d11_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d12_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d13_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d14_pin, GPIO_OUT);
|
||||
gpio_init(dev->params->d15_pin, GPIO_OUT);
|
||||
}
|
||||
dev->word_access = false;
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
#else
|
||||
assert(false);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user