Platform controller for the Mobile Arcade project

Dependencies:   APA102 Motor

main.cpp

Committer:
abraha2d
Date:
2018-12-11
Revision:
3:7e5233f883c7
Parent:
2:774edcf60939

File content as of revision 3:7e5233f883c7:

#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_GAME_MENU     CRGB(32, 32, 32)
#define COLOR_GAME_GAME     CRGB(0, 64, 128)
#define COLOR_GAME_NUM      3 
#define COLOR_GAME_DEN      3

#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_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 = 0;

CRGB l_leds[NUM_LEDS];
CRGB r_leds[NUM_LEDS];

int numGame = 0;

CRGB gameColor = COLOR_GAME_MENU;
double gameBrightness = 0;

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 pcThread;
Thread btThread;
Thread blinkerThread;
Thread gameThread;

void pc_thread() {
    for(;;) {
        while (!pc.readable()) wait(0.1);
        switch (pc.getc()) {
            case 's':
                // Switch to game
                while(pc.getc() != '\n'); // Flush rest of command
                while (gameBrightness > 0.1250168966) wait(0.01); // Wait for dim before switch
                for (int i = 0; i < 100; i++) {
                    gameColor = CRGB(
                        (COLOR_GAME_GAME.r - COLOR_GAME_MENU.r) * (i / 100.0) + COLOR_GAME_MENU.r,
                        (COLOR_GAME_GAME.g - COLOR_GAME_MENU.g) * (i / 100.0) + COLOR_GAME_MENU.g,
                        (COLOR_GAME_GAME.b - COLOR_GAME_MENU.b) * (i / 100.0) + COLOR_GAME_MENU.b
                    );
                    wait(0.01);
                }
                gameColor = COLOR_GAME_GAME;
                break;
            case 'e':
                // Switch to menu
                while(pc.getc() != '\n'); // Flush rest of command
                while (gameBrightness > 0.1250168966) wait(0.01); // Wait for dim before switch
                for (int i = 0; i < 100; i++) {
                    gameColor = CRGB(
                        (COLOR_GAME_MENU.r - COLOR_GAME_GAME.r) * (i / 100.0) + COLOR_GAME_GAME.r,
                        (COLOR_GAME_MENU.g - COLOR_GAME_GAME.g) * (i / 100.0) + COLOR_GAME_GAME.g,
                        (COLOR_GAME_MENU.b - COLOR_GAME_GAME.b) * (i / 100.0) + COLOR_GAME_GAME.b
                    );
                    wait(0.01);
                }
                gameColor = COLOR_GAME_MENU;
                break;
            case 'b':
                // Starting up
                while (numGame < NUM_GAME) {
                    numGame++;
                    wait(0.05);
                }
                lights = FOGLIGHT | UNDERGLOW | BRAKELIGHT;
                break;
            case 'h':
                // Shutting down
                lights = 0;
                while (numGame > 0) {
                    numGame--;
                    wait(0.05);
                }
                break;
        }
    }
}

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);
  }
}

void game_thread() {
    int bCtr = 0;
    for(;;) {
        gameBrightness = (exp(sin(bCtr*0.01570796327))-0.3678794412)*0.3722766811+0.125;
        bCtr = ++bCtr % 400;
        pc.printf("%i\r\n", bCtr);
        wait(0.01);
    }
}

// main() runs in its own thread in the OS
int main() {
    
    // Jack up the SPI 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
    pcThread.start(pc_thread);
    btThread.start(bt_thread);
    blinkerThread.start(blinker_thread);
    gameThread.start(game_thread);
    
    for(;;) {
        
        if (lights) {
        
            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);
        
        } else {
            
            fill_solid(&(l_leds[0]), NUM_LEDS, CRGB::Black);
            fill_solid(&(r_leds[0]), NUM_LEDS, CRGB::Black);
            
        }
        
        if (numGame != NUM_GAME) {
            fill_solid(&(l_leds[GAME_START]), NUM_GAME, CRGB::Black);
            fill_solid(&(r_leds[GAME_START]), NUM_GAME, CRGB::Black);
        }
        fill_solid(&(l_leds[GAME_START]), numGame, gameColor * gameBrightness);
        fill_solid(&(r_leds[GAME_START]), numGame, gameColor * gameBrightness);
        
        APA102_write(l_strip, l_leds, NUM_LEDS);
        APA102_write(r_strip, r_leds, NUM_LEDS);
        
        wait(0);
    }
}