Use Accelerometer and Joystick to mimic a mouse. This is for a class project. It is done for educational purpose. It is not practical to real world use.
Dependencies: C12832_lcd MMA7660 USBDevice mbed
accelestick.cpp@1:03d0f8a4a2d7, 2014-03-27 (annotated)
- Committer:
- thlu
- Date:
- Thu Mar 27 23:55:18 2014 +0000
- Revision:
- 1:03d0f8a4a2d7
- Parent:
- 0:22bdcdc386df
- Child:
- 2:3d012df30652
first working release for class project presentation
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
thlu | 1:03d0f8a4a2d7 | 1 | // Name: T.H. Lu |
thlu | 1:03d0f8a4a2d7 | 2 | // Date: 03/27/2014 |
thlu | 1:03d0f8a4a2d7 | 3 | // Description: |
thlu | 1:03d0f8a4a2d7 | 4 | // This program is not for practical use. It is my first mbed C code, |
thlu | 1:03d0f8a4a2d7 | 5 | // and is released only because my instructor mandates it. |
thlu | 1:03d0f8a4a2d7 | 6 | // The Accelestick uses the accelerometer and joystick on the mbed to emulate |
thlu | 1:03d0f8a4a2d7 | 7 | // a mouse. It is somewhat awkward to use, which is why it is only intended |
thlu | 1:03d0f8a4a2d7 | 8 | // for educational purpose. |
thlu | 1:03d0f8a4a2d7 | 9 | // The accelerometer provides the mouse movement, and the joystick acts as |
thlu | 1:03d0f8a4a2d7 | 10 | // the mouse buttons. A real-time debug mode prints messages onto the USB |
thlu | 1:03d0f8a4a2d7 | 11 | // serial interface. |
thlu | 1:03d0f8a4a2d7 | 12 | // Some features are: |
thlu | 1:03d0f8a4a2d7 | 13 | // 1. left joystick emulates left mouse button (with double click support) |
thlu | 1:03d0f8a4a2d7 | 14 | // right joystick emulates right mouse button, center position emulates |
thlu | 1:03d0f8a4a2d7 | 15 | // middle mouse button |
thlu | 1:03d0f8a4a2d7 | 16 | // 2. up and down joystick positions emulate mouse scroll |
thlu | 1:03d0f8a4a2d7 | 17 | // 3. push and hold left joystick for 1 second to initiate left mouse button |
thlu | 1:03d0f8a4a2d7 | 18 | // press and hold feature. LED1 will lit up. Push left joystick again to |
thlu | 1:03d0f8a4a2d7 | 19 | // release |
thlu | 1:03d0f8a4a2d7 | 20 | // 4. press joystick center position down twice to initiate accelestick |
thlu | 1:03d0f8a4a2d7 | 21 | // calibration. This will reduce cursor movement at rest position. LED3 |
thlu | 1:03d0f8a4a2d7 | 22 | // will flash rapidly and then remain lit when done |
thlu | 1:03d0f8a4a2d7 | 23 | // 5. push right joystick twice to enable debug mode printing. Debug messages |
thlu | 1:03d0f8a4a2d7 | 24 | // are written to USB serial (COM port). LED2 will lit when debug is on |
thlu | 1:03d0f8a4a2d7 | 25 | // LED4 will blink every second if accelestick is initialized properly |
thlu | 1:03d0f8a4a2d7 | 26 | // |
thlu | 1:03d0f8a4a2d7 | 27 | |
thlu | 0:22bdcdc386df | 28 | #include "accelestick.h" |
thlu | 0:22bdcdc386df | 29 | |
thlu | 1:03d0f8a4a2d7 | 30 | //--- Global Variables declaration ---// |
thlu | 1:03d0f8a4a2d7 | 31 | |
thlu | 1:03d0f8a4a2d7 | 32 | C12832_LCD lcd; // for debugging |
thlu | 1:03d0f8a4a2d7 | 33 | MMA7660 mma(p28, p27); // I2C Accelerometer |
thlu | 1:03d0f8a4a2d7 | 34 | USBMouseKeyboard mouse; // USB mouse |
thlu | 1:03d0f8a4a2d7 | 35 | DigitalOut leds[] = {LED1, LED2, LED3, LED4}; |
thlu | 1:03d0f8a4a2d7 | 36 | |
thlu | 1:03d0f8a4a2d7 | 37 | DigitalIn jd = p12; // joystick down |
thlu | 1:03d0f8a4a2d7 | 38 | DigitalIn jl = p13; // joystick left |
thlu | 1:03d0f8a4a2d7 | 39 | DigitalIn jc = p14; // joystick center |
thlu | 1:03d0f8a4a2d7 | 40 | DigitalIn ju = p15; // joystick up |
thlu | 1:03d0f8a4a2d7 | 41 | DigitalIn jr = p16; // joystick right |
thlu | 1:03d0f8a4a2d7 | 42 | BusIn joyb(p12, p13, p14, p15, p16); // joystick in vector form |
thlu | 1:03d0f8a4a2d7 | 43 | |
thlu | 1:03d0f8a4a2d7 | 44 | |
thlu | 1:03d0f8a4a2d7 | 45 | Max_min_t peaks; |
thlu | 1:03d0f8a4a2d7 | 46 | Mouse_state_t mouse_info; |
thlu | 1:03d0f8a4a2d7 | 47 | G_int_t offset; // calibration offset value |
thlu | 1:03d0f8a4a2d7 | 48 | |
thlu | 1:03d0f8a4a2d7 | 49 | int mouse_scroll = 0; // mouse scroll value |
thlu | 1:03d0f8a4a2d7 | 50 | bool calib_on = 0; // calibrate mouse |
thlu | 1:03d0f8a4a2d7 | 51 | bool debug_on = 0; // print debug message |
thlu | 1:03d0f8a4a2d7 | 52 | |
thlu | 1:03d0f8a4a2d7 | 53 | // two joystick active timers: one for long hold detection, one for double click detection |
thlu | 1:03d0f8a4a2d7 | 54 | uint8_t joystick_timers_active[2] = {JS_NONE,JS_NONE}; |
thlu | 1:03d0f8a4a2d7 | 55 | uint8_t debug_sel; |
thlu | 1:03d0f8a4a2d7 | 56 | |
thlu | 1:03d0f8a4a2d7 | 57 | G_float_t mma_g; // g values from accelerometer |
thlu | 1:03d0f8a4a2d7 | 58 | |
thlu | 1:03d0f8a4a2d7 | 59 | Ticker tk_led_alive; // Ticker for flashing LED as program alive beacon |
thlu | 1:03d0f8a4a2d7 | 60 | Ticker tk_print_debug; // Ticker for printing debug information |
thlu | 1:03d0f8a4a2d7 | 61 | Timer tm_joystick_dc; // Timer for joystick double-click detection |
thlu | 1:03d0f8a4a2d7 | 62 | Timer tm_joystick_lock; // Timer for locking mouse button position |
thlu | 1:03d0f8a4a2d7 | 63 | |
thlu | 1:03d0f8a4a2d7 | 64 | RawSerial debug_rs(USBTX, USBRX); // Raw serial is non-blocking, and is used for debugging |
thlu | 1:03d0f8a4a2d7 | 65 | |
thlu | 1:03d0f8a4a2d7 | 66 | // End of Global Variable Declaration |
thlu | 1:03d0f8a4a2d7 | 67 | |
thlu | 1:03d0f8a4a2d7 | 68 | |
thlu | 0:22bdcdc386df | 69 | inline void reset_tm_joystick_dc() |
thlu | 0:22bdcdc386df | 70 | { |
thlu | 1:03d0f8a4a2d7 | 71 | joystick_timers_active[0] = JS_NONE; |
thlu | 0:22bdcdc386df | 72 | tm_joystick_dc.stop(); |
thlu | 0:22bdcdc386df | 73 | tm_joystick_dc.reset(); |
thlu | 0:22bdcdc386df | 74 | } |
thlu | 0:22bdcdc386df | 75 | |
thlu | 1:03d0f8a4a2d7 | 76 | inline void reset_tm_joystick_lock() |
thlu | 1:03d0f8a4a2d7 | 77 | { |
thlu | 1:03d0f8a4a2d7 | 78 | joystick_timers_active[1] = JS_NONE; |
thlu | 1:03d0f8a4a2d7 | 79 | tm_joystick_lock.stop(); |
thlu | 1:03d0f8a4a2d7 | 80 | tm_joystick_lock.reset(); |
thlu | 1:03d0f8a4a2d7 | 81 | } |
thlu | 1:03d0f8a4a2d7 | 82 | |
thlu | 0:22bdcdc386df | 83 | // This function checks for joystick button presses which emulate a mouse's |
thlu | 0:22bdcdc386df | 84 | // left button, right button, middle button, double click, and scroll |
thlu | 1:03d0f8a4a2d7 | 85 | // features. Double click and press and hold detections are done using a timer |
thlu | 0:22bdcdc386df | 86 | void get_joystick_input() |
thlu | 0:22bdcdc386df | 87 | { |
thlu | 0:22bdcdc386df | 88 | static uint8_t prev_js = 0; |
thlu | 0:22bdcdc386df | 89 | static bool debug_sel_en = 0; |
thlu | 1:03d0f8a4a2d7 | 90 | static uint8_t mouse_lock = JS_NONE; |
thlu | 0:22bdcdc386df | 91 | |
thlu | 1:03d0f8a4a2d7 | 92 | // clear mouse buttons by default |
thlu | 0:22bdcdc386df | 93 | mouse_info.button = 0; |
thlu | 0:22bdcdc386df | 94 | mouse_info.scroll = 0; |
thlu | 0:22bdcdc386df | 95 | mouse_info.dc = 0; |
thlu | 0:22bdcdc386df | 96 | |
thlu | 0:22bdcdc386df | 97 | if (debug_on && debug_sel_en && (joyb != JS_NONE)) { |
thlu | 0:22bdcdc386df | 98 | debug_sel_en = 0; |
thlu | 0:22bdcdc386df | 99 | debug_sel = joyb; |
thlu | 1:03d0f8a4a2d7 | 100 | leds[LED_DEBUG] = 1; |
thlu | 0:22bdcdc386df | 101 | } |
thlu | 0:22bdcdc386df | 102 | |
thlu | 0:22bdcdc386df | 103 | if (debug_on && (debug_sel == JS_NONE) && (joyb == JS_NONE)) { |
thlu | 0:22bdcdc386df | 104 | debug_sel_en = 1; |
thlu | 0:22bdcdc386df | 105 | } |
thlu | 0:22bdcdc386df | 106 | |
thlu | 0:22bdcdc386df | 107 | switch(joyb) { // 1 = down, 2 = left, 4 = center, 8 = up, 16 = right |
thlu | 0:22bdcdc386df | 108 | case JS_LEFT: |
thlu | 0:22bdcdc386df | 109 | // 1 click = left button, 2 clicks = double click |
thlu | 1:03d0f8a4a2d7 | 110 | if ((prev_js != JS_LEFT) && (joystick_timers_active[0] == JS_LEFT)) { // double click left to lock |
thlu | 0:22bdcdc386df | 111 | mouse_info.dc = 1; |
thlu | 0:22bdcdc386df | 112 | reset_tm_joystick_dc(); |
thlu | 1:03d0f8a4a2d7 | 113 | } else if (!joystick_timers_active[0]) { |
thlu | 1:03d0f8a4a2d7 | 114 | joystick_timers_active[0] = JS_LEFT; |
thlu | 0:22bdcdc386df | 115 | tm_joystick_dc.start(); |
thlu | 0:22bdcdc386df | 116 | } |
thlu | 0:22bdcdc386df | 117 | mouse_info.button = MOUSE_LEFT; |
thlu | 0:22bdcdc386df | 118 | break; |
thlu | 0:22bdcdc386df | 119 | case JS_CENTER: // center |
thlu | 1:03d0f8a4a2d7 | 120 | if ((prev_js != JS_CENTER) && (joystick_timers_active[0] == JS_CENTER)) { // double click center to calibrate |
thlu | 0:22bdcdc386df | 121 | calib_on = 1; |
thlu | 0:22bdcdc386df | 122 | reset_tm_joystick_dc(); |
thlu | 1:03d0f8a4a2d7 | 123 | } else if (!joystick_timers_active[0]) { |
thlu | 1:03d0f8a4a2d7 | 124 | joystick_timers_active[0] = JS_CENTER; |
thlu | 0:22bdcdc386df | 125 | tm_joystick_dc.start(); |
thlu | 0:22bdcdc386df | 126 | |
thlu | 0:22bdcdc386df | 127 | } |
thlu | 0:22bdcdc386df | 128 | mouse_info.button = MOUSE_MIDDLE; |
thlu | 0:22bdcdc386df | 129 | break; |
thlu | 0:22bdcdc386df | 130 | case JS_RIGHT: |
thlu | 1:03d0f8a4a2d7 | 131 | if ((prev_js != JS_RIGHT) && (joystick_timers_active[0] == JS_RIGHT)) { // double click left to turn debug on/off |
thlu | 0:22bdcdc386df | 132 | debug_on = !debug_on; |
thlu | 0:22bdcdc386df | 133 | reset_tm_joystick_dc(); |
thlu | 0:22bdcdc386df | 134 | lcd.cls(); |
thlu | 0:22bdcdc386df | 135 | lcd.locate(0,0); |
thlu | 0:22bdcdc386df | 136 | if (debug_on) { |
thlu | 0:22bdcdc386df | 137 | lcd.printf("Debug print is ON\n"); |
thlu | 0:22bdcdc386df | 138 | debug_sel = JS_NONE; |
thlu | 0:22bdcdc386df | 139 | debug_sel_en = 0; |
thlu | 1:03d0f8a4a2d7 | 140 | } else { |
thlu | 1:03d0f8a4a2d7 | 141 | leds[LED_DEBUG] = 0; |
thlu | 0:22bdcdc386df | 142 | } |
thlu | 1:03d0f8a4a2d7 | 143 | } else if (!joystick_timers_active[0]) { |
thlu | 1:03d0f8a4a2d7 | 144 | joystick_timers_active[0] = JS_RIGHT; |
thlu | 0:22bdcdc386df | 145 | tm_joystick_dc.start(); |
thlu | 0:22bdcdc386df | 146 | } |
thlu | 0:22bdcdc386df | 147 | mouse_info.button = MOUSE_RIGHT; |
thlu | 0:22bdcdc386df | 148 | break; |
thlu | 0:22bdcdc386df | 149 | case JS_DOWN: // down |
thlu | 0:22bdcdc386df | 150 | reset_tm_joystick_dc(); |
thlu | 0:22bdcdc386df | 151 | break; |
thlu | 0:22bdcdc386df | 152 | case JS_UP: // up |
thlu | 0:22bdcdc386df | 153 | reset_tm_joystick_dc(); |
thlu | 0:22bdcdc386df | 154 | break; |
thlu | 0:22bdcdc386df | 155 | } |
thlu | 0:22bdcdc386df | 156 | |
thlu | 1:03d0f8a4a2d7 | 157 | // Update mouse scroll value |
thlu | 1:03d0f8a4a2d7 | 158 | switch (joyb) { |
thlu | 1:03d0f8a4a2d7 | 159 | case JS_DOWN: // down |
thlu | 1:03d0f8a4a2d7 | 160 | mouse_scroll++; |
thlu | 1:03d0f8a4a2d7 | 161 | break; |
thlu | 1:03d0f8a4a2d7 | 162 | case JS_UP: // up |
thlu | 1:03d0f8a4a2d7 | 163 | mouse_scroll--; |
thlu | 1:03d0f8a4a2d7 | 164 | break; |
thlu | 1:03d0f8a4a2d7 | 165 | default: |
thlu | 1:03d0f8a4a2d7 | 166 | mouse_scroll = 0; |
thlu | 1:03d0f8a4a2d7 | 167 | } |
thlu | 1:03d0f8a4a2d7 | 168 | mouse_info.scroll = mouse_scroll; |
thlu | 0:22bdcdc386df | 169 | |
thlu | 1:03d0f8a4a2d7 | 170 | // timeouit for double-click detectino |
thlu | 1:03d0f8a4a2d7 | 171 | if (tm_joystick_dc.read_ms() > 1000) { |
thlu | 0:22bdcdc386df | 172 | reset_tm_joystick_dc(); |
thlu | 0:22bdcdc386df | 173 | } |
thlu | 0:22bdcdc386df | 174 | |
thlu | 1:03d0f8a4a2d7 | 175 | // only support mouse lock feature for left button |
thlu | 1:03d0f8a4a2d7 | 176 | if ((prev_js != joyb) && (joyb == JS_LEFT)) { // click JS_LEFT to unlock |
thlu | 1:03d0f8a4a2d7 | 177 | if (mouse_lock == JS_LEFT) { |
thlu | 1:03d0f8a4a2d7 | 178 | mouse_lock = JS_NONE; |
thlu | 1:03d0f8a4a2d7 | 179 | } else if (joystick_timers_active[1] == JS_NONE) { |
thlu | 1:03d0f8a4a2d7 | 180 | joystick_timers_active[1] = JS_LEFT; |
thlu | 1:03d0f8a4a2d7 | 181 | tm_joystick_lock.start(); |
thlu | 1:03d0f8a4a2d7 | 182 | } |
thlu | 1:03d0f8a4a2d7 | 183 | } |
thlu | 1:03d0f8a4a2d7 | 184 | |
thlu | 1:03d0f8a4a2d7 | 185 | if (joyb != JS_LEFT) { |
thlu | 1:03d0f8a4a2d7 | 186 | reset_tm_joystick_lock(); |
thlu | 1:03d0f8a4a2d7 | 187 | // hold JS_LEFT for 1.2 sec to lock |
thlu | 1:03d0f8a4a2d7 | 188 | } else if ((joystick_timers_active[1] == JS_LEFT) && tm_joystick_lock.read_ms() > 1000) { |
thlu | 1:03d0f8a4a2d7 | 189 | mouse_lock = JS_LEFT; |
thlu | 1:03d0f8a4a2d7 | 190 | } |
thlu | 1:03d0f8a4a2d7 | 191 | |
thlu | 0:22bdcdc386df | 192 | prev_js = joyb; |
thlu | 1:03d0f8a4a2d7 | 193 | |
thlu | 1:03d0f8a4a2d7 | 194 | if (mouse_lock == JS_LEFT) { |
thlu | 1:03d0f8a4a2d7 | 195 | mouse_info.button = MOUSE_LEFT; |
thlu | 1:03d0f8a4a2d7 | 196 | } |
thlu | 1:03d0f8a4a2d7 | 197 | leds[LED_LOCK] = (mouse_lock == JS_LEFT); |
thlu | 0:22bdcdc386df | 198 | } |
thlu | 0:22bdcdc386df | 199 | |
thlu | 0:22bdcdc386df | 200 | |
thlu | 0:22bdcdc386df | 201 | void sample_mma() // Accelerometer value ranges from -1.5 to 1.5 |
thlu | 0:22bdcdc386df | 202 | { |
thlu | 0:22bdcdc386df | 203 | mma_g.x = mma.x(); |
thlu | 0:22bdcdc386df | 204 | mma_g.y = mma.y(); |
thlu | 0:22bdcdc386df | 205 | mma_g.z = mma.z(); |
thlu | 0:22bdcdc386df | 206 | G_int_t current; |
thlu | 0:22bdcdc386df | 207 | |
thlu | 0:22bdcdc386df | 208 | if (mma_g.x > peaks.max_x) { |
thlu | 0:22bdcdc386df | 209 | peaks.max_x = mma_g.x; |
thlu | 0:22bdcdc386df | 210 | } else if (mma_g.x < peaks.min_x) { |
thlu | 0:22bdcdc386df | 211 | peaks.min_x = mma_g.x; |
thlu | 0:22bdcdc386df | 212 | } |
thlu | 0:22bdcdc386df | 213 | if (mma_g.y > peaks.max_y) { |
thlu | 0:22bdcdc386df | 214 | peaks.max_y = mma_g.y; |
thlu | 0:22bdcdc386df | 215 | } else if (mma_g.y < peaks.min_y) { |
thlu | 0:22bdcdc386df | 216 | peaks.min_y = mma_g.y; |
thlu | 0:22bdcdc386df | 217 | } |
thlu | 0:22bdcdc386df | 218 | if (mma_g.z > peaks.max_z) { |
thlu | 0:22bdcdc386df | 219 | peaks.max_z = mma_g.z; |
thlu | 0:22bdcdc386df | 220 | } else if (mma_g.z < peaks.min_z) { |
thlu | 0:22bdcdc386df | 221 | peaks.min_z = mma_g.z; |
thlu | 0:22bdcdc386df | 222 | } |
thlu | 0:22bdcdc386df | 223 | |
thlu | 0:22bdcdc386df | 224 | current = conv_g2int(mma_g); |
thlu | 0:22bdcdc386df | 225 | if (calib_on) { |
thlu | 0:22bdcdc386df | 226 | calib_mma(current); |
thlu | 0:22bdcdc386df | 227 | } |
thlu | 0:22bdcdc386df | 228 | mouse_info.x = current.x - offset.x; |
thlu | 0:22bdcdc386df | 229 | mouse_info.y = current.y - offset.y; |
thlu | 0:22bdcdc386df | 230 | mouse_info.z = current.z - offset.z; |
thlu | 0:22bdcdc386df | 231 | detect_mma_rest(); |
thlu | 0:22bdcdc386df | 232 | } |
thlu | 0:22bdcdc386df | 233 | |
thlu | 1:03d0f8a4a2d7 | 234 | void update_mouse() |
thlu | 0:22bdcdc386df | 235 | { |
thlu | 0:22bdcdc386df | 236 | // x-direction is reversed on PC screen |
thlu | 0:22bdcdc386df | 237 | mouse.move(-mouse_info.x, mouse_info.y); |
thlu | 0:22bdcdc386df | 238 | mouse.press(mouse_info.button); |
thlu | 0:22bdcdc386df | 239 | mouse.scroll(mouse_info.scroll); |
thlu | 1:03d0f8a4a2d7 | 240 | |
thlu | 0:22bdcdc386df | 241 | if (mouse_info.dc) { |
thlu | 0:22bdcdc386df | 242 | mouse.doubleClick(); |
thlu | 0:22bdcdc386df | 243 | } |
thlu | 0:22bdcdc386df | 244 | } |
thlu | 0:22bdcdc386df | 245 | |
thlu | 0:22bdcdc386df | 246 | // Used for debugging |
thlu | 0:22bdcdc386df | 247 | void print_debug_msg() |
thlu | 0:22bdcdc386df | 248 | { |
thlu | 0:22bdcdc386df | 249 | if (debug_on) { |
thlu | 0:22bdcdc386df | 250 | switch (debug_sel) { |
thlu | 0:22bdcdc386df | 251 | case JS_LEFT: |
thlu | 1:03d0f8a4a2d7 | 252 | debug_rs.printf("Mx = %1.2f, mx = %1.2f ", peaks.max_x, peaks.min_x); |
thlu | 1:03d0f8a4a2d7 | 253 | debug_rs.printf("My = %1.2f, my = %1.2f ", peaks.max_y, peaks.min_y); |
thlu | 1:03d0f8a4a2d7 | 254 | debug_rs.printf("Mz = %1.2f, mz = %1.2f\r\n", peaks.max_z, peaks.min_z); |
thlu | 0:22bdcdc386df | 255 | break; |
thlu | 0:22bdcdc386df | 256 | case JS_CENTER: |
thlu | 1:03d0f8a4a2d7 | 257 | debug_rs.printf("x=%1.2f y=%1.2f z=%1.2f\r\n", mma_g.x, mma_g.y, mma_g.z); |
thlu | 1:03d0f8a4a2d7 | 258 | debug_rs.printf(" x=%0d, y=%0d, z=%0d, button=%0d, scroll=%0d, dc=%0d\r\n", |
thlu | 1:03d0f8a4a2d7 | 259 | mouse_info.x, mouse_info.y, mouse_info.z, mouse_info.button, |
thlu | 1:03d0f8a4a2d7 | 260 | mouse_info.scroll, mouse_info.dc); |
thlu | 0:22bdcdc386df | 261 | break; |
thlu | 0:22bdcdc386df | 262 | case JS_RIGHT: |
thlu | 1:03d0f8a4a2d7 | 263 | debug_rs.printf("offset.x=%0d, y=%0d, z=%0d\r\n", offset.x, offset.y, offset.z); |
thlu | 1:03d0f8a4a2d7 | 264 | break; |
thlu | 1:03d0f8a4a2d7 | 265 | case JS_UP: |
thlu | 1:03d0f8a4a2d7 | 266 | debug_rs.printf("scroll = %0d\r\n", mouse_scroll); |
thlu | 0:22bdcdc386df | 267 | break; |
thlu | 0:22bdcdc386df | 268 | } |
thlu | 0:22bdcdc386df | 269 | } |
thlu | 0:22bdcdc386df | 270 | } |
thlu | 0:22bdcdc386df | 271 | |
thlu | 1:03d0f8a4a2d7 | 272 | // Calibrate the accelerometer to work on non-level surface. This function is blocking. |
thlu | 0:22bdcdc386df | 273 | void calib_mma(const G_int_t current) |
thlu | 0:22bdcdc386df | 274 | { |
thlu | 0:22bdcdc386df | 275 | static uint8_t ctr = 0; |
thlu | 0:22bdcdc386df | 276 | static G_int_t prev[CALIB_SMPLS]; // average array |
thlu | 1:03d0f8a4a2d7 | 277 | Ticker tk_led_calib; |
thlu | 0:22bdcdc386df | 278 | |
thlu | 0:22bdcdc386df | 279 | int temp; |
thlu | 0:22bdcdc386df | 280 | |
thlu | 1:03d0f8a4a2d7 | 281 | tk_led_calib.attach(&flash_led2, 0.05); |
thlu | 1:03d0f8a4a2d7 | 282 | |
thlu | 1:03d0f8a4a2d7 | 283 | if (debug_on) { |
thlu | 1:03d0f8a4a2d7 | 284 | if (ctr == 0) { |
thlu | 1:03d0f8a4a2d7 | 285 | lcd.cls(); |
thlu | 1:03d0f8a4a2d7 | 286 | lcd.locate(0,0); |
thlu | 1:03d0f8a4a2d7 | 287 | lcd.printf("Calibrating mma"); |
thlu | 1:03d0f8a4a2d7 | 288 | wait(3); |
thlu | 1:03d0f8a4a2d7 | 289 | } else { |
thlu | 1:03d0f8a4a2d7 | 290 | lcd.printf("."); |
thlu | 1:03d0f8a4a2d7 | 291 | } |
thlu | 0:22bdcdc386df | 292 | } |
thlu | 1:03d0f8a4a2d7 | 293 | |
thlu | 0:22bdcdc386df | 294 | prev[ctr++] = current; |
thlu | 0:22bdcdc386df | 295 | |
thlu | 0:22bdcdc386df | 296 | if (ctr == CALIB_SMPLS) { |
thlu | 0:22bdcdc386df | 297 | temp = 0; |
thlu | 0:22bdcdc386df | 298 | for (uint8_t i=0; i<CALIB_SMPLS; i++) { |
thlu | 1:03d0f8a4a2d7 | 299 | debug_rs.printf("CALIB[%0d]: x=%0d, y=%0d, z=%0d\r\n", i, prev[i].x, prev[i].y, prev[i].z); |
thlu | 0:22bdcdc386df | 300 | temp += prev[i].x; |
thlu | 0:22bdcdc386df | 301 | } |
thlu | 0:22bdcdc386df | 302 | offset.x = temp/CALIB_SMPLS; // average |
thlu | 0:22bdcdc386df | 303 | |
thlu | 0:22bdcdc386df | 304 | temp = 0; |
thlu | 0:22bdcdc386df | 305 | for (uint8_t i=0; i<CALIB_SMPLS; i++) { |
thlu | 0:22bdcdc386df | 306 | temp += prev[i].y; |
thlu | 0:22bdcdc386df | 307 | } |
thlu | 0:22bdcdc386df | 308 | offset.y = temp/CALIB_SMPLS; |
thlu | 0:22bdcdc386df | 309 | |
thlu | 0:22bdcdc386df | 310 | temp = 0; |
thlu | 0:22bdcdc386df | 311 | for (uint8_t i=0; i<CALIB_SMPLS; i++) { |
thlu | 0:22bdcdc386df | 312 | temp += prev[i].z; |
thlu | 0:22bdcdc386df | 313 | } |
thlu | 0:22bdcdc386df | 314 | offset.z = temp/CALIB_SMPLS; |
thlu | 0:22bdcdc386df | 315 | |
thlu | 0:22bdcdc386df | 316 | ctr = 0; |
thlu | 0:22bdcdc386df | 317 | calib_on = 0; // calibration done |
thlu | 1:03d0f8a4a2d7 | 318 | |
thlu | 1:03d0f8a4a2d7 | 319 | if (debug_on) { |
thlu | 1:03d0f8a4a2d7 | 320 | lcd.cls(); |
thlu | 1:03d0f8a4a2d7 | 321 | lcd.locate(0,0); |
thlu | 1:03d0f8a4a2d7 | 322 | lcd.printf("Calibration Completed!\n"); |
thlu | 1:03d0f8a4a2d7 | 323 | wait(1); |
thlu | 1:03d0f8a4a2d7 | 324 | lcd.cls(); |
thlu | 1:03d0f8a4a2d7 | 325 | } |
thlu | 1:03d0f8a4a2d7 | 326 | |
thlu | 1:03d0f8a4a2d7 | 327 | tk_led_calib.detach(); |
thlu | 1:03d0f8a4a2d7 | 328 | leds[LED_CALIB] = 1; |
thlu | 0:22bdcdc386df | 329 | } |
thlu | 0:22bdcdc386df | 330 | } |
thlu | 0:22bdcdc386df | 331 | |
thlu | 1:03d0f8a4a2d7 | 332 | // use calibrated mouse x,y,z values to detect rest |
thlu | 0:22bdcdc386df | 333 | void detect_mma_rest () |
thlu | 0:22bdcdc386df | 334 | { |
thlu | 0:22bdcdc386df | 335 | if ((abs(mouse_info.z) <= 0.06*SCALE_Z) && |
thlu | 1:03d0f8a4a2d7 | 336 | (abs(mouse_info.x) <= 0.10*SCALE_X) && |
thlu | 1:03d0f8a4a2d7 | 337 | (abs(mouse_info.y) <= 0.10*SCALE_Y)) { |
thlu | 0:22bdcdc386df | 338 | mouse_info.x = 0; |
thlu | 0:22bdcdc386df | 339 | mouse_info.y = 0; |
thlu | 0:22bdcdc386df | 340 | } |
thlu | 0:22bdcdc386df | 341 | } |
thlu | 0:22bdcdc386df | 342 | |
thlu | 0:22bdcdc386df | 343 | // convert mma signed g float value into signed int value |
thlu | 0:22bdcdc386df | 344 | G_int_t conv_g2int (G_float_t mma_g) |
thlu | 0:22bdcdc386df | 345 | { |
thlu | 0:22bdcdc386df | 346 | G_int_t temp; |
thlu | 0:22bdcdc386df | 347 | |
thlu | 0:22bdcdc386df | 348 | temp.x = (mma_g.x * SCALE_X); |
thlu | 0:22bdcdc386df | 349 | temp.y = (mma_g.y * SCALE_Y); |
thlu | 0:22bdcdc386df | 350 | temp.z = (mma_g.z * SCALE_Z); |
thlu | 0:22bdcdc386df | 351 | return temp; |
thlu | 0:22bdcdc386df | 352 | } |
thlu | 0:22bdcdc386df | 353 | |
thlu | 1:03d0f8a4a2d7 | 354 | |
thlu | 1:03d0f8a4a2d7 | 355 | // Ticker cannot attach to functions with parameters |
thlu | 1:03d0f8a4a2d7 | 356 | void flash_led2() |
thlu | 0:22bdcdc386df | 357 | { |
thlu | 1:03d0f8a4a2d7 | 358 | leds[LED_CALIB] = !leds[LED_CALIB]; |
thlu | 1:03d0f8a4a2d7 | 359 | } |
thlu | 1:03d0f8a4a2d7 | 360 | void flash_led3() |
thlu | 1:03d0f8a4a2d7 | 361 | { |
thlu | 1:03d0f8a4a2d7 | 362 | leds[LED_ALIVE] = !leds[LED_ALIVE]; |
thlu | 0:22bdcdc386df | 363 | } |
thlu | 0:22bdcdc386df | 364 | |
thlu | 0:22bdcdc386df | 365 | int8_t init_accelestick() |
thlu | 0:22bdcdc386df | 366 | { |
thlu | 0:22bdcdc386df | 367 | lcd.cls(); |
thlu | 0:22bdcdc386df | 368 | reset_tm_joystick_dc(); |
thlu | 1:03d0f8a4a2d7 | 369 | reset_tm_joystick_lock(); |
thlu | 0:22bdcdc386df | 370 | |
thlu | 0:22bdcdc386df | 371 | offset.x = 0; |
thlu | 0:22bdcdc386df | 372 | offset.y = 0; |
thlu | 0:22bdcdc386df | 373 | offset.z = 1.0*SCALE_Z; |
thlu | 0:22bdcdc386df | 374 | |
thlu | 0:22bdcdc386df | 375 | peaks.max_x=ACCEL_MIN, peaks.max_y=ACCEL_MIN, peaks.max_z=ACCEL_MIN; |
thlu | 0:22bdcdc386df | 376 | peaks.min_x=ACCEL_MAX, peaks.min_y=ACCEL_MAX, peaks.min_z=ACCEL_MAX; |
thlu | 0:22bdcdc386df | 377 | |
thlu | 0:22bdcdc386df | 378 | if (!mma.testConnection()) { |
thlu | 0:22bdcdc386df | 379 | lcd.printf("Error in MMA init\n"); |
thlu | 0:22bdcdc386df | 380 | return -1; |
thlu | 0:22bdcdc386df | 381 | } |
thlu | 1:03d0f8a4a2d7 | 382 | tk_led_alive.attach(&flash_led3, 1.0); |
thlu | 0:22bdcdc386df | 383 | tk_print_debug.attach(&print_debug_msg, 1.0); |
thlu | 0:22bdcdc386df | 384 | return 0; |
thlu | 0:22bdcdc386df | 385 | |
thlu | 0:22bdcdc386df | 386 | } |
thlu | 0:22bdcdc386df | 387 | |
thlu | 1:03d0f8a4a2d7 | 388 | void run_accelestick() |
thlu | 0:22bdcdc386df | 389 | { |
thlu | 1:03d0f8a4a2d7 | 390 | get_joystick_input(); |
thlu | 1:03d0f8a4a2d7 | 391 | sample_mma(); |
thlu | 1:03d0f8a4a2d7 | 392 | update_mouse(); |
thlu | 0:22bdcdc386df | 393 | } |
thlu | 0:22bdcdc386df | 394 |