rev |
line source |
nuclear@0
|
1 #include <util/delay.h>
|
nuclear@0
|
2 #include "dotmatrix.h"
|
nuclear@0
|
3
|
nuclear@0
|
4 enum { CMD, DATA };
|
nuclear@0
|
5
|
nuclear@0
|
6 #define CMD_DISPCTL(x) (((x) & 7) | (1 << 3))
|
nuclear@0
|
7 #define CMD_FUNCSET(x) (((x) & 7) | (1 << 5))
|
nuclear@0
|
8 #define CMD_SETY(x) (((x) & 7) | (1 << 6))
|
nuclear@0
|
9 #define CMD_SETX(x) (((x) & 0x7f) | (1 << 7))
|
nuclear@0
|
10
|
nuclear@0
|
11 #define CMD_EXT_BIAS(x) (((x) & 7) | (1 << 4))
|
nuclear@0
|
12 #define CMD_EXT_VOP(x) (((x) & 0x7f) | (1 << 7))
|
nuclear@0
|
13
|
nuclear@0
|
14 #define FSET_BASIC 0
|
nuclear@0
|
15 #define FSET_EXTENDED 1
|
nuclear@0
|
16 #define FSET_VERTICAL 2
|
nuclear@0
|
17 #define FSET_POWERDOWN 3
|
nuclear@0
|
18
|
nuclear@0
|
19 #define DCTL_BLANK 0
|
nuclear@0
|
20 #define DCTL_NORMAL 4
|
nuclear@0
|
21 #define DCTL_ALL 1
|
nuclear@0
|
22 #define DCTL_INVERSE 5
|
nuclear@0
|
23
|
nuclear@0
|
24 #define FRAME_BYTES ((DM_WIDTH / 8) * DM_HEIGHT)
|
nuclear@0
|
25
|
nuclear@0
|
26 #define PINMASK \
|
nuclear@0
|
27 ((1 << DM_PIN_CLK) | \
|
nuclear@0
|
28 (1 << DM_PIN_DIN) | \
|
nuclear@0
|
29 (1 << DM_PIN_DC) | \
|
nuclear@0
|
30 (1 << DM_PIN_CE) | \
|
nuclear@0
|
31 (1 << DM_PIN_RST))
|
nuclear@0
|
32
|
nuclear@0
|
33 #define SET(var, bit) ((var) |= 1 << (bit))
|
nuclear@0
|
34 #define CLR(var, bit) ((var) &= ~(1 << (bit)))
|
nuclear@0
|
35
|
nuclear@0
|
36 #define NOP() asm volatile ("nop")
|
nuclear@0
|
37
|
nuclear@0
|
38 static void start_send(void);
|
nuclear@0
|
39 static void send(int type, unsigned char c);
|
nuclear@0
|
40 static void stop_send(void);
|
nuclear@0
|
41 static void send_byte(int type, unsigned char c);
|
nuclear@0
|
42
|
nuclear@0
|
43 static int mode;
|
nuclear@0
|
44
|
nuclear@0
|
45 int dm_init(void)
|
nuclear@0
|
46 {
|
nuclear@0
|
47 DM_DDR |= PINMASK; /* set used pins as outputs */
|
nuclear@0
|
48 SET(DM_PORT, DM_PIN_CE);
|
nuclear@0
|
49 SET(DM_PORT, DM_PIN_RST);
|
nuclear@0
|
50
|
nuclear@0
|
51 /* reset the lcd controller */
|
nuclear@0
|
52 CLR(DM_PORT, DM_PIN_RST);
|
nuclear@0
|
53 NOP();
|
nuclear@0
|
54 SET(DM_PORT, DM_PIN_RST);
|
nuclear@0
|
55
|
nuclear@0
|
56 /* set Vop (???) */
|
nuclear@0
|
57 start_send();
|
nuclear@0
|
58 send(CMD, CMD_FUNCSET(FSET_EXTENDED));
|
nuclear@2
|
59 send(CMD, CMD_EXT_VOP(78));
|
nuclear@0
|
60
|
nuclear@0
|
61 /* select function set (vertical addressing, basic set) */
|
nuclear@0
|
62 send(CMD, CMD_FUNCSET(FSET_VERTICAL | FSET_BASIC));
|
nuclear@0
|
63
|
nuclear@0
|
64 /* enable display (normal mode) */
|
nuclear@0
|
65 mode = DCTL_NORMAL;
|
nuclear@0
|
66 send(CMD, CMD_DISPCTL(mode));
|
nuclear@0
|
67 stop_send();
|
nuclear@0
|
68
|
nuclear@0
|
69 dm_clear(0);
|
nuclear@0
|
70
|
nuclear@0
|
71 return 0;
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 /* fill the screen with a test pattern */
|
nuclear@0
|
75 void dm_test(void)
|
nuclear@0
|
76 {
|
nuclear@0
|
77 static const unsigned char pattern[] = {
|
nuclear@0
|
78 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
nuclear@0
|
79 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
nuclear@0
|
80 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
nuclear@0
|
81 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
nuclear@0
|
82 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
nuclear@0
|
83 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
nuclear@0
|
84 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
nuclear@0
|
85 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f
|
nuclear@0
|
86 };
|
nuclear@0
|
87 int i;
|
nuclear@0
|
88
|
nuclear@0
|
89 for(i=0; i<DM_HEIGHT / 8; i++) {
|
nuclear@0
|
90 dm_copy(0, i * 8, pattern, sizeof pattern);
|
nuclear@0
|
91 }
|
nuclear@0
|
92 dm_copy(0, DM_HEIGHT - 4, pattern, 6 * 4);
|
nuclear@0
|
93 }
|
nuclear@0
|
94
|
nuclear@0
|
95 void dm_invert(void)
|
nuclear@0
|
96 {
|
nuclear@0
|
97 mode = (mode & 0xfe) | ((~mode) & 1);
|
nuclear@0
|
98 send_byte(CMD, CMD_DISPCTL(mode));
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 void dm_clear(unsigned char val)
|
nuclear@0
|
102 {
|
nuclear@0
|
103 int i;
|
nuclear@0
|
104
|
nuclear@0
|
105 start_send();
|
nuclear@0
|
106 send(CMD, CMD_SETY(0));
|
nuclear@0
|
107 send(CMD, CMD_SETX(0));
|
nuclear@0
|
108
|
nuclear@0
|
109 for(i=0; i<FRAME_BYTES; i++) {
|
nuclear@0
|
110 send(DATA, val);
|
nuclear@0
|
111 }
|
nuclear@0
|
112 stop_send();
|
nuclear@0
|
113 }
|
nuclear@0
|
114
|
nuclear@0
|
115 void dm_copy(int x, int y, const unsigned char *fb, int bytes)
|
nuclear@0
|
116 {
|
nuclear@0
|
117 int i;
|
nuclear@0
|
118
|
nuclear@0
|
119 if(bytes <= 0 || bytes > FRAME_BYTES) {
|
nuclear@0
|
120 bytes = FRAME_BYTES;
|
nuclear@0
|
121 }
|
nuclear@0
|
122
|
nuclear@0
|
123 start_send();
|
nuclear@0
|
124 send(CMD, CMD_SETY(x / 8));
|
nuclear@0
|
125 send(CMD, CMD_SETX(y));
|
nuclear@0
|
126
|
nuclear@0
|
127 for(i=0; i<bytes; i++) {
|
nuclear@0
|
128 send(DATA, *fb++);
|
nuclear@0
|
129 }
|
nuclear@0
|
130 stop_send();
|
nuclear@0
|
131 }
|
nuclear@0
|
132
|
nuclear@0
|
133 static void start_send(void)
|
nuclear@0
|
134 {
|
nuclear@0
|
135 /* start by pulling CE low */
|
nuclear@0
|
136 CLR(DM_PORT, DM_PIN_CE);
|
nuclear@0
|
137
|
nuclear@0
|
138 /* enable SPI, master, clock/4, setup-falling, sample-rising, MSB-first */
|
nuclear@0
|
139 SPCR = (1 << SPE) | (1 << MSTR);
|
nuclear@0
|
140 }
|
nuclear@0
|
141
|
nuclear@0
|
142 static void stop_send(void)
|
nuclear@0
|
143 {
|
nuclear@0
|
144 SPCR = 0;
|
nuclear@0
|
145
|
nuclear@0
|
146 /* end transfer by pulling CE high again */
|
nuclear@0
|
147 SET(DM_PORT, DM_PIN_CE);
|
nuclear@0
|
148 }
|
nuclear@0
|
149
|
nuclear@0
|
150 static void send(int type, unsigned char c)
|
nuclear@0
|
151 {
|
nuclear@0
|
152 int i;
|
nuclear@0
|
153 unsigned char bmask;
|
nuclear@0
|
154
|
nuclear@0
|
155 if(type == CMD) {
|
nuclear@0
|
156 CLR(DM_PORT, DM_PIN_DC);
|
nuclear@0
|
157 } else {
|
nuclear@0
|
158 SET(DM_PORT, DM_PIN_DC);
|
nuclear@0
|
159 }
|
nuclear@0
|
160
|
nuclear@0
|
161 SPDR = c;
|
nuclear@0
|
162 while(!(SPSR & (1 << SPIF)));
|
nuclear@0
|
163
|
nuclear@0
|
164 /* bitbang */
|
nuclear@0
|
165 /*
|
nuclear@0
|
166 bmask = 1 << 7;
|
nuclear@0
|
167 for(i=0; i<8; i++) {
|
nuclear@0
|
168 CLR(DM_PORT, DM_PIN_CLK);
|
nuclear@0
|
169
|
nuclear@0
|
170 if(c & bmask) {
|
nuclear@0
|
171 SET(DM_PORT, DM_PIN_DIN);
|
nuclear@0
|
172 } else {
|
nuclear@0
|
173 CLR(DM_PORT, DM_PIN_DIN);
|
nuclear@0
|
174 }
|
nuclear@0
|
175 bmask >>= 1;
|
nuclear@0
|
176
|
nuclear@0
|
177 SET(DM_PORT, DM_PIN_CLK);
|
nuclear@0
|
178 NOP();
|
nuclear@0
|
179 }
|
nuclear@0
|
180 */
|
nuclear@0
|
181 }
|
nuclear@0
|
182
|
nuclear@0
|
183 static void send_byte(int type, unsigned char c)
|
nuclear@0
|
184 {
|
nuclear@0
|
185 start_send();
|
nuclear@0
|
186 send(type, c);
|
nuclear@0
|
187 stop_send();
|
nuclear@0
|
188 }
|