Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FastAnalogIn FastIO FastPWM SimpleDMA USBDevice mbed
Fork of Pinscape_Controller by
Diff: main.cpp
- Revision:
- 3:3514575d4f86
- Parent:
- 2:c174f9ee414a
- Child:
- 4:02c7cd7b2183
--- a/main.cpp Tue Jul 22 04:33:47 2014 +0000
+++ b/main.cpp Wed Jul 23 17:53:28 2014 +0000
@@ -12,20 +12,16 @@
MyUSBJoystick(uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
: USBJoystick(vendor_id, product_id, product_release)
{
- connected_ = false;
suspended_ = false;
}
- int isConnected() const { return connected_; }
+ int isConnected() { return configured(); }
int isSuspended() const { return suspended_; }
protected:
- virtual void connectStateChanged(unsigned int connected)
- { connected_ = connected; }
virtual void suspendStateChanged(unsigned int suspended)
{ suspended_ = suspended; }
- int connected_;
int suspended_;
};
@@ -117,6 +113,104 @@
} d;
};
+// Accelerometer handler
+const int MMA8451_I2C_ADDRESS = (0x1d<<1);
+class Accel
+{
+public:
+ Accel(PinName sda, PinName scl, int i2cAddr, PinName irqPin)
+ : mma_(sda, scl, i2cAddr), intIn_(irqPin)
+ {
+ // set the initial ball velocity to zero
+ vx_ = vy_ = 0;
+
+ // set the initial raw acceleration reading to zero
+ xRaw_ = yRaw_ = 0;
+
+ // enable the interrupt
+ mma_.setInterruptMode(irqPin == PTA14 ? 1 : 2);
+
+ // set up the interrupt handler
+ intIn_.rise(this, &Accel::isr);
+
+ // read the current registers to clear the data ready flag
+ float z;
+ mma_.getAccXYZ(xRaw_, yRaw_, z);
+
+ // start our timers
+ tGet_.start();
+ tInt_.start();
+ }
+
+ void get(float &x, float &y, float &rx, float &ry)
+ {
+ // disable interrupts while manipulating the shared data
+ __disable_irq();
+
+ // read the shared data and store locally for calculations
+ float vx = vx_, vy = vy_, xRaw = xRaw_, yRaw = yRaw_;
+
+ // reset the velocity
+ vx_ = vy_ = 0;
+
+ // get the time since the last get() sample
+ float dt = tGet_.read_us()/1.0e6;
+ tGet_.reset();
+
+ // done manipulating the shared data
+ __enable_irq();
+
+ // calculate the acceleration since the last get(): a = dv/dt
+ x = vx/dt;
+ y = vy/dt;
+
+ // return the raw accelerometer data in rx,ry
+ rx = xRaw;
+ ry = yRaw;
+ }
+
+private:
+ // interrupt handler
+ void isr()
+ {
+ // Read the axes. Note that we have to read all three axes
+ // (even though we only really use x and y) in order to clear
+ // the "data ready" status bit in the accelerometer. The
+ // interrupt only occurs when the "ready" bit transitions from
+ // off to on, so we have to make sure it's off.
+ float z;
+ mma_.getAccXYZ(xRaw_, yRaw_, z);
+
+ // calculate the time since the last interrupt
+ float dt = tInt_.read_us()/1.0e6;
+ tInt_.reset();
+
+ // Accelerate the model ball: v = a*dt. Assume that the raw
+ // data from the accelerometer reflects the average physical
+ // acceleration over the interval since the last sample.
+ vx_ += xRaw_ * dt;
+ vy_ += yRaw_ * dt;
+ }
+
+ // current modeled ball velocity
+ float vx_, vy_;
+
+ // last raw axis readings
+ float xRaw_, yRaw_;
+
+ // underlying accelerometer object
+ MMA8451Q mma_;
+
+ // interrupt router
+ InterruptIn intIn_;
+
+ // timer for measuring time between get() samples
+ Timer tGet_;
+
+ // timer for measuring time between interrupts
+ Timer tInt_;
+};
+
int main(void)
{
// turn off our on-board indicator LED
@@ -188,13 +282,12 @@
// Create the joystick USB client. Light the on-board indicator LED
// red while connecting, and change to green after we connect.
led1 = 0;
- MyUSBJoystick js(0xFAFA, 0x00F7, 0x0001);
+ MyUSBJoystick js(0xFAFA, 0x00F7, 0x0003);
led1 = 1;
led2 = 0;
// create the accelerometer object
- const int MMA8451_I2C_ADDRESS = (0x1d<<1);
- MMA8451Q accel(PTE25, PTE24, MMA8451_I2C_ADDRESS);
+ Accel accel(PTE25, PTE24, MMA8451_I2C_ADDRESS, PTA15);
// create the CCD array object
TSL1410R ccd(PTE20, PTE21, PTB0);
@@ -362,13 +455,16 @@
newCalBtnLit = false;
break;
}
+
+ // light or flash the external calibration button LED, and
+ // do the same with the on-board blue LED
if (calBtnLit != newCalBtnLit)
{
calBtnLit = newCalBtnLit;
if (calBtnLit) {
calBtnLed = 1;
- led1 = 0;
- led2 = 0;
+ led1 = 1;
+ led2 = 1;
led3 = 1;
}
else {
@@ -447,8 +543,8 @@
}
// read the accelerometer
- float xa, ya;
- accel.getAccXY(xa, ya);
+ float xa, ya, rxa, rya;
+ accel.get(xa, ya, rxa, rya);
// check for auto-centering every so often
if (acTimer.read_ms() - t0ac > 1000)
@@ -521,17 +617,13 @@
}
}
- // Send the status report. Note one of the axes needs to be
- // reversed, because the native accelerometer reports seem to
- // assume that the card is component side down; we have to
- // reverse one or the other axis to account for the reversed
- // coordinate system. It doesn't really matter which one,
- // but reversing Y seems to give intuitive results when viewed
- // in the Windows joystick control panel. Note that the
- // coordinate system we report is ultimately arbitrary, since
- // Visual Pinball has preference settings that let us set up
- // axis reversals and a global rotation for the joystick.
- js.update(x, -y, z, 0);
+ // Send the status report. It doesn't really matter what
+ // coordinate system we use, since Visual Pinball has config
+ // options for rotations and axis reversals, but reversing y
+ // at the device level seems to produce the most intuitive
+ // results for the Windows joystick control panel view, which
+ // is an easy way to check that the device is working.
+ js.update(x, -y, z, int(rxa*127), int(rya*127), 0);
// show a heartbeat flash in blue every so often if not in
// calibration mode
@@ -566,7 +658,7 @@
hb = !hb;
led1 = (hb ? 0 : 1);
led2 = 0;
- led3 = 0;
+ led3 = 1;
}
// reset the heartbeat timer
