key-routines.c


1
#ifndef F_CPU
2
#define F_CPU           1000000                   // processor clock frequency
3
#warning no F_CPU defined
4
#endif
5
6
#include <stdint.h>
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include "key-routines.h"
10
11
/************************************************************************/
12
13
volatile uint8_t key_state;                  // debounced and inverted key state:
14
                              // bit = 1: key pressed
15
volatile uint8_t key_press;                  // key press detect
16
17
volatile uint8_t key_rpt;                  // key long press and repeat
18
19
/************************************************************************/
20
21
ISR( TIMER0_OVF_vect )                            // every 10ms
22
{
23
  static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt;
24
  uint8_t i;
25
  
26
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
27
  
28
  i = key_state ^ ~KEY_PIN;                       // key changed ?
29
  ct0 = ~( ct0 & i );                             // reset or count ct0
30
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
31
  i &= ct0 & ct1;                                 // count until roll over ?
32
  key_state ^= i;                                 // then toggle debounced state
33
  key_press |= key_state & i;                     // 0->1: key press detect
34
  
35
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
36
  rpt = REPEAT_START;                          // start delay
37
  if( --rpt == 0 ){
38
    rpt = REPEAT_NEXT;                            // repeat delay
39
    key_rpt |= key_state & REPEAT_MASK;
40
  }
41
}
42
43
/************************************************************************/
44
45
uint8_t get_key_press( uint8_t key_mask )
46
{
47
  cli();                                          // read and clear atomic !
48
  key_mask &= key_press;                          // read key(s)
49
  key_press ^= key_mask;                          // clear key(s)
50
  sei();
51
  return key_mask;
52
}
53
54
/************************************************************************/
55
56
uint8_t get_key_rpt( uint8_t key_mask )
57
{
58
  cli();                                          // read and clear atomic !
59
  key_mask &= key_rpt;                            // read key(s)
60
  key_rpt ^= key_mask;                            // clear key(s)
61
  sei();
62
  return key_mask;
63
}
64
65
/************************************************************************/
66
67
uint8_t get_key_state( uint8_t key_mask )
68
{
69
  key_mask &= key_state;
70
  return key_mask;
71
}
72
73
/************************************************************************/
74
75
uint8_t get_key_short( uint8_t key_mask )
76
{
77
  cli();                                          // read key state and key press atomic !
78
  return get_key_press( ~key_state & key_mask );
79
}
80
81
/************************************************************************/
82
83
uint8_t get_key_long( uint8_t key_mask )
84
{
85
  return get_key_press( get_key_rpt( key_mask ));
86
}