-
Notifications
You must be signed in to change notification settings - Fork 0
/
buttons.c
160 lines (141 loc) · 5.64 KB
/
buttons.c
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
156
157
158
159
// *******************************************************
//
// buttons.c
//
// Support for a set of FOUR specific buttons on the Tiva/Orbit.
// ENCE361 sample code.
// The buttons are: UP and DOWN (on the Orbit daughterboard) plus
// LEFT and RIGHT on the Tiva.
//
// Note that pin PF0 (the pin for the RIGHT pushbutton - SW2 on
// the Tiva board) needs special treatment - See PhilsNotesOnTiva.rtf.
//
// P.J. Bones UCECE
// Modified by Tom Rizzi, Euan Robinson, Satwik Meravanage
// Last modified: 21 May 2021
//
// *******************************************************
//*****************************************************************************
// Includes
//*****************************************************************************
#include <buttons.h>
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/debug.h"
#include "inc/tm4c123gh6pm.h" // Board specific defines (for PF0)
// *******************************************************
// Globals to module
// *******************************************************
static bool but_state[NUM_BUTS]; // Corresponds to the electrical state
static uint8_t but_count[NUM_BUTS];
static bool but_flag[NUM_BUTS];
static bool but_normal[NUM_BUTS]; // Corresponds to the electrical state
//*****************************************************************************
// Initialise the variables associated with the set of buttons
// defined by the constants in the buttons2.h header file.
//*****************************************************************************
void
initButtons (void) {
int i;
// UP button (active HIGH)
SysCtlPeripheralEnable (UP_BUT_PERIPH);
GPIOPinTypeGPIOInput (UP_BUT_PORT_BASE, UP_BUT_PIN);
GPIOPadConfigSet (UP_BUT_PORT_BASE, UP_BUT_PIN, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD_WPD);
but_normal[UP] = UP_BUT_NORMAL;
// DOWN button (active HIGH)
SysCtlPeripheralEnable (DOWN_BUT_PERIPH);
GPIOPinTypeGPIOInput (DOWN_BUT_PORT_BASE, DOWN_BUT_PIN);
GPIOPadConfigSet (DOWN_BUT_PORT_BASE, DOWN_BUT_PIN, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD_WPD);
but_normal[DOWN] = DOWN_BUT_NORMAL;
// LEFT button (active LOW)
SysCtlPeripheralEnable (LEFT_BUT_PERIPH);
GPIOPinTypeGPIOInput (LEFT_BUT_PORT_BASE, LEFT_BUT_PIN);
GPIOPadConfigSet (LEFT_BUT_PORT_BASE, LEFT_BUT_PIN, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD_WPU);
but_normal[LEFT] = LEFT_BUT_NORMAL;
// RIGHT button (active LOW)
// Note that PF0 is one of a handful of GPIO pins that need to be
// "unlocked" before they can be reconfigured. This also requires
// #include "inc/tm4c123gh6pm.h"
SysCtlPeripheralEnable (RIGHT_BUT_PERIPH);
//---Unlock PF0 for the right button:
GPIO_PORTF_LOCK_R = GPIO_LOCK_KEY;
GPIO_PORTF_CR_R |= GPIO_PIN_0; //PF0 unlocked
GPIO_PORTF_LOCK_R = GPIO_LOCK_M;
GPIOPinTypeGPIOInput (RIGHT_BUT_PORT_BASE, RIGHT_BUT_PIN);
GPIOPadConfigSet (RIGHT_BUT_PORT_BASE, RIGHT_BUT_PIN, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD_WPU);
but_normal[RIGHT] = RIGHT_BUT_NORMAL;
// RESET button
SysCtlPeripheralEnable (RESET_BUT_PERIPH);
GPIOPinTypeGPIOInput (RESET_BUT_PORT_BASE, RESET_BUT_PIN);
GPIOPadConfigSet (RESET_BUT_PORT_BASE, RESET_BUT_PIN, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD_WPU);
but_normal[RESET] = RESET_BUT_NORMAL;
for (i = 0; i < NUM_BUTS; i++)
{
but_state[i] = but_normal[i];
but_count[i] = 0;
but_flag[i] = false;
}
}
//*****************************************************************************
// Function designed to be called regularly. It polls all
// buttons once and updates variables associated with the buttons if
// necessary. It is efficient enough to be part of an ISR, e.g. from
// a SysTick interrupt.
// Debounce algorithm: A state machine is associated with each button.
// A state change occurs only after NUM_BUT_POLLS consecutive polls have
// read the pin in the opposite condition, before the state changes and
// a flag is set. Set NUM_BUT_POLLS according to the polling rate.
//*****************************************************************************
void
updateButtons (void) {
bool but_value[NUM_BUTS];
int i;
// Read the pins; true means HIGH, false means LOW
but_value[UP] = (GPIOPinRead (UP_BUT_PORT_BASE, UP_BUT_PIN) == UP_BUT_PIN);
but_value[DOWN] = (GPIOPinRead (DOWN_BUT_PORT_BASE, DOWN_BUT_PIN) == DOWN_BUT_PIN);
but_value[LEFT] = (GPIOPinRead (LEFT_BUT_PORT_BASE, LEFT_BUT_PIN) == LEFT_BUT_PIN);
but_value[RIGHT] = (GPIOPinRead (RIGHT_BUT_PORT_BASE, RIGHT_BUT_PIN) == RIGHT_BUT_PIN);
but_value[RESET] = (GPIOPinRead (RESET_BUT_PORT_BASE, RESET_BUT_PIN) == RESET_BUT_PIN);
// Iterate through the buttons, updating button variables as required
for (i = 0; i < NUM_BUTS; i++)
{
if (but_value[i] != but_state[i])
{
but_count[i]++;
if (but_count[i] >= NUM_BUT_POLLS)
{
but_state[i] = but_value[i];
but_flag[i] = true; // Reset by call to checkButton()
but_count[i] = 0;
}
}
else
but_count[i] = 0;
}
}
//*****************************************************************************
// Function returns the new button logical state if the button
// logical state (PUSHED or RELEASED) has changed since the last call,
// otherwise returns NO_CHANGE.
//*****************************************************************************
uint8_t checkButton (uint8_t butName)
{
if (but_flag[butName])
{
but_flag[butName] = false;
if (but_state[butName] == but_normal[butName])
return RELEASED;
else
return PUSHED;
}
return NO_CHANGE;
}