Skip to content

Commit 0df6382

Browse files
committed
Added continuous scanner
1 parent 10eca02 commit 0df6382

16 files changed

+1859
-476
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
/.vs
2+
/bin
3+
/lib
4+
/obj

src/Wiimote.cpp

+113-42
Original file line numberDiff line numberDiff line change
@@ -121,30 +121,30 @@ void parseReadData(const u8* data, DataCallback callback, RegisterType reg)
121121
callback(data + 6);
122122
}
123123

124-
bool Wiimote::setReportMode(ReportMode mode)
125-
{
126-
_lock.lock();
127-
_state.reportMode = mode;
128-
_lock.unlock();
124+
void Wiimote::start(int featureFlags)
125+
{
126+
if (_running)
127+
{
128+
std::cout << "Already running" << std::endl;
129+
return;
130+
}
129131

130-
return _device->write(DataBuffer({ OutputReportType::DataReportMode, 0x00, mode }));
131-
}
132+
_features = featureFlags;
132133

133-
bool Wiimote::resetReportMode()
134-
{
135-
_lock.lock();
136-
ReportMode mode = _state.reportMode;
137-
_lock.unlock();
134+
updateStatus();
135+
updateWiimoteCalibration();
136+
identifyMotionPlus();
138137

139-
return _device->write(DataBuffer({ OutputReportType::DataReportMode, 0x00, mode }));
138+
_device->startReader();
140139
}
141140

142-
void Wiimote::start(ReportMode mode)
141+
void Wiimote::stop()
143142
{
144-
setReportMode(mode);
145-
updateWiimoteCalibration();
146-
identifyMotionPlus();
147-
_device->startReader();
143+
if (!_running)
144+
{
145+
_device->stopReader();
146+
_running = false;
147+
}
148148
}
149149

150150
bool Wiimote::setLeds(LedState state)
@@ -169,16 +169,8 @@ bool Wiimote::setRumble(bool rumble)
169169

170170
bool Wiimote::updateStatus()
171171
{
172-
_expectingStatusUpdate = true;
173-
u8 s = (_state.rumble == true ? 0x01 : 0x00);
174-
175-
if (!_device->write(DataBuffer({ OutputReportType::Status, s })))
176-
{
177-
_expectingStatusUpdate = false;
178-
return false;
179-
}
180-
181-
return true;
172+
u8 s = _state.leds | (_state.rumble == true ? 0x01 : 0x00);
173+
return _device->write(DataBuffer({ OutputReportType::Status, s }));
182174
}
183175

184176
void Wiimote::updateWiimoteCalibration()
@@ -212,8 +204,70 @@ void Wiimote::updateNunchuckCalibration()
212204
});
213205
}
214206

207+
#define SET_FLAG(flags, flag) flags |= flag
208+
#define UNSET_FLAG(flags, flag) flags &= ~flag
209+
210+
bool Wiimote::updateReportMode()
211+
{
212+
_state.reportMode = ReportModes::Unknown;
213+
214+
int features = _features;
215+
216+
if (!_state.extensionActive)
217+
{
218+
UNSET_FLAG(features, WiimoteFeatures::Extension);
219+
}
220+
221+
if (_features | WiimoteFeatures::MotionPlus && _state.motionPlusActive)
222+
{
223+
SET_FLAG(features, WiimoteFeatures::Extension);
224+
}
225+
226+
UNSET_FLAG(features, WiimoteFeatures::MotionPlus);
227+
228+
switch (features)
229+
{
230+
case WiimoteFeatures::Buttons:
231+
_state.reportMode = ReportModes::Buttons;
232+
break;
233+
case WiimoteFeatures::Buttons | WiimoteFeatures::Accelerometer:
234+
_state.reportMode = ReportModes::ButtonsAccel;
235+
break;
236+
case WiimoteFeatures::Buttons | WiimoteFeatures::Extension:
237+
_state.reportMode = ReportModes::ButtonsExtension19;
238+
break;
239+
case WiimoteFeatures::Buttons | WiimoteFeatures::Accelerometer | WiimoteFeatures::IR:
240+
_state.reportMode = ReportModes::ButtonsAccelIR;
241+
break;
242+
case WiimoteFeatures::Buttons | WiimoteFeatures::Accelerometer | WiimoteFeatures::Extension:
243+
_state.reportMode = ReportModes::ButtonsAccelExtension;
244+
break;
245+
case WiimoteFeatures::Buttons | WiimoteFeatures::IR | WiimoteFeatures::Extension:
246+
_state.reportMode = ReportModes::ButtonsIRExtension;
247+
break;
248+
case WiimoteFeatures::Buttons | WiimoteFeatures::Accelerometer | WiimoteFeatures::IR | WiimoteFeatures::Extension:
249+
_state.reportMode = ReportModes::ButtonsAccelIRExtension;
250+
break;
251+
case WiimoteFeatures::Extension:
252+
_state.reportMode = ReportModes::Extension;
253+
break;
254+
default:
255+
_state.reportMode = ReportModes::ButtonsAccelExtension;
256+
std::cout << "Unable to find an appropriate report mode, defaulting to ButtonsAccelExtension" << std::endl;
257+
}
258+
259+
std::cout << "Setting report mode: " << ReportModes::toString(_state.reportMode) << std::endl;
260+
261+
return _device->write(DataBuffer({ OutputReportType::DataReportMode, 0x00, _state.reportMode }));
262+
}
263+
215264
void Wiimote::updateExtension()
216265
{
266+
if (_state.extensionConnected == false)
267+
{
268+
_state.extensionActive = false;
269+
}
270+
217271
readRegister(RegisterTypes::ExtensionType2, 1, [this](const u8* d) {
218272
bool motionPlus = d[0] == 0x04;
219273

@@ -228,6 +282,7 @@ void Wiimote::updateExtension()
228282
} else {
229283
if (_state.extensionType != ExtensionTypes::None)
230284
{
285+
_state.extensionActive = false;
231286
std::cout << ExtensionTypes::toString(_state.extensionType) << " disconnected" << std::endl;
232287
}
233288

@@ -265,18 +320,19 @@ void Wiimote::identifyExtension()
265320
case ExtensionTypes::Drums:
266321
case ExtensionTypes::TaikoDrum:
267322
_state.extensionConnected = true;
323+
_state.extensionActive = true;
268324
_state.extensionType = (ExtensionType)type;
269325

270326
std::cout << ExtensionTypes::toString(_state.extensionType) << " connected" << std::endl;
271-
writeReportMode(ReportModes::ButtonsAccelExtension);
327+
updateReportMode();
272328

273329
break;
274330
case ExtensionTypes::MotionPlus:
275331
case ExtensionTypes::MotionPlus_TR:
276332
if (!_state.motionPlusActive)
277333
{
278334
_state.motionPlusActive = true;
279-
writeReportMode(ReportModes::ButtonsExtension19);
335+
updateReportMode();
280336
std::cout << "Motion plus active" << std::endl;
281337
}
282338

@@ -301,18 +357,18 @@ void Wiimote::identifyMotionPlus()
301357
if (d[0] == 0x01)
302358
{
303359
_state.wiimoteType = WiimoteTypes::WiimotePlus;
304-
_state.motionPlusAttached = true;
360+
_state.motionPlusAvailable = true;
305361
} else {
306362
for (int x = 0; x < 6; x++)
307363
{
308364
if (x != 4 && x != 0 && d[x] != ID_InactiveMotionPlus[x])
309365
{
310-
_state.motionPlusAttached = false;
366+
_state.motionPlusAvailable = false;
311367
return;
312368
}
313369
}
314370

315-
_state.motionPlusAttached = true;
371+
_state.motionPlusAvailable = true;
316372
}
317373
});
318374
}
@@ -397,12 +453,10 @@ void Wiimote::onMessage(const u8* b)
397453

398454
case InputReportTypes::Status:
399455
{
400-
if (!_expectingStatusUpdate) writeReportMode(_state.reportMode);
401-
_expectingStatusUpdate = false;
402-
403456
parseButtons(b, _state);
404457
parseStatus(b, _state);
405458
updateExtension();
459+
updateReportMode();
406460
}
407461
}
408462

@@ -411,11 +465,11 @@ void Wiimote::onMessage(const u8* b)
411465
if (_state.motionPlus.extensionConnected)
412466
{
413467
std::cout << "Extension connected" << std::endl;
414-
updateExtension();
415468
} else {
416469
std::cout << "Extension disconnected" << std::endl;
417-
updateExtension();
418470
}
471+
472+
updateExtension();
419473
}
420474

421475
if (_currentRead == nullptr && !_pendingReads.empty())
@@ -430,10 +484,27 @@ void Wiimote::onMessage(const u8* b)
430484
_lock.unlock();
431485
}
432486

433-
bool Wiimote::writeReportMode(ReportMode mode)
487+
void Wiimote::update()
434488
{
435-
_state.reportMode = mode;
436-
return _device->write(DataBuffer({ OutputReportType::DataReportMode, 0x00, mode }));
489+
const WiimoteState& old = _outState[_outStateIdx];
490+
WiimoteState& next = _outState[1 - _outStateIdx];
491+
492+
_lock.lock();
493+
memcpy(&next, &_state, sizeof(WiimoteState));
494+
_lock.unlock();
495+
496+
if (_buttonCallback != nullptr)
497+
{
498+
for (int i = 0; i < c_WiimoteButtonCount; ++i)
499+
{
500+
if (next.buttons[i] != old.buttons[i])
501+
{
502+
_buttonCallback((WiimoteButton)i, next.buttons[i]);
503+
}
504+
}
505+
}
506+
507+
_outStateIdx = 1 - _outStateIdx;
437508
}
438509

439510
bool Wiimote::activateExtension()
@@ -451,7 +522,7 @@ bool Wiimote::activateExtension()
451522

452523
bool Wiimote::activateMotionPlus()
453524
{
454-
if (!_state.motionPlusAttached)
525+
if (!_state.motionPlusAvailable)
455526
{
456527
std::cout << "There is a request to activate the Wii Motion Plus even though it has not been confirmed to exist! Trying anyway..." << std::endl;
457528
}

src/Wiimote.h

+58-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,27 @@
44
#include <mutex>
55
#include <queue>
66

7+
#define BIT_ENUM(shift) 1 << shift
8+
79
typedef WiimoteDeviceWindows WiimoteDevice;
10+
typedef std::function<void(WiimoteButton button, bool down)> ButtonCallback;
11+
12+
namespace WiimoteFeatures {
13+
enum WiimoteFeature
14+
{
15+
None,
16+
Buttons = BIT_ENUM(1),
17+
Accelerometer = BIT_ENUM(2),
18+
Extension = BIT_ENUM(3),
19+
IR = BIT_ENUM(4),
20+
MotionPlus = BIT_ENUM(5),
21+
22+
NoIR = Buttons | Accelerometer | Extension | MotionPlus,
23+
All = NoIR | IR
24+
};
25+
}
26+
typedef WiimoteFeatures::WiimoteFeature WiimoteFeature;
27+
typedef int WiimoteFeatureFlags;
828

929
struct PendingRead
1030
{
@@ -18,52 +38,74 @@ class Wiimote
1838
private:
1939
WiimoteDevice* _device;
2040
WiimoteState _state;
21-
bool _expectingStatusUpdate = false;
2241
DataCallback _currentRead;
2342
RegisterType _currentReadRegister;
24-
bool _valid = false;
2543
std::mutex _lock;
2644
std::queue<PendingRead> _pendingReads;
45+
ButtonCallback _buttonCallback;
46+
int _features = WiimoteFeatures::None;
47+
48+
WiimoteState _outState[2];
49+
int _outStateIdx = 0;
50+
int _id = -1;
51+
bool _running = false;
2752

2853
public:
2954
Wiimote(WiimoteDevice* device) : _device(device)
3055
{
3156
memset(&_state, 0, sizeof(WiimoteState));
3257
device->setCallback([this](const u8* data) { onMessage(data); });
33-
_valid = device->setup();
3458
}
3559

3660
~Wiimote()
3761
{
38-
62+
stop();
3963
}
4064

41-
void start(ReportMode mode = ReportModes::ButtonsAccel);
42-
void stop() { _device->disconnect(); }
65+
void start(int featureFlags);
66+
void stop();
4367

44-
bool valid() const { return _valid; }
45-
bool available() { return _valid && updateStatus(); }
68+
bool available() { return _device->connected(); }
4669

4770
bool setLeds(LedState state);
48-
bool setReportMode(ReportMode mode);
4971
bool setRumble(bool rumble);
5072

5173
bool activateMotionPlus();
5274
bool deactivateMotionPlus();
5375

54-
void getState(WiimoteState& state)
76+
void onButton(ButtonCallback callback)
5577
{
56-
_lock.lock();
57-
memcpy(&state, &_state, sizeof(WiimoteState));
58-
_lock.unlock();
78+
_buttonCallback = callback;
5979
}
6080

81+
const WiimoteState& getState()
82+
{
83+
return _outState[_outStateIdx];
84+
}
85+
86+
void enableFeature(WiimoteFeature feature)
87+
{
88+
_features |= feature;
89+
}
90+
91+
void disableFeature(WiimoteFeature feature)
92+
{
93+
_features &= ~feature;
94+
}
95+
96+
void setFeatures(WiimoteFeatureFlags featureFlags)
97+
{
98+
_features = featureFlags;
99+
}
100+
101+
void update();
102+
61103
private:
62-
bool resetReportMode();
63104
bool updateStatus();
64105
void updateExtension();
65106
void updateWiimoteCalibration();
66107
void updateNunchuckCalibration();
108+
bool updateReportMode();
67109

68110
bool activateExtension();
69111

@@ -72,7 +114,8 @@ class Wiimote
72114

73115
void readRegister(RegisterType type, short size, DataCallback callback);
74116
bool writeRegister(RegisterType type, const DataBuffer& buffer);
75-
bool writeReportMode(ReportMode mode);
76117

77118
void onMessage(const u8* data);
119+
120+
friend class WiimoteManager;
78121
};

0 commit comments

Comments
 (0)