screen.c 9.9 KB

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