Wiimote/Extension Controllers/Wii Motion Plus
The Wii Motion Plus starts off at register 0xA60000 instead of register 0xA40000, because it has its own extension port on the back allowing a Nunchuk for example to be plugged in along with the Wii Motion Plus. BUT it changes to 0xA40000 once it is activated by writing 04 to 0xa600fe.
The Wii Motion Plus is first identified by the 6 bytes: 00 00 A6 20 00 05 at register address 0x(4)a600fa (instead of 0x(4)a400fa like a regular extension). Games attempt to detect the Wii Motion Plus by trying to read the two-byte expansion identifier at 0xA600FE (they try up to 3 times, then wait 8 seconds, then check again). If a Wii Motion Plus is not present, or it has already been activated, then the attempt to read those bytes will fail with error 7.
The extension is initialised by writing 0x55 to 0x(4)a600f0. But there is no need to write 00 to 0x(4)a500fb, since Wii games don't do that. While the Motion Plus is initialising, the value at 0x(4)a600f7 changes from 0x02 to 0x04 to 0x08 to 0x0C to 0x0E then stays at 0x0E. There is no need to read this byte, since games don't. While initialising, the 128 bytes from 0x(4)a60050 - 0x(4)a600cf also change briefly, but randomly, after the extension is initialized. More examples of this data block changing over time can be found here: Three Data Samples from Wii Motion Plus (Google Doc) (dead link). See this archive.
The 32 bytes from 0x(4)a60020 are, as usual, calibration information, described as follows:
| | Offset | |||||||
| | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
Address | 0x(4)a60020 | Fast mode yaw zero value | Fast mode roll zero value | Fast mode pitch zero value | Fast mode yaw scale value | ||||
0x(4)a60028 | Fast mode roll scale value | Fast mode pitch scale value | Fast mode degrees_div_6 | UID 1 (seems to just be a unique id) | CRC32 Hash of all calibration data's MSB | ||||
0x(4)a60030 | Slow mode yaw zero value | Slow mode roll zero value | Slow mode pitch zero value | Slow mode yaw scale value | |||||
0x(4)a60038 | Slow mode roll scale value | Slow mode pitch scale value | Slow mode degrees_div_6 | UID 2 (seems to just be a unique id) | CRC32 Hash of all calibration data's LSB |
source code struct example |
---|
// All values are big-endian.
// Assume data is tightly packed.
struct calibration_block
{
// Gyro values at 0 deg/sec to 16 bits of precision.
u16 yaw_zero;
u16 roll_zero;
u16 pitch_zero;
// Gyro values at "scale" deg/sec.
u16 yaw_scale;
u16 roll_scale;
u16 pitch_scale;
// Angular velocity of the above scale values in deg/sec divided by 6.
// e.g. A value of 45 would mean the "scale" values represent the gyro at 270 deg/sec.
u8 degrees_div_6;
};
// uid_1,2 seem to be just a unique ID.
// crc32_msb,lsb is a crc32 of all calibration data except the checksum bytes.
struct calibration_data_at_0x20
{
// Calibration for "fast" mode. (described below)
calibration_block fast;
u8 uid_1;
u16 crc32_msb;
// Calibration for "slow" mode.
calibration_block slow;
u8 uid_2;
u16 crc32_lsb;
}; |
Writing 0x04 to 0x(4)A600FE activates the MotionPlus as the "active" extension. This does 3 things (with no additional initialization):
- A status report (0x20) will automatically be sent indicating that a normal extension has been plugged in, if and only if there was no extension plugged into the MotionPlus pass-through extension port.
- The standard extension identifier at 0x(4)A400FA now reads 00 00 A4 20 04 05
- Extension reports now contain MotionPlus data.
Writing 0x55 to 0x(4)A400F0 deactivates the MotionPlus, and activates the Nunchuk or other extension plugged into the back of the Motion Plus. It does these things (with no additional initialization):
- A status report (0x20) will always be sent indicating that a normal extension has been unplugged.
- The Motion Plus extension identifier at 0x(4)A600FA now reads 00 00 A6 20 04 05
- Another status report (0x20) will always be sent indicating that a normal extension has been plugged in.
- The standard extension block at 0x(4)A40000 now reads from the Nunchuk (or other extension)
- Extension reports no longer contain MotionPlus data
It is possible to read from both MotionPlus and an extension controller at the same time by activating the MotionPlus in one of the pass-through modes suggested by DogP. When activated, this interleaves extension controller data with MotionPlus data on every other read. Data passing through are modified to make room for 3 bookkeeping bits. Two pass-through modes are currently known, one with modifications adapted to the Nunchuck, and one with modifications adapted to the Classic Controller (but suitable for Guitar, Drums, or Turntable).
Nunchuck pass-through mode :
- Activated by writing 0x05 instead of 0x04 to 0x(4)A600FE
- Data passing through drops the least significant bit of the three accelerometer values
- Bit 7 of byte 5 is moved to bit 6 of byte 5, overwriting it
- Bit 0 of byte 4 is moved to bit 7 of byte 5
- Bit 3 of byte 5 is moved to bit 4 of byte 5, overwriting it
- Bit 1 of byte 5 is moved to bit 3 of byte 5
- Bit 0 of byte 5 is moved to bit 2 of byte 5, overwriting it
Classic Controller or Musical Instrument pass-through mode:
- Activated by writing 0x07 instead of 0x04 to 0x(4)A600FE
- Data passing through drops the least significant bit of the axes of the left (or only) joystick
- Bit 0 of Byte 4 is overwritten
- Bits 0 and 1 of Byte 5 are moved to bit 0 of Bytes 0 and 1, overwriting what was there before
When not activated, the MotionPlus is detected by regular polling (every 8 seconds or so) of 0x(4)a600fe. Writing 0x55 to 0x4A400F0, then 0x00 to 0x4A400FB (the standard extension init, works fine even with no extension) re-activates the standard extension, if any, plugged into the MotionPlus pass-through port. The development version of the CWiid driver currently implements this method (without automatic 8 second checks) on the motionplus branch. Additional information on MotionPlus workings and implementation requirements are at http://abstrakraft.org/cwiid/wiki/MotionPlus.
There is no requirement to use the correct mode for the extension, but otherwise the bitshift/move wouldn't make sense. Using the Nunchuk in classic controller mode would clobber a significant bit in the middle of the Z acceleration. Using the Classic controller in Nunchuk mode would clobber some of the buttons. |
Data Format
The Wii Motion Plus reports its information as 6 bytes of data, readable at 0x(4)a40008 (or 0x(4)a40000 in some cases) and streamable using Data Reporting Modes that include Extension bytes (unused bytes are filled with 0x00). The data is packed into the six bytes as follows:
Bit | ||||||||
Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | Yaw Down Speed<7:0> | |||||||
1 | Roll Left Speed<7:0> | |||||||
2 | Pitch Left Speed<7:0> | |||||||
3 | Yaw Down Speed<13:8> | Yaw slow mode | Pitch slow mode | |||||
4 | Roll Left Speed<13:8> | Roll slow mode | Extension connected | |||||
5 | Pitch Left Speed<13:8> | 1 | 0 |
While the Wiimote is still, the values will be about 0x1F7F (8,063), although it is best to calibrate for a few seconds every time you start, to get the actual zero values.
Voltage reference is 1.35V that you can assume it as 8192 unit (half of the ADC range), using 2.27 mV/deg/s, 8192 is 595 deg/s (1.35V/2.27mV), you must divide by ~13.768 unit/deg/s (8192/595) to know the correct deg/s.
At high speed (slow bit = 0) raw values read are small with the same deg/s to reach higher values on top, so you must multiply it by 2000/440 (they are the max reference in the two modes in deg/s [1]). Example: reading 8083 raw value and assuming 8063 as zero, 20 unit in slow/normal mode are 1,45 deg/s and in fast mode are 1.45*2000/440=6.59 deg/s.
Yaw/Roll/Pitch fast/slow bits are 1 when the Wii Remote is rotating slowly (or not rotating at all), 0 when the Wii Remote is rotating fast.
Extension connected is 1 when an extension is connected to the MotionPlus extension port.
The definition of yaw, pitch, and roll, are slightly different for the gyros and accelerometers. Accelerometers measure angles relative to gravity. Gyros measure angles relative to the Wii Remote. If the Wii Remote is up the right way, then they are the same. But if the Wii Remote is on its side, then what the gyros call "pitch" is actually what the accelerometers would call "yaw". |
The correct way to measure orientation is to maintain a rotation matrix (or alternatively a quaternion) of the current orientation (relative to gravity), and update it each time you get a gyro reading. It will drift a little, so you should reset the matrix's pitch and roll (but not yaw) with the values from the accelerometers whenever the accelerometers and gyros indicate no movement. After significant rotation, you should reset the matrix's yaw to zero when the Wii Remote is pointing near the middle (horizontally) of the sensor bar.
The combination of 3 linear accelerations with 3 angular rates allows what Nintendo refers to as 1:1 motion tracking, which is another way of saying 6DOF (degrees of freedom) over a short time. It's only valid over short times because of the integration involved to convert accelerations and rates into positions (input errors, when integrated, blow up over time).
In addition to providing yaw, the gyros also allow the software to tell the difference between orientation and acceleration, which are difficult to tell apart from the accelerometers which measure a mixture of both.
Wii Motion Plus Documentation at AiLive
Nunchuck pass-through mode
In this mode, MotionPlus data and modified Nunchuck data are interleaved, you can retrieve one set of data every 3ms (one wm+, one nunchuck, one wm+ and so on). First 6 byte are the motion plus, send a byte 0, wait some time that WM+ retrieve and overwrite its buffer, and now read other 6 byte that are the nunchuck data. If you don't wait some time (3ms between every request), WM+ give incorrect data, mixing byte with nunchuck. The data format for the Motion Plus does not change, but the data format of the nunchuck is different than the normal way:
Bit | ||||||||
Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | SX<7:0> | |||||||
1 | SY<7:0> | |||||||
2 | AX<9:2> | |||||||
3 | AY<9:2> | |||||||
4 | AZ<9:3> | Extension connected | ||||||
5 | AZ<2:1> | AY<1> | AX<1> | BC | BZ | 0 | 0 |
Note that AZ, BC and BZ and the least significant bits of AX, AY and AZ are moved. Also, the least significant bit of each accelerometer axis are lost, consider them 0 to keep 10 bit values. Extension connected is usually 1.
Bit 1 of Byte 5 is used to determine which type of report is received : it is 1 when it contains MotionPlus Data and 0 when it contains extension data.
Classic Controller pass-through mode
In this mode, MotionPlus data and modified Classic Controller data are interleaved. The data format for the Motion Plus does not change. Here is the data format for the Classic Controller in this mode:
Bit | ||||||||
Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | RX<4:3> | LX<5:1> | BDU | |||||
1 | RX<2:1> | LY<5:1> | BDL | |||||
2 | RX<0> | LT<4:3> | RY<4:0> | |||||
3 | LT<2:0> | RT<4:0> | ||||||
4 | BDR | BDD | BLT | B- | BH | B+ | BRT | Extension connected |
5 | BZL | BB | BY | BA | BX | BZR | 0 | 0 |
Note that BDL and BDU are moved, and each axis of the left joystick loses its least significant bit. Extension connected is usually 1.
Bit 1 of Byte 5 is used to determine which type of report is received : it is 1 when it contains MotionPlus Data and 0 when it contains extension data.
Hardware
The Wii Motion Plus contains two gyro sensors: A dual-axis gyro by InvenSense, the IDG-600(pitch and roll), and a single-axis gyro by EPSON TOYOCOM labelled X3500W (yaw).
Until its release it was speculated that only a dual-axis gyro was included in the Wii Motion Plus. The combined use of a dual-axis gyro and a single-axis gyro is what enables the Wii Motion Plus to report the angular rate in all three axis, thus allowing full orientation tracking.
Specifications of the X3500W are currently unknown, but may be similar to the specifications of the similarly named XV-3500CB (same manufacturer.)
Wii MotionPlus contains RVL-GU chip and EEPROM. RVL-GU chip is a microprocessor NEC 78K0/KC2. It has two firmware modes. I2C bus repeater mode and 'Activated' Gyro mode. Wii_motion_plus_kaiseki (japanese)
T1-T4 on side A are test points for the gyros. W1-W7 on side B are test points for the RVL-GU. In some versions the ground plane has four large solderless pads on side A.
Label | RVL-GU Pin |
---|---|
W1 | Vss |
W2 | RESET |
W3 | P13/TxD6 (TOOLD) |
W4 | Vdd (tied to P15/TOH0) |
W5 | P14/RxD6 |
W6 | P122/X2/EXCLK/OCD0B |
W7 | FLMD0 (TOOLC) |
Readings
Sample readings of 0x100 bytes from 0x(4)a60000 produces the following:
Sample 1 |
---|
4a60000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4a60010: 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff
4a60020: 78 d9 78 38 77 9d 2f 0c cf f0 31 ad c8 0b 5e 39
4a60030: 6f 81 7b 89 78 51 33 60 c9 f5 37 c1 2d e9 15 8d
4a60040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a60050: b9 3f 25 93 9d 17 bb 9c 05 9d c3 38 18 3c ba 33
4a60060: ba 18 d1 7a bc 03 d3 55 32 ec 81 38 7d a6 77 a8
4a60070: 4c e6 c7 11 7c 50 78 80 77 35 08 81 f6 14 4e 67
4a60080: d4 b5 cb de 6a 54 5f 66 3c c4 25 fd 33 da 1d 75
4a60090: 58 98 15 6d 5e 63 51 ee 8f dd 3a b2 94 fe 5b 58
4a600a0: bf 17 91 78 7f 84 b4 9b b0 f9 75 c2 2e 7f 1f ed
4a600b0: e5 6b 02 f4 f2 7d 74 17 3d 23 35 5c e0 72 22 6e
4a600c0: 3b a7 7b 65 6c 3c 72 7e 5b ae e7 09 09 f0 01 00
4a600d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600f0: 55 ff ff ff ff ff ff 10 ff ff 00 00 a6 20 00 05 |
Sample 2 (Carl Kenner's Wiimote and Motion Plus) |
---|
4a60000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4a60010: 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff
4a60020: 79 83 73 54 72 E8 30 C3 CC 4A 34 FC C8 4F CC 5B
4a60030: 77 49 75 A4 73 9A 35 52 CA 22 37 26 2D E5 B5 A2
4a60040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a60050: 78 76 DD F5 6A 3C CF F7 2A 0E 32 EE 82 FE 2E FD
4a60060: 19 E7 0A CA 67 3B 3A 75 F6 45 55 8E 9D 33 CC EA
4a60070: 6E 52 C6 C6 16 9B EE 12 2E 3F 77 B1 A1 80 0B 0E
4a60080: C2 25 05 EA C3 2F 85 1E 31 53 74 C7 F1 93 F1 2D
4a60090: C1 6D 84 2A D8 6F 8A E5 2D 3B 7B CC D2 59 D5 D1
4a600A0: 9F 5B 6F AE 82 DE EA C3 73 42 06 A9 77 FF 61 A8
4a600B0: 1A 70 E4 16 90 7A 80 F7 79 4B 41 18 82 6C 62 1A
4a600C0: 3B BF FC FF 2C F2 32 97 B8 2F 17 E7 BD 35 1D 0A
4a600d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600f0: 55 ff ff ff ff ff ff 10 ff ff 00 00 a6 20 00 05 |
Sample 3 |
---|
4a60000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4a60010: 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff
4a60020: 7a 1a 79 ac 79 86 2f 2c d3 6a 2e ed c8 03 67 3c
4a60030: 6b d2 7b cf 7b 05 35 1c cd 3c 34 88 2d b6 c9 e8
4a60040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a60050: 69 cf 84 40 81 7b e2 6b 9a d7 95 c6 36 6e 98 38
4a60060: 8d 50 41 45 f5 aa 3f b6 f7 2b 6e 55 6a 72 00 f8
4a60070: 79 4f bd 5f 51 34 b5 6e f5 2e 6d fb a3 10 05 b0
4a60080: c9 c7 68 2c ef d9 e0 2c 3f ce e8 3c b8 21 61 3f
4a60090: b7 6d 18 44 07 af 5b 01 3e 1c 40 83 d3 f2 89 d0
4a600a0: 76 55 f9 ac e8 03 0a 16 f9 92 b0 59 49 69 3b 04
4a600b0: d8 d1 fe 39 b1 23 5c f7 fc 40 36 c9 34 c8 31 e7
4a600c0: f4 0d cc 4d f3 e6 f5 10 b6 1f 76 18 d1 42 32 0c
4a600d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600f0: 55 ff ff ff ff ff ff 10 ff ff 00 00 a6 20 00 05 |
Sample 4 |
---|
4a60000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4a60010: 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff
4a60020: 7c 3a 77 b1 77 e3 2f 56 d4 4b 31 13 c8 03 04 8c
4a60030: 83 ca 79 4b 7a 68 34 ef d1 2a 34 58 2d b4 12 41
4a60040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a60050: f9 f4 30 55 14 64 20 2d e3 f0 7b 30 49 dc 52 17
4a60060: 15 ab e0 78 39 2c 9a 30 6b 93 24 83 b4 88 6f 07
4a60070: 3e 94 17 b5 cf 8b 1f c8 50 a4 6a 15 49 71 99 49
4a60080: 39 5c d1 f8 43 f4 f9 a9 67 e1 7b a6 11 e5 66 7e
4a60090: fb 1c 6e 6b 97 a7 f8 6e 9f 5a c7 7b c2 7b 82 cb
4a600a0: 17 44 e3 66 ef 03 25 ea 01 36 a7 a7 08 6f bd 69
4a600b0: a5 3f 02 5c 49 00 23 89 9d 35 36 a7 31 fb eb 77
4a600c0: a5 c3 c5 d8 3d 95 4c 76 f4 74 b4 ba 5b 09 25 1f
4a600d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
4a600f0: 55 ff ff ff ff ff ff 10 ff ff 00 00 a6 20 00 05 |