2 * This file is subject to the terms of the GFX License. If a copy of
3 * the license was not distributed with this file, you can obtain one at:
5 * http://ugfx.org/license.html
12 #define GDISP_DRIVER_VMT GDISPVMT_ST7565_ERGODOX
13 #include "drivers/gdisp/st7565ergodox/gdisp_lld_config.h"
14 #include "src/gdisp/gdisp_driver.h"
16 #include "board_ST7565.h"
18 /*===========================================================================*/
19 /* Driver local definitions. */
20 /*===========================================================================*/
22 #ifndef GDISP_SCREEN_HEIGHT
23 #define GDISP_SCREEN_HEIGHT 32
25 #ifndef GDISP_SCREEN_WIDTH
26 #define GDISP_SCREEN_WIDTH 128
28 #ifndef GDISP_INITIAL_CONTRAST
29 #define GDISP_INITIAL_CONTRAST 0
31 #ifndef GDISP_INITIAL_BACKLIGHT
32 #define GDISP_INITIAL_BACKLIGHT 100
35 #define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0)
37 #include "drivers/gdisp/st7565ergodox/st7565.h"
39 /*===========================================================================*/
40 /* Driver config defaults for backward compatibility. */
41 /*===========================================================================*/
42 #ifndef ST7565_LCD_BIAS
43 #define ST7565_LCD_BIAS ST7565_LCD_BIAS_7
46 #define ST7565_ADC ST7565_ADC_NORMAL
48 #ifndef ST7565_COM_SCAN
49 #define ST7565_COM_SCAN ST7565_COM_SCAN_INC
51 #ifndef ST7565_PAGE_ORDER
52 #define ST7565_PAGE_ORDER 0,1,2,3
55 /*===========================================================================*/
56 /* Driver local functions. */
57 /*===========================================================================*/
61 uint8_t ram[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8];
64 // Some common routines and macros
65 #define PRIV(g) ((PrivData*)g->priv)
66 #define RAM(g) (PRIV(g)->ram)
67 #define write_cmd2(g, cmd1, cmd2) { write_cmd(g, cmd1); write_cmd(g, cmd2); }
68 #define write_cmd3(g, cmd1, cmd2, cmd3) { write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
70 // Some common routines and macros
71 #define delay(us) gfxSleepMicroseconds(us)
72 #define delay_ms(ms) gfxSleepMilliseconds(ms)
74 #define xyaddr(x, y) ((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
75 #define xybit(y) (1<<((y)&7))
77 /*===========================================================================*/
78 /* Driver exported functions. */
79 /*===========================================================================*/
82 * As this controller can't update on a pixel boundary we need to maintain the
83 * the entire display surface in memory so that we can do the necessary bit
84 * operations. Fortunately it is a small display in monochrome.
85 * 64 * 128 / 8 = 1024 bytes.
88 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
89 // The private area is the display surface.
90 g->priv = gfxAlloc(sizeof(PrivData));
91 PRIV(g)->buffer2 = false;
93 // Initialise the board interface
97 setpin_reset(g, TRUE);
98 gfxSleepMilliseconds(20);
99 setpin_reset(g, FALSE);
100 gfxSleepMilliseconds(20);
103 write_cmd(g, ST7565_DISPLAY_OFF);
104 write_cmd(g, ST7565_LCD_BIAS);
105 write_cmd(g, ST7565_ADC);
106 write_cmd(g, ST7565_COM_SCAN);
108 write_cmd(g, ST7565_START_LINE | 0);
110 write_cmd(g, ST7565_RESISTOR_RATIO | 0x6);
112 // turn on voltage converter (VC=1, VR=0, VF=0)
113 write_cmd(g, ST7565_POWER_CONTROL | 0x04);
116 // turn on voltage regulator (VC=1, VR=1, VF=0)
117 write_cmd(g, ST7565_POWER_CONTROL | 0x06);
120 // turn on voltage follower (VC=1, VR=1, VF=1)
121 write_cmd(g, ST7565_POWER_CONTROL | 0x07);
125 write_cmd(g, ST7565_COM_SCAN);
126 write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101);
127 //write_cmd2(g, ST7565_CONTRAST, 0);
128 write_cmd(g, ST7565_DISPLAY_ON);
129 write_cmd(g, ST7565_ALLON_NORMAL);
130 write_cmd(g, ST7565_INVERT_DISPLAY);
132 write_cmd(g, ST7565_RMW);
140 /* Initialise the GDISP structure */
141 g->g.Width = GDISP_SCREEN_WIDTH;
142 g->g.Height = GDISP_SCREEN_HEIGHT;
143 g->g.Orientation = GDISP_ROTATE_0;
144 g->g.Powermode = powerOn;
145 g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
146 g->g.Contrast = GDISP_INITIAL_CONTRAST;
150 #if GDISP_HARDWARE_FLUSH
151 LLDSPEC void gdisp_lld_flush(GDisplay *g) {
154 // Don't flush if we don't need it.
155 if (!(g->flags & GDISP_FLG_NEEDFLUSH))
159 unsigned dstOffset = (PRIV(g)->buffer2 ? 4 : 0);
160 for (p = 0; p < 4; p++) {
161 write_cmd(g, ST7565_PAGE | (p + dstOffset));
162 write_cmd(g, ST7565_COLUMN_MSB | 0);
163 write_cmd(g, ST7565_COLUMN_LSB | 0);
164 write_cmd(g, ST7565_RMW);
165 write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH);
167 unsigned line = (PRIV(g)->buffer2 ? 32 : 0);
168 write_cmd(g, ST7565_START_LINE | line);
169 PRIV(g)->buffer2 = !PRIV(g)->buffer2;
172 g->flags &= ~GDISP_FLG_NEEDFLUSH;
176 #if GDISP_HARDWARE_DRAWPIXEL
177 LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
180 switch(g->g.Orientation) {
186 case GDISP_ROTATE_90:
188 y = GDISP_SCREEN_HEIGHT-1 - g->p.x;
190 case GDISP_ROTATE_180:
191 x = GDISP_SCREEN_WIDTH-1 - g->p.x;
192 y = GDISP_SCREEN_HEIGHT-1 - g->p.y;
194 case GDISP_ROTATE_270:
195 x = GDISP_SCREEN_HEIGHT-1 - g->p.y;
199 if (gdispColor2Native(g->p.color) != Black)
200 RAM(g)[xyaddr(x, y)] |= xybit(y);
202 RAM(g)[xyaddr(x, y)] &= ~xybit(y);
203 g->flags |= GDISP_FLG_NEEDFLUSH;
207 #if GDISP_HARDWARE_PIXELREAD
208 LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
211 switch(g->g.Orientation) {
217 case GDISP_ROTATE_90:
219 y = GDISP_SCREEN_HEIGHT-1 - g->p.x;
221 case GDISP_ROTATE_180:
222 x = GDISP_SCREEN_WIDTH-1 - g->p.x;
223 y = GDISP_SCREEN_HEIGHT-1 - g->p.y;
225 case GDISP_ROTATE_270:
226 x = GDISP_SCREEN_HEIGHT-1 - g->p.y;
230 return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
234 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
235 LLDSPEC void gdisp_lld_control(GDisplay *g) {
237 case GDISP_CONTROL_POWER:
238 if (g->g.Powermode == (powermode_t)g->p.ptr)
240 switch((powermode_t)g->p.ptr) {
245 write_cmd(g, ST7565_DISPLAY_OFF);
250 write_cmd(g, ST7565_DISPLAY_ON);
256 g->g.Powermode = (powermode_t)g->p.ptr;
259 case GDISP_CONTROL_ORIENTATION:
260 if (g->g.Orientation == (orientation_t)g->p.ptr)
262 switch((orientation_t)g->p.ptr) {
263 /* Rotation is handled by the drawing routines */
265 case GDISP_ROTATE_180:
266 g->g.Height = GDISP_SCREEN_HEIGHT;
267 g->g.Width = GDISP_SCREEN_WIDTH;
269 case GDISP_ROTATE_90:
270 case GDISP_ROTATE_270:
271 g->g.Height = GDISP_SCREEN_WIDTH;
272 g->g.Width = GDISP_SCREEN_HEIGHT;
277 g->g.Orientation = (orientation_t)g->p.ptr;
280 case GDISP_CONTROL_CONTRAST:
281 if ((unsigned)g->p.ptr > 100)
282 g->p.ptr = (void *)100;
284 write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F);
286 g->g.Contrast = (unsigned)g->p.ptr;
290 #endif // GDISP_NEED_CONTROL
292 #endif // GFX_USE_GDISP