Code for Doug, Elizabeth, and Maruchi's team project: a Mario Kart controller.

Dependencies:   PinDetect USBDevice mbed

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();
+        }
+    }
+}