work in progress

Dependencies:   FastAnalogIn FastIO USBDevice mbed FastPWM SimpleDMA

Fork of Pinscape_Controller by Mike R

Committer:
mjr
Date:
Wed Jul 16 23:33:12 2014 +0000
Revision:
1:d913e0afb2ac
Parent:
0:5acbbe3f4cf4
Child:
2:c174f9ee414a
Before removing time/frequency limit on reading the plunger sensor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 0:5acbbe3f4cf4 1 #include "mbed.h"
mjr 0:5acbbe3f4cf4 2 #include "USBJoystick.h"
mjr 0:5acbbe3f4cf4 3 #include "MMA8451Q.h"
mjr 1:d913e0afb2ac 4 #include "tsl1410r.h"
mjr 1:d913e0afb2ac 5 #include "FreescaleIAP.h"
mjr 0:5acbbe3f4cf4 6
mjr 1:d913e0afb2ac 7 // on-board RGB LED elements - we use these for diagnostics
mjr 0:5acbbe3f4cf4 8 PwmOut led1(LED1), led2(LED2), led3(LED3);
mjr 0:5acbbe3f4cf4 9
mjr 1:d913e0afb2ac 10 // calibration button - switch input and LED output
mjr 1:d913e0afb2ac 11 DigitalIn calBtn(PTE29);
mjr 1:d913e0afb2ac 12 DigitalOut calBtnLed(PTE23);
mjr 0:5acbbe3f4cf4 13
mjr 0:5acbbe3f4cf4 14 static int pbaIdx = 0;
mjr 0:5acbbe3f4cf4 15
mjr 0:5acbbe3f4cf4 16 // on/off state for each LedWiz output
mjr 1:d913e0afb2ac 17 static uint8_t wizOn[32];
mjr 0:5acbbe3f4cf4 18
mjr 0:5acbbe3f4cf4 19 // profile (brightness/blink) state for each LedWiz output
mjr 1:d913e0afb2ac 20 static uint8_t wizVal[32] = {
mjr 0:5acbbe3f4cf4 21 0, 0, 0, 0, 0, 0, 0, 0,
mjr 0:5acbbe3f4cf4 22 0, 0, 0, 0, 0, 0, 0, 0,
mjr 0:5acbbe3f4cf4 23 0, 0, 0, 0, 0, 0, 0, 0,
mjr 0:5acbbe3f4cf4 24 0, 0, 0, 0, 0, 0, 0, 0
mjr 0:5acbbe3f4cf4 25 };
mjr 0:5acbbe3f4cf4 26
mjr 1:d913e0afb2ac 27 static float wizState(int idx)
mjr 0:5acbbe3f4cf4 28 {
mjr 1:d913e0afb2ac 29 if (wizOn[idx]) {
mjr 0:5acbbe3f4cf4 30 // on - map profile brightness state to PWM level
mjr 1:d913e0afb2ac 31 uint8_t val = wizVal[idx];
mjr 0:5acbbe3f4cf4 32 if (val >= 1 && val <= 48)
mjr 0:5acbbe3f4cf4 33 return 1.0 - val/48.0;
mjr 0:5acbbe3f4cf4 34 else if (val >= 129 && val <= 132)
mjr 0:5acbbe3f4cf4 35 return 0.0;
mjr 0:5acbbe3f4cf4 36 else
mjr 0:5acbbe3f4cf4 37 return 1.0;
mjr 0:5acbbe3f4cf4 38 }
mjr 0:5acbbe3f4cf4 39 else {
mjr 0:5acbbe3f4cf4 40 // off
mjr 0:5acbbe3f4cf4 41 return 1.0;
mjr 0:5acbbe3f4cf4 42 }
mjr 0:5acbbe3f4cf4 43 }
mjr 0:5acbbe3f4cf4 44
mjr 1:d913e0afb2ac 45 static void updateWizOuts()
mjr 1:d913e0afb2ac 46 {
mjr 1:d913e0afb2ac 47 led1 = wizState(0);
mjr 1:d913e0afb2ac 48 led2 = wizState(1);
mjr 1:d913e0afb2ac 49 led3 = wizState(2);
mjr 1:d913e0afb2ac 50 }
mjr 1:d913e0afb2ac 51
mjr 1:d913e0afb2ac 52 struct AccPrv
mjr 0:5acbbe3f4cf4 53 {
mjr 1:d913e0afb2ac 54 AccPrv() : x(0), y(0) { }
mjr 1:d913e0afb2ac 55 float x;
mjr 1:d913e0afb2ac 56 float y;
mjr 1:d913e0afb2ac 57
mjr 1:d913e0afb2ac 58 double dist(AccPrv &b)
mjr 1:d913e0afb2ac 59 {
mjr 1:d913e0afb2ac 60 float dx = x - b.x, dy = y - b.y;
mjr 1:d913e0afb2ac 61 return sqrt(dx*dx + dy*dy);
mjr 1:d913e0afb2ac 62 }
mjr 1:d913e0afb2ac 63 };
mjr 0:5acbbe3f4cf4 64
mjr 0:5acbbe3f4cf4 65 int main(void)
mjr 0:5acbbe3f4cf4 66 {
mjr 1:d913e0afb2ac 67 // turn off our on-board indicator LED
mjr 0:5acbbe3f4cf4 68 led1 = 1;
mjr 0:5acbbe3f4cf4 69 led2 = 1;
mjr 0:5acbbe3f4cf4 70 led3 = 1;
mjr 1:d913e0afb2ac 71
mjr 1:d913e0afb2ac 72 // plunger calibration data
mjr 1:d913e0afb2ac 73 const int npix = 320;
mjr 1:d913e0afb2ac 74 int plungerMin = 0, plungerMax = npix;
mjr 1:d913e0afb2ac 75
mjr 1:d913e0afb2ac 76 // plunger calibration button debounce timer
mjr 1:d913e0afb2ac 77 Timer calBtnTimer;
mjr 1:d913e0afb2ac 78 calBtnTimer.start();
mjr 1:d913e0afb2ac 79 int calBtnDownTime = 0;
mjr 1:d913e0afb2ac 80 int calBtnLit = false;
mjr 1:d913e0afb2ac 81
mjr 1:d913e0afb2ac 82 // Calibration button state:
mjr 1:d913e0afb2ac 83 // 0 = not pushed
mjr 1:d913e0afb2ac 84 // 1 = pushed, not yet debounced
mjr 1:d913e0afb2ac 85 // 2 = pushed, debounced, waiting for hold time
mjr 1:d913e0afb2ac 86 // 3 = pushed, hold time completed - in calibration mode
mjr 1:d913e0afb2ac 87 int calBtnState = 0;
mjr 1:d913e0afb2ac 88
mjr 1:d913e0afb2ac 89 // set up a timer for our heartbeat indicator
mjr 1:d913e0afb2ac 90 Timer hbTimer;
mjr 1:d913e0afb2ac 91 hbTimer.start();
mjr 1:d913e0afb2ac 92 int t0Hb = hbTimer.read_ms();
mjr 1:d913e0afb2ac 93 int hb = 0;
mjr 1:d913e0afb2ac 94
mjr 1:d913e0afb2ac 95 // set a timer for accelerometer auto-centering
mjr 1:d913e0afb2ac 96 Timer acTimer;
mjr 1:d913e0afb2ac 97 acTimer.start();
mjr 1:d913e0afb2ac 98 int t0ac = acTimer.read_ms();
mjr 1:d913e0afb2ac 99
mjr 1:d913e0afb2ac 100 // set up a timer for reading the plunger sensor
mjr 1:d913e0afb2ac 101 Timer ccdTimer;
mjr 1:d913e0afb2ac 102 ccdTimer.start();
mjr 1:d913e0afb2ac 103 int t0ccd = ccdTimer.read_ms();
mjr 1:d913e0afb2ac 104
mjr 1:d913e0afb2ac 105 #if 0
mjr 1:d913e0afb2ac 106 // DEBUG
mjr 1:d913e0afb2ac 107 Timer ccdDbgTimer;
mjr 1:d913e0afb2ac 108 ccdDbgTimer.start();
mjr 1:d913e0afb2ac 109 int t0ccdDbg = ccdDbgTimer.read_ms();
mjr 1:d913e0afb2ac 110 #endif
mjr 0:5acbbe3f4cf4 111
mjr 1:d913e0afb2ac 112 // Create the joystick USB client. Light the on-board indicator LED
mjr 1:d913e0afb2ac 113 // red while connecting, and change to green after we connect.
mjr 0:5acbbe3f4cf4 114 led1 = 0.75;
mjr 0:5acbbe3f4cf4 115 USBJoystick js(0xFAFA, 0x00F7, 0x0001);
mjr 0:5acbbe3f4cf4 116 led1 = 1;
mjr 0:5acbbe3f4cf4 117 led2 = 0.75;
mjr 0:5acbbe3f4cf4 118
mjr 0:5acbbe3f4cf4 119 // create the accelerometer object
mjr 0:5acbbe3f4cf4 120 const int MMA8451_I2C_ADDRESS = (0x1d<<1);
mjr 0:5acbbe3f4cf4 121 MMA8451Q accel(PTE25, PTE24, MMA8451_I2C_ADDRESS);
mjr 0:5acbbe3f4cf4 122
mjr 0:5acbbe3f4cf4 123 // create the CCD array object
mjr 1:d913e0afb2ac 124 TSL1410R ccd(PTE20, PTE21, PTB0);
mjr 1:d913e0afb2ac 125
mjr 1:d913e0afb2ac 126 // recent accelerometer readings, for auto centering
mjr 1:d913e0afb2ac 127 int iAccPrv = 0, nAccPrv = 0;
mjr 1:d913e0afb2ac 128 const int maxAccPrv = 5;
mjr 1:d913e0afb2ac 129 AccPrv accPrv[maxAccPrv];
mjr 0:5acbbe3f4cf4 130
mjr 1:d913e0afb2ac 131 // last accelerometer report, in mouse coordinates
mjr 1:d913e0afb2ac 132 int x = 127, y = 127, z = 0;
mjr 1:d913e0afb2ac 133
mjr 1:d913e0afb2ac 134 // raw accelerator centerpoint, on the unit interval (-1.0 .. +1.0)
mjr 1:d913e0afb2ac 135 float xCenter = 0.0, yCenter = 0.0;
mjr 1:d913e0afb2ac 136
mjr 1:d913e0afb2ac 137 // we're all set up - now just loop, processing sensor reports and
mjr 1:d913e0afb2ac 138 // host requests
mjr 0:5acbbe3f4cf4 139 for (;;)
mjr 0:5acbbe3f4cf4 140 {
mjr 0:5acbbe3f4cf4 141 // Look for an incoming report. Continue processing input as
mjr 0:5acbbe3f4cf4 142 // long as there's anything pending - this ensures that we
mjr 0:5acbbe3f4cf4 143 // handle input in as timely a fashion as possible by deferring
mjr 0:5acbbe3f4cf4 144 // output tasks as long as there's input to process.
mjr 0:5acbbe3f4cf4 145 HID_REPORT report;
mjr 0:5acbbe3f4cf4 146 while (js.readNB(&report) && report.length == 8)
mjr 0:5acbbe3f4cf4 147 {
mjr 0:5acbbe3f4cf4 148 uint8_t *data = report.data;
mjr 1:d913e0afb2ac 149 if (data[0] == 64)
mjr 1:d913e0afb2ac 150 {
mjr 0:5acbbe3f4cf4 151 // LWZ-SBA - first four bytes are bit-packed on/off flags
mjr 0:5acbbe3f4cf4 152 // for the outputs; 5th byte is the pulse speed (0-7)
mjr 0:5acbbe3f4cf4 153 //printf("LWZ-SBA %02x %02x %02x %02x ; %02x\r\n",
mjr 0:5acbbe3f4cf4 154 // data[1], data[2], data[3], data[4], data[5]);
mjr 0:5acbbe3f4cf4 155
mjr 0:5acbbe3f4cf4 156 // update all on/off states
mjr 0:5acbbe3f4cf4 157 for (int i = 0, bit = 1, ri = 1 ; i < 32 ; ++i, bit <<= 1)
mjr 0:5acbbe3f4cf4 158 {
mjr 0:5acbbe3f4cf4 159 if (bit == 0x100) {
mjr 0:5acbbe3f4cf4 160 bit = 1;
mjr 0:5acbbe3f4cf4 161 ++ri;
mjr 0:5acbbe3f4cf4 162 }
mjr 1:d913e0afb2ac 163 wizOn[i] = ((data[ri] & bit) != 0);
mjr 0:5acbbe3f4cf4 164 }
mjr 0:5acbbe3f4cf4 165
mjr 1:d913e0afb2ac 166 // update the physical outputs
mjr 1:d913e0afb2ac 167 updateWizOuts();
mjr 0:5acbbe3f4cf4 168
mjr 0:5acbbe3f4cf4 169 // reset the PBA counter
mjr 0:5acbbe3f4cf4 170 pbaIdx = 0;
mjr 0:5acbbe3f4cf4 171 }
mjr 1:d913e0afb2ac 172 else
mjr 1:d913e0afb2ac 173 {
mjr 0:5acbbe3f4cf4 174 // LWZ-PBA - full state dump; each byte is one output
mjr 0:5acbbe3f4cf4 175 // in the current bank. pbaIdx keeps track of the bank;
mjr 0:5acbbe3f4cf4 176 // this is incremented implicitly by each PBA message.
mjr 0:5acbbe3f4cf4 177 //printf("LWZ-PBA[%d] %02x %02x %02x %02x %02x %02x %02x %02x\r\n",
mjr 0:5acbbe3f4cf4 178 // pbaIdx, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
mjr 0:5acbbe3f4cf4 179
mjr 0:5acbbe3f4cf4 180 // update all output profile settings
mjr 0:5acbbe3f4cf4 181 for (int i = 0 ; i < 8 ; ++i)
mjr 1:d913e0afb2ac 182 wizVal[pbaIdx + i] = data[i];
mjr 0:5acbbe3f4cf4 183
mjr 0:5acbbe3f4cf4 184 // update the physical LED state if this is the last bank
mjr 0:5acbbe3f4cf4 185 if (pbaIdx == 24)
mjr 1:d913e0afb2ac 186 updateWizOuts();
mjr 0:5acbbe3f4cf4 187
mjr 0:5acbbe3f4cf4 188 // advance to the next bank
mjr 0:5acbbe3f4cf4 189 pbaIdx = (pbaIdx + 8) & 31;
mjr 0:5acbbe3f4cf4 190 }
mjr 0:5acbbe3f4cf4 191 }
mjr 1:d913e0afb2ac 192
mjr 1:d913e0afb2ac 193 // check for plunger calibration
mjr 1:d913e0afb2ac 194 if (!calBtn)
mjr 0:5acbbe3f4cf4 195 {
mjr 1:d913e0afb2ac 196 // check the state
mjr 1:d913e0afb2ac 197 switch (calBtnState)
mjr 0:5acbbe3f4cf4 198 {
mjr 1:d913e0afb2ac 199 case 0:
mjr 1:d913e0afb2ac 200 // button not yet pushed - start debouncing
mjr 1:d913e0afb2ac 201 calBtnTimer.reset();
mjr 1:d913e0afb2ac 202 calBtnDownTime = calBtnTimer.read_ms();
mjr 1:d913e0afb2ac 203 calBtnState = 1;
mjr 1:d913e0afb2ac 204 break;
mjr 1:d913e0afb2ac 205
mjr 1:d913e0afb2ac 206 case 1:
mjr 1:d913e0afb2ac 207 // pushed, not yet debounced - if the debounce time has
mjr 1:d913e0afb2ac 208 // passed, start the hold period
mjr 1:d913e0afb2ac 209 if (calBtnTimer.read_ms() - calBtnDownTime > 50)
mjr 1:d913e0afb2ac 210 calBtnState = 2;
mjr 1:d913e0afb2ac 211 break;
mjr 1:d913e0afb2ac 212
mjr 1:d913e0afb2ac 213 case 2:
mjr 1:d913e0afb2ac 214 // in the hold period - if the button has been held down
mjr 1:d913e0afb2ac 215 // for the entire hold period, move to calibration mode
mjr 1:d913e0afb2ac 216 if (calBtnTimer.read_ms() - calBtnDownTime > 2050)
mjr 1:d913e0afb2ac 217 {
mjr 1:d913e0afb2ac 218 // enter calibration mode
mjr 1:d913e0afb2ac 219 calBtnState = 3;
mjr 1:d913e0afb2ac 220
mjr 1:d913e0afb2ac 221 // reset the calibration limits
mjr 1:d913e0afb2ac 222 plungerMax = 0;
mjr 1:d913e0afb2ac 223 plungerMin = npix;
mjr 1:d913e0afb2ac 224 }
mjr 1:d913e0afb2ac 225 break;
mjr 0:5acbbe3f4cf4 226 }
mjr 0:5acbbe3f4cf4 227 }
mjr 1:d913e0afb2ac 228 else
mjr 1:d913e0afb2ac 229 {
mjr 1:d913e0afb2ac 230 // Button released. If we're not already in calibration mode,
mjr 1:d913e0afb2ac 231 // reset the button state. Once calibration mode starts, it sticks
mjr 1:d913e0afb2ac 232 // until the calibration time elapses.
mjr 1:d913e0afb2ac 233 if (calBtnState != 3)
mjr 1:d913e0afb2ac 234 calBtnState = 0;
mjr 1:d913e0afb2ac 235 else if (calBtnTimer.read_ms() - calBtnDownTime > 32500)
mjr 1:d913e0afb2ac 236 calBtnState = 0;
mjr 1:d913e0afb2ac 237 }
mjr 1:d913e0afb2ac 238
mjr 1:d913e0afb2ac 239 // light/flash the calibration button light, if applicable
mjr 1:d913e0afb2ac 240 int newCalBtnLit = calBtnLit;
mjr 1:d913e0afb2ac 241 switch (calBtnState)
mjr 0:5acbbe3f4cf4 242 {
mjr 1:d913e0afb2ac 243 case 2:
mjr 1:d913e0afb2ac 244 // in the hold period - flash the light
mjr 1:d913e0afb2ac 245 newCalBtnLit = (((calBtnTimer.read_ms() - calBtnDownTime)/250) & 1);
mjr 1:d913e0afb2ac 246 break;
mjr 1:d913e0afb2ac 247
mjr 1:d913e0afb2ac 248 case 3:
mjr 1:d913e0afb2ac 249 // calibration mode - show steady on
mjr 1:d913e0afb2ac 250 newCalBtnLit = true;
mjr 1:d913e0afb2ac 251 break;
mjr 1:d913e0afb2ac 252
mjr 1:d913e0afb2ac 253 default:
mjr 1:d913e0afb2ac 254 // not calibrating/holding - show steady off
mjr 1:d913e0afb2ac 255 newCalBtnLit = false;
mjr 1:d913e0afb2ac 256 break;
mjr 1:d913e0afb2ac 257 }
mjr 1:d913e0afb2ac 258 if (calBtnLit != newCalBtnLit)
mjr 1:d913e0afb2ac 259 {
mjr 1:d913e0afb2ac 260 calBtnLit = newCalBtnLit;
mjr 1:d913e0afb2ac 261 calBtnLed = (calBtnLit ? 1 : 0);
mjr 1:d913e0afb2ac 262 }
mjr 1:d913e0afb2ac 263
mjr 1:d913e0afb2ac 264 // read the plunger sensor
mjr 1:d913e0afb2ac 265 int znew = z;
mjr 1:d913e0afb2ac 266 /* if (ccdTimer.read_ms() - t0ccd > 33) */
mjr 1:d913e0afb2ac 267 {
mjr 1:d913e0afb2ac 268 // read the sensor at reduced resolution
mjr 1:d913e0afb2ac 269 uint16_t pix[npix];
mjr 1:d913e0afb2ac 270 ccd.read(pix, npix, 0);
mjr 1:d913e0afb2ac 271
mjr 1:d913e0afb2ac 272 #if 0
mjr 1:d913e0afb2ac 273 // debug - send samples every 5 seconds
mjr 1:d913e0afb2ac 274 if (ccdDbgTimer.read_ms() - t0ccdDbg > 5000)
mjr 1:d913e0afb2ac 275 {
mjr 1:d913e0afb2ac 276 for (int i = 0 ; i < npix ; ++i)
mjr 1:d913e0afb2ac 277 printf("%x ", pix[i]);
mjr 1:d913e0afb2ac 278 printf("\r\n\r\n");
mjr 1:d913e0afb2ac 279
mjr 1:d913e0afb2ac 280 ccdDbgTimer.reset();
mjr 1:d913e0afb2ac 281 t0ccdDbg = ccdDbgTimer.read_ms();
mjr 0:5acbbe3f4cf4 282 }
mjr 1:d913e0afb2ac 283 #endif
mjr 1:d913e0afb2ac 284
mjr 1:d913e0afb2ac 285 // check which end is the brighter - this is the "tip" end
mjr 1:d913e0afb2ac 286 // of the plunger
mjr 1:d913e0afb2ac 287 long avg1 = (long(pix[0]) + long(pix[1]) + long(pix[2]) + long(pix[3]) + long(pix[4]))/5;
mjr 1:d913e0afb2ac 288 long avg2 = (long(pix[npix-1]) + long(pix[npix-2]) + long(pix[npix-3]) + long(pix[npix-4]) + long(pix[npix-5]))/5;
mjr 1:d913e0afb2ac 289
mjr 1:d913e0afb2ac 290 // figure the midpoint in the brightness
mjr 1:d913e0afb2ac 291 long midpt = (avg1 + avg2)/2 * 3;
mjr 1:d913e0afb2ac 292
mjr 1:d913e0afb2ac 293 // Work from the bright end to the dark end. VP interprets the
mjr 1:d913e0afb2ac 294 // Z axis value as the amount the plunger is pulled: the minimum
mjr 1:d913e0afb2ac 295 // is the rest position, the maximum is fully pulled. So we
mjr 1:d913e0afb2ac 296 // essentially want to report how much of the sensor is lit,
mjr 1:d913e0afb2ac 297 // since this increases as the plunger is pulled back.
mjr 1:d913e0afb2ac 298 int si = 1, di = 1;
mjr 1:d913e0afb2ac 299 if (avg1 < avg2)
mjr 1:d913e0afb2ac 300 si = npix - 1, di = -1;
mjr 0:5acbbe3f4cf4 301
mjr 1:d913e0afb2ac 302 // scan for the midpoint
mjr 1:d913e0afb2ac 303 for (int n = 1, i = si ; n < npix - 1 ; ++n, i += di)
mjr 1:d913e0afb2ac 304 {
mjr 1:d913e0afb2ac 305 // if we've crossed the midpoint, report this position
mjr 1:d913e0afb2ac 306 if (long(pix[i-1]) + long(pix[i]) + long(pix[i+1]) < midpt)
mjr 1:d913e0afb2ac 307 {
mjr 1:d913e0afb2ac 308 // note the new position
mjr 1:d913e0afb2ac 309 int pos = abs(i - si);
mjr 1:d913e0afb2ac 310
mjr 1:d913e0afb2ac 311 // Calibrate, or apply calibration, depending on the mode.
mjr 1:d913e0afb2ac 312 // In either case, normalize to a 0-127 range. VP appears to
mjr 1:d913e0afb2ac 313 // ignore negative Z axis values.
mjr 1:d913e0afb2ac 314 if (calBtnState == 3)
mjr 1:d913e0afb2ac 315 {
mjr 1:d913e0afb2ac 316 // calibrating - note if we're expanding the calibration envelope
mjr 1:d913e0afb2ac 317 if (pos < plungerMin)
mjr 1:d913e0afb2ac 318 plungerMin = pos;
mjr 1:d913e0afb2ac 319 if (pos > plungerMax)
mjr 1:d913e0afb2ac 320 plungerMax = pos;
mjr 1:d913e0afb2ac 321
mjr 1:d913e0afb2ac 322 // normalize to the full physical range while calibrating
mjr 1:d913e0afb2ac 323 znew = int(float(pos)/npix * 127);
mjr 1:d913e0afb2ac 324 }
mjr 1:d913e0afb2ac 325 else
mjr 1:d913e0afb2ac 326 {
mjr 1:d913e0afb2ac 327 // running normally - normalize to the calibration range
mjr 1:d913e0afb2ac 328 if (pos < plungerMin)
mjr 1:d913e0afb2ac 329 pos = plungerMin;
mjr 1:d913e0afb2ac 330 if (pos > plungerMax)
mjr 1:d913e0afb2ac 331 pos = plungerMax;
mjr 1:d913e0afb2ac 332 znew = int(float(pos - plungerMin)/(plungerMax - plungerMin + 1) * 127);
mjr 1:d913e0afb2ac 333 }
mjr 1:d913e0afb2ac 334
mjr 1:d913e0afb2ac 335 // done
mjr 1:d913e0afb2ac 336 break;
mjr 1:d913e0afb2ac 337 }
mjr 1:d913e0afb2ac 338 }
mjr 1:d913e0afb2ac 339
mjr 1:d913e0afb2ac 340 // reset the timer
mjr 1:d913e0afb2ac 341 ccdTimer.reset();
mjr 1:d913e0afb2ac 342 t0ccd = ccdTimer.read_ms();
mjr 1:d913e0afb2ac 343 }
mjr 1:d913e0afb2ac 344
mjr 1:d913e0afb2ac 345 // read the accelerometer
mjr 1:d913e0afb2ac 346 float xa, ya;
mjr 1:d913e0afb2ac 347 accel.getAccXY(xa, ya);
mjr 1:d913e0afb2ac 348
mjr 1:d913e0afb2ac 349 // check for auto-centering every so often
mjr 1:d913e0afb2ac 350 if (acTimer.read_ms() - t0ac > 1000)
mjr 1:d913e0afb2ac 351 {
mjr 1:d913e0afb2ac 352 // add the sample to the history list
mjr 1:d913e0afb2ac 353 accPrv[iAccPrv].x = xa;
mjr 1:d913e0afb2ac 354 accPrv[iAccPrv].y = ya;
mjr 1:d913e0afb2ac 355
mjr 1:d913e0afb2ac 356 // store the slot
mjr 1:d913e0afb2ac 357 iAccPrv += 1;
mjr 1:d913e0afb2ac 358 iAccPrv %= maxAccPrv;
mjr 1:d913e0afb2ac 359 nAccPrv += 1;
mjr 1:d913e0afb2ac 360
mjr 1:d913e0afb2ac 361 // If we have a full complement, check for stability. The
mjr 1:d913e0afb2ac 362 // raw accelerometer input is in the rnage -4096 to 4096, but
mjr 1:d913e0afb2ac 363 // the class cover normalizes to a unit interval (-1.0 .. +1.0).
mjr 1:d913e0afb2ac 364 const float accTol = .005;
mjr 1:d913e0afb2ac 365 if (nAccPrv >= maxAccPrv
mjr 1:d913e0afb2ac 366 && accPrv[0].dist(accPrv[1]) < accTol
mjr 1:d913e0afb2ac 367 && accPrv[0].dist(accPrv[2]) < accTol
mjr 1:d913e0afb2ac 368 && accPrv[0].dist(accPrv[3]) < accTol
mjr 1:d913e0afb2ac 369 && accPrv[0].dist(accPrv[4]) < accTol)
mjr 1:d913e0afb2ac 370 {
mjr 1:d913e0afb2ac 371 // figure the new center
mjr 1:d913e0afb2ac 372 xCenter = (accPrv[0].x + accPrv[1].x + accPrv[2].x + accPrv[3].x + accPrv[4].x)/5.0;
mjr 1:d913e0afb2ac 373 yCenter = (accPrv[0].y + accPrv[1].y + accPrv[2].y + accPrv[3].y + accPrv[4].y)/5.0;
mjr 1:d913e0afb2ac 374 }
mjr 1:d913e0afb2ac 375
mjr 1:d913e0afb2ac 376 // reset the auto-center timer
mjr 1:d913e0afb2ac 377 acTimer.reset();
mjr 1:d913e0afb2ac 378 t0ac = acTimer.read_ms();
mjr 1:d913e0afb2ac 379 }
mjr 1:d913e0afb2ac 380
mjr 1:d913e0afb2ac 381 // adjust for our auto centering
mjr 1:d913e0afb2ac 382 xa -= xCenter;
mjr 1:d913e0afb2ac 383 ya -= yCenter;
mjr 1:d913e0afb2ac 384
mjr 1:d913e0afb2ac 385 // confine to the unit interval
mjr 1:d913e0afb2ac 386 if (xa < -1.0) xa = -1.0;
mjr 1:d913e0afb2ac 387 if (xa > 1.0) xa = 1.0;
mjr 1:d913e0afb2ac 388 if (ya < -1.0) ya = -1.0;
mjr 1:d913e0afb2ac 389 if (ya > 1.0) ya = 1.0;
mjr 0:5acbbe3f4cf4 390
mjr 1:d913e0afb2ac 391 // figure the new mouse report data
mjr 1:d913e0afb2ac 392 int xnew = (int)(127 * xa);
mjr 1:d913e0afb2ac 393 int ynew = (int)(127 * ya);
mjr 1:d913e0afb2ac 394
mjr 1:d913e0afb2ac 395 // send an update if the position has changed
mjr 1:d913e0afb2ac 396 // if (xnew != x || ynew != y || znew != z)
mjr 0:5acbbe3f4cf4 397 {
mjr 1:d913e0afb2ac 398 x = xnew;
mjr 1:d913e0afb2ac 399 y = ynew;
mjr 1:d913e0afb2ac 400 z = znew;
mjr 1:d913e0afb2ac 401
mjr 1:d913e0afb2ac 402 // Send the status report. Note that the X axis needs to be
mjr 1:d913e0afb2ac 403 // reversed, becasue the native accelerometer reports seem to
mjr 1:d913e0afb2ac 404 // assume that the card is component side down.
mjr 1:d913e0afb2ac 405 js.update(x, -y, z, 0);
mjr 0:5acbbe3f4cf4 406 }
mjr 1:d913e0afb2ac 407
mjr 1:d913e0afb2ac 408 // show a heartbeat flash in blue every so often
mjr 1:d913e0afb2ac 409 if (hbTimer.read_ms() - t0Hb > 1000)
mjr 1:d913e0afb2ac 410 {
mjr 1:d913e0afb2ac 411 // invert the blue LED state
mjr 1:d913e0afb2ac 412 hb = !hb;
mjr 1:d913e0afb2ac 413 led3 = (hb ? .5 : 1);
mjr 1:d913e0afb2ac 414
mjr 1:d913e0afb2ac 415 // reset the heartbeat timer
mjr 1:d913e0afb2ac 416 hbTimer.reset();
mjr 1:d913e0afb2ac 417 t0Hb = hbTimer.read_ms();
mjr 1:d913e0afb2ac 418 }
mjr 1:d913e0afb2ac 419 }
mjr 0:5acbbe3f4cf4 420 }