4008-04-07 Release
[avr_bc100.git] / BaseMegaFirmware / GCC / key_io.h
diff --git a/BaseMegaFirmware/GCC/key_io.h b/BaseMegaFirmware/GCC/key_io.h
new file mode 100644 (file)
index 0000000..8c0891f
--- /dev/null
@@ -0,0 +1,101 @@
+/* Copyright (c)2007, 2008 Martin Thomas, BSD license */\r
+\r
+#ifndef KEY_IO_H_\r
+#define KEY_IO_H_\r
+\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+\r
+#include "timebase.h" /* for TIMEBASE_DELTAT_MS */\r
+\r
+#define KEY_IO_KEYSA_DDR     DDRC\r
+#define KEY_IO_KEYSA_PORT    PORTC\r
+#define KEY_IO_KEYSA_PIN     PINC\r
+#define KEY_IO_KEYA1_BIT     PC0 /* SW0 */\r
+#define KEY_IO_KEYA2_BIT     PC1 /* SW1 */\r
+#define KEY_IO_KEYA3_BIT     PC6 /* SW2 */\r
+#define KEY_IO_KEYA4_BIT     PC7 /* SW3 */\r
+#define KEY_IO_KEYSB_DDR     DDRD\r
+#define KEY_IO_KEYSB_PORT    PORTD\r
+#define KEY_IO_KEYSB_PIN     PIND\r
+#define KEY_IO_KEYB1_BIT     PD5 /* Power button */\r
+\r
+#define KEY_IO_KEY_SW0      (1<<0)\r
+#define KEY_IO_KEY_SW1      (1<<1)\r
+#define KEY_IO_KEY_SW2      (1<<2)\r
+#define KEY_IO_KEY_SW3      (1<<3)\r
+#define KEY_IO_KEY_POWER    (1<<4)\r
+#define KEY_IO_KEY_ALL \\r
+       ( KEY_IO_KEY_SW0    | \\r
+         KEY_IO_KEY_SW1    | \\r
+         KEY_IO_KEY_SW2    | \\r
+         KEY_IO_KEY_SW3    | \\r
+         KEY_IO_KEY_POWER )\r
+\r
+\r
+static inline uint8_t key_io_state_hardware(void)\r
+{\r
+       uint8_t tmp1, tmp2, tmp3;\r
+       tmp1 = KEY_IO_KEYSA_PIN & (     (1<<KEY_IO_KEYA1_BIT) | (1<<KEY_IO_KEYA2_BIT) );\r
+       tmp2 = KEY_IO_KEYSA_PIN & (     (1<<KEY_IO_KEYA3_BIT) | (1<<KEY_IO_KEYA4_BIT) );\r
+       tmp2 >>= 4;\r
+       tmp3 = KEY_IO_KEYSB_PIN & (1<<KEY_IO_KEYB1_BIT);\r
+       tmp3 >>= 1;\r
+       return ( tmp1 | tmp2 | tmp3 );\r
+}\r
+\r
+/* debounce/repeat code based on an example from Peter Dannegger,\r
+   modified for better integration and volatiles added */\r
+\r
+//#define KEY_IO_REPEAT_MASK   ( KEY_IO_KEY_DOWN | KEY_IO_KEY_UP )\r
+#define KEY_IO_REPEAT_MASK   ( KEY_IO_KEY_ALL )\r
+#define KEY_IO_REPEAT_START  ( 500/*ms*/ / TIMEBASE_DELTAT_MS )\r
+#define KEY_IO_REPEAT_NEXT   ( 100/*ms*/ / TIMEBASE_DELTAT_MS )\r
+\r
+// debounced and inverted key state, bit = 1: key pressed\r
+extern volatile uint8_t key_io_state;          \r
+// key press detect\r
+extern volatile uint8_t key_io_press;\r
+// key long press and repeat\r
+extern volatile uint8_t key_io_rpt;\r
+\r
+/* The following callback-function has to be \r
+   called frequently from timer-ISR. Implemented \r
+   in this header-file as static inline to \r
+   indicate to the compiler that the function \r
+   should be inlined into the ISR-code. Tested with \r
+   avr-gcc 4.2.1: inlined - o.k. */\r
+static inline void key_io_callback(void)\r
+{\r
+       static uint8_t ct0, ct1, rpt;\r
+       uint8_t i, mystate;\r
+\r
+       mystate = key_io_state;\r
+\r
+       i = mystate ^ ~( key_io_state_hardware() );     // keys changed ?\r
+       ct0 = ~(ct0 & i);                       // reset or count ct0\r
+       ct1 = ct0 ^ (ct1 & i);          // reset or count ct1\r
+       i &= ct0 & ct1;                         // count until roll over ?\r
+       mystate ^= i;   // then toggle debounced state\r
+       key_io_press |= mystate & i;    // 0->1: key press detect\r
+\r
+       if( (mystate & KEY_IO_REPEAT_MASK) == 0 ) {     // check repeat function\r
+               rpt = KEY_IO_REPEAT_START;                              // start delay\r
+       }\r
+       if( --rpt == 0 ) {\r
+               rpt = KEY_IO_REPEAT_NEXT;       // repeat delay\r
+               key_io_rpt |= mystate & KEY_IO_REPEAT_MASK;\r
+       }\r
+\r
+       key_io_state = mystate;\r
+}\r
+\r
+void key_io_init(void);\r
+\r
+uint8_t key_io_get_press( uint8_t key_mask );\r
+uint8_t key_io_get_rpt( uint8_t key_mask );\r
+uint8_t key_io_get_longpress( uint8_t key_mask );\r
+/* only returns "true" after key has been released: */\r
+uint8_t key_io_get_was_short( uint8_t key_mask );\r
+\r
+#endif\r