The arduino can act as a wii controller. This means with the right hardware you can make your own drum or guitar hero controller.
A guitar hero simulator was implemented by Frank Zhao and others.
I want to start by getting two arduinos to talk to one another on I2C. One would be receiving the I2C code just like is done with the nunchuck reader.
The other would be acting as the controller.
I have made the the following hardware to try to filter the piezo element signal and make them suitable for the guitar hero simulator. On this site it is suggested that some sort of filtering is needed to condition the signal.
This is needed so that you do not get spurious drums coming from the multiple high/lows that a piezo element generates.
This is what this looks like in real life.
guitar hero software
The guitar hero software to start with is this one:
https://gitorious.org/randomstuff/arduino-wiimote/trees/master
In it a single key is simulating a button on the classic controller. The whole coding calibration etc issues are however solved. So its a cool platform to start from.
Here is an extract from the code. You can see that all that is needed is for the register bdr to be set correctly in the loop() part of the sketch.
This way you can also add the other buttons etc.
void loop() { // * If PushButton is pressed, pinRight will be LOW. This value is then inverted and given to variable "bdr", that represents D-Pad RIGHT button. bdr = !digitalRead(pinRight); delay(50); }
You can download a locally saved copy from here.
[spoiler]
/* * Sample sketch which makes the Arduino to impersonate a Classic Controller. * * Use a PushButton connected to the digital pin 2 and GND. It will trigger * a D-Pad RIGHT button press of the impersonated Classic Controller. * * Copyright (c) 2011 Peter Brinkmann (peter.brinkmann@gmail.com) * * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include // This seems redundant, but we need to declare this // dependency in the pde file or else it won't be included // in the build. #include "wiimote.h" // Classic Controller Buttons int bdl = 0; // D-Pad Left state int bdr = 0; // D-Pad Right state int bdu = 0; // D-Pad Up state int bdd = 0; // D-Pad Down state int ba = 0; // A button state int bb = 0; // B button state int bx = 0; // X button state int by = 0; // Y button state int bl = 0; // L button state int br = 0; // R button state int bm = 0; // MINUS button state int bp = 0; // PLUS button state int bhome = 0; // HOME button state int bzl = 0; // ZL button state int bzr = 0; // ZR button state /* * Analog Buttons. * They are initialized with center values from the calibration buffer. */ byte lx = calbuf[2]>>2; byte ly = calbuf[5]>>2; byte rx = calbuf[8]>>3; byte ry = calbuf[11]>>3; int pinRight = 2; // Wiimote button data stream byte *stream_callback(byte *buffer) { wiimote_write_buffer(buffer, bdl, bdr, bdu, bdd, ba, bb, bx, by, bl, br, bm, bp, bhome, lx, ly, rx, ry, bzl, bzr); return buffer; } void setup() { // Set PushButton pins as input, turning pull-up on pinMode(pinRight, INPUT); digitalWrite(pinRight, HIGH); // Prepare wiimote communications wiimote_stream = stream_callback; wiimote_init(); } void loop() { /* * If PushButton is pressed, pinRight will be LOW. * This value is then inverted and given to variable "bdr", that represents * D-Pad RIGHT button. */ bdr = !digitalRead(pinRight); delay(50); }
[/spoiler]
If you want to start from the Frank Zhao software you can use the one from his site. I also ported it to arduino.
It has not been tested but it does compile. You can also download it here. If someone wants to test it please let me know if it works.
[spoiler]
#include <string.h> #include <avr/io.h> #include <util/twi.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #define twi_port PORTC #define twi_ddr DDRC #define twi_scl_pin 5 #define twi_sda_pin 4 #define dev_detect_port PORTD #define dev_detect_ddr DDRD #define dev_detect_pin 4 unsigned char drum_id[6] = {0x01, 0x00, 0xA4, 0x20, 0x01, 0x03}; // drum id unsigned char guitar_id[6] = {0x00, 0x00, 0xA4, 0x20, 0x01, 0x03}; // GH3 id unsigned char nunchuk_id[6] = {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}; // nunchuck id unsigned char classic_id[6] = {0x00, 0x00, 0xA4, 0x20, 0x01, 0x01}; // classic controller id // crypto data // should all be declared as 'volatile' because they are access in an interrupt handler volatile unsigned char wm_rand[10]; volatile unsigned char wm_key[6]; volatile unsigned char wm_ft[8]; volatile unsigned char wm_sb[8]; // virtual register volatile unsigned char twi_reg[256]; volatile unsigned int twi_reg_addr; volatile unsigned char twi_first_addr_flag; // set address flag volatile unsigned char twi_rw_len; // length of most recent operation
// initialize wiimote interface with id, starting data, and calibration data void wm_init(unsigned char *, unsigned char *, unsigned char *, void (*)(void)); // set button data void wm_newaction(unsigned char *); // pointer to user function static void (*wm_sample_event)(); void twi_slave_init(unsigned char); void twi_clear_int(unsigned char); void wm_slaveTxStart(unsigned char); void wm_slaveRx(unsigned char, unsigned char); void wm_timer_inc(); /* From Frank Zhao: I'd like to thank Hector Martin for posting his encryption method! His website is http://www.marcansoft.com/ Decryption method found at http://www.derkeiler.com/pdf/Newsgroups/sci.crypt/2008-11/msg00110.pdf */ unsigned char wm_ror8(unsigned char, unsigned char); voidwm_gentabs();
/* Widely copied on the Internet */ char wm_ext_encode_byte (char); char wm_ext_decode_byte (char); unsigned char ans_tbl[7][6] PROGMEM = { {0xA8,0x77,0xA6,0xE0,0xF7,0x43 }, {0x5A,0x35,0x85,0xE2,0x72,0x97 }, {0x8F,0xB7,0x1A,0x62,0x87,0x38 }, {0xD,0x67,0xC7,0xBE,0x4F,0x3E }, {0x20,0x76,0x37,0x8F,0x68,0xB7 }, {0xA9,0x26,0x3F,0x2B,0x10,0xE3 }, {0x30,0x7E,0x90, 0xE,0x85, 0xA }, }; unsigned char sboxes[10][256] PROGMEM = { { 0x70,0x51, 3,0x86,0x40, 0xD,0x4F,0xEB,0x3E,0xCC,0xD1,0x87,0x35,0xBD,0xF5, 0xB, 0x5E,0xD0,0xF8,0xF2,0xD5,0xE2,0x6C,0x31, 0xC,0xAD,0xFC,0x21,0xC3,0x78,0xC1, 6, 0xC2,0x4C,0x55,0xE6,0x4A,0x34,0x48,0x11,0x1E,0xDA,0xE7,0x1A,0x84,0xA0,0x96,0xA7, 0xE3,0x7F,0xAF,0x63,0x9C,0xFA,0x23,0x5B,0x79,0xC8,0x9E,0xBA,0xB2,0xC9,0x22,0x12,
0x4B,0xB3,0xA1,0xB6,0x32,0x49,0xA2,0xE1,0x89,0x39,0x10,0x66,0xC5, 7,0x8F,0x54, 0xEA,0x91,0xCA,0x3F,0xF9,0x19,0xF0,0xD7,0x46,0xBC,0x28,0x1B,0x61,0xE8,0x2F,0x6A, 0xAE,0x9D,0xF6,0x4E, 9,0x14,0x77,0x4D,0xDB,0x1F,0x2E,0x7B,0x7C,0xF1,0x43,0xA3, 0,0xB8,0x13,0x8C,0x85,0xB9,0x29,0x75,0x88,0xFD,0xD2,0x56,0x1C,0x50,0x97,0x41, 0xE5,0x3B,0x60,0xB5,0xC0,0x64,0xEE,0x98,0xD6,0x2D,0x25,0xA4,0xAA,0xCD,0x7D,0xA8, 0x83,0xC6,0xAB,0xBE,0x44,0x99,0x26,0x3C,0xCE,0x9F,0xBF,0xD3,0xCB,0x76,0x7A,0x7E, 0x82, 1,0x8A,0x9A,0x80,0x1D, 0xE,0xB0,0x5C,0xD4,0x38,0x62,0xF4,0x30,0xE0,0x8E, 0x53,0xB7, 2,0x57,0xAC,0xA6,0x52, 0xA,0x6D,0x92,0x65,0x17,0x24,0x33,0x45,0x72, 0x74,0xB1,0xB4,0xF7,0x5D,0xED,0x2C,0xFF,0x47,0x37,0x5A,0x90,0xBB,0xDF,0x2A,0x16, 0x59,0x95,0xD9,0xC4,0x27,0x67,0x73,0xC7,0x68,0xFE,0xA5,0xDD,0x6B,0x5F,0x93,0xD8, 0xEC, 5,0x3A,0x8D,0x6E,0xFB,0x3D,0xA9,0x69,0x36,0xF3,0x94,0xDE,0xEF,0x15,0x6F,
0x8B,0x9B, 8, 0xF,0xDC,0x81,0x18,0x20, 4,0xE4,0x71,0xCF,0xE9,0x2B,0x42,0x58, } , { 1,0xA0,0xA9,0x62,0xD6,0x3F,0x85,0xA7,0xB6,0xD4,0xFA,0x15,0x66,0x17, 9,0xBD, 0x5D,0x14,0x34,0x26,0x59,0x72,0x91,0x54, 6,0x4F,0xF8,0xB0,0x5B,0x74,0x93,0x99, 0x8C,0xF2,0x45,0xCD,0xEA,0x4E,0xAD,0x10,0x4A,0xE5,0xCA,0xEE,0xDF,0xC6,0x6F,0x9F, 0x88,0x8E, 2,0xCC, 8,0xA8,0x77,0x94,0x6D,0x21,0xB1,0x28,0xE4,0x39,0x79,0x96, 0x60,0x71,0x81,0x16,0x2E,0xE6,0x78,0xB9,0xC4,0x46,0x9A,0x42,0xAE,0xB7,0x7C,0x43, 0xB3,0x22,0x1A,0x86,0xC2,0x32,0x3D,0x2D,0x9C,0xD2,0x29,0xE9,0x63,0x9B,0xD1,0x31, 0x38,0x5E,0x1E,0x36,0x41,0xBB, 3,0x18,0x2B,0x3E,0xBF,0x68,0x61,0xFC,0x52,0xC0, 0xDE,0xE0, 0xA,0x58,0x13,0x5A, 0,0xBE,0x1C,0x90, 0xE,0x53,0x12,0xFD,0xE2,0x6E, 0xBA,0xCE,0x24,0x27,0x44,0x7F,0x87,0xA3,0xA1,0xD5,0x50,0x40,0xE3,0xF9,0x83,0xF7, 0xC7,0xA2,0x35,0xC8,0xDB,0x19,0xAB,0x2F,0x11,0x25,0xED,0x33,0x9E,0x55,0xE1,0x48, 0xAF,0x73,0x84,0xDA,0x2A,0xAA,0x51,0xEB,0x9D,0x95,0xB2,0xCB,0xE7,0x70,0x80,0xFE, 0x4C,0x65, 4,0xEF,0xC5,0xF1,0xC3,0x3A,0xB4,0xF5,0x5F,0x23,0x89,0xDD,0x30,0xA5,
0x8B,0xD3,0xF6,0xDC,0x4D,0x64,0xD7,0xF0,0x8F,0xEC,0x56,0x37,0x5C,0xA4, 0xD, 7, 0x76,0x8A,0x2C, 0xB,0xB5,0xD8,0xC1,0x1F,0xE8,0x3B,0xF4,0x4B,0x1B,0x47,0x6C,0x49, 0x67,0x7B,0x92,0xCF,0x75,0x7E,0x20,0xD9,0x7D,0x3C,0x97,0x7A,0xD0, 5,0x6B, 0xF, 0x1D,0xFB,0x82,0x98,0x57,0x8D,0xF3,0x6A,0xBC,0xAC,0xC9,0xA6,0xFF,0xB8,0x69, 0xC, } , { 0x4C,0x4D,0x72, 7,0x5A,0x49,0x33,0x8D,0xA2,0xAB,0x46,0x3D,0x63, 0xD,0xA0,0x97, 0xFF,0xF0,0xF5,0xFA,0xC0,0xE9,0xDB,0x62,0xE4,0xE1,0x74,0x43,0xDC,0x86,0x18,0x29, 0x37,0xF4, 6,0xE2,0xED,0x6F,0x90,0x48,0x1E,0x2D,0x1D,0xEA,0x73,0x94,0x54,0xDF, 0x25,0xF6,0x47,0x27,0xD9,0x11,0x77,0xC9,0x84,0x1C,0x5B,0x5C,0x51,0x81,0xA6,0x22, 0x3E,0x24,0x96,0xC8,0x8A,0xEC,0x82,0x7C, 9,0xB8,0x45,0x4A,0x57,0xBB,0x2F,0x50, 0x75,0x8E,0x61,0x70,0x8C,0x6C,0xAF,0xD0,0xFD,0xB4,0x1B,0xAE,0xDE,0xFE,0x3B,0xB5, 0x36,0xBD,0x55, 1, 0xE,0x9C,0x41,0x56,0x5F,0xB3,0x26, 3,0x83,0xBA,0x13,0x4B, 0xCA,0xC5, 0xA,0xF8,0x60,0xA5,0xB9,0xC7,0xC3,0x98,0x32,0xFB,0x12,0xF9,0xA7,0x92, 0xAA,0x68,0xF3,0x78,0x7E, 5,0x20,0x21, 2,0xE8,0xBF,0xF2,0xB0,0x59,0x8F,0xD2,
0xCB,0x87,0x65,0x15,0xF1,0x1A,0xB2,0x30,0xAD,0xEE,0x58,0xA3,0x8B,0x66,0x1F,0x2C, 0xD7,0x5D,0x19,0x85,0xA8,0xE6,0xD3,0x6B,0xA1, 0xC,0x91,0x93,0x6A,0x5E, 0xB,0x79, 0xE3,0xDD, 0,0x4F,0x3C,0x89,0x6E,0x71,0x69,0xA9,0xAC,0x40,0xE5,0x99,0x28,0xC6, 0x31,0x4E,0x7A,0xCD, 8,0x9E,0x7D,0xEF,0x17,0xFC,0x88,0xD8,0xA4,0x6D,0x44,0x95, 0xD1,0xB7,0xD4,0x9B,0xBE,0x2A,0x34,0x64,0x2B,0xCF,0x2E,0xEB,0x38,0xCE,0x23,0xE0, 0x3A,0x3F,0xF7,0x7B,0x9F,0x10,0x53,0xBC,0x52,0x67,0x16,0xE7,0x80,0x76, 4,0xC4, 0xB6,0xC1,0xC2,0x7F,0x9A,0xDA,0xD5,0x39,0x42,0x14,0x9D,0xB1, 0xF,0x35,0xD6,0xCC, } , { 0xB9,0xDA,0x38, 0xC,0xA2,0x9C, 9,0x1F, 6,0xB1,0xB6,0xFD,0x1A,0x69,0x23,0x30, 0xC4,0xDE, 1,0xD1,0xF4,0x58,0x29,0x37,0x1C,0x7D,0xD5,0xBF,0xFF,0xBD,0xC8,0xC9, 0xCF,0x65,0xBE,0x7B,0x78,0x97,0x98,0x67, 8,0xB3,0x26,0x57,0xF7,0xFA,0x40,0xAD,
0x8E,0x75,0xA6,0x7C,0xDB,0x91,0x8B,0x51,0x99,0xD4,0x17,0x7A,0x90,0x8D,0xCE,0x63, 0xCB,0x4E,0xA0,0xAB,0x18,0x3A,0x5B,0x50,0x7F,0x21,0x74,0xC1,0xBB,0xB8,0xB7,0xBA, 0xB,0x35,0x95,0x31,0x59,0x9A,0x4D, 4, 7,0x1E,0x5A,0x76,0x13,0xF3,0x71,0x83, 0xD0,0x86, 3,0xA8,0x39,0x42,0xAA,0x28,0xE6,0xE4,0xD8,0x5D,0xD3,0xD0,0x6E,0x6F, 0x96,0xFB,0x5E,0xBC,0x56,0xC2,0x5F,0x85,0x9B,0xE7,0xAF,0xD2,0x3B,0x84,0x6A,0xA7, 0x53,0xC5,0x44,0x49,0xA5,0xF9,0x36,0x72,0x3D,0x2C,0xD9,0x1B,0xA1,0xF5,0x4F,0x93, 0x9D,0x68,0x47,0x41,0x16,0xCA,0x2A,0x4C,0xA3,0x87,0xD6,0xE5,0x19,0x2E,0x77,0x15, 0x6D,0x70,0xC0,0xDF,0xB2, 0,0x46,0xED,0xC6,0x6C,0x43,0x60,0x92,0x2D,0xA9,0x22, 0x45,0x8F,0x34,0x55,0xAE,0xA4, 0xA,0x66,0x32,0xE0,0xDC, 2,0xAC,0xE8,0x20,0x8C, 0x89,0x62,0x4A,0xFE,0xEE,0xC3,0xE3,0x3C,0xF1,0x79, 5,0xE9,0xF6,0x27,0x33,0xCC, 0xF2,0x9E,0x11,0x81,0x7E,0x80,0x10,0x8A,0x82,0x9F,0x48, 0xD,0xD7,0xB4,0xFC,0x2F,
0xB5,0xC7,0xDD,0x88,0x14,0x6B,0x2B,0x54,0xEA,0x1D,0x94,0x5C,0xB0,0xEF,0x12,0x24, 0xCD,0xEB,0xE1,0xE2,0x64,0x73,0x3F, 0xE,0x52,0x61,0x25,0x3E,0xF8, 0xF,0x4B,0xEC, } , { 0xC0, 0,0x30,0xF6, 2,0x49,0x3D,0x10,0x6E,0x20,0xC9,0xA6,0x2F,0xFE,0x2C,0x2B, 0x75,0x2E,0x45,0x26,0xAB,0x48,0xA9,0x80,0xFC, 4,0xCC,0xD3,0xB5,0xBA,0xA3,0x38, 0x31,0x7D, 1,0xD9,0xA7,0x7B,0x96,0xB6,0x63,0x69,0x4E,0xF7,0xDE,0xE0,0x78,0xCA, 0x50,0xAA,0x41,0x91,0x65,0x88,0xE4,0x21,0x85,0xDA,0x3A,0x27,0xBE,0x1C,0x3E,0x42, 0x5E,0x17,0x52,0x7F,0x1F,0x89,0x24,0x6F,0x8F,0x5C,0x67,0x74, 0xE,0x12,0x87,0x8D, 0xE9,0x34,0xED,0x73,0xC4,0xF8,0x61,0x5B, 5,0xDF,0x59,0x4C,0x97,0x79,0x83,0x18, 0xA4,0x55,0x95,0xEB,0xBD,0x53,0xF5,0xF1,0x57,0x66,0x46,0x9F,0xB2,0x81, 9,0x51,
0x86,0x22,0x16,0xDD,0x23,0x93,0x76,0x29,0xC2,0xD7,0x1D,0xD4,0xBF,0x36,0x3F,0xEA, 0x4B,0x11,0x32,0xB9,0x62,0x54,0x60,0xD6,0x6D,0x43,0x9A, 0xD,0x92,0x9C,0xB0,0xEF, 0x58,0x6C,0x9D,0x77,0x2D,0x70,0xFA,0xF3,0xB3, 0xB,0xE2,0x40,0x7E,0xF4,0x8A,0xE5, 0x8C,0x3C,0x56,0x71,0xD1,0x64,0xE1,0x82, 0xA,0xCB,0x13,0x15,0x90,0xEC, 3,0x99, 0xAF,0x14,0x5D, 0xF,0x33,0x4A,0x94,0xA5,0xA8,0x35,0x1B,0xE3,0x6A,0xC6,0x28,0xFF, 0x4D,0xE7,0x25,0x84,0xAC, 8,0xAE,0xC5,0xA2,0x2A,0xB8,0x37, 0xC,0x7A,0xA0,0xC3, 0xCE,0xAD, 6,0x1A,0x9E,0x8B,0xFB,0xD5,0xD0,0xC1,0x1E,0xD0,0xB4,0x9B,0xB1,0x44, 0xF2,0x47,0xC7,0x68,0xCF,0x72,0xBB,0x4F,0x5A,0xF9,0xDC,0x6B,0xDB,0xD2,0xE8,0x7C, 0xC8,0xEE,0x98,0xA1,0xE6,0xD8,0x39, 7,0x5F,0xFD,0x8E,0x19,0xB7,0x3B,0xBC,0xCD, } , { 0x7C,0xE3,0x81,0x73,0xB2,0x11,0xBF,0x6F,0x20,0x98,0xFE,0x75,0x96,0xEF,0x6C,0xDA, 0x50,0xE1, 9,0x72,0x54,0x45,0xBA,0x34,0x80,0x5B,0xED,0x3E,0x53,0x2C,0x87,0xA4, 0x57,0xF3,0x33,0x3F,0x3C,0xB7,0x67,0xB4,0xA3,0x25,0x60,0x4F, 7,0x6B,0x1B,0x47, 0x15, 0xF,0xE4, 0xA,0xEA,0xD1,0x32,0x78,0x36,0x49,0x8D,0x4B,0xD2,0xBC,0xA5,0xDC, 0x1D, 0xD,0x4D,0xCD,0x9A,0x82,0x5F,0xFC,0x94,0x65,0xBE,0xE2,0xF4,0xC9,0x1E,0x44, 0xCB,0x9E, 0xC,0x64,0x71,0x26,0x63,0xB3,0x14,0xE8,0x40,0x70,0x8A, 0xE,0x19,0x42, 0x6D,0xAC,0x88,0x10,0x5C,0xDF,0x41,0xA9,0xAD,0xE5,0xFB,0x74,0xCC,0xD5, 6,0x8E, 0x59,0x86,0xCE,0x1F,0x3D,0x76,0xE0,0x8F,0xB9,0x77,0x27,0x7B,0xA6,0xD8,0x29,0xD3,
0xEC,0xB8,0x13,0xF7,0xFA,0xC3,0x51,0x6A,0xDE,0x4A,0x5A,0xEB,0xC2,0x8B,0x23,0x48, 0x92,0xCF,0x62,0xA8,0x99,0xF8,0xD0,0x2E,0x85,0x61,0x43,0xC8,0xBD,0xF0, 5,0x93, 0xCA,0x4E,0xF1,0x7D,0x30,0xFD,0xC4,0x69,0x66,0x2F, 8,0xB1,0x52,0xF9,0x21,0xE6, 0x7A,0x2B,0xDD,0x39,0x84,0xFF,0xC0,0x91,0xD6,0x37,0xD4,0x7F,0x2D,0x9B,0x5D,0xA1, 0x3B,0x6E,0xB5,0xC5,0x46, 4,0xF5,0x90,0xEE,0x7E,0x83,0x1C, 3,0x56,0xB6,0xAA, 0,0x17, 1,0x35,0x55,0x79, 0xB,0x12,0xBB,0x1A,0x31,0xE7, 2,0x28,0x16,0xC1, 0xF6,0xA2,0xDB,0x18,0x9C,0x89,0x68,0x38,0x97,0xAB,0xC7,0x2A,0xD7,0x3A,0xF2,0xC6, 0x24,0x4C,0xB0,0x58,0xA0,0x22,0x5E,0x9D,0xD9,0xA7,0xE9,0xAE,0xAF,0x8C,0x95,0x9F, } , { 0x28,0xB7,0x20,0xD7,0xB0,0x30,0xC3, 9,0x19,0xC0,0x67,0xD6, 0,0x3C,0x7E,0xE7, 0xE9,0xF4, 8,0x5A,0xF8,0xB8,0x2E, 5,0xA6,0x25,0x9E,0x5C,0xD8,0x15, 0xD,0xE1, 0xF6,0x11,0x54,0x6B,0xCD,0x21,0x46,0x66,0x5E,0x84,0xAD, 6,0x38,0x29,0x44,0xC5, 0xA2,0xCE,0xF1,0xAA,0xC1,0x40,0x71,0x86,0xB5,0xEF,0xFC,0x36,0xA8,0xCB, 0xA,0x48, 0x27,0x45,0x64,0xA3,0xAF,0x8C,0xB2,0xC6,0x9F, 7,0x89,0xDC,0x17,0xD3,0x49,0x79, 0xFB,0xFE,0x1D,0xD0,0xB9,0x88,0x43,0x52,0xBC, 1,0x78,0x2B,0x7D,0x94,0xC7, 0xE, 0xDE,0xA5,0xD5,0x9B,0xCC,0xF7,0x61,0x7A,0xC2,0x74,0x81,0x39, 3,0xAB,0x96,0xA0, 0x37,0xBD,0x2D,0x72,0x75,0x3F,0xC9,0xD4,0x8E,0x6F,0xF9,0x8D,0xED,0x62,0xDB,0x1C, 0xDF, 4,0xAC,0x1B,0x6C,0x14,0x4B,0x63,0xD0,0xBF,0xB4,0x82,0xEC,0x7B,0x1A,0x59, 0x92,0xD2,0x10,0x60,0xB6,0x3D,0x5F,0xE6,0x80,0x6E,0x70,0xC4,0xF2,0x35,0xD9,0x7C, 0xEE,0xE5,0x41,0xA4,0x5B,0x50,0xDD,0xBB,0x4C,0xF3,0x1F,0x9D,0x5D,0x57,0x55,0x51,
0x97,0xE3,0x58,0x42,0x4D,0x9C,0x73,0xBA,0xC8,0x77,0x31,0x69,0x26,0xAE,0xEA,0x8A, 0xDA,0x22,0xB3,0x87,0x56,0xFA,0x93, 0xB,0x34,0x16,0x33,0xE8,0xE4,0x53,0xBE,0xA9, 0xB1,0x3A,0x3E,0xF5,0x90,0x6A,0xCF,0x3B,0x12,0xFD,0x8F,0x9A,0xA7,0x47,0x91,0x99, 0xEB, 0xF,0x24,0xFF,0x23,0x18,0x85,0x4E,0x7F, 0xC,0xE0,0xA1,0xD2,0xD1,0x2C,0x2A, 0x4A, 2,0x4F,0x1E,0x95,0x68,0x8B,0x98,0x83,0x6D,0x76,0xCA,0x65,0x32,0x13,0x2F, } , { 0xC3,0x82,0x9A,0xA4,0xBA,0x81,0x60,0x37,0x34,0x35,0xFC,0x80,0xA8,0x51,0x65,0x67, 0xED,0x30,0x5F,0x10,0xD3,0x4A,0x27,0x2F,0x13,0xB9,0x2A,0xD2,0xCC,0xE1,0xEF,0xAE, 0xEB,0xBE,0xF4,0xBD,0xCF,0x43,0xB3,0xC5,0x88,0x84,0xB7,0xDD,0x39,0x40,0xCE,0x48, 0x6D,0x9B,0x72,0x61,0x7E,0xE7,0xA1,0x4E,0x53,0x2E,0x77,0x3B,0xE2,0xC9,0x36,0x22,
0x1B,0x6E,0x73,0xB1, 3,0xB2,0x4C,0x87,0xA9,0xD4,0x4D, 0xF,0xD8,0x15,0x6C,0xAA, 0x18,0xF6,0x49,0x57,0x5D,0xFB,0x7A,0x14,0x94,0x63,0xA0,0x11,0xB0,0x9E,0xDE, 5, 0x46,0xC8,0xEE,0x47,0xDB,0xDC,0x24,0x89,0x9C,0x91,0x97,0x29,0xE9,0x7B,0xC1, 7, 0x1E,0xB8,0xFD,0xFE,0xAC,0xC6,0x62,0x98,0x4F,0xF1,0x79,0xE0,0xE8,0x6B,0x78,0x56, 0xB6,0x8D, 4,0x50,0x86,0xCA,0x6F,0x20,0xE6,0xEA,0xE5,0x76,0x17,0x1C,0x74,0x7F, 0xBC, 0xD,0x2C,0x85,0xF7,0x66,0x96,0xE4,0x8B,0x75,0x3F,0x4B,0xD9,0x38,0xAF,0x7C, 0xDA, 0xB,0x83,0x2D,0x31,0x32,0xA2,0xF5,0x1D,0x59,0x41,0x45,0xBF,0x3C,0x1F,0xF8, 0xF9,0x8A,0xD0,0x16,0x25,0x69,0x12,0x99,0x9D,0x21,0x95,0xAB, 1,0xA6,0xD7,0xB5, 0xC0,0x7D,0xFF,0x58, 0xE,0x3A,0x92,0xD1,0x55,0xE3, 8,0x9F,0xD6,0x3E,0x52,0x8E, 0xFA,0xA3,0xC7, 2,0xCD,0xDF,0x8F,0x64,0x19,0x8C,0xF3,0xA7, 0xC,0x5E, 0xA,0x6A, 9,0xF0,0x93,0x5B,0x42,0xC2, 6,0x23,0xEC,0x71,0xAD,0xB4,0xCB,0xBB,0x70,0x28,
0xD5,0x1A,0x5C,0x33,0x68,0x5A, 0,0x44,0x90,0xA5,0xC4,0x26,0x3D,0x2B,0xF2,0x54, } , { 0x96,0xAD,0xDA,0x1F,0xED,0x33,0xE1,0x81,0x69, 8, 0xD, 0xA,0xDB,0x35,0x77,0x9A, 0x64,0xD1,0xFC,0x78,0xAA,0x1B,0xD0,0x67,0xA0,0xDD,0xFA,0x6C,0x63,0x71, 5,0x84, 0x17,0x6A,0x89,0x4F,0x66,0x7F,0xC6,0x50,0x55,0x92,0x6F,0xBD,0xE7,0xD2,0x40,0x72, 0x8D,0xBB,0xEC, 6,0x42,0x8A,0xE4,0x88,0x9D,0x7E,0x7A,0x82,0x27,0x13,0x41,0x1A, 0xAF,0xC8,0xA4,0x76,0xB4,0xC2,0xFE,0x6D,0x1C,0xD9,0x61,0x30,0xB3,0x7C,0xEA,0xF7, 0x29, 0xF,0xF2,0x3B,0x51,0xC1,0xDE,0x5F,0xE5,0x2A,0x2F,0x99, 0xB,0x5D,0xA3,0x2B, 0x4A,0xAB,0x95,0xA5,0xD3,0x58,0x56,0xEE,0x28,0x31, 0,0xCC,0x15,0x46,0xCA,0xE6, 0x86,0x38,0x3C,0x65,0xF5,0xE3,0x9F,0xD6,0x5B, 9,0x49,0x83,0x70,0x2D,0x53,0xA9, 0x7D,0xE2,0xC4,0xAC,0x8E,0x5E,0xB8,0x25,0xF4,0xB9,0x57,0xF3,0xF1,0x68,0x47,0xB2, 0xA2,0x59,0x20,0xCE,0x34,0x79,0x5C,0x90, 0xE,0x1E,0xBE,0xD5,0x22,0x23,0xB1,0xC9, 0x18,0x62,0x16,0x2E,0x91,0x3E, 7,0x8F,0xD8,0x3F,0x93,0x3D,0xD4,0x9B,0xDF,0x85,
0x21,0xFB,0x11,0x74,0x97,0xC7,0xD7,0xDC,0x4C,0x19,0x45,0x98,0xE9,0x43, 2,0x4B, 0xBC,0xC3, 4,0x9C,0x6B,0xF0,0x75,0x52,0xA7,0x26,0xF6,0xC5,0xBA,0xCF,0xB0,0xB7, 0xAE,0x5A,0xA1,0xBF, 3,0x8B,0x80,0x12,0x6E, 0xC,0xEB,0xF9,0xC0,0x44,0x24,0xEF, 0x10,0xF8,0xA8,0x8C,0xE8,0x7B,0xFF,0x9E,0x2C,0xCD,0x60,0x36,0x87,0xB5,0x94,0xA6, 0x54,0x73,0x3A,0x14,0x4E, 1,0x1D,0xB6,0xFD,0x37,0x48,0x4D,0x39,0xCB,0xE0,0x32, } }; // begin FZ's original work void twi_slave_init(unsigned char addr) { // initialize stuff twi_reg_addr = 0; // set slave address (guitar hero or other) TWAR = addr << 1; // enable twi module, acks, and twi interrupt TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); // enable interrupts sei(); } void twi_clear_int(unsigned char ack) { // get ready by clearing interrupt, with or without ack if(ack != 0) { TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); } else { TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); } } /* The 'encode' and 'decode' functions have been so widely copied on the Internet that it is impossible to attribute correctly.
Refer to http://wiibrew.org/wiki/Wiimote/Extension_Controllers for details on why this works for Nintendo controllers */ // Encode/Decode data to format that most wiimote drivers except // only needed if you use one of the regular wiimote drivers char wm_ext_decode_byte (char x) { x = (x ^ 0x17) + 0x17; return x; } char wm_ext_encode_byte (char x) { x = x - 0x17; x = (x ^ 0x17); return x; } /* From Frank Zhao: I'd like to thank Hector Martin for posting his encryption method! His website is http://www.marcansoft.com/ Decryption method found at http://www.derkeiler.com/pdf/Newsgroups/sci.crypt/2008-11/msg00110.pdf */ unsigned char wm_ror8(unsigned char a, unsigned char b) { // bit shift with roll-over return (a >> b) | ((a << (8 - b)) & 0xFF); } void wm_gentabs() { unsigned char idx; // check all idx for(idx = 0; idx < 7; idx++) { // generate test key unsigned char ans[6]; unsigned char tkey[6]; unsigned char t0[10]; for(unsigned char i = 0; i < 6; i++) { ans[i] = pgm_read_byte(&(ans_tbl[idx][i])); } for(unsigned char i = 0; i < 10; i++) { t0[i] = pgm_read_byte(&(sboxes[0][wm_rand[i]])); } tkey[0] = ((wm_ror8((ans[0] ^ t0[5]), (t0[2] % 8)) - t0[9]) ^ t0[4]); tkey[1] = ((wm_ror8((ans[1] ^ t0[1]), (t0[0] % 8)) - t0[5]) ^ t0[7]); tkey[2] = ((wm_ror8((ans[2] ^ t0[6]), (t0[8] % 8)) - t0[2]) ^ t0[0]); tkey[3] = ((wm_ror8((ans[3] ^ t0[4]), (t0[7] % 8)) - t0[3]) ^ t0[2]); tkey[4] = ((wm_ror8((ans[4] ^ t0[1]), (t0[6] % 8)) - t0[3]) ^ t0[4]); tkey[5] = ((wm_ror8((ans[5] ^ t0[7]), (t0[8] % 8)) - t0[5]) ^ t0[9]);
// compare with actual key // TJM void* cast if(memcmp(tkey, (void*)wm_key, 6) == 0) break; // if match, then use this idx } // generate encryption from idx key and rand wm_ft[0] = pgm_read_byte(&(sboxes[idx + 1][wm_key[4]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[3]])); wm_ft[1] = pgm_read_byte(&(sboxes[idx + 1][wm_key[2]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[5]])); wm_ft[2] = pgm_read_byte(&(sboxes[idx + 1][wm_key[5]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[7]])); wm_ft[3] = pgm_read_byte(&(sboxes[idx + 1][wm_key[0]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[2]]));
wm_ft[4] = pgm_read_byte(&(sboxes[idx + 1][wm_key[1]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[4]])); wm_ft[5] = pgm_read_byte(&(sboxes[idx + 1][wm_key[3]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[9]])); wm_ft[6] = pgm_read_byte(&(sboxes[idx + 1][wm_rand[0]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[6]])); wm_ft[7] = pgm_read_byte(&(sboxes[idx + 1][wm_rand[1]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[8]])); wm_sb[0] = pgm_read_byte(&(sboxes[idx + 1][wm_key[0]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[1]])); wm_sb[1] = pgm_read_byte(&(sboxes[idx + 1][wm_key[5]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[4]])); wm_sb[2] = pgm_read_byte(&(sboxes[idx + 1][wm_key[3]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[0]])); wm_sb[3] = pgm_read_byte(&(sboxes[idx + 1][wm_key[2]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[9]])); wm_sb[4] = pgm_read_byte(&(sboxes[idx + 1][wm_key[4]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[7]])); wm_sb[5] = pgm_read_byte(&(sboxes[idx + 1][wm_key[1]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[8]]));
wm_sb[6] = pgm_read_byte(&(sboxes[idx + 1][wm_rand[3]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[5]])); wm_sb[7] = pgm_read_byte(&(sboxes[idx + 1][wm_rand[2]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[6]])); } void wm_slaveTxStart(unsigned char addr) { if(addr >= 0x00 && addr < 0x06) { // call user event wm_sample_event(); } } void wm_slaveRx(unsigned char addr, unsigned char l) { // if guitar hero encryption data is sent, store them accordingly if(addr >= 0x40 && addr < 0x46) { for(unsigned int i = 0; i < 6; i++) { wm_rand[9 - i] = twi_reg[0x40 + i]; } } else if(addr >= 0x46 && addr < 0x4C) { for(unsigned int i = 6; i < 10; i++) { wm_rand[9 - i] = twi_reg[0x40 + i]; } for(unsigned int i = 0; i < 2; i++) { wm_key[5 - i] = twi_reg[0x40 + 10 + i]; } } else if(addr >= 0x4C && addr < 0x50) { for(unsigned int i = 2; i < 6; i++) { wm_key[5 - i] = twi_reg[0x40 + 10 + i]; } if(addr + l == 0x50) { // generate decryption once all data is loaded wm_gentabs(); } } } void wm_newaction(unsigned char * d) { // load button data from user application // TJM: void* cast memcpy((void*)twi_reg, d, 6); } void wm_init(unsigned char * id, unsigned char * t, unsigned char * cal_data, void (*function)(void)) { // int encrypt = 1; // link user function wm_sample_event = function; // start state wm_newaction(t); // FIXME: encryption // if (encrypt) { twi_reg[0xF0] = 0xAA; // } else { // twi_reg[0xF0] = 0; // disable encryption // }
int numIdBytes = 6; unsigned int idAddrRegStart = 0xFA; for(unsigned int i = 0, j = idAddrRegStart; i < numIdBytes; i++, j++) { // FIXME: encryption // if (encrypt) { twi_reg[j] = wm_ext_encode_byte(id[i]); // } else { // twi_reg[j] = id[i]; // } }
// set calibration data for(unsigned int i = 0, j = 0x20; i < 6; i++, j++) { // if (encrypt) { twi_reg[j] = wm_ext_encode_byte(cal_data[i]); // } else { // twi_reg[j] = cal_data[i]; // } } // initialize device detect pin dev_detect_port &= 0xFF ^ _BV(dev_detect_pin); dev_detect_ddr |= _BV(dev_detect_pin); delay(500); // delay to simulate disconnect // TJM was _delay_ms(500) // ready twi bus, no pull-ups twi_port &= 0xFF ^ _BV(twi_scl_pin); twi_port &= 0xFF ^ _BV(twi_sda_pin); // start twi slave, link events twi_slave_init(0x52); // make the wiimote think something is connected dev_detect_port |= _BV(dev_detect_pin); } ISR(TWI_vect) { switch(TW_STATUS) { // Slave Rx case TW_SR_SLA_ACK: // addressed, returned ack case TW_SR_GCALL_ACK: // addressed generally, returned ack case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration generally, returned ack // get ready to receive pointer twi_first_addr_flag = 0; // ack twi_clear_int(1); break; case TW_SR_DATA_ACK: // data received, returned ack case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack if(twi_first_addr_flag != 0) { // put byte in register unsigned char t = TWDR; if(twi_reg[0xF0] == 0xAA && twi_reg_addr != 0xF0) // if encryption is on
{ // decrypt twi_reg[twi_reg_addr] = (t ^ wm_sb[twi_reg_addr % 8]) + wm_ft[twi_reg_addr % 8]; } else { twi_reg[twi_reg_addr] = t; } twi_reg_addr++; twi_rw_len++; } else { // set address twi_reg_addr = TWDR; twi_first_addr_flag = 1; twi_rw_len = 0; } twi_clear_int(1); // ack break; case TW_SR_STOP: // stop or repeated start condition received
// run user defined function wm_slaveRx(twi_reg_addr - twi_rw_len, twi_rw_len); twi_clear_int(1); // ack future responses break; case TW_SR_DATA_NACK: // data received, returned nack case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack twi_clear_int(0); // nack back at master break; // Slave Tx case TW_ST_SLA_ACK: // addressed, returned ack case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack // run user defined function wm_slaveTxStart(twi_reg_addr); twi_rw_len = 0; case TW_ST_DATA_ACK: // byte sent, ack returned // ready output byte if(twi_reg[0xF0] == 0xAA) // encryption is on { // encrypt TWDR = (twi_reg[twi_reg_addr] - wm_ft[twi_reg_addr % 8]) ^ wm_sb[twi_reg_addr % 8]; } else { TWDR = twi_reg[twi_reg_addr]; } twi_reg_addr++; twi_rw_len++; twi_clear_int(1); // ack break; case TW_ST_DATA_NACK: // received nack, we are done case TW_ST_LAST_DATA: // received ack, but we are done already! // ack future responses twi_clear_int(1); break; default: twi_clear_int(0); break; } } // array containing button data unsigned char but_dat[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // calibration data unsigned char cal_data[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void setup() { /* Data format info can be found at: http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Guitar_Hero_.28Wii.29_Guitars */ // GH3 Gibson Les Paul but_dat[0] = B11111111; but_dat[1] = B11111111; but_dat[2] = B00011111; but_dat[3] = B00011111; but_dat[4] = B11111111; but_dat[5] = B10000110; // make wiimote think this is a valid extension controller // initialize wiimote interface with id, starting data, and calibration data wm_init(guitar_id, but_dat, cal_data,wm_timer_inc); // /*not supported with wiiuse*/ wm_init(drums_id, but_dat, cal_data,wm_timer_inc); // wm_init(nunchuk_id, but_dat, cal_data,wm_timer_inc); // wm_init(classic_id, but_dat, cal_data,wm_timer_inc); } void loop() { while(1) { sample(); delay(5); } } /* called after wiimote has completed a request */ void wm_timer_inc() { } static int counter = 0; static int idx = 3; unsigned char idxc = 0xF0; void sample() { if (counter > 400) { counter = 0; if (idx == 8) {idx = 3; idxc = 0xF0;} but_dat[3] = ++idxc; but_dat[5] ^= (1 << 3); but_dat[5] ^= (1 << 4); but_dat[5] ^= (1 << 5); but_dat[5] ^= (1 << 6); but_dat[5] ^= (1 << 7); twi_reg[5] = wm_ext_encode_byte(twi_reg[5]); wm_newaction(but_dat); idx++; } counter++; }
[/spoiler]
If you are looking for other arduino projects look here.
Links:
Guitar Hero arduino note visualizer lights our fire — Engadget This would be cool to do with SEMS sensor and wii interface.
Wii Guitar Hero World Tour Drums MIDI Out interface (Arduino Style) « Jamers lair Seems to be dead link.
– – circle-of-current – Circle of Current – Google Project Hosting
Drum Master – Design and Theory
MIDItar Hero
Guitar Hero Drums as a real MIDI drumkit
MIDI Output Hack for the Guitar Hero World Tour Drum Kit
CoreMidiControl