-
Notifications
You must be signed in to change notification settings - Fork 0
/
Encoder.h
126 lines (114 loc) · 2.89 KB
/
Encoder.h
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
#pragma once
#include <stddef.h>
#include <avr/interrupt.h>
#include "settings.h"
#include "HAL_GPIO.h"
#include "HAL_Timer.h"
class Encoder{
public:
enum Encoder_Lead{
A_LEADS_B = 0,
B_LEADS_A = 1
};
enum Encoder_Dir{
NONE = 0,
CLOCKWISE = 1,
COUNTERCLOCKWISE = 2
};
enum Encoder_Gray{
ONE_ONE = 0b11,
ONE_ZERO = 0b10,
ZERO_ONE = 0b01,
ZERO_ZERO = 0b00
};
enum Encoder_Button{
NO_PUSH = 0,
PUSH = 1,
LONG_PUSH = 2
};
// static public members are shared with ISR
static HAL_GPIO *A_Ptr;
static HAL_GPIO *B_Ptr;
static HAL_GPIO *BTN_Ptr;
static HAL_Timer *Timer_Ptr;
// Encoder variables
static volatile Encoder_Gray last_state;
static volatile Encoder_Dir dir;
// Button variables
static volatile Encoder_Button pressed;
static volatile unsigned long button_time;
static volatile bool check_time;
private:
HAL_GPIO A;
HAL_GPIO B;
HAL_GPIO BTN;
HAL_Timer &Timer;
Encoder_Lead lead;
public:
Encoder(
HAL_GPIO::GPIO_port A_port, HAL_GPIO::GPIO_pin A_pin,
HAL_GPIO::GPIO_port B_port, HAL_GPIO::GPIO_pin B_pin,
HAL_GPIO::GPIO_port BTN_port, HAL_GPIO::GPIO_pin BTN_pin,
HAL_Timer &Timer_r, Encoder_Lead encoder_lead) :
A(A_port, A_pin), B(B_port, B_pin), BTN(BTN_port, BTN_pin), Timer(Timer_r), lead(encoder_lead)
{
// Constructor
// Set up static public members
A_Ptr = &A;
B_Ptr = &B;
BTN_Ptr = &BTN;
Timer_Ptr = &Timer;
last_state = ONE_ONE;
dir = NONE;
pressed = NO_PUSH;
button_time = 0;
check_time = false;
// Configure A, B and BTN
A.set_direction(HAL_GPIO::GPIO_INPUT);
B.set_direction(HAL_GPIO::GPIO_INPUT);
BTN.set_direction(HAL_GPIO::GPIO_INPUT);
A.int_mask_enable();
B.int_mask_enable();
BTN.int_mask_enable();
BTN.pin_change_int_enable();
// Configure Timer
Timer.enable_int();
}
Encoder_Dir get_dir(){
// reading dir clears it
Encoder_Dir to_return = dir;
// dir is written assuming A leads B
if(lead == B_LEADS_A){
// reverse direction
if(to_return == CLOCKWISE)
to_return = COUNTERCLOCKWISE;
else if(to_return == COUNTERCLOCKWISE)
to_return = CLOCKWISE;
}
dir = NONE;
return to_return;
}
Encoder_Button get_pressed(){
// If button hasn't been pushed, then return NO_PUSH
// If button has been pressed, then see if PUSH or LONG_PUSH
if(pressed == NO_PUSH)
return NO_PUSH;
else{
// Button has been pushed
// If time exceeds threshold, then considered long press
if(check_time){
if(Timer.get_tick() - button_time > SET_UI_ENC_LONG_PRESS_THRESH){
// Sufficient time has passed to be considered long press
pressed = NO_PUSH;
return LONG_PUSH;
}
// Insufficient time has passed, so wait
return NO_PUSH;
} else{
// button released early, so regular push
pressed = NO_PUSH;
return PUSH;
}
}
}
};