Skip to content

Commit adb165f

Browse files
committed
Calibrate the ESP32 joysticks for real this time. (hopefully)
1 parent c2fec9a commit adb165f

8 files changed

+97
-22
lines changed

SerialPrograms/Source/Controllers/JoystickTools.h

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,35 @@ namespace PokemonAutomation{
1414
namespace JoystickTools{
1515

1616

17+
inline void max_out_magnitude(double& x, double& y){
18+
double mag = x*x + y*y;
19+
if (mag == 0){
20+
return;
21+
}
22+
23+
double abs_x = std::abs(x);
24+
double abs_y = std::abs(y);
25+
26+
if (abs_x < abs_y){
27+
x /= abs_y;
28+
y = y < 0 ? -1 : 1;
29+
}else{
30+
y /= abs_x;
31+
x = x < 0 ? -1 : 1;
32+
}
33+
}
34+
inline double project_to_range(double x, double lo, double hi){
35+
if (x <= -1){
36+
return -1;
37+
}
38+
if (x >= 1){
39+
return 1;
40+
}
41+
return x * (hi - lo) + lo;
42+
}
43+
44+
45+
1746

1847
inline double linear_u8_to_float(uint8_t x){
1948
if (x <= 128){
@@ -55,26 +84,28 @@ inline uint16_t linear_float_to_u16(double f){
5584
return (uint16_t)(f + 0.5);
5685
}
5786
}
58-
inline uint16_t linear_float_to_u12(double lo, double hi, double f){
59-
if (f == 0){
60-
return 2048;
61-
}else if (f <= 0){
87+
88+
89+
90+
inline uint16_t linear_float_to_u12(double f){
91+
if (f <= 0){
6292
f = std::max<double>(f, -1);
63-
// if (f < -1){ return 0; }
64-
f = f * (hi - lo) - lo;
6593
f = f * 2048 + 2048;
6694
return (uint16_t)(f + 0.5);
6795
}else{
6896
f = std::min<double>(f, +1);
69-
// if (f > 1){ return 4095; }
70-
f = f * (hi - lo) + lo;
7197
f = f * 2047 + 2048;
7298
return (uint16_t)(f + 0.5);
7399
}
74100
}
75101

76102

77103

104+
105+
106+
107+
108+
78109
}
79110
}
80111
#endif

SerialPrograms/Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.h

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef PokemonAutomation_NintendoSwitch_SerialPABotBase_WirelessController_H
88
#define PokemonAutomation_NintendoSwitch_SerialPABotBase_WirelessController_H
99

10+
#include <cmath>
1011
#include "Common/SerialPABotBase/SerialPABotBase_Messages_ESP32.h"
1112
#include "Controllers/JoystickTools.h"
1213
#include "NintendoSwitch_SerialPABotBase_Controller.h"
@@ -44,6 +45,7 @@ class SerialPABotBase_WirelessController : public SerialPABotBase_Controller{
4445

4546

4647
protected:
48+
template <uint16_t min_threshold, uint16_t max_threshold>
4749
void encode_joystick(uint8_t data[3], uint8_t x, uint8_t y){
4850
// 2048 is the neutral position.
4951
//
@@ -52,25 +54,46 @@ class SerialPABotBase_WirelessController : public SerialPABotBase_Controller{
5254
//
5355
// ~320 is where it reaches the maximum value.
5456
//
55-
// It we linearly interpolate between 1897 and 320, we seem to match
57+
// If we linearly interpolate between 1897 and 320, we seem to match
5658
// the wired controller's behavior.
5759
//
5860
// I suspect the need to offset by 151 from 2048 -> 1897 is Nintendo's
5961
// way to alleviate the joycon drift problem.
60-
const uint16_t min = 1897;
62+
//
63+
// The values 320 and 1897 are for the pro controller. Joycons are
64+
// slightly different.
65+
//
66+
// const uint16_t min = 1897;
6167
// const uint16_t max = 320;
62-
const uint16_t max = 275; // REMOVE: TODO: Fix the clipping for real.
68+
// const uint16_t max = 275;
6369

64-
const double lo = 1 - min / 2048.;
65-
const double hi = 1 - max / 2048.;
70+
constexpr double lo = 1 - min_threshold / 2048.;
71+
constexpr double hi = 1 - max_threshold / 2048.;
6672

6773
double fx = JoystickTools::linear_u8_to_float(x);
6874
double fy = -JoystickTools::linear_u8_to_float(y);
6975
// cout << "fx = " << fx << ", fy = " << fy << endl;
76+
double mag_squared = fx*fx + fy*fy;
77+
78+
uint16_t wx, wy;
79+
if (mag_squared == 0){
80+
wx = 2048;
81+
wy = 2048;
82+
}else if (mag_squared >= 1){
83+
JoystickTools::max_out_magnitude(fx, fy);
84+
wx = JoystickTools::linear_float_to_u12(fx);
85+
wy = JoystickTools::linear_float_to_u12(fy);
86+
}else{
87+
double true_mag = std::sqrt(mag_squared);
88+
double report_mag = JoystickTools::project_to_range(true_mag, lo, hi);
89+
double scale = report_mag / true_mag;
90+
wx = JoystickTools::linear_float_to_u12(fx * scale);
91+
wy = JoystickTools::linear_float_to_u12(fy * scale);
92+
}
7093

71-
uint16_t wx = JoystickTools::linear_float_to_u12(lo, hi, fx);
72-
uint16_t wy = JoystickTools::linear_float_to_u12(lo, hi, fy);
7394
// cout << "wx = " << wx << ", wy = " << wy << endl;
95+
// wy = 2048;
96+
// wx = 260;
7497

7598
data[0] = (uint8_t)wx;
7699
data[1] = (uint8_t)(wx >> 8 | wy << 4);

SerialPrograms/Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,10 @@ void SerialPABotBase_WirelessJoycon::push_state_left_joycon(const Cancellable* c
181181

182182
// Left Stick
183183
if (m_left_joystick.is_busy()){
184-
encode_joystick(report.left_joystick, m_left_joystick.x, m_left_joystick.y);
184+
encode_joystick<JOYSTICK_MIN_THRESHOLD, JOYSTICK_MAX_THRESHOLD>(
185+
report.left_joystick,
186+
m_left_joystick.x, m_left_joystick.y
187+
);
185188
}
186189

187190
issue_report(cancellable, report, duration);
@@ -238,7 +241,10 @@ void SerialPABotBase_WirelessJoycon::push_state_right_joycon(const Cancellable*
238241

239242
// Right Stick
240243
if (m_right_joystick.is_busy()){
241-
encode_joystick(report.right_joystick, m_right_joystick.x, m_right_joystick.y);
244+
encode_joystick<JOYSTICK_MIN_THRESHOLD, JOYSTICK_MAX_THRESHOLD>(
245+
report.right_joystick,
246+
m_right_joystick.x, m_right_joystick.y
247+
);
242248
}
243249

244250
issue_report(cancellable, report, duration);

SerialPrograms/Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessJoycon.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class SerialPABotBase_WirelessJoycon final :
1919
public JoyconController,
2020
public SerialPABotBase_WirelessController
2121
{
22+
static constexpr uint16_t JOYSTICK_MIN_THRESHOLD = 1873;
23+
static constexpr uint16_t JOYSTICK_MAX_THRESHOLD = 260;
24+
2225
public:
2326
SerialPABotBase_WirelessJoycon(
2427
Logger& logger,

SerialPrograms/Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,18 @@ void SerialPABotBase_WirelessProController::push_state(const Cancellable* cancel
9595

9696
// Left Stick
9797
if (m_left_joystick.is_busy()){
98-
encode_joystick(report.left_joystick, m_left_joystick.x, m_left_joystick.y);
98+
encode_joystick<JOYSTICK_MIN_THRESHOLD, JOYSTICK_MAX_THRESHOLD>(
99+
report.left_joystick,
100+
m_left_joystick.x, m_left_joystick.y
101+
);
99102
}
100103

101104
// Right Stick
102105
if (m_right_joystick.is_busy()){
103-
encode_joystick(report.right_joystick, m_right_joystick.x, m_right_joystick.y);
106+
encode_joystick<JOYSTICK_MIN_THRESHOLD, JOYSTICK_MAX_THRESHOLD>(
107+
report.right_joystick,
108+
m_right_joystick.x, m_right_joystick.y
109+
);
104110
}
105111

106112
issue_report(cancellable, report, duration);

SerialPrograms/Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessProController.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class SerialPABotBase_WirelessProController final :
1919
public ProController,
2020
public SerialPABotBase_WirelessController
2121
{
22+
static constexpr uint16_t JOYSTICK_MIN_THRESHOLD = 1897;
23+
static constexpr uint16_t JOYSTICK_MAX_THRESHOLD = 320;
24+
2225
public:
2326
SerialPABotBase_WirelessProController(
2427
Logger& logger,

SerialPrograms/Source/NintendoSwitch/DevPrograms/JoyconProgram.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@ void JoyconProgram::program(SingleSwitchProgramEnvironment& env, CancellableScop
4545
// No support for gyro yet. That's coming later.
4646
//
4747

48+
// pbf_move_joystick(context, 64, 64, 10000ms, 0ms);
49+
50+
#if 1
4851
pbf_press_button(context, BUTTON_A, 200ms, 2000ms);
4952
pbf_press_button(context, BUTTON_HOME, 200ms, 2000ms);
5053
pbf_move_joystick(context, 128, 0, 100ms, 100ms);
5154
pbf_move_joystick(context, 128, 0, 100ms, 100ms);
5255
pbf_move_joystick(context, 255, 128, 100ms, 100ms);
5356
pbf_move_joystick(context, 128, 0, 100ms, 100ms);
5457
pbf_press_button(context, BUTTON_X, 200ms, 2000ms);
55-
58+
#endif
5659

5760
}
5861

SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
312312

313313
// std::terminate();
314314

315+
#if 0
315316
for (size_t i = 0; i < 100; i++){
316317
for (size_t c = 0; c < 2; c++){
317318
ssf_issue_scroll(context, DPAD_RIGHT, 32ms);
@@ -323,7 +324,6 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
323324

324325

325326

326-
#if 0
327327
for (size_t c = 0; c < 60; c++){
328328
ssf_issue_scroll(context, DPAD_DOWN, 20ms);
329329
}
@@ -333,7 +333,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
333333
}
334334
#endif
335335

336-
// pbf_move_left_joystick(context, 0, 0, 10000, 0);
336+
pbf_move_left_joystick(context, 38, 38, 10000, 0);
337337

338338

339339
// ssf_issue_scroll(context, DPAD_LEFT, 0);

0 commit comments

Comments
 (0)