-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInputController.cpp
More file actions
169 lines (153 loc) · 6.04 KB
/
Copy pathInputController.cpp
File metadata and controls
169 lines (153 loc) · 6.04 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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include "InputController.h"
bool TinyCon::DebouncedButton::Get() const
{
int8_t count = 0;
for (int8_t i = 0; i < 4; ++i)
if (StateAt(i) && ++count > 2) return true;
return false;
}
void TinyCon::SeesawController::Init(TwoWire& i2c, int8_t controller)
{
Device = {&i2c};
Controller = controller;
if ((Present = Device.begin(AddressByController[Controller]))) Init();
}
void TinyCon::SeesawController::Init()
{
Device.pinModeBulk(InputButtonMask, INPUT_PULLUP);
Device.setGPIOInterrupts(InputButtonMask, 1);
}
void TinyCon::SeesawController::Update()
{
if (!Present)
{
if ((Present = Device.begin(AddressByController[Controller]))) Init();
}
else if (auto buttonStates = Device.digitalReadBulk(InputButtonMask))
{
for (auto i = 0; i < InputButtonCount; ++i)
Buttons[i].AddState((buttonStates & InputButtons[i]) == 0);
for (auto i = 0; i < InputAxisCount; ++i)
Axis[i] = Tiny::Math::Min(Tiny::Math::Max(Device.analogRead(InputAxis[i]) / 512.0f - 1.0f, -1.0f), 1.0f);
}
else
// This is relevant for Seesaw inputs we connect via Stemma QT, since they may still have a reset button.
// This will result in the input register being all 0's, looking like all buttons are pressed at the same
// time. Try to reinitialize the device, causing a software reset in the process. Discard the input after,
// so we don't get random results because of the cached button states.
Present = false;
}
bool TinyCon::SeesawController::GetUpdatedButton(int8_t index) const
{
const auto mask = InputButtons[index];
return Device.digitalReadBulk(mask) == 0;
}
void TinyCon::SeesawController::Reset()
{
Present = false;
Device.SWReset();
}
void TinyCon::PinsInputController::Update()
{
for (std::size_t axisIndex = 0; axisIndex < AxisPins.size(); ++axisIndex)
Axis[axisIndex] = analogRead(AxisPins[axisIndex]) / 512.0f - 1.0f;
for (std::size_t buttonIndex = 0; buttonIndex < ButtonPins.size(); ++buttonIndex)
Buttons[buttonIndex].AddState(digitalRead(ButtonPins[buttonIndex]) == ((ButtonActiveState == ActiveState::High) ? HIGH : LOW));
}
bool TinyCon::PinsInputController::GetUpdatedButton(int8_t index) const
{
return digitalRead(ButtonPins[index]) == ((ButtonActiveState == ActiveState::High) ? HIGH : LOW);
}
void TinyCon::PinsInputController::Init(const std::array<int8_t, MaxNativeAdcPinCount>& axisPins, const std::array<int8_t, MaxNativeGpioPinCount>& buttonPins, ActiveState activeState)
{
AxisCount = CountNotNC(axisPins);
ButtonCount = CountNotNC(buttonPins);
Present = AxisCount > 0 || ButtonCount > 0;
ButtonActiveState = activeState;
memcpy(AxisPins.data(), axisPins.data(), AxisPins.size() * sizeof(int8_t));
memcpy(ButtonPins.data(), buttonPins.data(), ButtonPins.size() * sizeof(int8_t));
}
void TinyCon::InputController::Init(const std::array<int8_t, MaxNativeAdcPinCount>& axisPins, const std::array<int8_t, MaxNativeGpioPinCount>& buttonPins, ActiveState activeState)
{
Pins.Init(axisPins, buttonPins, activeState);
if (Pins.Present)
{
Type = Tiny::Drivers::Input::TITinyConControllerTypes::Pins;
Present = true;
}
else Present = false;
}
void TinyCon::InputController::Init(TwoWire& i2c, int8_t controller)
{
if (controller < 4) Seesaw.Init(i2c, controller);
if (Seesaw.Present)
{
Type = Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw;
Present = Seesaw.Present;
}
else Present = false;
}
void TinyCon::InputController::Update()
{
int8_t axisIndex = 0;
int8_t buttonIndex = 0;
switch (Type)
{
case Tiny::Drivers::Input::TITinyConControllerTypes::Pins:
Pins.Update();
for (float axis : Pins.Axis) Axis[axisIndex++] = axis;
for (auto & button : Pins.Buttons) Buttons[buttonIndex++] = button.Get();
break;
case Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw:
Seesaw.Update();
for (float axis : Seesaw.Axis) Axis[axisIndex++] = axis;
for (auto & button : Seesaw.Buttons) Buttons[buttonIndex++] = button.Get();
break;
default: break;
}
}
void TinyCon::InputController::Reset()
{
Enabled = true;
switch (Type)
{
case Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw: if (Seesaw.Present) Seesaw.Reset(); break;
default: break;
}
}
bool TinyCon::InputController::GetUpdatedButton(int8_t index) const
{
switch (Type)
{
case Tiny::Drivers::Input::TITinyConControllerTypes::Pins: return Pins.GetUpdatedButton(index);
case Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw: return Seesaw.GetUpdatedButton(index);
default: return false;
}
}
Tiny::Drivers::Input::TITinyConControllerTypes TinyCon::InputController::GetType() const
{
switch (Type)
{
case Tiny::Drivers::Input::TITinyConControllerTypes::Pins: return Pins.Present ? Tiny::Drivers::Input::TITinyConControllerTypes::Pins : Tiny::Drivers::Input::TITinyConControllerTypes::None;
case Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw: return Seesaw.Present ? Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw : Tiny::Drivers::Input::TITinyConControllerTypes::None;
default: return Tiny::Drivers::Input::TITinyConControllerTypes::None;
}
}
int16_t TinyCon::InputController::GetAxisCount() const
{
switch (Type)
{
case Tiny::Drivers::Input::TITinyConControllerTypes::Pins: return Pins.GetAxisCount();
case Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw: return Seesaw.Present ? sizeof(Seesaw.Axis) / sizeof(Seesaw.Axis[0]): 0;
default: return 0;
}
}
int16_t TinyCon::InputController::GetButtonCount() const
{
switch (Type)
{
case Tiny::Drivers::Input::TITinyConControllerTypes::Pins: return Pins.GetButtonCount();
case Tiny::Drivers::Input::TITinyConControllerTypes::Seesaw: return Seesaw.Present ? sizeof(Seesaw.Buttons) / sizeof(Seesaw.Buttons[0]): 0;
default: return 0;
}
}