FreeBSD/Linux Kernel Cross Reference
sys/bitsy/screen.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "ureg.h"
8 #include "../port/error.h"
9
10 #define Image IMAGE
11 #include <draw.h>
12 #include <memdraw.h>
13 #include <cursor.h>
14 #include "screen.h"
15 #include "gamma.h"
16
17 #define MINX 8
18
19 int landscape = 0; /* orientation of the screen, default is 0: portait */
20
21 enum {
22 Wid = 240,
23 Ht = 320,
24 Pal0 = 0x2000, /* 16-bit pixel data in active mode (12 in passive) */
25
26 hsw = 0x00,
27 elw = 0x0e,
28 blw = 0x0d,
29
30 vsw = 0x02,
31 efw = 0x01,
32 bfw = 0x0a,
33
34 pcd = 0x10,
35 };
36
37 struct sa1110fb {
38 /* Frame buffer for 16-bit active color */
39 short palette[16]; /* entry 0 set to Pal0, the rest to 0 */
40 ushort pixel[Wid*Ht]; /* Pixel data */
41 } *framebuf;
42
43 enum {
44 /* LCD Control Register 0, lcd->lccr0 */
45 LEN = 0, /* 1 bit */
46 CMS = 1, /* 1 bit */
47 SDS = 2, /* 1 bit */
48 LDM = 3, /* 1 bit */
49 BAM = 4, /* 1 bit */
50 ERM = 5, /* 1 bit */
51 PAS = 7, /* 1 bit */
52 BLE = 8, /* 1 bit */
53 DPD = 9, /* 1 bit */
54 PDD = 12, /* 8 bits */
55 };
56
57 enum {
58 /* LCD Control Register 1, lcd->lccr1 */
59 PPL = 0, /* 10 bits */
60 HSW = 10, /* 6 bits */
61 ELW = 16, /* 8 bits */
62 BLW = 24, /* 8 bits */
63 };
64
65 enum {
66 /* LCD Control Register 2, lcd->lccr2 */
67 LPP = 0, /* 10 bits */
68 VSW = 10, /* 6 bits */
69 EFW = 16, /* 8 bits */
70 BFW = 24, /* 8 bits */
71 };
72
73 enum {
74 /* LCD Control Register 3, lcd->lccr3 */
75 PCD = 0, /* 8 bits */
76 ACB = 8, /* 8 bits */
77 API = 16, /* 4 bits */
78 VSP = 20, /* 1 bit */
79 HSP = 21, /* 1 bit */
80 PCP = 22, /* 1 bit */
81 OEP = 23, /* 1 bit */
82 };
83
84 enum {
85 /* LCD Status Register, lcd->lcsr */
86 LDD = 0, /* 1 bit */
87 BAU = 1, /* 1 bit */
88 BER = 2, /* 1 bit */
89 ABC = 3, /* 1 bit */
90 IOL = 4, /* 1 bit */
91 IUL = 5, /* 1 bit */
92 OIU = 6, /* 1 bit */
93 IUU = 7, /* 1 bit */
94 OOL = 8, /* 1 bit */
95 OUL = 9, /* 1 bit */
96 OOU = 10, /* 1 bit */
97 OUU = 11, /* 1 bit */
98 };
99
100 struct sa1110regs {
101 ulong lccr0;
102 ulong lcsr;
103 ulong dummies[2];
104 short* dbar1;
105 ulong dcar1;
106 ulong dbar2;
107 ulong dcar2;
108 ulong lccr1;
109 ulong lccr2;
110 ulong lccr3;
111 } *lcd;
112
113 Point ZP = {0, 0};
114
115 static Memdata xgdata;
116
117 static Memimage xgscreen =
118 {
119 { 0, 0, Wid, Ht }, /* r */
120 { 0, 0, Wid, Ht }, /* clipr */
121 16, /* depth */
122 3, /* nchan */
123 RGB16, /* chan */
124 nil, /* cmap */
125 &xgdata, /* data */
126 0, /* zero */
127 Wid/2, /* width */
128 0, /* layer */
129 0, /* flags */
130 };
131
132 struct{
133 Point pos;
134 int bwid;
135 }out;
136
137 Memimage *gscreen;
138 Memimage *conscol;
139 Memimage *back;
140
141 Memsubfont *memdefont;
142
143 Lock screenlock;
144
145 Point ZP = {0, 0};
146 ushort *vscreen; /* virtual screen */
147 Rectangle window;
148 Point curpos;
149 int h, w;
150 int drawdebug;
151
152 static ulong rep(ulong, int);
153 static void screenwin(void);
154 static void screenputc(char *buf);
155 static void bitsyscreenputs(char *s, int n);
156 static void scroll(void);
157
158 static void
159 lcdinit(void)
160 {
161 /* the following line works because main memory is direct mapped */
162 gpioregs->direction |=
163 GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
164 |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o;
165 gpioregs->altfunc |=
166 GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
167 |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o;
168 framebuf->palette[0] = Pal0;
169 lcd->dbar1 = framebuf->palette;
170 lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
171 lcd->lccr2 = (Wid-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
172 lcd->lccr1 = (Ht-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
173 lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
174 }
175
176 void
177 flipscreen(int ls) {
178 if (ls == landscape)
179 return;
180 if (ls) {
181 gscreen->r = Rect(0, 0, Ht, Wid);
182 gscreen->clipr = gscreen->r;
183 gscreen->width = Ht/2;
184 xgdata.bdata = (uchar *)framebuf->pixel;
185 } else {
186 gscreen->r = Rect(0, 0, Wid, Ht);
187 gscreen->clipr = gscreen->r;
188 gscreen->width = Wid/2;
189 xgdata.bdata = (uchar *)vscreen;
190 }
191 landscape = ls;
192 }
193
194 void
195 lcdtweak(Cmdbuf *cmd)
196 {
197 if(cmd->nf < 4)
198 return;
199 if(*cmd->f[0] == 'h')
200 lcd->lccr1 = ((Ht-16)<<PPL)
201 | (atoi(cmd->f[1])<<HSW)
202 | (atoi(cmd->f[2])<<ELW)
203 | (atoi(cmd->f[3])<<BLW);
204 if(*cmd->f[0] == 'v')
205 lcd->lccr2 = ((Wid-1)<<LPP)
206 | (atoi(cmd->f[1])<<VSW)
207 | (atoi(cmd->f[2])<<EFW)
208 | (atoi(cmd->f[3])<<BFW);
209 }
210
211 void
212 screenpower(int on)
213 {
214 blankscreen(on == 0);
215 }
216
217 void
218 screeninit(void)
219 {
220 int i;
221
222 /* map the lcd regs into the kernel's virtual space */
223 lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;
224
225 framebuf = xspanalloc(sizeof *framebuf, 0x100, 0);
226
227 vscreen = xalloc(sizeof(ushort)*Wid*Ht);
228
229 lcdpower(1);
230 lcdinit();
231
232 gscreen = &xgscreen;
233
234 xgdata.ref = 1;
235 i = 0;
236 if (landscape) {
237 gscreen->r = Rect(0, 0, Ht, Wid);
238 gscreen->clipr = gscreen->r;
239 gscreen->width = Ht/2;
240 xgdata.bdata = (uchar *)framebuf->pixel;
241 while (i < Wid*Ht*1/3) framebuf->pixel[i++] = 0xf800; /* red */
242 while (i < Wid*Ht*2/3) framebuf->pixel[i++] = 0xffff; /* white */
243 while (i < Wid*Ht*3/3) framebuf->pixel[i++] = 0x001f; /* blue */
244 } else {
245 gscreen->r = Rect(0, 0, Wid, Ht);
246 gscreen->clipr = gscreen->r;
247 gscreen->width = Wid/2;
248 xgdata.bdata = (uchar *)vscreen;
249 while (i < Wid*Ht*1/3) vscreen[i++] = 0xf800; /* red */
250 while (i < Wid*Ht*2/3) vscreen[i++] = 0xffff; /* white */
251 while (i < Wid*Ht*3/3) vscreen[i++] = 0x001f; /* blue */
252 flushmemscreen(gscreen->r);
253 }
254 memimageinit();
255 memdefont = getmemdefont();
256
257 out.pos.x = MINX;
258 out.pos.y = 0;
259 out.bwid = memdefont->info[' '].width;
260
261 blanktime = 3; /* minutes */
262
263 screenwin();
264 // screenputs = bitsyscreenputs;
265 screenputs = nil;
266 }
267
268 void
269 flushmemscreen(Rectangle r)
270 {
271 int x, y;
272 ulong start, end;
273
274 if (landscape == 0) {
275 if (r.min.x < 0) r.min.x = 0;
276 if (r.max.x > Wid) r.max.x = Wid;
277 if (r.min.y < 0) r.min.y = 0;
278 if (r.max.y > Ht) r.max.y = Ht;
279 for (x = r.min.x; x < r.max.x; x++)
280 for (y = r.min.y; y < r.max.y; y++)
281 framebuf->pixel[(x+1)*Ht-1-y] = gamma[vscreen[y*Wid+x]];
282 start = (ulong)&framebuf->pixel[(r.min.x+1)*Ht-1-(r.max.y-1)];
283 end = (ulong)&framebuf->pixel[(r.max.x-1+1)*Ht-1-(r.min.y)];
284 } else {
285 start = (ulong)&framebuf->pixel[r.min.y*Ht + r.min.x];
286 end = (ulong)&framebuf->pixel[(r.max.y-1)*Ht + r.max.x - 1];
287 }
288 cachewbregion(start, end-start);
289 }
290
291 /*
292 * export screen to devdraw
293 */
294 uchar*
295 attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
296 {
297 *r = gscreen->r;
298 *d = gscreen->depth;
299 *chan = gscreen->chan;
300 *width = gscreen->width;
301 *softscreen = (landscape == 0);
302
303 return (uchar*)gscreen->data->bdata;
304 }
305
306 void
307 getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
308 {
309 USED(p, pr, pg, pb);
310 }
311
312 int
313 setcolor(ulong p, ulong r, ulong g, ulong b)
314 {
315 USED(p,r,g,b);
316 return 0;
317 }
318
319 void
320 blankscreen(int blank)
321 {
322 int cnt;
323
324 if (blank) {
325 lcd->lccr0 &= ~(1<<LEN); /* disable the LCD */
326 cnt = 0;
327 while((lcd->lcsr & (1<<LDD)) == 0) {
328 delay(10);
329 if (++cnt == 100) {
330 iprint("LCD doesn't stop\n");
331 break;
332 }
333 }
334 lcdpower(0);
335 } else {
336 lcdpower(1);
337 lcdinit();
338 }
339 }
340
341 static void
342 bitsyscreenputs(char *s, int n)
343 {
344 int i;
345 Rune r;
346 char buf[4];
347
348 if(!islo()) {
349 /* don't deadlock trying to print in interrupt */
350 if(!canlock(&screenlock))
351 return;
352 }
353 else
354 lock(&screenlock);
355
356 while(n > 0){
357 i = chartorune(&r, s);
358 if(i == 0){
359 s++;
360 --n;
361 continue;
362 }
363 memmove(buf, s, i);
364 buf[i] = 0;
365 n -= i;
366 s += i;
367 screenputc(buf);
368 }
369 unlock(&screenlock);
370 }
371
372 static void
373 screenwin(void)
374 {
375 Point p, q;
376 char *greet;
377 Memimage *orange;
378 Rectangle r;
379
380 memsetchan(gscreen, RGB16);
381
382 back = memwhite;
383 conscol = memblack;
384
385 orange = allocmemimage(Rect(0,0,1,1), RGB16);
386 orange->flags |= Frepl;
387 orange->clipr = gscreen->r;
388 orange->data->bdata[0] = 0x40;
389 orange->data->bdata[1] = 0xfd;
390
391 w = memdefont->info[' '].width;
392 h = memdefont->height;
393
394 r = insetrect(gscreen->r, 4);
395
396 memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
397 window = insetrect(r, 4);
398 memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
399
400 memimagedraw(gscreen, Rect(window.min.x, window.min.y,
401 window.max.x, window.min.y+h+5+6), orange, ZP, nil, ZP, S);
402 freememimage(orange);
403 window = insetrect(window, 5);
404
405 greet = " Plan 9 Console ";
406 p = addpt(window.min, Pt(10, 0));
407 q = memsubfontwidth(memdefont, greet);
408 memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
409 flushmemscreen(r);
410 window.min.y += h+6;
411 curpos = window.min;
412 window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
413 }
414
415 static void
416 screenputc(char *buf)
417 {
418 Point p;
419 int w, pos;
420 Rectangle r;
421 static int *xp;
422 static int xbuf[256];
423
424 if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
425 xp = xbuf;
426
427 switch(buf[0]) {
428 case '\n':
429 if(curpos.y+h >= window.max.y)
430 scroll();
431 curpos.y += h;
432 screenputc("\r");
433 break;
434 case '\r':
435 xp = xbuf;
436 curpos.x = window.min.x;
437 break;
438 case '\t':
439 p = memsubfontwidth(memdefont, " ");
440 w = p.x;
441 if(curpos.x >= window.max.x-4*w)
442 screenputc("\n");
443
444 pos = (curpos.x-window.min.x)/w;
445 pos = 4-(pos%4);
446 *xp++ = curpos.x;
447 r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
448 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
449 flushmemscreen(r);
450 curpos.x += pos*w;
451 break;
452 case '\b':
453 if(xp <= xbuf)
454 break;
455 xp--;
456 r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
457 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
458 flushmemscreen(r);
459 curpos.x = *xp;
460 break;
461 case '\0':
462 break;
463 default:
464 p = memsubfontwidth(memdefont, buf);
465 w = p.x;
466
467 if(curpos.x >= window.max.x-w)
468 screenputc("\n");
469
470 *xp++ = curpos.x;
471 r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
472 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
473 memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
474 flushmemscreen(r);
475 curpos.x += w;
476 }
477 }
478
479 static void
480 scroll(void)
481 {
482 int o;
483 Point p;
484 Rectangle r;
485
486 o = 8*h;
487 r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
488 p = Pt(window.min.x, window.min.y+o);
489 memimagedraw(gscreen, r, gscreen, p, nil, p, S);
490 flushmemscreen(r);
491 r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
492 memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
493 flushmemscreen(r);
494
495 curpos.y -= o;
496 }
Cache object: 6422eee492578a0d411bb24a4f68e13a
|