proton

Firmware for Ghostbusters proton pack
git clone https://git.woozle.org/neale/proton.git

Neale Pickett  ·  2016-10-02

ProtonPack.ino

  1// Proton Pack with NeoPixels
  2// Boy howdy do these make everything easy
  3
  4#include <SPI.h>
  5#include <Wire.h>
  6#include <Adafruit_NeoPixel.h>
  7#include <Adafruit_LEDBackpack.h>
  8#include <Adafruit_GFX.h>
  9#include "MusicPlayer.h"
 10#include "Synchrotron.h"
 11
 12// Music Player
 13#define MUSIC_MCS 7
 14#define MUSIC_DCS 6
 15#define MUSIC_CCS 4
 16#define MUSIC_DRQ 0 // Cut trace on board and wire to 0, so you can use 3 for SPI
 17MusicPlayer *music;
 18
 19// LED output scaling
 20#define brightness 255
 21
 22// Synchrotron
 23#define SYNC1_NPIXELS 24
 24#define SYNC1_DATA 5
 25Synchrotron *sync1;
 26
 27// Neutrona Wand
 28#define WAND1_NPIXELS 14
 29#define WAND1_DATA 9
 30Synchrotron *wand1;
 31
 32// Displays
 33Adafruit_7segment disp1;
 34Adafruit_7segment disp2;
 35
 36// Debug LED
 37#define DEBUG 13
 38
 39// Inputs
 40#define TRIGGER 8
 41#define POT1 A0
 42
 43// global time counter
 44unsigned long jiffies = 0;
 45
 46// 6 seems to be about what my overly-critical brain needs to buffer out
 47// any delays caused by NMI sections of music player code so that they're unnoticeable
 48#define MILLIS_PER_JIFFY 6
 49
 50
 51void setup() {
 52  randomSeed(analogRead(12));
 53
 54  // inputs
 55  pinMode(TRIGGER, INPUT_PULLUP);
 56
 57  // outputs
 58  pinMode(DEBUG, OUTPUT);
 59
 60  // music player, this sets up SPI for us
 61  music = new MusicPlayer(MUSIC_MCS, MUSIC_DCS, MUSIC_DRQ, MUSIC_CCS);
 62
 63  // synchrotron
 64  sync1 = new Synchrotron(SYNC1_NPIXELS, SYNC1_DATA);
 65
 66  // nuetrona wand
 67  wand1 = new Synchrotron(WAND1_NPIXELS, WAND1_DATA);
 68
 69  // 7segment displays
 70  disp1 = Adafruit_7segment();
 71  disp1.begin(0x70);
 72
 73  disp2 = Adafruit_7segment();
 74  disp2.begin(0x71);
 75}
 76
 77
 78void flashDebug() {
 79  uint8_t val;
 80
 81  val = (jiffies % 100) < 50;
 82  digitalWrite(DEBUG, val);
 83}
 84
 85void loop() {
 86  static int state = 0;
 87  static float disp2val = 40.83;
 88  unsigned long new_jiffies = millis() / MILLIS_PER_JIFFY;
 89  boolean trigger = ! digitalRead(TRIGGER);
 90
 91  music->poll(jiffies);
 92
 93  switch (state) {
 94  case 0: // move to steady state
 95    sync1->transition(400, 12, brightness, 0, 0);
 96    wand1->transition(400, 24, brightness, 0, 0);
 97    state = 10;
 98    break;
 99  case 10: // waiting for charge button
100    if (trigger && sync1->transitioned() && music->startPlayingFile("track001.mp3")) {
101      state = 20;
102      sync1->transition(700, 2, brightness, brightness/8, 0);
103      wand1->transition(700, 10, brightness, brightness/8, 0);
104    }
105    break;
106  case 20: // charge button pressed
107    if (sync1->transitioned()) {
108      state = 30;
109    }
110    break;
111  case 30: // waiting for fire button
112    if (trigger && music->startPlayingFile("nutrona.mp3")) {
113      state = 40;
114      sync1->transition(40, 1, brightness/8, brightness/4, brightness/2);
115      wand1->transition(40, 5, brightness/6, brightness/2, brightness/6);
116    }
117    break;
118  case 40: // fire button pressed
119    if (! trigger && music->startPlayingFile("track002.mp3")) {
120      state = 0;
121    }
122    break;
123  }
124
125  if (new_jiffies > jiffies) {
126    jiffies = new_jiffies;
127    sync1->tick(jiffies);
128    wand1->tick(jiffies);
129
130    if (jiffies % 10 == 0) {
131      // This is expensive
132      disp1.printFloat(5198 * sync1->speed());
133      disp1.writeDisplay();
134
135      disp2val = analogRead(POT1) / 10.0;
136      disp2.printFloat(disp2val, 1);
137      disp2.writeDisplay();
138    }
139    flashDebug();
140  }
141}
142