Two player imu pong
Dependencies: 4DGL-uLCD-SE IMUfilter LSM9DS0 PinDetect mbed
main.cpp@0:941225f01ccc, 2015-10-22 (annotated)
- Committer:
- rrr93
- Date:
- Thu Oct 22 16:50:22 2015 +0000
- Revision:
- 0:941225f01ccc
qewrt
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
rrr93 | 0:941225f01ccc | 1 | #include "mbed.h" |
rrr93 | 0:941225f01ccc | 2 | #include "PinDetect.h" |
rrr93 | 0:941225f01ccc | 3 | #include "uLCD_4DGL.h" |
rrr93 | 0:941225f01ccc | 4 | #include "Speaker.h" |
rrr93 | 0:941225f01ccc | 5 | #include "paddle.h" |
rrr93 | 0:941225f01ccc | 6 | #include "ball.h" |
rrr93 | 0:941225f01ccc | 7 | #include "soundBuilder.h" |
rrr93 | 0:941225f01ccc | 8 | #include "LSM9DS0.h" |
rrr93 | 0:941225f01ccc | 9 | |
rrr93 | 0:941225f01ccc | 10 | Serial pc(USBTX, USBRX); |
rrr93 | 0:941225f01ccc | 11 | //IMU |
rrr93 | 0:941225f01ccc | 12 | // SDO_XM and SDO_G are pulled up, so our addresses are: |
rrr93 | 0:941225f01ccc | 13 | #define LSM9DS0_XM_ADDR 0x1D // Would be 0x1E if SDO_XM is LOW |
rrr93 | 0:941225f01ccc | 14 | #define LSM9DS0_G_ADDR 0x6B // Would be 0x6A if SDO_G is LOW |
rrr93 | 0:941225f01ccc | 15 | LSM9DS0 imu(p9, p10, LSM9DS0_G_ADDR, LSM9DS0_XM_ADDR); |
rrr93 | 0:941225f01ccc | 16 | LSM9DS0 imu2(p28,p27, LSM9DS0_G_ADDR, LSM9DS0_XM_ADDR); |
rrr93 | 0:941225f01ccc | 17 | |
rrr93 | 0:941225f01ccc | 18 | // Pushbuttons |
rrr93 | 0:941225f01ccc | 19 | PinDetect pbUp(p15); |
rrr93 | 0:941225f01ccc | 20 | PinDetect pbDown(p16); |
rrr93 | 0:941225f01ccc | 21 | // uLCD |
rrr93 | 0:941225f01ccc | 22 | uLCD_4DGL uLCD(p13, p14, p29); |
rrr93 | 0:941225f01ccc | 23 | //Speaker |
rrr93 | 0:941225f01ccc | 24 | Speaker mySpeaker(p21); |
rrr93 | 0:941225f01ccc | 25 | |
rrr93 | 0:941225f01ccc | 26 | // Global variables needed for the push button interrupts |
rrr93 | 0:941225f01ccc | 27 | Paddle paddle(40, 3, 118,1); |
rrr93 | 0:941225f01ccc | 28 | Paddle paddle2(40,3, 8, 1); |
rrr93 | 0:941225f01ccc | 29 | Ball ball(p19, 1.6,1.2,5,50,21); |
rrr93 | 0:941225f01ccc | 30 | |
rrr93 | 0:941225f01ccc | 31 | // State machine definitions |
rrr93 | 0:941225f01ccc | 32 | enum gameStateType {START, WAIT, GAME_SETUP, GAME, LOSE}; |
rrr93 | 0:941225f01ccc | 33 | /* State Definitions: |
rrr93 | 0:941225f01ccc | 34 | * START -- Creates the start screen |
rrr93 | 0:941225f01ccc | 35 | * WAIT -- After the start screen, goes into wait where mbed spins and does nothing |
rrr93 | 0:941225f01ccc | 36 | * GAME_SETUP -- Sets up one time things (like boarders, initializes beginning velocity |
rrr93 | 0:941225f01ccc | 37 | * GAME -- When the user actually gets to play |
rrr93 | 0:941225f01ccc | 38 | * LOSE -- clears the screen, prints you lose, waits, then goes back to start |
rrr93 | 0:941225f01ccc | 39 | */ |
rrr93 | 0:941225f01ccc | 40 | |
rrr93 | 0:941225f01ccc | 41 | // Global state machine variable (So that the pushbuttons can modify it) |
rrr93 | 0:941225f01ccc | 42 | gameStateType gameState = START; |
rrr93 | 0:941225f01ccc | 43 | |
rrr93 | 0:941225f01ccc | 44 | // Pushbutton callbacks |
rrr93 | 0:941225f01ccc | 45 | // WARNING: Do not call to draw anything to the uLCD in these |
rrr93 | 0:941225f01ccc | 46 | // as this will cause the uLCD to crash sometimes. Update positions |
rrr93 | 0:941225f01ccc | 47 | // and draw elsewhere (like it's done here). |
rrr93 | 0:941225f01ccc | 48 | // Only modify the logic inside the callback functions. |
rrr93 | 0:941225f01ccc | 49 | void pbUp_hit_callback (void) |
rrr93 | 0:941225f01ccc | 50 | { |
rrr93 | 0:941225f01ccc | 51 | switch (gameState) |
rrr93 | 0:941225f01ccc | 52 | { |
rrr93 | 0:941225f01ccc | 53 | case WAIT: |
rrr93 | 0:941225f01ccc | 54 | gameState = GAME_SETUP; |
rrr93 | 0:941225f01ccc | 55 | break; |
rrr93 | 0:941225f01ccc | 56 | case GAME: |
rrr93 | 0:941225f01ccc | 57 | paddle.movePaddle(true); |
rrr93 | 0:941225f01ccc | 58 | paddle2.movePaddle(true); |
rrr93 | 0:941225f01ccc | 59 | break; |
rrr93 | 0:941225f01ccc | 60 | } |
rrr93 | 0:941225f01ccc | 61 | } |
rrr93 | 0:941225f01ccc | 62 | |
rrr93 | 0:941225f01ccc | 63 | void pbDown_hit_callback (void) |
rrr93 | 0:941225f01ccc | 64 | { |
rrr93 | 0:941225f01ccc | 65 | switch (gameState) |
rrr93 | 0:941225f01ccc | 66 | { |
rrr93 | 0:941225f01ccc | 67 | case WAIT: |
rrr93 | 0:941225f01ccc | 68 | gameState = GAME_SETUP; |
rrr93 | 0:941225f01ccc | 69 | break; |
rrr93 | 0:941225f01ccc | 70 | case GAME: |
rrr93 | 0:941225f01ccc | 71 | paddle.movePaddle(false); |
rrr93 | 0:941225f01ccc | 72 | paddle2.movePaddle(false); |
rrr93 | 0:941225f01ccc | 73 | break; |
rrr93 | 0:941225f01ccc | 74 | } |
rrr93 | 0:941225f01ccc | 75 | } |
rrr93 | 0:941225f01ccc | 76 | |
rrr93 | 0:941225f01ccc | 77 | int main() |
rrr93 | 0:941225f01ccc | 78 | { |
rrr93 | 0:941225f01ccc | 79 | |
rrr93 | 0:941225f01ccc | 80 | //IMU |
rrr93 | 0:941225f01ccc | 81 | uint16_t status = imu.begin(); |
rrr93 | 0:941225f01ccc | 82 | //Make sure communication is working |
rrr93 | 0:941225f01ccc | 83 | pc.printf("LSM9DS0 WHO_AM_I's returned: 0x%X\n", status); |
rrr93 | 0:941225f01ccc | 84 | pc.printf("Should be 0x49D4\n\n"); |
rrr93 | 0:941225f01ccc | 85 | |
rrr93 | 0:941225f01ccc | 86 | uint16_t status2 = imu2.begin(); |
rrr93 | 0:941225f01ccc | 87 | //Make sure communication is working |
rrr93 | 0:941225f01ccc | 88 | pc.printf("LSM9DS0 #2 WHO_AM_I's returned: 0x%X\n", status2); |
rrr93 | 0:941225f01ccc | 89 | pc.printf("Should be 0x49D4\n\n"); |
rrr93 | 0:941225f01ccc | 90 | |
rrr93 | 0:941225f01ccc | 91 | |
rrr93 | 0:941225f01ccc | 92 | |
rrr93 | 0:941225f01ccc | 93 | float IMU_offset = 0.14; //detrmined empirically |
rrr93 | 0:941225f01ccc | 94 | |
rrr93 | 0:941225f01ccc | 95 | // This is setting up the pushbuttons |
rrr93 | 0:941225f01ccc | 96 | // Don't modify this code. |
rrr93 | 0:941225f01ccc | 97 | pbUp.mode(PullUp); |
rrr93 | 0:941225f01ccc | 98 | pbDown.mode(PullUp); |
rrr93 | 0:941225f01ccc | 99 | wait(0.1); |
rrr93 | 0:941225f01ccc | 100 | pbUp.attach_deasserted(&pbUp_hit_callback); |
rrr93 | 0:941225f01ccc | 101 | pbDown.attach_deasserted(&pbDown_hit_callback); |
rrr93 | 0:941225f01ccc | 102 | pbUp.setSampleFrequency(); |
rrr93 | 0:941225f01ccc | 103 | pbDown.setSampleFrequency(); |
rrr93 | 0:941225f01ccc | 104 | // Don't modify this code. |
rrr93 | 0:941225f01ccc | 105 | |
rrr93 | 0:941225f01ccc | 106 | uLCD.display_control(PORTRAIT); |
rrr93 | 0:941225f01ccc | 107 | uLCD.cls(); |
rrr93 | 0:941225f01ccc | 108 | uLCD.baudrate(BAUD_3000000); |
rrr93 | 0:941225f01ccc | 109 | uLCD.background_color(BLACK); |
rrr93 | 0:941225f01ccc | 110 | |
rrr93 | 0:941225f01ccc | 111 | // Initialize all your variables outside the while/switch statement |
rrr93 | 0:941225f01ccc | 112 | // to avoid compiler warning/errors |
rrr93 | 0:941225f01ccc | 113 | int i = 0; |
rrr93 | 0:941225f01ccc | 114 | int random; |
rrr93 | 0:941225f01ccc | 115 | |
rrr93 | 0:941225f01ccc | 116 | //paddle stuff |
rrr93 | 0:941225f01ccc | 117 | int pmoveMin = 25; |
rrr93 | 0:941225f01ccc | 118 | int pmoveMax = 70; |
rrr93 | 0:941225f01ccc | 119 | int pmove; |
rrr93 | 0:941225f01ccc | 120 | |
rrr93 | 0:941225f01ccc | 121 | while (1) |
rrr93 | 0:941225f01ccc | 122 | { |
rrr93 | 0:941225f01ccc | 123 | switch (gameState) |
rrr93 | 0:941225f01ccc | 124 | { |
rrr93 | 0:941225f01ccc | 125 | case START: |
rrr93 | 0:941225f01ccc | 126 | uLCD.cls(); |
rrr93 | 0:941225f01ccc | 127 | uLCD.locate(0,0); |
rrr93 | 0:941225f01ccc | 128 | uLCD.printf("Pong!!!\n\n"); |
rrr93 | 0:941225f01ccc | 129 | uLCD.printf("Press Key to Start"); |
rrr93 | 0:941225f01ccc | 130 | gameState = WAIT; |
rrr93 | 0:941225f01ccc | 131 | ball.setX(50); |
rrr93 | 0:941225f01ccc | 132 | ball.setY(50); |
rrr93 | 0:941225f01ccc | 133 | break; |
rrr93 | 0:941225f01ccc | 134 | case GAME_SETUP: |
rrr93 | 0:941225f01ccc | 135 | uLCD.cls(); |
rrr93 | 0:941225f01ccc | 136 | uLCD.line(0, 0, 127, 0, 0xCFB53B); |
rrr93 | 0:941225f01ccc | 137 | uLCD.line(127, 0, 127, 127, 0xCFB53B); |
rrr93 | 0:941225f01ccc | 138 | uLCD.line(127, 127, 0, 127, 0xCFB53B); |
rrr93 | 0:941225f01ccc | 139 | uLCD.line(0, 127, 0, 0, 0xCFB53B); |
rrr93 | 0:941225f01ccc | 140 | ball.setBaseVx(2.0); |
rrr93 | 0:941225f01ccc | 141 | ball.setBaseVy(2.0); |
rrr93 | 0:941225f01ccc | 142 | random = rand() % 1; |
rrr93 | 0:941225f01ccc | 143 | ball.setVxSign(-1); ball.setVySign(((float)random - 0.5)*2); |
rrr93 | 0:941225f01ccc | 144 | paddle.initDraw(&uLCD); |
rrr93 | 0:941225f01ccc | 145 | paddle2.initDraw(&uLCD); |
rrr93 | 0:941225f01ccc | 146 | |
rrr93 | 0:941225f01ccc | 147 | Note note1(4000.0, 0.7, 0.5); |
rrr93 | 0:941225f01ccc | 148 | Note note2(3000.0, 0.3, 0.5); |
rrr93 | 0:941225f01ccc | 149 | Note note3(2000.0, 0.3, 0.5); |
rrr93 | 0:941225f01ccc | 150 | Note note4(1000.0, 0.7, 0.5); |
rrr93 | 0:941225f01ccc | 151 | Note note5(2500.0, 0.3, 0.5); |
rrr93 | 0:941225f01ccc | 152 | SoundBuilder sound(&mySpeaker); |
rrr93 | 0:941225f01ccc | 153 | sound.addNote(note1); |
rrr93 | 0:941225f01ccc | 154 | sound.addNote(note2); |
rrr93 | 0:941225f01ccc | 155 | sound.addNote(note3); |
rrr93 | 0:941225f01ccc | 156 | sound.addNote(note4); |
rrr93 | 0:941225f01ccc | 157 | sound.addNote(note5); |
rrr93 | 0:941225f01ccc | 158 | sound.playSong(); |
rrr93 | 0:941225f01ccc | 159 | gameState = GAME; |
rrr93 | 0:941225f01ccc | 160 | break; |
rrr93 | 0:941225f01ccc | 161 | case GAME: |
rrr93 | 0:941225f01ccc | 162 | if(ball.CheckHit()) |
rrr93 | 0:941225f01ccc | 163 | { |
rrr93 | 0:941225f01ccc | 164 | Note note(1000.0, 0.03, 0.5); |
rrr93 | 0:941225f01ccc | 165 | SoundBuilder sound(&mySpeaker); |
rrr93 | 0:941225f01ccc | 166 | sound.addNote(note); |
rrr93 | 0:941225f01ccc | 167 | sound.playSong(); |
rrr93 | 0:941225f01ccc | 168 | } |
rrr93 | 0:941225f01ccc | 169 | |
rrr93 | 0:941225f01ccc | 170 | if (paddle.checkHitY(ball.getFutureX(), ball.getFutureY(), ball.getRadius())) |
rrr93 | 0:941225f01ccc | 171 | { |
rrr93 | 0:941225f01ccc | 172 | |
rrr93 | 0:941225f01ccc | 173 | ball.reverseYDirection(); |
rrr93 | 0:941225f01ccc | 174 | } |
rrr93 | 0:941225f01ccc | 175 | |
rrr93 | 0:941225f01ccc | 176 | if (paddle2.checkHitY(ball.getFutureX(), ball.getFutureY(), ball.getRadius())) |
rrr93 | 0:941225f01ccc | 177 | { |
rrr93 | 0:941225f01ccc | 178 | |
rrr93 | 0:941225f01ccc | 179 | ball.reverseYDirection(); |
rrr93 | 0:941225f01ccc | 180 | } |
rrr93 | 0:941225f01ccc | 181 | |
rrr93 | 0:941225f01ccc | 182 | if (ball.CheckLose()) |
rrr93 | 0:941225f01ccc | 183 | {gameState = LOSE;} |
rrr93 | 0:941225f01ccc | 184 | if (paddle.checkHitX(ball.getFutureX(), ball.getFutureY(), ball.getRadius(),false)) |
rrr93 | 0:941225f01ccc | 185 | { |
rrr93 | 0:941225f01ccc | 186 | Note note(4000.0, 0.03, 0.5); |
rrr93 | 0:941225f01ccc | 187 | SoundBuilder sound(&mySpeaker); |
rrr93 | 0:941225f01ccc | 188 | sound.addNote(note); |
rrr93 | 0:941225f01ccc | 189 | sound.playSong(); |
rrr93 | 0:941225f01ccc | 190 | |
rrr93 | 0:941225f01ccc | 191 | ball.reverseXDirection(); |
rrr93 | 0:941225f01ccc | 192 | uLCD.locate(1,1); |
rrr93 | 0:941225f01ccc | 193 | } |
rrr93 | 0:941225f01ccc | 194 | |
rrr93 | 0:941225f01ccc | 195 | if (paddle2.checkHitX(ball.getFutureX(), ball.getFutureY(), ball.getRadius(),true)) |
rrr93 | 0:941225f01ccc | 196 | { |
rrr93 | 0:941225f01ccc | 197 | Note note(4000.0, 0.03, 0.5); |
rrr93 | 0:941225f01ccc | 198 | SoundBuilder sound(&mySpeaker); |
rrr93 | 0:941225f01ccc | 199 | sound.addNote(note); |
rrr93 | 0:941225f01ccc | 200 | sound.playSong(); |
rrr93 | 0:941225f01ccc | 201 | ball.reverseXDirection(); |
rrr93 | 0:941225f01ccc | 202 | uLCD.locate(1,1); |
rrr93 | 0:941225f01ccc | 203 | } |
rrr93 | 0:941225f01ccc | 204 | |
rrr93 | 0:941225f01ccc | 205 | |
rrr93 | 0:941225f01ccc | 206 | ball.update(&uLCD); |
rrr93 | 0:941225f01ccc | 207 | imu.readAccel(); |
rrr93 | 0:941225f01ccc | 208 | |
rrr93 | 0:941225f01ccc | 209 | imu2.readAccel(); |
rrr93 | 0:941225f01ccc | 210 | |
rrr93 | 0:941225f01ccc | 211 | if ( imu.ax + IMU_offset > 0.1) |
rrr93 | 0:941225f01ccc | 212 | { |
rrr93 | 0:941225f01ccc | 213 | paddle.movePaddle(true); |
rrr93 | 0:941225f01ccc | 214 | } |
rrr93 | 0:941225f01ccc | 215 | else if (imu.ax+ IMU_offset < -0.1) |
rrr93 | 0:941225f01ccc | 216 | { |
rrr93 | 0:941225f01ccc | 217 | paddle.movePaddle(false); |
rrr93 | 0:941225f01ccc | 218 | } |
rrr93 | 0:941225f01ccc | 219 | |
rrr93 | 0:941225f01ccc | 220 | if ( imu2.ax + IMU_offset > 0.1) |
rrr93 | 0:941225f01ccc | 221 | { |
rrr93 | 0:941225f01ccc | 222 | paddle2.movePaddle(true); |
rrr93 | 0:941225f01ccc | 223 | } |
rrr93 | 0:941225f01ccc | 224 | else if (imu2.ax+ IMU_offset < -0.1) |
rrr93 | 0:941225f01ccc | 225 | { |
rrr93 | 0:941225f01ccc | 226 | paddle2.movePaddle(false); |
rrr93 | 0:941225f01ccc | 227 | } |
rrr93 | 0:941225f01ccc | 228 | |
rrr93 | 0:941225f01ccc | 229 | // We can assume that these for loops are quick enough that the paddle will move only one interval. |
rrr93 | 0:941225f01ccc | 230 | // These movements of the paddle have been optimized. Feel free to draw it out to see how it's been done. |
rrr93 | 0:941225f01ccc | 231 | paddle.redraw(&uLCD); |
rrr93 | 0:941225f01ccc | 232 | paddle2.redraw(&uLCD); |
rrr93 | 0:941225f01ccc | 233 | break; |
rrr93 | 0:941225f01ccc | 234 | case LOSE: |
rrr93 | 0:941225f01ccc | 235 | uLCD.cls(); |
rrr93 | 0:941225f01ccc | 236 | uLCD.printf("YOU LOSE D:"); |
rrr93 | 0:941225f01ccc | 237 | Note note6(3000.0, 0.7, 0.5); |
rrr93 | 0:941225f01ccc | 238 | Note note7(2000.0, 0.3, 0.5); |
rrr93 | 0:941225f01ccc | 239 | Note note8(1000.0, 0.3, 0.5); |
rrr93 | 0:941225f01ccc | 240 | Note note9(2300.0, 0.7, 0.5); |
rrr93 | 0:941225f01ccc | 241 | Note note10(2500.0, 0.3, 0.5); |
rrr93 | 0:941225f01ccc | 242 | SoundBuilder sound2(&mySpeaker); |
rrr93 | 0:941225f01ccc | 243 | sound2.addNote(note6); |
rrr93 | 0:941225f01ccc | 244 | sound2.addNote(note7); |
rrr93 | 0:941225f01ccc | 245 | sound2.addNote(note8); |
rrr93 | 0:941225f01ccc | 246 | sound2.addNote(note9); |
rrr93 | 0:941225f01ccc | 247 | sound2.addNote(note10); |
rrr93 | 0:941225f01ccc | 248 | sound2.playSong(); |
rrr93 | 0:941225f01ccc | 249 | paddle.resetScore(); |
rrr93 | 0:941225f01ccc | 250 | paddle2.resetScore(); |
rrr93 | 0:941225f01ccc | 251 | wait(5.0); |
rrr93 | 0:941225f01ccc | 252 | gameState = START; |
rrr93 | 0:941225f01ccc | 253 | break; |
rrr93 | 0:941225f01ccc | 254 | case WAIT: |
rrr93 | 0:941225f01ccc | 255 | // Used to seed the rand() function so we don't get the same starting position every time. |
rrr93 | 0:941225f01ccc | 256 | i++; |
rrr93 | 0:941225f01ccc | 257 | break; |
rrr93 | 0:941225f01ccc | 258 | } |
rrr93 | 0:941225f01ccc | 259 | } |
rrr93 | 0:941225f01ccc | 260 | } |