Home PageGuitar hero

Guitar Hero

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.

guitarheroschematic

This is what this looks like in real life.

guitar hero pcb

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

Leave a Reply