-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
167 lines (140 loc) · 3.57 KB
/
main.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
160
161
162
163
164
165
166
167
/*
* debounce.c
*
* Created: 2018-01-21 6:33:07 AM
* Authors: Ayan & Abdullahi
*/
#include <avr/io.h>
#include <avr/interrupt.h>
const short min_sample_points =17;
const short total_sample_points = 20;
const float delta_t = 100e-6;
const float fclk = 14.7456e6;
unsigned short button_status, confirmed_button_status;
unsigned short sample_counts, good_sample_counts;
//Enumarate all possible states
//and assign them to the variable my_ccurent_state
enum fsm_states{
low,
trans_lh,
high,
trans_hl} my_current_state;
/*++++++EXTERNAL INTERRUPT SERVICE ROUNTINE+++++++
Actual undebounced signal is written to PB0.
My current state variable is used to change states
*/
ISR(INT0_vect){
button_status = (PIND & (1<<PD2));
//Write the actual signal to PB0
if(button_status){
PORTB |= (1<<PB0);
}else{
PORTB &= ~(1<<PB0);
}
//Change state from high/low to transition
if(my_current_state == low){
if(button_status){
//current state is in transition from low to high
my_current_state = trans_lh;
//reset all counters
good_sample_counts = 0;
sample_counts=0;
TCNT0 =0;
}
}
if(my_current_state == high){
if(!(button_status)){
//current state is in transition from high to low
my_current_state = trans_hl;
//reset all counters
good_sample_counts = 0;
sample_counts=0;
TCNT0 =0;
}
}
}
/*+++++OUTPUT COMPARE INTERRUPT SERVICE ROUNTINE+++++
Samples are incremented if the state is in transition
*/
ISR(TIMER0_COMPA_vect){
//increment samples
if(sample_counts < total_sample_points){
sample_counts++; //count the samples
if((my_current_state == trans_hl) || (my_current_state == trans_lh)){
//count good samples while state is in transition
good_sample_counts++;
}
}else{
//reset all counters
good_sample_counts = 0;
sample_counts=0;
TCNT0 =0;
}
}
/*++++++++++++DEBOUNCE ROUTINE++++++++++++++++
If enough samples are collected:
Button signal is debounced
The current state is changed back to high or low
*/
void debounce_button(){
//Check if enough samples were collected
if(good_sample_counts >= min_sample_points && sample_counts <=total_sample_points)
{
//check if still in transition
if(my_current_state == trans_lh){
//write debounced signal to this variable
confirmed_button_status = 1;
//Set state to high
my_current_state = high;
//clear all counters
good_sample_counts = 0;
sample_counts=0;
TCNT0 =0;
}
if(my_current_state == trans_hl)
{
//write debounced signal to this variable
confirmed_button_status = 0;
//change state to low
my_current_state = low;
//clear counters
good_sample_counts = 0;
sample_counts=0;
TCNT0 =0;
}
}
}
int main(void)
{
DDRB = 0xFF;
DDRD = 0;
//Intialize both PORTB and my current state to low
PORTB = 0;
my_current_state =low;
button_status = 0;
confirmed_button_status = 0;
}
//Initialize all counters to zero
sample_counts = 0;
good_sample_counts = 0;
//Enable external interrupt on PD2
EIMSK |= (1<<INT0);
EICRA |= (1<<ISC00);
//Start timer0 and enable Output Compare interrupt
TIMSK0 |= (1<<OCIE0A);
TCCR0B |= (1<<CS00);
TCNT0 = 0;
OCR0A = (fclk*delta_t/total_sample_points); //Set the trigger of the interrupt
sei(); //Enable global interrupt
while (1)
{
//Call debounce function
debounce_button();
//Write debounced signal to PB1
if(confirmed_button_status){
PORTB |= (1<<PB1);
}else{
PORTB &= ~(1<<PB1);
}
}
}