Repository navigation
Expand file tree
/
Copy pathI2CKeyboard.cpp
More file actions
147 lines (127 loc) · 3.07 KB
/
Copy pathI2CKeyboard.cpp
File metadata and controls
147 lines (127 loc) · 3.07 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "I2CKeyboard.h"
#include "Keys.h"
#include <deki/LogSystem.h>
#include <deki/Time.h>
#include <utility>
namespace DekiInput
{
I2CKeyboard::I2CKeyboard(ReadByte read, Probe probe, Clock clock)
: m_Read(std::move(read)),
m_Probe(std::move(probe)),
m_Clock(std::move(clock))
{
if (!m_Clock)
{
m_Clock = []() { return Deki::Time::GetTime(); };
}
}
bool I2CKeyboard::Initialize()
{
m_Initialized = m_Read && m_Probe;
m_State = State::Searching;
m_Probed = false;
m_Failures = 0;
m_DownKey = 0;
return m_Initialized;
}
void I2CKeyboard::Shutdown()
{
m_Initialized = false;
m_Callbacks.clear();
m_DownKey = 0;
}
void I2CKeyboard::RegisterEventCallback(const InputEventCallback& callback)
{
m_Callbacks.push_back(callback);
}
bool I2CKeyboard::GetPointerPosition(int32_t*, int32_t*) const
{
return false;
}
bool I2CKeyboard::IsKeyPressed(uint32_t key) const
{
return m_DownKey != 0 && m_DownKey == key;
}
void I2CKeyboard::Emit(InputEventType type, uint32_t key, uint32_t character)
{
InputEvent event{};
event.type = type;
event.key = key;
event.character = character;
event.pressed = (type == InputEventType::KeyDown);
event.timestamp = m_Clock();
for (const auto& callback : m_Callbacks)
{
callback(event);
}
}
void I2CKeyboard::Search(uint32_t now)
{
if (!m_Probed)
{
m_SearchStarted = now;
}
else if (now - m_LastProbe < kProbeIntervalMs)
{
return;
}
m_Probed = true;
m_LastProbe = now;
if (m_Probe())
{
DEKI_LOG_INFO("I2CKeyboard: keyboard found");
m_State = State::Active;
m_Failures = 0;
}
else if (now - m_SearchStarted >= kGiveUpAfterMs)
{
DEKI_LOG_ERROR("I2CKeyboard: nothing answered at the keyboard's address in %u ms; not reading it",
(unsigned)kGiveUpAfterMs);
m_State = State::GaveUp;
}
}
void I2CKeyboard::Update()
{
if (!m_Initialized)
{
return;
}
// Last update's press is released first, so a key typed twice in a row is
// two presses rather than one long one.
if (m_DownKey != 0)
{
const uint32_t key = m_DownKey;
m_DownKey = 0;
Emit(InputEventType::KeyUp, key, 0);
}
if (m_State == State::GaveUp)
{
return;
}
if (m_State == State::Searching)
{
Search(m_Clock());
return;
}
uint8_t byte = 0;
if (!m_Read(byte))
{
if (++m_Failures >= kLostAfterFailures)
{
DEKI_LOG_WARNING("I2CKeyboard: the keyboard stopped answering; looking for it again");
m_State = State::Searching;
m_Probed = false;
}
return;
}
m_Failures = 0;
if (byte == 0)
{
return;
}
m_DownKey = Keys::ForCharacter(byte);
// Control codes (Enter, Backspace, Tab) are keys that type nothing.
const uint32_t character = (byte >= 32 && byte != 127) ? byte : 0;
Emit(InputEventType::KeyDown, m_DownKey, character);
}
} // namespace DekiInput