Commit f97e7f0ee0efe49f2adee55cf21e6ff179720d79
authorAkos Kiss <akiss@inf.u-szeged.hu>
Thu, 8 Oct 2020 21:04:01 +0000 (23:04 +0200)
committerAkos Kiss <akiss@inf.u-szeged.hu>
Thu, 8 Oct 2020 21:32:39 +0000 (23:32 +0200)
HD44780 has only 80 bytes of DDRAM, which consists of two 40 bytes
long segments. The segment starting at address 0x00 contains the
data for the first line of the display, while the segment starting
at address 0x40 contains the data for the second line of the
display. This means that there are invalid ranges in the 7-bit
address space of the DDRAM (0x00+40 .. 0x3f and 0x40+40 .. 0x7f).
The cursor (address counter) of the HD44780 automatically "jumps
over" these regions whenever auto-incremented/decremented. This
commit implements this behaviour.

Moreover, this commit also fixes the 4-lines mode. When in a
4-lines setup, the first 20 bytes of the first and the second
memory segments control what is displayed in the first two lines,
as usual. However, the second 20 bytes of the memory segments
contain the data for the third and fourth lines of the display.
This means that the starting addresses of lines 3 & 4 are 0x00+20
and 0x40+20.

2 files changed:
examples/parts/hd44780.c
examples/parts/hd44780_glut.c

index 84fb993bacd91c77dce3058654c7287e6f99dfbe..0be074f97791b8bd8b3e34927f5c4afba664efef 100644 (file)
@@ -32,7 +32,7 @@ hd44780_print(
                hd44780_t *b)
 {
        printf("/******************\\\n");
-       const uint8_t offset[] = { 0, 0x40, 0x20, 0x60 };
+       const uint8_t offset[] = { 0x00, 0x40, 0x00 + 20, 0x40 + 20 };
        for (int i = 0; i < b->h; i++) {
                printf("| ");
                fwrite(b->vram + offset[i], 1, b->w, stdout);
@@ -83,16 +83,33 @@ static void
 hd44780_kick_cursor(
        hd44780_t *b)
 {
-       if (hd44780_get_flag(b, HD44780_FLAG_I_D)) {
-               if (b->cursor < 0x80-1)
+       if (hd44780_get_flag(b, HD44780_FLAG_I_D)) { // incrementing
+               if (b->cursor < 0x80) { // cursor in DDRAM
                        b->cursor++;
-               else if (b->cursor < 0x80+0x40-1)
-                       b->cursor++;
-       } else {
-               if (b->cursor < 0x80 && b->cursor)
-                       b->cursor--;
-               else if (b->cursor > 0x80)
-                       b->cursor--;
+                       if (b->cursor >= 0x00 + 40 && b->cursor < 0x40) // jump from end of first memory segment to the start of the second segment
+                               b->cursor = 0x40;
+                       else if (b->cursor >= 0x40 + 40) // wrap around from the end of the second memory segment to the start of the first segment
+                               b->cursor = 0x00;
+               } else { // cursor in CGRAM
+                       if (b->cursor == 0x80 + 0x3f) // wrap around in CGRAM
+                               b->cursor = 0x80;
+                       else
+                               b->cursor++;
+               }
+       } else { // decrementing
+               if (b->cursor < 0x80) { // cursor in DDRAM
+                       if (b->cursor == 0x40) // fall back from the start of the second memory segment to the end of the first segment
+                               b->cursor = 0x00 + 39;
+                       else if (b->cursor == 0x00) // wrap around from the start of the first memory segment to the end of the second segment
+                               b->cursor = 0x40 + 39;
+                       else
+                               b->cursor--;
+               } else { // cursor in CGRAM
+                       if (b->cursor == 0x80) // wrap around in CGRAM
+                               b->cursor = 0x80 + 0x3f;
+                       else
+                               b->cursor--;
+               }
                hd44780_set_flag(b, HD44780_FLAG_DIRTY, 1);
                avr_raise_irq(b->irq + IRQ_HD44780_ADDR, b->cursor);
        }
@@ -136,6 +153,10 @@ hd44780_write_command(
                // Set  DDRAM address
                case 7:         // 1 ADD ADD ADD ADD ADD ADD ADD
                        b->cursor = b->datapins & 0x7f;
+                       if (b->cursor >= 0x00 + 40 && b->cursor < 0x40) // illegal address after the first memory segment -> set cursor to start of second segment
+                               b->cursor = 0x40;
+                       else if (b->cursor >= 0x40 + 40) // illegal address after the second memory segment -> set cursor to start of first segment
+                               b->cursor = 0x00;
                        break;
                // Set  CGRAM address
                case 6:         // 0 1 ADD ADD ADD ADD ADD ADD ADD
index b1c6fb9af0f743364772792de9fd01b84720968f..77c28bcbda2c363b238c20b2509d24fff90382c8 100644 (file)
@@ -140,7 +140,7 @@ hd44780_gl_draw(
        glEnd();
 
        glColor3f(1.0f, 1.0f, 1.0f);
-       const uint8_t offset[] = { 0, 0x40, 0x20, 0x60 };
+       const uint8_t offset[] = { 0x00, 0x40, 0x00 + 20, 0x40 + 20 };
        for (int v = 0 ; v < b->h; v++) {
                glPushMatrix();
                for (int i = 0; i < b->w; i++) {