1 /* Copyright (c)2007, 2008 Martin Thomas, BSD license */
\r
9 #include "timebase.h" /* for TIMEBASE_DELTAT_MS */
\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
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
36 static inline uint8_t key_io_state_hardware(void)
\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
42 tmp3 = KEY_IO_KEYSB_PIN & (1<<KEY_IO_KEYB1_BIT);
\r
44 return ( tmp1 | tmp2 | tmp3 );
\r
47 /* debounce/repeat code based on an example from Peter Dannegger,
\r
48 modified for better integration and volatiles added */
\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
55 // debounced and inverted key state, bit = 1: key pressed
\r
56 extern volatile uint8_t key_io_state;
\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
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
70 static uint8_t ct0, ct1, rpt;
\r
73 mystate = key_io_state;
\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
82 if( (mystate & KEY_IO_REPEAT_MASK) == 0 ) { // check repeat function
\r
83 rpt = KEY_IO_REPEAT_START; // start delay
\r
86 rpt = KEY_IO_REPEAT_NEXT; // repeat delay
\r
87 key_io_rpt |= mystate & KEY_IO_REPEAT_MASK;
\r
90 key_io_state = mystate;
\r
93 void key_io_init(void);
\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