kbd.c
Go to the documentation of this file.00001
00044 #include "hw/hw_kbd.h"
00045
00046 #include "cfg/cfg_kbd.h"
00047 #include <cfg/debug.h>
00048 #include <cfg/module.h>
00049
00050 #include <drv/timer.h>
00051 #include <drv/kbd.h>
00052
00053
00054
00055 #if !defined(CONFIG_KBD_POLL) || (CONFIG_KBD_POLL != KBD_POLL_SOFTINT)
00056 #error CONFIG_KBD_POLL must be defined to either KBD_POLL_SOFTINT
00057 #endif
00058 #if !defined(CONFIG_KBD_BEEP) || (CONFIG_KBD_BEEP != 0 && CONFIG_KBD_BEEP != 1)
00059 #error CONFIG_KBD_BEEP must be defined to either 0 or 1
00060 #endif
00061 #if !defined(CONFIG_KBD_OBSERVER) || (CONFIG_KBD_OBSERVER != 0 && CONFIG_KBD_OBSERVER != 1)
00062 #error CONFIG_KBD_OBSERVER must be defined to either 0 or 1
00063 #endif
00064 #if !defined(CONFIG_KBD_LONGPRESS) || (CONFIG_KBD_LONGPRESS != 0 && CONFIG_KBD_LONGPRESS != 1)
00065 #error CONFIG_KBD_LONGPRESS must be defined to either 0 or 1
00066 #endif
00067
00068 #if CONFIG_KBD_BEEP
00069 #include <drv/buzzer.h>
00070 #endif
00071
00072 #define KBD_CHECK_INTERVAL 10
00073 #define KBD_DEBOUNCE_TIME 30
00074 #define KBD_BEEP_TIME 5
00076 #define KBD_REPEAT_DELAY 400
00077 #define KBD_REPEAT_RATE 100
00078 #define KBD_REPEAT_MAXRATE 20
00079 #define KBD_REPEAT_ACCEL 5
00081 #define KBD_LNG_DELAY 1000
00085 static enum { KS_IDLE, KS_REPDELAY, KS_REPEAT } kbd_rptStatus;
00086
00087
00088 static volatile keymask_t kbd_buf;
00089 static volatile keymask_t kbd_cnt;
00090 static keymask_t kbd_rpt_mask;
00092 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
00093 static Timer kbd_timer;
00094 #endif
00095
00096 static List kbd_rawHandlers;
00097 static List kbd_handlers;
00099 static KbdHandler kbd_defHandler;
00100 static KbdHandler kbd_debHandler;
00101 static KbdHandler kbd_rptHandler;
00103 #if CONFIG_KBD_LONGPRESS
00104 static KbdHandler kbd_lngHandler;
00105 #endif
00106
00107 #if CONFIG_KBD_OBSERVER
00108 #include <mware/observer.h>
00109 Subject kbd_subject;
00110 #endif
00111
00112
00122 static void kbd_poll(void)
00123 {
00125 static keymask_t current_key;
00126
00127 struct KbdHandler *handler;
00128 keymask_t key = kbd_readkeys();
00129
00130
00131 FOREACH_NODE(handler, &kbd_rawHandlers)
00132 key = handler->hook(key);
00133
00134
00135 if (key != current_key)
00136 {
00137
00138 current_key = key;
00139
00140
00141 FOREACH_NODE(handler, &kbd_handlers)
00142 key = handler->hook(key);
00143 }
00144 }
00145
00146 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
00147
00151 static void kbd_softint(UNUSED_ARG(iptr_t, arg))
00152 {
00153 kbd_poll();
00154 timer_add(&kbd_timer);
00155 }
00156
00157 #else
00158 #error "Define keyboard poll method"
00159
00160 #endif
00161
00176 keymask_t kbd_peek(void)
00177 {
00178 keymask_t key = 0;
00179
00180 #if CONFIG_KBD_SCHED
00181 extern void schedule(void);
00182 schedule();
00183 #endif
00184
00185
00186 IRQ_DISABLE;
00187 if (kbd_cnt)
00188 {
00189 --kbd_cnt;
00190 key = kbd_buf;
00191 }
00192 IRQ_ENABLE;
00193
00194 return key;
00195 }
00196
00202 keymask_t kbd_get(void)
00203 {
00204 keymask_t key;
00205
00206 while (!(key = kbd_peek())) {}
00207
00208 return key;
00209 }
00210
00211
00217 keymask_t kbd_get_timeout(mtime_t timeout)
00218 {
00219 keymask_t key;
00220
00221 ticks_t start = timer_clock();
00222 ticks_t stop = ms_to_ticks(timeout);
00223 do
00224 {
00225 if ((key = kbd_peek()))
00226 return key;
00227 }
00228 while (timer_clock() - start < stop);
00229
00230 return K_TIMEOUT;
00231 }
00232
00233
00234 void kbd_addHandler(struct KbdHandler *handler)
00235 {
00236 KbdHandler *node;
00237 List *list;
00238
00239 cpu_flags_t flags;
00240 IRQ_SAVE_DISABLE(flags);
00241
00242
00243 list = (handler->flags & KHF_RAWKEYS) ?
00244 &kbd_rawHandlers : &kbd_handlers;
00245
00246
00247
00248
00249
00250 FOREACH_NODE(node,list)
00251 if (node->pri < handler->pri)
00252 break;
00253
00254
00255 INSERT_BEFORE(&handler->link, &node->link);
00256
00257 IRQ_RESTORE(flags);
00258 }
00259
00260
00261 void kbd_remHandler(struct KbdHandler *handler)
00262 {
00263
00264 ATOMIC(REMOVE(&handler->link));
00265 }
00266
00267
00274 static keymask_t kbd_defHandlerFunc(keymask_t key)
00275 {
00276 if (key)
00277 {
00278
00279 kbd_buf = key;
00280 kbd_cnt = 1;
00281
00282 #if CONFIG_KBD_OBSERVER
00283 observer_notify(&kbd_subject, KBD_EVENT_KEY, &key);
00284 #endif
00285
00286 #if CONFIG_KBD_BEEP
00287 if (!(key & K_REPEAT))
00288 buz_beep(KBD_BEEP_TIME);
00289 #endif
00290 }
00291
00292
00293 return 0;
00294 }
00295
00299 static keymask_t kbd_debHandlerFunc(keymask_t key)
00300 {
00302 static keymask_t debounce_key;
00303
00305 static ticks_t debounce_time;
00306
00308 static keymask_t new_key;
00309
00310
00311 ticks_t now = timer_clock();
00312
00313 if (key != debounce_key)
00314 {
00315
00316 debounce_key = key;
00317 debounce_time = now;
00318 }
00319 else if ((new_key != debounce_key)
00320 && (now - debounce_time > ms_to_ticks(KBD_DEBOUNCE_TIME)))
00321 {
00322 new_key = debounce_key;
00323 debounce_time = now;
00324 }
00325
00326 return new_key;
00327 }
00328
00329 #if CONFIG_KBD_LONGPRESS
00330
00333 static keymask_t kbd_lngHandlerFunc(keymask_t key)
00334 {
00335 static ticks_t start;
00336 ticks_t now = timer_clock();
00337
00338 if (key & K_LNG_MASK)
00339 {
00340 if (now - start > ms_to_ticks(KBD_LNG_DELAY))
00341 key |= K_LONG;
00342 }
00343 else
00344 start = now;
00345 return key;
00346 }
00347 #endif
00348
00352 keymask_t kbd_setRepeatMask(keymask_t mask)
00353 {
00354 keymask_t oldmask = kbd_rpt_mask;
00355 ATOMIC(kbd_rpt_mask = mask);
00356 return oldmask;
00357 }
00358
00362 static keymask_t kbd_rptHandlerFunc(keymask_t key)
00363 {
00364
00365 static ticks_t repeat_time;
00366
00367
00368 static ticks_t repeat_rate;
00370 ticks_t now = timer_clock();
00371
00372 switch (kbd_rptStatus)
00373 {
00374 case KS_IDLE:
00375 if (key & kbd_rpt_mask)
00376 {
00377 repeat_time = now;
00378 kbd_rptStatus = KS_REPDELAY;
00379 }
00380 break;
00381
00382 case KS_REPDELAY:
00383 if (key & kbd_rpt_mask)
00384 {
00385 if (now - repeat_time > ms_to_ticks(KBD_REPEAT_DELAY))
00386 {
00387 key = (key & kbd_rpt_mask) | K_REPEAT;
00388 repeat_time = now;
00389 repeat_rate = ms_to_ticks(KBD_REPEAT_RATE);
00390 kbd_rptStatus = KS_REPEAT;
00391 }
00392 else
00393 key = 0;
00394 }
00395 else
00396 kbd_rptStatus = KS_IDLE;
00397 break;
00398
00399 case KS_REPEAT:
00400 if (key & kbd_rpt_mask)
00401 {
00402 if (now - repeat_time > repeat_rate)
00403 {
00404
00405 key = (key & kbd_rpt_mask) | K_REPEAT;
00406 repeat_time = now;
00407
00408
00409 if (repeat_rate > ms_to_ticks(KBD_REPEAT_MAXRATE))
00410 repeat_rate -= ms_to_ticks(KBD_REPEAT_ACCEL);
00411 }
00412 else
00413 key = 0;
00414 }
00415 else
00416 kbd_rptStatus = KS_IDLE;
00417
00418 break;
00419 }
00420
00421 return key;
00422 }
00423
00424
00425 MOD_DEFINE(kbd)
00426
00427
00430 void kbd_init(void)
00431 {
00432 #if CONFIG_KBD_BEEP
00433 MOD_CHECK(buzzer);
00434 #endif
00435
00436 KBD_HW_INIT;
00437
00438
00439 LIST_INIT(&kbd_handlers);
00440 LIST_INIT(&kbd_rawHandlers);
00441
00442
00443 kbd_debHandler.hook = kbd_debHandlerFunc;
00444 kbd_debHandler.pri = 100;
00445 kbd_debHandler.flags = KHF_RAWKEYS;
00446 kbd_addHandler(&kbd_debHandler);
00447
00448 #if CONFIG_KBD_LONGPRESS
00449
00450 kbd_lngHandler.hook = kbd_lngHandlerFunc;
00451 kbd_lngHandler.pri = 90;
00452 kbd_lngHandler.flags = KHF_RAWKEYS;
00453 kbd_addHandler(&kbd_lngHandler);
00454 #endif
00455
00456
00457 kbd_rptHandler.hook = kbd_rptHandlerFunc;
00458 kbd_rptHandler.pri = 80;
00459 kbd_rptHandler.flags = KHF_RAWKEYS;
00460 kbd_addHandler(&kbd_rptHandler);
00461
00462
00463 kbd_defHandler.hook = kbd_defHandlerFunc;
00464 kbd_defHandler.pri = -128;
00465 kbd_addHandler(&kbd_defHandler);
00466
00467 #if CONFIG_KBD_OBSERVER
00468 observer_InitSubject(&kbd_subject);
00469 #endif
00470
00471 #if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
00472
00473 MOD_CHECK(timer);
00474
00475
00476 event_initSoftint(&kbd_timer.expire, kbd_softint, NULL);
00477 timer_setDelay(&kbd_timer, ms_to_ticks(KBD_CHECK_INTERVAL));
00478 timer_add(&kbd_timer);
00479
00480 #else
00481 #error "Define keyboard poll method"
00482
00483 #endif
00484
00485 MOD_INIT(kbd);
00486 }