Difference between revisions of "Joy-Con"
Tags: Undo Replaced |
|||
(38 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
− | Joy-Con is the name for the Switch's primary game controllers. The | + | Joy-Con is the name for the Switch's primary game controllers. The Joy-Con are internally called Sakyo (Left) and Ukyo (Right). |
− | == | + | = Hardware = |
− | + | == Sakyo == | |
− | |||
− | |||
{| class="wikitable" | {| class="wikitable" | ||
− | ! | + | ! Component || Description |
|- | |- | ||
− | | | + | | SoC || Broadcom BCM20734 |
|- | |- | ||
− | | | + | | IMU || STMicroelectronics LSM6DS3H |
|- | |- | ||
− | | | + | | PMIC || Texas Instruments BQ24072 |
+ | |- | ||
+ | | Storage || Macronix International MX25U4033E 4 Mb CMOS Flash | ||
+ | |} | ||
+ | |||
+ | == Ukyo == | ||
+ | {| class="wikitable" | ||
+ | ! Component || Description | ||
+ | |- | ||
+ | | SoC || Broadcom BCM20734 | ||
+ | |- | ||
+ | | MCU || STMicroelectronics STM32P411 | ||
+ | |- | ||
+ | | NFC || STMicroelectronics ST21NFCB | ||
+ | |- | ||
+ | | IMU || STMicroelectronics LSM6DS3H | ||
+ | |- | ||
+ | | PMIC || Texas Instruments BQ24072 | ||
+ | |- | ||
+ | | Storage || Macronix International MX25U4033E 4 Mb CMOS Flash | ||
+ | |} | ||
+ | |||
+ | = Protocol = | ||
+ | The Joy-Con can communicate wirelessly over Bluetooth or through the rails over UART. The latter uses a Nintendo proprietary protocol called "Nwcp". | ||
+ | |||
+ | == NwcpPacket == | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x5 | ||
+ | | [[#HciHeader|HciHeader]] | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x7 | ||
+ | | [[#NwcpHeader|NwcpHeader]] | ||
+ | |- | ||
+ | | 0xC | ||
+ | | Variable | ||
+ | | Data | ||
+ | |} | ||
+ | |||
+ | === HciHeader === | ||
+ | This is a 5-byte packet header used by Broadcom's HCI Control Protocol. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | PacketType (always 0x19) | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | [[#CommandCode|CommandCode]] | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x1 | ||
+ | | GroupCode (always 0x03) | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x2 | ||
+ | | PacketLength | ||
+ | |} | ||
+ | |||
+ | ==== CommandCode ==== | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Value | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x1 || SendToDevice | ||
+ | |- | ||
+ | | 0x81 || ReceiveFromDevice | ||
+ | |} | ||
+ | |||
+ | === NwcpHeader === | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#CommandType|CommandType]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | [[#DeviceCommand|DeviceCommand]] | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x2 | ||
+ | | DataSize | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x1 | ||
+ | | CommandResult | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x1 | ||
+ | | DataCrc (CRC8 over Data for DataSize bytes) | ||
+ | |- | ||
+ | | 0x6 | ||
+ | | 0x1 | ||
+ | | HeaderCrc (CRC8 over the previous 6 bytes) | ||
+ | |} | ||
+ | |||
+ | ==== CommandType ==== | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Value | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x43 || ReportOut | ||
+ | |- | ||
+ | | 0x53 || ReportIn | ||
+ | |- | ||
+ | | 0x91 || DeviceCommandIn | ||
+ | |- | ||
+ | | 0x92 || Hid | ||
+ | |- | ||
+ | | 0x93 || | ||
+ | |- | ||
+ | | 0x94 || DeviceCommandOut | ||
+ | |- | ||
+ | | 0x95 || | ||
+ | |- | ||
+ | | 0x9A || Fifty | ||
+ | |- | ||
+ | | 0xA3 || ReportComplete | ||
+ | |- | ||
+ | | 0xA5 || Handshake | ||
+ | |} | ||
+ | |||
+ | == HidCommandInputReport == | ||
+ | This is a 0x31-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | LatencyTimer | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x1 | ||
+ | | PowerInfo | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x1 | ||
+ | | RightPadButtonStatus | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x1 | ||
+ | | SharedButtonStatus | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x1 | ||
+ | | LeftPadButtonStatus | ||
+ | |- | ||
+ | | 0x6 | ||
+ | | 0x3 | ||
+ | | LeftAnalogStickData | ||
+ | |- | ||
+ | | 0x9 | ||
+ | | 0x3 | ||
+ | | RightAnalogStickData | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x1 | ||
+ | | MotorStatus | ||
+ | |- | ||
+ | | 0xD | ||
+ | | 0x1 | ||
+ | | CommandAck | ||
+ | |- | ||
+ | | 0xE | ||
+ | | 0x1 | ||
+ | | [[#HidCommand|CommandId]] | ||
+ | |- | ||
+ | | 0xF | ||
+ | | 0x22 | ||
+ | | CommandReply | ||
+ | |} | ||
+ | |||
+ | == HidMcuUpdateInputReport == | ||
+ | This is a 0x30-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | LatencyTimer | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x1 | ||
+ | | PowerInfo | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x1 | ||
+ | | RightPadButtonStatus | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x1 | ||
+ | | SharedButtonStatus | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x1 | ||
+ | | LeftPadButtonStatus | ||
+ | |- | ||
+ | | 0x6 | ||
+ | | 0x3 | ||
+ | | LeftAnalogStickData | ||
+ | |- | ||
+ | | 0x9 | ||
+ | | 0x3 | ||
+ | | RightAnalogStickData | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x1 | ||
+ | | MotorStatus | ||
+ | |- | ||
+ | | 0xD | ||
+ | | 0x23 | ||
+ | | McuUpdateData | ||
+ | |} | ||
+ | |||
+ | == HidBasicInputReport == | ||
+ | This is a 0x31-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | LatencyTimer | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x1 | ||
+ | | PowerInfo | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x1 | ||
+ | | RightPadButtonStatus | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x1 | ||
+ | | SharedButtonStatus | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x1 | ||
+ | | LeftPadButtonStatus | ||
+ | |- | ||
+ | | 0x6 | ||
+ | | 0x3 | ||
+ | | LeftAnalogStickData | ||
+ | |- | ||
+ | | 0x9 | ||
+ | | 0x3 | ||
+ | | RightAnalogStickData | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x1 | ||
+ | | MotorStatus | ||
+ | |- | ||
+ | | 0xD | ||
+ | | 0x24 | ||
+ | | BasicData | ||
+ | |} | ||
+ | |||
+ | == HidMcuInputReport == | ||
+ | This is a 0x16A-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | LatencyTimer | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x1 | ||
+ | | PowerInfo | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x1 | ||
+ | | RightPadButtonStatus | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x1 | ||
+ | | SharedButtonStatus | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x1 | ||
+ | | LeftPadButtonStatus | ||
+ | |- | ||
+ | | 0x6 | ||
+ | | 0x3 | ||
+ | | LeftAnalogStickData | ||
+ | |- | ||
+ | | 0x9 | ||
+ | | 0x3 | ||
+ | | RightAnalogStickData | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x1 | ||
+ | | MotorStatus | ||
+ | |- | ||
+ | | 0xD | ||
+ | | 0x6 | ||
+ | | SensorAccelSample0 | ||
+ | |- | ||
+ | | 0x13 | ||
+ | | 0x6 | ||
+ | | SensorGyroSample0 | ||
+ | |- | ||
+ | | 0x19 | ||
+ | | 0x6 | ||
+ | | SensorAccelSample1 | ||
+ | |- | ||
+ | | 0x1F | ||
+ | | 0x6 | ||
+ | | SensorGyroSample1 | ||
+ | |- | ||
+ | | 0x25 | ||
+ | | 0x6 | ||
+ | | SensorAccelSample2 | ||
+ | |- | ||
+ | | 0x2B | ||
+ | | 0x6 | ||
+ | | SensorGyroSample2 | ||
+ | |- | ||
+ | | 0x31 | ||
+ | | 0x139 | ||
+ | | McuData | ||
+ | |} | ||
+ | |||
+ | == HidAttachmentInputReport == | ||
+ | This is a 0x16A-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | LatencyTimer | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x1 | ||
+ | | PowerInfo | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x1 | ||
+ | | RightPadButtonStatus | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x1 | ||
+ | | SharedButtonStatus | ||
+ | |- | ||
+ | | 0x5 | ||
+ | | 0x1 | ||
+ | | LeftPadButtonStatus | ||
+ | |- | ||
+ | | 0x6 | ||
+ | | 0x3 | ||
+ | | LeftAnalogStickData | ||
+ | |- | ||
+ | | 0x9 | ||
+ | | 0x3 | ||
+ | | RightAnalogStickData | ||
+ | |- | ||
+ | | 0xC | ||
+ | | 0x1 | ||
+ | | MotorStatus | ||
+ | |- | ||
+ | | 0xD | ||
+ | | 0x6 | ||
+ | | SensorAccelSample0 | ||
+ | |- | ||
+ | | 0x13 | ||
+ | | 0x6 | ||
+ | | SensorGyroSample0 | ||
+ | |- | ||
+ | | 0x19 | ||
+ | | 0x6 | ||
+ | | SensorAccelSample1 | ||
+ | |- | ||
+ | | 0x1F | ||
+ | | 0x6 | ||
+ | | SensorGyroSample1 | ||
+ | |- | ||
+ | | 0x25 | ||
+ | | 0x6 | ||
+ | | SensorAccelSample2 | ||
+ | |- | ||
+ | | 0x2B | ||
+ | | 0x6 | ||
+ | | SensorGyroSample2 | ||
+ | |- | ||
+ | | 0x31 | ||
+ | | 0x139 | ||
+ | | AttachmentData | ||
+ | |} | ||
+ | |||
+ | == HidGenericInputReport == | ||
+ | This is a 0xC-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x2 | ||
+ | | ButtonStatus | ||
+ | |- | ||
+ | | 0x3 | ||
+ | | 0x1 | ||
+ | | StickHatData | ||
+ | |- | ||
+ | | 0x4 | ||
+ | | 0x4 | ||
+ | | LeftAnalogStickData | ||
+ | |- | ||
+ | | 0x8 | ||
+ | | 0x4 | ||
+ | | RightAnalogStickData | ||
+ | |} | ||
+ | |||
+ | == HidCommandOutputReport == | ||
+ | This is a 0x31-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | PacketNumber | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x8 | ||
+ | | [[#HidMotorData|MotorData]] | ||
+ | |- | ||
+ | | 0xA | ||
+ | | 0x1 | ||
+ | | [[#HidCommand|CommandId]] | ||
+ | |- | ||
+ | | 0xB | ||
+ | | 0x26 | ||
+ | | CommandData | ||
+ | |} | ||
+ | |||
+ | == HidMcuUpdateOutputReport == | ||
+ | This is a 0x13E-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | PacketNumber | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x8 | ||
+ | | [[#HidMotorData|MotorData]] | ||
+ | |- | ||
+ | | 0xA | ||
+ | | 0x134 | ||
+ | | McuUpdateData | ||
+ | |} | ||
+ | |||
+ | == HidBasicOutputReport == | ||
+ | This is a 0xA-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | PacketNumber | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x8 | ||
+ | | [[#HidMotorData|MotorData]] | ||
+ | |} | ||
+ | |||
+ | == HidMcuOutputReport == | ||
+ | This is a 0x30-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | PacketNumber | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x8 | ||
+ | | [[#HidMotorData|MotorData]] | ||
+ | |- | ||
+ | | 0xA | ||
+ | | 0x26 | ||
+ | | McuData | ||
+ | |} | ||
+ | |||
+ | == HidAttachmentOutputReport == | ||
+ | This is a 0x30-byte struct. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 | ||
+ | | 0x1 | ||
+ | | [[#HidReportId|ReportId]] | ||
+ | |- | ||
+ | | 0x1 | ||
+ | | 0x1 | ||
+ | | PacketNumber | ||
+ | |- | ||
+ | | 0x2 | ||
+ | | 0x8 | ||
+ | | [[#HidMotorData|MotorData]] | ||
+ | |- | ||
+ | | 0xA | ||
+ | | 0x26 | ||
+ | | AttachmentData | ||
+ | |} | ||
+ | |||
+ | == HidReportId == | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Value | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x01 || CommandOutputReport | ||
+ | |- | ||
+ | | 0x03 || McuUpdateOutputReport | ||
+ | |- | ||
+ | | 0x10 || BasicOutputReport | ||
+ | |- | ||
+ | | 0x11 || McuOutputReport | ||
+ | |- | ||
+ | | 0x12 || AttachmentOutputReport | ||
+ | |- | ||
+ | | 0x21 || CommandInputReport | ||
+ | |- | ||
+ | | 0x23 || McuUpdateInputReport | ||
+ | |- | ||
+ | | 0x30 || BasicInputReport | ||
+ | |- | ||
+ | | 0x31 || McuInputReport | ||
+ | |- | ||
+ | | 0x32 || AttachmentInputReport | ||
+ | |- | ||
+ | | 0x33 || | ||
+ | |- | ||
+ | | 0x3F || GenericInputReport | ||
+ | |- | ||
+ | | 0x70 || OtaEnableFwuReport | ||
+ | |- | ||
+ | | 0x71 || OtaSetupReadReport | ||
+ | |- | ||
+ | | 0x72 || OtaReadReport | ||
+ | |- | ||
+ | | 0x73 || OtaWriteReport | ||
+ | |- | ||
+ | | 0x74 || OtaEraseReport | ||
+ | |- | ||
+ | | 0x75 || OtaLaunchReport | ||
+ | |- | ||
+ | | 0x80 || ExtGripOutputReport | ||
+ | |- | ||
+ | | 0x81 || ExtGripInputReport | ||
+ | |- | ||
+ | | 0x82 || | ||
+ | |} | ||
+ | |||
+ | == HidMotorData == | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x4 || [[#VibrationAmFmPackTag|JoyLeftVibrationAmFmPackTag]] | ||
+ | |- | ||
+ | | 0x4 || 0x8 || [[#VibrationAmFmPackTag|JoyRightVibrationAmFmPackTag]] | ||
+ | |} | ||
+ | |||
+ | == VibrationAmFmPackTag == | ||
+ | This is "nn::xcd::VibrationAmFmPackTag". This is a BitPack object. | ||
+ | |||
+ | === VibrationAmFmPackFormatZero === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0-29 || Reserved | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 0) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatOne === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0-19 || Reserved | ||
+ | |- | ||
+ | | 20-24 || ChannelCodesHigh | ||
+ | |- | ||
+ | | 25-29 || ChannelCodesLow | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 1) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatOne28bit === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0-1 || Reserved | ||
+ | |- | ||
+ | | 2-8 || ChannelFrequencyHigh | ||
+ | |- | ||
+ | | 9-15 || ChannelAmplitudeHigh | ||
+ | |- | ||
+ | | 16-22 || ChannelFrequencyLow | ||
+ | |- | ||
+ | | 23-29 || ChannelAmplitudeLow | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 1) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatTwo === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0-9 || Reserved | ||
+ | |- | ||
+ | | 10-14 || VibrationCodesHigh | ||
+ | |- | ||
+ | | 15-19 || VibrationCodesLow | ||
+ | |- | ||
+ | | 20-24 || ChannelCodesHigh | ||
+ | |- | ||
+ | | 25-29 || ChannelCodesLow | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 2) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatTwo14bitLow === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0 || IsChannelHigh (must be 0) | ||
+ | |- | ||
+ | | 1-7 || ChannelFrequency | ||
+ | |- | ||
+ | | 8-12 || VibrationCodesHigh1 | ||
+ | |- | ||
+ | | 13-17 || VibrationCodesLow1 | ||
+ | |- | ||
+ | | 18-22 || VibrationCodesHigh0 | ||
+ | |- | ||
+ | | 23-29 || ChannelAmplitude | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 2) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatTwo14bitHigh === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0 || IsChannelHigh (must be 1) | ||
+ | |- | ||
+ | | 1-7 || ChannelFrequency | ||
+ | |- | ||
+ | | 8-12 || VibrationCodesHigh1 | ||
+ | |- | ||
+ | | 13-17 || VibrationCodesLow1 | ||
+ | |- | ||
+ | | 18-22 || VibrationCodesLow0 | ||
+ | |- | ||
+ | | 23-29 || ChannelAmplitude | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 2) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatThree === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0-4 || VibrationCodesHigh1 | ||
+ | |- | ||
+ | | 5-9 || VibrationCodesLow1 | ||
+ | |- | ||
+ | | 10-14 || VibrationCodesHigh0 | ||
+ | |- | ||
+ | | 15-19 || VibrationCodesLow0 | ||
+ | |- | ||
+ | | 20-24 || ChannelCodesHigh | ||
+ | |- | ||
+ | | 25-29 || ChannelCodesLow | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 3) | ||
+ | |} | ||
+ | |||
+ | === VibrationAmFmPackFormatThree7bit === | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Bits | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0 || IsChannelHigh | ||
+ | |- | ||
+ | | 1 || IsThree7bit (must be 1) | ||
+ | |- | ||
+ | | 2 || IsFm | ||
+ | |- | ||
+ | | 3-7 || VibrationCodesHigh1 | ||
+ | |- | ||
+ | | 8-12 || VibrationCodesLow1 | ||
+ | |- | ||
+ | | 13-17 || VibrationCodesHigh0 | ||
+ | |- | ||
+ | | 18-22 || VibrationCodesLow0 | ||
+ | |- | ||
+ | | 23-29 || ChannelAmFm | ||
+ | |- | ||
+ | | 30-31 || PackFormat (must be 1, instead of 3) | ||
+ | |} | ||
+ | |||
+ | == AmFmCodes == | ||
+ | These are 32-bit values used by the Joy-Con firmware to represent combinations of amplitude/frequency pairs for vibration. | ||
+ | |||
+ | === Unpacking === | ||
+ | The Joy-Con firmware receives vibration data packed as [[#VibrationAmFmPackTag|VibrationAmFmPackTag]] from output reports. Depending on the packing format, these tags are then converted to an array of AmFmCodes as follows. | ||
+ | |||
+ | ==== AmFm5BitCodes ==== | ||
+ | Converted from [[#VibrationAmFmPackFormatOne|VibrationAmFmPackFormatOne]], [[#VibrationAmFmPackFormatTwo|VibrationAmFmPackFormatTwo]] or [[#VibrationAmFmPackFormatThree|VibrationAmFmPackFormatThree]]. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x4 || <nowiki>(ChannelCodesLow & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0x4 || 0x4 || <nowiki>(ChannelCodesHigh & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0x8 || 0x4 || <nowiki>(VibrationCodesLow0 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0xC || 0x4 || <nowiki>(VibrationCodesHigh0 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0x10 || 0x4 || <nowiki>(VibrationCodesLow1 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0x14 || 0x4 || <nowiki>(VibrationCodesHigh1 & 0x1F)</nowiki> | ||
+ | |} | ||
+ | |||
+ | ==== AmFm7BitOneCodes ==== | ||
+ | Converted from [[#VibrationAmFmPackFormatOne28bit|VibrationAmFmPackFormatOne28bit]]. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x4 || <nowiki>(((ChannelFrequencyLow & 0x7F) << 8) | (ChannelAmplitudeLow & 0x7F) | 0x8080)</nowiki> | ||
+ | |- | ||
+ | | 0x4 || 0x4 || <nowiki>(((ChannelFrequencyHigh & 0x7F) << 8) | (ChannelAmplitudeHigh & 0x7F) | 0x8080)</nowiki> | ||
+ | |} | ||
+ | |||
+ | ==== AmFm7BitTwoCodes ==== | ||
+ | Converted from [[#VibrationAmFmPackFormatTwo14bitLow|VibrationAmFmPackFormatTwo14bitLow]] or [[#VibrationAmFmPackFormatTwo14bitHigh|VibrationAmFmPackFormatTwo14bitHigh]]. | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x4 || <nowiki>IsChannelHigh ? (VibrationCodesLow0 & 0x1F) : (((ChannelFrequency & 0x7F) << 8) | (ChannelAmplitude & 0x7F) | 0x8080)</nowiki> | ||
+ | |- | ||
+ | | 0x4 || 0x4 || <nowiki>IsChannelHigh ? (((ChannelFrequency & 0x7F) << 8) | (ChannelAmplitude & 0x7F) | 0x8080) : (VibrationCodesHigh0 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0x8 || 0x4 || <nowiki>(VibrationCodesLow1 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0xC || 0x4 || <nowiki>(VibrationCodesHigh1 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0x10 || 0x4 || <nowiki>Always 0x18</nowiki> | ||
+ | |- | ||
+ | | 0x14 || 0x4 || <nowiki>Always 0x18</nowiki> | ||
|} | |} | ||
− | == | + | ==== AmFm7BitThreeCodes ==== |
− | + | Converted from [[#VibrationAmFmPackFormatThree7bit|VibrationAmFmPackFormatThree7bit]]. | |
− | + | {| class="wikitable" border="1" | |
− | {| class="wikitable" | + | |- |
− | ! | + | ! Offset |
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x4 || <nowiki>IsChannelHigh ? 0x18 : (IsFm ? (((ChannelAmFm & 0x7F) << 8) | 0x8000) : ((ChannelAmFm & 0x7F) | 0x80))</nowiki> | ||
+ | |- | ||
+ | | 0x4 || 0x4 || <nowiki>IsChannelHigh ? (IsFm ? (((ChannelAmFm & 0x7F) << 8) | 0x8000) : ((ChannelAmFm & 0x7F) | 0x80)) : 0x18</nowiki> | ||
+ | |- | ||
+ | | 0x8 || 0x4 || <nowiki>(VibrationCodesLow0 & 0x1F)</nowiki> | ||
+ | |- | ||
+ | | 0xC || 0x4 || <nowiki>(VibrationCodesHigh0 & 0x1F)</nowiki> | ||
|- | |- | ||
− | | | + | | 0x10 || 0x4 || <nowiki>(VibrationCodesLow1 & 0x1F)</nowiki> |
|- | |- | ||
− | | | + | | 0x14 || 0x4 || <nowiki>(VibrationCodesHigh1 & 0x1F)</nowiki> |
|} | |} | ||
− | |||
− | |||
− | == | + | == DeviceCommand == |
− | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
+ | ! Value | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x01 || Inquiry | ||
|- | |- | ||
− | + | | 0x02 || WriteChargerSettings | |
|- | |- | ||
− | | | + | | 0x03 || ReadChargerSettings |
+ | |- | ||
+ | | 0x04 || AttachmentEnable | ||
+ | |- | ||
+ | | 0x05 || IsAttachmentEnabled | ||
+ | |- | ||
+ | | 0x06 || GetBatteryVoltage | ||
+ | |- | ||
+ | | 0x07 || ReadWakeUpReason | ||
+ | |- | ||
+ | | 0x10 || CreateHidConnection | ||
+ | |- | ||
+ | | 0x11 || DisconnectHid | ||
+ | |- | ||
+ | | 0x12 || SetHidInterval | ||
+ | |- | ||
+ | | 0x13 || GetHidInterval | ||
+ | |- | ||
+ | | 0x18 || Pairing | ||
+ | |- | ||
+ | | 0x20 || UpdateUartBaudRate | ||
+ | |- | ||
+ | | 0x40 || Test | ||
+ | |} | ||
+ | |||
+ | == HidCommand == | ||
+ | {| class="wikitable" border="1" | ||
+ | ! Value | ||
+ | ! Description | ||
|- | |- | ||
| 0x01 || PairingOut | | 0x01 || PairingOut | ||
Line 64: | Line 974: | ||
|- | |- | ||
| 0x22 || McuResume | | 0x22 || McuResume | ||
− | |||
− | |||
|- | |- | ||
| 0x24 || McuPollingEnable | | 0x24 || McuPollingEnable | ||
Line 73: | Line 981: | ||
| 0x28 || AttachmentWrite | | 0x28 || AttachmentWrite | ||
|- | |- | ||
− | | 0x29 || | + | | 0x29 || AttachmentRead |
|- | |- | ||
| 0x2A || AttachmentEnable | | 0x2A || AttachmentEnable | ||
|- | |- | ||
− | | 0x2B || | + | | 0x2B || GetAttachmentInfo |
|- | |- | ||
| 0x30 || SetIndicatorLed | | 0x30 || SetIndicatorLed | ||
Line 99: | Line 1,007: | ||
| 0x51 || WriteChargeSetting | | 0x51 || WriteChargeSetting | ||
|- | |- | ||
− | | 0x52 || | + | | 0x52 || ReadChargeSetting |
|- | |- | ||
| 0x58 || ExtDevWrite | | 0x58 || ExtDevWrite | ||
Line 110: | Line 1,018: | ||
|- | |- | ||
| 0x5C || ExtDevInFormatConfig | | 0x5C || ExtDevInFormatConfig | ||
+ | |- | ||
+ | | 0x5D || | ||
|- | |- | ||
| 0x60 || InternalAttachmentWrite | | 0x60 || InternalAttachmentWrite | ||
Line 120: | Line 1,030: | ||
|- | |- | ||
| 0x64 || InternalAttachmentPollingDisable | | 0x64 || InternalAttachmentPollingDisable | ||
+ | |- | ||
+ | | 0x7A || AddButtonPlayData | ||
+ | |- | ||
+ | | 0x7B || StartStopButtonPlayData | ||
|- | |- | ||
| 0x80 || Ack | | 0x80 || Ack | ||
Line 134: | Line 1,048: | ||
|- | |- | ||
| 0xA8 || AttachmentData | | 0xA8 || AttachmentData | ||
+ | |- | ||
+ | | 0xA9 || AttachmentInfo | ||
|- | |- | ||
| 0xAA || InternalAttachmentRead | | 0xAA || InternalAttachmentRead | ||
Line 148: | Line 1,064: | ||
|} | |} | ||
− | === | + | == ExtGripCommand == |
− | + | {| class="wikitable" border="1" | |
+ | ! Value | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x01 || Inquiry | ||
+ | |- | ||
+ | | 0x02 || CreateHidConnection | ||
+ | |- | ||
+ | | 0x03 || DeleteHidConnection | ||
+ | |- | ||
+ | | 0x04 || StartHidData | ||
+ | |- | ||
+ | | 0x05 || StopHidData | ||
+ | |- | ||
+ | | 0x06 || | ||
+ | |- | ||
+ | | 0x07 || GetFirmwareVersion | ||
+ | |- | ||
+ | | 0x08 || | ||
+ | |- | ||
+ | | 0x91 || LoopbackTest | ||
+ | |- | ||
+ | | 0x92 || | ||
+ | |- | ||
+ | | 0xA0 || SetUartClockTrim | ||
+ | |} | ||
+ | |||
+ | = Firmware = | ||
+ | The firmware is stored inside the flash in Broadcom's PatchRAM format as follows: | ||
+ | |||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x1000 || StaticSection | ||
+ | |- | ||
+ | | 0x1000 || 0x1000 || [[#FailsafeSection|FailsafeSection]] | ||
+ | |- | ||
+ | | 0x2000 || 0x1000 || [[#VolatileSection|VolatileSection]] | ||
+ | |- | ||
+ | | 0x3000 || 0x1000 || VolatileSectionBackup1 | ||
+ | |- | ||
+ | | 0x4000 || 0x1000 || VolatileSectionBackup2 | ||
+ | |- | ||
+ | | 0x5000 || 0x1000 || [[#ShipmentInfo|ShipmentInfo]] | ||
+ | |- | ||
+ | | 0x6000 || 0x1000 || [[#FactoryConfiguration|FactoryConfiguration]] | ||
+ | |- | ||
+ | | 0x7000 || 0x1000 || Reserved | ||
+ | |- | ||
+ | | 0x8000 || 0x1000 || [[#UserCalibration|UserCalibration]] | ||
+ | |- | ||
+ | | 0x9000 || 0x7000 || Reserved | ||
+ | |- | ||
+ | | 0x10000 || 0x18000 || DynamicSection1 | ||
+ | |- | ||
+ | | 0x28000 || 0x18000 || DynamicSection2 | ||
+ | |- | ||
+ | | 0x40000 || 0x40000 || Reserved | ||
+ | |} | ||
+ | |||
+ | == FailsafeSection == | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0xFF4 || Reserved | ||
+ | |- | ||
+ | | 0xFF4 || 0x8 || Signature | ||
+ | |- | ||
+ | | 0xFFC || 0x4 || Ds2Offset | ||
+ | |} | ||
− | + | == VolatileSection == | |
− | + | {| class="wikitable" border="1" | |
− | + | |- | |
− | + | ! Offset | |
− | + | ! Size | |
− | + | ! Description | |
− | + | |- | |
− | + | | 0x0 || 0x26 || | |
− | + | |- | |
− | + | | 0x26 || 0xFDA || Reserved | |
− | + | |} | |
− | |||
− | |||
− | |||
− | {| class="wikitable" | + | == ShipmentInfo == |
− | ! | + | {| class="wikitable" border="1" |
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x1 || Shipment | ||
+ | |- | ||
+ | | 0x1 || 0xFFF || Reserved | ||
+ | |} | ||
+ | |||
+ | == FactoryConfiguration == | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x10 || IdentificationCode | ||
+ | |- | ||
+ | | 0x10 || 0x2 || Reserved | ||
+ | |- | ||
+ | | 0x12 || 0x1 || [[#DeviceType|DeviceType]] | ||
+ | |- | ||
+ | | 0x13 || 0x1 || BoardRevision | ||
+ | |- | ||
+ | | 0x14 || 0x7 || Reserved | ||
+ | |- | ||
+ | | 0x1B || 0x1 || FormatVersion | ||
+ | |- | ||
+ | | 0x1C || 0x4 || Reserved | ||
+ | |- | ||
+ | | 0x20 || 0x18 || [[#Cal1|Cal1]] | ||
+ | |- | ||
+ | | 0x38 || 0x5 || Reserved | ||
+ | |- | ||
+ | | 0x3D || 0x12 || [[#Cal2|Cal2]] | ||
+ | |- | ||
+ | | 0x4F || 0x1 || Reserved | ||
+ | |- | ||
+ | | 0x50 || 0xD || [[#Design|Design]] | ||
+ | |- | ||
+ | | 0x5D || 0x23 || Reserved | ||
+ | |- | ||
+ | | 0x80 || 0x18 || [[#Model1|Model1]] | ||
+ | |- | ||
+ | | 0x98 || 0x12 || [[#Model2|Model2]] | ||
+ | |- | ||
+ | | 0xAA || 0x1 || Reserved | ||
+ | |- | ||
+ | | 0xAB || 0x1 || AccelerometerAxisAssignment | ||
+ | |- | ||
+ | | 0xAC || 0x1 || GyroscopeAxisAssignment | ||
+ | |- | ||
+ | | 0xAD || 0x1 || AnalogStickMainAxisAssignment | ||
+ | |- | ||
+ | | 0xAE || 0x1 || AnalogStickSubAxisAssignment | ||
+ | |- | ||
+ | | 0xAF || 0x151 || Reserved | ||
+ | |- | ||
+ | | 0x200 || 0x2 || BatteryVoltage | ||
+ | |- | ||
+ | | 0x202 || 0xB7E || Reserved | ||
+ | |- | ||
+ | | 0xD80 || 0x2 || TarragonVid | ||
+ | |- | ||
+ | | 0xD82 || 0x2 || TarragonPid | ||
+ | |- | ||
+ | | 0xD84 || 0x7C || Reserved | ||
+ | |- | ||
+ | | 0xE00 || 0x100 || InspectionLog | ||
+ | |- | ||
+ | | 0xF00 || 0x100 || Reserved | ||
+ | |} | ||
+ | |||
+ | === DeviceType === | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Value | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x01 || JoyConLeft | ||
+ | |- | ||
+ | | 0x02 || JoyConRight | ||
+ | |- | ||
+ | | 0x03 || SwitchProController | ||
+ | |- | ||
+ | | 0x04 || MiyabiLeft | ||
+ | |- | ||
+ | | 0x05 || MiyabiRight | ||
+ | |- | ||
+ | | 0x06 || Tarragon | ||
+ | |- | ||
+ | | 0x07 || LarkH1 | ||
+ | |- | ||
+ | | 0x08 || LarkH2 | ||
+ | |- | ||
+ | | 0x09 || LarkNL | ||
+ | |- | ||
+ | | 0x0A || LarkNR | ||
+ | |- | ||
+ | | 0x0B || Lucia | ||
+ | |- | ||
+ | | 0x0C || [12.0.0+] Lagon | ||
|- | |- | ||
− | | | + | | 0x0D || [13.0.0+] Lager |
|- | |- | ||
− | | | + | | 0x0E || [14.0.0+] Tarragon2 |
|- | |- | ||
− | | | + | | 0x21 || FiftyL |
|- | |- | ||
− | | | + | | 0x22 || FiftyR |
+ | |} | ||
+ | |||
+ | === Cal1 === | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x18 || [[#SixAxisSensorCalibrationValue|SixAxisSensorCalibrationValue]] |
+ | |} | ||
+ | |||
+ | ==== SixAxisSensorCalibrationValue ==== | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x2 || Accelerometer0OffsetX |
|- | |- | ||
− | | | + | | 0x2 || 0x2 || Accelerometer0OffsetY |
|- | |- | ||
− | | | + | | 0x4 || 0x2 || Accelerometer0OffsetZ |
|- | |- | ||
− | | | + | | 0x6 || 0x2 || Accelerometer1gScaleX |
|- | |- | ||
− | | | + | | 0x8 || 0x2 || Accelerometer1gScaleY |
|- | |- | ||
− | | | + | | 0xA || 0x2 || Accelerometer1gScaleZ |
|- | |- | ||
− | | | + | | 0xC || 0x2 || Gyroscope0OffsetX |
|- | |- | ||
− | | | + | | 0xE || 0x2 || Gyroscope0OffsetY |
|- | |- | ||
− | | | + | | 0x10 || 0x2 || Gyroscope0OffsetZ |
|- | |- | ||
− | | | + | | 0x12 || 0x2 || Gyroscope78rpmScaleX |
|- | |- | ||
− | | | + | | 0x14 || 0x2 || Gyroscope78rpmScaleY |
|- | |- | ||
− | | | + | | 0x16 || 0x2 || Gyroscope78rpmScaleZ |
+ | |} | ||
+ | |||
+ | === Cal2 === | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickMainCalibrationValue]] |
|- | |- | ||
− | | | + | | 0x9 || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickSubCalibrationValue]] |
+ | |} | ||
+ | |||
+ | ==== AnalogStickCalibrationValue ==== | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x1 || AnalogStickCalXPositive |
|- | |- | ||
− | | | + | | 0x1 || 0x2 || AnalogStickCalYPositive |
|- | |- | ||
− | | | + | | 0x3 || 0x1 || AnalogStickCalX0 |
|- | |- | ||
− | | | + | | 0x4 || 0x2 || AnalogStickCalY0 |
|- | |- | ||
− | | | + | | 0x6 || 0x1 || AnalogStickCalXNegative |
|- | |- | ||
− | | | + | | 0x7 || 0x2 || AnalogStickCalYNegative |
+ | |} | ||
+ | |||
+ | === Design === | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0xC || [[#ControllerColor|ControllerColor]] |
|- | |- | ||
− | | | + | | 0xC || 0x1 || [[#DesignVariation|DesignVariation]] |
+ | |} | ||
+ | |||
+ | ==== ControllerColor ==== | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x1 || MainColorR |
|- | |- | ||
− | | | + | | 0x1 || 0x1 || MainColorG |
|- | |- | ||
− | | | + | | 0x2 || 0x1 || MainColorB |
|- | |- | ||
− | | | + | | 0x3 || 0x1 || SubColorR |
|- | |- | ||
− | | | + | | 0x4 || 0x1 || SubColorG |
|- | |- | ||
− | | | + | | 0x5 || 0x1 || SubColorB |
|- | |- | ||
− | | | + | | 0x6 || 0x1 || 3rdColorR |
|- | |- | ||
− | | | + | | 0x7 || 0x1 || 3rdColorG |
|- | |- | ||
− | | | + | | 0x8 || 0x1 || 3rdColorB |
|- | |- | ||
− | | | + | | 0x9 || 0x1 || 4thColorR |
|- | |- | ||
− | | | + | | 0xA || 0x1 || 4thColorG |
|- | |- | ||
− | | | + | | 0xB || 0x1 || 4thColorB |
+ | |} | ||
+ | |||
+ | ==== DesignVariation ==== | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Value | |
+ | ! Name | ||
|- | |- | ||
− | | | + | | 0x0 || LuciaJ, LagerJ |
|- | |- | ||
− | | | + | | 0x1 || LuciaE, LagerE |
|- | |- | ||
− | | | + | | 0x2 || LuciaU, LagerU |
+ | |} | ||
+ | |||
+ | === Model1 === | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x6 || [[#SixAxisSensorModelValue|SixAxisSensorModelValue]] |
|- | |- | ||
− | | | + | | 0x6 || 0x12 || [[#AnalogStickModelValue|AnalogStickMainModelValue]] |
+ | |} | ||
+ | |||
+ | ==== SixAxisSensorModelValue ==== | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x2 || SixAxisHorizontalOffsetX |
|- | |- | ||
− | | | + | | 0x2 || 0x2 || SixAxisHorizontalOffsetY |
|- | |- | ||
− | | | + | | 0x4 || 0x2 || SixAxisHorizontalOffsetZ |
+ | |} | ||
+ | |||
+ | ==== AnalogStickModelValue ==== | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x1 || AnalogStickModelNoise |
|- | |- | ||
− | | | + | | 0x1 || 0x2 || AnalogStickModelTypicalStroke |
|- | |- | ||
− | | | + | | 0x3 || 0x1 || AnalogStickModelCenterDeadZoneSize |
|- | |- | ||
− | | | + | | 0x4 || 0x2 || AnalogStickModelCircuitDeadZoneScale |
|- | |- | ||
− | | | + | | 0x6 || 0x1 || AnalogStickModelMinimumStrokeXPositive |
|- | |- | ||
− | | | + | | 0x7 || 0x2 || AnalogStickModelMinimumStrokeYPositive |
|- | |- | ||
− | | | + | | 0x9 || 0x1 || AnalogStickModelMinimumStrokeXNegative |
|- | |- | ||
− | | | + | | 0xA || 0x2 || AnalogStickModelMinimumStrokeYNegative |
|- | |- | ||
− | | | + | | 0xC || 0x1 || AnalogStickModelCenterRangeXPositive |
|- | |- | ||
− | | | + | | 0xD || 0x2 || AnalogStickModelCenterRangeYPositive |
|- | |- | ||
− | | | + | | 0xF || 0x1 || AnalogStickModelCenterRangeXNegative |
|- | |- | ||
− | | | + | | 0x10 || 0x2 || AnalogStickModelCenterRangeYNegative |
+ | |} | ||
+ | |||
+ | === Model2 === | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0x0 || 0x12 || [[#AnalogStickModelValue|AnalogStickSubModelValue]] | ||
+ | |} | ||
+ | |||
+ | == UserCalibration == | ||
+ | {| class="wikitable" border="1" | ||
+ | |- | ||
+ | ! Offset | ||
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x10 || Reserved |
|- | |- | ||
− | | | + | | 0x10 || 0x16 || [[#UserCal1|UserCal1]] |
|- | |- | ||
− | | | + | | 0x26 || 0x1A || [[#UserCal2|UserCal2]] |
|- | |- | ||
− | | | + | | 0x40 || 0xFC0 || Reserved |
+ | |} | ||
+ | |||
+ | === UserCal1 === | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x2 || AnalogStickMainUserMagicNumber |
|- | |- | ||
− | | | + | | 0x2 || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickMainUserCalibrationValue]] |
|- | |- | ||
− | | | + | | 0xB || 0x2 || AnalogStickSubUserMagicNumber |
|- | |- | ||
− | | | + | | 0xD || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickSubUserCalibrationValue]] |
+ | |} | ||
+ | |||
+ | === UserCal2 === | ||
+ | {| class="wikitable" border="1" | ||
|- | |- | ||
− | + | ! Offset | |
+ | ! Size | ||
+ | ! Description | ||
|- | |- | ||
− | | | + | | 0x0 || 0x2 || SixAxisUserCalibrationMagicNumber |
|- | |- | ||
− | | | + | | 0x2 || 0x18 || [[#SixAxisSensorCalibrationValue|SixAxisUserCalibrationValue]] |
|} | |} | ||
== Colors == | == Colors == | ||
HEX codes for the colors shown in the "Controllers" menu of the Switch UI can be found in a Joy-con SPI dump starting at offset 0x6050. Body color is first followed by button color and each is 3 bytes long. These values are able to be re-written with any HEX color value to make the Joy-cons show up as different colors in the UI. The following is a list of official HEX colors recovered from SPI dumps. | HEX codes for the colors shown in the "Controllers" menu of the Switch UI can be found in a Joy-con SPI dump starting at offset 0x6050. Body color is first followed by button color and each is 3 bytes long. These values are able to be re-written with any HEX color value to make the Joy-cons show up as different colors in the UI. The following is a list of official HEX colors recovered from SPI dumps. | ||
+ | |||
{| class="wikitable" | {| class="wikitable" | ||
− | ! Retail Color || Body HEX || Button HEX | + | ! Developer Kit Joy-Con || Release || Body HEX || Button HEX |
+ | |- | ||
+ | | Black / ブラック || 2015.10.16 || #313131 || #0F0F0F | ||
+ | |- | ||
+ | ! Standard Retail Joy-Con Color || Release || Body HEX || Button HEX | ||
+ | |- | ||
+ | | Gray / グレー || 2017.03.03 || #828282 || #0F0F0F | ||
+ | |- | ||
+ | | Neon Red / ネオンレッド || 2017.03.03 || #FF3C28 || #1E0A0A | ||
+ | |- | ||
+ | | Neon Blue / ネオンブルー || 2017.03.03 || #0AB9E6 || #001E1E | ||
+ | |- | ||
+ | | Neon Yellow / ネオンイエロー || 2017.06.16 || #E6FF00 || #142800 | ||
+ | |- | ||
+ | | Neon Green / ネオングリーン || 2017.07.21 || #1EDC00 || #002800 | ||
+ | |- | ||
+ | | Neon Pink / ネオンピンク || 2017.07.21 || #FF3278 || #28001E | ||
+ | |- | ||
+ | | Red / レッド || 2017.10.27 || #E10F00 || #280A0A | ||
+ | |- | ||
+ | | Blue / ブルー || 2019.10.04 || #4655F5 || #00000A | ||
+ | |- | ||
+ | | Neon Purple / ネオンパープル || 2019.10.04 || #B400E6 || #140014 | ||
+ | |- | ||
+ | | Neon Orange / ネオンオレンジ || 2019.10.04 || #FAA005 || #0F0A00 | ||
+ | |- | ||
+ | | White / ホワイト || 2021.10.08 || #E6E6E6 || #323232 | ||
+ | |- | ||
+ | | Pastel Pink / パステルピンク || 2023.06.30 || #FFAFAF || #372D2D | ||
+ | |- | ||
+ | | Pastel Yellow / パステルイエロー || 2023.06.30 || #F5FF82 || #32332D | ||
+ | |- | ||
+ | | Pastel Purple / パステルパープル || 2023.06.30 || #F0CBEB || #373037 | ||
+ | |- | ||
+ | | Pastel Green / パステルグリーン || 2023.06.30 || #BCFFC8 || #2D322D | ||
|- | |- | ||
− | | | + | ! Special Edition Joy-Con Color || Release || Body HEX || Button HEX |
|- | |- | ||
− | | Gray / グレー || #828282 || #0F0F0F | + | | Nintendo Switch Gray Joy-Con / Nintendo Switch グレー || 2017.03.03 || #828282 || #0F0F0F |
|- | |- | ||
− | | Neon | + | | Nintendo Switch Neon-Blue Left Joy-Con / Nintendo Switch ネオンブルー・ネオンレッド || 2017.03.03 || #0AB9E6 || #001E1E |
|- | |- | ||
− | | Neon | + | | Nintendo Switch Neon-Red Right Joy-Con / Nintendo Switch ネオンブルー・ネオンレッド || 2017.03.03 || #FF3C28 || #1E0A0A |
|- | |- | ||
− | | Neon | + | | Splatoon 2 Edition Neon-Green Left Joy-Con / スプラトゥーン2 || 2017.07.21 || #1EDC00 || #002800 |
|- | |- | ||
− | | Neon | + | | Splatoon 2 Edition Neon-Pink Right Joy-Con / スプラトゥーン2 || 2017.07.21 || #FF3278 || #28001E |
|- | |- | ||
− | | | + | | Super Mario Odyssey Edition Red Joy-Con / スーパーマリオ オデッセイ || 2017.10.27 || #E10F00 || #280A0A |
|- | |- | ||
− | | | + | | Super Smash Bros. Ultimate Edition Gray Joy-Con / 大乱闘スマッシュブラザーズ || 2018.11.02 || #828282 || #0F0F0F |
|- | |- | ||
− | | | + | | Pokémon: Let's Go! Edition Eevee-Brown Left Joy-Con / ポケットモンスター Let's Go! イーブイ || 2018.11.16 || #C88C32 || #281900 |
|- | |- | ||
− | | | + | | Pokémon: Let's Go! Edition Pikachu-Yellow Right Joy-Con / ポケットモンスター Let's Go! ピカチュウ || 2018.11.16 || #FFDC00 || #322800 |
|- | |- | ||
− | | | + | | *Nintendo Labo Creators Contest Edition "Cardboard"-Colored Joy-Con || 2018. (...?) || #D7AA73 || #1E1914 |
|- | |- | ||
− | | | + | | **Dragon Quest XI S Lotto Edition Royal-Blue Joy-Con / ドラゴン クエスト XI S (ロト版) || 2019.09.27 || #1473FA || #00000F |
|- | |- | ||
− | + | | **Disney Tsum Tsum Festival Edition Neon-Purple Left Joy-Con / ディズニー ツムツム フェスティバル || 2019.10.10 || #B400E6 || #140014 | |
|- | |- | ||
− | | | + | | **Disney Tsum Tsum Festival Edition Neon-Pink Right Joy-Con / ディズニー ツムツム フェスティバル || 2019.10.10 || #FF3278 || #28001E |
|- | |- | ||
− | | | + | | Animal Crossing: New Horizons Edition Pastel-Green Left Joy-Con / あつまれ どうぶつの森 || 2020.03.13 || #82FF96 || #0A1E0A |
|- | |- | ||
− | | | + | | Animal Crossing: New Horizons Edition Pastel-Blue Right Joy-Con / あつまれ どうぶつの森 || 2020.03.13 || #96F5F5 || #0A1E28 |
|- | |- | ||
− | | | + | | Fortnite Wildcat Edition Yellow Left Joy-Con / フォートナイト ワイルドキャット(山猫) || 2020.10.30 || #FFCC00 || #1A1100 |
|- | |- | ||
− | | | + | | Fortnite Wildcat Edition Dark-Blue Right Joy-Con / フォートナイト ワイルドキャット(山猫) || 2020.10.30 || #0084FF || #000F1E |
|- | |- | ||
− | | | + | | Mario Red × Blue Edition Red Joy-Con / マリオ レッド × ブルー || 2021.02.12 || #F04614 || #1E1914 |
|- | |- | ||
− | | | + | | Monster Hunter Rise Edition Gray Joy-Con / モンスターハンターライズ || 2021.03.26 || #818282 || #0E0F0F |
|- | |- | ||
− | | | + | | Fortnite Fleet Force Edition Dark-Blue Left Joy-Con / フォートナイト フリート フォース(力の艦隊) || 2021.06.04 || #0084FF || #000F1E |
|- | |- | ||
− | | | + | | Fortnite Fleet Force Edition Yellow Right Joy-Con / フォートナイト フリート フォース(力の艦隊) || 2021.06.04 || #FFCC00 || #1A1100 |
|- | |- | ||
− | | | + | | Legend of Zelda: Skyward Sword Edition Dark-Blue Left Joy-Con / ゼルダの伝説 スカイウォードソード || 2021.07.16 || #2D50F0 || #1E0F46 |
|- | |- | ||
− | | | + | | Legend of Zelda: Skyward Sword Edition Dark-Purple Right Joy-Con / ゼルダの伝説 スカイウォードソード || 2021.07.16 || #500FC8 || #00051E |
|- | |- | ||
− | | | + | | Nintendo Switch OLED Edition White Joy-Con / Nintendo Switch (有機ELモデル) ホワイト || 2021.10.08 || #E6E6E6 || #323232 |
|- | |- | ||
− | | | + | | Splatoon 3 OLED Edition Blue-Gradient Left Joy-Con / (有機ELモデル) スプラトゥーン3 || 2022.08.26 || #6455F5 || #28282D |
|- | |- | ||
− | | | + | | Splatoon 3 OLED Edition Neon-Yellow-Gradient Right Joy-Con / (有機ELモデル) スプラトゥーン3 || 2022.08.26 || #C3FA05 || #1E1E28 |
|- | |- | ||
− | | | + | | Pokémon: Scarlet × Violet OLED Edition Scarlet Left Joy-Con / (有機ELモデル) ポケットモンスター スカーレット・バイオレット || 2022.11.04 || #F07341 || #322D1E |
|- | |- | ||
− | | | + | | Pokémon: Scarlet × Violet OLED Edition Violet Right Joy-Con / (有機ELモデル) ポケットモンスター スカーレット・バイオレット || 2022.11.04 || #9650AA || #32322D |
|- | |- | ||
− | | Legend of Zelda: | + | | Legend of Zelda: Tears of the Kingdom Edition Gold Joy-Con / (有機ELモデル) ゼルダの伝説 ティアーズ オブ ザ キングダム || 2023.04.28 || #D2BE69 || #32322D |
|- | |- | ||
| // *(Prize Awarded for Labo Contest - No Retail) // **(Available Japan Only) | | // *(Prize Awarded for Labo Contest - No Retail) // **(Available Japan Only) | ||
|} | |} | ||
− | |||
− | |||
− |
Latest revision as of 21:06, 29 September 2024
Joy-Con is the name for the Switch's primary game controllers. The Joy-Con are internally called Sakyo (Left) and Ukyo (Right).
Hardware
Sakyo
Component | Description |
---|---|
SoC | Broadcom BCM20734 |
IMU | STMicroelectronics LSM6DS3H |
PMIC | Texas Instruments BQ24072 |
Storage | Macronix International MX25U4033E 4 Mb CMOS Flash |
Ukyo
Component | Description |
---|---|
SoC | Broadcom BCM20734 |
MCU | STMicroelectronics STM32P411 |
NFC | STMicroelectronics ST21NFCB |
IMU | STMicroelectronics LSM6DS3H |
PMIC | Texas Instruments BQ24072 |
Storage | Macronix International MX25U4033E 4 Mb CMOS Flash |
Protocol
The Joy-Con can communicate wirelessly over Bluetooth or through the rails over UART. The latter uses a Nintendo proprietary protocol called "Nwcp".
NwcpPacket
Offset | Size | Description |
---|---|---|
0x0 | 0x5 | HciHeader |
0x5 | 0x7 | NwcpHeader |
0xC | Variable | Data |
HciHeader
This is a 5-byte packet header used by Broadcom's HCI Control Protocol.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | PacketType (always 0x19) |
0x1 | 0x1 | CommandCode |
0x2 | 0x1 | GroupCode (always 0x03) |
0x3 | 0x2 | PacketLength |
CommandCode
Value | Description |
---|---|
0x1 | SendToDevice |
0x81 | ReceiveFromDevice |
NwcpHeader
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | CommandType |
0x1 | 0x1 | DeviceCommand |
0x2 | 0x2 | DataSize |
0x4 | 0x1 | CommandResult |
0x5 | 0x1 | DataCrc (CRC8 over Data for DataSize bytes) |
0x6 | 0x1 | HeaderCrc (CRC8 over the previous 6 bytes) |
CommandType
Value | Description |
---|---|
0x43 | ReportOut |
0x53 | ReportIn |
0x91 | DeviceCommandIn |
0x92 | Hid |
0x93 | |
0x94 | DeviceCommandOut |
0x95 | |
0x9A | Fifty |
0xA3 | ReportComplete |
0xA5 | Handshake |
HidCommandInputReport
This is a 0x31-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | LatencyTimer |
0x2 | 0x1 | PowerInfo |
0x3 | 0x1 | RightPadButtonStatus |
0x4 | 0x1 | SharedButtonStatus |
0x5 | 0x1 | LeftPadButtonStatus |
0x6 | 0x3 | LeftAnalogStickData |
0x9 | 0x3 | RightAnalogStickData |
0xC | 0x1 | MotorStatus |
0xD | 0x1 | CommandAck |
0xE | 0x1 | CommandId |
0xF | 0x22 | CommandReply |
HidMcuUpdateInputReport
This is a 0x30-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | LatencyTimer |
0x2 | 0x1 | PowerInfo |
0x3 | 0x1 | RightPadButtonStatus |
0x4 | 0x1 | SharedButtonStatus |
0x5 | 0x1 | LeftPadButtonStatus |
0x6 | 0x3 | LeftAnalogStickData |
0x9 | 0x3 | RightAnalogStickData |
0xC | 0x1 | MotorStatus |
0xD | 0x23 | McuUpdateData |
HidBasicInputReport
This is a 0x31-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | LatencyTimer |
0x2 | 0x1 | PowerInfo |
0x3 | 0x1 | RightPadButtonStatus |
0x4 | 0x1 | SharedButtonStatus |
0x5 | 0x1 | LeftPadButtonStatus |
0x6 | 0x3 | LeftAnalogStickData |
0x9 | 0x3 | RightAnalogStickData |
0xC | 0x1 | MotorStatus |
0xD | 0x24 | BasicData |
HidMcuInputReport
This is a 0x16A-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | LatencyTimer |
0x2 | 0x1 | PowerInfo |
0x3 | 0x1 | RightPadButtonStatus |
0x4 | 0x1 | SharedButtonStatus |
0x5 | 0x1 | LeftPadButtonStatus |
0x6 | 0x3 | LeftAnalogStickData |
0x9 | 0x3 | RightAnalogStickData |
0xC | 0x1 | MotorStatus |
0xD | 0x6 | SensorAccelSample0 |
0x13 | 0x6 | SensorGyroSample0 |
0x19 | 0x6 | SensorAccelSample1 |
0x1F | 0x6 | SensorGyroSample1 |
0x25 | 0x6 | SensorAccelSample2 |
0x2B | 0x6 | SensorGyroSample2 |
0x31 | 0x139 | McuData |
HidAttachmentInputReport
This is a 0x16A-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | LatencyTimer |
0x2 | 0x1 | PowerInfo |
0x3 | 0x1 | RightPadButtonStatus |
0x4 | 0x1 | SharedButtonStatus |
0x5 | 0x1 | LeftPadButtonStatus |
0x6 | 0x3 | LeftAnalogStickData |
0x9 | 0x3 | RightAnalogStickData |
0xC | 0x1 | MotorStatus |
0xD | 0x6 | SensorAccelSample0 |
0x13 | 0x6 | SensorGyroSample0 |
0x19 | 0x6 | SensorAccelSample1 |
0x1F | 0x6 | SensorGyroSample1 |
0x25 | 0x6 | SensorAccelSample2 |
0x2B | 0x6 | SensorGyroSample2 |
0x31 | 0x139 | AttachmentData |
HidGenericInputReport
This is a 0xC-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x2 | ButtonStatus |
0x3 | 0x1 | StickHatData |
0x4 | 0x4 | LeftAnalogStickData |
0x8 | 0x4 | RightAnalogStickData |
HidCommandOutputReport
This is a 0x31-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | PacketNumber |
0x2 | 0x8 | MotorData |
0xA | 0x1 | CommandId |
0xB | 0x26 | CommandData |
HidMcuUpdateOutputReport
This is a 0x13E-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | PacketNumber |
0x2 | 0x8 | MotorData |
0xA | 0x134 | McuUpdateData |
HidBasicOutputReport
This is a 0xA-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | PacketNumber |
0x2 | 0x8 | MotorData |
HidMcuOutputReport
This is a 0x30-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | PacketNumber |
0x2 | 0x8 | MotorData |
0xA | 0x26 | McuData |
HidAttachmentOutputReport
This is a 0x30-byte struct.
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | ReportId |
0x1 | 0x1 | PacketNumber |
0x2 | 0x8 | MotorData |
0xA | 0x26 | AttachmentData |
HidReportId
Value | Description |
---|---|
0x01 | CommandOutputReport |
0x03 | McuUpdateOutputReport |
0x10 | BasicOutputReport |
0x11 | McuOutputReport |
0x12 | AttachmentOutputReport |
0x21 | CommandInputReport |
0x23 | McuUpdateInputReport |
0x30 | BasicInputReport |
0x31 | McuInputReport |
0x32 | AttachmentInputReport |
0x33 | |
0x3F | GenericInputReport |
0x70 | OtaEnableFwuReport |
0x71 | OtaSetupReadReport |
0x72 | OtaReadReport |
0x73 | OtaWriteReport |
0x74 | OtaEraseReport |
0x75 | OtaLaunchReport |
0x80 | ExtGripOutputReport |
0x81 | ExtGripInputReport |
0x82 |
HidMotorData
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | JoyLeftVibrationAmFmPackTag |
0x4 | 0x8 | JoyRightVibrationAmFmPackTag |
VibrationAmFmPackTag
This is "nn::xcd::VibrationAmFmPackTag". This is a BitPack object.
VibrationAmFmPackFormatZero
Bits | Description |
---|---|
0-29 | Reserved |
30-31 | PackFormat (must be 0) |
VibrationAmFmPackFormatOne
Bits | Description |
---|---|
0-19 | Reserved |
20-24 | ChannelCodesHigh |
25-29 | ChannelCodesLow |
30-31 | PackFormat (must be 1) |
VibrationAmFmPackFormatOne28bit
Bits | Description |
---|---|
0-1 | Reserved |
2-8 | ChannelFrequencyHigh |
9-15 | ChannelAmplitudeHigh |
16-22 | ChannelFrequencyLow |
23-29 | ChannelAmplitudeLow |
30-31 | PackFormat (must be 1) |
VibrationAmFmPackFormatTwo
Bits | Description |
---|---|
0-9 | Reserved |
10-14 | VibrationCodesHigh |
15-19 | VibrationCodesLow |
20-24 | ChannelCodesHigh |
25-29 | ChannelCodesLow |
30-31 | PackFormat (must be 2) |
VibrationAmFmPackFormatTwo14bitLow
Bits | Description |
---|---|
0 | IsChannelHigh (must be 0) |
1-7 | ChannelFrequency |
8-12 | VibrationCodesHigh1 |
13-17 | VibrationCodesLow1 |
18-22 | VibrationCodesHigh0 |
23-29 | ChannelAmplitude |
30-31 | PackFormat (must be 2) |
VibrationAmFmPackFormatTwo14bitHigh
Bits | Description |
---|---|
0 | IsChannelHigh (must be 1) |
1-7 | ChannelFrequency |
8-12 | VibrationCodesHigh1 |
13-17 | VibrationCodesLow1 |
18-22 | VibrationCodesLow0 |
23-29 | ChannelAmplitude |
30-31 | PackFormat (must be 2) |
VibrationAmFmPackFormatThree
Bits | Description |
---|---|
0-4 | VibrationCodesHigh1 |
5-9 | VibrationCodesLow1 |
10-14 | VibrationCodesHigh0 |
15-19 | VibrationCodesLow0 |
20-24 | ChannelCodesHigh |
25-29 | ChannelCodesLow |
30-31 | PackFormat (must be 3) |
VibrationAmFmPackFormatThree7bit
Bits | Description |
---|---|
0 | IsChannelHigh |
1 | IsThree7bit (must be 1) |
2 | IsFm |
3-7 | VibrationCodesHigh1 |
8-12 | VibrationCodesLow1 |
13-17 | VibrationCodesHigh0 |
18-22 | VibrationCodesLow0 |
23-29 | ChannelAmFm |
30-31 | PackFormat (must be 1, instead of 3) |
AmFmCodes
These are 32-bit values used by the Joy-Con firmware to represent combinations of amplitude/frequency pairs for vibration.
Unpacking
The Joy-Con firmware receives vibration data packed as VibrationAmFmPackTag from output reports. Depending on the packing format, these tags are then converted to an array of AmFmCodes as follows.
AmFm5BitCodes
Converted from VibrationAmFmPackFormatOne, VibrationAmFmPackFormatTwo or VibrationAmFmPackFormatThree.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | (ChannelCodesLow & 0x1F) |
0x4 | 0x4 | (ChannelCodesHigh & 0x1F) |
0x8 | 0x4 | (VibrationCodesLow0 & 0x1F) |
0xC | 0x4 | (VibrationCodesHigh0 & 0x1F) |
0x10 | 0x4 | (VibrationCodesLow1 & 0x1F) |
0x14 | 0x4 | (VibrationCodesHigh1 & 0x1F) |
AmFm7BitOneCodes
Converted from VibrationAmFmPackFormatOne28bit.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | (((ChannelFrequencyLow & 0x7F) << 8) | (ChannelAmplitudeLow & 0x7F) | 0x8080) |
0x4 | 0x4 | (((ChannelFrequencyHigh & 0x7F) << 8) | (ChannelAmplitudeHigh & 0x7F) | 0x8080) |
AmFm7BitTwoCodes
Converted from VibrationAmFmPackFormatTwo14bitLow or VibrationAmFmPackFormatTwo14bitHigh.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | IsChannelHigh ? (VibrationCodesLow0 & 0x1F) : (((ChannelFrequency & 0x7F) << 8) | (ChannelAmplitude & 0x7F) | 0x8080) |
0x4 | 0x4 | IsChannelHigh ? (((ChannelFrequency & 0x7F) << 8) | (ChannelAmplitude & 0x7F) | 0x8080) : (VibrationCodesHigh0 & 0x1F) |
0x8 | 0x4 | (VibrationCodesLow1 & 0x1F) |
0xC | 0x4 | (VibrationCodesHigh1 & 0x1F) |
0x10 | 0x4 | Always 0x18 |
0x14 | 0x4 | Always 0x18 |
AmFm7BitThreeCodes
Converted from VibrationAmFmPackFormatThree7bit.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | IsChannelHigh ? 0x18 : (IsFm ? (((ChannelAmFm & 0x7F) << 8) | 0x8000) : ((ChannelAmFm & 0x7F) | 0x80)) |
0x4 | 0x4 | IsChannelHigh ? (IsFm ? (((ChannelAmFm & 0x7F) << 8) | 0x8000) : ((ChannelAmFm & 0x7F) | 0x80)) : 0x18 |
0x8 | 0x4 | (VibrationCodesLow0 & 0x1F) |
0xC | 0x4 | (VibrationCodesHigh0 & 0x1F) |
0x10 | 0x4 | (VibrationCodesLow1 & 0x1F) |
0x14 | 0x4 | (VibrationCodesHigh1 & 0x1F) |
DeviceCommand
Value | Description |
---|---|
0x01 | Inquiry |
0x02 | WriteChargerSettings |
0x03 | ReadChargerSettings |
0x04 | AttachmentEnable |
0x05 | IsAttachmentEnabled |
0x06 | GetBatteryVoltage |
0x07 | ReadWakeUpReason |
0x10 | CreateHidConnection |
0x11 | DisconnectHid |
0x12 | SetHidInterval |
0x13 | GetHidInterval |
0x18 | Pairing |
0x20 | UpdateUartBaudRate |
0x40 | Test |
HidCommand
Value | Description |
---|---|
0x01 | PairingOut |
0x02 | GetDeviceInfo |
0x03 | SetDataFormat |
0x04 | LRButtonDetection |
0x05 | Page |
0x06 | Reset |
0x07 | ClearPairingInfo |
0x08 | Shipment |
0x10 | SerialFlashRead |
0x11 | SerialFlashWrite |
0x12 | SerialFlashSectorErase |
0x20 | McuReset |
0x21 | McuWrite |
0x22 | McuResume |
0x24 | McuPollingEnable |
0x25 | McuPollingDisable |
0x28 | AttachmentWrite |
0x29 | AttachmentRead |
0x2A | AttachmentEnable |
0x2B | GetAttachmentInfo |
0x30 | SetIndicatorLed |
0x31 | GetIndicatorLed |
0x38 | SetNotificationLed |
0x40 | SensorSleep |
0x41 | SensorConfig |
0x42 | SensorWrite |
0x43 | SensorRead |
0x48 | MotorEnable |
0x50 | GetBatteryVoltage |
0x51 | WriteChargeSetting |
0x52 | ReadChargeSetting |
0x58 | ExtDevWrite |
0x59 | GetExtDevInfo |
0x5A | ExtDevPollingEnable |
0x5B | ExtDevPollingDisable |
0x5C | ExtDevInFormatConfig |
0x5D | |
0x60 | InternalAttachmentWrite |
0x61 | |
0x62 | InternalAttachmentEnable |
0x63 | InternalAttachmentPollingEnable |
0x64 | InternalAttachmentPollingDisable |
0x7A | AddButtonPlayData |
0x7B | StartStopButtonPlayData |
0x80 | Ack |
0x81 | PairingIn |
0x82 | DeviceInfo |
0x83 | LRButtonElapsedTime |
0x90 | SerialFlashData |
0xA0 | McuData |
0xA8 | AttachmentData |
0xA9 | AttachmentInfo |
0xAA | InternalAttachmentRead |
0xB0 | IndicatorLed |
0xC0 | SensorData |
0xD0 | BatteryVoltage |
0xD8 | ExtDevRead |
0xD9 | ExtDevInfo |
ExtGripCommand
Value | Description |
---|---|
0x01 | Inquiry |
0x02 | CreateHidConnection |
0x03 | DeleteHidConnection |
0x04 | StartHidData |
0x05 | StopHidData |
0x06 | |
0x07 | GetFirmwareVersion |
0x08 | |
0x91 | LoopbackTest |
0x92 | |
0xA0 | SetUartClockTrim |
Firmware
The firmware is stored inside the flash in Broadcom's PatchRAM format as follows:
Offset | Size | Description |
---|---|---|
0x0 | 0x1000 | StaticSection |
0x1000 | 0x1000 | FailsafeSection |
0x2000 | 0x1000 | VolatileSection |
0x3000 | 0x1000 | VolatileSectionBackup1 |
0x4000 | 0x1000 | VolatileSectionBackup2 |
0x5000 | 0x1000 | ShipmentInfo |
0x6000 | 0x1000 | FactoryConfiguration |
0x7000 | 0x1000 | Reserved |
0x8000 | 0x1000 | UserCalibration |
0x9000 | 0x7000 | Reserved |
0x10000 | 0x18000 | DynamicSection1 |
0x28000 | 0x18000 | DynamicSection2 |
0x40000 | 0x40000 | Reserved |
FailsafeSection
Offset | Size | Description |
---|---|---|
0x0 | 0xFF4 | Reserved |
0xFF4 | 0x8 | Signature |
0xFFC | 0x4 | Ds2Offset |
VolatileSection
Offset | Size | Description |
---|---|---|
0x0 | 0x26 | |
0x26 | 0xFDA | Reserved |
ShipmentInfo
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | Shipment |
0x1 | 0xFFF | Reserved |
FactoryConfiguration
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | IdentificationCode |
0x10 | 0x2 | Reserved |
0x12 | 0x1 | DeviceType |
0x13 | 0x1 | BoardRevision |
0x14 | 0x7 | Reserved |
0x1B | 0x1 | FormatVersion |
0x1C | 0x4 | Reserved |
0x20 | 0x18 | Cal1 |
0x38 | 0x5 | Reserved |
0x3D | 0x12 | Cal2 |
0x4F | 0x1 | Reserved |
0x50 | 0xD | Design |
0x5D | 0x23 | Reserved |
0x80 | 0x18 | Model1 |
0x98 | 0x12 | Model2 |
0xAA | 0x1 | Reserved |
0xAB | 0x1 | AccelerometerAxisAssignment |
0xAC | 0x1 | GyroscopeAxisAssignment |
0xAD | 0x1 | AnalogStickMainAxisAssignment |
0xAE | 0x1 | AnalogStickSubAxisAssignment |
0xAF | 0x151 | Reserved |
0x200 | 0x2 | BatteryVoltage |
0x202 | 0xB7E | Reserved |
0xD80 | 0x2 | TarragonVid |
0xD82 | 0x2 | TarragonPid |
0xD84 | 0x7C | Reserved |
0xE00 | 0x100 | InspectionLog |
0xF00 | 0x100 | Reserved |
DeviceType
Value | Description |
---|---|
0x01 | JoyConLeft |
0x02 | JoyConRight |
0x03 | SwitchProController |
0x04 | MiyabiLeft |
0x05 | MiyabiRight |
0x06 | Tarragon |
0x07 | LarkH1 |
0x08 | LarkH2 |
0x09 | LarkNL |
0x0A | LarkNR |
0x0B | Lucia |
0x0C | [12.0.0+] Lagon |
0x0D | [13.0.0+] Lager |
0x0E | [14.0.0+] Tarragon2 |
0x21 | FiftyL |
0x22 | FiftyR |
Cal1
Offset | Size | Description |
---|---|---|
0x0 | 0x18 | SixAxisSensorCalibrationValue |
SixAxisSensorCalibrationValue
Offset | Size | Description |
---|---|---|
0x0 | 0x2 | Accelerometer0OffsetX |
0x2 | 0x2 | Accelerometer0OffsetY |
0x4 | 0x2 | Accelerometer0OffsetZ |
0x6 | 0x2 | Accelerometer1gScaleX |
0x8 | 0x2 | Accelerometer1gScaleY |
0xA | 0x2 | Accelerometer1gScaleZ |
0xC | 0x2 | Gyroscope0OffsetX |
0xE | 0x2 | Gyroscope0OffsetY |
0x10 | 0x2 | Gyroscope0OffsetZ |
0x12 | 0x2 | Gyroscope78rpmScaleX |
0x14 | 0x2 | Gyroscope78rpmScaleY |
0x16 | 0x2 | Gyroscope78rpmScaleZ |
Cal2
Offset | Size | Description |
---|---|---|
0x0 | 0x9 | AnalogStickMainCalibrationValue |
0x9 | 0x9 | AnalogStickSubCalibrationValue |
AnalogStickCalibrationValue
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | AnalogStickCalXPositive |
0x1 | 0x2 | AnalogStickCalYPositive |
0x3 | 0x1 | AnalogStickCalX0 |
0x4 | 0x2 | AnalogStickCalY0 |
0x6 | 0x1 | AnalogStickCalXNegative |
0x7 | 0x2 | AnalogStickCalYNegative |
Design
Offset | Size | Description |
---|---|---|
0x0 | 0xC | ControllerColor |
0xC | 0x1 | DesignVariation |
ControllerColor
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | MainColorR |
0x1 | 0x1 | MainColorG |
0x2 | 0x1 | MainColorB |
0x3 | 0x1 | SubColorR |
0x4 | 0x1 | SubColorG |
0x5 | 0x1 | SubColorB |
0x6 | 0x1 | 3rdColorR |
0x7 | 0x1 | 3rdColorG |
0x8 | 0x1 | 3rdColorB |
0x9 | 0x1 | 4thColorR |
0xA | 0x1 | 4thColorG |
0xB | 0x1 | 4thColorB |
DesignVariation
Value | Name |
---|---|
0x0 | LuciaJ, LagerJ |
0x1 | LuciaE, LagerE |
0x2 | LuciaU, LagerU |
Model1
Offset | Size | Description |
---|---|---|
0x0 | 0x6 | SixAxisSensorModelValue |
0x6 | 0x12 | AnalogStickMainModelValue |
SixAxisSensorModelValue
Offset | Size | Description |
---|---|---|
0x0 | 0x2 | SixAxisHorizontalOffsetX |
0x2 | 0x2 | SixAxisHorizontalOffsetY |
0x4 | 0x2 | SixAxisHorizontalOffsetZ |
AnalogStickModelValue
Offset | Size | Description |
---|---|---|
0x0 | 0x1 | AnalogStickModelNoise |
0x1 | 0x2 | AnalogStickModelTypicalStroke |
0x3 | 0x1 | AnalogStickModelCenterDeadZoneSize |
0x4 | 0x2 | AnalogStickModelCircuitDeadZoneScale |
0x6 | 0x1 | AnalogStickModelMinimumStrokeXPositive |
0x7 | 0x2 | AnalogStickModelMinimumStrokeYPositive |
0x9 | 0x1 | AnalogStickModelMinimumStrokeXNegative |
0xA | 0x2 | AnalogStickModelMinimumStrokeYNegative |
0xC | 0x1 | AnalogStickModelCenterRangeXPositive |
0xD | 0x2 | AnalogStickModelCenterRangeYPositive |
0xF | 0x1 | AnalogStickModelCenterRangeXNegative |
0x10 | 0x2 | AnalogStickModelCenterRangeYNegative |
Model2
Offset | Size | Description |
---|---|---|
0x0 | 0x12 | AnalogStickSubModelValue |
UserCalibration
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | Reserved |
0x10 | 0x16 | UserCal1 |
0x26 | 0x1A | UserCal2 |
0x40 | 0xFC0 | Reserved |
UserCal1
Offset | Size | Description |
---|---|---|
0x0 | 0x2 | AnalogStickMainUserMagicNumber |
0x2 | 0x9 | AnalogStickMainUserCalibrationValue |
0xB | 0x2 | AnalogStickSubUserMagicNumber |
0xD | 0x9 | AnalogStickSubUserCalibrationValue |
UserCal2
Offset | Size | Description |
---|---|---|
0x0 | 0x2 | SixAxisUserCalibrationMagicNumber |
0x2 | 0x18 | SixAxisUserCalibrationValue |
Colors
HEX codes for the colors shown in the "Controllers" menu of the Switch UI can be found in a Joy-con SPI dump starting at offset 0x6050. Body color is first followed by button color and each is 3 bytes long. These values are able to be re-written with any HEX color value to make the Joy-cons show up as different colors in the UI. The following is a list of official HEX colors recovered from SPI dumps.
Developer Kit Joy-Con | Release | Body HEX | Button HEX |
---|---|---|---|
Black / ブラック | 2015.10.16 | #313131 | #0F0F0F |
Standard Retail Joy-Con Color | Release | Body HEX | Button HEX |
Gray / グレー | 2017.03.03 | #828282 | #0F0F0F |
Neon Red / ネオンレッド | 2017.03.03 | #FF3C28 | #1E0A0A |
Neon Blue / ネオンブルー | 2017.03.03 | #0AB9E6 | #001E1E |
Neon Yellow / ネオンイエロー | 2017.06.16 | #E6FF00 | #142800 |
Neon Green / ネオングリーン | 2017.07.21 | #1EDC00 | #002800 |
Neon Pink / ネオンピンク | 2017.07.21 | #FF3278 | #28001E |
Red / レッド | 2017.10.27 | #E10F00 | #280A0A |
Blue / ブルー | 2019.10.04 | #4655F5 | #00000A |
Neon Purple / ネオンパープル | 2019.10.04 | #B400E6 | #140014 |
Neon Orange / ネオンオレンジ | 2019.10.04 | #FAA005 | #0F0A00 |
White / ホワイト | 2021.10.08 | #E6E6E6 | #323232 |
Pastel Pink / パステルピンク | 2023.06.30 | #FFAFAF | #372D2D |
Pastel Yellow / パステルイエロー | 2023.06.30 | #F5FF82 | #32332D |
Pastel Purple / パステルパープル | 2023.06.30 | #F0CBEB | #373037 |
Pastel Green / パステルグリーン | 2023.06.30 | #BCFFC8 | #2D322D |
Special Edition Joy-Con Color | Release | Body HEX | Button HEX |
Nintendo Switch Gray Joy-Con / Nintendo Switch グレー | 2017.03.03 | #828282 | #0F0F0F |
Nintendo Switch Neon-Blue Left Joy-Con / Nintendo Switch ネオンブルー・ネオンレッド | 2017.03.03 | #0AB9E6 | #001E1E |
Nintendo Switch Neon-Red Right Joy-Con / Nintendo Switch ネオンブルー・ネオンレッド | 2017.03.03 | #FF3C28 | #1E0A0A |
Splatoon 2 Edition Neon-Green Left Joy-Con / スプラトゥーン2 | 2017.07.21 | #1EDC00 | #002800 |
Splatoon 2 Edition Neon-Pink Right Joy-Con / スプラトゥーン2 | 2017.07.21 | #FF3278 | #28001E |
Super Mario Odyssey Edition Red Joy-Con / スーパーマリオ オデッセイ | 2017.10.27 | #E10F00 | #280A0A |
Super Smash Bros. Ultimate Edition Gray Joy-Con / 大乱闘スマッシュブラザーズ | 2018.11.02 | #828282 | #0F0F0F |
Pokémon: Let's Go! Edition Eevee-Brown Left Joy-Con / ポケットモンスター Let's Go! イーブイ | 2018.11.16 | #C88C32 | #281900 |
Pokémon: Let's Go! Edition Pikachu-Yellow Right Joy-Con / ポケットモンスター Let's Go! ピカチュウ | 2018.11.16 | #FFDC00 | #322800 |
*Nintendo Labo Creators Contest Edition "Cardboard"-Colored Joy-Con | 2018. (...?) | #D7AA73 | #1E1914 |
**Dragon Quest XI S Lotto Edition Royal-Blue Joy-Con / ドラゴン クエスト XI S (ロト版) | 2019.09.27 | #1473FA | #00000F |
**Disney Tsum Tsum Festival Edition Neon-Purple Left Joy-Con / ディズニー ツムツム フェスティバル | 2019.10.10 | #B400E6 | #140014 |
**Disney Tsum Tsum Festival Edition Neon-Pink Right Joy-Con / ディズニー ツムツム フェスティバル | 2019.10.10 | #FF3278 | #28001E |
Animal Crossing: New Horizons Edition Pastel-Green Left Joy-Con / あつまれ どうぶつの森 | 2020.03.13 | #82FF96 | #0A1E0A |
Animal Crossing: New Horizons Edition Pastel-Blue Right Joy-Con / あつまれ どうぶつの森 | 2020.03.13 | #96F5F5 | #0A1E28 |
Fortnite Wildcat Edition Yellow Left Joy-Con / フォートナイト ワイルドキャット(山猫) | 2020.10.30 | #FFCC00 | #1A1100 |
Fortnite Wildcat Edition Dark-Blue Right Joy-Con / フォートナイト ワイルドキャット(山猫) | 2020.10.30 | #0084FF | #000F1E |
Mario Red × Blue Edition Red Joy-Con / マリオ レッド × ブルー | 2021.02.12 | #F04614 | #1E1914 |
Monster Hunter Rise Edition Gray Joy-Con / モンスターハンターライズ | 2021.03.26 | #818282 | #0E0F0F |
Fortnite Fleet Force Edition Dark-Blue Left Joy-Con / フォートナイト フリート フォース(力の艦隊) | 2021.06.04 | #0084FF | #000F1E |
Fortnite Fleet Force Edition Yellow Right Joy-Con / フォートナイト フリート フォース(力の艦隊) | 2021.06.04 | #FFCC00 | #1A1100 |
Legend of Zelda: Skyward Sword Edition Dark-Blue Left Joy-Con / ゼルダの伝説 スカイウォードソード | 2021.07.16 | #2D50F0 | #1E0F46 |
Legend of Zelda: Skyward Sword Edition Dark-Purple Right Joy-Con / ゼルダの伝説 スカイウォードソード | 2021.07.16 | #500FC8 | #00051E |
Nintendo Switch OLED Edition White Joy-Con / Nintendo Switch (有機ELモデル) ホワイト | 2021.10.08 | #E6E6E6 | #323232 |
Splatoon 3 OLED Edition Blue-Gradient Left Joy-Con / (有機ELモデル) スプラトゥーン3 | 2022.08.26 | #6455F5 | #28282D |
Splatoon 3 OLED Edition Neon-Yellow-Gradient Right Joy-Con / (有機ELモデル) スプラトゥーン3 | 2022.08.26 | #C3FA05 | #1E1E28 |
Pokémon: Scarlet × Violet OLED Edition Scarlet Left Joy-Con / (有機ELモデル) ポケットモンスター スカーレット・バイオレット | 2022.11.04 | #F07341 | #322D1E |
Pokémon: Scarlet × Violet OLED Edition Violet Right Joy-Con / (有機ELモデル) ポケットモンスター スカーレット・バイオレット | 2022.11.04 | #9650AA | #32322D |
Legend of Zelda: Tears of the Kingdom Edition Gold Joy-Con / (有機ELモデル) ゼルダの伝説 ティアーズ オブ ザ キングダム | 2023.04.28 | #D2BE69 | #32322D |
// *(Prize Awarded for Labo Contest - No Retail) // **(Available Japan Only) |