root / branches / encoders / code / lib / src / libdragonfly / lcd.c @ 1345
History | View | Annotate | Download (12.4 KB)
1 | 7 | bcoltin | /*
|
---|---|---|---|
2 | |||
3 | lcd-ar2.c - implementation for lcd functions
|
||
4 | |||
5 | Author: CMU Robotics Club, Colony Project
|
||
6 | |||
7 | This uses SPI.
|
||
8 | |||
9 | lcd_init MUST be called before anything can be used.
|
||
10 | |||
11 | */
|
||
12 | |||
13 | #include <avr/io.h> |
||
14 | #include <lcd.h> |
||
15 | #include <time.h> |
||
16 | |||
17 | #define LCD_RS PB4 // Command/Data |
||
18 | #define LCD_RSTB PE2 // reset line |
||
19 | #define LCD_CS PB0
|
||
20 | |||
21 | //////lcd defines
|
||
22 | #define RST _BV(4) // pd4 (GPIO) |
||
23 | #define SCE _BV(0) // pb0 (~SS) |
||
24 | #define D_C _BV(5) // pd5 (GPIO?) |
||
25 | #define SDI _BV(2) // pb2 (MOSI) |
||
26 | #define SCK _BV(1) // pb1 (SCK) |
||
27 | |||
28 | #define LCDPORT PORTB
|
||
29 | #define LCDDDR DDRB
|
||
30 | |||
31 | #define LCDRESETPORT PORTD
|
||
32 | #define LCDRESETDDR DDRD
|
||
33 | |||
34 | // Internal Function Prototypes
|
||
35 | // inialize OLED and SPI
|
||
36 | void OLED_init(void); |
||
37 | |||
38 | // reset Controller
|
||
39 | void Reset_SSD1339(void); |
||
40 | |||
41 | // write command or data
|
||
42 | void write_c(unsigned char out_command); |
||
43 | void write_d(unsigned char out_data); |
||
44 | |||
45 | // these write data to the OLED on 8 bit data bus, depends on MCU
|
||
46 | void LCD_out(unsigned char cmd); |
||
47 | |||
48 | // these functions set / clear pins for OLED control lines. they accecpt a 0 or 1
|
||
49 | void DC(char stat); |
||
50 | void RES(char stat); |
||
51 | void CS(char stat); |
||
52 | |||
53 | void lcd_putbyte(unsigned char b); |
||
54 | |||
55 | void crazycircle (void) { |
||
56 | /* int i;
|
||
57 | // draw 100 random circles
|
||
58 | for(i = 0;i < 100;i++){
|
||
59 | write_c(0x86); // draw circle command
|
||
60 | write_d(rand() % 130);
|
||
61 | write_d(rand() % 130);
|
||
62 | write_d(rand() % 64);
|
||
63 | write_d(rand());
|
||
64 | write_d(rand());
|
||
65 | write_d(rand());
|
||
66 | write_d(rand());
|
||
67 | |||
68 | delay_ms(10);
|
||
69 | }
|
||
70 | */
|
||
71 | } |
||
72 | |||
73 | void OLEDtest (void) { |
||
74 | //int i = 0;
|
||
75 | |||
76 | // Initialize
|
||
77 | //Initialize();
|
||
78 | OLED_init(); |
||
79 | |||
80 | delay_ms(120);
|
||
81 | |||
82 | write_c(0x8e); // clear window command |
||
83 | write_d(0);
|
||
84 | write_d(0);
|
||
85 | write_d(130);
|
||
86 | write_d(130);
|
||
87 | |||
88 | delay_ms(100);
|
||
89 | |||
90 | write_c(0x92); // fill enable command |
||
91 | write_d(0x01);
|
||
92 | |||
93 | delay_ms(10);
|
||
94 | |||
95 | crazycircle(); |
||
96 | /*
|
||
97 | // write directly to ram, this fills up bottom 1/3 of display with color pattern
|
||
98 | write_c(0x5c);
|
||
99 | for (i = 0; i < 2000; i++){
|
||
100 | write_c(0x5c);
|
||
101 | write_d(i);
|
||
102 | write_d(i);
|
||
103 | write_d(i);
|
||
104 | }
|
||
105 | */
|
||
106 | } |
||
107 | |||
108 | /**********************************************************
|
||
109 | Initialize
|
||
110 | **********************************************************/
|
||
111 | |||
112 | void OLED_init(void) |
||
113 | { |
||
114 | // Setup SPI here
|
||
115 | SPCR = 0x5D; // enable SPI, master, SPI mode 3 |
||
116 | DDRB |= 0x06; // enable MOSI and SCK as outputs |
||
117 | |||
118 | LCD_out(0);
|
||
119 | DC(0);
|
||
120 | CS(0);
|
||
121 | Reset_SSD1339(); |
||
122 | write_c(0xa0); // Set Re-map / Color Depth |
||
123 | write_d(0x34);//0xb4); // 262K 8bit R->G->B |
||
124 | write_c(0xa1); // Set display start line |
||
125 | write_d(0x00); // 00h start |
||
126 | //write_c(0xa2); // Set display offset
|
||
127 | //write_d(0x80); // 80h start
|
||
128 | write_c(0xA6); // Normal display |
||
129 | write_c(0xad); // Set Master Configuration |
||
130 | write_d(0x8e); // DC-DC off & external VcomH voltage & external pre-charge voltage |
||
131 | write_c(0xb0); // Power saving mode |
||
132 | write_d(0x05);
|
||
133 | write_c(0xb1); // Set pre & dis_charge |
||
134 | write_d(0x11); // pre=1h dis=1h |
||
135 | write_c(0xb3); // clock & frequency |
||
136 | write_d(0xf0); // clock=Divser+1 frequency=fh |
||
137 | write_c(0xbb); // Set pre-charge voltage of color A B C |
||
138 | write_d(0xff); // color A was 1c |
||
139 | write_d(0xff); // color B was 1c |
||
140 | write_d(0xff); // color C was 1c |
||
141 | write_c(0xbe); // Set VcomH |
||
142 | write_d(0x1f); // |
||
143 | write_c(0xc1); // Set contrast current for A B C |
||
144 | write_d(0xCa); // Color A was AA |
||
145 | write_d(0xD4); // Color B was B4 |
||
146 | write_d(0xF8); // Color C was C8 |
||
147 | write_c(0xc7); // Set master contrast |
||
148 | write_d(0x0f); // no change |
||
149 | write_c(0xca); // Duty |
||
150 | write_d(0x7f); // 127+1 |
||
151 | write_c(0xaf); // Display on |
||
152 | } |
||
153 | |||
154 | void Reset_SSD1339(void) |
||
155 | { |
||
156 | RES(0);
|
||
157 | delay_ms(100);
|
||
158 | RES(1);
|
||
159 | } |
||
160 | void write_c(unsigned char out_command) |
||
161 | { |
||
162 | DC(0);CS(0); |
||
163 | //delay_ms(1);
|
||
164 | |||
165 | LCD_out(out_command); |
||
166 | // delay_ms(1);
|
||
167 | |||
168 | DC(1);
|
||
169 | // potentially add NOP
|
||
170 | CS(1);
|
||
171 | |||
172 | } |
||
173 | |||
174 | void write_d(unsigned char out_data) |
||
175 | { |
||
176 | DC(1);CS(0); |
||
177 | // delay_ms(1);
|
||
178 | |||
179 | LCD_out(out_data); |
||
180 | // delay_ms(1);
|
||
181 | DC(1);
|
||
182 | //potentially add NOP
|
||
183 | CS(1);
|
||
184 | } |
||
185 | |||
186 | // these functions set / clear pins for LCD control lines. they accecpt a 0 or 1
|
||
187 | void DC(char stat) |
||
188 | { |
||
189 | DDRB |= _BV(LCD_RS); // RS is P0.30, set to output
|
||
190 | if (stat)
|
||
191 | PORTB |= _BV(LCD_RS); |
||
192 | else
|
||
193 | PORTB &= ~(_BV(LCD_RS)); |
||
194 | } |
||
195 | |||
196 | void RES(char stat) |
||
197 | { |
||
198 | DDRE |= _BV(LCD_RSTB); // RSTB is P0.7, set to output
|
||
199 | if (stat)
|
||
200 | PORTE |= _BV(LCD_RSTB); |
||
201 | else
|
||
202 | PORTE &= ~(_BV(LCD_RSTB)); |
||
203 | } |
||
204 | |||
205 | void CS(char stat) |
||
206 | { |
||
207 | DDRB |= _BV(LCD_CS); // RSTB is P0.7, set to output
|
||
208 | if (stat)
|
||
209 | PORTB |= _BV(LCD_CS); |
||
210 | else
|
||
211 | PORTB &= ~(_BV(LCD_CS)); |
||
212 | } |
||
213 | |||
214 | // send to the LCD
|
||
215 | void LCD_out(unsigned char cmd) |
||
216 | { |
||
217 | SPDR = cmd; |
||
218 | // could also do this via interrupts
|
||
219 | loop_until_bit_is_set(SPSR, SPIF); |
||
220 | } |
||
221 | |||
222 | |||
223 | //**************************************Old shit below!*****************
|
||
224 | /*
|
||
225 | FontLookup - a lookup table for all characters
|
||
226 | */
|
||
227 | static const unsigned char FontLookup [][5] = |
||
228 | { |
||
229 | { 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp |
||
230 | { 0x00, 0x00, 0x5f, 0x00, 0x00 }, // ! |
||
231 | { 0x00, 0x07, 0x00, 0x07, 0x00 }, // " |
||
232 | { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # |
||
233 | { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ |
||
234 | { 0x23, 0x13, 0x08, 0x64, 0x62 }, // % |
||
235 | { 0x36, 0x49, 0x55, 0x22, 0x50 }, // & |
||
236 | { 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' |
||
237 | { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( |
||
238 | { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) |
||
239 | { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * |
||
240 | { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + |
||
241 | { 0x00, 0x00, 0x50, 0x30, 0x00 }, // , |
||
242 | { 0x10, 0x10, 0x10, 0x10, 0x10 }, // - |
||
243 | { 0x00, 0x60, 0x60, 0x00, 0x00 }, // . |
||
244 | { 0x20, 0x10, 0x08, 0x04, 0x02 }, // / |
||
245 | { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 |
||
246 | { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 |
||
247 | { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 |
||
248 | { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 |
||
249 | { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 |
||
250 | { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 |
||
251 | { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 |
||
252 | { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 |
||
253 | { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 |
||
254 | { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 |
||
255 | { 0x00, 0x36, 0x36, 0x00, 0x00 }, // : |
||
256 | { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; |
||
257 | { 0x08, 0x14, 0x22, 0x41, 0x00 }, // < |
||
258 | { 0x14, 0x14, 0x14, 0x14, 0x14 }, // = |
||
259 | { 0x00, 0x41, 0x22, 0x14, 0x08 }, // > |
||
260 | { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? |
||
261 | { 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ |
||
262 | { 0x7E, 0x11, 0x11, 0x11, 0x7E }, // A |
||
263 | { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B |
||
264 | { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C |
||
265 | { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D |
||
266 | { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E |
||
267 | { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F |
||
268 | { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G |
||
269 | { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H |
||
270 | { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I |
||
271 | { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J |
||
272 | { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K |
||
273 | { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L |
||
274 | { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M |
||
275 | { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N |
||
276 | { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O |
||
277 | { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P |
||
278 | { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q |
||
279 | { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R |
||
280 | { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S |
||
281 | { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T |
||
282 | { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U |
||
283 | { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V |
||
284 | { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W |
||
285 | { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X |
||
286 | { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y |
||
287 | { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z |
||
288 | { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ |
||
289 | { 0x02, 0x04, 0x08, 0x10, 0x20 }, // backslash |
||
290 | { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] |
||
291 | { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ |
||
292 | { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ |
||
293 | { 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' |
||
294 | { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a |
||
295 | { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b |
||
296 | { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c |
||
297 | { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d |
||
298 | { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e |
||
299 | { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f |
||
300 | { 0x0C, 0x52, 0x52, 0x52, 0x3E }, // g |
||
301 | { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h |
||
302 | { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i |
||
303 | { 0x20, 0x40, 0x44, 0x3D, 0x00 }, // j |
||
304 | { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k |
||
305 | { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l |
||
306 | { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m |
||
307 | { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n |
||
308 | { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o |
||
309 | { 0x7C, 0x14, 0x14, 0x14, 0x08 }, // p |
||
310 | { 0x08, 0x14, 0x14, 0x18, 0x7C }, // q |
||
311 | { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r |
||
312 | { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s |
||
313 | { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t |
||
314 | { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u |
||
315 | { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v |
||
316 | { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w |
||
317 | { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x |
||
318 | { 0x0C, 0x50, 0x50, 0x50, 0x3C }, // y |
||
319 | { 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z |
||
320 | { 0x00, 0x08, 0x36, 0x41, 0x41 }, // { |
||
321 | { 0x00, 0x00, 0x7F, 0x00, 0x00 }, // | |
||
322 | { 0x41, 0x41, 0x36, 0x08, 0x00 }, // } |
||
323 | { 0x02, 0x01, 0x01, 0x02, 0x01 }, // ~ |
||
324 | { 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // del |
||
325 | }; |
||
326 | |||
327 | |||
328 | /**
|
||
329 | * @defgroup lcd LCD
|
||
330 | * @brief Functions for the LCD
|
||
331 | * Functions for writing to the LCD.
|
||
332 | * All functions may be found in lcd.h.
|
||
333 | *
|
||
334 | * @{
|
||
335 | **/
|
||
336 | |||
337 | /**
|
||
338 | * Initializes the LCD. Must be called before any other
|
||
339 | * LCD functions.
|
||
340 | **/
|
||
341 | void lcd_init(void) |
||
342 | { |
||
343 | LCDDDR |= (SCE | SDI | SCK); |
||
344 | LCDRESETDDR |= (RST|D_C); |
||
345 | |||
346 | LCDPORT &= ~( SCE | SDI | SCK); |
||
347 | LCDRESETPORT &=~(D_C); |
||
348 | |||
349 | SPCR |= 0x50;//0b01010000; // no SPI int, SPI en, Master, sample on rising edge, fosc/2 |
||
350 | SPSR |= 0x01; // a continuation of the above |
||
351 | |||
352 | LCDRESETPORT |= RST; |
||
353 | delay_ms(10);
|
||
354 | LCDRESETPORT &= (~RST); |
||
355 | delay_ms(100);
|
||
356 | LCDRESETPORT |= RST; |
||
357 | |||
358 | lcd_putbyte( 0x21 ); // LCD Extended Commands. |
||
359 | lcd_putbyte( 0xC8 ); // Set LCD Vop (Contrast). |
||
360 | lcd_putbyte( 0x06 ); // Set Temp coefficent. |
||
361 | lcd_putbyte( 0x13 ); // LCD bias mode 1:48. |
||
362 | lcd_putbyte( 0x20 ); // LCD Standard Commands, Horizontal addressing mode. |
||
363 | lcd_putbyte( 0x0C ); // LCD in normal mode. |
||
364 | |||
365 | LCDRESETPORT |= D_C; //put it in init instead of main
|
||
366 | |||
367 | lcd_clear_screen(); |
||
368 | } |
||
369 | |||
370 | /**
|
||
371 | * Clears the LCD screen. lcd_init must be called first.
|
||
372 | *
|
||
373 | * @see lcd_init
|
||
374 | **/
|
||
375 | void lcd_clear_screen( void ) { |
||
376 | int i;
|
||
377 | for (i = 0; i < 504; i++) |
||
378 | lcd_putbyte(0x0);
|
||
379 | |||
380 | lcd_gotoxy(0,0); |
||
381 | } |
||
382 | |||
383 | /**
|
||
384 | * Prints a character on the LCD screen. lcd_init
|
||
385 | * must be called before this function may be used.
|
||
386 | *
|
||
387 | * @param c the character to print
|
||
388 | *
|
||
389 | * @see lcd_init
|
||
390 | **/
|
||
391 | void lcd_putc(char c) |
||
392 | { |
||
393 | int i;
|
||
394 | |||
395 | for (i = 0; i < 5; i++) |
||
396 | lcd_putbyte(FontLookup[c-32][i]);
|
||
397 | lcd_putbyte(0);
|
||
398 | } |
||
399 | |||
400 | /*
|
||
401 | print an entire string to the lcd
|
||
402 | */
|
||
403 | void lcd_puts(char *s) |
||
404 | { |
||
405 | char *t = s;
|
||
406 | while (*t != 0) |
||
407 | { |
||
408 | lcd_putc(*t); |
||
409 | t++; |
||
410 | } |
||
411 | } |
||
412 | |||
413 | /*
|
||
414 | go to coordinate x, y
|
||
415 | y: vertically - 1 char
|
||
416 | x: horizontally - 1 pixel
|
||
417 | |||
418 | multiply x by 6 if want to move 1 entire character
|
||
419 | |||
420 | origin (0,0) is at top left corner of lcd screen
|
||
421 | */
|
||
422 | /**
|
||
423 | * Move the current cursor position to the one specified.
|
||
424 | * lcd_init must be called before this function may be used.
|
||
425 | *
|
||
426 | * @param x The x coordinate of the new position
|
||
427 | * @param y The y coordinate of the new position
|
||
428 | *
|
||
429 | * @see lcd_init
|
||
430 | **/
|
||
431 | void lcd_gotoxy(int x, int y) |
||
432 | { |
||
433 | LCDRESETPORT &= ~(D_C); |
||
434 | lcd_putbyte(0x40 | (y & 0x07)); |
||
435 | lcd_putbyte(0x80 | (x & 0x7f)); |
||
436 | LCDRESETPORT |= D_C; |
||
437 | } |
||
438 | |||
439 | /*
|
||
440 | prints an int to the lcd
|
||
441 | |||
442 | code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
|
||
443 | */
|
||
444 | /**
|
||
445 | * Print an integer to the LCD screen.
|
||
446 | * lcd_init must be called before this function may be used.
|
||
447 | *
|
||
448 | * @param value the integer to print
|
||
449 | *
|
||
450 | * @see lcd_init
|
||
451 | **/
|
||
452 | void lcd_puti(int value ) { |
||
453 | unsigned char lcd_data[6]={'0','0','0','0','0','0' }, position=sizeof(lcd_data), radix=10; |
||
454 | |||
455 | /* convert int to ascii */
|
||
456 | if(value<0) { lcd_putc('-'); value=-value; } |
||
457 | do { position--; *(lcd_data+position)=(value%radix)+'0'; value/=radix; } while(value); |
||
458 | |||
459 | |||
460 | /* start displaying the number */
|
||
461 | for(;position<=(sizeof(lcd_data)-1);position++) |
||
462 | { |
||
463 | |||
464 | lcd_putc(lcd_data[position]); |
||
465 | } |
||
466 | |||
467 | return;
|
||
468 | } |
||
469 | |||
470 | /** @} **/ //end defgroup |
||
471 | |||
472 | void lcd_putbyte(unsigned char b) |
||
473 | { |
||
474 | SPDR = b; |
||
475 | while (!(SPSR & 0x80)); /* Wait until SPI transaction is complete */ |
||
476 | } |