1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <avr/signal.h>
|
4 | #include <avr/pgmspace.h>
|
5 | #include <avr/sfr_defs.h>
|
6 |
|
7 | #include "lcd.h"
|
8 | #include "display.h"
|
9 | #include "delay.h"
|
10 |
|
11 |
|
12 | void lcd_write(unsigned char data, unsigned char mode);
|
13 | void lcd_enable(void);
|
14 | unsigned char lcd_read(unsigned char mode);
|
15 | unsigned char lcd_waitbusy(void);
|
16 |
|
17 | void lcd_init(void)
|
18 | {
|
19 | LCD_LIGHT_INIT; /* set output for contrast and backlight */
|
20 | LCD_DATA_OUT_INIT; /* set output for databytes */
|
21 | LCD_E_INIT; /* set output for enable */
|
22 | LCD_RS_INIT; /* set output for select */
|
23 | LCD_RW_INIT; /* set output for write/read-toggle */
|
24 | LCD_RS_CLR; /* disable lcd */
|
25 |
|
26 | cli();
|
27 | OCR1B = DISPLAY_PWM_TOP; /* set display contrast */
|
28 | OCR1C = DISPLAY_PWM_TOP; /* set display backlight */
|
29 |
|
30 | /* init display */
|
31 | TCNT1 = 0; /* set counter to zero */
|
32 | TCCR1A |= 1<<COM1B1 | 1<<COM1C1 | 1<<WGM11; /* fast pwm 9-bit, set at top, clear on match */
|
33 | TCCR1B |= 1<<WGM12 | 1<<CS11; /* 8 prescaling: 16 MHz -> 3906 Hz */
|
34 |
|
35 | sei();
|
36 | delay_ms(16); /* power up lcd */
|
37 | LCD_DATA &= 0x0F; /* set 8 bit first (three times) */
|
38 | LCD_DATA |= 0x30;
|
39 | lcd_enable();
|
40 | delay_us(4100);
|
41 | lcd_enable();
|
42 | delay_us(40);
|
43 | lcd_enable();
|
44 | delay_us(40);
|
45 | LCD_DATA &= 0x0F; /* set 4 bit */
|
46 | LCD_DATA |= 0x20;
|
47 | lcd_enable();
|
48 | delay_us(40);
|
49 | lcd_write(LCD_CMD_SET_4BIT_2LINE, 0);
|
50 | delay_us(40);
|
51 | lcd_write(LCD_CMD_ENTRY_MODE_RN,0);
|
52 | lcd_write(LCD_CMD_CLEAR, 0);
|
53 | lcd_write(LCD_CMD_DISPLAY_ON, 0);
|
54 | return;
|
55 | }
|
56 |
|
57 | void lcd_set(uint8_t option, uint16_t value)
|
58 | {
|
59 | value = DISPLAY_PWM_TOP - value; /* invert contrast and backlight */
|
60 | switch (option) {
|
61 | case DISPLAY_CONFIG_CONTRAST:
|
62 | OCR1B = value;
|
63 | break;
|
64 |
|
65 | case DISPLAY_CONFIG_BACKLIGHT:
|
66 | OCR1C = value;
|
67 | break;
|
68 | }
|
69 | return;
|
70 | }
|
71 |
|
72 | void lcd_putc(unsigned char c)
|
73 | {
|
74 | unsigned char addr;
|
75 |
|
76 | addr = lcd_waitbusy();
|
77 | switch (c) {
|
78 | case '\n':
|
79 | if (addr < LCD_ADDR_LINE2) addr += 0x40;
|
80 | else addr -= 0x40;
|
81 | lcd_write(addr, 0);
|
82 | break;
|
83 |
|
84 | case '\r':
|
85 | if (addr < LCD_ADDR_LINE2) addr = LCD_ADDR_LINE1;
|
86 | else addr = LCD_ADDR_LINE2;
|
87 | lcd_write(addr, 0);
|
88 | break;
|
89 |
|
90 | default:
|
91 | lcd_write(c, 1);
|
92 | break;
|
93 | }
|
94 | return;
|
95 | }
|
96 |
|
97 | void lcd_write(unsigned char data, unsigned char mode)
|
98 | {
|
99 | lcd_waitbusy();
|
100 | if (mode) LCD_RS_SET; /* set to data mode */
|
101 | else LCD_RS_CLR; /* set to instruction mode */
|
102 | LCD_RW_CLR; /* set to write */
|
103 | LCD_DATA &= 0x0F; /* clear output: 0000xxxx */
|
104 | LCD_DATA |= (data & 0xF0); /* first high nibble */
|
105 | lcd_enable();
|
106 | LCD_DATA &= 0x0F; /* clear output: 0000xxxx */
|
107 | LCD_DATA |= ((data<<4) & 0xF0); /* second low nibble */
|
108 | lcd_enable();
|
109 | return;
|
110 | }
|
111 |
|
112 | void lcd_enable(void)
|
113 | {
|
114 | LCD_E_SET;
|
115 | asm("nop");
|
116 | asm("nop");
|
117 | asm("nop");
|
118 | LCD_E_CLR;
|
119 | return;
|
120 | }
|
121 |
|
122 | unsigned char lcd_read(unsigned char mode)
|
123 | {
|
124 | unsigned char data;
|
125 |
|
126 | LCD_DATA_IN_INIT;
|
127 | if (mode) LCD_RS_SET; /* set to data mode */
|
128 | else LCD_RS_CLR; /* set to instruction mode */
|
129 | LCD_RW_SET; /* set to write */
|
130 | LCD_E_SET;
|
131 | asm("nop");
|
132 | asm("nop");
|
133 | asm("nop");
|
134 | data = LCD_DATA_IN & 0xF0;
|
135 | LCD_E_CLR;
|
136 | asm("nop");
|
137 | asm("nop");
|
138 | asm("nop");
|
139 | LCD_E_SET;
|
140 | asm("nop");
|
141 | asm("nop");
|
142 | asm("nop");
|
143 | data |= (LCD_DATA_IN & 0xF0)>>4;
|
144 | LCD_E_CLR;
|
145 | LCD_DATA_OUT_INIT;
|
146 | return(data);
|
147 | }
|
148 |
|
149 | unsigned char lcd_waitbusy(void)
|
150 | {
|
151 | while (lcd_read(0) & (1<<LCD_ADDR_BUSY));
|
152 | delay_us(4);
|
153 | return(lcd_read(0) | (1<<LCD_ADDR_BUSY));
|
154 | }
|