embox

Форк
0
196 строк · 5.5 Кб
1
/*
2
 * @file
3
 *
4
 * @date 31.01.2023
5
 * @author Andrew Bursian
6
 */
7

8
#include <util/log.h>
9

10
#include <errno.h>
11
#include <assert.h>
12

13
//#include <kernel/irq.h>
14
#include <kernel/time/timer.h>
15
#include <drivers/input/input_dev.h>
16

17
#include <drivers/gpio/gpio.h>
18

19
#include <embox/unit.h>
20

21
EMBOX_UNIT_INIT(keypad_init);
22

23
#include <framework/mod/options.h>
24

25
#define KEYPAD_ROWS OPTION_GET(NUMBER,rows)
26
#define KEYPAD_COLS OPTION_GET(NUMBER,cols)
27

28
#define KP_POLL_PERIOD   OPTION_GET(NUMBER, kp_poll_period)
29
#define KP_HOLD_TICKS    OPTION_GET(NUMBER, kp_hold_ticks)
30

31
#define COL0_PORT   OPTION_GET(NUMBER, kp_col0_port)
32
#define COL0_PIN    OPTION_GET(NUMBER, kp_col0_pino)
33
#define COL1_PORT   OPTION_GET(NUMBER, kp_col1_port)
34
#define COL1_PIN    OPTION_GET(NUMBER, kp_col1_pino)
35
#define COL2_PORT   OPTION_GET(NUMBER, kp_col2_port)
36
#define COL2_PIN    OPTION_GET(NUMBER, kp_col2_pino)
37
#define COL3_PORT   OPTION_GET(NUMBER, kp_col3_port)
38
#define COL3_PIN    OPTION_GET(NUMBER, kp_col3_pino)
39
#define ROW0_PORT   OPTION_GET(NUMBER, kp_row0_port)
40
#define ROW0_PIN    OPTION_GET(NUMBER, kp_row0_pino)
41
#define ROW1_PORT   OPTION_GET(NUMBER, kp_row1_port)
42
#define ROW1_PIN    OPTION_GET(NUMBER, kp_row1_pino)
43
#define ROW2_PORT   OPTION_GET(NUMBER, kp_row2_port)
44
#define ROW2_PIN    OPTION_GET(NUMBER, kp_row2_pino)
45
#define ROW3_PORT   OPTION_GET(NUMBER, kp_row3_port)
46
#define ROW3_PIN    OPTION_GET(NUMBER, kp_row3_pino)
47

48
struct bpid {				// board pin id
49
	unsigned port;			// port (| chip_no<<4)
50
	unsigned pino;			// pin no 0..15
51
};
52
static const struct bpid cols[4]={
53
	{COL0_PORT, COL0_PIN},
54
	{COL1_PORT, COL1_PIN},
55
	{COL2_PORT, COL2_PIN},
56
	{COL3_PORT, COL3_PIN}
57
};
58
static const struct bpid rows[4]={
59
	{ROW0_PORT, ROW0_PIN},
60
	{ROW1_PORT, ROW1_PIN},
61
	{ROW2_PORT, ROW2_PIN},
62
	{ROW3_PORT, ROW3_PIN}
63
};
64
//static const struct bpid rows[4]={{GPIO_PORT_C, 12}, {GPIO_PORT_D, 2}, {GPIO_PORT_G, 2}, {GPIO_PORT_G, 3}};
65
//static const struct bpid cols[4]={{GPIO_PORT_C, 8}, {GPIO_PORT_C, 9}, {GPIO_PORT_C, 10}, {GPIO_PORT_C, 11}};
66
static const int keys[]={
67
	2, 3, 4, (3*8+6)|KBD_SHIFT_PRESSED,
68
	5, 6, 7, (6*8+0)|KBD_SHIFT_PRESSED,
69
	8, 9, 10, (5*8+6)|KBD_SHIFT_PRESSED,
70
	9|KBD_SHIFT_PRESSED, 11, 4|KBD_SHIFT_PRESSED, (4*8+0)|KBD_SHIFT_PRESSED	
71
};
72
//static const char keys[]="123A456B789C*0#D";
73

74
struct keypad_s {
75
	struct input_dev indev;
76
	int  down;			// internal flag-counter, means key still down
77
	int  row, col;			// internal row & column of key, last pressed
78
	unsigned long timer_counter;	// timer_counter*KEYBOARD_POLL_PERIOD is the time elapsed from open or flush
79
	int POLL_PERIOD;		// in ms
80
	int HOLD_TICKS;			// number of poll periods to ensure that key is up
81
	sys_timer_t * timer;		// timer pointer for timer_close
82
};
83

84
static struct keypad_s keypad; // static initialisation see below 
85

86
static void keypad_timer_handler(sys_timer_t* timer, void *param) {
87
	struct keypad_s *kp=param;
88
	struct input_dev *dev=&((struct keypad_s *)param)->indev;
89
	struct input_event ev;
90

91
	kp->timer_counter++;
92
	
93
	if (!(kp->down)) {
94
		for (int c=0; c<4; c++) {
95
			gpio_set(cols[c].port, 1<<cols[c].pino, GPIO_PIN_LOW);
96
			for (int r=0; r<4; r++) {
97
				if (!gpio_get(rows[r].port, 1<<rows[r].pino)) {
98
					ev.type=USER_BUTTON_PRESSED | KBD_KEY_PRESSED;
99
					ev.value=keys[(r<<2)+c];
100
					log_debug("keypad key pressed");
101
					input_dev_report_event(dev, &ev);
102
					kp->down=kp->HOLD_TICKS;
103
					kp->row=r; kp->col=c;
104
				}
105
			}
106
			gpio_set(cols[c].port, 1<<cols[c].pino, GPIO_PIN_HIGH);
107
		}
108
	} else {	// no matter about down spikes, holding poll until key up for HOLD_TICKS
109
		gpio_set(cols[kp->col].port, 1<<cols[kp->col].pino, GPIO_PIN_LOW);
110
		if (!gpio_get(rows[kp->row].port, 1<<rows[kp->row].pino)) kp->down=kp->HOLD_TICKS;
111
		else kp->down--;
112
		if (!(kp->down)) {
113
			ev.type=USER_BUTTON_UNPRESSED;
114
			ev.value=keys[(kp->row<<2)+kp->col];
115
			log_debug("keypad key released");
116
			input_dev_report_event(dev, &ev);
117
		} 
118
		gpio_set(cols[kp->col].port, 1<<cols[kp->col].pino, GPIO_PIN_HIGH);
119
	}
120
}
121

122
void keypad_flush(struct keypad_s *kp) {
123
	kp->down=0;
124
	kp->row=0;
125
	kp->col=0;
126
	kp->timer_counter=0;
127
}
128

129
static int keypad_start(struct input_dev *dev) {
130
	// Flags & variables flush
131
	struct keypad_s *kp=(struct keypad_s *)&keypad;				// ????
132
	keypad_flush(kp);
133

134
	// Set timer handler
135
	if (timer_set(&(kp->timer), TIMER_PERIODIC, kp->POLL_PERIOD, keypad_timer_handler, kp)) {
136
		log_error("Failed to install timer");
137
		return -1;
138
	}
139
	return 0;
140
}
141

142
static int keypad_stop(struct input_dev *dev) {
143
	struct keypad_s *kp=(struct keypad_s *)&keypad;				// ????
144
	// Reset timer handler
145
	timer_close(kp->timer);
146
	return 0;
147
}
148

149
static const struct input_dev_ops keypad_input_ops = {
150
	.start=keypad_start,
151
	.stop=keypad_stop
152
};
153

154
static struct keypad_s keypad = {
155
	.indev = {
156
		.ops = &keypad_input_ops,
157
		.name = "keypad",
158
		//.type = INPUT_DEV_BUTTON
159
		.type = INPUT_DEV_KBD
160
	}
161
};
162

163
static int keypad_init(void) {
164
	int ret = 0;
165

166
	// Check matrix size
167
	if (KEYPAD_ROWS !=4 || KEYPAD_COLS != 4) {
168
		log_error("only 4x4 matrix can be driven");
169
		goto err_out;
170
	}
171

172
	// Driver registration
173
	ret = input_dev_register(&keypad.indev);
174
	if (ret != 0) {
175
		log_error("input_dev_register failed");
176
		goto err_out;
177
	}
178
	keypad.indev.data = (void *) &keypad;
179

180
	// Internal data structure preparation
181
	struct keypad_s *kp=(struct keypad_s *)&keypad;				// ????
182
	kp->POLL_PERIOD=KP_POLL_PERIOD;
183
	kp->HOLD_TICKS=KP_HOLD_TICKS;
184

185
	// I/O pins intitialization
186
	for (int i=0; i<4; i++) {
187
		// Output pins
188
		gpio_setup_mode(cols[i].port, 1<<cols[i].pino, GPIO_MODE_OUT);
189
		gpio_set(cols[i].port, 1<<cols[i].pino, GPIO_PIN_HIGH);
190
		// Input pins
191
		gpio_setup_mode(rows[i].port, 1<<rows[i].pino, GPIO_MODE_IN|GPIO_MODE_IN_PULL_UP);
192
	}
193

194
err_out:
195
	return ret;
196
}
197

198

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.