Compare commits

..

No commits in common. "52770fcdf55aafa16074062ee2095c45a798165d" and "3e059d0fb1929c192cdb3d0a3251526017094446" have entirely different histories.

8 changed files with 77 additions and 201 deletions

View File

@ -6,6 +6,7 @@
#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
@ -25,20 +26,18 @@
#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: see INSTALL.md #error USB_VID must be set to 0x1bad
#endif #endif
#if USB_PID == 0x0004 #if USB_PID == 0x0004
#define GUITAR #define GUITAR
#elif USB_PID == 0x0005 #elif USB_PID == 0x0005
#define DRUM // Wii RB1 #define DRUM
#elif USB_PID == 0x3110
#define DRUM // Wii RB2
#else #else
#error USB_PID not recognized: see INSTALL.md #error USB_PID must be set to 4 (Guitar) or 5 (Drum)
#endif #endif
InstrumentButtonState buttonState = {0}; InstrumentButtonState buttonState;
void setup() { void setup() {
pinMode(STRUM_DOWN, INPUT_PULLUP); pinMode(STRUM_DOWN, INPUT_PULLUP);
@ -54,15 +53,21 @@ 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;
} }
@ -96,9 +101,7 @@ 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++;
@ -114,17 +117,10 @@ 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
@ -148,12 +144,6 @@ 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
@ -164,10 +154,14 @@ void loop() {
} }
#endif #endif
#ifdef DPAD // D-pad would go here if I ever implemented that:
#error DPAD isn't implemented yet // nothing seems to actualy need it.
#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;

View File

@ -1,3 +1,11 @@
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
----------- -----------
@ -31,10 +39,6 @@ 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
--------------- ---------------
@ -42,38 +46,28 @@ 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:
* 0o00: Blue * 0: Blue
* 0o01: Green * 1: Green
* 0o02: Red * 2: Red
* 0o03: Yellow * 3: Yellow
* 0o04: Orange * 4: Orange
* 0o05: Tilt Switch / 2x kick * 5: Tilt Switch / 2x kick
* 0o06: Solo modifier (second row of buttons on guitar) * 6: Solo modifier (second row of buttons on guitar)
* 0o07: ??? * 7: ?
* 0o10: Minus * 8: Minus
* 0o11: Plus * 9: Plus
* 0o12: Drum pad modifier * 10: Drum pad modifier?
* 0o13: Cymbal modifier * 11: Cymbal modifier?
* 0o14: Select * 12: ?
hatAndConstant hatAndConstant
-------------- --------------
Here's what the values mean: I don't get this, but 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
View File

@ -16,154 +16,39 @@ which are very quick!
* A physical controller * A physical controller
# Controllers ## Sample controllers
## Guitar I used the following:
I 3D printed the * [MiniCaster](https://www.printables.com/model/479046-minicaster-mini-clone-heromidi-controller)
[MiniCaster](https://www.printables.com/model/479046-minicaster-mini-clone-heromidi-controller) by Vlad the Inhaler:
by Vlad the Inhaler. it comes with full build instructions.
It comes with full build instructions.
## Drums * [Cheap children's drum toy](https://www.amazon.com/Electronic-Sboet-Practice-Headphone-Christmas/dp/B0CHJMYCH9/),
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
Both the guitar and drum kit I used ![see standard.hh for pin connections](wii-rb-std.png)
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
![drum wiring](drums.png) On the drum kit,
| silkscreen pin name | description | * Orange: kick pedal
| --- | --- | * Solo Buttons: cymbals
| TX0 | no connection | * Red Solo: high hat
| RX1 | no connection | * Tilt: 2x kick
| 2 | 2x kick |
| 3 | green | I think. I haven't been able to test this yet,
| 4 | red | but the Clone Hero wiki leads me to believe this is how it works.
| 5 | yellow |
| 6 | blue | You can hook up a wammy bar for the drum kit,
| 7 | kick | and it will be sent the same way as the guitar.
| 8 | no connection | I don't know why anyone would want this,
| 9 | no connection | but I'm not going to tell you how to live your life.
| 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
@ -176,9 +61,3 @@ 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 Normal file
View File

@ -0,0 +1,13 @@
#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;

BIN
drums.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

View File

@ -73,8 +73,6 @@ 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[4]; // Not sure what this is uint8_t reserved1[12]; // 12
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;

View File

@ -33,9 +33,7 @@ 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;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 KiB

After

Width:  |  Height:  |  Size: 419 KiB