mockband/MockBand.ino

144 lines
3.9 KiB
Arduino
Raw Normal View History

2023-04-22 16:15:03 -06:00
#include <stdint.h>
#include <Arduino.h>
2023-12-31 16:19:10 -07:00
#include <PluggableUSB.h>
2023-04-22 16:15:03 -06:00
2023-12-31 20:33:29 -07:00
#include "hid.hh" // Modified HID library: doesn't prefix each packet with ID
#include "instrument.hh"
2023-04-22 16:15:03 -06:00
2023-12-31 20:33:29 -07:00
//#include "blue.hh" // Ginnie's blue guitar
#include "standard.hh" // Standard pins
2024-01-01 12:19:50 -07:00
// Maximum time between wammy bar updates.
2023-12-31 20:39:45 -07:00
#define UPDATE_INTERVAL_MS 20
2023-04-22 16:15:03 -06:00
2024-01-01 12:19:50 -07:00
// After an edge on a pin, stop listening for this long, to debounce it
#define SILENCE_INTERVAL_MS 40
// Your measured samples per frame, more or less
#define SAMPLES_PER_FRAME 127
// Some arithmetic for the compiler, to make the code fast
#define SAMPLES_PER_MS (SAMPLES_PER_FRAME / UPDATE_INTERVAL_MS)
#define SILENCE_SAMPLES (SAMPLES_PER_MS * SILENCE_INTERVAL_MS)
2024-01-01 12:42:07 -07:00
#if USB_VID != 0x1bad
#error USB_VID must be set to 0x1bad
#endif
#if USB_PID == 0x0004
#define GUITAR
#elif USB_PID == 0x0005
#define DRUM
#else
#error USB_PID must be set to 4 (Guitar) or 5 (Drum)
#endif
2024-01-01 12:19:50 -07:00
2023-04-22 16:15:03 -06:00
InstrumentButtonState buttonState;
void setup() {
pinMode(STRUM_DOWN, INPUT_PULLUP);
pinMode(STRUM_UP, INPUT_PULLUP);
pinMode(TILT_SWITCH, INPUT_PULLUP);
pinMode(BUTTON_GREEN, INPUT_PULLUP);
pinMode(BUTTON_RED, INPUT_PULLUP);
pinMode(BUTTON_YELLOW, INPUT_PULLUP);
pinMode(BUTTON_BLUE, INPUT_PULLUP);
pinMode(BUTTON_ORANGE, INPUT_PULLUP);
2023-12-31 16:19:10 -07:00
pinMode(SOLO_GREEN, INPUT_PULLUP);
pinMode(SOLO_RED, INPUT_PULLUP);
pinMode(SOLO_YELLOW, INPUT_PULLUP);
pinMode(SOLO_BLUE, INPUT_PULLUP);
pinMode(SOLO_ORANGE, INPUT_PULLUP);
pinMode(ANALOG_WAMMY, INPUT);
pinMode(BUTTON_PLUS, INPUT_PULLUP);
pinMode(BUTTON_MINUS, INPUT_PULLUP);
2023-12-31 16:19:10 -07:00
// Initialize HID
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
HID().AppendDescriptor(&node);
buttonState.axis[0] = 0;
buttonState.axis[1] = 0;
buttonState.axis[2] = 0;
buttonState.axis[3] = 0;
2023-12-31 16:19:10 -07:00
for (int i = 0; i < 12; i++) {
2023-04-22 16:15:03 -06:00
buttonState.reserved1[i] = 0x0;
}
buttonState.finalConstant = 0x0200020002000200;
}
2024-01-01 12:19:50 -07:00
// Order of pins in sample
uint8_t pins[] = {
BUTTON_BLUE,
BUTTON_GREEN,
BUTTON_RED,
BUTTON_YELLOW,
BUTTON_ORANGE,
TILT_SWITCH,
STRUM_UP, // Not in USB packet
STRUM_DOWN, // Not in USB packet
BUTTON_MINUS,
BUTTON_PLUS,
SOLO_BLUE, // Not in USB packet
SOLO_GREEN, // Not in USB packet
SOLO_RED, // Not in USB packet
SOLO_YELLOW, // Not in USB packet
SOLO_ORANGE, // Not in USB packet
};
#define npins (sizeof(pins) / sizeof(*pins))
2023-12-31 17:04:49 -07:00
// The 3.3v Pro Micro is on the slow side.
// Our strategy is to poll button state as quickly as possible,
// and hope we don't miss anything while we're doing USB stuff.
2023-04-22 16:15:03 -06:00
void loop() {
2024-01-01 12:19:50 -07:00
uint16_t buttons = 0;
uint16_t samples = 0;
2023-12-31 20:33:29 -07:00
unsigned long next = 0;
2024-01-01 12:19:50 -07:00
uint16_t silence[npins] = {0};
2023-12-31 16:19:10 -07:00
2023-12-31 17:22:47 -07:00
while (1) {
2023-12-31 20:33:29 -07:00
unsigned long now = millis();
2024-01-01 12:19:50 -07:00
uint16_t edge = 0;
2023-12-31 20:33:29 -07:00
2024-01-01 12:19:50 -07:00
samples++;
2023-12-31 16:44:08 -07:00
2024-01-01 12:19:50 -07:00
for (uint8_t i = 0; i < npins; i++) {
if (silence[i]) {
silence[i]--;
} else if (bitRead(buttons, i) != !digitalRead(pins[i])) {
edge |= bit(i);
silence[i] = SILENCE_SAMPLES;
}
2023-12-31 17:22:47 -07:00
}
2024-01-01 12:19:50 -07:00
buttons ^= edge;
2024-01-01 12:19:50 -07:00
// We've sampled everything. Is it time to do calculations and USB?
if (!edge && (next > now)) {
continue;
}
next = now + UPDATE_INTERVAL_MS;
2023-12-31 17:22:47 -07:00
buttonState.buttons = (buttons & 0b1100111111); // All directly-mappable bits
buttonState.buttons |= ((buttons >> 10) & 0b11111); // Solo keys
bitWrite(buttonState.buttons, 6, (buttons >> 10) & 0b11111); // Solo bit
2023-12-31 16:19:10 -07:00
2023-12-31 17:22:47 -07:00
// I don't understand why any rational engineer would have done this.
2023-12-31 20:33:29 -07:00
buttonState.hatAndConstant = (0x08
^ (bitRead(buttons, 6) << 4) // up
// right << 3
^ (bitRead(buttons, 7) << 2) // down
// left << 1
);
2023-12-31 16:44:08 -07:00
2023-12-31 17:22:47 -07:00
buttonState.axis[2] = analogRead(ANALOG_WAMMY) / 4;
2023-12-31 16:44:08 -07:00
2024-01-01 12:19:50 -07:00
// The second Y axis doesn't appear to be used, so I'm logging sample rate with it
buttonState.axis[3] = samples & 0xff; // most things map this to [-1,1]
2023-12-31 17:22:47 -07:00
// Send an update
HID().SendReport(0, (uint8_t *)&buttonState, 27);
2023-12-31 20:33:29 -07:00
2024-01-01 12:19:50 -07:00
samples = 0;
2023-12-31 17:22:47 -07:00
}
2023-04-22 16:15:03 -06:00
}