Platform controller for the Mobile Arcade project

Dependencies:   APA102 Motor

main.cpp

Committer:
abraha2d
Date:
2018-12-11
Revision:
1:113469a23547
Parent:
0:d4e7f9c1287f
Child:
2:774edcf60939

File content as of revision 1:113469a23547:

#include "mbed.h"
#include "Motor.h"
#include "APA102.h"

#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)

#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

float l_vel = 0;
float r_vel = 0;

Serial bt(p28, p27);    // Bluefruit RX, TX
Serial pc(USBTX, USBRX);

Thread btThread;
Thread blinkerThread;

void bt_thread() {
    char bnum = 0;
    char bhit = 0;
    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
            if (bt.getc() == char(~('!' + 'B' + bnum + bhit))) {
                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() {
    
    // 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);
    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);
    }
}