Skip to content

Commit 6647b1c

Browse files
committed
Add joycon support.
1 parent 11ea1d3 commit 6647b1c

19 files changed

+797
-76
lines changed

SerialPrograms/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,8 @@ file(GLOB MAIN_SOURCES
835835
Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.h
836836
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerWithScheduler.cpp
837837
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerWithScheduler.h
838+
Source/NintendoSwitch/Controllers/NintendoSwitch_Joycon.cpp
839+
Source/NintendoSwitch/Controllers/NintendoSwitch_Joycon.h
838840
Source/NintendoSwitch/Controllers/NintendoSwitch_VirtualControllerState.cpp
839841
Source/NintendoSwitch/Controllers/NintendoSwitch_VirtualControllerState.h
840842
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_Controller.cpp
@@ -843,6 +845,8 @@ file(GLOB MAIN_SOURCES
843845
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_PokkenController.h
844846
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.cpp
845847
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.h
848+
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.cpp
849+
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.h
846850
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.cpp
847851
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.h
848852
Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Connection.cpp

SerialPrograms/SerialPrograms.pro

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,15 @@ SOURCES += \
408408
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_Routines.cpp \
409409
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.cpp \
410410
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.cpp \
411+
Source/NintendoSwitch/Controllers/NintendoSwitch_Joycon.cpp \
411412
Source/NintendoSwitch/Controllers/NintendoSwitch_KeyboardMapping.cpp \
412413
Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.cpp \
413414
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerWithScheduler.cpp \
414415
Source/NintendoSwitch/Controllers/NintendoSwitch_VirtualControllerState.cpp \
415416
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_Controller.cpp \
416417
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_PokkenController.cpp \
417418
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.cpp \
419+
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.cpp \
418420
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.cpp \
419421
Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Connection.cpp \
420422
Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Descriptor.cpp \
@@ -1578,13 +1580,15 @@ HEADERS += \
15781580
Source/NintendoSwitch/Commands/NintendoSwitch_Messages_Device.h \
15791581
Source/NintendoSwitch/Commands/NintendoSwitch_Messages_PushButtons.h \
15801582
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.h \
1583+
Source/NintendoSwitch/Controllers/NintendoSwitch_Joycon.h \
15811584
Source/NintendoSwitch/Controllers/NintendoSwitch_KeyboardMapping.h \
15821585
Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.h \
15831586
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerWithScheduler.h \
15841587
Source/NintendoSwitch/Controllers/NintendoSwitch_VirtualControllerState.h \
15851588
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_Controller.h \
15861589
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_PokkenController.h \
15871590
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.h \
1591+
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.h \
15881592
Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.h \
15891593
Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Connection.h \
15901594
Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_Descriptor.h \

SerialPrograms/Source/Controllers/KeyboardInput/KeyboardInput.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
#ifndef PokemonAutomation_Controllers_KeyboardInput_H
88
#define PokemonAutomation_Controllers_KeyboardInput_H
99

10+
#include <map>
1011
#include <thread>
1112
#include <condition_variable>
13+
#include <Qt>
1214
#include "Common/Cpp/Concurrency/SpinLock.h"
15+
#include "Controllers/Controller.h"
16+
#include "Controllers/KeyboardInput/GlobalQtKeyMap.h"
1317
#include "KeyboardStateTracker.h"
1418

1519
class QKeyEvent;
@@ -79,6 +83,66 @@ class KeyboardInputController{
7983

8084

8185

86+
template <typename StateType, typename DeltaType>
87+
class KeyboardManager : public KeyboardInputController{
88+
public:
89+
KeyboardManager(AbstractController& controller)
90+
: KeyboardInputController(true)
91+
, m_controller(&controller)
92+
{}
93+
void stop() noexcept{
94+
{
95+
WriteSpinLock lg(m_lock);
96+
if (m_controller == nullptr){
97+
return;
98+
}
99+
m_controller = nullptr;
100+
}
101+
KeyboardInputController::stop();
102+
}
103+
104+
virtual std::unique_ptr<ControllerState> make_state() const override{
105+
return std::make_unique<StateType>();
106+
}
107+
virtual void update_state(ControllerState& state, const std::set<uint32_t>& pressed_keys) override{
108+
DeltaType deltas;
109+
const QtKeyMap& qkey_map = QtKeyMap::instance();
110+
for (uint32_t native_key : pressed_keys){
111+
std::set<Qt::Key> qkeys = qkey_map.get_QtKeys(native_key);
112+
for (Qt::Key qkey : qkeys){
113+
auto iter = m_mapping.find(qkey);
114+
if (iter != m_mapping.end()){
115+
deltas += iter->second;
116+
break;
117+
}
118+
}
119+
}
120+
deltas.to_state(static_cast<StateType&>(state));
121+
}
122+
virtual void cancel_all_commands() override{
123+
WriteSpinLock lg(m_lock);
124+
if (m_controller == nullptr){
125+
return;
126+
}
127+
m_controller->cancel_all_commands();
128+
}
129+
virtual void replace_on_next_command() override{
130+
WriteSpinLock lg(m_lock);
131+
if (m_controller == nullptr){
132+
return;
133+
}
134+
m_controller->replace_on_next_command();
135+
}
136+
137+
138+
protected:
139+
SpinLock m_lock;
140+
AbstractController* m_controller;
141+
std::map<Qt::Key, DeltaType> m_mapping;
142+
};
143+
144+
145+
82146

83147
}
84148
#endif

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase_Descriptor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_PokkenController.h"
1515
#include "NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.h"
16+
#include "NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.h"
1617

1718
//#include <iostream>
1819
//using std::cout;
@@ -86,6 +87,17 @@ std::unique_ptr<AbstractController> SerialPABotBase_Descriptor::make_controller(
8687
)
8788
);
8889

90+
case ControllerType::NintendoSwitch_LeftJoycon:
91+
case ControllerType::NintendoSwitch_RightJoycon:
92+
return std::unique_ptr<AbstractController>(
93+
new NintendoSwitch::SerialPABotBase_WirelessJoycon(
94+
logger,
95+
static_cast<SerialPABotBase_Connection&>(connection),
96+
controller_type,
97+
requirements
98+
)
99+
);
100+
89101
default:;
90102
}
91103

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,18 @@ enum Button : ButtonFlagType{
4747
BUTTON_RIGHT_SL = ((uint32_t)1 << 20),
4848
BUTTON_RIGHT_SR = ((uint32_t)1 << 21),
4949
};
50-
inline Button operator|(Button x, Button y){
50+
inline constexpr Button operator|(Button x, Button y){
5151
return (Button)((ButtonFlagType)x | (ButtonFlagType)y);
5252
}
53-
inline void operator|=(Button& x, Button y){
53+
inline constexpr void operator|=(Button& x, Button y){
5454
x = (Button)((ButtonFlagType)x | (ButtonFlagType)y);
5555
}
56+
inline constexpr Button operator&(Button x, Button y){
57+
return (Button)((ButtonFlagType)x & (ButtonFlagType)y);
58+
}
59+
inline constexpr void operator&=(Button& x, Button y){
60+
x = (Button)((ButtonFlagType)x & (ButtonFlagType)y);
61+
}
5662

5763
std::string button_to_string(Button button);
5864

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerWithScheduler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ void ControllerWithScheduler::issue_full_controller_state(
180180
cancellable->throw_if_cancelled();
181181
}
182182

183-
for (size_t c = 0; c < 14; c++){
184-
uint16_t mask = (uint16_t)1 << c;
183+
for (size_t c = 0; c < TOTAL_BUTTONS; c++){
184+
ButtonFlagType mask = (ButtonFlagType)1 << c;
185185
if (button & mask){
186186
this->issue_wait_for_resource(cancellable, m_buttons[c]);
187187
}
@@ -196,8 +196,8 @@ void ControllerWithScheduler::issue_full_controller_state(
196196
m_right_joystick.x = right_x;
197197
m_right_joystick.y = right_y;
198198

199-
for (size_t c = 0; c < 14; c++){
200-
uint16_t mask = (uint16_t)1 << c;
199+
for (size_t c = 0; c < TOTAL_BUTTONS; c++){
200+
ButtonFlagType mask = (ButtonFlagType)1 << c;
201201
if (button & mask){
202202
this->issue_to_resource(
203203
cancellable, m_buttons[c],
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* Nintendo Switch Joycon
2+
*
3+
* From: https://github.com/PokemonAutomation/Arduino-Source
4+
*
5+
*/
6+
7+
#include "Common/Cpp/Containers/Pimpl.tpp"
8+
#include "CommonTools/Async/InterruptableCommands.tpp"
9+
#include "CommonTools/Async/SuperControlSession.tpp"
10+
#include "Controllers/ControllerTypes.h"
11+
#include "Controllers/KeyboardInput/KeyboardInput.h"
12+
#include "NintendoSwitch/NintendoSwitch_Settings.h"
13+
#include "NintendoSwitch_VirtualControllerState.h"
14+
#include "NintendoSwitch_Joycon.h"
15+
16+
namespace PokemonAutomation{
17+
18+
// Instantiate some template helper classes.
19+
template class AsyncCommandSession<NintendoSwitch::JoyconController>;
20+
template class SuperControlSession<NintendoSwitch::JoyconController>;
21+
22+
namespace NintendoSwitch{
23+
24+
using namespace std::chrono_literals;
25+
26+
27+
28+
class JoyconController::KeyboardManager final :
29+
public PokemonAutomation::KeyboardManager<JoyconState, JoyconDeltas>
30+
{
31+
public:
32+
KeyboardManager(JoyconController& controller, ControllerType controller_type)
33+
: PokemonAutomation::KeyboardManager<JoyconState, JoyconDeltas>(controller)
34+
{
35+
std::vector<std::shared_ptr<EditableTableRow>> mapping;
36+
switch (controller_type){
37+
case ControllerType::NintendoSwitch_LeftJoycon:
38+
mapping = ConsoleSettings::instance().KEYBOARD_MAPPINGS.LEFT_JOYCON.current_refs();
39+
break;
40+
case ControllerType::NintendoSwitch_RightJoycon:
41+
mapping = ConsoleSettings::instance().KEYBOARD_MAPPINGS.RIGHT_JOYCON.current_refs();
42+
break;
43+
default:;
44+
}
45+
for (const auto& deltas : mapping){
46+
const JoyconKeyMapTableRow& row = static_cast<const JoyconKeyMapTableRow&>(*deltas);
47+
m_mapping[(Qt::Key)(uint32_t)row.key] += row.snapshot();
48+
}
49+
start();
50+
}
51+
~KeyboardManager(){
52+
stop();
53+
}
54+
virtual void send_state(const ControllerState& state) override{
55+
const JoyconState& switch_state = static_cast<const JoyconState&>(state);
56+
#if 0
57+
m_controller->logger().log(
58+
"VirtualController: (" + button_to_string(switch_state.buttons) +
59+
"), LJ(" + std::to_string(switch_state.joystick_x) + "," + std::to_string(switch_state.joystick_y) +
60+
")",
61+
COLOR_DARKGREEN
62+
);
63+
#endif
64+
WriteSpinLock lg(m_lock);
65+
if (m_controller == nullptr){
66+
return;
67+
}
68+
Milliseconds ticksize = m_controller->ticksize();
69+
static_cast<JoyconController*>(m_controller)->issue_full_controller_state(
70+
nullptr,
71+
switch_state.buttons,
72+
switch_state.joystick_x,
73+
switch_state.joystick_y,
74+
ticksize == Milliseconds::zero() ? 2000ms : ticksize * 255
75+
);
76+
}
77+
};
78+
79+
80+
81+
JoyconController::JoyconController(ControllerType controller_type)
82+
: m_keyboard_manager(CONSTRUCT_TOKEN, *this, controller_type)
83+
{
84+
85+
}
86+
JoyconController::~JoyconController(){
87+
88+
}
89+
void JoyconController::stop() noexcept{
90+
m_keyboard_manager->stop();
91+
}
92+
93+
94+
void JoyconController::keyboard_release_all(){
95+
m_keyboard_manager->clear_state();
96+
}
97+
void JoyconController::keyboard_press(const QKeyEvent& event){
98+
m_keyboard_manager->on_key_press(event);
99+
}
100+
void JoyconController::keyboard_release(const QKeyEvent& event){
101+
m_keyboard_manager->on_key_release(event);
102+
}
103+
104+
105+
106+
107+
108+
109+
110+
}
111+
}

0 commit comments

Comments
 (0)