Compare commits
2 Commits
3e059d0fb1
...
52770fcdf5
Author | SHA1 | Date |
---|---|---|
Neale Pickett | 52770fcdf5 | |
Neale Pickett | 8bcb905028 |
44
MockBand.ino
44
MockBand.ino
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "hid.hh" // Modified HID library: doesn't prefix each packet with ID
|
#include "hid.hh" // Modified HID library: doesn't prefix each packet with ID
|
||||||
#include "instrument.hh"
|
#include "instrument.hh"
|
||||||
//#include "blue.hh" // Ginnie's blue guitar
|
|
||||||
#include "standard.hh" // Standard pins
|
#include "standard.hh" // Standard pins
|
||||||
|
|
||||||
// If defined, we will check the wammy bar input
|
// If defined, we will check the wammy bar input
|
||||||
|
@ -26,18 +25,20 @@
|
||||||
#define SILENCE_SAMPLES (SAMPLES_PER_MS * SILENCE_INTERVAL_MS)
|
#define SILENCE_SAMPLES (SAMPLES_PER_MS * SILENCE_INTERVAL_MS)
|
||||||
|
|
||||||
#if USB_VID != 0x1bad
|
#if USB_VID != 0x1bad
|
||||||
#error USB_VID must be set to 0x1bad
|
#error USB_VID must be set to 0x1bad: see INSTALL.md
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USB_PID == 0x0004
|
#if USB_PID == 0x0004
|
||||||
#define GUITAR
|
#define GUITAR
|
||||||
#elif USB_PID == 0x0005
|
#elif USB_PID == 0x0005
|
||||||
#define DRUM
|
#define DRUM // Wii RB1
|
||||||
|
#elif USB_PID == 0x3110
|
||||||
|
#define DRUM // Wii RB2
|
||||||
#else
|
#else
|
||||||
#error USB_PID must be set to 4 (Guitar) or 5 (Drum)
|
#error USB_PID not recognized: see INSTALL.md
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
InstrumentButtonState buttonState;
|
InstrumentButtonState buttonState = {0};
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
pinMode(STRUM_DOWN, INPUT_PULLUP);
|
pinMode(STRUM_DOWN, INPUT_PULLUP);
|
||||||
|
@ -53,21 +54,15 @@ void setup() {
|
||||||
pinMode(SOLO_YELLOW, INPUT_PULLUP);
|
pinMode(SOLO_YELLOW, INPUT_PULLUP);
|
||||||
pinMode(SOLO_BLUE, INPUT_PULLUP);
|
pinMode(SOLO_BLUE, INPUT_PULLUP);
|
||||||
pinMode(SOLO_ORANGE, INPUT_PULLUP);
|
pinMode(SOLO_ORANGE, INPUT_PULLUP);
|
||||||
pinMode(ANALOG_WAMMY, INPUT);
|
|
||||||
pinMode(BUTTON_PLUS, INPUT_PULLUP);
|
pinMode(BUTTON_PLUS, INPUT_PULLUP);
|
||||||
pinMode(BUTTON_MINUS, INPUT_PULLUP);
|
pinMode(BUTTON_MINUS, INPUT_PULLUP);
|
||||||
|
pinMode(ANALOG_WAMMY, INPUT);
|
||||||
|
pinMode(ANALOG_DPAD, INPUT);
|
||||||
|
|
||||||
// Initialize HID
|
// Initialize HID
|
||||||
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
|
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
|
||||||
HID().AppendDescriptor(&node);
|
HID().AppendDescriptor(&node);
|
||||||
|
|
||||||
buttonState.axis[0] = 0;
|
|
||||||
buttonState.axis[1] = 0;
|
|
||||||
buttonState.axis[2] = 0;
|
|
||||||
buttonState.axis[3] = 0;
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
buttonState.reserved1[i] = 0x0;
|
|
||||||
}
|
|
||||||
buttonState.finalConstant = 0x0200020002000200;
|
buttonState.finalConstant = 0x0200020002000200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +96,9 @@ void loop() {
|
||||||
uint16_t silence[npins] = {0};
|
uint16_t silence[npins] = {0};
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
#ifdef WAMMY
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
#endif
|
||||||
uint16_t edge = 0;
|
uint16_t edge = 0;
|
||||||
|
|
||||||
samples++;
|
samples++;
|
||||||
|
@ -117,10 +114,17 @@ void loop() {
|
||||||
buttons ^= edge;
|
buttons ^= edge;
|
||||||
|
|
||||||
// We've sampled everything. Is it time to do calculations and USB?
|
// We've sampled everything. Is it time to do calculations and USB?
|
||||||
|
#ifdef WAMMY
|
||||||
if (!edge && (next > now)) {
|
if (!edge && (next > now)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
next = now + UPDATE_INTERVAL_MS;
|
next = now + UPDATE_INTERVAL_MS;
|
||||||
|
buttonState.axis[2] = analogRead(ANALOG_WAMMY) / 4; // Wammy bar
|
||||||
|
#else
|
||||||
|
if (!edge) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate and send an HID update
|
// Calculate and send an HID update
|
||||||
|
@ -144,6 +148,12 @@ void loop() {
|
||||||
bitWrite(buttonState.buttons, 11, buttons & (0b01011 << 10)); // Cymbals modifier
|
bitWrite(buttonState.buttons, 11, buttons & (0b01011 << 10)); // Cymbals modifier
|
||||||
buttonState.axis[3] = bitRead(buttons, 12)?255:0; // High hat
|
buttonState.axis[3] = bitRead(buttons, 12)?255:0; // High hat
|
||||||
|
|
||||||
|
// rbdrum2midi wants these set
|
||||||
|
buttonState.velocity[0] = bitRead(buttonState.buttons, 3)?127:0; // Y
|
||||||
|
buttonState.velocity[1] = bitRead(buttonState.buttons, 2)?127:0; // R
|
||||||
|
buttonState.velocity[2] = bitRead(buttonState.buttons, 1)?127:0; // G
|
||||||
|
buttonState.velocity[3] = bitRead(buttonState.buttons, 0)?127:0; // B
|
||||||
|
|
||||||
// Use the cymbals for up and down, since I don't have a D-pad
|
// Use the cymbals for up and down, since I don't have a D-pad
|
||||||
if bitRead(buttons, 13) {
|
if bitRead(buttons, 13) {
|
||||||
buttonState.hatAndConstant = 0; // up
|
buttonState.hatAndConstant = 0; // up
|
||||||
|
@ -154,14 +164,10 @@ void loop() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// D-pad would go here if I ever implemented that:
|
#ifdef DPAD
|
||||||
// nothing seems to actualy need it.
|
#error DPAD isn't implemented yet
|
||||||
|
|
||||||
#ifdef WAMMY
|
|
||||||
buttonState.axis[2] = analogRead(ANALOG_WAMMY) / 4; // Wammy bar
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Log sample rate to the first X axis
|
// Log sample rate to the first X axis
|
||||||
buttonState.axis[0] = samples & 0xff;
|
buttonState.axis[0] = samples & 0xff;
|
||||||
|
|
50
NOTES.md
50
NOTES.md
|
@ -1,11 +1,3 @@
|
||||||
I did some performance testing.
|
|
||||||
|
|
||||||
The Pro Micro runs an Atmel 32u4 at 8MHz.
|
|
||||||
If the code does nothing else,
|
|
||||||
I was able to poll all pins around 13 times every 1ms,
|
|
||||||
or 13kHz.
|
|
||||||
|
|
||||||
|
|
||||||
Sample Rate
|
Sample Rate
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -39,6 +31,10 @@ I settled on a 40ms silence window as feeling pretty good.
|
||||||
You can adjust this if you want to.
|
You can adjust this if you want to.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
USB Junk
|
||||||
|
========
|
||||||
|
|
||||||
Gamepad Buttons
|
Gamepad Buttons
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -46,28 +42,38 @@ The `buttons` struct member is a bitmap,
|
||||||
each bit mapping to one of the 12 buttons reported through HID.
|
each bit mapping to one of the 12 buttons reported through HID.
|
||||||
Here's what each bit means:
|
Here's what each bit means:
|
||||||
|
|
||||||
* 0: Blue
|
* 0o00: Blue
|
||||||
* 1: Green
|
* 0o01: Green
|
||||||
* 2: Red
|
* 0o02: Red
|
||||||
* 3: Yellow
|
* 0o03: Yellow
|
||||||
* 4: Orange
|
* 0o04: Orange
|
||||||
* 5: Tilt Switch / 2x kick
|
* 0o05: Tilt Switch / 2x kick
|
||||||
* 6: Solo modifier (second row of buttons on guitar)
|
* 0o06: Solo modifier (second row of buttons on guitar)
|
||||||
* 7: ?
|
* 0o07: ???
|
||||||
* 8: Minus
|
* 0o10: Minus
|
||||||
* 9: Plus
|
* 0o11: Plus
|
||||||
* 10: Drum pad modifier?
|
* 0o12: Drum pad modifier
|
||||||
* 11: Cymbal modifier?
|
* 0o13: Cymbal modifier
|
||||||
* 12: ?
|
* 0o14: Select
|
||||||
|
|
||||||
|
|
||||||
hatAndConstant
|
hatAndConstant
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
I don't get this, but here's what the values mean:
|
Here's what the values mean:
|
||||||
|
|
||||||
* 2: right
|
* 2: right
|
||||||
* 6: left
|
* 6: left
|
||||||
* 0: up
|
* 0: up
|
||||||
* 4: down
|
* 4: down
|
||||||
* 8: nothing
|
* 8: nothing
|
||||||
|
|
||||||
|
|
||||||
|
velocity
|
||||||
|
--------
|
||||||
|
|
||||||
|
I don't know how I can verify that I'm setting this right,
|
||||||
|
but the `rbdrum2midi` program looks at these bytes to detect hits.
|
||||||
|
I set them to 127 when a hit is detected on the digital pin.
|
||||||
|
|
||||||
|
Sending these values does not seem to cause problems with my Wii games.
|
163
README.md
163
README.md
|
@ -16,39 +16,154 @@ which are very quick!
|
||||||
* A physical controller
|
* A physical controller
|
||||||
|
|
||||||
|
|
||||||
## Sample controllers
|
# Controllers
|
||||||
|
|
||||||
I used the following:
|
## Guitar
|
||||||
|
|
||||||
* [MiniCaster](https://www.printables.com/model/479046-minicaster-mini-clone-heromidi-controller)
|
I 3D printed the
|
||||||
by Vlad the Inhaler:
|
[MiniCaster](https://www.printables.com/model/479046-minicaster-mini-clone-heromidi-controller)
|
||||||
it comes with full build instructions.
|
by Vlad the Inhaler.
|
||||||
|
It comes with full build instructions.
|
||||||
|
|
||||||
* [Cheap children's drum toy](https://www.amazon.com/Electronic-Sboet-Practice-Headphone-Christmas/dp/B0CHJMYCH9/),
|
## Drums
|
||||||
each pad is a momentary switch.
|
|
||||||
|
I bought a [Cheap children's drum toy](https://www.amazon.com/Electronic-Sboet-Practice-Headphone-Christmas/dp/B0CHJMYCH9/)
|
||||||
|
from Amazon.
|
||||||
|
There are dozens of copies of this thing,
|
||||||
|
the one I got was on sale for $25.
|
||||||
|
|
||||||
|
I had to unscrew the cover and remove the
|
||||||
|
logic board, battery, and speaker.
|
||||||
|
The pads were connected with
|
||||||
|
a sort of ribbon connector,
|
||||||
|
which I desoldered and removed,
|
||||||
|
then placed in my own perma-proto board.
|
||||||
|
|
||||||
|
I also hooked up a 3.5mm TRS jack for the two pedals,
|
||||||
|
which I could have desoldered from the toy
|
||||||
|
(I already had these).
|
||||||
|
|
||||||
|
I'm sorry I didn't photograph or record any of this,
|
||||||
|
but it was pretty straightforward.
|
||||||
|
|
||||||
|
|
||||||
|
# Compiling
|
||||||
|
|
||||||
|
This compiles in the Arduino IDE.
|
||||||
|
It doesn't have any library dependencies.
|
||||||
|
|
||||||
|
You need to make two edits to `boards.txt`.
|
||||||
|
Instructions for this are all over the place.
|
||||||
|
|
||||||
|
Find your board, and edit the `build` lines.
|
||||||
|
Don't edit anything that doesn't say `build` on the line! I can't help you if you do this.
|
||||||
|
|
||||||
|
In my examples, I'm editing the lines for the leonardo build. Yours might be different:
|
||||||
|
it should match the board you're using.
|
||||||
|
|
||||||
|
## Build flags
|
||||||
|
|
||||||
|
This disables serial communications on the board.
|
||||||
|
|
||||||
|
leonardo.build.extra_flags={build.usb_flags} -DCDC_DISABLED
|
||||||
|
|
||||||
|
Hat tip to Nicholas Angle for figuring this out
|
||||||
|
so I didn't have to.
|
||||||
|
|
||||||
|
## VID and PID
|
||||||
|
|
||||||
|
These set the USB identifiers.
|
||||||
|
VID is the Vendor ID,
|
||||||
|
and PID is the Product ID.
|
||||||
|
|
||||||
|
`0x1bad` means "Harmonix Music",
|
||||||
|
at least, it does to the Linux kernel.
|
||||||
|
|
||||||
|
### For guitar
|
||||||
|
|
||||||
|
PID `0x004` means "Guitar controller".
|
||||||
|
|
||||||
|
leonardo.build.vid=0x1bad
|
||||||
|
leonardo.build.pid=0x0004
|
||||||
|
leonardo.build.usb_product="Mockband Guitar"
|
||||||
|
|
||||||
|
|
||||||
|
### For drums
|
||||||
|
|
||||||
|
PID `0x3110` means "Rock Band 2 drums".
|
||||||
|
This works better with all versions of Rock Band on my wii,
|
||||||
|
even if you don't use the cymbal inputs.
|
||||||
|
|
||||||
|
leonardo.build.vid=0x1bad
|
||||||
|
leonardo.build.pid=0x3110
|
||||||
|
leonardo.build.usb_product="Mockband Drums"
|
||||||
|
|
||||||
|
|
||||||
# Wiring
|
# Wiring
|
||||||
|
|
||||||
![see standard.hh for pin connections](wii-rb-std.png)
|
Both the guitar and drum kit I used
|
||||||
|
provide simple momentary switches:
|
||||||
|
nothing fancy like a piezo.
|
||||||
|
If you're using fancier types of inputs,
|
||||||
|
you'll need to modify the source code.
|
||||||
|
|
||||||
|
## Guitar
|
||||||
|
|
||||||
|
![guitar wiring](guitar.png)
|
||||||
|
|
||||||
|
| silkscreen pin name | description |
|
||||||
|
| --- | --- |
|
||||||
|
| TX0 | strum up |
|
||||||
|
| RX1 | strum down |
|
||||||
|
| 2 | tilt switch |
|
||||||
|
| 3 | green |
|
||||||
|
| 4 | red |
|
||||||
|
| 5 | yellow |
|
||||||
|
| 6 | blue |
|
||||||
|
| 7 | orange |
|
||||||
|
| 8 | no connection |
|
||||||
|
| 9 | wammy bar (see note) |
|
||||||
|
| 10 | plus |
|
||||||
|
| 16 | minus |
|
||||||
|
| 14 | orange solo |
|
||||||
|
| 15 | blue solo |
|
||||||
|
| 18 | yello solo |
|
||||||
|
| 19 | red solo |
|
||||||
|
| 20 | green solo |
|
||||||
|
| 21 | no connection |
|
||||||
|
|
||||||
|
The solo buttons and wammy bar are optional.
|
||||||
|
I don't use them.
|
||||||
|
|
||||||
|
If you hook up a wammy bar,
|
||||||
|
be sure to uncomment the `#define WAMMY`
|
||||||
|
in the code!
|
||||||
|
|
||||||
|
|
||||||
## Drum Kit
|
## Drum Kit
|
||||||
|
|
||||||
On the drum kit,
|
![drum wiring](drums.png)
|
||||||
|
|
||||||
* Orange: kick pedal
|
| silkscreen pin name | description |
|
||||||
* Solo Buttons: cymbals
|
| --- | --- |
|
||||||
* Red Solo: high hat
|
| TX0 | no connection |
|
||||||
* Tilt: 2x kick
|
| RX1 | no connection |
|
||||||
|
| 2 | 2x kick |
|
||||||
I think. I haven't been able to test this yet,
|
| 3 | green |
|
||||||
but the Clone Hero wiki leads me to believe this is how it works.
|
| 4 | red |
|
||||||
|
| 5 | yellow |
|
||||||
You can hook up a wammy bar for the drum kit,
|
| 6 | blue |
|
||||||
and it will be sent the same way as the guitar.
|
| 7 | kick |
|
||||||
I don't know why anyone would want this,
|
| 8 | no connection |
|
||||||
but I'm not going to tell you how to live your life.
|
| 9 | no connection |
|
||||||
|
| 10 | plus |
|
||||||
|
| 16 | minus |
|
||||||
|
| 14 | no connection |
|
||||||
|
| 15 | blue cymbal |
|
||||||
|
| 18 | yellow cymbal |
|
||||||
|
| 19 | hi hat pedal |
|
||||||
|
| 20 | green cymbal |
|
||||||
|
| 21 | no connection |
|
||||||
|
|
||||||
|
|
||||||
# Bugs / Not Yet Implemented
|
# Bugs / Not Yet Implemented
|
||||||
|
@ -61,3 +176,9 @@ Until that happens,
|
||||||
just
|
just
|
||||||
[email me](mailto:neale@woozle.org),
|
[email me](mailto:neale@woozle.org),
|
||||||
and I'll open an issue.
|
and I'll open an issue.
|
||||||
|
|
||||||
|
|
||||||
|
# Need help?
|
||||||
|
|
||||||
|
[Email me](mailto:neale@woozle.org),
|
||||||
|
I'm friendly :)
|
||||||
|
|
13
blue.hh
13
blue.hh
|
@ -1,13 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
const int STRUM_DOWN = 8;
|
|
||||||
const int STRUM_UP = 9;
|
|
||||||
const int TILT_SWITCH = 2;
|
|
||||||
const int BUTTON_GREEN = 3;
|
|
||||||
const int BUTTON_RED = 4;
|
|
||||||
const int BUTTON_YELLOW = 5;
|
|
||||||
const int BUTTON_BLUE = 6;
|
|
||||||
const int BUTTON_ORANGE = 7;
|
|
||||||
const int BUTTON_PLUS = 13;
|
|
||||||
const int BUTTON_MINUS = 12;
|
|
||||||
const int ANALOG_WAMMY = 19;
|
|
Binary file not shown.
Before Width: | Height: | Size: 419 KiB After Width: | Height: | Size: 419 KiB |
|
@ -73,6 +73,8 @@ typedef struct {
|
||||||
uint16_t buttons; // 2
|
uint16_t buttons; // 2
|
||||||
uint8_t hatAndConstant; // 1
|
uint8_t hatAndConstant; // 1
|
||||||
uint8_t axis[4]; // 4
|
uint8_t axis[4]; // 4
|
||||||
uint8_t reserved1[12]; // 12
|
uint8_t reserved1[4]; // Not sure what this is
|
||||||
|
uint8_t velocity[4]; // Y, R, G, B
|
||||||
|
uint8_t reserved2[4]; // Not sure what this is, either
|
||||||
uint64_t finalConstant; // 8
|
uint64_t finalConstant; // 8
|
||||||
} InstrumentButtonState;
|
} InstrumentButtonState;
|
||||||
|
|
|
@ -33,7 +33,9 @@ const int SOLO_YELLOW = 18;
|
||||||
const int SOLO_BLUE = 15;
|
const int SOLO_BLUE = 15;
|
||||||
const int SOLO_ORANGE = 14;
|
const int SOLO_ORANGE = 14;
|
||||||
|
|
||||||
const int ANALOG_WAMMY = 9;
|
|
||||||
|
|
||||||
const int BUTTON_PLUS = 10;
|
const int BUTTON_PLUS = 10;
|
||||||
const int BUTTON_MINUS = 16;
|
const int BUTTON_MINUS = 16;
|
||||||
|
|
||||||
|
const int ANALOG_WAMMY = 9;
|
||||||
|
const int ANALOG_DPAD = 21;
|
Loading…
Reference in New Issue