diff --git a/drivers/gdisp/PCD8544/PCD8544.h b/drivers/gdisp/PCD8544/PCD8544.h new file mode 100644 index 00000000..1a269ab4 --- /dev/null +++ b/drivers/gdisp/PCD8544/PCD8544.h @@ -0,0 +1,45 @@ +/* + * 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 _PCD8544_H +#define _PCD8544_H + +#define PCD8544_SET_FUNC 0x20 // Function set +#define PCD8544_H 0x01 +#define PCD8544_V 0x02 +#define PCD8544_PD 0x04 + +#define PCD8544_SET_DISPLAY 0x08 +#define PCD8544_DISPLAY_MODE_BLANK 0x00 // bit D = 0, E = 0 +#define PCD8544_DISPLAY_MODE_FILL 0x01 // bit D = 0, E = 1 +#define PCD8544_DISPLAY_MODE_NORMAL 0x04 // bit D = 1, E = 0 +#define PCD8544_DISPLAY_MODE_INVERT 0x05 // bit D = 1, E = 1 + +#define PCD8544_SET_Y 0x40 // 0 0 1 0 0 Y3 Y2 Y1 Y0 +#define PCD8544_SET_X 0x80 // 0 1 X6 X5 X4 X3 X2 X1 X0 + +// ========================================= + +#define PCD8544_SET_TEMP 0x04 // set temperature coefficient (TCx) +#define PCD8544_TEMP_MODE_0 0x00 // TC1 = 0, TC0 = 0 +#define PCD8544_TEMP_MODE_1 0x01 // TC1 = 0, TC0 = 1 +#define PCD8544_TEMP_MODE_2 0x02 // TC1 = 1, TC0 = 0 +#define PCD8544_TEMP_MODE_3 0x03 // TC1 = 1, TC0 = 1 + +#define PCD8544_SET_BIAS 0x10 // set bias system (BSx) +#define PCD8544_BIAS_MODE_7 0x00 // 1 to 100 +#define PCD8544_BIAS_MODE_6 0x01 // 1 to 80 +#define PCD8544_BIAS_MODE_5 0x02 // 1 to 65 +#define PCD8544_BIAS_MODE_4 0x03 // 1 to 48 +#define PCD8544_BIAS_MODE_3 0x04 // 1 to 40 or 1 to 34 +#define PCD8544_BIAS_MODE_2 0x05 // 1 to 24 +#define PCD8544_BIAS_MODE_1 0x06 // 1 to 18 or 1 to 16 +#define PCD8544_BIAS_MODE_0 0x07 // 1 to 10 or 1 to 9 or 1 to 8 + +#define PCD8544_SET_VOP 0x80 // write VOP to register, 1 VOP6 VOP5 VOP4 VOP3 VOP2 VOP1 VOP0 + +#endif /* _PCD8544_H */ diff --git a/drivers/gdisp/PCD8544/board_PCD8544_template.h b/drivers/gdisp/PCD8544/board_PCD8544_template.h new file mode 100644 index 00000000..08ec130d --- /dev/null +++ b/drivers/gdisp/PCD8544/board_PCD8544_template.h @@ -0,0 +1,43 @@ +/* + * 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 + +static inline void init_board(GDisplay *g) { + (void) g; +} + +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + (void) state; +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; +} + +static inline void release_bus(GDisplay *g) { + (void) g; +} + +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + (void) g; + (void) cmd; +} + +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/PCD8544/driver.mk b/drivers/gdisp/PCD8544/driver.mk new file mode 100644 index 00000000..262550d3 --- /dev/null +++ b/drivers/gdisp/PCD8544/driver.mk @@ -0,0 +1,2 @@ +GFXINC += $(GFXLIB)/drivers/gdisp/PCD8544 +GFXSRC += $(GFXLIB)/drivers/gdisp/PCD8544/gdisp_lld_PCD8544.c diff --git a/drivers/gdisp/PCD8544/gdisp_lld_PCD8544.c b/drivers/gdisp/PCD8544/gdisp_lld_PCD8544.c new file mode 100644 index 00000000..8ebd619a --- /dev/null +++ b/drivers/gdisp/PCD8544/gdisp_lld_PCD8544.c @@ -0,0 +1,233 @@ +/* + * 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 + */ + +#include "gfx.h" + +#if GFX_USE_GDISP + +#define GDISP_DRIVER_VMT GDISPVMT_PCD8544 +#include "drivers/gdisp/PCD8544/gdisp_lld_config.h" +#include "src/gdisp/driver.h" +#include "board_PCD8544.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define GDISP_SCREEN_HEIGHT 48 +#define GDISP_SCREEN_WIDTH 84 + +#define GDISP_INITIAL_CONTRAST 51 +#define GDISP_INITIAL_BACKLIGHT 100 + +#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER << 0) + +#include "drivers/gdisp/PCD8544/PCD8544.h" + +/*===========================================================================*/ +/* Driver local routines . */ +/*===========================================================================*/ + +// Some common routines and macros +#define RAM(g) ((uint8_t *)g->priv) + +#define xyaddr(x, y) ((x) + ((y) >> 3) * GDISP_SCREEN_WIDTH) +#define xybit(y) (1 << ((y) & 7)) + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/* + * 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. + * Display 48 * 84 / 8 = 504 + */ + +#define GDISP_SCREEN_BYTES ((GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT) / 8) + +LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { + // The private area is the display surface. + if (!(g->priv = gfxAlloc(GDISP_SCREEN_BYTES))) + gfxHalt("GDISP PCD8544: Failed to allocate private memory"); + + // Initialise the board interface + init_board(g); + + // Hardware reset + setpin_reset(g, TRUE); + gfxSleepMilliseconds(100); + setpin_reset(g, FALSE); + gfxSleepMilliseconds(100); + + acquire_bus(g); + + write_cmd(g, PCD8544_SET_FUNC | PCD8544_H); + write_cmd(g, PCD8544_SET_TEMP | PCD8544_TEMP_MODE_2); + write_cmd(g, PCD8544_SET_BIAS | PCD8544_BIAS_MODE_4); + write_cmd(g, PCD8544_SET_VOP | (0x40)); + write_cmd(g, PCD8544_SET_FUNC); + write_cmd(g, PCD8544_SET_DISPLAY | PCD8544_DISPLAY_MODE_NORMAL); + write_cmd(g, PCD8544_SET_X); // X = 0 + write_cmd(g, PCD8544_SET_Y); // Y = 0 + + coord_t i; + + for (i = 0; i < GDISP_SCREEN_BYTES; i++) { + write_data(g, 0x00, 1); + } + + // Finish Init + post_init_board(g); + + // Release the bus + release_bus(g); + + /* Turn on the back-light */ + set_backlight(g, GDISP_INITIAL_BACKLIGHT); + + /* 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; +} + +#if GDISP_HARDWARE_FLUSH + LLDSPEC void gdisp_lld_flush(GDisplay *g) { + + // Don't flush if we don't need it. + if (!(g->flags & GDISP_FLG_NEEDFLUSH)) { + return; + } + + acquire_bus(g); + + write_cmd(g, PCD8544_SET_X | 0); // X = 0 + write_cmd(g, PCD8544_SET_Y | 0); // Y = 0 + + coord_t i; + + for (i = 0; i < GDISP_SCREEN_BYTES; i++) { + write_data(g, RAM(g)[i], 1); + } + + release_bus(g); + } +#endif + +#if GDISP_HARDWARE_DRAWPIXEL + LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { + coord_t x, y; + + #if GDISP_NEED_CONTROL + switch(g->g.Orientation) { + default: + case GDISP_ROTATE_0: + x = g->p.x; + y = g->p.y; + break; + case GDISP_ROTATE_90: + x = g->p.y; + y = g->g.Width - g->p.x - 1; + break; + case GDISP_ROTATE_180: + x = g->g.Width - g->p.x - 1; + y = g->g.Height - g->p.y - 1; + break; + case GDISP_ROTATE_270: + x = g->g.Height - g->p.y - 1; + y = g->p.x; + break; + } + #else + x = g->p.x; + y = g->p.y; + #endif + + if (gdispColor2Native(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 + 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: + write_cmd(g, PCD8544_SET_FUNC | PCD8544_PD); + break; + case powerOn: + write_cmd(g, PCD8544_SET_FUNC); + break; + default: + return; + } + g->g.Powermode = (powermode_t)g->p.ptr; + return; + + case GDISP_CONTROL_ORIENTATION: + if (g->g.Orientation == (orientation_t)g->p.ptr) + return; + switch((orientation_t)g->p.ptr) { + case GDISP_ROTATE_0: + case GDISP_ROTATE_180: + if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) { + coord_t tmp; + + tmp = g->g.Width; + g->g.Width = g->g.Height; + g->g.Height = tmp; + } + break; + case GDISP_ROTATE_90: + case GDISP_ROTATE_270: + if (g->g.Orientation == GDISP_ROTATE_0 || g->g.Orientation == GDISP_ROTATE_180) { + coord_t tmp; + + tmp = g->g.Width; + g->g.Width = g->g.Height; + g->g.Height = tmp; + } + break; + default: + return; + } + g->g.Orientation = (orientation_t)g->p.ptr; + return; + + case GDISP_CONTROL_BACKLIGHT: + if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100; + set_backlight(g, (unsigned)g->p.ptr); + g->g.Backlight = (unsigned)g->p.ptr; + return; + + case GDISP_CONTROL_CONTRAST: + if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100; + write_cmd(g, PCD8544_SET_VOP | (unsigned)g->p.ptr); + g->g.Contrast = (unsigned)g->p.ptr; + return; + } + } +#endif + +#endif // GFX_USE_GDISP diff --git a/drivers/gdisp/PCD8544/gdisp_lld_config.h b/drivers/gdisp/PCD8544/gdisp_lld_config.h new file mode 100644 index 00000000..6ad8a571 --- /dev/null +++ b/drivers/gdisp/PCD8544/gdisp_lld_config.h @@ -0,0 +1,28 @@ +/* + * 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_CONFIG_H +#define _GDISP_LLD_CONFIG_H + +#if GFX_USE_GDISP + +/*===========================================================================*/ +/* Driver hardware support. */ +/*===========================================================================*/ + +#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing +#define GDISP_HARDWARE_DRAWPIXEL TRUE +#define GDISP_HARDWARE_CONTROL TRUE + +// Set this to your frame buffer pixel format. +#ifndef GDISP_LLD_PIXELFORMAT + #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO +#endif + +#endif /* GFX_USE_GDISP */ + +#endif /* _GDISP_LLD_CONFIG_H */