Wiimote/Extension Controllers/Nunchuk
From WiiLi
The Nunchuk is the first attachment Nintendo revealed for the Wii Remote (Wiimote) at the 2005 Tokyo Game Show. It connects to the Wiimote via a long cord, and its appearance while attached resembles the nunchaku. It features an analog stick similar to the one found on the Nintendo GameCube controller and two trigger buttons. It works in tandem with the main controller in many games. Like the Wiimote, the Nunchuk controller also provides accelerometer for motion-sensing, but no rumble.
Contents |
[edit] Buttons & Sticks
Nunchuk controller features an analog stick and two trigger buttons. Since the Game Developers Conference the two shoulder buttons, formerly named Z1 and Z2 respectively, had been reshaped and renamed. The top shoulder button, now called C, is a good deal smaller than the lower shoulder button, now called Z.
[edit] Connector
The Nunchuk uses a proprietary connector. The connector have 6 pins but the cable has 4 wires only.
_______ | 1 2 3 | | | | 6 5 4 | |_-----_|
1 - green - data
2 - nothing
3 - red - 3.3+v
4 - yellow - clock
5 - nothing
6 - white - ground
[edit] Dimensions
The body of the Nunchuk controller measures 113 mm long, 38.2 mm wide, and 37.5 mm thick.
[edit] Price
One Nunchuk controller is bundled with the Wii console.
| Country | Cost |
| Japan | JP¥1,800 |
| United States | US$19.99 |
| Canada | CA$24.99 |
| Europe | €19 |
| Australia | AU$25.00 |
| United Kingdom | £14. |
[edit] Communication
Data is sent to/received from the Nunchuk by writing to/reading from address space 0x04A400xx on the Wiimote. Trying to read from/write to that address space without the Nunchuk being attached will return errorcode 7.
Before the data from the Nunchuk can be read, it is necessary to send an initialization command. This is done by writing value 0x00 to address 0x04A40040 (in the beginning it was thought that value 0x01 must be written, but this actually only makes things more complicated):
(52) 16 04 A4 00 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
It is now possible to read the Nunchuk data. It seems that Bits 8-15 (= Byte 3) of the address don't care when reading the data, so for example reading address 0x04A40000 will return the same data as reading 0x04A4FF00.
This is a hexdump of that address region from a sample Nunchuk:
04a40000: FF FF FF FF FF FF FF FF 70 73 80 71 62 0B FE FE 04a40010: FE FE FE FE FE FF FF FF FF FF FF FF FF FF FF 71 04a40020: 71 74 70 E4 8E 8F 8D EC D9 1D 72 C7 1B 74 F2 2D 04a40030: 71 74 70 E4 8E 8F 8D EC D9 1D 72 C7 1B 74 F2 2D 04a40040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400a0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400b0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400c0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400d0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400e0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400f0: 84 FE FE FE FE FE FE FE FE FE FE FE 9A 1E FE FE
The data is encrypted, but can be decrypted by applying a simple transformation to every byte:
<Decrypted byte> = (<Encrypted byte> XOR 0x17) + 0x17
It is not yet clear why this transformation is necessary. Maybe this isn't necessary if a different command is used for initialization, but for now this works.
After applying this transformation to the hexdump above, the data looks like this:
04a40000: FF FF FF FF FF FF FF FF 7E 7B AF 80 7A 3B 00 00 04a40010: 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF 7D 04a40020: 7D 7A 7E 0A B0 AF B1 12 E5 21 7C E7 23 7A FC 51 04a40030: 7D 7A 7E 0A B0 AF B1 12 E5 21 7C E7 23 7A FC 51 04a40040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a40090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400a0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400b0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400c0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400d0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400e0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04a400f0: AA 00 00 00 00 00 00 00 00 00 00 00 A4 20 00 00
This data has the following meaning:
04a40000: FF FF FF FF FF FF FF FF 7E 7B AF 80 7A 3B 00 00
-----------------
Current Nunchuk status (see below)
04a40020: 7D 7A 7E 0A B0 AF B1 12 E5 21 7C E7 23 7A FC 51
-----------------------------------------------
Calibration and other (not yet understood) data
Data is repeated at 0x04a40030
04a400f0: AA 00 00 00 00 00 00 00 00 00 00 00 A4 20 00 00
-----------------------------------------------
Meaning not yet understood, but seems to be the
same on all Nunchuks. A classic controller has
similar, yet slightly different data at this
address, so it might be some kind of device type ID
[edit] Meaning of the Nunchuk data
Six bytes define the current state of the Nunchuk. In the example above, they are
7E 7B AF 80 7A 3B
and they have the following meaning:
| Value in example | Description | Values of sample Nunchuk |
| 0x7E | X-axis value of the analog stick | Min(Full Left):0x1E / Medium(Center):0x7E / Max(Full Right):0xE1 |
| 0x7B | Y-axis value of the analog stick | Min(Full Down):0x1D / Medium(Center):0x7B / Max(Full Right):0xDF |
| 0xAF | X-axis acceleration value | Min(at 1G):0x48 / Medium(at 1G):0x7D / Max(at 1G):0xB0 |
| 0x80 | Y-axis acceleration value | Min(at 1G):0x46 / Medium(at 1G):0x7A / Max(at 1G):0xAF |
| 0x7A | Z-axis acceleration value | Min(at 1G):0x4A / Medium(at 1G):0x7E / Max(at 1G):0xB1 |
| 0x3B | Button state (Bits 0/1) / acceleration LSB | Bit 0: "Z"-Button (0 = pressed, 1 = released) / Bit 1: "C" button (0 = pressed, 1 = released) / Bits 2-3: X acceleration LSB / Bits 4-5: Y acceleration LSB / Bits 6-7: Z acceleration LSB |
As you can see, the acceleration data of the Nunchuk is encoded almost exactly like the acceleration data of the Wiimote. Except there are 2 LSB bits for each acceleration axis in the button data instead of 1.
A quick example in C to use the additional 2 LSBs:
int outbuf[6]; readData(&outbuf); int joy_x = outbuf[0]; int joy_y = outbuf[1]; int accel_x = outbuf[2] << 2 | ((outbuf[5] >> 2) & 0x03); int accel_y = outbuf[3] << 2 | ((outbuf[5] >> 4) & 0x03); int accel_z = outbuf[4] << 2 | ((outbuf[5] >> 6) & 0x03);
[edit] Calibration data
The Nunchuks calibration data is stored in a flash memory area at address 0x04A40020, and is repeated at 0x04A40030. Remember that the data needs to be decrypted using the algorithm above before it can be used. Sample data from the example above:
7D 7A 7E 0A B0 AF B1 12 E5 21 7C E7 23 7A FC 51 ----------- ----------- -------- -------- 0G values 1G values Joy X Joy Y 7D: Zero value of X-axis 7A: Zero value of Y-axis 7E: Zero value of Z-axis 0A: LSB of Zero value of X,Y,Z axes (in theory) B0: 1G value of X-axis AF: 1G value of Y-axis B1: 1G value of Z-axis 12: LSB of 1G value of X,Y,Z axes (in theory) E5: Joystick X-axis maximum 21: Joystick X-axis minimum 7C: Joystick X-axis center E7: Joystick Y-axis maximum 23: Joystick Y-axis minimum 7A: Joystick Y-axis center
Bytes 0-3 store the zero values of the X, Y and Z axis, whereas bytes 4-7 store the values at 1G (earth gravitation). This is once again similar to the way the Wiimote stores it's calibration data.
Note, I have had trouble with the built-in calibration on the Nunchuk not always returning a total force of exactly 1g when the nunchuk is still in various orientations. The +1g seems to be correct, but the -1g values I calculate don't seem accurate enough. Perhaps the zero values of the built-in calibration aren't measured very well during manufacture, or I am misinterpretting the data somehow. CarlKenner 08:36, 1 March 2007 (EST)
Bytes 8-10 store the extremes and center position for the joystick's X axis, and bytes 11-13 store the values for the Y axis.
[edit] Ways of retrieving the Nunchuk data
There are two different ways to get the current state of the Nunchuk: By polling and by getting reports. Both ways require that the Nunchuk has been initialized first.
[edit] Reports
This is probably the preferred way, as the data is automatically sent by the Wiimote, and Wiimote and Nunchuk data are both contained in one single message sent by the Wiimote.
Once the Nunchuk is initialized, reports 0x32, 0x34, 0x35, 0x36, 0x37 and 0x3D will contain the six bytes of Nunchuk data (the actual offset depends on the report ID).
Before the data can be used, it needs to be decrypted using the simple transformation algorithm mentioned above.
[edit] Polling
Nunchuk data can also be retrieved by reading 0x10 bytes starting at address 0x04A40000. In the 0x10 bytes received, the actual data will be at offset 0x8-0xD, but it seems to be impossible to start reading at address 0x04A40008 instead, as different data is returned then.
[edit] Streaming updates
If you set your report type to 0x36 or 0x37, you get nunchuck updates in the last 6 bytes of each update packet once the nunchuck is enabled. Use 0x37 to get the Wiimote buttons, accelerometer, IR sensor, and extension port all reporting in a single packet. For example, the following is a report of type 0x37 with the nunchuck attached and enabled, and the Wiimote pointing at an active sensor bar:
(A1) 3E 37 20 00 86 80 A1 11 06 65 C4 08 FF FF FF FF FF 7F 7D 2D DF 6C A6
----------- ----------------------------- -----------------
Wiimote IR sensor Nunchuck
The XOR operation must still be performed on the nunchuck data (it is the same format as 0x04A40008-0x04A4000D above). Note that, at least on my nunchuck, the Y axis of the accelerometer must be XORed with 0xB6 instead of 0x17 to get consistent data.
Note that to get the IR data in report 0x37, you need to change the IR enabling code so that it sets register 0x04B00033 to 0 instead of whatever you are currently setting it to. The IR data will then be two and a half bytes per dot. like this:
dot1x dot1y dot1extra*16+dot2extra dot2x dot2y dot3x dot3y dot3extra*16+dot4extra dot4x dot4y
The extra parts contain the high bits of the x and y coordinates. The dot size is not reported. When the dot is invisible all two and a half bytes will be set to FF FF F or F FF FF.
[edit] Direct I2C
Data can be read directly from the nunchuck cable using the I2C protocol at 400khz. A micro controller such as an Atmel Atmega168 can be used to read the data. Two bytes "0x40,0x00" must be sent to initialize the nunchuck. Then one byte "0x00" must be sent before each data request. Data is requested in 6 byte chunks. Sample code can be found at [1].
[edit] Other findings
- The classic controller is also readable using this technique.
[edit] Still unknown
- What the data starting at 0x04A400F0 means
[edit] See Also:
Linux
WiiLi Link | GameCube Linux | Artwork | Wiimux
Hardware
Wiimote (Drivers, Extension Port, Mii Data) | Wii balance board | Classic Controller | Nunchuk | GameCube Controller (Keyboard, GBA) | Nintendo DS
Bluetooth (BlueZ, Devices) | Ethernet Adapter | USB Devices | Modchips
Homebrew
GameCube | Wii | Action Replay
Specs
Wii | Comparison
File System
Wii Optical Disc | Wii Flash Memory | SD Card
GameCube Optical Disc | GameCube Memory Card

