Code for Doug, Elizabeth, and Maruchi's team project: a Mario Kart controller.
Dependencies: PinDetect USBDevice mbed
main.cpp@0:0c8c5c9f7586, 2014-09-29 (annotated)
- Committer:
- douglasc
- Date:
- Mon Sep 29 06:55:14 2014 +0000
- Revision:
- 0:0c8c5c9f7586
initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
douglasc | 0:0c8c5c9f7586 | 1 | /** |
douglasc | 0:0c8c5c9f7586 | 2 | * Interactive Device Design, Fall 2014 |
douglasc | 0:0c8c5c9f7586 | 3 | * Homework 3 - Mario Kart Wii Game Controller |
douglasc | 0:0c8c5c9f7586 | 4 | * |
douglasc | 0:0c8c5c9f7586 | 5 | * Elizabeth Lin |
douglasc | 0:0c8c5c9f7586 | 6 | * Doug Cook |
douglasc | 0:0c8c5c9f7586 | 7 | * Maruchi Kim |
douglasc | 0:0c8c5c9f7586 | 8 | * |
douglasc | 0:0c8c5c9f7586 | 9 | * This program will setup the mbed device to act |
douglasc | 0:0c8c5c9f7586 | 10 | * as a Gamecube controller by emulating a mouse |
douglasc | 0:0c8c5c9f7586 | 11 | * with input data from an accelerometer. It also |
douglasc | 0:0c8c5c9f7586 | 12 | * provides buttons to support other gamepad |
douglasc | 0:0c8c5c9f7586 | 13 | * functions specific to Mario Kart. |
douglasc | 0:0c8c5c9f7586 | 14 | * |
douglasc | 0:0c8c5c9f7586 | 15 | * The Dolphin Emulator (dolphin-emu.org) can be |
douglasc | 0:0c8c5c9f7586 | 16 | * configured to accept this device (a USB Mouse) |
douglasc | 0:0c8c5c9f7586 | 17 | * as the joystick for an emulated Wiimote/GCPad. |
douglasc | 0:0c8c5c9f7586 | 18 | * |
douglasc | 0:0c8c5c9f7586 | 19 | */ |
douglasc | 0:0c8c5c9f7586 | 20 | |
douglasc | 0:0c8c5c9f7586 | 21 | #include "mbed.h" |
douglasc | 0:0c8c5c9f7586 | 22 | #include "USBMouseKeyboard.h" |
douglasc | 0:0c8c5c9f7586 | 23 | #include "PinDetect.h" |
douglasc | 0:0c8c5c9f7586 | 24 | #include "KeyManager.h" |
douglasc | 0:0c8c5c9f7586 | 25 | |
douglasc | 0:0c8c5c9f7586 | 26 | // ********************************************************** |
douglasc | 0:0c8c5c9f7586 | 27 | // constants |
douglasc | 0:0c8c5c9f7586 | 28 | const int PINDETECT_SAMPLE_FREQUENCY = 20000; |
douglasc | 0:0c8c5c9f7586 | 29 | const int GAIN = 15000; |
douglasc | 0:0c8c5c9f7586 | 30 | const int ADAFRUIT_ACC_RANGE_MIDPOINT = 32768; |
douglasc | 0:0c8c5c9f7586 | 31 | // ********************************************************** |
douglasc | 0:0c8c5c9f7586 | 32 | |
douglasc | 0:0c8c5c9f7586 | 33 | // ********************************************************** |
douglasc | 0:0c8c5c9f7586 | 34 | // Adafruit Accelerometer Input and calibration variables |
douglasc | 0:0c8c5c9f7586 | 35 | AnalogIn xAxisIn(A2); |
douglasc | 0:0c8c5c9f7586 | 36 | AnalogIn yAxisIn(A1); |
douglasc | 0:0c8c5c9f7586 | 37 | AnalogIn zAxisIn(A0); |
douglasc | 0:0c8c5c9f7586 | 38 | uint16_t addBias = false; |
douglasc | 0:0c8c5c9f7586 | 39 | int bias = 0; |
douglasc | 0:0c8c5c9f7586 | 40 | int sensitivity = 1; |
douglasc | 0:0c8c5c9f7586 | 41 | float read_correct(AnalogIn input) { |
douglasc | 0:0c8c5c9f7586 | 42 | float result = (float) input.read_u16(); |
douglasc | 0:0c8c5c9f7586 | 43 | result = result - ADAFRUIT_ACC_RANGE_MIDPOINT; |
douglasc | 0:0c8c5c9f7586 | 44 | return (result - (float)bias) / (float) sensitivity; |
douglasc | 0:0c8c5c9f7586 | 45 | } |
douglasc | 0:0c8c5c9f7586 | 46 | // ********************************************************** |
douglasc | 0:0c8c5c9f7586 | 47 | |
douglasc | 0:0c8c5c9f7586 | 48 | // LED and Serial Interface for 'Ready' feedback and debugging |
douglasc | 0:0c8c5c9f7586 | 49 | DigitalOut greenLed(LED2); |
douglasc | 0:0c8c5c9f7586 | 50 | Serial pc(USBTX, USBRX); |
douglasc | 0:0c8c5c9f7586 | 51 | |
douglasc | 0:0c8c5c9f7586 | 52 | // ********************************************************** |
douglasc | 0:0c8c5c9f7586 | 53 | // minimum function for unsigned 16-bit integers |
douglasc | 0:0c8c5c9f7586 | 54 | uint16_t min(uint16_t a, uint16_t b) { |
douglasc | 0:0c8c5c9f7586 | 55 | return (a < b) ? a : b; |
douglasc | 0:0c8c5c9f7586 | 56 | } |
douglasc | 0:0c8c5c9f7586 | 57 | // ********************************************************** |
douglasc | 0:0c8c5c9f7586 | 58 | |
douglasc | 0:0c8c5c9f7586 | 59 | int main() { |
douglasc | 0:0c8c5c9f7586 | 60 | // Perform accelerometer calibration at startup |
douglasc | 0:0c8c5c9f7586 | 61 | // (assume the accelerometer is flat and |
douglasc | 0:0c8c5c9f7586 | 62 | // face-down on a level surface). |
douglasc | 0:0c8c5c9f7586 | 63 | greenLed = 1; |
douglasc | 0:0c8c5c9f7586 | 64 | uint16_t initialX = xAxisIn.read_u16(); |
douglasc | 0:0c8c5c9f7586 | 65 | uint16_t correctX = 32768; |
douglasc | 0:0c8c5c9f7586 | 66 | bias = initialX - correctX; |
douglasc | 0:0c8c5c9f7586 | 67 | sensitivity = (zAxisIn.read_u16() - 32768 - bias); |
douglasc | 0:0c8c5c9f7586 | 68 | greenLed = 0; |
douglasc | 0:0c8c5c9f7586 | 69 | |
douglasc | 0:0c8c5c9f7586 | 70 | // Keyboard init and config |
douglasc | 0:0c8c5c9f7586 | 71 | USBMouseKeyboard key_mouse = USBMouseKeyboard(ABS_MOUSE); |
douglasc | 0:0c8c5c9f7586 | 72 | KeyManager keys = KeyManager(); |
douglasc | 0:0c8c5c9f7586 | 73 | PinDetect buttonA(D7); |
douglasc | 0:0c8c5c9f7586 | 74 | PinDetect buttonB(D6); |
douglasc | 0:0c8c5c9f7586 | 75 | buttonA.mode(PullUp); |
douglasc | 0:0c8c5c9f7586 | 76 | buttonB.mode(PullUp); |
douglasc | 0:0c8c5c9f7586 | 77 | buttonA.setSampleFrequency( PINDETECT_SAMPLE_FREQUENCY ); |
douglasc | 0:0c8c5c9f7586 | 78 | buttonA.attach_asserted(&keys, &KeyManager::keyAOn); |
douglasc | 0:0c8c5c9f7586 | 79 | buttonA.attach_deasserted(&keys, &KeyManager::keyAOff); |
douglasc | 0:0c8c5c9f7586 | 80 | buttonB.setSampleFrequency( PINDETECT_SAMPLE_FREQUENCY ); |
douglasc | 0:0c8c5c9f7586 | 81 | buttonB.attach_asserted(&keys, &KeyManager::keyBOn); |
douglasc | 0:0c8c5c9f7586 | 82 | buttonB.attach_deasserted(&keys, &KeyManager::keyBOff); |
douglasc | 0:0c8c5c9f7586 | 83 | |
douglasc | 0:0c8c5c9f7586 | 84 | // analog-in to joystick calculation variables |
douglasc | 0:0c8c5c9f7586 | 85 | uint16_t xAxis; |
douglasc | 0:0c8c5c9f7586 | 86 | uint16_t yAxis; |
douglasc | 0:0c8c5c9f7586 | 87 | uint16_t xCenter = (X_MAX_ABS - X_MIN_ABS)/2; |
douglasc | 0:0c8c5c9f7586 | 88 | uint16_t yCenter = (Y_MAX_ABS - Y_MIN_ABS)/2; |
douglasc | 0:0c8c5c9f7586 | 89 | uint32_t xOrigin = xCenter; |
douglasc | 0:0c8c5c9f7586 | 90 | uint32_t yOrigin = yCenter; |
douglasc | 0:0c8c5c9f7586 | 91 | uint16_t lastXAxis = 0; |
douglasc | 0:0c8c5c9f7586 | 92 | uint16_t lastYAxis = 0; |
douglasc | 0:0c8c5c9f7586 | 93 | |
douglasc | 0:0c8c5c9f7586 | 94 | while(1) { |
douglasc | 0:0c8c5c9f7586 | 95 | xAxis = min(floor(.5*lastXAxis + .5*(uint16_t)(floor(atan(read_correct(xAxisIn)/read_correct(yAxisIn))*GAIN)+xOrigin)),X_MAX_ABS); |
douglasc | 0:0c8c5c9f7586 | 96 | yAxis = floor(.5*lastYAxis + .5*(uint16_t)(-1*floor(atan(read_correct(zAxisIn)/read_correct(yAxisIn))*GAIN)+yOrigin)); |
douglasc | 0:0c8c5c9f7586 | 97 | lastXAxis = xAxis; |
douglasc | 0:0c8c5c9f7586 | 98 | lastYAxis = yAxis; |
douglasc | 0:0c8c5c9f7586 | 99 | key_mouse.move(xAxis, yAxis); |
douglasc | 0:0c8c5c9f7586 | 100 | |
douglasc | 0:0c8c5c9f7586 | 101 | // read button pads |
douglasc | 0:0c8c5c9f7586 | 102 | if (keys.keysPressed()) { |
douglasc | 0:0c8c5c9f7586 | 103 | key_mouse.keyDown(keys.getCharacter()); |
douglasc | 0:0c8c5c9f7586 | 104 | } else { |
douglasc | 0:0c8c5c9f7586 | 105 | key_mouse.keyUp(); |
douglasc | 0:0c8c5c9f7586 | 106 | } |
douglasc | 0:0c8c5c9f7586 | 107 | } |
douglasc | 0:0c8c5c9f7586 | 108 | } |