1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: 17: 18: 19:
20: #include "kbpd.h"
21: #include <tk/syslib.h>
22: #include <device/devconf.h>
23: #include <device/em1d512_iic.h>
24:
25:
26: IMPORT W GetDevConf(UB *name, W *val);
27:
28: LOCAL ID FlgID;
29:
30: #define TpFlg (1 << 0)
31: #define SwFlg (1 << 1)
32:
33:
34:
35: typedef struct {
36: W x_bias;
37: W x_span;
38: W y_bias;
39: W y_span;
40: W nodsp;
41: W rate_off;
42: W rate_on;
43: } TABPAR;
44:
45: LOCAL TABPAR TabPar = {944, -880, 912, -832, 0, 50, 50};
46:
47: #define ACC_DELTA_X (8)
48: #define ACC_DELTA_Y (8)
49: #define INV_DELTA_X (0)
50: #define INV_DELTA_Y (0)
51:
52: LOCAL W px, py, pb, ax, ay;
53: LOCAL RawEvt PrevTpEvt;
54: LOCAL UW PrevTpSts = 0;
55: LOCAL W CurrTpSw = 0;
56: LOCAL W TpActive = 1;
57: LOCAL FastLock HwLock_tp;
58: LOCAL ID TpTaskID;
59:
60: #define TpVec IV_GPIO(0)
61: #define RETRY 4
62:
63:
64: LOCAL W ReadDA9052(W reg)
65: {
66: W er, i;
67: UB cmd[2];
68:
69: for (i = RETRY; i > 0; i--) {
70: cmd[0] = (reg << 1) | 1;
71: cmd[1] = ~0;
72: er = em1d512_spixfer(0, cmd, cmd, sizeof(cmd));
73: if (er >= E_OK) return cmd[1];
74: }
75:
76: DP(("ReadDA9052(R%d) [%#x]\n", reg, er));
77: return er;
78: }
79:
80:
81: LOCAL W WriteDA9052(W reg, W dat)
82: {
83: W er, i;
84: UB cmd[2];
85:
86: for (i = RETRY; i > 0; i--) {
87: cmd[0] = reg << 1;
88: cmd[1] = dat;
89: er = em1d512_spixfer(0, cmd, cmd, sizeof(cmd));
90: if (er >= E_OK) return E_OK;
91: }
92:
93: DP(("WriteDA9052(R%d, %#x) [%#x]\n", reg, dat, er));
94: return er;
95: }
96:
97:
98: LOCAL void tpproc(InMsg *msg)
99: {
100: W x, y, sw, dx, dy;
101: RawEvt evt;
102: union {
103: PdInStat stat;
104: UW uw;
105: } u;
106:
107: sw = msg->hw.dt[0];
108: x = msg->hw.dt[2] | (msg->hw.dt[3] << 8);
109: y = msg->hw.dt[4] | (msg->hw.dt[5] << 8);
110:
111: if (!sw) {
112: if (!pb) goto fin;
113: x = px;
114: y = py;
115: } else {
116: if (pb) {
117:
118: dx = x - px;
119: dy = y - py;
120: if (dx < 0 && (dx += INV_DELTA_X) > 0) dx = 0;
121: if (dx > 0 && (dx -= INV_DELTA_X) < 0) dx = 0;
122: if (dy < 0 && (dy += INV_DELTA_Y) > 0) dy = 0;
123: if (dy > 0 && (dy -= INV_DELTA_Y) < 0) dy = 0;
124: ax += dx;
125: ay += dy;
126: if (ax > -ACC_DELTA_X && ax < ACC_DELTA_X &&
127: ay > -ACC_DELTA_Y && ay < ACC_DELTA_Y) goto fin;
128: }
129: }
130: ax = ay = 0;
131: px = x;
132: py = y;
133:
134:
135: u.uw = 0;
136: evt.p.stat = u.stat;
137: evt.p.stat.cmd = INP_PD;
138: evt.p.stat.main = pb = sw ? 1 : 0;
139: evt.p.stat.abs = 1;
140: evt.p.stat.norel = 1;
141: evt.p.stat.nodsp = TabPar.nodsp;
142:
143:
144: x = (x - TabPar.x_bias) * PDIN_XMAX / TabPar.x_span;
145: y = (y - TabPar.y_bias) * PDIN_YMAX / TabPar.y_span;
146:
147: evt.p.xpos = (x < 0) ? 0 : ((x > PDIN_XMAX) ? PDIN_XMAX : x);
148: evt.p.ypos = (y < 0) ? 0 : ((y > PDIN_YMAX) ? PDIN_YMAX : y);
149:
150:
151: kpSendPdEvt(&evt, &PrevTpSts, &PrevTpEvt);
152:
153: fin:
154: return;
155: }
156:
157:
158: LOCAL void tpIntEnable(void)
159: {
160: 161: 162:
163: SetIntMode(TpVec, IM_ENA | IM_LEVEL | IM_LOW);
164: EnableInt(TpVec);
165:
166: return;
167: }
168:
169:
170: LOCAL void tpIntDisable(void)
171: {
172: DisableInt(TpVec);
173: SetIntMode(TpVec, IM_DIS);
174:
175: return;
176: }
177:
178:
179: LOCAL void tp_inthdr(INTVEC vec)
180: {
181:
182: tk_set_flg(FlgID, TpFlg);
183:
184:
185: DisableInt(vec);
186:
187: return;
188: }
189:
190:
191: LOCAL ER tpread(UW *x, UW *y, UW *sw)
192: {
193: W sts, xmsb, ymsb, xylsb;
194:
195:
196: if ((sts = ReadDA9052(6)) < 0 ||
197: (xmsb = ReadDA9052(107)) < 0 ||
198: (ymsb = ReadDA9052(108)) < 0 ||
199: (xylsb = ReadDA9052(109)) < 0) return E_IO;
200:
201:
202: *x = (ymsb << 2) | ((xylsb & 0x0c) >> 2);
203: *y = (xmsb << 2) | ((xylsb & 0x03) >> 0);
204: *sw = xylsb & 0x40;
205:
206:
207: return (*sw && !(sts & 0x80)) ? E_BUSY : E_OK;
208: }
209:
210:
211: LOCAL void tpscan(void)
212: {
213: ER er;
214: UW x, y, sw;
215: InMsg msg;
216:
217:
218: er = tpread(&x, &y, &sw);
219: if (er < E_OK) goto fin0;
220:
221:
222: if(!sw && !CurrTpSw) goto fin0;
223:
224:
225: CurrTpSw = sw;
226:
227: msg.hw.id = HWPD;
228: msg.hw.dt[0] = sw;
229: msg.hw.dt[2] = x & 0xff;
230: msg.hw.dt[3] = (x >> 8) & 0xff;
231: msg.hw.dt[4] = y & 0xff;
232: msg.hw.dt[5] = (y >> 8) & 0xff;
233: tk_snd_mbf(InpMbf, &msg, sizeof(msg), TMO_POL);
234: fin0:
235: return;
236: }
237:
238:
239: LOCAL void tp_task(void)
240: {
241: ER er;
242: W i;
243: UINT flg;
244: LOCAL const UB tpsetup[] = {
245: 10, 0xff,
246: 11, 0xbf,
247: 12, 0xff,
248: 13, 0xff,
249: 5, 0xff,
250: 6, 0xff,
251: 7, 0xff,
252: 8, 0xff,
253: 22, 0x09,
254: 23, 0x00,
255: 24, 0x00,
256: 105, 0xc3,
257: 106, 0x80,
258: 82, 0x40,
259: 0, 0x00,
260: };
261:
262:
263: for (i = 0; tpsetup[i]; i += 2) {
264: er = WriteDA9052(tpsetup[i], tpsetup[i + 1]);
265: if (er < E_OK) goto fin0;
266: }
267:
268:
269: tpIntEnable();
270:
271: while (1) {
272:
273: tk_wai_flg(FlgID, TpFlg, TWF_ANDW | TWF_BITCLR, &flg, TMO_FEVR);
274:
275:
276:
277:
278: while (1) {
279: Lock(&HwLock_tp);
280: tpscan();
281: Unlock(&HwLock_tp);
282:
283: if (CurrTpSw) {
284: tk_dly_tsk(TabPar.rate_on);
285: WriteDA9052(6, 0xc0);
286: } else {
287: 288: 289: 290:
291: WriteDA9052(6, 0xc0);
292: tk_dly_tsk(TabPar.rate_off);
293: break;
294: }
295: }
296:
297:
298: EnableInt(TpVec);
299: }
300:
301: fin0:
302: tpIntDisable();
303: tk_exd_tsk();
304: }
305:
306:
307: LOCAL ER tpstart(BOOL start)
308: {
309: ER er;
310: W n, par[L_DEVCONF_VAL];
311: T_DINT dint;
312: T_CTSK ctsk;
313:
314:
315: if (!start) {
316: er = E_OK;
317: if (!TpActive) goto fin0;
318: else goto fin4;
319: }
320:
321:
322: n = GetDevConf("TEngUseTablet", par);
323: if (n > 0) TpActive = par[0] ? 1 : 0;
324: if (!TpActive) goto fin0;
325:
326:
327: n = GetDevConf("TEngTabletPar", par);
328: if (n >= 6 && par[1] != 0 && par[3] != 0) {
329: TabPar.x_bias = par[0];
330: TabPar.x_span = par[1];
331: TabPar.y_bias = par[2];
332: TabPar.y_span = par[3];
333: TabPar.nodsp = par[4] ? 1 : 0;
334: TabPar.rate_off = par[5];
335: TabPar.rate_on = (n >= 7) ? par[6] : par[5];
336: }
337:
338:
339: er = CreateLock(&HwLock_tp, "lkbY");
340: if (er < E_OK) goto fin0;
341:
342:
343: dint.inthdr = tp_inthdr;
344: dint.intatr = TA_HLNG;
345: er = tk_def_int(TpVec, &dint);
346: if (er < E_OK) goto fin1;
347:
348:
349: SetOBJNAME(ctsk.exinf, "lkbY");
350: ctsk.task = tp_task;
351: ctsk.itskpri = DEF_PRIORITY;
352: ctsk.stksz = TASK_STKSZ;
353: ctsk.tskatr = TA_HLNG | TA_RNG0;
354: er = tk_cre_tsk(&ctsk);
355: if (er < E_OK) goto fin2;
356: TpTaskID = er;
357:
358:
359: er = tk_sta_tsk(TpTaskID, 0);
360: if (er < E_OK) goto fin3;
361:
362: er = E_OK;
363: goto fin0;
364: fin4:
365: tpIntDisable();
366: tk_ter_tsk(TpTaskID);
367: fin3:
368: tk_del_tsk(TpTaskID);
369: fin2:
370: tk_def_int(TpVec, NULL);
371: fin1:
372: DeleteLock(&HwLock_tp);
373: fin0:
374: return er;
375: }
376:
377:
378: LOCAL UB PrevSwMsg = 0;
379: LOCAL UB PrevSwSts = 0;
380: LOCAL FastLock HwLock_sw;
381: LOCAL ID SwTaskID;
382:
383: LOCAL const INTVEC SwVec[] = {IV_GPIO(4), IV_GPIO(6), IV_GPIO(7)};
384: LOCAL const UB KeyCode[] = {
385:
386: 0x6f, 0x00, 0x6d, 0x6e, 0x00,
387: };
388:
389: #define GIOBase(x) (0xc0050000 + 0x00000040 * (x))
390: #define GIO_L 0x00
391: #define GIO_I(x) (GIOBase(x) + 0x0010)
392:
393:
394: LOCAL void swproc(InMsg *msg)
395: {
396: INT i, mask, kchg, kcode;
397:
398:
399: kchg = PrevSwMsg ^ msg->hw.dt[0];
400: for (i = 0, mask = 1; i < sizeof(KeyCode); i++, mask <<= 1) {
401: if (!(mask & kchg)) continue;
402:
403: kcode = KeyCode[i];
404: if (kcode) kpSendKeyEvt((msg->hw.dt[0] & mask) ?
405: 0x01 : 0x00, kcode);
406: }
407:
408:
409: PrevSwMsg = msg->hw.dt[0];
410:
411: return;
412: }
413:
414:
415: LOCAL void swIntEnable(void)
416: {
417: W i;
418:
419: for (i = 0; i < sizeof(SwVec) / sizeof(INTVEC); i++) {
420: SetIntMode(SwVec[i], IM_ENA | IM_EDGE | IM_BOTH);
421: ClearInt(SwVec[i]);
422: EnableInt(SwVec[i]);
423: }
424:
425: return;
426: }
427:
428:
429: LOCAL void swIntDisable(void)
430: {
431: W i;
432:
433: for (i = 0; i < sizeof(SwVec) / sizeof(INTVEC); i++) {
434: DisableInt(SwVec[i]);
435: SetIntMode(SwVec[i], IM_DIS);
436: ClearInt(SwVec[i]);
437: }
438:
439: return;
440: }
441:
442:
443: LOCAL void sw_inthdr(INTVEC vec)
444: {
445:
446: tk_set_flg(FlgID, SwFlg);
447:
448:
449: ClearInt(vec);
450:
451: return;
452: }
453:
454:
455: LOCAL void swscan(void)
456: {
457: InMsg msg;
458: UW sw;
459:
460:
461: sw = in_w(GIO_I(GIO_L));
462:
463:
464: sw &= 0x000000d0;
465: sw >>= 4;
466:
467:
468: if (sw != PrevSwSts) {
469: msg.hw.id = HWKB;
470: msg.hw.dt[0] = sw;
471: tk_snd_mbf(InpMbf, &msg, sizeof(msg), TMO_POL);
472: PrevSwSts = sw;
473: }
474: return;
475: }
476:
477:
478: LOCAL void sw_task(void)
479: {
480: UINT flg;
481:
482:
483: swIntEnable();
484:
485: while (1) {
486:
487: tk_clr_flg(FlgID, ~SwFlg);
488: tk_wai_flg(FlgID, SwFlg, TWF_ANDW, &flg, TMO_FEVR);
489:
490:
491: tk_dly_tsk(10);
492:
493:
494: Lock(&HwLock_sw);
495: swscan();
496: Unlock(&HwLock_sw);
497: }
498:
499:
500: swIntDisable();
501: tk_exd_tsk();
502: }
503:
504:
505: LOCAL ER swstart(BOOL start)
506: {
507: ER er;
508: W i;
509: T_DINT dint;
510: T_CTSK ctsk;
511:
512:
513: if (!start) {
514: er = E_OK;
515: goto fin4;
516: }
517:
518:
519: er = CreateLock(&HwLock_sw, "lkbX");
520: if (er < E_OK) goto fin0;
521:
522:
523: dint.inthdr = sw_inthdr;
524: dint.intatr = TA_HLNG;
525: for (i = 0; i < sizeof(SwVec) / sizeof(INTVEC); i++) {
526: er = tk_def_int(SwVec[i], &dint);
527: if (er < E_OK) goto fin2;
528: }
529:
530:
531: SetOBJNAME(ctsk.exinf, "lkbX");
532: ctsk.task = sw_task;
533: ctsk.itskpri = DEF_PRIORITY;
534: ctsk.stksz = TASK_STKSZ;
535: ctsk.tskatr = TA_HLNG | TA_RNG0;
536: er = tk_cre_tsk(&ctsk);
537: if (er < E_OK) goto fin2;
538: SwTaskID = er;
539:
540:
541: er = tk_sta_tsk(SwTaskID, 0);
542: if (er < E_OK) goto fin3;
543:
544: er = E_OK;
545: goto fin0;
546: fin4:
547: swIntDisable();
548: tk_ter_tsk(SwTaskID);
549: fin3:
550: tk_del_tsk(SwTaskID);
551: fin2:
552: for (i = 0; i < sizeof(SwVec) / sizeof(INTVEC); i++) {
553: tk_def_int(SwVec[i], NULL);
554: }
555:
556: DeleteLock(&HwLock_sw);
557: fin0:
558: return er;
559: }
560:
561:
562:
563: EXPORT void hwProc(InMsg *msg)
564: {
565: switch (msg->hw.id) {
566: case HWKB: swproc(msg); break;
567: case HWPD: if (TpActive) tpproc(msg); break;
568: default: break;
569: }
570:
571: return;
572: }
573:
574:
575: EXPORT void hwImode(W inpmd)
576: {
577: return;
578: }
579:
580:
581: EXPORT ER hwInit(W cmd)
582: {
583: ER er;
584: T_CFLG cflg;
585:
586: switch (cmd) {
587: default:
588: return E_OK;
589:
590: case DC_SUSPEND:
591: Lock(&HwLock_sw);
592: if (TpActive) Lock(&HwLock_tp);
593: return E_OK;
594:
595: case DC_RESUME:
596: if (TpActive) Unlock(&HwLock_tp);
597: Unlock(&HwLock_sw);
598: return E_OK;
599:
600: case DC_OPEN:
601: break;
602: }
603:
604:
605: if ( (er = em1d512_iicspi_svc(TRUE)) < E_OK ) goto fin0;
606:
607: SetOBJNAME(cflg.exinf, "lkbZ");
608: cflg.flgatr = TA_TFIFO | TA_WMUL;
609: cflg.iflgptn = 0;
610: er = tk_cre_flg(&cflg);
611: if (er < E_OK) goto fin0;
612: FlgID = er;
613:
614: er = swstart(TRUE);
615: if (er < E_OK) goto fin1;
616:
617: er = tpstart(TRUE);
618: if (er < E_OK) goto fin2;
619:
620: er = E_OK;
621: goto fin0;
622:
623:
624: tpstart(FALSE);
625: fin2:
626: swstart(FALSE);
627: fin1:
628: tk_del_flg(FlgID);
629: fin0:
630: return er;
631: }