-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeypad.c
More file actions
executable file
·130 lines (108 loc) · 3.15 KB
/
keypad.c
File metadata and controls
executable file
·130 lines (108 loc) · 3.15 KB
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
/*
source file for the key scan matrix
Author: Pete Fan
*/
#include <stdbool.h>
#include "keypad.h"
#include "easi_globals.h"
#include "../inc/tm4c123gh6pm.h"
#include "../inc/CortexM.h"
#define COL_NUM 6
#define COL_PORT_NUM 0x10
#define COL_PORT_DATA_R GPIO_PORTE_DATA_R
#define COL_PORT_MASK 0x3F
#define COL_PORT_DIR_R GPIO_PORTE_DIR_R
#define COL_PORT_DEN_R GPIO_PORTE_DEN_R
#define ROW_NUM 7
#define ROW_PORT_NUM 0x02
#define ROW_PORT_DATA_R GPIO_PORTB_DATA_R
#define ROW_PORT_MASK 0x7F
#define ROW_PORT_DIR_R GPIO_PORTB_DIR_R
#define ROW_PORT_DEN_R GPIO_PORTB_DEN_R
#define SYSCTL_MASK (ROW_PORT_NUM | COL_PORT_NUM)
/*
Keyboard State Variables
*/
static uint8_t key_prev[COL_NUM];
static uint8_t key_curr[COL_NUM];
// cross-thread communication struct
typedef struct key_event_queue {
key_event_t buf[FIFO_SIZE];
uint32_t head;
uint32_t tail;
} key_event_queue_t;
key_event_queue_t EVENT_QUEUE;
fifo_err_t
key_fifo_put (key_event_t k)
{
fifo_err_t err = FIFO_NO_ERR;
long sr = StartCritical();
if (EVENT_QUEUE.head + 1 == EVENT_QUEUE.tail) {
err = FIFO_FULL_ERR;
} else {
EVENT_QUEUE.head = (EVENT_QUEUE.head + 1) % FIFO_SIZE;
EVENT_QUEUE.buf[EVENT_QUEUE.head] = k;
}
EndCritical(sr);
return err;
}
fifo_err_t
key_fifo_get (key_event_t * k)
{
fifo_err_t err = FIFO_NO_ERR;
long sr = StartCritical();
if (EVENT_QUEUE.head == EVENT_QUEUE.tail) {
err = FIFO_EMPTY_ERR;
} else {
EVENT_QUEUE.tail = (EVENT_QUEUE.tail + 1) % FIFO_SIZE;
*k = EVENT_QUEUE.buf[EVENT_QUEUE.tail];
}
EndCritical(sr);
return err;
}
void
keypad_init(void)
{
// Enable the clock for switch port and wait for stabilization.
SYSCTL_RCGCGPIO_R |= SYSCTL_MASK;
while ((SYSCTL_RCGCGPIO_R & SYSCTL_MASK) != SYSCTL_MASK);
// Initalize row pins as digital outputs.
COL_PORT_DIR_R |= COL_PORT_MASK;
COL_PORT_DEN_R |= COL_PORT_MASK;
// Initalize col pins as digital inputs.
ROW_PORT_DIR_R &= ~(ROW_PORT_MASK);
ROW_PORT_DEN_R = ROW_PORT_MASK;
// Initialize event queue
EVENT_QUEUE.head = 0;
EVENT_QUEUE.tail = 0;
}
void
keypad_scan(void)
{
int col, row;
key_event_t ev;
for (col = 0; col < COL_NUM; ++col) {
COL_PORT_DATA_R = (COL_PORT_DATA_R & ~COL_PORT_MASK) | (0x01 << col);
key_prev[col] = key_curr[col];
key_curr[col] = ROW_PORT_DATA_R & ROW_PORT_MASK;
uint8_t diff = key_prev[col] ^ key_curr[col];
for (row = 0; row < ROW_NUM; ++row) {
if (diff & (0x01 << row)) {
ev.key = (col * ROW_NUM) + row;
if (key_prev[col] & (0x01 << row)) {
ev.k_action = KEY_UP;
} else {
ev.k_action = KEY_DN;
}
key_fifo_put(ev);
WAKE = true;
}
}
}
COL_PORT_DATA_R = (COL_PORT_DATA_R & ~COL_PORT_MASK);
}
uint8_t *
keypad_get_raw(void)
{
return key_curr;
}