1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Driver for 128x64 pixel display based on the ST7565 LCD controller.
10 This driver is based on the ST7565 Library from Limor Fried
11 (Adafruit Industries) at: http://github.com/adafruit/ST7565-LCD/
15 Software License Agreement (BSD License)
17 Copyright (c) 2010, microBuilder SARL
20 Redistribution and use in source and binary forms, with or without
21 modification, are permitted provided that the following conditions are met:
22 1. Redistributions of source code must retain the above copyright
23 notice, this list of conditions and the following disclaimer.
24 2. Redistributions in binary form must reproduce the above copyright
25 notice, this list of conditions and the following disclaimer in the
26 documentation and/or other materials provided with the distribution.
27 3. Neither the name of the copyright holders nor the
28 names of its contributors may be used to endorse or promote products
29 derived from this software without specific prior written permission.
31 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
32 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
35 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 /**************************************************************************/
47 #include "core/gpio/gpio.h"
48 #include "core/systick/systick.h"
49 #include "drivers/displays/smallfonts.h"
51 void sendByte(uint8_t byte
);
53 #define CMD(c) do { gpioSetValue( ST7565_A0_PORT, ST7565_A0_PIN, 0 ); sendByte( c ); } while (0);
54 #define DATA(d) do { gpioSetValue( ST7565_A0_PORT, ST7565_A0_PIN, 1 ); sendByte( d ); } while (0);
55 #define DELAY(mS) do { systickDelay( mS / CFG_SYSTICK_DELAY_IN_MS ); } while(0);
57 uint8_t _st7565buffer
[128*64/8];
59 /**************************************************************************/
61 /**************************************************************************/
63 /**************************************************************************/
65 @brief Renders the buffer contents
68 Pointer to the buffer containing the raw pixel data
70 /**************************************************************************/
71 void writeBuffer(uint8_t *buffer
)
74 int pagemap
[] = { 3, 2, 1, 0, 7, 6, 5, 4 };
76 for(p
= 0; p
< 8; p
++)
78 CMD(ST7565_CMD_SET_PAGE
| pagemap
[p
]);
79 CMD(ST7565_CMD_SET_COLUMN_LOWER
| (0x0 & 0xf));
80 CMD(ST7565_CMD_SET_COLUMN_UPPER
| ((0x0 >> 4) & 0xf));
84 for(c
= 0; c
< 128; c
++)
86 DATA(buffer
[(128*p
)+c
]);
91 /**************************************************************************/
93 @brief Simulates an SPI write using GPIO
98 /**************************************************************************/
99 void sendByte(uint8_t byte
)
103 // Note: This code can be optimised to avoid the branches by setting
104 // GPIO registers directly, but we'll leave it as is for the moment
105 // for simplicity sake
107 // Make sure clock pin starts high
108 gpioSetValue(ST7565_SCLK_PORT
, ST7565_SCLK_PIN
, 1);
110 // Write from MSB to LSB
114 gpioSetValue(ST7565_SCLK_PORT
, ST7565_SCLK_PIN
, 0);
115 // Set data pin high or low depending on the value of the current bit
116 gpioSetValue(ST7565_SDAT_PORT
, ST7565_SDAT_PIN
, byte
& (1 << i
) ? 1 : 0);
117 // Set clock pin high
118 gpioSetValue(ST7565_SCLK_PORT
, ST7565_SCLK_PIN
, 1);
122 /**************************************************************************/
124 @brief Draws a single graphic character using the supplied font
126 /**************************************************************************/
127 void drawChar(uint16_t x
, uint16_t y
, uint8_t c
, struct FONT_DEF font
)
129 uint8_t col
, column
[font
.u8Width
];
131 // Check if the requested character is available
132 if ((c
>= font
.u8FirstChar
) && (c
<= font
.u8LastChar
))
134 // Retrieve appropriate columns from font data
135 for (col
= 0; col
< font
.u8Width
; col
++)
137 column
[col
] = font
.au8FontTable
[((c
- font
.u8FirstChar
) * font
.u8Width
) + col
]; // Get first column of appropriate character
142 // Requested character is not available in this font ... send a space instead
143 for (col
= 0; col
< font
.u8Width
; col
++)
145 column
[col
] = 0xFF; // Send solid space
149 // Render each column
150 uint16_t xoffset
, yoffset
;
151 for (xoffset
= 0; xoffset
< font
.u8Width
; xoffset
++)
153 for (yoffset
= 0; yoffset
< (font
.u8Height
+ 1); yoffset
++)
156 bit
= (column
[xoffset
] << (8 - (yoffset
+ 1))); // Shift current row bit left
157 bit
= (bit
>> 7); // Shift current row but right (results in 0x01 for black, and 0x00 for white)
160 st7565DrawPixel(x
+ xoffset
, y
+ yoffset
);
166 /**************************************************************************/
168 /**************************************************************************/
170 /**************************************************************************/
172 @brief Initialises the ST7565 LCD display
174 /**************************************************************************/
175 void st7565Init(void)
177 // Note: This can be optimised to set all pins to output and high
178 // in two commands by manipulating the registers directly (assuming
179 // that the pins are located in the same GPIO bank). The code is left
180 // as is for clarity sake in case the pins are not all located in the
183 // Set clock pin to output and high
184 gpioSetDir(ST7565_SCLK_PORT
, ST7565_SCLK_PIN
, 1);
185 gpioSetValue(ST7565_SCLK_PORT
, ST7565_SCLK_PIN
, 1);
187 // Set data pin to output and high
188 gpioSetDir(ST7565_SDAT_PORT
, ST7565_SDAT_PIN
, 1);
189 gpioSetValue(ST7565_SDAT_PORT
, ST7565_SDAT_PIN
, 1);
191 // Configure backlight pin to output and set high (off)
192 gpioSetDir(ST7565_BL_PORT
, ST7565_BL_PIN
, 1);
193 gpioSetValue(ST7565_BL_PORT
, ST7565_BL_PIN
, 1);
195 // Configure A0 pin to output and set high
196 gpioSetDir(ST7565_A0_PORT
, ST7565_A0_PIN
, 1);
197 gpioSetValue(ST7565_A0_PORT
, ST7565_A0_PIN
, 1);
199 // Configure Reset pin and set high
200 gpioSetDir(ST7565_RST_PORT
, ST7565_RST_PIN
, 1);
201 gpioSetValue(ST7565_RST_PORT
, ST7565_RST_PIN
, 1);
203 // Configure select pin and set high
204 gpioSetDir(ST7565_CS_PORT
, ST7565_CS_PIN
, 1);
205 gpioSetValue(ST7565_CS_PORT
, ST7565_CS_PIN
, 1);
208 gpioSetValue(ST7565_CS_PORT
, ST7565_CS_PIN
, 0); // Set CS low
209 gpioSetValue(ST7565_RST_PORT
, ST7565_RST_PIN
, 0); // Set reset low
210 DELAY(500 / CFG_SYSTICK_DELAY_IN_MS
); // Wait 500mS
211 gpioSetValue(ST7565_RST_PORT
, ST7565_RST_PIN
, 1); // Set reset high
214 CMD(ST7565_CMD_SET_BIAS_7
); // LCD Bias Select
215 CMD(ST7565_CMD_SET_ADC_NORMAL
); // ADC Select
216 CMD(ST7565_CMD_SET_COM_NORMAL
); // SHL Select
217 CMD(ST7565_CMD_SET_DISP_START_LINE
); // Initial Display Line
218 CMD(ST7565_CMD_SET_POWER_CONTROL
| 0x04); // Turn on voltage converter (VC=1, VR=0, VF=0)
219 DELAY(50 / CFG_SYSTICK_DELAY_IN_MS
); // Wait 50mS
220 CMD(ST7565_CMD_SET_POWER_CONTROL
| 0x06); // Turn on voltage regulator (VC=1, VR=1, VF=0)
221 DELAY(50 / CFG_SYSTICK_DELAY_IN_MS
); // Wait 50mS
222 CMD(ST7565_CMD_SET_POWER_CONTROL
| 0x07); // Turn on voltage follower
223 DELAY(10 / CFG_SYSTICK_DELAY_IN_MS
); // Wait 10mS
224 CMD(ST7565_CMD_SET_RESISTOR_RATIO
| 0x6); // Set LCD operating voltage
227 CMD(ST7565_CMD_DISPLAY_ON
);
228 CMD(ST7565_CMD_SET_ALLPTS_NORMAL
);
229 st7565SetBrightness(0x18);
232 /**************************************************************************/
234 @brief Enables or disables the backlight
236 /**************************************************************************/
237 void st7565Backlight(bool state
)
239 gpioSetValue( ST7565_BL_PORT
, ST7565_BL_PIN
, state
? 0 : 1 );
242 /**************************************************************************/
244 @brief Sets the display brightness
246 /**************************************************************************/
247 void st7565SetBrightness(uint8_t val
)
249 CMD(ST7565_CMD_SET_VOLUME_FIRST
);
250 CMD(ST7565_CMD_SET_VOLUME_SECOND
| (val
& 0x3f));
253 /**************************************************************************/
255 @brief Clears the screen
257 /**************************************************************************/
258 void st7565ClearScreen(void)
260 memset(&_st7565buffer
, 0x00, 128*64/8);
263 /**************************************************************************/
265 @brief Renders the contents of the pixel buffer on the LCD
267 /**************************************************************************/
268 void st7565Refresh(void)
270 writeBuffer(_st7565buffer
);
273 /**************************************************************************/
275 @brief Draws a single pixel in image buffer
278 The x position (0..127)
280 The y position (0..63)
282 /**************************************************************************/
283 void st7565DrawPixel(uint8_t x
, uint8_t y
)
285 if ((x
>= 128) || (y
>= 64))
289 _st7565buffer
[x
+ (y
/8)*128] |= (1 << (7-(y
%8)));
292 /**************************************************************************/
294 @brief Clears a single pixel in image buffer
297 The x position (0..127)
299 The y position (0..63)
301 /**************************************************************************/
302 void st7565ClearPixel(uint8_t x
, uint8_t y
)
304 if ((x
>= 128) || (y
>= 64))
308 _st7565buffer
[x
+ (y
/8)*128] &= ~(1 << (7-(y
%8)));
311 /**************************************************************************/
313 @brief Gets the value (1 or 0) of the specified pixel from the buffer
316 The x position (0..127)
318 The y position (0..63)
320 @return 1 if the pixel is enabled, 0 if disabled
322 /**************************************************************************/
323 uint8_t st7565GetPixel(uint8_t x
, uint8_t y
)
325 if ((x
>= 128) || (y
>= 64)) return 0;
326 return _st7565buffer
[x
+ (y
/8)*128] & (1 << (7-(y
%8)));
329 /**************************************************************************/
331 @brief Draws a string using the supplied font data.
334 Starting x co-ordinate
336 Starting y co-ordinate
340 Pointer to the FONT_DEF to use when drawing the string
346 #include "drivers/displays/bitmap/st7565/st7565.h"
347 #include "drivers/displays/smallfonts.h"
349 // Configure the pins and initialise the LCD screen
352 // Enable the backlight
355 // Render some text on the screen with different fonts
356 st7565DrawString(1, 1, "3X6 SYSTEM", Font_System3x6); // 3x6 is UPPER CASE only
357 st7565DrawString(1, 10, "5x8 System", Font_System5x8);
358 st7565DrawString(1, 20, "7x8 System", Font_System7x8);
360 // Refresh the screen to see the results
365 /**************************************************************************/
366 void st7565DrawString(uint16_t x
, uint16_t y
, char* text
, struct FONT_DEF font
)
369 for (l
= 0; l
< strlen(text
); l
++)
371 drawChar(x
+ (l
* (font
.u8Width
+ 1)), y
, text
[l
], font
);
375 /**************************************************************************/
377 @brief Shifts the contents of the frame buffer up the specified
381 The number of pixels to shift the frame buffer up, leaving
382 a blank space at the bottom of the frame buffer x pixels
389 #include "drivers/displays/bitmap/st7565/st7565.h"
390 #include "drivers/displays/smallfonts.h"
392 // Configure the pins and initialise the LCD screen
395 // Enable the backlight
398 // Continually write some text, scrolling upward one line each time
401 // Shift the buffer up 8 pixels (adjust for font-height)
402 st7565ShiftFrameBuffer(8);
403 // Render some text on the screen with different fonts
404 st7565DrawString(1, 56, "INSERT TEXT HERE", Font_System3x6); // 3x6 is UPPER CASE only
405 // Refresh the screen to see the results
407 // Wait a bit before writing the next line
413 /**************************************************************************/
414 void st7565ShiftFrameBuffer( uint8_t height
)
416 if (height
== 0) return;
419 // Clear the entire frame buffer
424 // This is horribly inefficient, but at least easy to understand
425 // In a production environment, this should be significantly optimised
428 for (y
= 0; y
< 64; y
++)
430 for (x
= 0; x
< 128; x
++)
434 // Shift height from further ahead in the buffer
435 st7565GetPixel(x
, y
+ height
) ? st7565DrawPixel(x
, y
) : st7565ClearPixel(x
, y
);
439 // Clear the entire line
440 st7565ClearPixel(x
, y
);