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 }