/*#*
*#* $Log$
+ *#* Revision 1.6 2006/03/20 17:50:17 bernie
+ *#* Add FreeRTOS and Observers support.
+ *#*
+ *#* Revision 1.5 2006/02/27 22:39:45 bernie
+ *#* Misc build and doc fixes from project_grl.
+ *#*
+ *#* Revision 1.4 2006/02/24 00:27:14 bernie
+ *#* Use new naming convention for list macros.
+ *#*
+ *#* Revision 1.3 2006/02/17 21:15:42 bernie
+ *#* Add MOD_CHECK() checks.
+ *#*
+ *#* Revision 1.2 2006/02/10 12:36:20 bernie
+ *#* Add preliminary FreeRTOS support; Enforce CONFIG_* definitions.
+ *#*
*#* Revision 1.1 2005/06/27 21:28:45 bernie
*#* Import generic keyboard driver.
*#*
#include <drv/timer.h>
#include <drv/kbd.h>
-#include <drv/buzzer.h>
#include <cfg/debug.h>
+#include <cfg/module.h>
+#include <appconfig.h>
+/* Configuration sanity checks */
+#if !defined(CONFIG_KBD_POLL) || (CONFIG_KBD_POLL != KBD_POLL_SOFTINT && CONFIG_KBD_POLL != CONFIG_POLL_FREERTOS)
+ #error CONFIG_KBD_POLL must be defined to either KBD_POLL_SOFTINT or CONFIG_POLL_FREERTOS
+#endif
+#if !defined(CONFIG_KBD_BEEP) || (CONFIG_KBD_BEEP != 0 && CONFIG_KBD_BEEP != 1)
+ #error CONFIG_KBD_BEEP must be defined to either 0 or 1
+#endif
+#if !defined(CONFIG_KBD_OBSERVER) || (CONFIG_KBD_OBSERVER != 0 && CONFIG_KBD_OBSERVER != 1)
+ #error CONFIG_KBD_OBSERVER must be defined to either 0 or 1
+#endif
-
+#if CONFIG_KBD_BEEP
+ #include <drv/buzzer.h>
+#endif
#define KBD_CHECK_INTERVAL 10 /*!< (ms) Timing for kbd softint */
#define KBD_DEBOUNCE_TIME 30 /*!< (ms) Debounce time */
static volatile keymask_t kbd_buf; /*!< Single entry keyboard buffer */
static volatile keymask_t kbd_cnt; /*!< Number of keypress events in \c kbd_buf */
-static Timer kbd_timer; /*!< KeyboardKBD_BEEP_TIME softtimer */
+#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
+static Timer kbd_timer; /*!< Keyboard softtimer */
+#endif
static List kbd_rawHandlers; /*!< Raw keyboard handlers */
static List kbd_handlers; /*!< Cooked keyboard handlers */
static KbdHandler kbd_lngHandler; /*!< Long pression keys handler */
#endif
+#if CONFIG_KBD_OBSERVER
+ #include <mware/observer.h>
+ Subject kbd_subject;
+#endif
/*!
- * Keyboard soft-irq handler.
+ * Poll keyboard and dispatch keys to handlers.
+ *
+ * Read the key states and invoke all keyboard
+ * handlers to process the new state.
+ *
+ * Call this function periodically using a software
+ * timer, an interrupt or a process.
*/
-static void kbd_softint(UNUSED_ARG(iptr_t, arg))
+static void kbd_poll(void)
{
/*! Currently depressed key */
static keymask_t current_key;
keymask_t key = kbd_readkeys();
/* Call raw input handlers */
- FOREACHNODE(handler, &kbd_rawHandlers)
+ FOREACH_NODE(handler, &kbd_rawHandlers)
key = handler->hook(key);
/* If this key was not previously pressed */
current_key = key;
/* Call cooked input handlers */
- FOREACHNODE(handler, &kbd_handlers)
+ FOREACH_NODE(handler, &kbd_handlers)
key = handler->hook(key);
}
+}
+#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
+
+/*!
+ * Keyboard soft-irq handler.
+ */
+static void kbd_softint(UNUSED_ARG(iptr_t, arg))
+{
+ kbd_poll();
timer_add(&kbd_timer);
}
+#elif CONFIG_KBD_POLL == CONFIG_POLL_FREERTOS
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+static portTASK_FUNCTION(kbd_task, arg)
+{
+ for (;;)
+ {
+ kbd_poll();
+ timer_delay(KBD_CHECK_INTERVAL);
+ }
+}
+
+#endif /* CONFIG_KBD_POLL */
/*!
* \brief Read a key from the keyboard buffer.
{
keymask_t key = 0;
+// FIXME
+ /* Let other tasks run for a while */
+ extern void schedule(void);
+ schedule();
+
/* Extract an event from the keyboard buffer */
IRQ_DISABLE;
if (kbd_cnt)
return key;
}
-
/*!
* Wait for a keypress and return the mask of depressed keys.
*
keymask_t key;
while (!(key = kbd_peek())) {}
+
return key;
}
* Search for the first node whose priority
* is lower than the timer we want to add.
*/
- FOREACHNODE(node,list)
+ FOREACH_NODE(node,list)
if (node->pri < handler->pri)
break;
/* Enqueue handler in the handlers chain */
- INSERTBEFORE(&handler->link, &node->link);
+ INSERT_BEFORE(&handler->link, &node->link);
IRQ_RESTORE(flags);
}
kbd_buf = key;
kbd_cnt = 1;
- if (!(key & K_REPEAT))
- buz_beep(KBD_BEEP_TIME);
+ #if CONFIG_KBD_OBSERVER
+ observer_notify(&kbd_subject, KBD_EVENT_KEY, &key);
+ #endif
+
+ #if CONFIG_KBD_BEEP
+ if (!(key & K_REPEAT))
+ buz_beep(KBD_BEEP_TIME);
+ #endif
}
/* Eat all input */
*/
static keymask_t kbd_rptHandlerFunc(keymask_t key)
{
- /*! Timer for keyboard repeat events */
+ /* Timer for keyboard repeat events. */
static ticks_t repeat_time;
+ /* Current repeat rate (for acceleration). */
static ticks_t repeat_rate; /*! Current repeat rate (for acceleration) */
ticks_t now = timer_clock();
}
+MOD_DEFINE(kbd)
/*!
* Initialize keyboard ports and softtimer
*/
void kbd_init(void)
{
-
- cpuflags_t flags;
- IRQ_SAVE_DISABLE(flags);
+#if CONFIG_KBD_BEEP
+ MOD_CHECK(buzzer);
+#endif
KBD_HW_INIT;
- IRQ_RESTORE(flags);
-
/* Init handlers lists */
LIST_INIT(&kbd_handlers);
LIST_INIT(&kbd_rawHandlers);
kbd_addHandler(&kbd_lngHandler);
#endif
-
/* Add repeat keyboard handler */
kbd_rptHandler.hook = kbd_rptHandlerFunc;
kbd_rptHandler.pri = 80; /* high priority */
kbd_rptHandler.flags = KHF_RAWKEYS;
kbd_addHandler(&kbd_rptHandler);
-
/* Add default keyboard handler */
kbd_defHandler.hook = kbd_defHandlerFunc;
kbd_defHandler.pri = -128; /* lowest priority */
kbd_addHandler(&kbd_defHandler);
+#if CONFIG_KBD_OBSERVER
+ observer_InitSubject(&kbd_subject);
+#endif
+
+#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT
+
+ MOD_CHECK(timer);
+
/* Add kbd handler to soft timers list */
event_initSoftInt(&kbd_timer.expire, kbd_softint, 0);
timer_setDelay(&kbd_timer, ms_to_ticks(KBD_CHECK_INTERVAL));
timer_add(&kbd_timer);
+
+#elif CONFIG_KBD_POLL == CONFIG_POLL_FREERTOS
+
+ /* Create a timer specific thread */
+ xTaskCreate(kbd_task, "kbd", CONFIG_STACK_KBD,
+ NULL, CONFIG_PRI_KBD, NULL);
+
+#else
+ #error "Define keyboard poll method"
+#endif
+
+ MOD_INIT(kbd);
}