comparison service/arduinoNode/arduino-libraries/ST7565/ST7565.cpp @ 973:d7e8227fefc5

core files from https://github.com/adafruit/ST7565-LCD Ignore-this: 8dfadccdfb732e632cf7221c2fb527e4 darcs-hash:20150412104320-312f9-b27958020aa66c0bb6e9ba1e26c6900eafba0856
author drewp <drewp@bigasterisk.com>
date Sun, 12 Apr 2015 03:43:20 -0700
parents
children
comparison
equal deleted inserted replaced
972:5f1bbec24d45 973:d7e8227fefc5
1 /*
2 $Id:$
3
4 ST7565 LCD library!
5
6 Copyright (C) 2010 Limor Fried, Adafruit Industries
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 // some of this code was written by <cstone@pobox.com> originally; it is in the public domain.
23 */
24
25 //#include <Wire.h>
26 #include <avr/pgmspace.h>
27 #include <util/delay.h>
28 #include <stdlib.h>
29
30 #include "ST7565.h"
31
32 #define ST7565_STARTBYTES 1
33
34 uint8_t is_reversed = 0;
35
36 // a handy reference to where the pages are on the screen
37 const uint8_t pagemap[] = { 3, 2, 1, 0, 7, 6, 5, 4 };
38
39 // a 5x7 font table
40 const extern uint8_t PROGMEM font[];
41
42 // the memory buffer for the LCD
43 uint8_t st7565_buffer[1024] = {
44 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
45 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
46 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
47 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
48 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
49 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
50 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
51 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
52
53 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
54 0x0, 0x0, 0x0, 0x3, 0x7, 0xF, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7, 0x0, 0x0, 0x0,
55 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
56 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
57 0x0, 0x0, 0x7F, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
58 0x0, 0x0, 0x1F, 0x3F, 0x70, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
59 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x6, 0x0, 0x0, 0x0, 0x3, 0x3,
60 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
61
62 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xF, 0x7, 0x7,
63 0x7, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x0, 0x0,
64 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x3F,
65 0x70, 0x60, 0x60, 0x60, 0x60, 0x30, 0x7F, 0x3F, 0x0, 0x0, 0x1F, 0x3F, 0x70, 0x60, 0x60, 0x60,
66 0x60, 0x39, 0xFF, 0xFF, 0x0, 0x6, 0x1F, 0x39, 0x60, 0x60, 0x60, 0x60, 0x30, 0x3F, 0x7F, 0x0,
67 0x0, 0x60, 0xFF, 0xFF, 0x60, 0x60, 0x0, 0x7F, 0x7F, 0x70, 0x60, 0x60, 0x40, 0x0, 0x7F, 0x7F,
68 0x0, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x60, 0xFF, 0xFF,
69 0x60, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
70
71 0x80, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xE7, 0xE7, 0xE3,
72 0xF3, 0xF9, 0xFF, 0xFF, 0xFF, 0xF7, 0x7, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
73 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x0, 0x0, 0x0, 0xC0,
74 0xE0, 0x60, 0x20, 0x20, 0x60, 0xE0, 0xE0, 0xE0, 0x0, 0x0, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x60,
75 0x60, 0xE0, 0xE0, 0xE0, 0x0, 0x0, 0x80, 0xC0, 0x60, 0x60, 0x20, 0x60, 0x60, 0xE0, 0xE0, 0x0,
76 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xE0,
77 0x60, 0x60, 0x60, 0x60, 0xE0, 0x80, 0x0, 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0xE0, 0xE0,
78 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
79
80 0x0, 0x0, 0x0, 0x3, 0x7, 0x1F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF1, 0xE3,
81 0xE3, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFC, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF,
82 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xE0, 0x80, 0x0, 0x0, 0x0, 0xC,
83 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
84 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
85 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7, 0x0,
86 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0,
87 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
88
89 0x0, 0x7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8,
90 0xF8, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
91 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF,
92 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xE0, 0xC0, 0xC0, 0xC0, 0xFF, 0x7F, 0x0, 0x0, 0x1E, 0x7F,
93 0xE1, 0xC0, 0xC0, 0xC0, 0xC0, 0x61, 0xFF, 0xFF, 0x0, 0x0, 0xFE, 0xFF, 0x1, 0x0, 0x0, 0x0,
94 0xFF, 0xFF, 0x0, 0x0, 0x21, 0xF9, 0xF8, 0xDC, 0xCC, 0xCF, 0x7, 0x0, 0xC0, 0xFF, 0xFF, 0xC0,
95 0x80, 0x0, 0xFF, 0xFF, 0xC0, 0xC0, 0x80, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x1F, 0x7F, 0xF9,
96 0xC8, 0xC8, 0xC8, 0xC8, 0x79, 0x39, 0x0, 0x0, 0x71, 0xF9, 0xD8, 0xCC, 0xCE, 0x47, 0x3, 0x0,
97
98 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
99 0x0, 0x0, 0x0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xC0,
100 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0,
101 0xC0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80,
102 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0,
103 0xC0, 0x80, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0,
104 0x0, 0x0, 0xC0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, 0xC0,
105 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x0, 0x0,
106
107 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
108 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
109 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
110 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
111 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
112 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
113 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
114 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,};
115
116 // reduces how much is refreshed, which speeds it up!
117 // originally derived from Steve Evans/JCW's mod but cleaned up and
118 // optimized
119 #define enablePartialUpdate
120
121 #ifdef enablePartialUpdate
122 static uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax;
123 #endif
124
125
126
127 static void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax) {
128 #ifdef enablePartialUpdate
129 if (xmin < xUpdateMin) xUpdateMin = xmin;
130 if (xmax > xUpdateMax) xUpdateMax = xmax;
131 if (ymin < yUpdateMin) yUpdateMin = ymin;
132 if (ymax > yUpdateMax) yUpdateMax = ymax;
133 #endif
134 }
135
136 void ST7565::drawbitmap(uint8_t x, uint8_t y,
137 const uint8_t *bitmap, uint8_t w, uint8_t h,
138 uint8_t color) {
139 for (uint8_t j=0; j<h; j++) {
140 for (uint8_t i=0; i<w; i++ ) {
141 if (pgm_read_byte(bitmap + i + (j/8)*w) & _BV(j%8)) {
142 my_setpixel(x+i, y+j, color);
143 }
144 }
145 }
146
147 updateBoundingBox(x, y, x+w, y+h);
148 }
149
150 void ST7565::drawstring(uint8_t x, uint8_t line, char *c) {
151 while (c[0] != 0) {
152 drawchar(x, line, c[0]);
153 c++;
154 x += 6; // 6 pixels wide
155 if (x + 6 >= LCDWIDTH) {
156 x = 0; // ran out of this line
157 line++;
158 }
159 if (line >= (LCDHEIGHT/8))
160 return; // ran out of space :(
161 }
162 }
163
164
165 void ST7565::drawstring_P(uint8_t x, uint8_t line, const char *str) {
166 while (1) {
167 char c = pgm_read_byte(str++);
168 if (! c)
169 return;
170 drawchar(x, line, c);
171 x += 6; // 6 pixels wide
172 if (x + 6 >= LCDWIDTH) {
173 x = 0; // ran out of this line
174 line++;
175 }
176 if (line >= (LCDHEIGHT/8))
177 return; // ran out of space :(
178 }
179 }
180
181 void ST7565::drawchar(uint8_t x, uint8_t line, char c) {
182 for (uint8_t i =0; i<5; i++ ) {
183 st7565_buffer[x + (line*128) ] = pgm_read_byte(font+(c*5)+i);
184 x++;
185 }
186
187 updateBoundingBox(x, line*8, x+5, line*8 + 8);
188 }
189
190
191 // bresenham's algorithm - thx wikpedia
192 void ST7565::drawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
193 uint8_t color) {
194 uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
195 if (steep) {
196 swap(x0, y0);
197 swap(x1, y1);
198 }
199
200 if (x0 > x1) {
201 swap(x0, x1);
202 swap(y0, y1);
203 }
204
205 // much faster to put the test here, since we've already sorted the points
206 updateBoundingBox(x0, y0, x1, y1);
207
208 uint8_t dx, dy;
209 dx = x1 - x0;
210 dy = abs(y1 - y0);
211
212 int8_t err = dx / 2;
213 int8_t ystep;
214
215 if (y0 < y1) {
216 ystep = 1;
217 } else {
218 ystep = -1;}
219
220 for (; x0<=x1; x0++) {
221 if (steep) {
222 my_setpixel(y0, x0, color);
223 } else {
224 my_setpixel(x0, y0, color);
225 }
226 err -= dy;
227 if (err < 0) {
228 y0 += ystep;
229 err += dx;
230 }
231 }
232 }
233
234 // filled rectangle
235 void ST7565::fillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
236 uint8_t color) {
237
238 // stupidest version - just pixels - but fast with internal buffer!
239 for (uint8_t i=x; i<x+w; i++) {
240 for (uint8_t j=y; j<y+h; j++) {
241 my_setpixel(i, j, color);
242 }
243 }
244
245 updateBoundingBox(x, y, x+w, y+h);
246 }
247
248 // draw a rectangle
249 void ST7565::drawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
250 uint8_t color) {
251 // stupidest version - just pixels - but fast with internal buffer!
252 for (uint8_t i=x; i<x+w; i++) {
253 my_setpixel(i, y, color);
254 my_setpixel(i, y+h-1, color);
255 }
256 for (uint8_t i=y; i<y+h; i++) {
257 my_setpixel(x, i, color);
258 my_setpixel(x+w-1, i, color);
259 }
260
261 updateBoundingBox(x, y, x+w, y+h);
262 }
263
264 // draw a circle outline
265 void ST7565::drawcircle(uint8_t x0, uint8_t y0, uint8_t r,
266 uint8_t color) {
267 updateBoundingBox(x0-r, y0-r, x0+r, y0+r);
268
269 int8_t f = 1 - r;
270 int8_t ddF_x = 1;
271 int8_t ddF_y = -2 * r;
272 int8_t x = 0;
273 int8_t y = r;
274
275 my_setpixel(x0, y0+r, color);
276 my_setpixel(x0, y0-r, color);
277 my_setpixel(x0+r, y0, color);
278 my_setpixel(x0-r, y0, color);
279
280 while (x<y) {
281 if (f >= 0) {
282 y--;
283 ddF_y += 2;
284 f += ddF_y;
285 }
286 x++;
287 ddF_x += 2;
288 f += ddF_x;
289
290 my_setpixel(x0 + x, y0 + y, color);
291 my_setpixel(x0 - x, y0 + y, color);
292 my_setpixel(x0 + x, y0 - y, color);
293 my_setpixel(x0 - x, y0 - y, color);
294
295 my_setpixel(x0 + y, y0 + x, color);
296 my_setpixel(x0 - y, y0 + x, color);
297 my_setpixel(x0 + y, y0 - x, color);
298 my_setpixel(x0 - y, y0 - x, color);
299
300 }
301
302
303
304 }
305
306 void ST7565::fillcircle(uint8_t x0, uint8_t y0, uint8_t r,
307 uint8_t color) {
308 updateBoundingBox(x0-r, y0-r, x0+r, y0+r);
309
310 int8_t f = 1 - r;
311 int8_t ddF_x = 1;
312 int8_t ddF_y = -2 * r;
313 int8_t x = 0;
314 int8_t y = r;
315
316 for (uint8_t i=y0-r; i<=y0+r; i++) {
317 my_setpixel(x0, i, color);
318 }
319
320 while (x<y) {
321 if (f >= 0) {
322 y--;
323 ddF_y += 2;
324 f += ddF_y;
325 }
326 x++;
327 ddF_x += 2;
328 f += ddF_x;
329
330 for (uint8_t i=y0-y; i<=y0+y; i++) {
331 my_setpixel(x0+x, i, color);
332 my_setpixel(x0-x, i, color);
333 }
334 for (uint8_t i=y0-x; i<=y0+x; i++) {
335 my_setpixel(x0+y, i, color);
336 my_setpixel(x0-y, i, color);
337 }
338 }
339 }
340
341 void ST7565::my_setpixel(uint8_t x, uint8_t y, uint8_t color) {
342 if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
343 return;
344
345 // x is which column
346 if (color)
347 st7565_buffer[x+ (y/8)*128] |= _BV(7-(y%8));
348 else
349 st7565_buffer[x+ (y/8)*128] &= ~_BV(7-(y%8));
350 }
351
352 // the most basic function, set a single pixel
353 void ST7565::setpixel(uint8_t x, uint8_t y, uint8_t color) {
354 if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
355 return;
356
357 // x is which column
358 if (color)
359 st7565_buffer[x+ (y/8)*128] |= _BV(7-(y%8));
360 else
361 st7565_buffer[x+ (y/8)*128] &= ~_BV(7-(y%8));
362
363 updateBoundingBox(x,y,x,y);
364 }
365
366
367 // the most basic function, get a single pixel
368 uint8_t ST7565::getpixel(uint8_t x, uint8_t y) {
369 if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
370 return 0;
371
372 return (st7565_buffer[x+ (y/8)*128] >> (7-(y%8))) & 0x1;
373 }
374
375 void ST7565::begin(uint8_t contrast) {
376 st7565_init();
377 st7565_command(CMD_DISPLAY_ON);
378 st7565_command(CMD_SET_ALLPTS_NORMAL);
379 st7565_set_brightness(contrast);
380 }
381
382 void ST7565::st7565_init(void) {
383 // set pin directions
384 pinMode(sid, OUTPUT);
385 pinMode(sclk, OUTPUT);
386 pinMode(a0, OUTPUT);
387 pinMode(rst, OUTPUT);
388 pinMode(cs, OUTPUT);
389
390 // toggle RST low to reset; CS low so it'll listen to us
391 if (cs > 0)
392 digitalWrite(cs, LOW);
393
394 digitalWrite(rst, LOW);
395 _delay_ms(500);
396 digitalWrite(rst, HIGH);
397
398 // LCD bias select
399 st7565_command(CMD_SET_BIAS_7);
400 // ADC select
401 st7565_command(CMD_SET_ADC_NORMAL);
402 // SHL select
403 st7565_command(CMD_SET_COM_NORMAL);
404 // Initial display line
405 st7565_command(CMD_SET_DISP_START_LINE);
406
407 // turn on voltage converter (VC=1, VR=0, VF=0)
408 st7565_command(CMD_SET_POWER_CONTROL | 0x4);
409 // wait for 50% rising
410 _delay_ms(50);
411
412 // turn on voltage regulator (VC=1, VR=1, VF=0)
413 st7565_command(CMD_SET_POWER_CONTROL | 0x6);
414 // wait >=50ms
415 _delay_ms(50);
416
417 // turn on voltage follower (VC=1, VR=1, VF=1)
418 st7565_command(CMD_SET_POWER_CONTROL | 0x7);
419 // wait
420 _delay_ms(10);
421
422 // set lcd operating voltage (regulator resistor, ref voltage resistor)
423 st7565_command(CMD_SET_RESISTOR_RATIO | 0x6);
424
425 // initial display line
426 // set page address
427 // set column address
428 // write display data
429
430 // set up a bounding box for screen updates
431
432 updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1);
433 }
434
435 inline void ST7565::spiwrite(uint8_t c) {
436 shiftOut(sid, sclk, MSBFIRST, c);
437 /*
438 int8_t i;
439 for (i=7; i>=0; i--) {
440 SCLK_PORT &= ~_BV(SCLK);
441 if (c & _BV(i))
442 SID_PORT |= _BV(SID);
443 else
444 SID_PORT &= ~_BV(SID);
445 SCLK_PORT |= _BV(SCLK);
446 }
447 */
448
449 /*
450 // loop unwrapped! too fast doesnt work :(
451
452 SCLK_PORT &= ~_BV(SCLK);
453 if (c & _BV(7))
454 SID_PORT |= _BV(SID);
455 else
456 SID_PORT &= ~_BV(SID);
457 SCLK_PORT |= _BV(SCLK);
458
459 SCLK_PORT &= ~_BV(SCLK);
460 if (c & _BV(6))
461 SID_PORT |= _BV(SID);
462 else
463 SID_PORT &= ~_BV(SID);
464 SCLK_PORT |= _BV(SCLK);
465
466 SCLK_PORT &= ~_BV(SCLK);
467 if (c & _BV(5))
468 SID_PORT |= _BV(SID);
469 else
470 SID_PORT &= ~_BV(SID);
471 SCLK_PORT |= _BV(SCLK);
472
473 SCLK_PORT &= ~_BV(SCLK);
474 if (c & _BV(4))
475 SID_PORT |= _BV(SID);
476 else
477 SID_PORT &= ~_BV(SID);
478 SCLK_PORT |= _BV(SCLK);
479
480 SCLK_PORT &= ~_BV(SCLK);
481 if (c & _BV(3))
482 SID_PORT |= _BV(SID);
483 else
484 SID_PORT &= ~_BV(SID);
485 SCLK_PORT |= _BV(SCLK);
486
487 SCLK_PORT &= ~_BV(SCLK);
488 if (c & _BV(2))
489 SID_PORT |= _BV(SID);
490 else
491 SID_PORT &= ~_BV(SID);
492 SCLK_PORT |= _BV(SCLK);
493
494
495 SCLK_PORT &= ~_BV(SCLK);
496 if (c & _BV(1))
497 SID_PORT |= _BV(SID);
498 else
499 SID_PORT &= ~_BV(SID);
500 SCLK_PORT |= _BV(SCLK);
501
502 SCLK_PORT &= ~_BV(SCLK);
503 if (c & _BV(0))
504 SID_PORT |= _BV(SID);
505 else
506 SID_PORT &= ~_BV(SID);
507 SCLK_PORT |= _BV(SCLK);
508 */
509
510 }
511 void ST7565::st7565_command(uint8_t c) {
512 digitalWrite(a0, LOW);
513
514 spiwrite(c);
515 }
516
517 void ST7565::st7565_data(uint8_t c) {
518 digitalWrite(a0, HIGH);
519
520 spiwrite(c);
521 }
522 void ST7565::st7565_set_brightness(uint8_t val) {
523 st7565_command(CMD_SET_VOLUME_FIRST);
524 st7565_command(CMD_SET_VOLUME_SECOND | (val & 0x3f));
525 }
526
527
528 void ST7565::display(void) {
529 uint8_t col, maxcol, p;
530
531 /*
532 Serial.print("Refresh ("); Serial.print(xUpdateMin, DEC);
533 Serial.print(", "); Serial.print(xUpdateMax, DEC);
534 Serial.print(","); Serial.print(yUpdateMin, DEC);
535 Serial.print(", "); Serial.print(yUpdateMax, DEC); Serial.println(")");
536 */
537
538 for(p = 0; p < 8; p++) {
539 /*
540 putstring("new page! ");
541 uart_putw_dec(p);
542 putstring_nl("");
543 */
544 #ifdef enablePartialUpdate
545 // check if this page is part of update
546 if ( yUpdateMin >= ((p+1)*8) ) {
547 continue; // nope, skip it!
548 }
549 if (yUpdateMax < p*8) {
550 break;
551 }
552 #endif
553
554 st7565_command(CMD_SET_PAGE | pagemap[p]);
555
556
557 #ifdef enablePartialUpdate
558 col = xUpdateMin;
559 maxcol = xUpdateMax;
560 #else
561 // start at the beginning of the row
562 col = 0;
563 maxcol = LCDWIDTH-1;
564 #endif
565
566 st7565_command(CMD_SET_COLUMN_LOWER | ((col+ST7565_STARTBYTES) & 0xf));
567 st7565_command(CMD_SET_COLUMN_UPPER | (((col+ST7565_STARTBYTES) >> 4) & 0x0F));
568 st7565_command(CMD_RMW);
569
570 for(; col <= maxcol; col++) {
571 //uart_putw_dec(col);
572 //uart_putchar(' ');
573 st7565_data(st7565_buffer[(128*p)+col]);
574 }
575 }
576
577 #ifdef enablePartialUpdate
578 xUpdateMin = LCDWIDTH - 1;
579 xUpdateMax = 0;
580 yUpdateMin = LCDHEIGHT-1;
581 yUpdateMax = 0;
582 #endif
583 }
584
585 // clear everything
586 void ST7565::clear(void) {
587 memset(st7565_buffer, 0, 1024);
588 updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1);
589 }
590
591
592 // this doesnt touch the buffer, just clears the display RAM - might be handy
593 void ST7565::clear_display(void) {
594 uint8_t p, c;
595
596 for(p = 0; p < 8; p++) {
597 /*
598 putstring("new page! ");
599 uart_putw_dec(p);
600 putstring_nl("");
601 */
602
603 st7565_command(CMD_SET_PAGE | p);
604 for(c = 0; c < 129; c++) {
605 //uart_putw_dec(c);
606 //uart_putchar(' ');
607 st7565_command(CMD_SET_COLUMN_LOWER | (c & 0xf));
608 st7565_command(CMD_SET_COLUMN_UPPER | ((c >> 4) & 0xf));
609 st7565_data(0x0);
610 }
611 }
612 }