ProtonPack

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

main.cpp (22938B)


      1 #include <Arduino.h>
      2 
      3 #include <FastLED.h>
      4 #include <DFPlayerMini_Fast.h>
      5 
      6 // time it takes to reload when overheated
      7 // if not overheatign reloading takes half the time
      8 #define OVERHEAT_TIME 5000
      9 
     10 // default "hp"
     11 // this value represents how long it is until
     12 // the pack overheats and is slowly depleted
     13 // over time or via shooting
     14 #define DEFAULT_PROTON_HP 100
     15 
     16 #define DEFAULT_PROTON_PACK_TIME 600
     17 #define SHOOTING_TIME 20000
     18 #define IDLE_TIME 550000
     19 
     20 #define DEBUGGING 0
     21 
     22 // front potentiometer is the potentiometer on the gun
     23 // it is used to change the proton hp directly above
     24 // a cretan threshold
     25 #define FRONT_POTENTIOMETER A8
     26 #define PACK_POWER A9
     27 // lower button on the right side
     28 #define GUN_POWER A10
     29 // upper button on the right side
     30 #define PROTON_INDICATOR A11
     31 // upper button on the left side
     32 #define ACTIVATE A12
     33 // button on the front of the gun
     34 #define INTENSIFY_FRONT A13
     35 // lower button on the left side, starts the shootign animation
     36 #define INTENSIFY A14
     37 // motor that vibrates the neutrino wand
     38 #define VIBRATOR 8
     39 // output for the high power led, AKA the proton beam
     40 #define HP_LED_R 9
     41 #define HP_LED_G 10
     42 #define HP_LED_B 11
     43 
     44 enum {
     45         PROTON_ACCELERATOR,
     46         DARK_MATTER_GENERATOR,
     47         PLASM_DISTRIBUTION_SYSTEM,
     48         COMPOSITE_PARTICLE_SYSTEM,
     49         PROTON_MODES_COUNT,
     50 } proton_modes;
     51 int current_mode = PROTON_ACCELERATOR;
     52 
     53 // cyclotron fade time
     54 #define CYCLOTRON_FADE_TIME 10
     55 #define CYCLOTRON_FADE_AMOUNT 5
     56 
     57 enum {
     58         CYCLOTRON1,
     59         CYCLOTRON2,
     60         CYCLOTRON3,
     61         CYCLOTRON4,
     62         N_FILTER,
     63         PACK_NUM_LEDS,
     64 } pack_leds_names;
     65 #define PACK_LEDS_PIN 13
     66 CRGB pack_leds[PACK_NUM_LEDS];
     67 
     68 const CRGB cyclotron_colors[PROTON_MODES_COUNT] = {
     69         CRGB::Red,
     70         CRGB::Blue,
     71         CRGB::Green,
     72         CRGB::DarkOrange,
     73 };
     74 #define SET_CYCLOTRON_ON(_led) pack_leds[_led] = cyclotron_colors[current_mode]
     75 
     76 enum {
     77 	GUN_ON_LED,
     78 	WHITE_LED,
     79 	VENT_LED,
     80 	FRONT_LED,
     81 	GUN_NUM_LEDS,
     82 } gun_leds_names;
     83 #define GUN_LEDS_PIN 12
     84 CRGB gun_leds[GUN_NUM_LEDS];
     85 
     86 const CRGB gun_led_colors[PROTON_MODES_COUNT][GUN_NUM_LEDS] = {
     87 	{
     88 		CRGB::Red,
     89         	CRGB::White,
     90         	CRGB::White,
     91 		CRGB::OrangeRed,
     92 	}, {
     93 		CRGB::Red,
     94         	CRGB::White,
     95         	CRGB::Blue,
     96 		CRGB::OrangeRed,
     97 	}, {
     98 		CRGB::Red,
     99         	CRGB::White,
    100         	CRGB::Green,
    101 		CRGB::OrangeRed,
    102 	}, {
    103 		CRGB::Red,
    104         	CRGB::White,
    105         	CRGB::Yellow,
    106 		CRGB::OrangeRed,
    107 	},
    108 };
    109 #define SET_GUN_LED_ON(_led) gun_leds[_led] = gun_led_colors[current_mode][_led]
    110 
    111 #define JRGEN_EXTRA
    112 
    113 #ifdef JRGEN_EXTRA
    114 enum {
    115         power_down_sound = 1,
    116         pack_hum_sound,
    117         gun_trail_sound,
    118         start_up_sound,
    119         beep_sound,
    120         beep_shoot_sound,
    121         gun_overheat_sound,
    122         shoot_sound,
    123 	ghostbusters_theme_song,
    124 } tracks;
    125 #else
    126 enum {
    127         power_down_sound = 1,
    128         pack_hum_sound,
    129         gun_trail_sound,
    130         start_up_sound,
    131         beep_sound,
    132         beep_shoot_sound,
    133         gun_overheat_sound,
    134 } trakcs;
    135 #endif
    136 
    137 #define PACK_VOLUME 30
    138 DFPlayerMini_Fast myMP3;
    139 
    140 #define PROTON_GRAPH_COUNT 10
    141 const uint8_t proton_graph[PROTON_GRAPH_COUNT] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
    142 uint8_t proton_graph_stage = 0;
    143 
    144 #define POWERCELL_COUNT 20
    145 const int powercell[POWERCELL_COUNT] {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
    146 uint8_t powercell_stage = 0;
    147 
    148 // button variables (stored here so that debug mode can change them)
    149 bool pack_power_on = true;
    150 bool gun_power_on;
    151 bool proton_indicator_on;
    152 bool activate_on;
    153 bool intensify_on;
    154 bool intensify_reload;
    155 
    156 bool front_led_on = true;
    157 bool vent_led_on = true;
    158 bool shooting;
    159 bool system_on;
    160 
    161 // current proton reduction caused by the proton indicator knob
    162 int proton_reduction;
    163 uint8_t proton_indicator_pot_value = 5;
    164 
    165 uint8_t cyclotron_stage;
    166 
    167 uint8_t proton_hp = DEFAULT_PROTON_HP;
    168 
    169 // state of the high power led
    170 // for smooth transition
    171 int red_state = 0;
    172 int green_state = 0;
    173 int blue_state = 0;
    174 
    175 // colors of the firing beam
    176 uint8_t high_power_led_colors[PROTON_MODES_COUNT][4][3] = {
    177         { // PROTON_ACCELERATOR
    178                 // red-orange, blue, yellow, white
    179                 {255, 130, 0}, {20 , 20, 255}, {255 , 180, 0}, {255, 200, 230},
    180         },
    181         { // DARK_MATTER_GENERATOR
    182                 // blue, white, light blue, purple
    183                 {0 , 0, 90}, {80 , 80, 90}, {0 , 30, 70}, {60 , 0, 80}
    184         },
    185         { // PLASM_DISTRIBUTION_SYSTEM
    186                 // green, light green, green, white
    187                 {0, 90, 0}, {20, 90, 10}, {0, 90, 0}, {80 , 90, 80}
    188         },
    189         { // COMPOSITE_PARTICLE_SYSTEM
    190                 // yellow, orange, red, white
    191                 {70 , 60, 0}, {80 , 60, 5}, {90, 0, 0}, {90 , 80, 80}
    192         }
    193 };
    194 
    195 
    196 // time in between cyclotron changes
    197 // incereeses depending on the proton hp
    198 unsigned long proton_pack_time = DEFAULT_PROTON_PACK_TIME / 100 * proton_hp;
    199 
    200 // global time value to run the different timings
    201 unsigned long t = 0;
    202 
    203 void start_up();
    204 void run_proton_pack();
    205 void reduce_proton_hp();
    206 void run_proton_gun();
    207 void gun_lights_off();
    208 void shoot();
    209 void reload(bool overheat);
    210 void reset_pack();
    211 
    212 void run_powercell();
    213 void powercell_off();
    214 
    215 // changes brightness in the led at the end of the gun accordingly
    216 bool high_power_led(const uint8_t* ledcolor, const unsigned long spacing_delay, bool no_fade);
    217 void high_power_led_off();
    218 
    219 bool start_vent(bool reset = false);
    220 void pulse_led(); // pulses the WHITE_LED inversely with the FRONT_LED
    221 void run_proton_indicator();
    222 void read_potentiometer();
    223 void proton_indicator_off();
    224 
    225 void run_cyclotron();
    226 void fade_cyclotron();
    227 void cyclotron_off();
    228 
    229 void debugging_message();
    230 void debugging_switches();
    231 
    232 void setup()
    233 {
    234 #if DEBUGGING
    235         Serial.begin(115200);
    236         Serial.println("Debug mode entered");
    237         delay(1000);
    238 #endif
    239 
    240         // input pins (buttons and switches)
    241         pinMode(PACK_POWER,       INPUT);
    242         pinMode(GUN_POWER,        INPUT);
    243         pinMode(PROTON_INDICATOR, INPUT);
    244         pinMode(ACTIVATE,         INPUT);
    245         pinMode(INTENSIFY,        INPUT);
    246         pinMode(INTENSIFY_FRONT,  INPUT);
    247 
    248         // output pins
    249         for (int i = 0; i < PROTON_GRAPH_COUNT; i++)
    250                 pinMode(proton_graph[i], OUTPUT);
    251         for (int i = 0; i < POWERCELL_COUNT; i++)
    252                 pinMode(powercell[i], OUTPUT);
    253 
    254         pinMode(HP_LED_R, OUTPUT);
    255         pinMode(HP_LED_G, OUTPUT);
    256         pinMode(HP_LED_B, OUTPUT);
    257         pinMode(VIBRATOR, OUTPUT);
    258 
    259         // neopixel leds
    260         FastLED.addLeds<NEOPIXEL, PACK_LEDS_PIN>(pack_leds, PACK_NUM_LEDS);
    261         FastLED.addLeds<NEOPIXEL, GUN_LEDS_PIN>(gun_leds, GUN_NUM_LEDS);
    262         FastLED.clear(true);
    263         cyclotron_off();
    264         gun_lights_off();
    265 
    266         // sound
    267         Serial1.begin(9600);
    268         myMP3.begin(Serial1);
    269         delay(100);
    270 }
    271 
    272 
    273 // loop while the arduino has power
    274 void loop()
    275 {
    276 #if DEBUGGING
    277         debugging_switches();
    278         //debugging_message();
    279 #else
    280         gun_power_on = digitalRead(GUN_POWER);
    281 #endif
    282         t = millis();
    283 
    284         if (pack_power_on || gun_power_on) {
    285                 if (!system_on) {
    286                         start_up();
    287                         system_on = true;
    288                 }
    289 
    290                 if (gun_power_on) run_proton_gun();
    291                 else              gun_lights_off();
    292 
    293                 run_proton_pack();
    294         }
    295         if (!pack_power_on && !gun_power_on && system_on) {
    296                 myMP3.play(power_down_sound);
    297                 reset_pack();
    298                 system_on = false;
    299                 delay(100);
    300         }
    301 }
    302 
    303 // turn on / keep running the proton pack lights
    304 void run_proton_pack()
    305 {
    306         proton_pack_time = DEFAULT_PROTON_PACK_TIME / DEFAULT_PROTON_HP * ( proton_hp - proton_reduction ) + 40;
    307 
    308         run_cyclotron();
    309         run_powercell();
    310         reduce_proton_hp();
    311 	FastLED.show();
    312 }
    313 
    314 // reads the potentiometer at the front and writes a value to proton_hp
    315 void read_potentiometer()
    316 {
    317 #if !DEBUGGING
    318         proton_indicator_pot_value = map(analogRead(FRONT_POTENTIOMETER), 0, 1023, 0, 5);
    319 #endif
    320         if (proton_indicator_pot_value == 5) proton_indicator_pot_value = 4;
    321 
    322         if (proton_indicator_pot_value == 0) proton_reduction = DEFAULT_PROTON_HP - 20;
    323         else               proton_reduction = DEFAULT_PROTON_HP - (proton_indicator_pot_value + 1) * 20;
    324 }
    325 
    326 // animation and sound when the proton pack starts
    327 void start_up()
    328 {
    329         myMP3.play(start_up_sound);
    330 
    331         for (int i = 0; i < POWERCELL_COUNT; i++)
    332                 digitalWrite(powercell[i], HIGH);
    333 
    334 	// TODO make it fade towards selected mdoes target color
    335         for (int i = 0; i < 255; i++) {
    336                 pack_leds[CYCLOTRON1].setRGB(i, 0, 0);
    337                 pack_leds[CYCLOTRON2].setRGB(i, 0, 0);
    338                 pack_leds[CYCLOTRON3].setRGB(i, 0, 0);
    339                 pack_leds[CYCLOTRON4].setRGB(i, 0, 0);
    340                 FastLED.show();
    341 
    342                 delay(10);
    343         }
    344         reset_pack();
    345 }
    346 
    347 // check the gun switches and act accordingly
    348 void run_proton_gun()
    349 {
    350 	SET_GUN_LED_ON(GUN_ON_LED);
    351         // if debugging mode is on, dont read switches
    352         // the buttons are set from the serial monitor
    353         // see debugging_switches()
    354 	static bool last_intensify_reload_state;
    355 	last_intensify_reload_state = intensify_reload;
    356 #if !DEBUGGING
    357         // check the gun switches
    358         proton_indicator_on = digitalRead(PROTON_INDICATOR);
    359         activate_on         = digitalRead(ACTIVATE);
    360         intensify_on        = digitalRead(INTENSIFY);
    361         intensify_reload    = digitalRead(INTENSIFY_FRONT);
    362 #endif
    363 
    364         if (proton_indicator_on) {
    365                 read_potentiometer();
    366                 run_proton_indicator();
    367 
    368                 if (activate_on) {
    369                         pulse_led();
    370 			if(vent_led_on) vent_led_on = start_vent();
    371 
    372 			static unsigned long last_shot;
    373                         if (intensify_on) {
    374 				if (t - last_shot > 500)
    375                                 	shoot();
    376                         } else if (shooting) {
    377 				last_shot = t;
    378                                 myMP3.play(gun_trail_sound);
    379                                 shooting = false;
    380                                 high_power_led_off();
    381 				digitalWrite(VIBRATOR, LOW);
    382                         }
    383 			if (intensify_reload) {
    384 				shooting = false;
    385 				reload(false);
    386 				return;
    387 			}
    388                 } else {
    389                         // do theese if the proton indicator is on but not the generator switch
    390                         front_led_on        = true;
    391                         gun_leds[VENT_LED]  = CRGB::Black;
    392 			vent_led_on         = true;
    393                         gun_leds[FRONT_LED] = CRGB::Black;
    394 			SET_GUN_LED_ON(WHITE_LED);
    395 
    396 			if (intensify_reload && !last_intensify_reload_state) {
    397 				static bool is_on = false;
    398 				is_on = !is_on;
    399 #ifdef JRGEN_EXTRA
    400 				if (is_on)
    401 					myMP3.play(ghostbusters_theme_song);
    402 				else
    403 					myMP3.stop();
    404 #endif
    405 			}
    406                 }
    407         } else {
    408                 gun_leds[VENT_LED]  = CRGB::Black;
    409                 gun_leds[FRONT_LED] = CRGB::Black;
    410                 gun_leds[WHITE_LED] = CRGB::Black;
    411                 proton_reduction = 0;
    412 		vent_led_on     = true;
    413                 proton_indicator_off();
    414         }
    415 }
    416 
    417 void powercell_off()
    418 {
    419         for (int i = 0; i < POWERCELL_COUNT; i++)
    420                 digitalWrite(powercell[i], LOW);
    421         powercell_stage = 0;
    422 }
    423 
    424 void run_powercell()
    425 {
    426         static unsigned long powercell_previous_time;
    427 
    428         if (t - powercell_previous_time >= proton_pack_time / 6) {
    429                 if (powercell_stage >= POWERCELL_COUNT) {
    430                         for (int i = 0; i < POWERCELL_COUNT; i++)
    431                                 digitalWrite(powercell[i], LOW);
    432                         powercell_stage = 0;
    433                 } else {
    434                         digitalWrite(powercell[powercell_stage++], HIGH);
    435                 }
    436     
    437                 powercell_previous_time = t;
    438         }
    439 }
    440 
    441 void run_cyclotron()
    442 {
    443         static unsigned long cyclotron_previous_time;
    444         static bool cyclotron_on;
    445 
    446         fade_cyclotron();
    447 
    448         // while the cyclotron is on, it should stay on for a set amount of time
    449         if (cyclotron_on && t - cyclotron_previous_time >= proton_pack_time / 3 * 2) {
    450                 cyclotron_stage++;
    451                 cyclotron_previous_time = t;
    452                 cyclotron_on = false;
    453         }
    454 
    455         // loop around
    456         if (cyclotron_stage > 3) cyclotron_stage = 0;
    457 
    458         // if the cyclotron is off, turn it on after a time has exceeded.
    459         if (!cyclotron_on && t - cyclotron_previous_time >= proton_pack_time) {
    460 		SET_CYCLOTRON_ON(cyclotron_stage);
    461                 cyclotron_previous_time = t;
    462                 cyclotron_on = true;
    463         }
    464 }
    465 
    466 // reloads (sound and light animations), if overheated it lasts longer
    467 void reload(bool overheat)
    468 {
    469 #if DEBUGGING
    470         Serial.println("---------!RELOADING!---------");
    471         if (overheat) Serial.println("---------!OVERHEATED!---------");
    472 #endif
    473         myMP3.play(gun_overheat_sound);
    474 
    475 	SET_CYCLOTRON_ON(CYCLOTRON1);
    476 	SET_CYCLOTRON_ON(CYCLOTRON2);
    477 	SET_CYCLOTRON_ON(CYCLOTRON3);
    478 	SET_CYCLOTRON_ON(CYCLOTRON4);
    479         proton_indicator_off();
    480         for (int i = 0; i < POWERCELL_COUNT; i++)
    481                 digitalWrite(powercell[i], HIGH);
    482         high_power_led_off();
    483 	digitalWrite(VIBRATOR, LOW);
    484 
    485         pack_leds[N_FILTER] = CRGB::White;
    486 
    487 	SET_GUN_LED_ON(WHITE_LED);
    488 	SET_GUN_LED_ON(FRONT_LED);
    489 	SET_GUN_LED_ON(VENT_LED);
    490         FastLED.show();
    491         if (overheat) {
    492                 delay(OVERHEAT_TIME);
    493         } else {
    494                 delay(OVERHEAT_TIME / 2);
    495                 intensify_reload = false;
    496         }
    497         reset_pack();
    498         start_up();
    499 }
    500 
    501 // resets variables and resets functions
    502 void reset_pack()
    503 {
    504         gun_lights_off();
    505         FastLED.clear(true);
    506         FastLED.show();
    507 
    508         proton_hp       = DEFAULT_PROTON_HP;
    509         cyclotron_off();
    510         powercell_off();
    511 }
    512 
    513 // reduces the proton_hp (ammonution) accordingly
    514 void reduce_proton_hp()
    515 {
    516         static unsigned long previous_hp_reduction;
    517         static bool beeped;
    518 
    519         // automaticaly reload if the proton hp is a zero
    520         if (proton_hp - proton_reduction <= 0) {
    521                 reload(true);
    522                 return;
    523         }
    524 
    525         // reduce the proton_hp slowly while the pack is ideling (does not apply if there isn't any proton reduction)
    526         if (proton_reduction != 0 && t - previous_hp_reduction >= IDLE_TIME / DEFAULT_PROTON_HP) {
    527                 proton_hp -= 1;
    528                 previous_hp_reduction = t;
    529         }
    530 
    531         // if there is less than x hp left, play the overheat warning sound
    532         if (proton_hp - proton_reduction <= 10 && !beeped) {
    533                 beeped = true;
    534                 if (shooting) myMP3.play(beep_shoot_sound);
    535                 else         myMP3.play(beep_sound);
    536 
    537                 for (uint8_t blinkamount = 0; blinkamount <= 5; blinkamount++) {
    538                         for (int i = 0; i < PROTON_GRAPH_COUNT; i++)
    539                                 digitalWrite(proton_graph[i], HIGH);
    540                         for (int i = 0; i < POWERCELL_COUNT; i++)
    541                                 digitalWrite(powercell[i], HIGH);
    542 
    543                         cyclotron_off();
    544                         pack_leds[N_FILTER] = CRGB::White;
    545                         gun_leds[FRONT_LED] = CRGB::Black;
    546                         gun_leds[WHITE_LED] = CRGB::Black;
    547                         gun_leds[VENT_LED] = CRGB::Black;
    548                         FastLED.show();
    549 
    550 						unsigned long time_now = millis();
    551 						while (millis() - time_now < 200) {
    552 							run_proton_gun();
    553 						}
    554 
    555 						proton_indicator_off();
    556 						powercell_off();
    557 						SET_CYCLOTRON_ON(CYCLOTRON1);
    558 						SET_CYCLOTRON_ON(CYCLOTRON2);
    559 						SET_CYCLOTRON_ON(CYCLOTRON3);
    560 						SET_CYCLOTRON_ON(CYCLOTRON4);
    561 						pack_leds[N_FILTER] = CRGB::Black;
    562 						SET_GUN_LED_ON(VENT_LED);
    563 						SET_GUN_LED_ON(FRONT_LED);
    564 						SET_GUN_LED_ON(WHITE_LED);
    565 						FastLED.show();
    566 
    567 						time_now = millis();
    568 						while (millis() - time_now < 200) {
    569 							run_proton_gun();
    570 						}
    571                 }
    572         } else if (proton_hp - proton_reduction > 12 && beeped){
    573                 beeped = false;
    574         }
    575 }
    576 
    577 // shoot and depleet amunition
    578 void shoot()
    579 {
    580         // letting the program know it has shot so that when it turns of it can play the trail effect
    581         if (!shooting) {
    582                 shooting = true;
    583                 myMP3.play(shoot_sound);
    584 		digitalWrite(VIBRATOR, HIGH);
    585         }
    586 
    587 	static bool color_change;
    588 	static unsigned long rng_delay = 100;
    589 	static int rng;
    590 	static bool no_fade;
    591 
    592 	if (color_change) {
    593 		static bool no_fade_next;
    594 		rng = random(10);
    595 		rng_delay = random(80, 200);
    596 		if (no_fade_next) {
    597 			no_fade_next = false;
    598 			no_fade = false;
    599 		} else {
    600 			if (no_fade) no_fade_next = true;
    601 			else         no_fade = random(2) && rng_delay < 150;
    602 		}
    603 		color_change = false;
    604 	}
    605 
    606 	switch (rng)  {
    607 	case 0:
    608 	case 1:
    609 	case 2:
    610 	case 3:
    611 		color_change = high_power_led(high_power_led_colors[current_mode][0], rng_delay + 60, no_fade);
    612 		break;
    613 	case 4:
    614 	case 5:
    615 	case 6:
    616 		color_change = high_power_led(high_power_led_colors[current_mode][1], rng_delay, no_fade);
    617 		break;
    618 	case 7:
    619 	case 8:
    620 		color_change = high_power_led(high_power_led_colors[current_mode][2], rng_delay, no_fade);
    621 		break;
    622 	case 9:
    623 		color_change = high_power_led(high_power_led_colors[current_mode][3], rng_delay, no_fade);
    624 		break;
    625 	}
    626 
    627         // reduce the proton_hp (ammonution)
    628         static unsigned long last_shooting;
    629         if (t - last_shooting >= SHOOTING_TIME / DEFAULT_PROTON_HP) {
    630                 proton_hp -= 1;
    631                 last_shooting = t;
    632         }
    633 }
    634 
    635 #define red_max 90
    636 // changes brightness in the led at the end of the gun accordingly
    637 bool high_power_led(const uint8_t* ledcolor, const unsigned long spacing_delay, bool no_fade)
    638 {
    639         static unsigned long previous_color_change;
    640         int R = min(ledcolor[0], red_max);
    641         int G = ledcolor[1];
    642         int B = ledcolor[2];
    643 	if (no_fade) {
    644 		red_state = R;
    645 		green_state = G;
    646 		blue_state = B;
    647 	}
    648 
    649         if (red_state < R)      red_state++;
    650         else if (red_state > R) red_state--;
    651 
    652 #ifdef JRGEN_EXTRA
    653         if (green_state < G)      green_state++;
    654         else if (green_state > G) green_state--;
    655 #else
    656 	green_state = G;
    657 #endif
    658 
    659         if (blue_state < B)       blue_state++;
    660         else if (blue_state > B)  blue_state--;
    661 
    662         analogWrite(HP_LED_R, red_state);
    663         analogWrite(HP_LED_G, green_state);
    664         analogWrite(HP_LED_B, blue_state);
    665         if (t - previous_color_change >= spacing_delay) {
    666                 previous_color_change = t;
    667                 return true;
    668         }
    669         return false;
    670 }
    671 
    672 void high_power_led_off()
    673 {
    674         analogWrite(HP_LED_R, 0);
    675         analogWrite(HP_LED_G, 0);
    676         analogWrite(HP_LED_B, 0);
    677         red_state   = 0;
    678         green_state = 0;
    679         blue_state  = 0;
    680 }
    681 
    682 void gun_lights_off()
    683 {
    684         proton_reduction = 0;
    685         front_led_on     = true;
    686 	vent_led_on      = true;
    687 	start_vent(true);
    688 
    689         gun_leds[GUN_ON_LED] = CRGB::Black;
    690         gun_leds[WHITE_LED]  = CRGB::Black; 
    691 	gun_leds[FRONT_LED]  = CRGB::Black;
    692         gun_leds[VENT_LED]   = CRGB::Black;
    693         FastLED.show();
    694 
    695         high_power_led_off();
    696 	digitalWrite(VIBRATOR, LOW);
    697         proton_indicator_off();
    698 
    699         if (shooting) {
    700                 delay(100);
    701                 myMP3.play(gun_trail_sound);
    702                 shooting = false;
    703         }
    704 }
    705 
    706 
    707 // pulses the WHITE_LED inversely with the FRONT_LED
    708 void pulse_led()
    709 {
    710         static unsigned long previous_pulse;
    711         if (t - previous_pulse >= proton_pack_time) {
    712                 if (front_led_on) {
    713 			SET_GUN_LED_ON(WHITE_LED);
    714                         gun_leds[FRONT_LED] = CRGB::Black;
    715                 } else {
    716                         gun_leds[WHITE_LED] = CRGB::Black;
    717 			SET_GUN_LED_ON(FRONT_LED);
    718                 }
    719                 front_led_on = !front_led_on;
    720                 previous_pulse   = t;
    721         }
    722 }
    723 
    724 #define vent_blink_time 60
    725 bool start_vent(bool reset) {
    726 	static unsigned long last_vent_blink;
    727 	static int vent_times;
    728 	static bool vent_on;
    729 
    730 	if (vent_times > 4 || reset) {
    731 		if (!reset) SET_GUN_LED_ON(VENT_LED);
    732 		vent_times = 0;
    733 		return false;
    734 	}
    735 	if (millis() - last_vent_blink < vent_blink_time)
    736 		return true;
    737 
    738 	if (vent_on)
    739         	gun_leds[VENT_LED] = CRGB::Black;
    740 	else
    741 		SET_GUN_LED_ON(VENT_LED);
    742 
    743 	vent_on = !vent_on;
    744 	last_vent_blink = millis();
    745 	vent_times++;
    746 	return true;
    747 }
    748 
    749 void run_proton_indicator()
    750 {
    751         proton_graph_stage = (proton_hp - proton_reduction) / (DEFAULT_PROTON_HP / 10);
    752         for (int i = 0; i < PROTON_GRAPH_COUNT; i++) {
    753                 if (i <= proton_graph_stage) digitalWrite(proton_graph[i], HIGH);
    754                 else                         digitalWrite(proton_graph[i], LOW);
    755         }
    756 }
    757 
    758 void proton_indicator_off()
    759 {
    760         for (int i = 0; i < PROTON_GRAPH_COUNT; i++)
    761                 digitalWrite(proton_graph[i], LOW);
    762 }
    763 
    764 void cyclotron_off()
    765 {
    766         pack_leds[CYCLOTRON1] = CRGB::Black;
    767         pack_leds[CYCLOTRON2] = CRGB::Black;
    768         pack_leds[CYCLOTRON3] = CRGB::Black;
    769         pack_leds[CYCLOTRON4] = CRGB::Black;
    770         FastLED.show();
    771 }
    772 
    773 void fade_cyclotron()
    774 {
    775         static unsigned long cyclotron_previous_fade;
    776         if(t - cyclotron_previous_fade < CYCLOTRON_FADE_TIME) return;
    777 
    778         for(int i = 0; i < 4; i++) {
    779                 if (i == cyclotron_stage) continue;
    780 
    781                 // cycle down r, g and b values
    782                 for(int c = 0; c < 3; c++)
    783                         if (pack_leds[i].raw[c] >= CYCLOTRON_FADE_AMOUNT)
    784                                 pack_leds[i].raw[c] -= CYCLOTRON_FADE_AMOUNT;
    785                         else
    786                                 pack_leds[i].raw[c] = 0;
    787         }
    788         cyclotron_previous_fade = t;
    789 }
    790 
    791 // turning on and off switches from Serial monitor
    792 void debugging_switches()
    793 {
    794         if (Serial.available()) {
    795                 switch(Serial.read()) {
    796                 case 'g': gun_power_on        = !gun_power_on;         break;
    797                 case 'p': pack_power_on       = !pack_power_on;        break;
    798                 case 'q': proton_indicator_on = !proton_indicator_on;  break;
    799                 case 'a': activate_on         = !activate_on;          break;
    800                 case 'i': intensify_on        = !intensify_on;         break;
    801                 case 'r': intensify_reload    = !intensify_reload;     break;
    802 
    803                 case '0': proton_indicator_pot_value = 0; break;
    804                 case '1': proton_indicator_pot_value = 1; break;
    805                 case '2': proton_indicator_pot_value = 2; break;
    806                 case '3': proton_indicator_pot_value = 3; break;
    807                 case '4': proton_indicator_pot_value = 4; break;
    808                 case '5': proton_indicator_pot_value = 5; break;
    809                 }
    810         }
    811 }