summaryrefslogtreecommitdiffstats
path: root/app/keypad.c
blob: d4a82db0dec89132e72789574c3d59bddf0615ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "project.h"

#define GPIO_CLOCK GPIOA
#define GPIO_DATA GPIOB
#define CLOCK 	GPIO5
#define DATA	GPIO11

#define KEYPAD_DELAY do { delay_us(1); } while (0)


#define SCAN_INTERVAL 73
#define DEBOUNCE_INTERVAL 1
#define DEBOUNCE_COUNT 3

static uint32_t next_scan;


uint16_t
keypad_raw_read (void)
{
  uint16_t ret = 0;
  uint16_t c;

/*Reset the state machine in the keypad */

  gpio_set (GPIO_DATA, DATA);
  KEYPAD_DELAY;
  gpio_clear (GPIO_DATA, DATA);
  KEYPAD_DELAY;
  gpio_set (GPIO_DATA, DATA);
  KEYPAD_DELAY;

  gpio_clear (GPIO_CLOCK, CLOCK);
  KEYPAD_DELAY;

  for (c = 0x8000; c; c >>= 1)
    {
      gpio_set (GPIO_CLOCK, CLOCK);
      KEYPAD_DELAY;
      if (!(gpio_get (GPIO_DATA, DATA) & DATA))
        ret |= c;
      gpio_clear (GPIO_CLOCK, CLOCK);
      KEYPAD_DELAY;
    }

  gpio_set (GPIO_CLOCK, CLOCK);

  return ret;
}

uint16_t
keypad_read (void)
{
  int c;
  const uint8_t lut[] = "cdef89ab45670123";
  uint8_t ret = 0;



/*Reset the state machine in the keypad */

  gpio_set (GPIO_DATA, DATA);
  KEYPAD_DELAY;
  gpio_clear (GPIO_DATA, DATA);
  KEYPAD_DELAY;
  gpio_set (GPIO_DATA, DATA);
  KEYPAD_DELAY;

  gpio_clear (GPIO_CLOCK, CLOCK);
  KEYPAD_DELAY;

  for (c = 0; c < 16; ++c)
    {
      gpio_set (GPIO_CLOCK, CLOCK);
      KEYPAD_DELAY;
      if (!(gpio_get (GPIO_DATA, DATA) & DATA))
        ret = lut[c];
      gpio_clear (GPIO_CLOCK, CLOCK);
      KEYPAD_DELAY;
    }

  gpio_set (GPIO_CLOCK, CLOCK);

  return ret;
}


static void
keypad_scan (void)
{
  static uint8_t last_v;
  static uint8_t key_down;
  static int same;
  uint8_t v;

  v = keypad_read ();

  next_scan = DEBOUNCE_INTERVAL;

  if (v!=last_v) {
     last_v=v;
     same=0;
     return;
  } else {
     if (same<DEBOUNCE_COUNT) {
     	same++;
	return;
     }
  }

  if (!v && !key_down)  {	
      next_scan = SCAN_INTERVAL;
      return;
  }

	if (key_down==v) {
		return;
	} else if (key_down!=v) {
	  if (key_down)
          key_event (key_down, 0);
	key_down=v;
	  if (key_down)
          key_event (key_down, 1);
	}
}




void
keypad_tick (void)
{

  if (!next_scan)
    keypad_scan ();
  else
    next_scan--;

}




void
keypad_init (void)
{

  gpio_set_mode (GPIO_CLOCK, GPIO_MODE_OUTPUT_50_MHZ,
                 GPIO_CNF_OUTPUT_OPENDRAIN, CLOCK);
  gpio_set_mode (GPIO_DATA, GPIO_MODE_OUTPUT_50_MHZ,
                 GPIO_CNF_OUTPUT_OPENDRAIN, DATA);



}