FreeCalypso > hg > freecalypso-tools
comparison target-utils/pirexplore/lcd.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Jun 2016 00:13:35 +0000 |
parents | |
children | 87cb03b35f77 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e7502631a0f9 |
---|---|
1 /* | |
2 * Almost all of this Pirelli LCD black magic has been lifted from OsmocomBB. | |
3 */ | |
4 | |
5 #include <sys/types.h> | |
6 #include "types.h" | |
7 | |
8 #define GPIO_OUT_REG (*(volatile u16 *)0xFFFE4802) | |
9 #define nCS4_ADDR0 (*(volatile u16 *)0x02800000) | |
10 #define nCS4_ADDR2 (*(volatile u16 *)0x02800002) | |
11 | |
12 fb_spca_write(addr, data) | |
13 { | |
14 GPIO_OUT_REG &= 0xFF7F; | |
15 nCS4_ADDR0 = addr; | |
16 nCS4_ADDR2 = data; | |
17 } | |
18 | |
19 void | |
20 cmd_spca(argbulk) | |
21 char *argbulk; | |
22 { | |
23 char *argv[3]; | |
24 u_long addr, data; | |
25 | |
26 if (parse_args(argbulk, 2, 2, argv, 0) < 0) | |
27 return; | |
28 if (parse_hexarg(argv[0], 4, &addr) < 0) { | |
29 printf("ERROR: arg1 must be a valid 16-bit hex value\n"); | |
30 return; | |
31 } | |
32 if (parse_hexarg(argv[1], 4, &data) < 0) { | |
33 printf("ERROR: arg2 must be a valid 16-bit hex value\n"); | |
34 return; | |
35 } | |
36 fb_spca_write(addr, data); | |
37 } | |
38 | |
39 void | |
40 cmd_spcainit() | |
41 { | |
42 /* | |
43 * Apparently we have to give it a reset pulse, then immediately | |
44 * do the black magic register write sequence. | |
45 */ | |
46 GPIO_OUT_REG = 0x0000; | |
47 GPIO_OUT_REG = 0x0012; | |
48 /* non-understandable voodoo copied from OsmocomBB */ | |
49 fb_spca_write(0x7e, 0x00); /* internal register access */ | |
50 osmo_delay_ms(10); | |
51 fb_spca_write(0x7a, 0x00); /* keep CPU in reset state */ | |
52 osmo_delay_ms(10); | |
53 fb_spca_write(0x7f, 0x00); /* select main page */ | |
54 osmo_delay_ms(5); | |
55 fb_spca_write(0x72, 0x07); /* don't reshape timing, 16 bit mode */ | |
56 fb_spca_write(0x14, 0x03); | |
57 fb_spca_write(0x7f, 0x00); /* select main page */ | |
58 osmo_delay_ms(5); | |
59 fb_spca_write(0x06, 0xff); | |
60 fb_spca_write(0x7f, 0x09); | |
61 fb_spca_write(0x19, 0x08); /* backlight: 0x08 is on, 0x0c is off */ | |
62 fb_spca_write(0x23, 0x18); | |
63 } | |
64 | |
65 enum s6b33b1x_cmdflag { CMD, DATA, END }; | |
66 | |
67 struct s6b33b1x_cmdlist { | |
68 enum s6b33b1x_cmdflag is_cmd:8; /* 1: is a command, 0: is data, 2: end marker! */ | |
69 u_char data; /* 8 bit to send to LC display */ | |
70 }; | |
71 | |
72 static const struct s6b33b1x_cmdlist | |
73 s6b33b1x_initdata[] = { | |
74 { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */ | |
75 { DATA, 0x00 }, /* DATA: everything off */ | |
76 { CMD, 0x02 }, /* CMD Oscillation Mode Set */ | |
77 { DATA, 0x00 }, /* DATA: oscillator off */ | |
78 { CMD, 0x2c }, /* CMD Standby Mode off */ | |
79 { CMD, 0x50 }, /* CMD Display off */ | |
80 { CMD, 0x02 }, /* CMD Oscillation Mode Set */ | |
81 { DATA, 0x01 }, /* DATA: oscillator on */ | |
82 { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */ | |
83 { DATA, 0x01 }, /* DATA: Booster 1 on */ | |
84 { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */ | |
85 { DATA, 0x09 }, /* DATA: Booster 1 on, OP-AMP on */ | |
86 { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */ | |
87 { DATA, 0x0b }, /* DATA: Booster 1 + 2 on, OP-AMP on */ | |
88 { CMD, 0x26 }, /* CMD DCDC and AMP ON/OFF set */ | |
89 { DATA, 0x0f }, /* DATA: Booster 1 + 2 + 3 on, OP-AMP on */ | |
90 { CMD, 0x20 }, /* CMD DC-DC Select */ | |
91 { DATA, 0x01 }, /* DATA: step up x1.5 */ | |
92 { CMD, 0x24 }, /* CMD DCDC Clock Division Set */ | |
93 { DATA, 0x0a }, /* DATA: fPCK = fOSC/6 */ | |
94 { CMD, 0x2a }, /* CMD Contrast Control */ | |
95 { DATA, 0x2d }, /* DATA: default contrast */ | |
96 { CMD, 0x30 }, /* CMD Adressing mode set */ | |
97 { DATA, 0x0b }, /* DATA: 65536 color mode */ | |
98 { CMD, 0x10 }, /* CMD Driver output mode set */ | |
99 { DATA, 0x03 }, /* DATA: Display duty: 1/132 */ | |
100 { CMD, 0x34 }, /* CMD N-line inversion set */ | |
101 { DATA, 0x88 }, /* DATA: inversion on, one frame, every 8 blocks */ | |
102 { CMD, 0x40 }, /* CMD Entry mode set */ | |
103 { DATA, 0x00 }, /* DATA: Y address counter mode */ | |
104 { CMD, 0x28 }, /* CMD Temperature Compensation set */ | |
105 { DATA, 0x01 }, /* DATA: slope -0.05%/degC */ | |
106 { CMD, 0x32 }, /* CMD ROW vector mode set */ | |
107 { DATA, 0x01 }, /* DATA: every 2 subgroup */ | |
108 { CMD, 0x51 }, /* CMD Display on */ | |
109 { END, 0x00 }, /* MARKER: end of list */ | |
110 }; | |
111 | |
112 static void | |
113 fb_s6b33b1x_send_cmdlist(p) | |
114 struct s6b33b1x_cmdlist *p; | |
115 { | |
116 while(p->is_cmd != END) { | |
117 nCS4_ADDR0 = p->data; | |
118 p++; | |
119 } | |
120 } | |
121 | |
122 void | |
123 cmd_lcdinit() | |
124 { | |
125 GPIO_OUT_REG |= 0x0080; | |
126 fb_s6b33b1x_send_cmdlist(s6b33b1x_initdata); | |
127 } | |
128 | |
129 set_lcd_addr_region(xstart, xend, ystart, yend) | |
130 { | |
131 GPIO_OUT_REG |= 0x0080; | |
132 nCS4_ADDR0 = 0x42; | |
133 nCS4_ADDR0 = ystart + 4; | |
134 nCS4_ADDR0 = yend + 4; | |
135 nCS4_ADDR0 = 0x43; | |
136 nCS4_ADDR0 = xstart; | |
137 nCS4_ADDR0 = xend; | |
138 } | |
139 | |
140 void | |
141 cmd_lcdfill(argbulk) | |
142 char *argbulk; | |
143 { | |
144 int argc; | |
145 char *argv[6]; | |
146 u_long pixval; | |
147 int xstart, xend, ystart, yend; | |
148 int npix; | |
149 | |
150 if (parse_args(argbulk, 1, 5, argv, &argc) < 0) | |
151 return; | |
152 if (parse_hexarg(argv[0], 4, &pixval) < 0) { | |
153 printf("ERROR: arg1 must be a valid 16-bit hex value\n"); | |
154 return; | |
155 } | |
156 switch (argc) { | |
157 case 1: | |
158 xstart = ystart = 0; | |
159 xend = yend = 127; | |
160 break; | |
161 case 5: | |
162 xstart = atoi(argv[1]); | |
163 if (xstart < 0 || xstart > 127) { | |
164 range_err: printf("ERROR: coordinate arg out of range\n"); | |
165 return; | |
166 } | |
167 xend = atoi(argv[2]); | |
168 if (xend < 0 || xend > 127) | |
169 goto range_err; | |
170 ystart = atoi(argv[3]); | |
171 if (ystart < 0 || ystart > 127) | |
172 goto range_err; | |
173 yend = atoi(argv[4]); | |
174 if (yend < 0 || yend > 127) | |
175 goto range_err; | |
176 if (xend < xstart || yend < ystart) { | |
177 printf("ERROR: negative range\n"); | |
178 return; | |
179 } | |
180 break; | |
181 default: | |
182 printf("ERROR: wrong number of arguments\n"); | |
183 return; | |
184 } | |
185 set_lcd_addr_region(xstart, xend, ystart, yend); | |
186 npix = (xend + 1 - xstart) * (yend + 1 - ystart); | |
187 while (npix--) | |
188 nCS4_ADDR2 = pixval; | |
189 } | |
190 | |
191 void | |
192 cmd_lcdtest() | |
193 { | |
194 int i, j, k, p; | |
195 | |
196 /* | |
197 * The result of this command should be 8 vertical bars | |
198 * in the natural RGB order. | |
199 */ | |
200 set_lcd_addr_region(10, 89, 10, 89); | |
201 for (i = 0; i < 80; i++) { | |
202 for (j = 0; j < 8; j++) { | |
203 p = 0; | |
204 if (j & 4) | |
205 p |= 0xF800; | |
206 if (j & 2) | |
207 p |= 0x07E0; | |
208 if (j & 1) | |
209 p |= 0x001F; | |
210 for (k = 0; k < 10; k++) | |
211 nCS4_ADDR2 = p; | |
212 } | |
213 } | |
214 } | |
215 | |
216 void | |
217 cmd_blit(argbulk) | |
218 char *argbulk; | |
219 { | |
220 int argc; | |
221 char *argv[6]; | |
222 u16 imgbuf[16384]; | |
223 size_t img_file_size; | |
224 int xstart, ystart, width, height; | |
225 int npix, i; | |
226 | |
227 if (parse_args(argbulk, 1, 5, argv, &argc) < 0) | |
228 return; | |
229 if (mpffs_read_into_ram(argv[0], imgbuf, 32768, &img_file_size) < 0) | |
230 return; | |
231 switch (argc) { | |
232 case 1: | |
233 xstart = ystart = 0; | |
234 width = height = 128; | |
235 break; | |
236 case 3: | |
237 xstart = ystart = 0; | |
238 goto widthheight; | |
239 case 5: | |
240 xstart = atoi(argv[3]); | |
241 if (xstart < 0 || xstart > 127) { | |
242 range_err: printf("ERROR: coordinate arg out of range\n"); | |
243 return; | |
244 } | |
245 ystart = atoi(argv[4]); | |
246 if (ystart < 0 || ystart > 127) | |
247 goto range_err; | |
248 /* FALL THRU */ | |
249 widthheight: | |
250 width = atoi(argv[1]); | |
251 if (width < 1 || width > 128) | |
252 goto range_err; | |
253 height = atoi(argv[2]); | |
254 if (height < 1 || height > 128) | |
255 goto range_err; | |
256 if (xstart + width > 128) | |
257 goto range_err; | |
258 if (ystart + height > 128) | |
259 goto range_err; | |
260 break; | |
261 default: | |
262 printf("ERROR: wrong number of arguments\n"); | |
263 return; | |
264 } | |
265 npix = width * height; | |
266 if (img_file_size != npix * 2) { | |
267 printf("ERROR: image file size (%u bytes) does not match WxH\n", | |
268 img_file_size); | |
269 return; | |
270 } | |
271 set_lcd_addr_region(xstart, xstart + width - 1, | |
272 ystart, ystart + height - 1); | |
273 /* the artwork images in Pirelli's FFS appear to be inverted */ | |
274 for (i = 0; i < npix; i++) | |
275 nCS4_ADDR2 = ~imgbuf[i]; | |
276 } |