Compare commits

..

22 Commits
main ... piezo

Author SHA1 Message Date
Neale Pickett ed8d884054 Looks like I forgot to add my changes?
Mockband / build (push) Failing after 11s Details
2024-01-10 08:46:38 -07:00
Neale Pickett 8ccbaaa4b7 Attempt to read piezo analog inputs
Mockband / build (push) Successful in 24s Details
2024-01-09 11:24:51 -07:00
Neale Pickett 195c02748b Clean up publish script
Mockband / build (push) Successful in 26s Details
2024-01-08 13:13:42 -07:00
Neale Pickett 13825855d3 twiddling things trying to get drums working on CH
Mockband / build (push) Failing after 16s Details
2024-01-06 15:08:12 -07:00
Neale Pickett e54595e630 Merge branch 'main' into builder 2024-01-05 18:18:18 -07:00
Neale Pickett 63bd067250 More idiomatic (to me) Makefile
Mockband / build (push) Failing after 11s Details
2024-01-05 09:29:16 -07:00
Neale Pickett 9f0c0711a8 fancypants flash target
Mockband / build (push) Failing after 9s Details
2024-01-05 09:10:28 -07:00
Neale Pickett efc67e9fe5 Also publish zip file
Mockband / build (push) Failing after 10s Details
2024-01-05 09:06:59 -07:00
Neale Pickett ce7d6107cf stop using removed `make publish`
Mockband / build (push) Successful in 15s Details
2024-01-05 09:04:51 -07:00
Neale Pickett 48d2450514 make dist
Mockband / build (push) Failing after 12s Details
2024-01-05 09:02:53 -07:00
Neale Pickett 5f44832151 move to Makefile
Mockband / build (push) Successful in 33s Details
2024-01-05 08:50:10 -07:00
Neale Pickett da45584955 Makefile
Mockband / build (push) Successful in 26s Details
2024-01-05 08:37:03 -07:00
Neale Pickett 50ce7c245a Fix quoting
Mockband / build (push) Successful in 22s Details
2024-01-04 23:16:08 -07:00
Neale Pickett f767eb6e23 Build log formatting
Mockband / build (push) Failing after 4s Details
2024-01-04 23:15:05 -07:00
Neale Pickett 7495bfd20f Try preserving package versions
Mockband / build (push) Successful in 21s Details
2024-01-04 23:12:51 -07:00
Neale Pickett 5fa607d6b0 build and code cleanup
Mockband / build (push) Successful in 25s Details
2024-01-04 22:59:14 -07:00
Neale Pickett 855ad3ba60 fix: change quoting?
Mockband / build (push) Successful in 21s Details
2024-01-04 22:48:20 -07:00
Neale Pickett 25a917dc81 directly specify gcc flags
Mockband / build (push) Failing after 5s Details
2024-01-04 22:42:11 -07:00
Neale Pickett a8d4918e05 variables expand again
Mockband / build (push) Failing after 3s Details
2024-01-04 22:23:03 -07:00
Neale Pickett 544ffa8ced quote stuff
Mockband / build (push) Failing after 3s Details
2024-01-04 22:21:25 -07:00
Neale Pickett a3d8262e01 fix build on non-default branch
Mockband / build (push) Failing after 6s Details
2024-01-04 22:19:58 -07:00
Neale Pickett 0ba9c0957a Clever vid/pid settings?
Mockband / build (push) Successful in 19s Details
2024-01-04 22:16:36 -07:00
9 changed files with 133 additions and 291 deletions

View File

@ -7,23 +7,21 @@ VERSION=$GITHUB_REF_NAME
BASE=$GITHUB_SERVER_URL/api/packages/$GITHUB_ACTOR/generic/$PACKAGE/$VERSION
echo "=== Delete $VERSION"
curl \
--user "$GITHUB_ACTOR:$PACKAGE_API_TOKEN" \
--request DELETE \
$BASE
echo
for path in "$@"; do
fn=$(basename "$path")
echo "=== Upload $VERSION/$fn"
curl \
--user "$GITHUB_ACTOR:$PACKAGE_API_TOKEN" \
--request DELETE \
$BASE/$fn
curl \
--fail \
--user "$GITHUB_ACTOR:$PACKAGE_API_TOKEN" \
--upload-file "$path" \
$BASE/$fn
echo
done

View File

@ -16,4 +16,4 @@ jobs:
- name: publish
env:
PACKAGE_API_TOKEN: ${{ secrets.PACKAGE_API_TOKEN }}
run: .gitea/publish.sh *.hex *.zip
run: .gitea/publish.sh build/*.zip build/*.hex

View File

@ -2,29 +2,27 @@ DEVICE=/dev/ttyACM0
all: firmwares
firmwares: MockBand.guitar-wammy.hex
MockBand.guitar-wammy.hex: VID=0x1bad
MockBand.guitar-wammy.hex: PID=0x0004
MockBand.guitar-wammy.hex: FLAGS=-DWAMMY
firmwares: build/MockBand.guitar-wammy.hex
build/MockBand.guitar-wammy.hex: VID=0x1bad
build/MockBand.guitar-wammy.hex: PID=0x0004
build/MockBand.guitar-wammy.hex: FLAGS=-DWAMMY
firmwares: MockBand.guitar.hex
MockBand.guitar.hex: VID=0x1bad
MockBand.guitar.hex: PID=0x0004
firmwares: build/MockBand.guitar.hex
build/MockBand.guitar.hex: VID=0x1bad
build/MockBand.guitar.hex: PID=0x0004
firmwares: MockBand.drums.hex
MockBand.drums.hex: VID=0x1bad
MockBand.drums.hex: PID=0x3110
firmwares: build/MockBand.drums.hex
build/MockBand.drums.hex: VID=0x1bad
build/MockBand.drums.hex: PID=0x3110
MockBand.drums-xbox.hex: VID=0x1bad
MockBand.drums-xbox.hex: PID=0x0003
MockBand.drums-rb1.hex: VID=0x1bad
MockBand.drums-rb1.hex: PID=00005
firmwares: build/MockBand.drums1.hex
build/MockBand.drums1.hex: VID=0x1bad
build/MockBand.drums1.hex: PID=00005
MockBand.%.hex: MockBand.ino
rm -rf build
build/MockBand.%.hex: MockBand.ino
mkdir -p build/cache
rm -f build/build.options.json
arduino-builder \
-build-path $(abspath build/) \
-build-cache $(abspath build/cache/) \
@ -36,16 +34,16 @@ MockBand.%.hex: MockBand.ino
mv build/MockBand.ino.hex $@
flash-%: MockBand.%.hex
flash-%: build/MockBand.%.hex
echo -n "Waiting for $(DEVICE)..."; while [ ! -e $(DEVICE) ]; do echo -n .; sleep 1; done
avrdude -v -patmega32u4 -cavr109 -P$(DEVICE) -b57600 -D -Uflash:w:$<:i
dist: MockBand.zip
dist: build/MockBand.zip
MockBand.zip: firmwares
build/MockBand.zip: firmwares
rm -f $@
zip -r $@ README.md *.hex docs/
zip -r $@ README.md build/*.hex docs/
clean:
rm -rf build MockBand.*.hex MockBand.zip
rm -rf build

View File

@ -2,9 +2,11 @@
#include <Arduino.h>
#include <PluggableUSB.h>
#define DEBUG
#include "hid.hh" // Modified HID library: doesn't prefix each packet with ID
#include "instrument.hh"
#include "standard.hh" // Standard pins
#include "piezos.hh"
// If defined, we will check the wammy bar input
//#define WAMMY
@ -26,9 +28,7 @@
#error USB_VID must be set to 0x1bad: see INSTALL.md
#endif
#if USB_PID == 0x0003
#define DRUM // XBox
#elif USB_PID == 0x0004
#if USB_PID == 0x0004
#define GUITAR
#elif USB_PID == 0x0005
#define DRUM // Wii RB1
@ -41,23 +41,17 @@
InstrumentButtonState buttonState = {0};
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_GREEN, INPUT);
pinMode(BUTTON_RED, INPUT);
pinMode(BUTTON_YELLOW, INPUT);
pinMode(BUTTON_BLUE, INPUT);
pinMode(BUTTON_ORANGE, INPUT_PULLUP);
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(SOLO_GREEN, INPUT);
pinMode(SOLO_RED, INPUT);
pinMode(SOLO_YELLOW, INPUT);
pinMode(SOLO_BLUE, INPUT);
pinMode(BUTTON_PLUS, INPUT_PULLUP);
pinMode(BUTTON_MINUS, INPUT_PULLUP);
pinMode(ANALOG_WAMMY, INPUT);
pinMode(ANALOG_DPAD, INPUT);
// Initialize HID
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
@ -86,10 +80,13 @@ uint8_t pins[] = {
};
#define npins (sizeof(pins) / sizeof(*pins))
#define NOISE_THRESHOLD 40 // Minimum analog value to treat as a hit
// 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.
void loop() {
uint16_t inputs[16] = {0};
uint16_t buttons = 0;
uint16_t samples = 0;
unsigned long next = 0;
@ -99,13 +96,20 @@ void loop() {
uint16_t edge = 0;
samples++;
inputs[0] = analogRead(INPUT_BLUE);
inputs[1] = analogRead(INPUT_GREEN);
inputs[2] = analogRead(INPUT_RED);
inputs[3] = analogRead(INPUT_YELLOW);
for (uint8_t i = 0; i < npins; i++) {
for (uint8_t i = 0; i < 4; i++) {
if (silence[i]) {
silence[i]--;
} else if (bitRead(buttons, i) != !digitalRead(pins[i])) {
edge |= bit(i);
silence[i] = SILENCE_SAMPLES;
} else {
bool trigger = inputs[i] > NOISE_THRESHOLD;
if (trigger != bitRead(buttons, i)) {
edge |= bit(i);
silence[i] = SILENCE_SAMPLES;
}
}
}
buttons ^= edge;
@ -127,58 +131,42 @@ void loop() {
//
// Calculate and send an HID update
//
uint16_t vbuttons = buttons; // We're going to mess with the button state
buttonState.buttons = (vbuttons & 0b1100111111); // +-..!OYRGB
buttonState.buttons = (buttons & 0b1100111111); // +-..!OYRGB
#ifdef GUITAR
buttonState.buttons |= (vbuttons >> 10) & 0b11111; // Solo keys
bitWrite(buttonState.buttons, 6, (vbuttons >> 10) & 0b11111); // Solo modifier
buttonState.buttons |= (buttons >> 10) & 0b11111; // Solo keys
bitWrite(buttonState.buttons, 6, buttons & (0b11111 << 10)); // Solo modifier
if (bitRead(vbuttons, 6)) {
if (bitRead(buttons, 6)) {
buttonState.hatAndConstant = 0; // up
} else if bitRead(vbuttons, 7) {
} else if bitRead(buttons, 7) { //
buttonState.hatAndConstant = 4; // down
} else {
buttonState.hatAndConstant = 8; // nothing
}
#else // DRUMS
buttonState.buttons |= (buttons >> 10) & 0b01011; // Cymbals
bitWrite(buttonState.buttons, 10, (buttons >> 0) & 0b01111); // Drum pad modifier
bitWrite(buttonState.buttons, 11, (buttons >> 10) & 0b01011); // Cymbals modifier
buttonState.axis[3] = bitRead(buttons, 12)?255:0; // High hat
// Hi hat pedal (SOLO_RED) makes yellow cymbal strike a blue cymbal strike
if (bitRead(vbuttons, 12) && bitRead(vbuttons, 13)) {
bitClear(vbuttons, 13);
bitSet(vbuttons, 10);
}
// rbdrum2midi wants these set
buttonState.velocity[0] = inputs[3]/4; // Y
buttonState.velocity[1] = inputs[2]/4; // R
buttonState.velocity[2] = inputs[1]/2; // G
buttonState.velocity[3] = inputs[0]/4; // B
buttonState.buttons |= (vbuttons >> 10) & 0b01011; // Cymbals
bitWrite(buttonState.buttons, 10, (vbuttons >> 0) & 0b01111); // Drum pad modifier
bitWrite(buttonState.buttons, 11, (vbuttons >> 10) & 0b01011); // Cymbals modifier
// rbdrum2midi wants these set: it ignores the button states.
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
// Clone Hero 1.0.0.4080-final needs blue and yellow cymbals to send up and down on d-pad.
// This is what the mysterous CymExt1 and CymExt2 mappings mean.
// If these aren't set, all pads (except red) register as simultaneous drum and cymbal hits.
if (bitRead(vbuttons, 13)) {
buttonState.hatAndConstant = 0; // up
} else if (bitRead(vbuttons, 10)) {
buttonState.hatAndConstant = 4; // down
} else {
buttonState.hatAndConstant = 8; // nothing
}
// Say the D-pad is centered
buttonState.hatAndConstant = 8;
#endif
#ifdef DPAD
#error DPAD isn't implemented yet
#endif
#ifdef DEBUGY0
// Log sample rate to the first Y axis
buttonState.axis[1] = samples & 0xff;
#ifdef DEBUG
// Log sample rate to the first X axis
buttonState.axis[0] = samples & 0xff;
#endif
// Send an update

View File

@ -1,9 +1,4 @@
---
gitea: none
include_toc: true
---
# Introduction
# Mock Band
Microcontroller Firmware to emulate guitar and drum kit controllers from the
Wii version of the Rock Band games.
@ -23,23 +18,6 @@ Thanks, Nicholas!
* A physical controller
# Skills Needed
This is a research project:
it's assumed you already have a skillset that includes:
* Disassembling consumer electronics
* Using a multimeter to perform continuity checks
* Building electronics projects using a microcontroller
* Soldering
* Running the Arduino IDE *or* using `avrdude` to flash a firmware
If you're not comfortable with the above list,
your best option right now (Jan 2024) is to either buy a used kit,
or wait for the Polybar project to finish their work
producing a beginner-friendly kit with assembly manual.
# Controllers
## Guitar
@ -71,30 +49,10 @@ I'm sorry I didn't photograph or record any of this,
but it was pretty straightforward.
# Building
# Compiling
This will compile in the Arduino IDE,
or on the commandline using `make`.
## Command Line
Just run `make` on a Unix system.
I set up paths for my Debian install of Arduino 1.8;
you may need to adjust them if your setup has different paths.
There is a `flash-%` target that will upload the built firmware to a Pro Micro.
The following targets exist:
make flash-guitar # Guitar firmware
make flash-guitar-wammy # Guitar firmware with wammy bar
make flash-drums # Drums firmware
## Arduino
Mockband has no library dependencies,
and as far as I can tell,
will work with the built-in Leonardo profile,
even though you're uploading to a Pro Micro.
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.
@ -105,7 +63,7 @@ Don't edit anything that doesn't say `build` on the line! I can't help you if yo
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
## Build flags
This disables serial communications on the board.
@ -114,7 +72,7 @@ This disables serial communications on the board.
Hat tip to Nicholas Angle for figuring this out
so I didn't have to.
### VID and PID
## VID and PID
These set the USB identifiers.
VID is the Vendor ID,
@ -123,7 +81,7 @@ and PID is the Product ID.
`0x1bad` means "Harmonix Music",
at least, it does to the Linux kernel.
#### For guitar
### For guitar
PID `0x004` means "Guitar controller".
@ -132,7 +90,7 @@ PID `0x004` means "Guitar controller".
leonardo.build.usb_product="Mockband Guitar"
#### For drums
### For drums
PID `0x3110` means "Rock Band 2 drums".
This works better with all versions of Rock Band on my wii,
@ -228,19 +186,6 @@ will use both the 2x kick and the hi hat.
Maybe there is some other game that uses this too.
# Related Projects
Mockband is a research project.
You can use it to build a fully working controller,
but the main goal of this project is to inform other developers.
If you're looking for a user-friendly way to get a Rock Band drum controller,
consider the following alternatives:
* Buying a used Harmonix (official Rock Band) drum kit
* Mad Catz Rock Band 3 MIDI PRO-Adapter and a MIDI e-drum kit
* [Santroller](https://santroller.tangentmc.net/wiring_guides/drum.html)
wired to a used Harmonix drum kit
# Bugs / Not Yet Implemented
@ -255,11 +200,6 @@ just
and I'll open an issue.
# License
You may use this under the terms of the [MIT License](docs/COPYING.md).
# Need help?
[Email me](mailto:neale@woozle.org),

View File

@ -1,27 +0,0 @@
# Changelog
## [1.0-beta2] - 2024-01-07
### Added
- CI/CD build
- Make-based build, but it still works with the Arduino IDE!
- XBox controller
### Fixed
- Blue and Yellow cymbal strikes send up and down on the D-pad.
- This fixes a bug with Clone Hero where Blue, Yellow, and Green pads,
both cymbal and drum pads,
triggered a drum and cymbal hit at the same time.
- Clone Hero's mysterious CymExt1 and CymExt2 are read on Yellow and Blue
cymbal hits, and must map to dpad up and down. In Windows this might be called "POV Hat";
in Linux it's called "Hat 0"
### Changed
- The "high hat" pin now causes the yellow cymbal to send a blue cymbal hit,
similar to devices sold in the past for this express purpose.
Previously it changed a hat axis,
because I thought "hat" meant "high hat". Heh.
### Removed
- No more DEBUG option
## [1.0-beta1] - 2024-01-04

View File

@ -1,22 +0,0 @@
MIT License
Copyright © 2023 Nicholas Angle
Copyright © 2023-2024 Neale Pickett <neale@woozle.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
**The software is provided "as is", without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose and noninfringement. In no event shall the
authors or copyright holders be liable for any claim, damages or other
liability, whether in an action of contract, tort or otherwise, arising from,
out of or in connection with the software or the use or other dealings in the
software.**

View File

@ -7,44 +7,16 @@ so that when original sources fall off the net,
hopefully at least my notes will still be around.
USB data rate
-------------
Unlike the Santroller
(which is much easier to install for beginners),
this firmware does not send continuous updates over USB,
unless it has to.
Because the only analog input is the wammy bar,
if you don't include that input,
the controller can stay silent until a button is pressed or released.
This allows 4 controllers to connect to a USB hub,
with no concern for overwhelming the hub.
Since the amount of data is about the same as a keyboard,
and a little less than a mouse,
I would expect that a 7-port USB 2 hub would also handle 7 instruments,
no problem.
I just don't know of any games that can use mor than 4 instruments.
If you do use the wammy bar,
an update is sent every 20 milliseconds.
The firmware still attempts to reduce lag
by sending button change events as soon as possible.
I haven't played with this much,
so if you have a wammy bar set up,
please reach out to me and let me know how it works.
Sample Rate
-----------
If `DEBUGY0' is defined,
the number of samples taken since the last HID report
is sent as Y axis on hat 0.
You can use the
The number of samples taken since the last HID report
is sent as the second Y axis.
If you `#define DEBUG`,
you can use the
[included gamepad tester](gamepad.html),
to see the approximate number of samples as an integer.
to see the approximate number of samples as an integer,
on the first X axis.
This is approximate,
because the browser encodes the value as a real number between -1 and 1.
@ -52,11 +24,6 @@ We convert it back, but may lose a little precision.
It's close enough for me,
hopefully it's close enough for you.
This number will not be very useful
unless you are polling the wammy bar,
since without that input,
updates are only sent when a button state changes.
Debouncing
----------
@ -99,33 +66,11 @@ Here's what each bit means:
* 0o13: Cymbal modifier
* 0o14: Select
Hats
----
I guess "hats" are what I would have called "joysticks and dpads".
hatAndConstant
--------------
### Hat 0: unknown
This doesn't appear to be sent or used.
### Hat 1: guitar analog controls
The X axis is the position of the wammy bar.
The Y axis is the pickup selector.
I believe this was a 5-position switch on some guitars.
Only Rock Band 1 seems to use this.
### Hat 2: navigation
Sent by the dpad on the controller,
as `hatAndConstant`.
Guitars send up/down for the up/down strum buttons.
Drums send up/down on the blue/yellow cymbal pads.
The position of this digital input is reported in only 3 bits:
The HAT switch reports its position like a clock.
7 0 1
@ -153,19 +98,20 @@ Sending these values does not seem to cause problems with my Wii games.
Product ID (PID)
----------------
The following USB PIDs are recognized by various things:
Nicholas,
who did the initial work on the guitar,
suggested that PID 0x0005 would get the sketch working as drums.
And that was correct:
this works great on
Wii Rock Band 1 and
Wii LEGO Rock Band.
* 0x0003: XBox Drum
* 0x0004: Wii Guitar
* 0x0005: Wii Drums - Rock Band 1
* 0x3110: Wii Drums - Rock Band 2
But it fails in frustrating ways on
Wii Rock Band 3:
the yellow and blue pads don't navigate menus,
and cymbals aren't detected.
There are some quirks to note:
* Rock Band 3 won't recognize cymbal hits on PID=0x0005,
but the same program with PID=0x3110 works fine.
* Wii games don't appear to recognized PID=0x0003.
Maybe Rock Band 3 does: I didn't test that one.
The fix was setting the USB PID to 0x3110.
Drum Velocity
@ -173,8 +119,7 @@ Drum Velocity
I split the 12 "reserved" bytes from Nicholas's
`struct InstrumentButtonState`
into 4 bytes of I-Don't-Know,
4 bytes of velocity,
into 4 bytes of I-Don't-Know, 4 bytes of velocity,
and 4 more bytes of I-Don't-Know.
Whenever a pad is hit,
I send 127 on the corresponding velocity.
@ -185,21 +130,10 @@ and looks only at the velocity values.
None of the Wii games I have
seem to care what these values are set to.
Clone Hero also does not care.
Clone Hero
==========
Clone Hero wants Hat 2 up on yellow cymbal hit,
and Hat 2 down on blue cymbal hit.
If it doesn't see these while mapping drum pads,
then hitting any color bad will trigger both drum and cymbal for that color.
References
==========
=========
The most valuable sources of information I found were:

33
piezos.hh Normal file
View File

@ -0,0 +1,33 @@
#pragma once
// Standard setup for a Pro Micro
/*
* Don't forget to do this (guitar pid=0x0004, drum pid=0x0005):
< micro.build.vid=0x2341
< micro.build.pid=0x8037
--
> micro.build.vid=0x1bad
> micro.build.pid=0x0004
< micro.build.extra_flags={build.usb_flags}
---
> micro.build.extra_flags={build.usb_flags} -DCDC_DISABLED
*/
const int BUTTON_GREEN = 18; // A0
const int BUTTON_RED = 19; // A1
const int BUTTON_YELLOW = 20; // A2
const int BUTTON_BLUE = 21; // A3
const int BUTTON_ORANGE = 15;
const int SOLO_GREEN = 9;
const int SOLO_RED = 8;
const int SOLO_YELLOW = 6;
const int SOLO_BLUE = 4;
const int SOLO_ORANGE = 14;
const int BUTTON_PLUS = 1;
const int BUTTON_MINUS = 0;