From 92b00e125cf8d7754e12fd05e0a2cdfd6550af07 Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 22 Oct 2013 19:53:39 +1000 Subject: [PATCH] Convert ST7565 driver to new driver format. --- drivers/gdisp/ST7565/board_ST7565_template.h | 108 +++++ drivers/gdisp/ST7565/gdisp_lld.c | 419 +++++++++--------- drivers/gdisp/ST7565/gdisp_lld.mk | 6 +- .../gdisp/ST7565/gdisp_lld_board_template.h | 82 ---- drivers/gdisp/ST7565/gdisp_lld_config.h | 11 +- 5 files changed, 320 insertions(+), 306 deletions(-) create mode 100644 drivers/gdisp/ST7565/board_ST7565_template.h delete mode 100644 drivers/gdisp/ST7565/gdisp_lld_board_template.h diff --git a/drivers/gdisp/ST7565/board_ST7565_template.h b/drivers/gdisp/ST7565/board_ST7565_template.h new file mode 100644 index 00000000..aef6cf2b --- /dev/null +++ b/drivers/gdisp/ST7565/board_ST7565_template.h @@ -0,0 +1,108 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file drivers/gdisp/ST7565/board_ST7565_template.h + * @brief GDISP Graphic Driver subsystem board interface for the ST7565 display. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +/** + * @brief Initialise the board for the display. + * + * @param[in] g The GDisplay structure + * + * @note Set the g->board member to whatever is appropriate. For multiple + * displays this might be a pointer to the appropriate register set. + * + * @notapi + */ +static inline void init_board(GDisplay *g) { + (void) g; +} + +/** + * @brief After the initialisation. + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +/** + * @brief Set or clear the lcd reset pin. + * + * @param[in] g The GDisplay structure + * @param[in] state TRUE = lcd in reset, FALSE = normal operation + * + * @notapi + */ +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + (void) state; +} + +/** + * @brief Take exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void acquire_bus(GDisplay *g) { + (void) g; +} + +/** + * @brief Release exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void release_bus(GDisplay *g) { + (void) g; +} + +/** + * @brief Send a command to the controller. + * + * @param[in] g The GDisplay structure + * @param[in] cmd The command to send * + * + * @notapi + */ +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + (void) g; + (void) cmd; +} + +/** + * @brief Send data to the lcd. + * + * @param[in] g The GDisplay structure + * @param[in] data The data to send + * + * @notapi + */ +static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { + (void) g; + (void) data; + (void) length; +} + +#endif /* _GDISP_LLD_BOARD_H */ +/** @} */ + diff --git a/drivers/gdisp/ST7565/gdisp_lld.c b/drivers/gdisp/ST7565/gdisp_lld.c index 960b1389..bd8c7b74 100644 --- a/drivers/gdisp/ST7565/gdisp_lld.c +++ b/drivers/gdisp/ST7565/gdisp_lld.c @@ -5,265 +5,258 @@ * http://ugfx.org/license.html */ +/** + * @file drivers/gdisp/ST7565/gdisp_lld.c + * @brief GDISP Graphics Driver subsystem low level driver source for the ST7565 display. + */ + #include "gfx.h" -#if GFX_USE_GDISP || defined(__DOXYGEN__) +#if GFX_USE_GDISP +#define GDISP_DRIVER_VMT GDISPVMT_ST7565 +#include "../drivers/gdisp/ST7565/gdisp_lld_config.h" +#include "gdisp/lld/gdisp_lld.h" -/* Include the emulation code for things we don't support */ -#include "gdisp/lld/emulation.c" -#include "st7565.h" -#include "gdisp_lld_board.h" - +#include "board_ST7565.h" /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ #ifndef GDISP_SCREEN_HEIGHT -#define GDISP_SCREEN_HEIGHT 64 + #define GDISP_SCREEN_HEIGHT 64 #endif #ifndef GDISP_SCREEN_WIDTH -#define GDISP_SCREEN_WIDTH 128 + #define GDISP_SCREEN_WIDTH 128 +#endif +#ifndef GDISP_INITIAL_CONTRAST + #define GDISP_INITIAL_CONTRAST 51 +#endif +#ifndef GDISP_INITIAL_BACKLIGHT + #define GDISP_INITIAL_BACKLIGHT 100 #endif -#define GDISP_INITIAL_CONTRAST 0xFF +#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0) + +#include "st7565.h" /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ // Some common routines and macros -#define delay(us) gfxSleepMicroseconds(us) -#define delay_ms(ms) gfxSleepMilliseconds(ms) +#define RAM(g) ((uint8_t *)g->priv) +#define write_cmd2(g, cmd1, cmd2) { write_cmd(g, cmd1); write_cmd(g, cmd2); } +#define write_cmd3(g, cmd1, cmd2, cmd3) { write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); } -// The memory buffer for the display -static uint8_t gdisp_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8]; +// Some common routines and macros +#define delay(us) gfxSleepMicroseconds(us) +#define delay_ms(ms) gfxSleepMilliseconds(ms) -/** Set the display to normal or inverse. - * @param[in] value 0 for normal mode, or 1 for inverse mode. - * @notapi - */ -static void invert_display(uint8_t i) { - write_cmd(i ? ST7565_INVERT_DISPLAY : ST7565_POSITIVE_DISPLAY); -} - -/** Turn the whole display off. - * Sends the display to sleep, but leaves RAM intact. - * @notapi - */ -static void display_off(void) { - write_cmd(ST7565_DISPLAY_OFF); -} - -/** Turn the whole display on. - * Wakes up this display following a sleep() call. - * @notapi - */ -static void display_on(void) { - write_cmd(ST7565_DISPLAY_ON); -} - -/** Set the display contrast. - * @param[in] value The contrast, from 1 to 63. - * @notapi - */ -static void set_contrast(uint8_t value) { - write_cmd(ST7565_CONTRAST); - write_cmd(value & 0x3F); -} - -/** Set the display start line. This is the line at which the display will start rendering. - * @param[in] value A value from 0 to 63 denoting the line to start at. - * @notapi - */ -static void set_display_start_line(unsigned char value) { - write_cmd(ST7565_START_LINE | value); -} - -static void gdisp_lld_display(void) { - uint8_t p; - set_display_start_line(0); - - for (p = 0; p < 8; p++) { - write_cmd(ST7565_PAGE | p); - write_cmd(ST7565_COLUMN_MSB | 0); - write_cmd(ST7565_COLUMN_LSB | 0); - write_cmd(ST7565_RMW); - write_data(&gdisp_buffer[p * GDISP_SCREEN_WIDTH], GDISP_SCREEN_WIDTH); - } -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ +#define xyaddr(x, y) ((x) + ((y)>>3)*GDISP_SCREEN_WIDTH) +#define xybit(y) (1<<((y)&7)) /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ -/* ---- Required Routines ---- */ -/* - The following 2 routines are required. - All other routines are optional. - */ - /** - * @brief Low level GDISP driver initialization. - * - * @notapi + * As this controller can't update on a pixel boundary we need to maintain the + * the entire display surface in memory so that we can do the necessary bit + * operations. Fortunately it is a small display in monochrome. + * 64 * 128 / 8 = 1024 bytes. */ -bool_t gdisp_lld_init(void) { - // Initialize your display - init_board(); - // Hardware reset. - setpin_reset(TRUE); - delay_ms(10); - setpin_reset(FALSE); - delay_ms(1); +LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { + // The private area is the display surface. + g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8); - write_cmd(ST7565_LCD_BIAS_7); - write_cmd(ST7565_ADC_NORMAL); - write_cmd(ST7565_COM_SCAN_INC); - set_display_start_line(0); + // Initialise the board interface + init_board(g); - set_contrast(32); - write_cmd(ST7565_RESISTOR_RATIO | 0x3); + // Hardware reset + setpin_reset(g, TRUE); + gfxSleepMilliseconds(20); + setpin_reset(g, FALSE); + gfxSleepMilliseconds(20); - // turn on voltage converter (VC=1, VR=0, VF=0) - write_cmd(ST7565_POWER_CONTROL | 0x04); - delay_ms(50); - // turn on voltage regulator (VC=1, VR=1, VF=0) - write_cmd(ST7565_POWER_CONTROL | 0x06); - delay_ms(50); - // turn on voltage follower (VC=1, VR=1, VF=1) - write_cmd(ST7565_POWER_CONTROL | 0x07); - delay_ms(50); + acquire_bus(g); - display_on(); - write_cmd(ST7565_ALLON_NORMAL); - invert_display(0);// Disable Inversion of display. + write_cmd(g, ST7565_LCD_BIAS_7); + write_cmd(g, ST7565_ADC_NORMAL); + write_cmd(g, ST7565_COM_SCAN_INC); + write_cmd(g, ST7565_START_LINE | 0); - write_cmd(ST7565_RMW); - gdisp_lld_display(); + write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101); + write_cmd(g, ST7565_RESISTOR_RATIO | 0x3); - // Initialize the GDISP structure - GDISP.Width = GDISP_SCREEN_WIDTH; - GDISP.Height = GDISP_SCREEN_HEIGHT; - GDISP.Orientation = GDISP_ROTATE_0; - GDISP.Powermode = powerOn; - GDISP.Contrast = 50; -#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - GDISP.clipx0 = 0; - GDISP.clipy0 = 0; - GDISP.clipx1 = GDISP.Width; - GDISP.clipy1 = GDISP.Height; -#endif - return TRUE; + // turn on voltage converter (VC=1, VR=0, VF=0) + write_cmd(g, ST7565_POWER_CONTROL | 0x04); + delay_ms(50); + + // turn on voltage regulator (VC=1, VR=1, VF=0) + write_cmd(g, ST7565_POWER_CONTROL | 0x06); + delay_ms(50); + + // turn on voltage follower (VC=1, VR=1, VF=1) + write_cmd(g, ST7565_POWER_CONTROL | 0x07); + delay_ms(50); + + write_cmd(g, ST7565_DISPLAY_ON); + write_cmd(g, ST7565_ALLON_NORMAL); + write_cmd(g, ST7565_POSITIVE_DISPLAY); // Disable Inversion of display. + + write_cmd(g, ST7565_RMW); + + // Finish Init + post_init_board(g); + + // Release the bus + release_bus(g); + + /* Initialise the GDISP structure */ + g->g.Width = GDISP_SCREEN_WIDTH; + g->g.Height = GDISP_SCREEN_HEIGHT; + g->g.Orientation = GDISP_ROTATE_0; + g->g.Powermode = powerOn; + g->g.Backlight = GDISP_INITIAL_BACKLIGHT; + g->g.Contrast = GDISP_INITIAL_CONTRAST; + return TRUE; } -/** - * @brief Draws a pixel on the display. - * - * @param[in] x X location of the pixel - * @param[in] y Y location of the pixel - * @param[in] color The color of the pixel - * - * @notapi - */ -void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) { -#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; +#if GDISP_HARDWARE_FLUSH + LLDSPEC void gdisp_lld_flush(GDisplay *g) { + unsigned p; + + // Don't flush if we don't need it. + if (!(g->flags & GDISP_FLG_NEEDFLUSH)) + return; + + acquire_bus(g); + for (p = 0; p < 8; p++) { + write_cmd(g, ST7565_PAGE | p); + write_cmd(g, ST7565_COLUMN_MSB | 0); + write_cmd(g, ST7565_COLUMN_LSB | 0); + write_cmd(g, ST7565_RMW); + write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH); + } + release_bus(g); + } #endif - if (color == 1) - gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] |= (1<g.Orientation) { + case GDISP_ROTATE_0: + x = g->p.x; + y = g->p.y; + break; + case GDISP_ROTATE_90: + x = g->p.y; + y = GDISP_SCREEN_HEIGHT-1 - g->p.x; + break; + case GDISP_ROTATE_180: + x = GDISP_SCREEN_WIDTH-1 - g->p.x; + y = GDISP_SCREEN_HEIGHT-1 - g->p.y; + break; + case GDISP_ROTATE_270: + x = GDISP_SCREEN_HEIGHT-1 - g->p.y; + y = g->p.x; + break; + } + if (g->p.color != Black) + RAM(g)[xyaddr(x, y)] |= xybit(y); + else + RAM(g)[xyaddr(x, y)] &= ~xybit(y); + g->flags |= GDISP_FLG_NEEDFLUSH; + } +#endif -#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) -/** - * @brief Driver Control - * @details Unsupported control codes are ignored. - * @note The value parameter should always be typecast to (void *). - * @note There are some predefined and some specific to the low level driver. - * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t - * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t - * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver - * that only supports off/on anything other - * than zero is on. - * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. - * GDISP_CONTROL_LLD - Low level driver control constants start at - * this value. - * - * @param[in] what What to do. - * @param[in] value The value to use (always cast to a void *). - * - * @notapi - */ -void gdisp_lld_control(unsigned what, void *value) { - switch(what) { - case GDISP_CONTROL_POWER: - if (GDISP.Powermode == (gdisp_powermode_t)value) - return; +#if GDISP_HARDWARE_PIXELREAD + LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { + coord_t x, y; - switch((gdisp_powermode_t)value) { - case powerOff: - display_off(); - break; - case powerSleep: - display_off(); - break; - case powerDeepSleep: - display_off(); - break; - case powerOn: - display_on(); - break; - default: - return; - } - GDISP.Powermode = (gdisp_powermode_t)value; - return; + switch(g->g.Orientation) { + case GDISP_ROTATE_0: + x = g->p.x; + y = g->p.y; + break; + case GDISP_ROTATE_90: + x = g->p.y; + y = GDISP_SCREEN_HEIGHT-1 - g->p.x; + break; + case GDISP_ROTATE_180: + x = GDISP_SCREEN_WIDTH-1 - g->p.x; + y = GDISP_SCREEN_HEIGHT-1 - g->p.y; + break; + case GDISP_ROTATE_270: + x = GDISP_SCREEN_HEIGHT-1 - g->p.y; + x = g->p.x; + break; + } + return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black; + } +#endif - case GDISP_CONTROL_BACKLIGHT: - set_backlight((uint8_t)(size_t)value); - return; +#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL + LLDSPEC void gdisp_lld_control(GDisplay *g) { + switch(g->p.x) { + case GDISP_CONTROL_POWER: + if (g->g.Powermode == (powermode_t)g->p.ptr) + return; + switch((powermode_t)g->p.ptr) { + case powerOff: + case powerSleep: + case powerDeepSleep: + acquire_bus(g); + write_cmd(g, ST7565_DISPLAY_OFF); + release_bus(g); + break; + case powerOn: + acquire_bus(g); + write_cmd(g, ST7565_DISPLAY_ON); + release_bus(g); + break; + default: + return; + } + g->g.Powermode = (powermode_t)g->p.ptr; + return; - case GDISP_CONTROL_CONTRAST: - if ((unsigned)value > 100) value = (void*)100; - if (GDISP.Contrast == (uint8_t)((float)((size_t)value) * 63.0/100.0)) - return; - set_contrast((uint8_t)((float)((size_t)value) * 63.0/100.0) ); - GDISP.Contrast = (unsigned)value; - return; + case GDISP_CONTROL_ORIENTATION: + if (g->g.Orientation == (orientation_t)g->p.ptr) + return; + switch((orientation_t)g->p.ptr) { + /* Rotation is handled by the drawing routines */ + case GDISP_ROTATE_0: + case GDISP_ROTATE_180: + g->g.Height = GDISP_SCREEN_HEIGHT; + g->g.Width = GDISP_SCREEN_WIDTH; + break; + case GDISP_ROTATE_90: + case GDISP_ROTATE_270: + g->g.Height = GDISP_SCREEN_WIDTH; + g->g.Width = GDISP_SCREEN_HEIGHT; + break; + default: + return; + } + g->g.Orientation = (orientation_t)g->p.ptr; + return; - case GDISP_CONTROL_LLD_FLUSH: - gdisp_lld_display(); - return; - } -} + case GDISP_CONTROL_CONTRAST: + if ((unsigned)g->p.ptr > 100) + g->p.ptr = (void *)100; + acquire_bus(g); + write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F); + release_bus(g); + g->g.Contrast = (unsigned)g->p.ptr; + return; + } + } #endif // GDISP_NEED_CONTROL #endif // GFX_USE_GDISP -/** @} */ - diff --git a/drivers/gdisp/ST7565/gdisp_lld.mk b/drivers/gdisp/ST7565/gdisp_lld.mk index cd925824..cf0896e6 100644 --- a/drivers/gdisp/ST7565/gdisp_lld.mk +++ b/drivers/gdisp/ST7565/gdisp_lld.mk @@ -1,6 +1,2 @@ -# List the required driver. -GFXSRC += $(GFXLIB)/drivers/gdisp/ST7565/gdisp_lld.c - -# Required include directories GFXINC += $(GFXLIB)/drivers/gdisp/ST7565 - +GFXSRC += $(GFXLIB)/drivers/gdisp/ST7565/gdisp_lld.c diff --git a/drivers/gdisp/ST7565/gdisp_lld_board_template.h b/drivers/gdisp/ST7565/gdisp_lld_board_template.h deleted file mode 100644 index 2f40ccc7..00000000 --- a/drivers/gdisp/ST7565/gdisp_lld_board_template.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is subject to the terms of the GFX License. If a copy of - * the license was not distributed with this file, you can obtain one at: - * - * http://ugfx.org/license.html - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/** - * @brief Initialize the board for the display. - * @notes This board definition uses GPIO and assumes exclusive access to these GPIO pins - * @notapi - */ -static inline void init_board(void) { - /* Configure SPI bus here. Up to 10Mhz, SPI Mode = 3 (CPOL = 1, CPHA = 0) */ - /* Configure A0, !CS, !RST pin for output */ -} - -/** - * @brief Set or clear the lcd reset pin. - * @param[in] state TRUE = lcd in reset, FALSE = normal operation - * @notapi - */ -static inline void setpin_reset(bool_t state) { - /* Set !CS to low */ - if (state) { - /* Set !RST to low */ - } else { - /* Set !RST to high */ - } -} - -/** - * @brief Set the lcd back-light level. - * @param[in] percent 0 to 100% - * @notapi - */ -static inline void set_backlight(uint8_t percent) { - -} - -/** - * @brief Take exclusive control of the bus - * @notapi - */ -static inline void acquire_bus(void) { - -} - -/** - * @brief Release exclusive control of the bus - * @notapi - */ -static inline void release_bus(void) { - -} - -/** - * @brief Send command to the display. - * @param[in] cmd The command to send - * @notapi - */ -static inline void write_cmd(uint8_t cmd) { - /* Set A0 to low */ - /* Transmit cmd over SPI */ -} - -/** - * @brief Send data to the display. - * @param[in] data The data to send - * @notapi - */ -static inline void write_data(uint8_t* data, uint16_t length) { - /* Set A0 to high */ - /* Transmit data for length over SPI. DMA is recommended. */ -} - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/ST7565/gdisp_lld_config.h b/drivers/gdisp/ST7565/gdisp_lld_config.h index 8d26a0aa..632dc431 100644 --- a/drivers/gdisp/ST7565/gdisp_lld_config.h +++ b/drivers/gdisp/ST7565/gdisp_lld_config.h @@ -14,13 +14,12 @@ /* Driver hardware support. */ /*===========================================================================*/ -#define GDISP_DRIVER_NAME "ST7565" +#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing +#define GDISP_HARDWARE_DRAWPIXEL TRUE +#define GDISP_HARDWARE_PIXELREAD TRUE +#define GDISP_HARDWARE_CONTROL TRUE -#define GDISP_HARDWARE_CONTROL TRUE - -#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_MONO - -#define GDISP_CONTROL_LLD_FLUSH (GDISP_CONTROL_LLD + 1) +#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_MONO #endif /* GFX_USE_GDISP */