From e0a81da777b4dd0dd962e366c61de763ccea510c Mon Sep 17 00:00:00 2001 From: aleph Date: Sat, 23 Oct 2010 16:21:40 +0000 Subject: [PATCH] Add new LCD display driver for ILI9225 based lcds, configured for 4 wire 8-bit serial interface. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4454 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/drv/lcd_ili9225.c | 297 +++++++++++++++++++++++++++++++++++++++ bertos/drv/lcd_ili9225.h | 61 ++++++++ bertos/hw/hw_ili9225.h | 76 ++++++++++ 3 files changed, 434 insertions(+) create mode 100644 bertos/drv/lcd_ili9225.c create mode 100644 bertos/drv/lcd_ili9225.h create mode 100644 bertos/hw/hw_ili9225.h diff --git a/bertos/drv/lcd_ili9225.c b/bertos/drv/lcd_ili9225.c new file mode 100644 index 00000000..51428db6 --- /dev/null +++ b/bertos/drv/lcd_ili9225.c @@ -0,0 +1,297 @@ +/** + * \file + * + * + * \brief ILI9225B 176x220 graphic driver + * + * \author Stefano Fedrigo + * + * Display initialization sequence is based on Atmel's softpack library + * implementation, see license below. + */ + +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * ---------------------------------------------------------------------------- + */ + +#include "lcd_ili9225.h" + +#include "hw/hw_ili9225.h" + +#include +#include +#include + + +static struct Serial *spi; + + +struct lcd_ili9225_reg +{ + uint8_t cmd; // Register index, if 0xFF wait for value ms + uint16_t data; // Register value +}; + +static const struct lcd_ili9225_reg init_seq[] = +{ + {0x01, 0x011c}, // Set SS, SM, GS and NL bits + {0x02, 0x0100}, // Set 1 line inversion + {0x03, 0x1030}, // Entry Mode set GRAM write direction and BGR=1 + {0x08, 0x0808}, // Set BP and FP + {0x0C, 0x0001}, // RGB Input Interface Control: 16-bit RGB interface + {0x0F, 0x0A01}, // Set frame rate: 83Hz + {0x20, LCD_WIDTH}, // Set GRAM Address + {0x21, LCD_HEIGHT}, // Set GRAM Address + + /* power on sequence */ + {0x10, 0x0A00}, // Set asp DSTB,STB + {0x11, 0x1038}, // SET APON PON AON VCI1EN VC + {0xFF, 50}, // Wait 50 ms + + {0x12, 0x1121}, // Internal reference voltage = VCI + {0x13, 0x06CE}, // Set GVDD + {0x14, 0x676F}, // Set VCOMH/VCOML voltage + + // Set gram area + {0x30, 0x0000}, + {0x31, 0x00DB}, + {0x32, 0x0000}, + {0x33, 0x0000}, + {0x34, 0x00DB}, + {0x35, 0x0000}, + {0x36, LCD_WIDTH}, + {0x37, 0x0000}, + {0x38, LCD_HEIGHT}, + {0x39, 0x0000}, + + // Set gamma curve + {0x50, 0x0000}, + {0x51, 0x060A}, + {0x52, 0x0D0A}, + {0x53, 0x0303}, + {0x54, 0x0A0D}, + {0x55, 0x0A06}, + {0x56, 0x0000}, + {0x57, 0x0303}, + {0x58, 0x0000}, + {0x59, 0x0000}, +}; + +static void lcd_cmd(uint8_t cmd) +{ + LCD_CS_LOW(); + LCD_RS_LOW(); + kfile_write(&spi->fd, &cmd, sizeof(cmd)); +} + +static void lcd_data(uint16_t data) +{ + char bytes[2]; + bytes[0] = data >> 8; + bytes[1] = data & 0xFF; + + kfile_flush(&spi->fd); + LCD_RS_HIGH(); + kfile_write(&spi->fd, bytes, 2); + kfile_flush(&spi->fd); + LCD_CS_HIGH(); +} + +static void lcd_regWrite(uint8_t reg, uint16_t data) +{ + lcd_cmd(reg); + lcd_data(data); +} + +static void lcd_startBlit(uint8_t x, uint8_t y, uint8_t width, uint8_t height) +{ + ASSERT((x + width) <= LCD_WIDTH); + ASSERT((y + height) <= LCD_HEIGHT); + + lcd_regWrite(0x36, x + width); + lcd_regWrite(0x37, x); + lcd_regWrite(0x38, y + height); + lcd_regWrite(0x39, y); + + lcd_regWrite(0x20, x); + lcd_regWrite(0x21, y); +} + +/* + * Refresh a raw image on screen + */ +void lcd_ili9225_blitRaw(UNUSED_ARG(const uint8_t *, data), + uint8_t x, uint8_t y, uint8_t width, uint8_t height) +{ + lcd_startBlit(x, y, width, height); + // TODO +} + +/* + * Refresh a bitmap on screen + */ +void lcd_ili9225_blitBitmap(const Bitmap *bm) +{ + //uint16_t lcd_row[bm->width]; + uint8_t mask; + int i, l, r; + + lcd_startBlit(0, 0, bm->width, bm->height); + + for (l = 0; l < bm->height / 8; l++) + { + for (mask = 1; mask; mask <<= 1) + { + for (i = 0; i < bm->width; i++) + { + if (bm->raster[l * bm->width + i] & mask) + lcd_regWrite(0x22, 0xffff); + else + lcd_regWrite(0x22, 0x0000); + } + } + } + + for (r = 0, mask = 1; r < bm->height % 8; r++, mask <<= 1) + { + for (i = 0; i < bm->width; i++) + { + if (bm->raster[l * bm->width + i] & mask) + lcd_regWrite(0x22, 0xffff); + else + lcd_regWrite(0x22, 0x0000); + } + } +} + +/** + * Turn off display. + */ +void lcd_ili9225_off(void) +{ + lcd_regWrite(0x07, 0x0000); +} + +/** + * Turn on display. + */ +void lcd_ili9225_on(void) +{ + lcd_regWrite(0x07, 0x1017); +} + +/** + * Reset display. + */ +static void lcd_reset(void) +{ + LCD_RESET_LOW(); + timer_delay(20); + LCD_RESET_HIGH(); + timer_delay(50); +} + +/** + * Set display backlight intensity. + */ +void lcd_ili9225_backlight(unsigned level) +{ + unsigned i; + + if (level > LCD_BACKLIGHT_MAX) + level = LCD_BACKLIGHT_MAX; + + // Switch off backlight + LCD_BACKLIGHT_LOW(); + timer_delay(1); + + // Set new level + for (i = 0; i <= level; i++) + { + LCD_BACKLIGHT_LOW(); + LCD_BACKLIGHT_LOW(); + LCD_BACKLIGHT_LOW(); + + LCD_BACKLIGHT_HIGH(); + LCD_BACKLIGHT_HIGH(); + LCD_BACKLIGHT_HIGH(); + } +} + +/** + * Display initialization. + */ +void lcd_ili9225_init(struct Serial *_spi) +{ + unsigned i; + + ASSERT(_spi); + spi = _spi; + lcd_ili9225_hw_bus_init(); + + lcd_reset(); + lcd_ili9225_off(); + + for (i = 0; i < countof(init_seq); i++) + { + if (init_seq[i].cmd != 0xFF) + lcd_regWrite(init_seq[i].cmd, init_seq[i].data); + else + timer_delay(init_seq[i].data); + } + + lcd_ili9225_on(); +} diff --git a/bertos/drv/lcd_ili9225.h b/bertos/drv/lcd_ili9225.h new file mode 100644 index 00000000..13e01301 --- /dev/null +++ b/bertos/drv/lcd_ili9225.h @@ -0,0 +1,61 @@ +/** + * \file + * + * + * \brief ILI9225B 176x220 graphic driver + * + * $WIZ$ module_name = "lcd_ili9225" + * $WIZ$ module_hw = "bertos/hw/hw_ili9225.h" + */ + +#ifndef LCD_ILI9225_H +#define LCD_ILI9225_H + +#include /* Bitmap */ + +#include + +#define LCD_WIDTH 176 +#define LCD_HEIGHT 220 +#define LCD_BACKLIGHT_MAX 15 + +// Fwd decl +struct Serial; + +void lcd_ili9225_init(struct Serial *spi); +void lcd_ili9225_on(void); +void lcd_ili9225_off(void); +void lcd_ili9225_backlight(unsigned level); +void lcd_ili9225_blitRaw(const uint8_t *data, + uint8_t x, uint8_t y, uint8_t width, uint8_t height); +void lcd_ili9225_blitBitmap(const Bitmap *bm); + +#endif /* LCD_ILI9225_H */ diff --git a/bertos/hw/hw_ili9225.h b/bertos/hw/hw_ili9225.h new file mode 100644 index 00000000..0a78856f --- /dev/null +++ b/bertos/hw/hw_ili9225.h @@ -0,0 +1,76 @@ +/** + * \file + * + * + * \brief SAM3N-EK: ILI9225B low-level hardware macros + * + * \author Stefano Fedrigo + */ + +#ifndef HW_ILI9225_H +#define HW_ILI9225_H + +#include "cfg/macros.h" /* BV() */ + + +/** + * \name LCD I/O pins/ports + * @{ + */ +#define LCD_CS_PIN 0 /* Implement me! */ +#define LCD_RESET_PIN 0 /* Implement me! */ +#define LCD_RS_PIN 0 /* Implement me! */ +#define LCD_BACKLIGHT_PIN 0 /* Implement me! */ +/*@}*/ + +/** + * \name LCD bus control macros + * @{ + */ +#define LCD_CS_HIGH() do { /* Implement me! */ } while (0) +#define LCD_CS_LOW() do { /* Implement me! */ } while (0) +#define LCD_RESET_HIGH() do { /* Implement me! */ } while (0) +#define LCD_RESET_LOW() do { /* Implement me! */ } while (0) +#define LCD_RS_HIGH() do { /* Implement me! */ } while (0) +#define LCD_RS_LOW() do { /* Implement me! */ } while (0) +#define LCD_BACKLIGHT_HIGH() do { /* Implement me! */ } while (0) +#define LCD_BACKLIGHT_LOW() do { /* Implement me! */ } while (0) +/*@}*/ + +/** + * Setup hardware bus where LCD is connected. + */ +INLINE void lcd_ili9225_hw_bus_init(void) +{ + /* Implement me! */ +} + +#endif /* HW_ILI9225_H */ -- 2.25.1