Code for Doug, Elizabeth, and Maruchi's team project: a Mario Kart controller.
Dependencies: PinDetect USBDevice mbed
Diff: main.cpp
- Revision:
- 0:0c8c5c9f7586
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Sep 29 06:55:14 2014 +0000 @@ -0,0 +1,108 @@ +/** + * Interactive Device Design, Fall 2014 + * Homework 3 - Mario Kart Wii Game Controller + * + * Elizabeth Lin + * Doug Cook + * Maruchi Kim + * + * This program will setup the mbed device to act + * as a Gamecube controller by emulating a mouse + * with input data from an accelerometer. It also + * provides buttons to support other gamepad + * functions specific to Mario Kart. + * + * The Dolphin Emulator (dolphin-emu.org) can be + * configured to accept this device (a USB Mouse) + * as the joystick for an emulated Wiimote/GCPad. + * + */ + +#include "mbed.h" +#include "USBMouseKeyboard.h" +#include "PinDetect.h" +#include "KeyManager.h" + +// ********************************************************** +// constants +const int PINDETECT_SAMPLE_FREQUENCY = 20000; +const int GAIN = 15000; +const int ADAFRUIT_ACC_RANGE_MIDPOINT = 32768; +// ********************************************************** + +// ********************************************************** +// Adafruit Accelerometer Input and calibration variables +AnalogIn xAxisIn(A2); +AnalogIn yAxisIn(A1); +AnalogIn zAxisIn(A0); +uint16_t addBias = false; +int bias = 0; +int sensitivity = 1; +float read_correct(AnalogIn input) { + float result = (float) input.read_u16(); + result = result - ADAFRUIT_ACC_RANGE_MIDPOINT; + return (result - (float)bias) / (float) sensitivity; +} +// ********************************************************** + +// LED and Serial Interface for 'Ready' feedback and debugging +DigitalOut greenLed(LED2); +Serial pc(USBTX, USBRX); + +// ********************************************************** +// minimum function for unsigned 16-bit integers +uint16_t min(uint16_t a, uint16_t b) { + return (a < b) ? a : b; +} +// ********************************************************** + +int main() { + // Perform accelerometer calibration at startup + // (assume the accelerometer is flat and + // face-down on a level surface). + greenLed = 1; + uint16_t initialX = xAxisIn.read_u16(); + uint16_t correctX = 32768; + bias = initialX - correctX; + sensitivity = (zAxisIn.read_u16() - 32768 - bias); + greenLed = 0; + + // Keyboard init and config + USBMouseKeyboard key_mouse = USBMouseKeyboard(ABS_MOUSE); + KeyManager keys = KeyManager(); + PinDetect buttonA(D7); + PinDetect buttonB(D6); + buttonA.mode(PullUp); + buttonB.mode(PullUp); + buttonA.setSampleFrequency( PINDETECT_SAMPLE_FREQUENCY ); + buttonA.attach_asserted(&keys, &KeyManager::keyAOn); + buttonA.attach_deasserted(&keys, &KeyManager::keyAOff); + buttonB.setSampleFrequency( PINDETECT_SAMPLE_FREQUENCY ); + buttonB.attach_asserted(&keys, &KeyManager::keyBOn); + buttonB.attach_deasserted(&keys, &KeyManager::keyBOff); + + // analog-in to joystick calculation variables + uint16_t xAxis; + uint16_t yAxis; + uint16_t xCenter = (X_MAX_ABS - X_MIN_ABS)/2; + uint16_t yCenter = (Y_MAX_ABS - Y_MIN_ABS)/2; + uint32_t xOrigin = xCenter; + uint32_t yOrigin = yCenter; + uint16_t lastXAxis = 0; + uint16_t lastYAxis = 0; + + while(1) { + xAxis = min(floor(.5*lastXAxis + .5*(uint16_t)(floor(atan(read_correct(xAxisIn)/read_correct(yAxisIn))*GAIN)+xOrigin)),X_MAX_ABS); + yAxis = floor(.5*lastYAxis + .5*(uint16_t)(-1*floor(atan(read_correct(zAxisIn)/read_correct(yAxisIn))*GAIN)+yOrigin)); + lastXAxis = xAxis; + lastYAxis = yAxis; + key_mouse.move(xAxis, yAxis); + + // read button pads + if (keys.keysPressed()) { + key_mouse.keyDown(keys.getCharacter()); + } else { + key_mouse.keyUp(); + } + } +}