parts: Updated to name their IRQs
[simavr] / examples / parts / hd44780.h
1 /*
2         hd44780.h
3
4         Copyright 2011 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /*
23  * This "Part" simulates the business end of a HD44780 LCD display
24  * It supports from 8x1 to 20x4 or even 40x4 (not sure that exists)
25  *
26  * It works both in 4 bits and 8 bits mode and supports a "quicky" method
27  * of driving that is commonly used on AVR, namely
28  * (msb) RW:E:RS:D7:D6:D5:D4 (lsb)
29  *
30  * + As usual, the "RW" pin is optional if you are willing to wait for the
31  *   specific number of cycles as per the datasheet (37uS between operations)
32  * + If you decide to use the RW pin, the "busy" flag is supported and will
33  *   be automaticly cleared on the second read, to exercisee the code a bit.
34  * + Cursor is supported, but now "display shift"
35  * + The Character RAM is supported, but is not currently drawn.
36  *
37  * To interface this part, you can use the "INPUT" IRQs and hook them to the
38  * simavr instance, if you use the RW pins or read back frim the display, you
39  * can hook the data pins /back/ to the AVR too.
40  *
41  * The "part" also provides various IRQs that are there to be placed in a VCD file
42  * to show what is sent, and some of the internal status.
43  *
44  * This part has been tested with two different implementation of an AVR driver
45  * for the hd44780. The one shipped in this directory is straight out of the
46  * avr-libc example code.
47  */
48 #ifndef __HD44780_H__
49 #define __HD44780_H__
50
51 #include "sim_irq.h"
52
53 enum {
54     IRQ_HD44780_ALL = 0,        // Only if (msb) RW:E:RS:D7:D6:D5:D4 (lsb)  configured
55     IRQ_HD44780_RS,
56     IRQ_HD44780_RW,
57     IRQ_HD44780_E,
58     // bidirectional
59     IRQ_HD44780_D0,IRQ_HD44780_D1,IRQ_HD44780_D2,IRQ_HD44780_D3,
60     IRQ_HD44780_D4,IRQ_HD44780_D5,IRQ_HD44780_D6,IRQ_HD44780_D7,
61     IRQ_HD44780_INPUT_COUNT,
62
63     IRQ_HD44780_BUSY = IRQ_HD44780_INPUT_COUNT, // for VCD traces sake...
64     IRQ_HD44780_ADDR,
65     IRQ_HD44780_DATA_IN,
66     IRQ_HD44780_DATA_OUT,
67     IRQ_HD44780_COUNT
68 };
69
70 enum {
71     HD44780_FLAG_F = 0,         // 1: 5x10 Font, 0: 5x7 Font
72     HD44780_FLAG_N,             // 1: 2/4-lines Display, 0: 1-line Display,
73     HD44780_FLAG_D_L,           // 1: 4-Bit Interface, 0: 8-Bit Interface
74     HD44780_FLAG_R_L,           // 1: Shift right, 0: shift left
75     HD44780_FLAG_S_C,           // 1: Display shift, 0: Cursor move
76     HD44780_FLAG_B,             // 1: Cursor Blink
77     HD44780_FLAG_C,             // 1: Cursor on
78     HD44780_FLAG_D,             // 1: Set Entire Display memory (for clear)
79     HD44780_FLAG_S,             // 1: Follow display shift
80     HD44780_FLAG_I_D,                   // 1: Increment, 0: Decrement
81
82     /*
83      * Internal flags, not HD44780
84      */
85     HD44780_FLAG_LOWNIBBLE,             // 1: 4 bits mode, write/read low nibble
86     HD44780_FLAG_BUSY,                  // 1: Busy between instruction, 0: ready
87     HD44780_FLAG_REENTRANT,             // 1: Do not update pins
88
89     HD44780_FLAG_DIRTY,                 // 1: needs redisplay...
90     HD44780_FLAG_CRAM_DIRTY,    // 1: Character memory has changed
91 };
92
93
94 typedef struct hd44780_t
95 {
96         avr_irq_t * irq;
97         struct avr_t * avr;
98         int             w, h;                           // width and height of the LCD
99
100         uint16_t cursor;                        // offset in vram
101         uint8_t  vram[80 + 64];
102
103         uint16_t pinstate;                      // 'actual' LCd data pins (IRQ bit field)
104         // uint16_t oldstate;                   /// previous pins
105         uint8_t  datapins;                      // composite of 4 high bits, or 8 bits
106         uint8_t  readpins;
107
108         uint16_t flags;                         // LCD flags ( HD44780_FLAG_*)
109 } hd44780_t;
110
111 void
112 hd44780_init(
113                 struct avr_t *avr,
114                 struct hd44780_t * b,
115                 int width,
116                 int height );
117 void
118 hd44780_print(
119                 struct hd44780_t *b);
120
121 static inline int
122 hd44780_set_flag(
123                 hd44780_t *b, uint16_t bit, int val)
124 {
125         int old = b->flags &  (1 << bit);
126         b->flags = (b->flags & ~(1 << bit)) | (val ? (1 << bit) : 0);
127         return old != 0;
128 }
129
130 static inline int
131 hd44780_get_flag(
132                 hd44780_t *b, uint16_t bit)
133 {
134         return (b->flags &  (1 << bit)) != 0;
135 }
136
137 #endif