Platform controller for the Mobile Arcade project

Dependencies:   APA102 Motor

Revision:
1:113469a23547
Parent:
0:d4e7f9c1287f
Child:
2:774edcf60939
--- a/main.cpp	Fri Nov 30 20:15:39 2018 +0000
+++ b/main.cpp	Tue Dec 11 06:34:25 2018 +0000
@@ -1,60 +1,223 @@
 #include "mbed.h"
 #include "Motor.h"
+#include "APA102.h"
 
-DigitalOut led1(LED1);
+#define NUM_LEDS            72
+
+#define TAIL_BLINKER_START  0
+#define NUM_TAIL_BLINKER    3
+#define TAIL_REVERSE_START  3
+#define NUM_TAIL_REVERSE    2
+
+#define GLOW_START          6
+#define NUM_GLOW            21
+
+#define HEAD_FOG_START      28
+#define NUM_HEAD_FOG        1
+
+#define HEAD_BLINKER_START  30
+#define NUM_HEAD_BLINKER    2
+#define HEAD_LIGHT_START    32
+#define NUM_HEAD_LIGHT      3
+
+#define GAME_START          51
+#define NUM_GAME            19
+
+#define COLOR_HEADLIGHT_DIM CRGB(8, 8, 8)
+#define COLOR_HEADLIGHT_ON  CRGB(32, 32, 32)
+#define COLOR_FOGLIGHT      CRGB(64, 64, 0)
 
-// TB6612   mbed
-// PWMA     21
-// AI2      22
-// AI1      23
-// BI1      24
-// BI2      25
-// PWMB     26
+#define COLOR_TAILLIGHT     CRGB(32, 0, 0)
+#define COLOR_BRAKELIGHT    CRGB(128, 0, 0)
+#define COLOR_REVERSE       CRGB(64, 64, 64)
+
+#define COLOR_UNDERGLOW     CRGB(0, 16, 0)
+#define COLOR_GAME          CRGB(0, 2, 3)
+
+#define COLOR_BLINKER       CRGB(128, 32, 0)
+#define BLINK_DELAY         0.5
+
+#define BLINKER_L           1
+#define BLINKER_R           2
+#define FOGLIGHT            4
+#define REVERSE             8
+#define UNDERGLOW           16
+#define HEADLIGHT           32
+#define BRAKELIGHT          64
+uint8_t lights = FOGLIGHT | UNDERGLOW | BRAKELIGHT;
+
+CRGB l_leds[NUM_LEDS];
+CRGB r_leds[NUM_LEDS];
+
+CRGB gameColor = COLOR_GAME;
+
+SPI l_strip(p5, p6, p7);
+SPI r_strip(p11, p12, p13);
 
 Motor l_motor(p21, p23, p22);   // PWMA, AI1, AI2
 Motor r_motor(p26, p24, p25);   // PWMB, BI1, BI2
 
-Serial bt(p28, p27);     // Bluefruit RX, TX
-Thread btThread;
+float l_vel = 0;
+float r_vel = 0;
 
-void bt_thread()
-{
+Serial bt(p28, p27);    // Bluefruit RX, TX
+Serial pc(USBTX, USBRX);
+
+Thread btThread;
+Thread blinkerThread;
+
+void bt_thread() {
     char bnum = 0;
     char bhit = 0;
-    while(1) {
-        while (!bt.readable()) wait(0.01);
+    for(;;) {
+        while (!bt.readable()) wait(0.1);
         if (bt.getc() == '!' && bt.getc() == 'B') {
             bnum = bt.getc(); // button number
-            bhit = bt.getc(); // 1 = hit, 0 = release
+            bhit = bt.getc(); // '1' = hit, '0' = release
             if (bt.getc() == char(~('!' + 'B' + bnum + bhit))) {
-                switch (bnum) {
-                    case '1': // number button 1
-                        l_motor.speed(bhit == '1' ? 1.0f : 0);
-                        break;
-                    case '2': // number button 2
-                        r_motor.speed(bhit == '1' ? 1.0f : 0);
-                        break;
-                    case '3': // number button 3
-                        l_motor.speed(bhit == '1' ? -1.0f : 0);
-                        break;
-                    case '4': // number button 4
-                        r_motor.speed(bhit == '1' ? -1.0f : 0);
-                        break;
-                    default:
-                        break;
+                pc.printf("%i\n", bnum);
+                if (bnum == 53 && bhit == '1') { // UP
+                    l_vel += 0.25f;
+                    r_vel += 0.25f;
+                } else if (bnum == 54 && bhit == '1') { // DOWN
+                    l_vel -= 0.25f;
+                    r_vel -= 0.25f;
+                } else if (bnum == 55 && bhit == '1') { // LEFT
+                    l_vel += 0.25f;
+                    r_vel -= 0.25f;
+                } else if (bnum == 56 && bhit == '1') { // RIGHT
+                    l_vel -= 0.25f;
+                    r_vel += 0.25f;
+                } else if (bnum == '2' && bhit == '1') {
+                    lights ^= FOGLIGHT;
+                }
+                l_motor.speed(l_vel);
+                r_motor.speed(r_vel);
+                if (bnum == '1' && bhit == '1') {
+                    l_vel = 0;
+                    r_vel = 0;
+                    l_motor.brake(1);
+                    r_motor.brake(1);
+                }
+                if (l_vel + r_vel > 0.01f) {
+                    lights &= ~(BRAKELIGHT | REVERSE);
+                    lights |= HEADLIGHT;
+                } else if (l_vel + r_vel < -0.01f) {
+                    lights &= ~(BRAKELIGHT | HEADLIGHT);
+                    lights |= REVERSE;
+                } else {
+                    lights &= ~(HEADLIGHT | REVERSE);
+                    lights |= BRAKELIGHT;
+                }
+                if (l_vel - r_vel > 0.01f) {
+                    lights &= ~BLINKER_R;
+                    lights |= BLINKER_L;
+                } else if (r_vel - l_vel > 0.01f) {
+                    lights &= ~BLINKER_L;
+                    lights |= BLINKER_R;
+                } else {
+                    lights &= ~(BLINKER_L | BLINKER_R);
                 }
             }
         }
     }
 }
 
+void blinker_thread() {
+  for (;;) {
+    while (!(lights & (BLINKER_L | BLINKER_R))) {
+      wait(0.1);
+    }
+
+    if (lights & BLINKER_L) {
+      fill_solid(&(l_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, COLOR_BLINKER);
+      fill_solid(&(l_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, COLOR_BLINKER);
+    }
+    if (lights & BLINKER_R) {
+      fill_solid(&(r_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, COLOR_BLINKER);
+      fill_solid(&(r_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, COLOR_BLINKER);
+    }
+    wait(BLINK_DELAY);
+
+    if (l_leds[HEAD_BLINKER_START] == COLOR_BLINKER) {
+      fill_solid(&(l_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, CRGB::Black);
+      fill_solid(&(l_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, CRGB::Black);
+    }
+    if (r_leds[HEAD_BLINKER_START] == COLOR_BLINKER) {
+      fill_solid(&(r_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, CRGB::Black);
+      fill_solid(&(r_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, CRGB::Black);
+    }
+    wait(BLINK_DELAY);
+  }
+}
+
 // main() runs in its own thread in the OS
-int main()
-{
+int main() {
+    
+    // Jack up the frequency
+    l_strip.frequency(4000000);
+    r_strip.frequency(4000000);
+    
+    // Clear out the strip
+    fill_solid(l_leds, NUM_LEDS, CRGB::Black);
+    fill_solid(r_leds, NUM_LEDS, CRGB::Black);
+    APA102_write(l_strip, l_leds, NUM_LEDS);
+    APA102_write(r_strip, r_leds, NUM_LEDS);
+    
+    // Start threads
     btThread.start(bt_thread);
-    while (true) {
-        // Blink LED and wait 0.5 seconds
-        led1 = !led1;
-        wait(0.5);
+    blinkerThread.start(blinker_thread);
+    
+    int ctr = 0;
+    bool up = true;
+    
+    int gamePwmNum = 1;
+    int gamePwmDen = 4;
+    int gamePwmMax = 8;
+    
+    for(;;) {
+        if (ctr % (gamePwmDen * 7) == 0) {
+            gamePwmNum += up ? 1 : -1;
+            if (gamePwmNum == gamePwmMax) {
+                up = false;
+            } else if (gamePwmNum == 1) {
+                up = true;
+                ctr = 0;
+            }
+        }
+        
+        fill_solid(&(l_leds[HEAD_LIGHT_START]), NUM_HEAD_LIGHT, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
+        fill_solid(&(r_leds[HEAD_LIGHT_START]), NUM_HEAD_LIGHT, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
+        
+        if (!(lights & BLINKER_L)) {
+            fill_solid(&(l_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
+            fill_solid(&(l_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
+        }
+
+        if (!(lights & BLINKER_R)) {
+            fill_solid(&(r_leds[HEAD_BLINKER_START]), NUM_HEAD_BLINKER, lights & HEADLIGHT ? COLOR_HEADLIGHT_ON : COLOR_HEADLIGHT_DIM);
+            fill_solid(&(r_leds[TAIL_BLINKER_START]), NUM_TAIL_BLINKER, lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
+        }
+
+        fill_solid(&(l_leds[HEAD_FOG_START]), NUM_HEAD_FOG, lights & FOGLIGHT ? COLOR_FOGLIGHT : CRGB::Black);
+        fill_solid(&(r_leds[HEAD_FOG_START]), NUM_HEAD_FOG, lights & FOGLIGHT ? COLOR_FOGLIGHT : CRGB::Black);
+        
+        fill_solid(&(l_leds[GLOW_START]), NUM_GLOW, lights & UNDERGLOW ? COLOR_UNDERGLOW : CRGB::Black);
+        fill_solid(&(r_leds[GLOW_START]), NUM_GLOW, lights & UNDERGLOW ? COLOR_UNDERGLOW : CRGB::Black);
+        
+        fill_solid(&(l_leds[TAIL_REVERSE_START]), NUM_TAIL_REVERSE, lights & REVERSE ? COLOR_REVERSE :
+                                                                    lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
+        fill_solid(&(r_leds[TAIL_REVERSE_START]), NUM_TAIL_REVERSE, lights & REVERSE ? COLOR_REVERSE :
+                                                                    lights & BRAKELIGHT ? COLOR_BRAKELIGHT : COLOR_TAILLIGHT);
+        
+        double scaleFactor = ceil((double) gamePwmNum / gamePwmDen);
+        fill_solid(&(l_leds[GAME_START]), NUM_GAME, (ctr % gamePwmDen) < (gamePwmNum / scaleFactor) ? gameColor * scaleFactor : CRGB::Black);
+        fill_solid(&(r_leds[GAME_START]), NUM_GAME, (ctr % gamePwmDen) < (gamePwmNum / scaleFactor) ? gameColor * scaleFactor : CRGB::Black);
+        ctr++;
+        
+        APA102_write(l_strip, l_leds, NUM_LEDS);
+        APA102_write(r_strip, r_leds, NUM_LEDS);
+        
+        wait(0);
     }
 }