From e09742633855c6d033f008aba0ee8e30f1384a87 Mon Sep 17 00:00:00 2001 From: resset Date: Tue, 5 Feb 2013 23:39:48 +0100 Subject: [PATCH] SSD2119: first working version of driver It is a mix of barely changed few drivers already present in ChibiOS/GFX project. No other routines than initialization ones were changed. Properly displays "basics" demo. Main features and changes: - Based on SSD1289 and SSD1121 in FSMC mode. - Uses FSMC module. Maybe oneday I will make GPIO version. - LCD backlight PWM input is tied high (no timer yet). - Added ssd2119.h with SSD2119 registers' addresses. - Updated set_cursor and set_viewport functions. Not thoroughly tested, however. - Rewritten GDISP_LLD(init)(void) function. --- drivers/gdisp/SSD2119/gdisp_lld.c | 170 ++++++++++-------- .../SSD2119/gdisp_lld_board_embest_dmstf4bb.h | 84 +++++---- drivers/gdisp/SSD2119/ssd2119.h | 74 ++++++++ 3 files changed, 213 insertions(+), 115 deletions(-) create mode 100644 drivers/gdisp/SSD2119/ssd2119.h diff --git a/drivers/gdisp/SSD2119/gdisp_lld.c b/drivers/gdisp/SSD2119/gdisp_lld.c index eac72d76..f430d669 100644 --- a/drivers/gdisp/SSD2119/gdisp_lld.c +++ b/drivers/gdisp/SSD2119/gdisp_lld.c @@ -30,6 +30,8 @@ #include "hal.h" #include "gfx.h" +#include "ssd2119.h" + #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ @@ -40,10 +42,10 @@ /*===========================================================================*/ #ifndef GDISP_SCREEN_HEIGHT - #define GDISP_SCREEN_HEIGHT 320 + #define GDISP_SCREEN_HEIGHT 240 #endif #ifndef GDISP_SCREEN_WIDTH - #define GDISP_SCREEN_WIDTH 240 + #define GDISP_SCREEN_WIDTH 320 #endif #define GDISP_INITIAL_CONTRAST 50 @@ -56,8 +58,6 @@ #if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD /* Include the user supplied board definitions */ #include "gdisp_lld_board.h" -#elif defined(BOARD_FIREBULL_STM32_F103) - #include "gdisp_lld_board_firebullstm32f103.h" #elif defined(BOARD_EMBEST_DMSTF4BB) #include "gdisp_lld_board_embest_dmstf4bb.h" #else @@ -73,26 +73,26 @@ #define delayms(ms) chThdSleepMilliseconds(ms) static __inline void set_cursor(coord_t x, coord_t y) { - /* Reg 0x004E is an 8 bit value - * Reg 0x004F is 9 bit + /* Reg SSD2119_REG_X_RAM_ADDR is 9 bit value + * Reg SSD2119_REG_Y_RAM_ADDR is an 8 bit * Use a bit mask to make sure they are not set too high */ switch(GDISP.Orientation) { case GDISP_ROTATE_180: - write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-x) & 0x00FF); - write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-y) & 0x01FF); + write_reg(SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - 1 - x) & 0x01FF); + write_reg(SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - 1 - y) & 0x00FF); break; case GDISP_ROTATE_0: - write_reg(0x004e, x & 0x00FF); - write_reg(0x004f, y & 0x01FF); + write_reg(SSD2119_REG_X_RAM_ADDR, x & 0x01FF); + write_reg(SSD2119_REG_Y_RAM_ADDR, y & 0x00FF); break; case GDISP_ROTATE_270: - write_reg(0x004e, y & 0x00FF); - write_reg(0x004f, x & 0x01FF); + write_reg(SSD2119_REG_X_RAM_ADDR, y & 0x01FF); + write_reg(SSD2119_REG_Y_RAM_ADDR, x & 0x00FF); break; case GDISP_ROTATE_90: - write_reg(0x004e, (GDISP_SCREEN_WIDTH - y - 1) & 0x00FF); - write_reg(0x004f, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF); + write_reg(SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - y - 1) & 0x01FF); + write_reg(SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - x - 1) & 0x00FF); break; } } @@ -101,35 +101,35 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) { set_cursor(x, y); - /* Reg 0x44 - Horizontal RAM address position - * Upper Byte - HEA - * Lower Byte - HSA - * 0 <= HSA <= HEA <= 0xEF - * Reg 0x45,0x46 - Vertical RAM address position - * Lower 9 bits gives 0-511 range in each value - * 0 <= Reg(0x45) <= Reg(0x46) <= 0x13F + /* Reg 0x44 - Vertical RAM address position + * Upper Byte - VEA + * Lower Byte - VSA + * 0 <= VSA <= VEA <= 0xEF + * Reg 0x45,0x46 - Horizontal RAM address position + * Lower 9 bits gives 0-511 range in each value, HSA and HEA respectively + * 0 <= HSA <= HEA <= 0x13F */ switch(GDISP.Orientation) { case GDISP_ROTATE_0: - write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (x & 0x00FF)); - write_reg(0x45, y & 0x01FF); - write_reg(0x46, (y+cy-1) & 0x01FF); + write_reg(SSD2119_REG_V_RAM_POS, (((y + cy - 1) << 8) & 0xFF00 ) | (y & 0x00FF)); + write_reg(SSD2119_REG_H_RAM_START, (x & 0x01FF)); + write_reg(SSD2119_REG_H_RAM_END, (x + cx - 1) & 0x01FF); break; case GDISP_ROTATE_270: - write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF)); - write_reg(0x45, x & 0x01FF); - write_reg(0x46, (x+cx-1) & 0x01FF); + write_reg(SSD2119_REG_V_RAM_POS, (((y + cy - 1) << 8) & 0xFF00 ) | (x & 0x00FF)); + write_reg(SSD2119_REG_H_RAM_START, (y & 0x01FF)); + write_reg(SSD2119_REG_H_RAM_END, (y + cy - 1) & 0x01FF); break; case GDISP_ROTATE_180: - write_reg(0x44, (((GDISP_SCREEN_WIDTH-x-1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (x+cx)) & 0x00FF)); - write_reg(0x45, (GDISP_SCREEN_HEIGHT-(y+cy)) & 0x01FF); - write_reg(0x46, (GDISP_SCREEN_HEIGHT-y-1) & 0x01FF); + write_reg(SSD2119_REG_V_RAM_POS, (((GDISP_SCREEN_HEIGHT - y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (y + cy)) & 0x00FF)); + write_reg(SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (x + cx)) & 0x01FF); + write_reg(SSD2119_REG_H_RAM_END, (GDISP_SCREEN_WIDTH - x - 1) & 0x01FF); break; case GDISP_ROTATE_90: - write_reg(0x44, (((GDISP_SCREEN_WIDTH - y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (y+cy)) & 0x00FF)); - write_reg(0x45, (GDISP_SCREEN_HEIGHT - (x+cx)) & 0x01FF); - write_reg(0x46, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF); + write_reg(SSD2119_REG_V_RAM_POS, (((GDISP_SCREEN_HEIGHT - x - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (x + cx)) & 0x00FF)); + write_reg(SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (y + cy)) & 0x01FF); + write_reg(SSD2119_REG_H_RAM_END, (GDISP_SCREEN_WIDTH - y - 1) & 0x01FF); break; } @@ -171,52 +171,70 @@ bool_t GDISP_LLD(init)(void) { // Get the bus for the following initialisation commands acquire_bus(); - - write_reg(0x0000,0x0001); delay(5); - write_reg(0x0003,0xA8A4); delay(5); - write_reg(0x000C,0x0000); delay(5); - write_reg(0x000D,0x080C); delay(5); - write_reg(0x000E,0x2B00); delay(5); - write_reg(0x001E,0x00B0); delay(5); - write_reg(0x0001,0x2B3F); delay(5); - write_reg(0x0002,0x0600); delay(5); - write_reg(0x0010,0x0000); delay(5); - write_reg(0x0011,0x6070); delay(5); - write_reg(0x0005,0x0000); delay(5); - write_reg(0x0006,0x0000); delay(5); - write_reg(0x0016,0xEF1C); delay(5); - write_reg(0x0017,0x0003); delay(5); - write_reg(0x0007,0x0133); delay(5); - write_reg(0x000B,0x0000); delay(5); - write_reg(0x000F,0x0000); delay(5); - write_reg(0x0041,0x0000); delay(5); - write_reg(0x0042,0x0000); delay(5); - write_reg(0x0048,0x0000); delay(5); - write_reg(0x0049,0x013F); delay(5); - write_reg(0x004A,0x0000); delay(5); - write_reg(0x004B,0x0000); delay(5); - write_reg(0x0044,0xEF00); delay(5); - write_reg(0x0045,0x0000); delay(5); - write_reg(0x0046,0x013F); delay(5); - write_reg(0x0030,0x0707); delay(5); - write_reg(0x0031,0x0204); delay(5); - write_reg(0x0032,0x0204); delay(5); - write_reg(0x0033,0x0502); delay(5); - write_reg(0x0034,0x0507); delay(5); - write_reg(0x0035,0x0204); delay(5); - write_reg(0x0036,0x0204); delay(5); - write_reg(0x0037,0x0502); delay(5); - write_reg(0x003A,0x0302); delay(5); - write_reg(0x003B,0x0302); delay(5); - write_reg(0x0023,0x0000); delay(5); - write_reg(0x0024,0x0000); delay(5); - write_reg(0x0025,0x8000); delay(5); - write_reg(0x004f,0x0000); delay(5); - write_reg(0x004e,0x0000); delay(5); + + write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0001); + delay(5); + write_reg(SSD2119_REG_PWR_CTRL_5, 0x00B2); + delay(5); + write_reg(SSD2119_REG_VCOM_OTP_1, 0x0006); + delay(5); + write_reg(SSD2119_REG_OSC_START, 0x0001); + delay(5); + write_reg(SSD2119_REG_OUTPUT_CTRL, 0x30EF); + delay(5); + write_reg(SSD2119_REG_LCD_DRIVE_AC_CTRL, 0x0600); + delay(5); + write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000); + delay(5); + write_reg(SSD2119_REG_ENTRY_MODE, 0x6830); // ENTRY_MODE_DEFAULT + delay(5); + write_reg(SSD2119_REG_SLEEP_MODE_2, 0x0999); + delay(5); + write_reg(SSD2119_REG_ANALOG_SET, 0x3800); + delay(5); + write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0033); + delay(5); + write_reg(SSD2119_REG_PWR_CTRL_2, 0x0005); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_1, 0x0000); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_2, 0x0303); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_3, 0x0407); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_4, 0x0301); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_5, 0x0301); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_6, 0x0403); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_7, 0x0707); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_8, 0x0400); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_9, 0x0a00); + delay(5); + write_reg(SSD2119_REG_GAMMA_CTRL_10, 0x1000); + delay(5); + write_reg(SSD2119_REG_PWR_CTRL_3, 0x000A); + delay(5); + write_reg(SSD2119_REG_PWR_CTRL_4, 0x2E00); + delay(5); + write_reg(SSD2119_REG_V_RAM_POS, (GDISP_SCREEN_HEIGHT - 1) << 8); + delay(5); + write_reg(SSD2119_REG_H_RAM_START, 0x0000); + delay(5); + write_reg(SSD2119_REG_H_RAM_END, GDISP_SCREEN_WIDTH - 1); + delay(5); + + write_reg(SSD2119_REG_X_RAM_ADDR, 0x00); + delay(5); + write_reg(SSD2119_REG_Y_RAM_ADDR, 0x00); + delay(5); // Release the bus release_bus(); - + /* Turn on the back-light */ set_backlight(GDISP_INITIAL_BACKLIGHT); diff --git a/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h b/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h index 61e4a662..630000fe 100644 --- a/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h +++ b/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h @@ -29,14 +29,12 @@ #ifndef _GDISP_LLD_BOARD_H #define _GDISP_LLD_BOARD_H -#define SET_CS palSetPad(GPIOD, 12); -#define CLR_CS palClearPad(GPIOD, 12); -#define SET_RS palSetPad(GPIOD, 13); -#define CLR_RS palClearPad(GPIOD, 13); -#define SET_WR palSetPad(GPIOD, 14); -#define CLR_WR palClearPad(GPIOD, 14); -#define SET_RD palSetPad(GPIOD, 15); -#define CLR_RD palClearPad(GPIOD, 15); +/* Using FSMC A19 (PE3) as DC */ +#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* DC = 0 */ +#define GDISP_RAM (*((volatile uint16_t *) 0x60100000)) /* DC = 1 */ + +#define SET_RST palSetPad(GPIOD, 3); +#define CLR_RST palClearPad(GPIOD, 3); /** * @brief Initialise the board for the display. @@ -45,20 +43,38 @@ * @notapi */ static __inline void init_board(void) { - palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL); + unsigned char FSMC_Bank; + + /* STM32F2-F4 FSMC init */ + rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0); + + /* set pins to FSMC mode */ + IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) | + (1 << 9) | (1 << 10) | (1 << 14) | (1 << 15), 0}; + + IOBus busE = {GPIOE, (1 << 3) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | + (1 << 13) | (1 << 14) | (1 << 15), 0}; + + /* FSMC is an alternate function 12 (AF12). */ + palSetBusMode(&busD, PAL_MODE_ALTERNATE(12)); + palSetBusMode(&busE, PAL_MODE_ALTERNATE(12)); + + FSMC_Bank = 0; + + /* FSMC timing */ + FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \ + | (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \ + | (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ; + + /* Bank1 NOR/SRAM control register configuration + * This is actually not needed as already set by default after reset */ + FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN; + + /* Display backlight always on. */ palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL); - - // Configure the pins to a well know state - SET_RS; - SET_RD; - SET_WR; - CLR_CS; + palSetPad(GPIOD, 13); } - /** * @brief Set or clear the lcd reset pin. * @@ -67,8 +83,11 @@ static __inline void init_board(void) { * @notapi */ static __inline void setpin_reset(bool_t state) { - (void) state; - /* Nothing to do here - reset pin tied to Vcc */ + if (state) { + CLR_RST; + } else { + SET_RST; + } } /** @@ -85,6 +104,7 @@ static __inline void set_backlight(uint8_t percent) { /** * @brief Take exclusive control of the bus + * @note Not needed, not implemented * * @notapi */ @@ -94,6 +114,7 @@ static __inline void acquire_bus(void) { /** * @brief Release exclusive control of the bus + * @note Not needed, not implemented * * @notapi */ @@ -109,8 +130,7 @@ static __inline void release_bus(void) { * @notapi */ static __inline void write_index(uint16_t index) { - palWritePort(GPIOE, index); - CLR_RS; CLR_WR; SET_WR; SET_RS; + GDISP_REG = index; } /** @@ -121,8 +141,7 @@ static __inline void write_index(uint16_t index) { * @notapi */ static __inline void write_data(uint16_t data) { - palWritePort(GPIOE, data); - CLR_WR; SET_WR; + GDISP_RAM = data; } #if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__) @@ -136,20 +155,7 @@ static __inline void write_data(uint16_t data) { * @notapi */ static __inline uint16_t read_data(void) { - uint16_t value; - - // change pin mode to digital input - palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT); - - CLR_RD; - value = palReadPort(GPIOE); - value = palReadPort(GPIOE); - SET_RD; - - // change pin mode back to digital output - palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL); - - return value; + return GDISP_RAM; } #endif diff --git a/drivers/gdisp/SSD2119/ssd2119.h b/drivers/gdisp/SSD2119/ssd2119.h new file mode 100644 index 00000000..d3eb484e --- /dev/null +++ b/drivers/gdisp/SSD2119/ssd2119.h @@ -0,0 +1,74 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SSD2119_H +#define _SSD2119_H + +/* SSD2119 registers */ + +#define SSD2119_REG_DEVICE_CODE_READ 0x00 +#define SSD2119_REG_OSC_START 0x00 +#define SSD2119_REG_OUTPUT_CTRL 0x01 +#define SSD2119_REG_LCD_DRIVE_AC_CTRL 0x02 +#define SSD2119_REG_PWR_CTRL_1 0x03 +#define SSD2119_REG_DISPLAY_CTRL 0x07 +#define SSD2119_REG_FRAME_CYCLE_CTRL 0x0B +#define SSD2119_REG_PWR_CTRL_2 0x0C +#define SSD2119_REG_PWR_CTRL_3 0x0D +#define SSD2119_REG_PWR_CTRL_4 0x0E +#define SSD2119_REG_GATE_SCAN_START 0x0F +#define SSD2119_REG_SLEEP_MODE_1 0x10 +#define SSD2119_REG_ENTRY_MODE 0x11 +#define SSD2119_REG_SLEEP_MODE_2 0x12 +#define SSD2119_REG_GEN_IF_CTRL 0x15 +#define SSD2119_REG_H_PORCH 0x16 +#define SSD2119_REG_V_PORCH 0x17 +#define SSD2119_REG_PWR_CTRL_5 0x1E +#define SSD2119_REG_UNIFORMITY 0x20 +#define SSD2119_REG_RAM_DATA 0x22 +#define SSD2119_REG_FRAME_FREQ 0x25 +#define SSD2119_REG_ANALOG_SET 0x26 +#define SSD2119_REG_VCOM_OTP_1 0x28 +#define SSD2119_REG_VCOM_OTP_2 0x29 +#define SSD2119_REG_GAMMA_CTRL_1 0x30 +#define SSD2119_REG_GAMMA_CTRL_2 0x31 +#define SSD2119_REG_GAMMA_CTRL_3 0x32 +#define SSD2119_REG_GAMMA_CTRL_4 0x33 +#define SSD2119_REG_GAMMA_CTRL_5 0x34 +#define SSD2119_REG_GAMMA_CTRL_6 0x35 +#define SSD2119_REG_GAMMA_CTRL_7 0x36 +#define SSD2119_REG_GAMMA_CTRL_8 0x37 +#define SSD2119_REG_GAMMA_CTRL_9 0x3A +#define SSD2119_REG_GAMMA_CTRL_10 0x3B +#define SSD2119_REG_V_SCROLL_1 0x41 +#define SSD2119_REG_V_SCROLL_2 0x42 +#define SSD2119_REG_V_RAM_POS 0x44 +#define SSD2119_REG_H_RAM_START 0x45 +#define SSD2119_REG_H_RAM_END 0x46 +#define SSD2119_REG_1_DRV_POS_1 0x48 +#define SSD2119_REG_1_DRV_POS_2 0x49 +#define SSD2119_REG_2_DRV_POS_1 0x4A +#define SSD2119_REG_2_DRV_POS_2 0x4B +#define SSD2119_REG_X_RAM_ADDR 0x4E +#define SSD2119_REG_Y_RAM_ADDR 0x4F + +/* SSD2119 commands */ + +#endif // _SSD2119_H