Platform controller for the Mobile Arcade project

Dependencies:   APA102 Motor

Committer:
abraha2d
Date:
Tue Dec 11 17:29:25 2018 +0000
Revision:
3:7e5233f883c7
Parent:
2:774edcf60939
Better game/menu lighting

Who changed what in which revision?

UserRevisionLine numberNew contents of line
abraha2d 0:d4e7f9c1287f 1 #include "mbed.h"
abraha2d 0:d4e7f9c1287f 2 #include "Motor.h"
abraha2d 1:113469a23547 3 #include "APA102.h"
abraha2d 0:d4e7f9c1287f 4
abraha2d 1:113469a23547 5 #define NUM_LEDS 72
abraha2d 1:113469a23547 6
abraha2d 1:113469a23547 7 #define TAIL_BLINKER_START 0
abraha2d 1:113469a23547 8 #define NUM_TAIL_BLINKER 3
abraha2d 1:113469a23547 9 #define TAIL_REVERSE_START 3
abraha2d 1:113469a23547 10 #define NUM_TAIL_REVERSE 2
abraha2d 1:113469a23547 11
abraha2d 1:113469a23547 12 #define GLOW_START 6
abraha2d 1:113469a23547 13 #define NUM_GLOW 21
abraha2d 1:113469a23547 14
abraha2d 1:113469a23547 15 #define HEAD_FOG_START 28
abraha2d 1:113469a23547 16 #define NUM_HEAD_FOG 1
abraha2d 1:113469a23547 17
abraha2d 1:113469a23547 18 #define HEAD_BLINKER_START 30
abraha2d 1:113469a23547 19 #define NUM_HEAD_BLINKER 2
abraha2d 1:113469a23547 20 #define HEAD_LIGHT_START 32
abraha2d 1:113469a23547 21 #define NUM_HEAD_LIGHT 3
abraha2d 1:113469a23547 22
abraha2d 1:113469a23547 23 #define GAME_START 51
abraha2d 1:113469a23547 24 #define NUM_GAME 19
abraha2d 1:113469a23547 25
abraha2d 3:7e5233f883c7 26 #define COLOR_GAME_MENU CRGB(32, 32, 32)
abraha2d 3:7e5233f883c7 27 #define COLOR_GAME_GAME CRGB(0, 64, 128)
abraha2d 3:7e5233f883c7 28 #define COLOR_GAME_NUM 3
abraha2d 3:7e5233f883c7 29 #define COLOR_GAME_DEN 3
abraha2d 2:774edcf60939 30
abraha2d 1:113469a23547 31 #define COLOR_HEADLIGHT_DIM CRGB(8, 8, 8)
abraha2d 1:113469a23547 32 #define COLOR_HEADLIGHT_ON CRGB(32, 32, 32)
abraha2d 1:113469a23547 33 #define COLOR_FOGLIGHT CRGB(64, 64, 0)
abraha2d 0:d4e7f9c1287f 34
abraha2d 1:113469a23547 35 #define COLOR_TAILLIGHT CRGB(32, 0, 0)
abraha2d 1:113469a23547 36 #define COLOR_BRAKELIGHT CRGB(128, 0, 0)
abraha2d 1:113469a23547 37 #define COLOR_REVERSE CRGB(64, 64, 64)
abraha2d 1:113469a23547 38
abraha2d 1:113469a23547 39 #define COLOR_UNDERGLOW CRGB(0, 16, 0)
abraha2d 1:113469a23547 40
abraha2d 1:113469a23547 41 #define COLOR_BLINKER CRGB(128, 32, 0)
abraha2d 1:113469a23547 42 #define BLINK_DELAY 0.5
abraha2d 1:113469a23547 43
abraha2d 1:113469a23547 44 #define BLINKER_L 1
abraha2d 1:113469a23547 45 #define BLINKER_R 2
abraha2d 1:113469a23547 46 #define FOGLIGHT 4
abraha2d 1:113469a23547 47 #define REVERSE 8
abraha2d 1:113469a23547 48 #define UNDERGLOW 16
abraha2d 1:113469a23547 49 #define HEADLIGHT 32
abraha2d 1:113469a23547 50 #define BRAKELIGHT 64
abraha2d 2:774edcf60939 51 uint8_t lights = 0;
abraha2d 1:113469a23547 52
abraha2d 1:113469a23547 53 CRGB l_leds[NUM_LEDS];
abraha2d 1:113469a23547 54 CRGB r_leds[NUM_LEDS];
abraha2d 1:113469a23547 55
abraha2d 2:774edcf60939 56 int numGame = 0;
abraha2d 2:774edcf60939 57
abraha2d 2:774edcf60939 58 CRGB gameColor = COLOR_GAME_MENU;
abraha2d 3:7e5233f883c7 59 double gameBrightness = 0;
abraha2d 1:113469a23547 60
abraha2d 1:113469a23547 61 SPI l_strip(p5, p6, p7);
abraha2d 1:113469a23547 62 SPI r_strip(p11, p12, p13);
abraha2d 0:d4e7f9c1287f 63
abraha2d 0:d4e7f9c1287f 64 Motor l_motor(p21, p23, p22); // PWMA, AI1, AI2
abraha2d 0:d4e7f9c1287f 65 Motor r_motor(p26, p24, p25); // PWMB, BI1, BI2
abraha2d 0:d4e7f9c1287f 66
abraha2d 1:113469a23547 67 float l_vel = 0;
abraha2d 1:113469a23547 68 float r_vel = 0;
abraha2d 0:d4e7f9c1287f 69
abraha2d 1:113469a23547 70 Serial bt(p28, p27); // Bluefruit RX, TX
abraha2d 1:113469a23547 71 Serial pc(USBTX, USBRX);
abraha2d 1:113469a23547 72
abraha2d 2:774edcf60939 73 Thread pcThread;
abraha2d 1:113469a23547 74 Thread btThread;
abraha2d 1:113469a23547 75 Thread blinkerThread;
abraha2d 3:7e5233f883c7 76 Thread gameThread;
abraha2d 1:113469a23547 77
abraha2d 2:774edcf60939 78 void pc_thread() {
abraha2d 2:774edcf60939 79 for(;;) {
abraha2d 2:774edcf60939 80 while (!pc.readable()) wait(0.1);
abraha2d 2:774edcf60939 81 switch (pc.getc()) {
abraha2d 2:774edcf60939 82 case 's':
abraha2d 2:774edcf60939 83 // Switch to game
abraha2d 2:774edcf60939 84 while(pc.getc() != '\n'); // Flush rest of command
abraha2d 3:7e5233f883c7 85 while (gameBrightness > 0.1250168966) wait(0.01); // Wait for dim before switch
abraha2d 3:7e5233f883c7 86 for (int i = 0; i < 100; i++) {
abraha2d 3:7e5233f883c7 87 gameColor = CRGB(
abraha2d 3:7e5233f883c7 88 (COLOR_GAME_GAME.r - COLOR_GAME_MENU.r) * (i / 100.0) + COLOR_GAME_MENU.r,
abraha2d 3:7e5233f883c7 89 (COLOR_GAME_GAME.g - COLOR_GAME_MENU.g) * (i / 100.0) + COLOR_GAME_MENU.g,
abraha2d 3:7e5233f883c7 90 (COLOR_GAME_GAME.b - COLOR_GAME_MENU.b) * (i / 100.0) + COLOR_GAME_MENU.b
abraha2d 3:7e5233f883c7 91 );
abraha2d 3:7e5233f883c7 92 wait(0.01);
abraha2d 3:7e5233f883c7 93 }
abraha2d 2:774edcf60939 94 gameColor = COLOR_GAME_GAME;
abraha2d 2:774edcf60939 95 break;
abraha2d 2:774edcf60939 96 case 'e':
abraha2d 2:774edcf60939 97 // Switch to menu
abraha2d 2:774edcf60939 98 while(pc.getc() != '\n'); // Flush rest of command
abraha2d 3:7e5233f883c7 99 while (gameBrightness > 0.1250168966) wait(0.01); // Wait for dim before switch
abraha2d 3:7e5233f883c7 100 for (int i = 0; i < 100; i++) {
abraha2d 3:7e5233f883c7 101 gameColor = CRGB(
abraha2d 3:7e5233f883c7 102 (COLOR_GAME_MENU.r - COLOR_GAME_GAME.r) * (i / 100.0) + COLOR_GAME_GAME.r,
abraha2d 3:7e5233f883c7 103 (COLOR_GAME_MENU.g - COLOR_GAME_GAME.g) * (i / 100.0) + COLOR_GAME_GAME.g,
abraha2d 3:7e5233f883c7 104 (COLOR_GAME_MENU.b - COLOR_GAME_GAME.b) * (i / 100.0) + COLOR_GAME_GAME.b
abraha2d 3:7e5233f883c7 105 );
abraha2d 3:7e5233f883c7 106 wait(0.01);
abraha2d 3:7e5233f883c7 107 }
abraha2d 2:774edcf60939 108 gameColor = COLOR_GAME_MENU;
abraha2d 2:774edcf60939 109 break;
abraha2d 2:774edcf60939 110 case 'b':
abraha2d 2:774edcf60939 111 // Starting up
abraha2d 2:774edcf60939 112 while (numGame < NUM_GAME) {
abraha2d 2:774edcf60939 113 numGame++;
abraha2d 2:774edcf60939 114 wait(0.05);
abraha2d 2:774edcf60939 115 }
abraha2d 2:774edcf60939 116 lights = FOGLIGHT | UNDERGLOW | BRAKELIGHT;
abraha2d 2:774edcf60939 117 break;
abraha2d 2:774edcf60939 118 case 'h':
abraha2d 2:774edcf60939 119 // Shutting down
abraha2d 2:774edcf60939 120 lights = 0;
abraha2d 2:774edcf60939 121 while (numGame > 0) {
abraha2d 2:774edcf60939 122 numGame--;
abraha2d 2:774edcf60939 123 wait(0.05);
abraha2d 2:774edcf60939 124 }
abraha2d 2:774edcf60939 125 break;
abraha2d 2:774edcf60939 126 }
abraha2d 2:774edcf60939 127 }
abraha2d 2:774edcf60939 128 }
abraha2d 2:774edcf60939 129
abraha2d 1:113469a23547 130 void bt_thread() {
abraha2d 0:d4e7f9c1287f 131 char bnum = 0;
abraha2d 0:d4e7f9c1287f 132 char bhit = 0;
abraha2d 1:113469a23547 133 for(;;) {
abraha2d 1:113469a23547 134 while (!bt.readable()) wait(0.1);
abraha2d 0:d4e7f9c1287f 135 if (bt.getc() == '!' && bt.getc() == 'B') {
abraha2d 0:d4e7f9c1287f 136 bnum = bt.getc(); // button number
abraha2d 1:113469a23547 137 bhit = bt.getc(); // '1' = hit, '0' = release
abraha2d 0:d4e7f9c1287f 138 if (bt.getc() == char(~('!' + 'B' + bnum + bhit))) {
abraha2d 1:113469a23547 139 pc.printf("%i\n", bnum);
abraha2d 1:113469a23547 140 if (bnum == 53 && bhit == '1') { // UP
abraha2d 1:113469a23547 141 l_vel += 0.25f;
abraha2d 1:113469a23547 142 r_vel += 0.25f;
abraha2d 1:113469a23547 143 } else if (bnum == 54 && bhit == '1') { // DOWN
abraha2d 1:113469a23547 144 l_vel -= 0.25f;
abraha2d 1:113469a23547 145 r_vel -= 0.25f;
abraha2d 1:113469a23547 146 } else if (bnum == 55 && bhit == '1') { // LEFT
abraha2d 1:113469a23547 147 l_vel += 0.25f;
abraha2d 1:113469a23547 148 r_vel -= 0.25f;
abraha2d 1:113469a23547 149 } else if (bnum == 56 && bhit == '1') { // RIGHT
abraha2d 1:113469a23547 150 l_vel -= 0.25f;
abraha2d 1:113469a23547 151 r_vel += 0.25f;
abraha2d 1:113469a23547 152 } else if (bnum == '2' && bhit == '1') {
abraha2d 1:113469a23547 153 lights ^= FOGLIGHT;
abraha2d 1:113469a23547 154 }
abraha2d 1:113469a23547 155 l_motor.speed(l_vel);
abraha2d 1:113469a23547 156 r_motor.speed(r_vel);
abraha2d 1:113469a23547 157 if (bnum == '1' && bhit == '1') {
abraha2d 1:113469a23547 158 l_vel = 0;
abraha2d 1:113469a23547 159 r_vel = 0;
abraha2d 1:113469a23547 160 l_motor.brake(1);
abraha2d 1:113469a23547 161 r_motor.brake(1);
abraha2d 1:113469a23547 162 }
abraha2d 1:113469a23547 163 if (l_vel + r_vel > 0.01f) {
abraha2d 1:113469a23547 164 lights &= ~(BRAKELIGHT | REVERSE);
abraha2d 1:113469a23547 165 lights |= HEADLIGHT;
abraha2d 1:113469a23547 166 } else if (l_vel + r_vel < -0.01f) {
abraha2d 1:113469a23547 167 lights &= ~(BRAKELIGHT | HEADLIGHT);
abraha2d 1:113469a23547 168 lights |= REVERSE;
abraha2d 1:113469a23547 169 } else {
abraha2d 1:113469a23547 170 lights &= ~(HEADLIGHT | REVERSE);
abraha2d 1:113469a23547 171 lights |= BRAKELIGHT;
abraha2d 1:113469a23547 172 }
abraha2d 1:113469a23547 173 if (l_vel - r_vel > 0.01f) {
abraha2d 1:113469a23547 174 lights &= ~BLINKER_R;
abraha2d 1:113469a23547 175 lights |= BLINKER_L;
abraha2d 1:113469a23547 176 } else if (r_vel - l_vel > 0.01f) {
abraha2d 1:113469a23547 177 lights &= ~BLINKER_L;
abraha2d 1:113469a23547 178 lights |= BLINKER_R;
abraha2d 1:113469a23547 179 } else {
abraha2d 1:113469a23547 180 lights &= ~(BLINKER_L | BLINKER_R);
abraha2d 0:d4e7f9c1287f 181 }
abraha2d 0:d4e7f9c1287f 182 }
abraha2d 0:d4e7f9c1287f 183 }
abraha2d 0:d4e7f9c1287f 184 }
abraha2d 0:d4e7f9c1287f 185 }
abraha2d 0:d4e7f9c1287f 186
abraha2d 1:113469a23547 187 void blinker_thread() {
abraha2d 1:113469a23547 188 for (;;) {
abraha2d 1:113469a23547 189 while (!(lights & (BLINKER_L | BLINKER_R))) {
abraha2d 1:113469a23547 190 wait(0.1);
abraha2d 1:113469a23547 191 }
abraha2d 2:774edcf60939 192
abraha2d 1:113469a23547 193 if (lights & BLINKER_L) {
abraha2d 1:113469a23547 194 fill_solid(&(l_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, COLOR_BLINKER);
abraha2d 1:113469a23547 195 fill_solid(&(l_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, COLOR_BLINKER);
abraha2d 1:113469a23547 196 }
abraha2d 1:113469a23547 197 if (lights & BLINKER_R) {
abraha2d 1:113469a23547 198 fill_solid(&(r_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, COLOR_BLINKER);
abraha2d 1:113469a23547 199 fill_solid(&(r_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, COLOR_BLINKER);
abraha2d 1:113469a23547 200 }
abraha2d 1:113469a23547 201 wait(BLINK_DELAY);
abraha2d 2:774edcf60939 202
abraha2d 1:113469a23547 203 if (l_leds[HEAD_BLINKER_START] == COLOR_BLINKER) {
abraha2d 1:113469a23547 204 fill_solid(&(l_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, CRGB::Black);
abraha2d 1:113469a23547 205 fill_solid(&(l_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, CRGB::Black);
abraha2d 1:113469a23547 206 }
abraha2d 1:113469a23547 207 if (r_leds[HEAD_BLINKER_START] == COLOR_BLINKER) {
abraha2d 1:113469a23547 208 fill_solid(&(r_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, CRGB::Black);
abraha2d 1:113469a23547 209 fill_solid(&(r_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, CRGB::Black);
abraha2d 1:113469a23547 210 }
abraha2d 1:113469a23547 211 wait(BLINK_DELAY);
abraha2d 1:113469a23547 212 }
abraha2d 1:113469a23547 213 }
abraha2d 1:113469a23547 214
abraha2d 3:7e5233f883c7 215 void game_thread() {
abraha2d 3:7e5233f883c7 216 int bCtr = 0;
abraha2d 3:7e5233f883c7 217 for(;;) {
abraha2d 3:7e5233f883c7 218 gameBrightness = (exp(sin(bCtr*0.01570796327))-0.3678794412)*0.3722766811+0.125;
abraha2d 3:7e5233f883c7 219 bCtr = ++bCtr % 400;
abraha2d 3:7e5233f883c7 220 pc.printf("%i\r\n", bCtr);
abraha2d 3:7e5233f883c7 221 wait(0.01);
abraha2d 3:7e5233f883c7 222 }
abraha2d 3:7e5233f883c7 223 }
abraha2d 3:7e5233f883c7 224
abraha2d 0:d4e7f9c1287f 225 // main() runs in its own thread in the OS
abraha2d 1:113469a23547 226 int main() {
abraha2d 1:113469a23547 227
abraha2d 2:774edcf60939 228 // Jack up the SPI frequency
abraha2d 1:113469a23547 229 l_strip.frequency(4000000);
abraha2d 1:113469a23547 230 r_strip.frequency(4000000);
abraha2d 1:113469a23547 231
abraha2d 1:113469a23547 232 // Clear out the strip
abraha2d 1:113469a23547 233 fill_solid(l_leds, NUM_LEDS, CRGB::Black);
abraha2d 1:113469a23547 234 fill_solid(r_leds, NUM_LEDS, CRGB::Black);
abraha2d 1:113469a23547 235 APA102_write(l_strip, l_leds, NUM_LEDS);
abraha2d 1:113469a23547 236 APA102_write(r_strip, r_leds, NUM_LEDS);
abraha2d 1:113469a23547 237
abraha2d 1:113469a23547 238 // Start threads
abraha2d 2:774edcf60939 239 pcThread.start(pc_thread);
abraha2d 0:d4e7f9c1287f 240 btThread.start(bt_thread);
abraha2d 1:113469a23547 241 blinkerThread.start(blinker_thread);
abraha2d 3:7e5233f883c7 242 gameThread.start(game_thread);
abraha2d 1:113469a23547 243
abraha2d 1:113469a23547 244 for(;;) {
abraha2d 1:113469a23547 245
abraha2d 2:774edcf60939 246 if (lights) {
abraha2d 1:113469a23547 247
abraha2d 2:774edcf60939 248 fill_solid(&(l_leds[HEAD_LIGHT_START]), NUM_HEAD_LIGHT, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
abraha2d 2:774edcf60939 249 fill_solid(&(r_leds[HEAD_LIGHT_START]), NUM_HEAD_LIGHT, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
abraha2d 2:774edcf60939 250
abraha2d 2:774edcf60939 251 if (!(lights & BLINKER_L)) {
abraha2d 2:774edcf60939 252 fill_solid(&(l_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
abraha2d 2:774edcf60939 253 fill_solid(&(l_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
abraha2d 2:774edcf60939 254 }
abraha2d 2:774edcf60939 255
abraha2d 2:774edcf60939 256 if (!(lights & BLINKER_R)) {
abraha2d 2:774edcf60939 257 fill_solid(&(r_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
abraha2d 2:774edcf60939 258 fill_solid(&(r_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
abraha2d 2:774edcf60939 259 }
abraha2d 2:774edcf60939 260
abraha2d 2:774edcf60939 261 fill_solid(&(l_leds[HEAD_FOG_START]), NUM_HEAD_FOG, lights & FOGLIGHT ? COLOR_FOGLIGHT : CRGB::Black);
abraha2d 2:774edcf60939 262 fill_solid(&(r_leds[HEAD_FOG_START]), NUM_HEAD_FOG, lights & FOGLIGHT ? COLOR_FOGLIGHT : CRGB::Black);
abraha2d 2:774edcf60939 263
abraha2d 2:774edcf60939 264 fill_solid(&(l_leds[GLOW_START]), NUM_GLOW, lights & UNDERGLOW ? COLOR_UNDERGLOW : CRGB::Black);
abraha2d 2:774edcf60939 265 fill_solid(&(r_leds[GLOW_START]), NUM_GLOW, lights & UNDERGLOW ? COLOR_UNDERGLOW : CRGB::Black);
abraha2d 2:774edcf60939 266
abraha2d 2:774edcf60939 267 fill_solid(&(l_leds[TAIL_REVERSE_START]), NUM_TAIL_REVERSE, lights & REVERSE ? COLOR_REVERSE :
abraha2d 2:774edcf60939 268 lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
abraha2d 2:774edcf60939 269 fill_solid(&(r_leds[TAIL_REVERSE_START]), NUM_TAIL_REVERSE, lights & REVERSE ? COLOR_REVERSE :
abraha2d 2:774edcf60939 270 lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
abraha2d 2:774edcf60939 271
abraha2d 2:774edcf60939 272 } else {
abraha2d 2:774edcf60939 273
abraha2d 2:774edcf60939 274 fill_solid(&(l_leds[0]), NUM_LEDS, CRGB::Black);
abraha2d 2:774edcf60939 275 fill_solid(&(r_leds[0]), NUM_LEDS, CRGB::Black);
abraha2d 2:774edcf60939 276
abraha2d 1:113469a23547 277 }
abraha2d 1:113469a23547 278
abraha2d 2:774edcf60939 279 if (numGame != NUM_GAME) {
abraha2d 2:774edcf60939 280 fill_solid(&(l_leds[GAME_START]), NUM_GAME, CRGB::Black);
abraha2d 2:774edcf60939 281 fill_solid(&(r_leds[GAME_START]), NUM_GAME, CRGB::Black);
abraha2d 2:774edcf60939 282 }
abraha2d 3:7e5233f883c7 283 fill_solid(&(l_leds[GAME_START]), numGame, gameColor * gameBrightness);
abraha2d 3:7e5233f883c7 284 fill_solid(&(r_leds[GAME_START]), numGame, gameColor * gameBrightness);
abraha2d 1:113469a23547 285
abraha2d 1:113469a23547 286 APA102_write(l_strip, l_leds, NUM_LEDS);
abraha2d 1:113469a23547 287 APA102_write(r_strip, r_leds, NUM_LEDS);
abraha2d 1:113469a23547 288
abraha2d 1:113469a23547 289 wait(0);
abraha2d 0:d4e7f9c1287f 290 }
abraha2d 0:d4e7f9c1287f 291 }