@@ -32,7 +32,7 @@ hd44780_print(
32
32
hd44780_t * b )
33
33
{
34
34
printf ("/******************\\\n" );
35
- const uint8_t offset [] = { 0 , 0x40 , 0x20 , 0x60 };
35
+ const uint8_t offset [] = { 0x00 , 0x40 , 0x00 + 20 , 0x40 + 20 };
36
36
for (int i = 0 ; i < b -> h ; i ++ ) {
37
37
printf ("| " );
38
38
fwrite (b -> vram + offset [i ], 1 , b -> w , stdout );
@@ -55,15 +55,17 @@ static void
55
55
_hd44780_clear_screen (
56
56
hd44780_t * b )
57
57
{
58
- memset (b -> vram , ' ' , 80 );
58
+ memset (b -> vram , ' ' , 0x80 );
59
+ b -> cursor = 0 ;
60
+ hd44780_set_flag (b , HD44780_FLAG_I_D , 2 );
59
61
hd44780_set_flag (b , HD44780_FLAG_DIRTY , 1 );
60
62
avr_raise_irq (b -> irq + IRQ_HD44780_ADDR , b -> cursor );
61
63
}
62
64
63
65
64
66
65
67
/*
66
- * This is called when the delay between operation is triggered
68
+ * This is called when the delay between operations is triggered
67
69
* without the AVR firmware 'reading' the status byte. It
68
70
* automatically clears the BUSY flag for the next command
69
71
*/
@@ -83,16 +85,45 @@ static void
83
85
hd44780_kick_cursor (
84
86
hd44780_t * b )
85
87
{
86
- if (hd44780_get_flag (b , HD44780_FLAG_I_D )) {
87
- if (b -> cursor < 79 )
88
- b -> cursor ++ ;
89
- else if (b -> cursor < 80 + 64 - 1 )
88
+ if (hd44780_get_flag (b , HD44780_FLAG_I_D )) { // incrementing
89
+ if (b -> cursor < 0x80 ) { // cursor in DDRAM
90
90
b -> cursor ++ ;
91
- } else {
92
- if (b -> cursor < 80 && b -> cursor )
93
- b -> cursor -- ;
94
- else if (b -> cursor > 80 )
95
- b -> cursor -- ;
91
+ if (hd44780_get_flag (b , HD44780_FLAG_N )) { // 2-line display
92
+ if (b -> cursor >= 0x00 + 40 && b -> cursor < 0x40 ) // jump from end of first memory segment to the start of the second segment
93
+ b -> cursor = 0x40 ;
94
+ else if (b -> cursor >= 0x40 + 40 ) // wrap around from the end of the second memory segment to the start of the first segment
95
+ b -> cursor = 0x00 ;
96
+ } else { // 1-line display
97
+ if (b -> cursor >= 0x00 + 80 ) // wrap around from the end of the memory to the start
98
+ b -> cursor = 0x00 ;
99
+ }
100
+ } else { // cursor in CGRAM
101
+ if (b -> cursor == 0x80 + 0x3f ) // wrap around in CGRAM
102
+ b -> cursor = 0x80 ;
103
+ else
104
+ b -> cursor ++ ;
105
+ }
106
+ } else { // decrementing
107
+ if (b -> cursor < 0x80 ) { // cursor in DDRAM
108
+ if (hd44780_get_flag (b , HD44780_FLAG_N )) { // 2-line display
109
+ if (b -> cursor == 0x40 ) // fall back from the start of the second memory segment to the end of the first segment
110
+ b -> cursor = 0x00 + 39 ;
111
+ else if (b -> cursor == 0x00 ) // wrap around from the start of the first memory segment to the end of the second segment
112
+ b -> cursor = 0x40 + 39 ;
113
+ else
114
+ b -> cursor -- ;
115
+ } else { // 1-line display
116
+ if (b -> cursor == 0x00 ) // wrap around from the start of the memory to the end
117
+ b -> cursor = 0x00 + 79 ;
118
+ else
119
+ b -> cursor -- ;
120
+ }
121
+ } else { // cursor in CGRAM
122
+ if (b -> cursor == 0x80 ) // wrap around in CGRAM
123
+ b -> cursor = 0x80 + 0x3f ;
124
+ else
125
+ b -> cursor -- ;
126
+ }
96
127
hd44780_set_flag (b , HD44780_FLAG_DIRTY , 1 );
97
128
avr_raise_irq (b -> irq + IRQ_HD44780_ADDR , b -> cursor );
98
129
}
@@ -125,21 +156,30 @@ hd44780_write_command(
125
156
hd44780_t * b )
126
157
{
127
158
uint32_t delay = 37 ; // uS
128
- int top = 7 ; // get highest bit set'm
159
+ int top = 7 ; // get highest bit set
129
160
while (top )
130
161
if (b -> datapins & (1 << top ))
131
162
break ;
132
163
else top -- ;
133
164
printf ("hd44780_write_command %02x\n" , b -> datapins );
134
165
135
166
switch (top ) {
136
- // Set DDRAM address
167
+ // Set DDRAM address
137
168
case 7 : // 1 ADD ADD ADD ADD ADD ADD ADD
138
169
b -> cursor = b -> datapins & 0x7f ;
170
+ if (hd44780_get_flag (b , HD44780_FLAG_N )) { // 2-line display
171
+ if (b -> cursor >= 0x00 + 40 && b -> cursor < 0x40 ) // illegal address after the first memory segment -> set cursor to start of second segment
172
+ b -> cursor = 0x40 ;
173
+ else if (b -> cursor >= 0x40 + 40 ) // illegal address after the second memory segment -> set cursor to start of first segment
174
+ b -> cursor = 0x00 ;
175
+ } else { // 1-line display
176
+ if (b -> cursor >= 0x00 + 80 ) // illegal address after valid memory -> set cursor to start
177
+ b -> cursor = 0x00 ;
178
+ }
139
179
break ;
140
- // Set CGRAM address
141
- case 6 : // 0 1 ADD ADD ADD ADD ADD ADD ADD
142
- b -> cursor = 64 + (b -> datapins & 0x3f );
180
+ // Set CGRAM address
181
+ case 6 : // 0 1 ACG ACG ACG ACG ACG ACG
182
+ b -> cursor = 0x80 + (b -> datapins & 0x3f );
143
183
break ;
144
184
// Function set
145
185
case 5 : { // 0 0 1 DL N F x x
@@ -246,7 +286,7 @@ hd44780_process_read(
246
286
delay = 0 ; // no raising busy when reading busy !
247
287
248
288
// low bits are the current cursor
249
- b -> readpins = b -> cursor < 80 ? b -> cursor : b -> cursor - 64 ;
289
+ b -> readpins = b -> cursor < 0x80 ? b -> cursor : b -> cursor - 0x80 ;
250
290
int busy = hd44780_get_flag (b , HD44780_FLAG_BUSY );
251
291
b -> readpins |= busy ? 0x80 : 0 ;
252
292
@@ -391,4 +431,3 @@ hd44780_init(
391
431
printf ("LCD: %duS is %d cycles for your AVR\n" ,
392
432
1 , (int )avr_usec_to_cycles (avr , 1 ));
393
433
}
394
-
0 commit comments