From: Akos Kiss Date: Thu, 8 Oct 2020 21:04:01 +0000 (+0200) Subject: Fix cursor handling in segmented DDRAM of HD44780 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=f97e7f0ee0efe49f2adee55cf21e6ff179720d79;p=sx%2Fsimavr.git Fix cursor handling in segmented DDRAM of HD44780 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. --- diff --git a/examples/parts/hd44780.c b/examples/parts/hd44780.c index 84fb993..0be074f 100644 --- a/examples/parts/hd44780.c +++ b/examples/parts/hd44780.c @@ -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 diff --git a/examples/parts/hd44780_glut.c b/examples/parts/hd44780_glut.c index b1c6fb9..77c28bc 100644 --- a/examples/parts/hd44780_glut.c +++ b/examples/parts/hd44780_glut.c @@ -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++) {