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