4008-04-07 Release
[avr_bc100.git] / BaseMegaFirmware / GCC / key_io.h
1 /* Copyright (c)2007, 2008 Martin Thomas, BSD license */\r
2 \r
3 #ifndef KEY_IO_H_\r
4 #define KEY_IO_H_\r
5 \r
6 #include <stdint.h>\r
7 #include <avr/io.h>\r
8 \r
9 #include "timebase.h" /* for TIMEBASE_DELTAT_MS */\r
10 \r
11 #define KEY_IO_KEYSA_DDR     DDRC\r
12 #define KEY_IO_KEYSA_PORT    PORTC\r
13 #define KEY_IO_KEYSA_PIN     PINC\r
14 #define KEY_IO_KEYA1_BIT     PC0 /* SW0 */\r
15 #define KEY_IO_KEYA2_BIT     PC1 /* SW1 */\r
16 #define KEY_IO_KEYA3_BIT     PC6 /* SW2 */\r
17 #define KEY_IO_KEYA4_BIT     PC7 /* SW3 */\r
18 #define KEY_IO_KEYSB_DDR     DDRD\r
19 #define KEY_IO_KEYSB_PORT    PORTD\r
20 #define KEY_IO_KEYSB_PIN     PIND\r
21 #define KEY_IO_KEYB1_BIT     PD5 /* Power button */\r
22 \r
23 #define KEY_IO_KEY_SW0      (1<<0)\r
24 #define KEY_IO_KEY_SW1      (1<<1)\r
25 #define KEY_IO_KEY_SW2      (1<<2)\r
26 #define KEY_IO_KEY_SW3      (1<<3)\r
27 #define KEY_IO_KEY_POWER    (1<<4)\r
28 #define KEY_IO_KEY_ALL \\r
29         ( KEY_IO_KEY_SW0    | \\r
30           KEY_IO_KEY_SW1    | \\r
31           KEY_IO_KEY_SW2    | \\r
32           KEY_IO_KEY_SW3    | \\r
33           KEY_IO_KEY_POWER )\r
34 \r
35 \r
36 static inline uint8_t key_io_state_hardware(void)\r
37 {\r
38         uint8_t tmp1, tmp2, tmp3;\r
39         tmp1 = KEY_IO_KEYSA_PIN & (     (1<<KEY_IO_KEYA1_BIT) | (1<<KEY_IO_KEYA2_BIT) );\r
40         tmp2 = KEY_IO_KEYSA_PIN & (     (1<<KEY_IO_KEYA3_BIT) | (1<<KEY_IO_KEYA4_BIT) );\r
41         tmp2 >>= 4;\r
42         tmp3 = KEY_IO_KEYSB_PIN & (1<<KEY_IO_KEYB1_BIT);\r
43         tmp3 >>= 1;\r
44         return ( tmp1 | tmp2 | tmp3 );\r
45 }\r
46 \r
47 /* debounce/repeat code based on an example from Peter Dannegger,\r
48    modified for better integration and volatiles added */\r
49 \r
50 //#define KEY_IO_REPEAT_MASK   ( KEY_IO_KEY_DOWN | KEY_IO_KEY_UP )\r
51 #define KEY_IO_REPEAT_MASK   ( KEY_IO_KEY_ALL )\r
52 #define KEY_IO_REPEAT_START  ( 500/*ms*/ / TIMEBASE_DELTAT_MS )\r
53 #define KEY_IO_REPEAT_NEXT   ( 100/*ms*/ / TIMEBASE_DELTAT_MS )\r
54 \r
55 // debounced and inverted key state, bit = 1: key pressed\r
56 extern volatile uint8_t key_io_state;           \r
57 // key press detect\r
58 extern volatile uint8_t key_io_press;\r
59 // key long press and repeat\r
60 extern volatile uint8_t key_io_rpt;\r
61 \r
62 /* The following callback-function has to be \r
63    called frequently from timer-ISR. Implemented \r
64    in this header-file as static inline to \r
65    indicate to the compiler that the function \r
66    should be inlined into the ISR-code. Tested with \r
67    avr-gcc 4.2.1: inlined - o.k. */\r
68 static inline void key_io_callback(void)\r
69 {\r
70         static uint8_t ct0, ct1, rpt;\r
71         uint8_t i, mystate;\r
72 \r
73         mystate = key_io_state;\r
74 \r
75         i = mystate ^ ~( key_io_state_hardware() );     // keys changed ?\r
76         ct0 = ~(ct0 & i);                       // reset or count ct0\r
77         ct1 = ct0 ^ (ct1 & i);          // reset or count ct1\r
78         i &= ct0 & ct1;                         // count until roll over ?\r
79         mystate ^= i;   // then toggle debounced state\r
80         key_io_press |= mystate & i;    // 0->1: key press detect\r
81 \r
82         if( (mystate & KEY_IO_REPEAT_MASK) == 0 ) {     // check repeat function\r
83                 rpt = KEY_IO_REPEAT_START;                              // start delay\r
84         }\r
85         if( --rpt == 0 ) {\r
86                 rpt = KEY_IO_REPEAT_NEXT;       // repeat delay\r
87                 key_io_rpt |= mystate & KEY_IO_REPEAT_MASK;\r
88         }\r
89 \r
90         key_io_state = mystate;\r
91 }\r
92 \r
93 void key_io_init(void);\r
94 \r
95 uint8_t key_io_get_press( uint8_t key_mask );\r
96 uint8_t key_io_get_rpt( uint8_t key_mask );\r
97 uint8_t key_io_get_longpress( uint8_t key_mask );\r
98 /* only returns "true" after key has been released: */\r
99 uint8_t key_io_get_was_short( uint8_t key_mask );\r
100 \r
101 #endif\r