diff options
Diffstat (limited to 'src/input_common')
6 files changed, 215 insertions, 114 deletions
diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp index f6e7e97d5..d8f040f75 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.cpp +++ b/src/input_common/helpers/joycon_protocol/calibration.cpp | |||
| @@ -13,33 +13,33 @@ CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle) | |||
| 13 | 13 | ||
| 14 | DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { | 14 | DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { |
| 15 | ScopedSetBlocking sb(this); | 15 | ScopedSetBlocking sb(this); |
| 16 | std::vector<u8> buffer; | ||
| 17 | DriverResult result{DriverResult::Success}; | 16 | DriverResult result{DriverResult::Success}; |
| 17 | JoystickLeftSpiCalibration spi_calibration{}; | ||
| 18 | bool has_user_calibration = false; | ||
| 18 | calibration = {}; | 19 | calibration = {}; |
| 19 | 20 | ||
| 20 | result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer); | ||
| 21 | |||
| 22 | if (result == DriverResult::Success) { | 21 | if (result == DriverResult::Success) { |
| 23 | const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1; | 22 | result = HasUserCalibration(SpiAddress::USER_LEFT_MAGIC, has_user_calibration); |
| 24 | if (has_user_calibration) { | ||
| 25 | result = ReadSPI(CalAddr::USER_LEFT_DATA, 9, buffer); | ||
| 26 | } else { | ||
| 27 | result = ReadSPI(CalAddr::FACT_LEFT_DATA, 9, buffer); | ||
| 28 | } | ||
| 29 | } | 23 | } |
| 30 | 24 | ||
| 31 | if (result == DriverResult::Success) { | 25 | // Read User defined calibration |
| 32 | calibration.x.max = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]); | 26 | if (result == DriverResult::Success && has_user_calibration) { |
| 33 | calibration.y.max = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4)); | 27 | result = ReadSPI(SpiAddress::USER_LEFT_DATA, spi_calibration); |
| 34 | calibration.x.center = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]); | ||
| 35 | calibration.y.center = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4)); | ||
| 36 | calibration.x.min = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]); | ||
| 37 | calibration.y.min = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4)); | ||
| 38 | } | 28 | } |
| 39 | 29 | ||
| 40 | // Nintendo fix for drifting stick | 30 | // Read Factory calibration |
| 41 | // result = ReadSPI(0x60, 0x86 ,buffer, 16); | 31 | if (result == DriverResult::Success && !has_user_calibration) { |
| 42 | // calibration.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]); | 32 | result = ReadSPI(SpiAddress::FACT_LEFT_DATA, spi_calibration); |
| 33 | } | ||
| 34 | |||
| 35 | if (result == DriverResult::Success) { | ||
| 36 | calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); | ||
| 37 | calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); | ||
| 38 | calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); | ||
| 39 | calibration.y.min = GetYAxisCalibrationValue(spi_calibration.min); | ||
| 40 | calibration.x.max = GetXAxisCalibrationValue(spi_calibration.max); | ||
| 41 | calibration.y.max = GetYAxisCalibrationValue(spi_calibration.max); | ||
| 42 | } | ||
| 43 | 43 | ||
| 44 | // Set a valid default calibration if data is missing | 44 | // Set a valid default calibration if data is missing |
| 45 | ValidateCalibration(calibration); | 45 | ValidateCalibration(calibration); |
| @@ -49,33 +49,33 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration | |||
| 49 | 49 | ||
| 50 | DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) { | 50 | DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) { |
| 51 | ScopedSetBlocking sb(this); | 51 | ScopedSetBlocking sb(this); |
| 52 | std::vector<u8> buffer; | ||
| 53 | DriverResult result{DriverResult::Success}; | 52 | DriverResult result{DriverResult::Success}; |
| 53 | JoystickRightSpiCalibration spi_calibration{}; | ||
| 54 | bool has_user_calibration = false; | ||
| 54 | calibration = {}; | 55 | calibration = {}; |
| 55 | 56 | ||
| 56 | result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer); | ||
| 57 | |||
| 58 | if (result == DriverResult::Success) { | 57 | if (result == DriverResult::Success) { |
| 59 | const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1; | 58 | result = HasUserCalibration(SpiAddress::USER_RIGHT_MAGIC, has_user_calibration); |
| 60 | if (has_user_calibration) { | ||
| 61 | result = ReadSPI(CalAddr::USER_RIGHT_DATA, 9, buffer); | ||
| 62 | } else { | ||
| 63 | result = ReadSPI(CalAddr::FACT_RIGHT_DATA, 9, buffer); | ||
| 64 | } | ||
| 65 | } | 59 | } |
| 66 | 60 | ||
| 67 | if (result == DriverResult::Success) { | 61 | // Read User defined calibration |
| 68 | calibration.x.center = static_cast<u16>(((buffer[1] & 0x0F) << 8) | buffer[0]); | 62 | if (result == DriverResult::Success && has_user_calibration) { |
| 69 | calibration.y.center = static_cast<u16>((buffer[2] << 4) | (buffer[1] >> 4)); | 63 | result = ReadSPI(SpiAddress::USER_RIGHT_DATA, spi_calibration); |
| 70 | calibration.x.min = static_cast<u16>(((buffer[4] & 0x0F) << 8) | buffer[3]); | 64 | } |
| 71 | calibration.y.min = static_cast<u16>((buffer[5] << 4) | (buffer[4] >> 4)); | 65 | |
| 72 | calibration.x.max = static_cast<u16>(((buffer[7] & 0x0F) << 8) | buffer[6]); | 66 | // Read Factory calibration |
| 73 | calibration.y.max = static_cast<u16>((buffer[8] << 4) | (buffer[7] >> 4)); | 67 | if (result == DriverResult::Success && !has_user_calibration) { |
| 68 | result = ReadSPI(SpiAddress::FACT_RIGHT_DATA, spi_calibration); | ||
| 74 | } | 69 | } |
| 75 | 70 | ||
| 76 | // Nintendo fix for drifting stick | 71 | if (result == DriverResult::Success) { |
| 77 | // buffer = ReadSPI(0x60, 0x98 , 16); | 72 | calibration.x.center = GetXAxisCalibrationValue(spi_calibration.center); |
| 78 | // joystick.deadzone = (u16)((buffer[4] << 8) & 0xF00 | buffer[3]); | 73 | calibration.y.center = GetYAxisCalibrationValue(spi_calibration.center); |
| 74 | calibration.x.min = GetXAxisCalibrationValue(spi_calibration.min); | ||
| 75 | calibration.y.min = GetYAxisCalibrationValue(spi_calibration.min); | ||
| 76 | calibration.x.max = GetXAxisCalibrationValue(spi_calibration.max); | ||
| 77 | calibration.y.max = GetYAxisCalibrationValue(spi_calibration.max); | ||
| 78 | } | ||
| 79 | 79 | ||
| 80 | // Set a valid default calibration if data is missing | 80 | // Set a valid default calibration if data is missing |
| 81 | ValidateCalibration(calibration); | 81 | ValidateCalibration(calibration); |
| @@ -85,39 +85,41 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio | |||
| 85 | 85 | ||
| 86 | DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { | 86 | DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) { |
| 87 | ScopedSetBlocking sb(this); | 87 | ScopedSetBlocking sb(this); |
| 88 | std::vector<u8> buffer; | ||
| 89 | DriverResult result{DriverResult::Success}; | 88 | DriverResult result{DriverResult::Success}; |
| 89 | ImuSpiCalibration spi_calibration{}; | ||
| 90 | bool has_user_calibration = false; | ||
| 90 | calibration = {}; | 91 | calibration = {}; |
| 91 | 92 | ||
| 92 | result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer); | ||
| 93 | |||
| 94 | if (result == DriverResult::Success) { | 93 | if (result == DriverResult::Success) { |
| 95 | const bool has_user_calibration = buffer[0] == 0xB2 && buffer[1] == 0xA1; | 94 | result = HasUserCalibration(SpiAddress::USER_IMU_MAGIC, has_user_calibration); |
| 96 | if (has_user_calibration) { | 95 | } |
| 97 | result = ReadSPI(CalAddr::USER_IMU_DATA, sizeof(IMUCalibration), buffer); | 96 | |
| 98 | } else { | 97 | // Read User defined calibration |
| 99 | result = ReadSPI(CalAddr::FACT_IMU_DATA, sizeof(IMUCalibration), buffer); | 98 | if (result == DriverResult::Success && has_user_calibration) { |
| 100 | } | 99 | result = ReadSPI(SpiAddress::USER_IMU_DATA, spi_calibration); |
| 100 | } | ||
| 101 | |||
| 102 | // Read Factory calibration | ||
| 103 | if (result == DriverResult::Success && !has_user_calibration) { | ||
| 104 | result = ReadSPI(SpiAddress::FACT_IMU_DATA, spi_calibration); | ||
| 101 | } | 105 | } |
| 102 | 106 | ||
| 103 | if (result == DriverResult::Success) { | 107 | if (result == DriverResult::Success) { |
| 104 | IMUCalibration device_calibration{}; | 108 | calibration.accelerometer[0].offset = spi_calibration.accelerometer_offset[0]; |
| 105 | memcpy(&device_calibration, buffer.data(), sizeof(IMUCalibration)); | 109 | calibration.accelerometer[1].offset = spi_calibration.accelerometer_offset[1]; |
| 106 | calibration.accelerometer[0].offset = device_calibration.accelerometer_offset[0]; | 110 | calibration.accelerometer[2].offset = spi_calibration.accelerometer_offset[2]; |
| 107 | calibration.accelerometer[1].offset = device_calibration.accelerometer_offset[1]; | ||
| 108 | calibration.accelerometer[2].offset = device_calibration.accelerometer_offset[2]; | ||
| 109 | 111 | ||
| 110 | calibration.accelerometer[0].scale = device_calibration.accelerometer_scale[0]; | 112 | calibration.accelerometer[0].scale = spi_calibration.accelerometer_scale[0]; |
| 111 | calibration.accelerometer[1].scale = device_calibration.accelerometer_scale[1]; | 113 | calibration.accelerometer[1].scale = spi_calibration.accelerometer_scale[1]; |
| 112 | calibration.accelerometer[2].scale = device_calibration.accelerometer_scale[2]; | 114 | calibration.accelerometer[2].scale = spi_calibration.accelerometer_scale[2]; |
| 113 | 115 | ||
| 114 | calibration.gyro[0].offset = device_calibration.gyroscope_offset[0]; | 116 | calibration.gyro[0].offset = spi_calibration.gyroscope_offset[0]; |
| 115 | calibration.gyro[1].offset = device_calibration.gyroscope_offset[1]; | 117 | calibration.gyro[1].offset = spi_calibration.gyroscope_offset[1]; |
| 116 | calibration.gyro[2].offset = device_calibration.gyroscope_offset[2]; | 118 | calibration.gyro[2].offset = spi_calibration.gyroscope_offset[2]; |
| 117 | 119 | ||
| 118 | calibration.gyro[0].scale = device_calibration.gyroscope_scale[0]; | 120 | calibration.gyro[0].scale = spi_calibration.gyroscope_scale[0]; |
| 119 | calibration.gyro[1].scale = device_calibration.gyroscope_scale[1]; | 121 | calibration.gyro[1].scale = spi_calibration.gyroscope_scale[1]; |
| 120 | calibration.gyro[2].scale = device_calibration.gyroscope_scale[2]; | 122 | calibration.gyro[2].scale = spi_calibration.gyroscope_scale[2]; |
| 121 | } | 123 | } |
| 122 | 124 | ||
| 123 | ValidateCalibration(calibration); | 125 | ValidateCalibration(calibration); |
| @@ -127,10 +129,12 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati | |||
| 127 | 129 | ||
| 128 | DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration, | 130 | DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibration, |
| 129 | s16 current_value) { | 131 | s16 current_value) { |
| 132 | constexpr s16 DefaultRingRange{800}; | ||
| 133 | |||
| 130 | // TODO: Get default calibration form ring itself | 134 | // TODO: Get default calibration form ring itself |
| 131 | if (ring_data_max == 0 && ring_data_min == 0) { | 135 | if (ring_data_max == 0 && ring_data_min == 0) { |
| 132 | ring_data_max = current_value + 800; | 136 | ring_data_max = current_value + DefaultRingRange; |
| 133 | ring_data_min = current_value - 800; | 137 | ring_data_min = current_value - DefaultRingRange; |
| 134 | ring_data_default = current_value; | 138 | ring_data_default = current_value; |
| 135 | } | 139 | } |
| 136 | ring_data_max = std::max(ring_data_max, current_value); | 140 | ring_data_max = std::max(ring_data_max, current_value); |
| @@ -143,42 +147,72 @@ DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibratio | |||
| 143 | return DriverResult::Success; | 147 | return DriverResult::Success; |
| 144 | } | 148 | } |
| 145 | 149 | ||
| 150 | DriverResult CalibrationProtocol::HasUserCalibration(SpiAddress address, | ||
| 151 | bool& has_user_calibration) { | ||
| 152 | MagicSpiCalibration spi_magic{}; | ||
| 153 | const DriverResult result{ReadSPI(address, spi_magic)}; | ||
| 154 | has_user_calibration = false; | ||
| 155 | if (result == DriverResult::Success) { | ||
| 156 | has_user_calibration = spi_magic.first == CalibrationMagic::USR_MAGIC_0 && | ||
| 157 | spi_magic.second == CalibrationMagic::USR_MAGIC_1; | ||
| 158 | } | ||
| 159 | return result; | ||
| 160 | } | ||
| 161 | |||
| 162 | u16 CalibrationProtocol::GetXAxisCalibrationValue(std::span<u8> block) const { | ||
| 163 | return static_cast<u16>(((block[1] & 0x0F) << 8) | block[0]); | ||
| 164 | } | ||
| 165 | |||
| 166 | u16 CalibrationProtocol::GetYAxisCalibrationValue(std::span<u8> block) const { | ||
| 167 | return static_cast<u16>((block[2] << 4) | (block[1] >> 4)); | ||
| 168 | } | ||
| 169 | |||
| 146 | void CalibrationProtocol::ValidateCalibration(JoyStickCalibration& calibration) { | 170 | void CalibrationProtocol::ValidateCalibration(JoyStickCalibration& calibration) { |
| 147 | constexpr u16 DefaultStickCenter{2048}; | 171 | constexpr u16 DefaultStickCenter{0x800}; |
| 148 | constexpr u16 DefaultStickRange{1740}; | 172 | constexpr u16 DefaultStickRange{0x6cc}; |
| 149 | 173 | ||
| 150 | if (calibration.x.center == 0xFFF || calibration.x.center == 0) { | 174 | calibration.x.center = ValidateValue(calibration.x.center, DefaultStickCenter); |
| 151 | calibration.x.center = DefaultStickCenter; | 175 | calibration.x.max = ValidateValue(calibration.x.max, DefaultStickRange); |
| 152 | } | 176 | calibration.x.min = ValidateValue(calibration.x.min, DefaultStickRange); |
| 153 | if (calibration.x.max == 0xFFF || calibration.x.max == 0) { | 177 | |
| 154 | calibration.x.max = DefaultStickRange; | 178 | calibration.y.center = ValidateValue(calibration.y.center, DefaultStickCenter); |
| 179 | calibration.y.max = ValidateValue(calibration.y.max, DefaultStickRange); | ||
| 180 | calibration.y.min = ValidateValue(calibration.y.min, DefaultStickRange); | ||
| 181 | } | ||
| 182 | |||
| 183 | void CalibrationProtocol::ValidateCalibration(MotionCalibration& calibration) { | ||
| 184 | constexpr s16 DefaultAccelerometerScale{0x4000}; | ||
| 185 | constexpr s16 DefaultGyroScale{0x3be7}; | ||
| 186 | constexpr s16 DefaultOffset{0}; | ||
| 187 | |||
| 188 | for (auto& sensor : calibration.accelerometer) { | ||
| 189 | sensor.scale = ValidateValue(sensor.scale, DefaultAccelerometerScale); | ||
| 190 | sensor.offset = ValidateValue(sensor.offset, DefaultOffset); | ||
| 155 | } | 191 | } |
| 156 | if (calibration.x.min == 0xFFF || calibration.x.min == 0) { | 192 | for (auto& sensor : calibration.gyro) { |
| 157 | calibration.x.min = DefaultStickRange; | 193 | sensor.scale = ValidateValue(sensor.scale, DefaultGyroScale); |
| 194 | sensor.offset = ValidateValue(sensor.offset, DefaultOffset); | ||
| 158 | } | 195 | } |
| 196 | } | ||
| 159 | 197 | ||
| 160 | if (calibration.y.center == 0xFFF || calibration.y.center == 0) { | 198 | u16 CalibrationProtocol::ValidateValue(u16 value, u16 default_value) const { |
| 161 | calibration.y.center = DefaultStickCenter; | 199 | if (value == 0) { |
| 162 | } | 200 | return default_value; |
| 163 | if (calibration.y.max == 0xFFF || calibration.y.max == 0) { | ||
| 164 | calibration.y.max = DefaultStickRange; | ||
| 165 | } | 201 | } |
| 166 | if (calibration.y.min == 0xFFF || calibration.y.min == 0) { | 202 | if (value == 0xFFF) { |
| 167 | calibration.y.min = DefaultStickRange; | 203 | return default_value; |
| 168 | } | 204 | } |
| 205 | return value; | ||
| 169 | } | 206 | } |
| 170 | 207 | ||
| 171 | void CalibrationProtocol::ValidateCalibration(MotionCalibration& calibration) { | 208 | s16 CalibrationProtocol::ValidateValue(s16 value, s16 default_value) const { |
| 172 | for (auto& sensor : calibration.accelerometer) { | 209 | if (value == 0) { |
| 173 | if (sensor.scale == 0) { | 210 | return default_value; |
| 174 | sensor.scale = 0x4000; | ||
| 175 | } | ||
| 176 | } | 211 | } |
| 177 | for (auto& sensor : calibration.gyro) { | 212 | if (value == 0xFFF) { |
| 178 | if (sensor.scale == 0) { | 213 | return default_value; |
| 179 | sensor.scale = 0x3be7; | ||
| 180 | } | ||
| 181 | } | 214 | } |
| 215 | return value; | ||
| 182 | } | 216 | } |
| 183 | 217 | ||
| 184 | } // namespace InputCommon::Joycon | 218 | } // namespace InputCommon::Joycon |
diff --git a/src/input_common/helpers/joycon_protocol/calibration.h b/src/input_common/helpers/joycon_protocol/calibration.h index afb52a36a..c6fd0f729 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.h +++ b/src/input_common/helpers/joycon_protocol/calibration.h | |||
| @@ -53,9 +53,27 @@ public: | |||
| 53 | DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value); | 53 | DriverResult GetRingCalibration(RingCalibration& calibration, s16 current_value); |
| 54 | 54 | ||
| 55 | private: | 55 | private: |
| 56 | /// Returns true if the specified address corresponds to the magic value of user calibration | ||
| 57 | DriverResult HasUserCalibration(SpiAddress address, bool& has_user_calibration); | ||
| 58 | |||
| 59 | /// Converts a raw calibration block to an u16 value containing the x axis value | ||
| 60 | u16 GetXAxisCalibrationValue(std::span<u8> block) const; | ||
| 61 | |||
| 62 | /// Converts a raw calibration block to an u16 value containing the y axis value | ||
| 63 | u16 GetYAxisCalibrationValue(std::span<u8> block) const; | ||
| 64 | |||
| 65 | /// Ensures that all joystick calibration values are set | ||
| 56 | void ValidateCalibration(JoyStickCalibration& calibration); | 66 | void ValidateCalibration(JoyStickCalibration& calibration); |
| 67 | |||
| 68 | /// Ensures that all motion calibration values are set | ||
| 57 | void ValidateCalibration(MotionCalibration& calibration); | 69 | void ValidateCalibration(MotionCalibration& calibration); |
| 58 | 70 | ||
| 71 | /// Returns the default value if the value is either zero or 0xFFF | ||
| 72 | u16 ValidateValue(u16 value, u16 default_value) const; | ||
| 73 | |||
| 74 | /// Returns the default value if the value is either zero or 0xFFF | ||
| 75 | s16 ValidateValue(s16 value, s16 default_value) const; | ||
| 76 | |||
| 59 | s16 ring_data_max = 0; | 77 | s16 ring_data_max = 0; |
| 60 | s16 ring_data_default = 0; | 78 | s16 ring_data_default = 0; |
| 61 | s16 ring_data_min = 0; | 79 | s16 ring_data_min = 0; |
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index 417d0dcc5..0ef240344 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp | |||
| @@ -22,8 +22,8 @@ void JoyconCommonProtocol::SetNonBlocking() { | |||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { | 24 | DriverResult JoyconCommonProtocol::GetDeviceType(ControllerType& controller_type) { |
| 25 | std::vector<u8> buffer; | 25 | std::array<u8, 1> buffer{}; |
| 26 | const auto result = ReadSPI(CalAddr::DEVICE_TYPE, 1, buffer); | 26 | const auto result = ReadRawSPI(SpiAddress::DEVICE_TYPE, buffer); |
| 27 | controller_type = ControllerType::None; | 27 | controller_type = ControllerType::None; |
| 28 | 28 | ||
| 29 | if (result == DriverResult::Success) { | 29 | if (result == DriverResult::Success) { |
| @@ -148,11 +148,13 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe | |||
| 148 | return SendData(local_buffer); | 148 | return SendData(local_buffer); |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) { | 151 | DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span<u8> output) { |
| 152 | constexpr std::size_t HeaderSize = 20; | ||
| 152 | constexpr std::size_t MaxTries = 10; | 153 | constexpr std::size_t MaxTries = 10; |
| 154 | const auto size = output.size(); | ||
| 153 | std::size_t tries = 0; | 155 | std::size_t tries = 0; |
| 154 | std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, size}; | 156 | std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, static_cast<u8>(size)}; |
| 155 | std::vector<u8> local_buffer(size + 20); | 157 | std::vector<u8> local_buffer{}; |
| 156 | 158 | ||
| 157 | buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); | 159 | buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF); |
| 158 | buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8); | 160 | buffer[1] = static_cast<u8>((static_cast<u16>(addr) & 0xFF00) >> 8); |
| @@ -167,8 +169,12 @@ DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8 | |||
| 167 | } | 169 | } |
| 168 | } while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]); | 170 | } while (local_buffer[15] != buffer[0] || local_buffer[16] != buffer[1]); |
| 169 | 171 | ||
| 172 | if (local_buffer.size() < size + HeaderSize) { | ||
| 173 | return DriverResult::WrongReply; | ||
| 174 | } | ||
| 175 | |||
| 170 | // Remove header from output | 176 | // Remove header from output |
| 171 | output = std::vector<u8>(local_buffer.begin() + 20, local_buffer.begin() + 20 + size); | 177 | memcpy(output.data(), local_buffer.data() + HeaderSize, size); |
| 172 | return DriverResult::Success; | 178 | return DriverResult::Success; |
| 173 | } | 179 | } |
| 174 | 180 | ||
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h index 903bcf402..75d3f20a4 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.h +++ b/src/input_common/helpers/joycon_protocol/common_protocol.h | |||
| @@ -97,10 +97,29 @@ public: | |||
| 97 | /** | 97 | /** |
| 98 | * Reads the SPI memory stored on the joycon | 98 | * Reads the SPI memory stored on the joycon |
| 99 | * @param Initial address location | 99 | * @param Initial address location |
| 100 | * @param size in bytes to be read | ||
| 101 | * @returns output buffer containing the responce | 100 | * @returns output buffer containing the responce |
| 102 | */ | 101 | */ |
| 103 | DriverResult ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output); | 102 | DriverResult ReadRawSPI(SpiAddress addr, std::span<u8> output); |
| 103 | |||
| 104 | /** | ||
| 105 | * Reads the SPI memory stored on the joycon | ||
| 106 | * @param Initial address location | ||
| 107 | * @returns output object containing the responce | ||
| 108 | */ | ||
| 109 | template <typename Output> | ||
| 110 | requires std::is_trivially_copyable_v<Output> DriverResult ReadSPI(SpiAddress addr, | ||
| 111 | Output& output) { | ||
| 112 | std::array<u8, sizeof(Output)> buffer; | ||
| 113 | output = {}; | ||
| 114 | |||
| 115 | const auto result = ReadRawSPI(addr, buffer); | ||
| 116 | if (result != DriverResult::Success) { | ||
| 117 | return result; | ||
| 118 | } | ||
| 119 | |||
| 120 | std::memcpy(&output, buffer.data(), sizeof(Output)); | ||
| 121 | return DriverResult::Success; | ||
| 122 | } | ||
| 104 | 123 | ||
| 105 | /** | 124 | /** |
| 106 | * Enables MCU chip on the joycon | 125 | * Enables MCU chip on the joycon |
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp index 63cfb1369..484c208e6 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp +++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp | |||
| @@ -71,8 +71,8 @@ DriverResult GenericProtocol::GetBattery(u32& battery_level) { | |||
| 71 | 71 | ||
| 72 | DriverResult GenericProtocol::GetColor(Color& color) { | 72 | DriverResult GenericProtocol::GetColor(Color& color) { |
| 73 | ScopedSetBlocking sb(this); | 73 | ScopedSetBlocking sb(this); |
| 74 | std::vector<u8> buffer; | 74 | std::array<u8, 12> buffer{}; |
| 75 | const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer); | 75 | const auto result = ReadRawSPI(SpiAddress::COLOR_DATA, buffer); |
| 76 | 76 | ||
| 77 | color = {}; | 77 | color = {}; |
| 78 | if (result == DriverResult::Success) { | 78 | if (result == DriverResult::Success) { |
| @@ -87,8 +87,8 @@ DriverResult GenericProtocol::GetColor(Color& color) { | |||
| 87 | 87 | ||
| 88 | DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { | 88 | DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { |
| 89 | ScopedSetBlocking sb(this); | 89 | ScopedSetBlocking sb(this); |
| 90 | std::vector<u8> buffer; | 90 | std::array<u8, 16> buffer{}; |
| 91 | const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer); | 91 | const auto result = ReadRawSPI(SpiAddress::SERIAL_NUMBER, buffer); |
| 92 | 92 | ||
| 93 | serial_number = {}; | 93 | serial_number = {}; |
| 94 | if (result == DriverResult::Success) { | 94 | if (result == DriverResult::Success) { |
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index 182d2c15b..14b07bfb5 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h | |||
| @@ -159,13 +159,12 @@ enum class UsbSubCommand : u8 { | |||
| 159 | SEND_UART = 0x92, | 159 | SEND_UART = 0x92, |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | enum class CalMagic : u8 { | 162 | enum class CalibrationMagic : u8 { |
| 163 | USR_MAGIC_0 = 0xB2, | 163 | USR_MAGIC_0 = 0xB2, |
| 164 | USR_MAGIC_1 = 0xA1, | 164 | USR_MAGIC_1 = 0xA1, |
| 165 | USRR_MAGI_SIZE = 2, | ||
| 166 | }; | 165 | }; |
| 167 | 166 | ||
| 168 | enum class CalAddr { | 167 | enum class SpiAddress { |
| 169 | SERIAL_NUMBER = 0X6000, | 168 | SERIAL_NUMBER = 0X6000, |
| 170 | DEVICE_TYPE = 0X6012, | 169 | DEVICE_TYPE = 0X6012, |
| 171 | COLOR_EXIST = 0X601B, | 170 | COLOR_EXIST = 0X601B, |
| @@ -396,10 +395,35 @@ struct MotionData { | |||
| 396 | u64 delta_timestamp{}; | 395 | u64 delta_timestamp{}; |
| 397 | }; | 396 | }; |
| 398 | 397 | ||
| 398 | // Output from SPI read command containing user calibration magic | ||
| 399 | struct MagicSpiCalibration { | ||
| 400 | CalibrationMagic first; | ||
| 401 | CalibrationMagic second; | ||
| 402 | }; | ||
| 403 | static_assert(sizeof(MagicSpiCalibration) == 0x2, "MagicSpiCalibration is an invalid size"); | ||
| 404 | |||
| 405 | // Output from SPI read command containing left joystick calibration | ||
| 406 | struct JoystickLeftSpiCalibration { | ||
| 407 | std::array<u8, 3> max; | ||
| 408 | std::array<u8, 3> center; | ||
| 409 | std::array<u8, 3> min; | ||
| 410 | }; | ||
| 411 | static_assert(sizeof(JoystickLeftSpiCalibration) == 0x9, | ||
| 412 | "JoystickLeftSpiCalibration is an invalid size"); | ||
| 413 | |||
| 414 | // Output from SPI read command containing right joystick calibration | ||
| 415 | struct JoystickRightSpiCalibration { | ||
| 416 | std::array<u8, 3> center; | ||
| 417 | std::array<u8, 3> min; | ||
| 418 | std::array<u8, 3> max; | ||
| 419 | }; | ||
| 420 | static_assert(sizeof(JoystickRightSpiCalibration) == 0x9, | ||
| 421 | "JoystickRightSpiCalibration is an invalid size"); | ||
| 422 | |||
| 399 | struct JoyStickAxisCalibration { | 423 | struct JoyStickAxisCalibration { |
| 400 | u16 max{1}; | 424 | u16 max; |
| 401 | u16 min{1}; | 425 | u16 min; |
| 402 | u16 center{0}; | 426 | u16 center; |
| 403 | }; | 427 | }; |
| 404 | 428 | ||
| 405 | struct JoyStickCalibration { | 429 | struct JoyStickCalibration { |
| @@ -407,6 +431,14 @@ struct JoyStickCalibration { | |||
| 407 | JoyStickAxisCalibration y; | 431 | JoyStickAxisCalibration y; |
| 408 | }; | 432 | }; |
| 409 | 433 | ||
| 434 | struct ImuSpiCalibration { | ||
| 435 | std::array<s16, 3> accelerometer_offset; | ||
| 436 | std::array<s16, 3> accelerometer_scale; | ||
| 437 | std::array<s16, 3> gyroscope_offset; | ||
| 438 | std::array<s16, 3> gyroscope_scale; | ||
| 439 | }; | ||
| 440 | static_assert(sizeof(ImuSpiCalibration) == 0x18, "ImuSpiCalibration is an invalid size"); | ||
| 441 | |||
| 410 | struct RingCalibration { | 442 | struct RingCalibration { |
| 411 | s16 default_value; | 443 | s16 default_value; |
| 412 | s16 max_value; | 444 | s16 max_value; |
| @@ -488,14 +520,6 @@ struct InputReportNfcIr { | |||
| 488 | static_assert(sizeof(InputReportNfcIr) == 0x29, "InputReportNfcIr is an invalid size"); | 520 | static_assert(sizeof(InputReportNfcIr) == 0x29, "InputReportNfcIr is an invalid size"); |
| 489 | #pragma pack(pop) | 521 | #pragma pack(pop) |
| 490 | 522 | ||
| 491 | struct IMUCalibration { | ||
| 492 | std::array<s16, 3> accelerometer_offset; | ||
| 493 | std::array<s16, 3> accelerometer_scale; | ||
| 494 | std::array<s16, 3> gyroscope_offset; | ||
| 495 | std::array<s16, 3> gyroscope_scale; | ||
| 496 | }; | ||
| 497 | static_assert(sizeof(IMUCalibration) == 0x18, "IMUCalibration is an invalid size"); | ||
| 498 | |||
| 499 | struct NFCReadBlock { | 523 | struct NFCReadBlock { |
| 500 | u8 start; | 524 | u8 start; |
| 501 | u8 end; | 525 | u8 end; |