CiderRacer2600.ino 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. /* This code is in all sorts of disarray. Trust nothing. */
  2. /* Notably, the `ws2812_*` functions are unused, I think */
  3. /*
  4. Cider Drag Races
  5. A project to let two racers compete in drinking a glass of cider,
  6. complete with start button, weight activated drink coasters,
  7. a drag-strip "christmas tree", and buzzer.
  8. Along with a few easter eggs.
  9. Pin Assignments per Default Sketch:
  10. Digital:
  11. 2 - Right Player Display
  12. 3 - Left Player Display
  13. 4 - unused (RX for right display)
  14. 5 - unused (RX for left display)
  15. A0 - Left Pressure Simulator
  16. 8 - Right Ready Button
  17. 9 - Buzzer (+)
  18. A7 - Right Pressure Simularor
  19. 11 - Left Player Light Ring
  20. 12 - Right Player Light Ring
  21. 13 - Left Ready Button
  22. 30-39 - Colored LEDs
  23. Analog:
  24. A0 - Left Player Pressure Sensor [Digital]
  25. A7 - Right Player Pressure Sensor [Digital]
  26. A5 - Unused; Seeds RNG.
  27. Fred Damstra
  28. fred.damstra@gmail.com
  29. 2016-09-29 - Initial Draft
  30. 2025-02-09 - Revised for mouse switches and LED rings
  31. Licensed under GPLv3: https://www.gnu.org/licenses/gpl.html
  32. */
  33. #include <SoftwareSerial.h>
  34. #include <WS2812_Definitions.h>
  35. #include <eRCaGuy_ButtonReader.h>
  36. #include <BackgroundRingClass.h>
  37. /**********
  38. CONFIGURATION SECTION
  39. */
  40. /* Buzzer Setup:
  41. Wire ground to common ground, and positive to a PWM
  42. pin. In this example, pin 9.
  43. Lots of help for this example at
  44. https://learn.sparkfun.com/tutorials/sik-experiment-guide-for-arduino---v32/experiment-11-using-a-piezo-buzzer
  45. */
  46. const int debug = 0;
  47. const int buzzerPin = 9;
  48. const unsigned long songFrequency = 90000; // How frequently the song may play in seconds
  49. const float songProbability = 0.0; // Probability that the song will play during that frequency
  50. /* randomPin should be an unused analog pin for seeding the RNG */
  51. const int randomPin = A5;
  52. /* WS2812 Christmas Tree Setup:
  53. Two strips of 6 LEDs connected to 5V and Ground, plus the signal pin
  54. */
  55. const int ledPinRight = 12;
  56. const int ledPinLeft = 11;
  57. const int brightness = 255;
  58. /* Digital (old school) Christmas Tree Setup:
  59. Two strips of 6 LEDs connected to 5V and Ground, plus the signal pin
  60. */
  61. //const int ledPinsLeft[] = {30, 32, 34, 36, 38};
  62. const int ledPinsRight[] = {38, 36, 34, 32, 30};
  63. //const int ledPinsRight[] = {31, 33, 35, 37, 39};
  64. const int ledPinsLeft[] = {39, 37, 35, 33, 31};
  65. const unsigned long prettyLEDFrequency = 30; // How frequently something pretty happens on the LEDs
  66. const float prettyLEDProbability = 0.75; // Probability that the song will play during that frequency
  67. /* Christmas Tree */
  68. const unsigned long startDelay = 1000; /* How long to wait between hitting the start ubtton and starting */
  69. const unsigned long maxDelay = 5000; /* In non dragrace mode, how long might we wait *after* a guaranteed startDelay? */
  70. const unsigned long lightDelay = 600; /* How long to wait between lights during the countdown */
  71. const unsigned long topColor = PURPLE; /* Top LED is constant to show power */
  72. /* 7-Segment Display Setup
  73. Two 7 OpenSegment displays from SparkFun in serial mode.
  74. */
  75. const int leftDisplayTX = 2;
  76. const int rightDisplayTX = 3;
  77. const int leftDisplayRX = 4; /* Unused */
  78. const int rightDisplayRX = 5; /* Unused */
  79. /* Force Sensitive Resistor Switches (Analog inputs) */
  80. //const int leftFSR = A7;
  81. //const int rightFSR = A0;
  82. //const int leftFSRThreshold = 10; /* > this number is closed */
  83. //const int rightFSRThreshold = 10;
  84. const int leftFSRSimPin = A7;
  85. const int rightFSRSimPin = A0;
  86. /* Start Button */
  87. const int leftReadyButtonPin = 13;
  88. const int rightReadyButtonPin = 8;
  89. /* Difficulty */
  90. //const int difficultyLeftPin = 46;
  91. //const int difficultyRightPin = 47;
  92. /* Loop delays
  93. n.b. It occurs to me that unusual values for these variables /may/ upset
  94. the math on looping. Probably not, but if you run into problems, return
  95. these to original values of 100 and 25 respectively
  96. */
  97. const int mainDelay = 100; /* How long to sleep during the main loop */
  98. const int countdownDelay = 25; /* How long to sleep during the countdown loop */
  99. /* Special Functions */
  100. const int modePin = 51; /* Red */
  101. const int buzzPin = 52; /* Green */
  102. const int clearPin = 53; /* White */
  103. /***********
  104. Application Constants
  105. */
  106. const int LED_COUNT = 24;
  107. const unsigned int buzzerFrequency = 70;
  108. const int buzzerDuration = 1800;
  109. const unsigned int beepFrequency = 3700;
  110. const int beepDuration = 100;
  111. const int beepMultiplier = 3; /* long beep is this x as long a short beep */
  112. const unsigned long renegDelay = 500;
  113. const unsigned long debounceDelay = 250;
  114. /***********
  115. Application Variables
  116. */
  117. unsigned long lastSongCheck = 0;
  118. BackgroundRingClass rightRing = BackgroundRingClass(LED_COUNT, ledPinRight);
  119. BackgroundRingClass leftRing = BackgroundRingClass(LED_COUNT, ledPinLeft);
  120. SoftwareSerial leftDisplay(leftDisplayRX, leftDisplayTX);
  121. SoftwareSerial rightDisplay(rightDisplayRX, rightDisplayTX);
  122. eRCaGuy_ButtonReader leftReadyButton = eRCaGuy_ButtonReader(leftReadyButtonPin);
  123. eRCaGuy_ButtonReader rightReadyButton = eRCaGuy_ButtonReader(rightReadyButtonPin);
  124. eRCaGuy_ButtonReader leftFSRButton = eRCaGuy_ButtonReader(leftFSRSimPin, 25);
  125. eRCaGuy_ButtonReader rightFSRButton = eRCaGuy_ButtonReader(rightFSRSimPin, 25);
  126. eRCaGuy_ButtonReader clearToggle = eRCaGuy_ButtonReader(clearPin);
  127. /* Buzzer: Some constants for playing a song: */
  128. const int songLength = 18;
  129. char notes[] = "cdfda ag cdfdg gf ";
  130. int beats[] = {1, 1, 1, 1, 1, 1, 4, 4, 2, 1, 1, 1, 1, 1, 1, 4, 4, 2};
  131. const int tempo = 118;
  132. int songLength2 = 26;
  133. char notes2[] = "eeeeeeegcde fffffeeeeddedg";
  134. int beats2[] = { 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
  135. const int tempo2 = 130;
  136. /* LEDs */
  137. unsigned long lastPrettyLEDCheck = 0;
  138. /* 7 Segment */
  139. long rightClock = 0;
  140. long leftClock = 0;
  141. #define APOSTROPHE 5
  142. #define COLON 4
  143. #define DECIMAL4 3
  144. #define DECIMAL3 2
  145. #define DECIMAL2 1
  146. #define DECIMAL1 0
  147. /***********
  148. Code
  149. */
  150. void setup() {
  151. Serial.begin(115200); // Serial used for logging
  152. /* Buzzer Setup */
  153. pinMode(buzzerPin, OUTPUT);
  154. randomSeed(analogRead(randomPin));
  155. /* Digital LED Setup */
  156. for(int i = 0; i < 5; i++) {
  157. pinMode(ledPinsLeft[i], OUTPUT);
  158. digitalWrite(ledPinsLeft[i], LOW);
  159. pinMode(ledPinsRight[i], OUTPUT);
  160. digitalWrite(ledPinsRight[i], LOW);
  161. }
  162. /* clearLEDs(); */
  163. clearLEDs();
  164. rightRing.setColor(BLACK, 255, true);
  165. leftRing.setColor(BLACK, 255, true);
  166. /* 7 Segment Displays */
  167. leftDisplay.listen();
  168. leftDisplay.begin(9600);
  169. leftDisplay.write('v');
  170. leftDisplay.write(0x7A);
  171. leftDisplay.write((byte) brightness);
  172. rightDisplay.listen();
  173. rightDisplay.begin(9600);
  174. rightDisplay.write('v');
  175. rightDisplay.write(0x7A);
  176. rightDisplay.write((byte) brightness);
  177. longbeep(); delay(400);
  178. printClocks(1223,1996);
  179. /* Initialize our buttons */
  180. pinMode(leftReadyButtonPin, INPUT_PULLUP);
  181. pinMode(rightReadyButtonPin, INPUT_PULLUP);
  182. pinMode(leftFSRSimPin, INPUT_PULLUP);
  183. pinMode(rightFSRSimPin, INPUT_PULLUP);
  184. //pinMode(leftFSR, INPUT_PULLUP);
  185. //pinMode(rightFSR, INPUT_PULLUP);
  186. /* And our switches */
  187. pinMode(modePin, INPUT_PULLUP); /* Red */
  188. pinMode(clearPin, INPUT_PULLUP); /* Green */
  189. pinMode(buzzPin, INPUT_PULLUP); /* White */
  190. /* And our sliders */
  191. //pinMode(difficultyLeftPin, INPUT_PULLUP); /* HIGH is normal difficulty */
  192. //pinMode(difficultyRightPin, INPUT_PULLUP);
  193. /* Demo the Christmas Tree */
  194. setLEDs(BLACK, BLACK, BLACK, BLACK, YELLOW);
  195. rightRing.init_pulse_and_beep(YELLOW, 80, 400, buzzerPin, beepFrequency, beepDuration);
  196. leftRing.init_pulse_and_beep(YELLOW, 80, 400, buzzerPin, 0, beepDuration);
  197. mydelay(400);
  198. setLEDs(BLACK, BLACK, BLACK, YELLOW, BLACK);
  199. rightRing.init_pulse_and_beep(YELLOW, 80, 400, buzzerPin, beepFrequency, beepDuration);
  200. leftRing.init_pulse_and_beep(YELLOW, 80, 400, buzzerPin, 0, beepDuration);
  201. mydelay(400);
  202. setLEDs(BLACK, BLACK, YELLOW, BLACK, BLACK);
  203. rightRing.init_pulse_and_beep(YELLOW, 80, 400, buzzerPin, beepFrequency, beepDuration);
  204. leftRing.init_pulse_and_beep(YELLOW, 80, 400, buzzerPin, 0, beepDuration);
  205. mydelay(400);
  206. delay(100);
  207. setLEDs(BLACK, GREEN, BLACK, BLACK, BLACK);
  208. //rightRing.init_pulse_and_beep(DARKGREEN, 80, 1000, buzzerPin, beepFrequency, 300);
  209. //leftRing.init_pulse_and_beep(DARKGREEN, 80, 1000, buzzerPin, 0, 300);
  210. leftRing.init_solid(DARKGREEN, 80);
  211. rightRing.init_solid(DARKGREEN, 80);
  212. longbeep();
  213. delay(1000);
  214. setLEDs(BLACK, BLACK, BLACK, BLACK, BLACK);
  215. rightRing.init_idle();
  216. leftRing.init_idle();
  217. //longbeep();
  218. /* 7 Segment Display Continued */
  219. int special_clocks = random(0, 1000);
  220. if(special_clocks < 100) {
  221. // BOOBIES!
  222. leftClock=531;
  223. rightClock=8008;
  224. printClocks(leftClock, rightClock);
  225. } else if(special_clocks < 200) {
  226. leftClock=1223;
  227. rightClock=2025;
  228. printClocks(leftClock,rightClock);
  229. } else {
  230. leftClock=1223;
  231. rightClock=2016;
  232. printClocks(leftClock,rightClock);
  233. }
  234. //longbeep();
  235. /* start button */
  236. //pinMode(startButtonPin, INPUT_PULLUP);
  237. Serial.println("Setup complete.");
  238. }
  239. void mydelay(int ms) {
  240. // things we do during delays
  241. unsigned long starttime = millis();
  242. while(millis() - starttime < ms) {
  243. rightRing.tick();
  244. leftRing.tick();
  245. }
  246. }
  247. /* MAIN LOOP */
  248. void loop() {
  249. int8_t clearButtonAction;
  250. boolean clearButtonState;
  251. // put your main code here, to run repeatedly:
  252. easterEggSongCheck(); // Sometimes we play a song
  253. prettyLEDCheck(); // Sometimes we do something pretty with LEDs
  254. //prettyRingCheck(); // Sometimes we do something pretty with the RGB LEDs
  255. leftRing.tick();
  256. rightRing.tick();
  257. clearToggle.readButton(&clearButtonAction, &clearButtonState);
  258. if(clearButtonAction == 1) {
  259. Serial.println("clear action called");
  260. if(random(0, 1000) < 100) {
  261. leftClock=531;
  262. rightClock=8008;
  263. printClocks(leftClock, rightClock);
  264. } else {
  265. leftClock=0;
  266. rightClock=0;
  267. printClocks(leftClock,rightClock);
  268. }
  269. }
  270. printClocks(leftClock, rightClock);
  271. shouldwebuzz(true); // blocking buzz so we don't do LED stuff
  272. /* If either coaster is open (no glass), continue through the loop */
  273. if (leftSwitchOpen() || rightSwitchOpen()) {
  274. clearLEDs();
  275. if(!leftSwitchOpen()) {
  276. digitalWrite(ledPinsLeft[0], HIGH);
  277. leftRing.init_solid(RED, 80);
  278. } else if(leftRing.action == Solid) {
  279. leftRing.init_idle();
  280. }
  281. if(!rightSwitchOpen()) {
  282. digitalWrite(ledPinsRight[0], HIGH);
  283. rightRing.init_solid(RED, 80);
  284. } else if(rightRing.action == Solid) {
  285. rightRing.init_idle();
  286. }
  287. mydelay(mainDelay);
  288. return; /* Can't continue in main loop */
  289. } else {
  290. /* Both are closed, race can begin */
  291. ledsToRed();
  292. if(millis() % 5000 == 0) {
  293. Serial.println("Waiting for start button to be pressed.");
  294. }
  295. if (startButtonPressed()) {
  296. countdown();
  297. /* We're back from a race */
  298. /* Reset easter eggs */
  299. lastSongCheck = lastPrettyLEDCheck = millis();
  300. startButtonPressed(); /* Clear out "stuck" state input */
  301. //return; /* no continue in main loop */
  302. }
  303. }
  304. /* Rest before looping again */
  305. mydelay(mainDelay);
  306. }
  307. void countdown(void) {
  308. unsigned long randomAdditionalDelay;
  309. int mode; /* 1 is drag race, 0 is randomness */
  310. int cstep = -1; /* Which step of the countdown are we on? */
  311. rightClock = leftClock = 0;
  312. if(digitalRead(modePin) == HIGH) {
  313. /* Drag race mode */
  314. leftRing.init_solid(YELLOW, 80);
  315. rightRing.init_solid(YELLOW, 80);
  316. mode = 1;
  317. } else {
  318. /* Random delay mode */
  319. setLEDs(RED, BLACK, BLACK, BLACK, YELLOW);
  320. leftRing.init_solid(YELLOW, 80);
  321. rightRing.init_solid(YELLOW, 80);
  322. randomAdditionalDelay = random(maxDelay);
  323. mode = 0;
  324. }
  325. if(mode) {
  326. Serial.print("Start button pressed. Beginning xmas tree in ");
  327. Serial.print(startDelay);
  328. Serial.println("ms");
  329. } else {
  330. Serial.print("Start button pressed. Skipping xmas tree. Beginning in ");
  331. Serial.print(startDelay + randomAdditionalDelay);
  332. Serial.println("ms.");
  333. }
  334. printClocks(leftClock, rightClock);
  335. startsong();
  336. mydelay(startDelay);
  337. unsigned long start = millis();
  338. while (1) {
  339. rightRing.tick();
  340. leftRing.tick();
  341. shouldwebuzz(false);
  342. if (leftSwitchOpen_debounce(1) || rightSwitchOpen_debounce(1)) {
  343. /* FALSE START! */
  344. if (leftSwitchOpen_debounce(1)) {
  345. Serial.println("FALSE START: Player Left");
  346. leftRing.init_solid(RED, 80);
  347. buzz_nonblock();
  348. leftClock = 9999;
  349. rightClock = 0;
  350. printClocks(leftClock, rightClock);
  351. for(int i = 0; i < 3; i++) {
  352. leftDisplay.listen();
  353. leftDisplay.write(0x7A);
  354. leftDisplay.write((byte) 0);
  355. delay(150);
  356. leftDisplay.listen();
  357. leftDisplay.write(0x7A);
  358. leftDisplay.write((byte) brightness);
  359. delay(150);
  360. }
  361. delay(buzzerDuration - 900); /* Rest for the remaining buzz */
  362. leftSwitchOpen_debounce(1);
  363. rightSwitchOpen_debounce(1); /* Get another reading just to clear things out */
  364. leftRing.init_pulse(RED, 80, 1000);
  365. mydelay(1000);
  366. leftRing.init_pulse(RED, 80, 1000);
  367. mydelay(1000);
  368. leftRing.init_pulse(RED, 80, 1000);
  369. return;
  370. } else if (rightSwitchOpen_debounce(1)) {
  371. Serial.println("FALSE START: Player Right");
  372. rightRing.init_solid(RED, 80);
  373. buzz_nonblock();
  374. rightClock = 9999;
  375. leftClock = 0;
  376. printClocks(leftClock, rightClock);
  377. for(int i = 0; i < 3; i++) {
  378. rightDisplay.listen();
  379. rightDisplay.write(0x7A);
  380. rightDisplay.write((byte) 0);
  381. delay(150);
  382. rightDisplay.listen();
  383. rightDisplay.write(0x7A);
  384. rightDisplay.write((byte) 255);
  385. delay(150);
  386. }
  387. delay(buzzerDuration - 900); /* Rest for the remaining buzz */
  388. leftSwitchOpen_debounce(1);
  389. rightSwitchOpen_debounce(1); /* Get another reading just to clear things out */
  390. rightRing.init_pulse(RED, 80, 1000);
  391. mydelay(1000);
  392. rightRing.init_pulse(RED, 80, 1000);
  393. mydelay(1000);
  394. rightRing.init_pulse(RED, 80, 1000);
  395. return;
  396. } else {
  397. /* WTF? Timing issue */
  398. Serial.println("WARNING: False start detected, but corrected?!");
  399. }
  400. }
  401. /* No false start */
  402. if(mode) {
  403. /* drag race! */
  404. switch ( (millis() - start) / lightDelay ) {
  405. case 0:
  406. if (cstep != 0) {
  407. Serial.println("Countdown ... 3");
  408. setLEDs(RED, BLACK, BLACK, BLACK, YELLOW);
  409. rightRing.init_pulse_and_beep(YELLOW, 80, lightDelay, buzzerPin, beepFrequency, beepDuration);
  410. leftRing.init_pulse_and_beep(YELLOW, 80, lightDelay, buzzerPin, 0, beepDuration);
  411. cstep = 0;
  412. }
  413. continue;
  414. case 1:
  415. if (cstep != 1) {
  416. Serial.println("Countdown ... 2");
  417. setLEDs(RED, BLACK, BLACK, YELLOW, BLACK);
  418. rightRing.init_pulse_and_beep(YELLOW, 80, lightDelay, buzzerPin, beepFrequency, beepDuration);
  419. leftRing.init_pulse_and_beep(YELLOW, 80, lightDelay, buzzerPin, 0, beepDuration);
  420. cstep = 1;
  421. }
  422. continue;
  423. case 2:
  424. if (cstep != 2) {
  425. Serial.println("Countdown ... 1");
  426. setLEDs(RED, BLACK, YELLOW, BLACK, BLACK);
  427. rightRing.init_pulse_and_beep(YELLOW, 80, lightDelay, buzzerPin, beepFrequency, beepDuration);
  428. leftRing.init_pulse_and_beep(YELLOW, 80, lightDelay, buzzerPin, 0, beepDuration);
  429. cstep = 2;
  430. }
  431. continue;
  432. case 3:
  433. Serial.println("Countdown ... GO!!!!!!!!");
  434. setLEDs(BLACK, GREEN, BLACK, BLACK, BLACK);
  435. leftRing.init_solid(GREEN, 80);
  436. rightRing.init_solid(GREEN, 80);
  437. mydelay(lightDelay/2);
  438. longbeep();
  439. race_loop();
  440. return;
  441. }
  442. } else {
  443. /* Silent start */
  444. if(millis() > (start + startDelay + randomAdditionalDelay)) {
  445. Serial.println("Random delay met... GO!!!!!!!!");
  446. setLEDs(BLACK, GREEN, BLACK, BLACK, BLACK);
  447. leftRing.init_solid(GREEN, 80);
  448. rightRing.init_solid(GREEN, 80);
  449. longbeep();
  450. race_loop();
  451. return;
  452. }
  453. }
  454. mydelay(countdownDelay); /* Make the loop less aggressive */
  455. }
  456. Serial.println("Should never get here...");
  457. }
  458. void race_loop(void) {
  459. /* Race is on! */
  460. unsigned long start = millis();
  461. Serial.print("Race is ON at ");
  462. Serial.println(start);
  463. boolean handicap_left = false;
  464. boolean handicap_right = false;
  465. unsigned long timerLeft, timerRight;
  466. timerLeft = timerRight = 0;
  467. /* determine handicap settings */
  468. //if(digitalRead(difficultyLeftPin) == 0) {
  469. // handicap_left = true;
  470. //}
  471. //if(digitalRead(difficultyRightPin) == 0) {
  472. // handicap_right = true;
  473. //}
  474. /* Record whether the racer picked up his/her cup */
  475. int leftStarted = 0;
  476. int rightStarted = 0;
  477. unsigned long loopstart = millis();
  478. unsigned long lastloop = millis();
  479. unsigned long leftRenegBounce = 0;
  480. unsigned long rightRenegBounce = 0;
  481. while (1) {
  482. loopstart = millis();
  483. //Serial.print("Loop time with serial: ");
  484. //Serial.println(loopstart - lastloop);
  485. /* Check for winners */
  486. boolean leftOpen, rightOpen;
  487. leftOpen = rightOpen = false;
  488. /* Choose which one to read first randomly to offset any potential bias. I
  489. * find that the loop is generally less than 1ms, so this is probably unnecessary,
  490. * but it doesn't hurt.
  491. */
  492. if(random(0, 2)) {
  493. // Serial.print("Left first. Time = ");
  494. // Serial.println(millis());
  495. leftOpen = leftSwitchOpen();
  496. rightOpen = rightSwitchOpen();
  497. } else {
  498. // Serial.print("Right first. Time = ");
  499. // Serial.println(millis());
  500. rightOpen = rightSwitchOpen();
  501. leftOpen = leftSwitchOpen();
  502. }
  503. /* Check for finishers */
  504. if (!leftOpen && leftStarted && !timerLeft) {
  505. /* Finished */
  506. Serial.print("Left player finished at ");
  507. Serial.println(millis() - start);
  508. timerLeft = (millis() - start) / 10;
  509. //if(handicap_left) {
  510. // /* Handicapped player */
  511. // timerLeft = timerLeft - (timerLeft >> 2);
  512. //}
  513. leftRing.init_solid(ORANGE, 80);
  514. beep_nonblock();
  515. } else if (leftOpen && !leftStarted) {
  516. Serial.print("Left cup lifted at ");
  517. Serial.println(millis() - start);
  518. leftStarted = 1;
  519. leftRing.init_solid(YELLOW, 80);
  520. }
  521. if (!rightOpen && rightStarted && !timerRight) {
  522. /* Finished */
  523. Serial.print("Right player finished at ");
  524. Serial.println(millis() - start);
  525. timerRight = (millis() - start) / 10;
  526. //if(handicap_right) {
  527. // /* Handicapped player */
  528. // timerRight = timerRight - (timerRight >> 2);
  529. //}
  530. rightRing.init_solid(ORANGE, 80);
  531. beep_nonblock();
  532. } else if (rightOpen && !rightStarted) {
  533. Serial.print("Right cup lifted at ");
  534. Serial.println(millis() - start);
  535. rightStarted = 1;
  536. rightRing.init_solid(YELLOW, 80);
  537. }
  538. /* Check for renegers
  539. * Note to cheaters: too hard a hit can make the opponent's cup bounce.
  540. * However, we can't turn this off, because things bounce on removal.
  541. */
  542. if (leftSwitchOpen() && timerLeft) {
  543. /* Bullshit! */
  544. if(leftRenegBounce == 0) {
  545. leftRenegBounce = millis();
  546. } else if((millis() - leftRenegBounce) > renegDelay) {
  547. Serial.println("Left player RENEGS! This is bullshit!");
  548. timerLeft = 0;
  549. leftRenegBounce = 0;
  550. } else {
  551. Serial.print("Left reneg on delay: ");
  552. Serial.println(millis() - leftRenegBounce);
  553. }
  554. }
  555. if (rightSwitchOpen() && timerRight) {
  556. /* Bullshit! */
  557. if(rightRenegBounce == 0) {
  558. rightRenegBounce = millis();
  559. } else if((millis() - rightRenegBounce) > renegDelay) {
  560. Serial.println("Right player RENEGS! This is bullshit!");
  561. timerRight = 0;
  562. rightRenegBounce = 0;
  563. } else {
  564. Serial.print("Right reneg on delay: ");
  565. Serial.println(millis() - rightRenegBounce);
  566. }
  567. }
  568. /* If still a winner and not a reneger, I think we have a winner */
  569. if (timerLeft) {
  570. leftClock = timerLeft;
  571. } else {
  572. leftClock = (millis() - start) / 10;
  573. //if(handicap_left) {
  574. // /* Handicapped player */
  575. // leftClock = leftClock - (leftClock >> 2);
  576. //}
  577. }
  578. if (timerRight) {
  579. rightClock = timerRight;
  580. } else {
  581. rightClock = (millis() - start) / 10;
  582. //if(handicap_right) {
  583. // /* Handicapped player */
  584. // rightClock = rightClock - (rightClock >> 2);
  585. //}
  586. }
  587. /* Print the clocks */
  588. printClocks(leftClock, rightClock);
  589. if (timerRight && timerLeft) {
  590. /* Race is finished */
  591. ledsToRed();
  592. if(timerRight < timerLeft) {
  593. Serial.println("Right player WINS!");
  594. rightRing.init_solid(GREEN, 80);
  595. leftRing.init_solid(RED, 80);
  596. for(int i = 0; i < 3; i++) {
  597. rightDisplay.listen();
  598. rightDisplay.write(0x7A);
  599. rightDisplay.write((byte) 0);
  600. delay(150);
  601. beep();
  602. rightDisplay.listen();
  603. rightDisplay.write(0x7A);
  604. rightDisplay.write((byte) 255);
  605. delay(150);
  606. }
  607. } else if(timerLeft < timerRight) {
  608. leftRing.init_solid(GREEN, 80);
  609. rightRing.init_solid(RED, 80);
  610. for(int i = 0; i < 3; i++) {
  611. leftDisplay.listen();
  612. leftDisplay.write(0x7A);
  613. leftDisplay.write((byte) 0);
  614. delay(150);
  615. beep();
  616. leftDisplay.listen();
  617. leftDisplay.write(0x7A);
  618. leftDisplay.write((byte) 255);
  619. delay(150);
  620. }
  621. Serial.println("Left player WINS!");
  622. } else {
  623. Serial.println("TIE GAME!!!");
  624. }
  625. playWinner();
  626. /* Wait until start buttons are no longer pressed */
  627. while(startButtonPressed()) {
  628. mydelay(100);
  629. }
  630. return;
  631. }
  632. lastloop = loopstart;
  633. }
  634. Serial.println("ERROR: Woah. Just Woah. How the fuck? 0x73184fcgukl");
  635. }
  636. /* Beep and buzz if those toggles are pressed */
  637. void shouldwebuzz(bool block) {
  638. if(digitalRead(buzzPin) == LOW) {
  639. if(block) {
  640. buzz();
  641. } else {
  642. buzz_nonblock();
  643. }
  644. }
  645. }
  646. /* Start button switch */
  647. int startButtonPressed() {
  648. int8_t leftButtonAction, rightButtonAction;
  649. boolean leftButtonState, rightButtonState;
  650. leftReadyButton.readButton(&leftButtonAction, &leftButtonState);
  651. rightReadyButton.readButton(&rightButtonAction, &rightButtonState);
  652. if(leftButtonState == false && rightButtonState == false) {
  653. Serial.println("Both ready buttons pressed.");
  654. return 1;
  655. } else {
  656. /* Serial.print("Left state: ");
  657. Serial.println(leftButtonState);
  658. Serial.print("Right state: ");
  659. Serial.println(rightButtonState);
  660. */
  661. return 0;
  662. }
  663. }
  664. /* FSR Functions */
  665. int leftSwitchOpen() {
  666. return leftSwitchOpen_debounce(0);
  667. }
  668. int leftSwitchOpen_debounce(int silent) {
  669. return leftSwitchOpen(silent);
  670. // Temporarily just ignoring everything
  671. /* Not a standard debounce method. We're going to keep the last 16 values
  672. * and majority rules.
  673. */
  674. static int results[16] = {0,0,0,0,0,
  675. 0,0,0,0,0,
  676. 0,0,0,0,0,0};
  677. static int pointer = 0;
  678. results[pointer] = leftSwitchOpen(silent);
  679. pointer = (pointer + 1) % 16;
  680. int sum = 0;
  681. // Serial.print("Left array: [");
  682. for(int i = 0; i < 16; i++) {
  683. sum+=results[i];
  684. // Serial.print(results[i]);
  685. // Serial.print(",");
  686. }
  687. if(sum > 8) {
  688. // Serial.println("]; Returning 1");
  689. return 1;
  690. } else {
  691. // Serial.println("]; Returning 0");
  692. return 0;
  693. }
  694. }
  695. int leftSwitchOpen(int silent) {
  696. int8_t leftButtonAction;
  697. boolean leftButtonState;
  698. static int lastvalue = 0;
  699. leftFSRButton.readButton(&leftButtonAction, &leftButtonState);
  700. if(leftButtonState == false) {
  701. /* Button is low, meaning it's pressed */
  702. return 0;
  703. }
  704. return 1;
  705. }
  706. int rightSwitchOpen() {
  707. return rightSwitchOpen_debounce(0);
  708. }
  709. int rightSwitchOpen_debounce(int silent) {
  710. return rightSwitchOpen(silent);
  711. /* Not a standard debounce method. We're going to keep the last 16 values
  712. * and majority rules.
  713. */
  714. // we are ignoring all this
  715. static int results[16] = {0,0,0,0,0,
  716. 0,0,0,0,0,
  717. 0,0,0,0,0,0};
  718. static int pointer = 0;
  719. results[pointer] = rightSwitchOpen(silent);
  720. pointer = (pointer + 1) % 16;
  721. int sum = 0;
  722. // Serial.print("Right array: [");
  723. for(int i = 0; i < 16; i++) {
  724. sum+=results[i];
  725. // Serial.print(results[i]);
  726. // Serial.print(",");
  727. }
  728. if(sum > 8) {
  729. // Serial.println("]; Returning 1");
  730. return 1;
  731. } else {
  732. // Serial.println("]; Returning 0");
  733. return 0;
  734. }
  735. }
  736. int rightSwitchOpen(int silent) {
  737. int8_t rightButtonAction;
  738. boolean rightButtonState;
  739. static int lastvalue = 0;
  740. rightFSRButton.readButton(&rightButtonAction, &rightButtonState);
  741. if(rightButtonState == false) {
  742. /*Button is low, meaning it's pressed */
  743. return 0;
  744. }
  745. return 1;
  746. }
  747. int switchOpen(int pin, int threshold, int silent) {
  748. int fsrADC = analogRead(pin);
  749. #ifdef SIMULATION
  750. fsrADC = random(0, 1000);
  751. #endif
  752. if (fsrADC < threshold) {
  753. if (!silent) {
  754. Serial.print(fsrADC);
  755. Serial.println(" -- OPEN");
  756. }
  757. return 1;
  758. }
  759. if (!silent) {
  760. Serial.print(fsrADC);
  761. Serial.println(" -- CLOSED");
  762. }
  763. return 0;
  764. }
  765. /* 7-Segment Functions */
  766. void printClocks(unsigned long leftValue, unsigned long rightValue) {
  767. if (leftValue > 9999) {
  768. leftValue = 9999;
  769. }
  770. if (rightValue > 9999) {
  771. rightValue = 9999;
  772. }
  773. // Serial.print("Clocks: ");
  774. char tempstring[10];
  775. snprintf(tempstring, sizeof(tempstring), "%04lu", leftValue);
  776. leftDisplay.listen();
  777. leftDisplay.write(tempstring);
  778. // Serial.print(tempstring);
  779. snprintf(tempstring, sizeof(tempstring), "%04lu", rightValue);
  780. rightDisplay.listen();
  781. rightDisplay.write(tempstring);
  782. // Serial.print(" ");
  783. // Serial.println(tempstring);
  784. /* TUrn on decimal point */
  785. leftDisplay.listen();
  786. leftDisplay.write(0x77); /* Decimal, colon, and apostrophe command */
  787. leftDisplay.write(0b000010); /* Decimal 2 is second bit) */
  788. rightDisplay.listen();
  789. rightDisplay.write(0x77); /* Decimal, colon, and apostrophe command */
  790. rightDisplay.write(0b000010); /* Decimal 2 is second bit) */
  791. }
  792. /* LED Functions */
  793. void ledsToRed() {
  794. leftRing.init_solid(RED, 80);
  795. rightRing.init_solid(RED, 80);
  796. digitalWrite(ledPinsLeft[0], HIGH);
  797. digitalWrite(ledPinsRight[0], HIGH);
  798. for(int i=1; i<5; i++) {
  799. digitalWrite(ledPinsLeft[i], LOW);
  800. digitalWrite(ledPinsRight[i], LOW);
  801. }
  802. }
  803. // Sets red light on.
  804. //void ws2812_ledsToRed() {
  805. // clearLEDs();
  806. // rightRing.setPixelColor(0, RED);
  807. // leftRing.setPixelColor(0, RED);
  808. // rightRing.show();
  809. // leftRing.show();
  810. //}
  811. /* Clears all LEDs (for WS2812, except the top one) */
  812. void clearLEDs() {
  813. for(int i = 0; i < 5; i++) {
  814. digitalWrite(ledPinsLeft[i], LOW);
  815. digitalWrite(ledPinsRight[i], LOW);
  816. }
  817. }
  818. void ws2812_clearLEDs()
  819. {
  820. //ring_setColor(rightRing, WHITE);
  821. //ring_setColor(leftRing, WHITE);
  822. }
  823. void setLEDs(unsigned long redlight,
  824. unsigned long greenlight,
  825. unsigned long yellow3,
  826. unsigned long yellow2,
  827. unsigned long yellow1) {
  828. //ws2812_setLEDs(redlight, greenlight, yellow3, yellow2, yellow1);
  829. /* If black, turn it off, otherwise turn it on */
  830. if(redlight == BLACK) {
  831. digitalWrite(ledPinsLeft[0], LOW);
  832. digitalWrite(ledPinsRight[0], LOW);
  833. } else {
  834. digitalWrite(ledPinsLeft[0], HIGH);
  835. digitalWrite(ledPinsRight[0], HIGH);
  836. }
  837. /* If black, turn it off, otherwise turn it on */
  838. if(greenlight == BLACK) {
  839. digitalWrite(ledPinsLeft[1], LOW);
  840. digitalWrite(ledPinsRight[1], LOW);
  841. } else {
  842. digitalWrite(ledPinsLeft[1], HIGH);
  843. digitalWrite(ledPinsRight[1], HIGH);
  844. }
  845. /* If black, turn it off, otherwise turn it on */
  846. if(yellow3 == BLACK) {
  847. digitalWrite(ledPinsLeft[2], LOW);
  848. digitalWrite(ledPinsRight[2], LOW);
  849. } else {
  850. digitalWrite(ledPinsLeft[2], HIGH);
  851. digitalWrite(ledPinsRight[2], HIGH);
  852. }
  853. /* If black, turn it off, otherwise turn it on */
  854. if(yellow2 == BLACK) {
  855. digitalWrite(ledPinsLeft[3], LOW);
  856. digitalWrite(ledPinsRight[3], LOW);
  857. } else {
  858. digitalWrite(ledPinsLeft[3], HIGH);
  859. digitalWrite(ledPinsRight[3], HIGH);
  860. }
  861. /* If black, turn it off, otherwise turn it on */
  862. if(yellow1 == BLACK) {
  863. digitalWrite(ledPinsLeft[4], LOW);
  864. digitalWrite(ledPinsRight[4], LOW);
  865. } else {
  866. digitalWrite(ledPinsLeft[4], HIGH);
  867. digitalWrite(ledPinsRight[4], HIGH);
  868. }
  869. }
  870. void red_green_pulse() {
  871. // pulses one coaster red and the other green.
  872. leftRing.setBrightness(1);
  873. rightRing.setBrightness(1);
  874. if(random(0, 2)) {
  875. leftring_setColor(RED);
  876. } else {
  877. leftring_setColor(GREEN);
  878. }
  879. if(random(0, 2)) {
  880. rightring_setColor(RED);
  881. } else {
  882. rightring_setColor(GREEN);
  883. }
  884. for(int pulses=0; pulses < 3; pulses++) {
  885. Serial.println("Pulsing up.");
  886. for(int brightness=1; brightness <= 255; brightness++) {
  887. rightRing.setBrightness(brightness);
  888. leftRing.setBrightness(brightness);
  889. rightRing.show();
  890. leftRing.show();
  891. delay(1);
  892. }
  893. Serial.println("Pulsing down.");
  894. for(int brightness=255; brightness >= 1; brightness--) {
  895. rightRing.setBrightness(brightness);
  896. leftRing.setBrightness(brightness);
  897. rightRing.show();
  898. leftRing.show();
  899. delay(1);
  900. }
  901. }
  902. leftRing.setBrightness(255);
  903. rightRing.setBrightness(255);
  904. clearLEDs();
  905. }
  906. void rings_setColor(unsigned long color) {
  907. for(uint8_t i=0; i< LED_COUNT; i++) {
  908. rightRing.setPixelColor(i, color);
  909. leftRing.setPixelColor(i, color);
  910. }
  911. rightRing.show();
  912. leftRing.show();
  913. }
  914. void leftring_setColor(unsigned long color) {
  915. for(uint8_t i=0; i< LED_COUNT; i++) {
  916. leftRing.setPixelColor(i, color);
  917. }
  918. leftRing.show();
  919. }
  920. void rightring_setColor(unsigned long color) {
  921. for(uint8_t i=0; i< LED_COUNT; i++) {
  922. rightRing.setPixelColor(i, color);
  923. }
  924. rightRing.show();
  925. }
  926. void ws2812_setLEDs(unsigned long redlight,
  927. unsigned long greenlight,
  928. unsigned long yellow3,
  929. unsigned long yellow2,
  930. unsigned long yellow1) {
  931. rightRing.setPixelColor(0, redlight);
  932. rightRing.setPixelColor(1, greenlight);
  933. rightRing.setPixelColor(2, yellow3);
  934. rightRing.setPixelColor(3, yellow2);
  935. rightRing.setPixelColor(4, yellow1);
  936. rightRing.setPixelColor(LED_COUNT, topColor);
  937. leftRing.setPixelColor(0, redlight);
  938. leftRing.setPixelColor(1, greenlight);
  939. leftRing.setPixelColor(2, yellow3);
  940. leftRing.setPixelColor(3, yellow2);
  941. leftRing.setPixelColor(4, yellow1);
  942. leftRing.setPixelColor(LED_COUNT, topColor);
  943. rightRing.show();
  944. leftRing.show();
  945. }
  946. void prettyLEDCheck() {
  947. /* Lets see if we should do pretty things with the regular LEDs */
  948. if ( (millis() - lastPrettyLEDCheck) > (prettyLEDFrequency * 1000) ) {
  949. lastPrettyLEDCheck = millis();
  950. if ( (random(0, 1000) < long(prettyLEDProbability * 1000.0)) ) {
  951. Serial.println("Pretty LED Approved");
  952. prettyLED();
  953. } else {
  954. Serial.println("Pretty lED probability check declined.");
  955. }
  956. }
  957. }
  958. void prettyLED() {
  959. if(random(0, 2) == 0) {
  960. // use the classic LEDs
  961. if(random(0, 1000) < 500) {
  962. prettyCircleLED();
  963. prettyCircleLED();
  964. // prettyCircleLED();
  965. } else {
  966. prettyBounceLED();
  967. prettyBounceLED();
  968. prettyBounceLED();
  969. }
  970. } else {
  971. // Use the RGB LEDs
  972. if(random(0, 10) != 0) {
  973. // 90% chance that both rings do the same thing
  974. int draw = leftRing.random_event();
  975. rightRing.random_event(draw);
  976. } else {
  977. leftRing.random_event();
  978. rightRing.random_event();
  979. }
  980. }
  981. }
  982. void prettyCircleLED() {
  983. clearLEDs();
  984. for(int i = 4; i >= 0; i--) {
  985. shouldwebuzz(true);
  986. Serial.print("Pin: ");
  987. Serial.println(i);
  988. digitalWrite(ledPinsLeft[i], HIGH);
  989. delay(100);
  990. digitalWrite(ledPinsLeft[i], LOW);
  991. }
  992. for(int i = 0; i < 5; i++) {
  993. shouldwebuzz(true);
  994. Serial.print("Pin: ");
  995. Serial.println(i);
  996. digitalWrite(ledPinsRight[i], HIGH);
  997. delay(100);
  998. digitalWrite(ledPinsRight[i], LOW);
  999. }
  1000. }
  1001. void prettyBounceLED() {
  1002. clearLEDs();
  1003. for(int i = 4; i >= 0; i--) {
  1004. shouldwebuzz(true);
  1005. digitalWrite(ledPinsLeft[i], HIGH);
  1006. digitalWrite(ledPinsRight[i], HIGH);
  1007. delay(100);
  1008. digitalWrite(ledPinsLeft[i], LOW);
  1009. digitalWrite(ledPinsRight[i], LOW);
  1010. }
  1011. for(int i = 1; i < 5; i++) {
  1012. shouldwebuzz(true);
  1013. digitalWrite(ledPinsLeft[i], HIGH);
  1014. digitalWrite(ledPinsRight[i], HIGH);
  1015. delay(100);
  1016. digitalWrite(ledPinsLeft[i], LOW);
  1017. digitalWrite(ledPinsRight[i], LOW);
  1018. }
  1019. }
  1020. void prettyRingCheck() {
  1021. // this doesn't work
  1022. static unsigned long last_random_check = millis();
  1023. if(leftRing.action == Idle && rightRing.action == Idle) {
  1024. if(millis() - last_random_check > 1000) { // only check every 10 seconds
  1025. if(random(0, 20) == 0) { // do we do anything?
  1026. if(random(0, 10) != 0) {
  1027. // 90% chance that both rings do the same thing
  1028. int draw = leftRing.random_event();
  1029. rightRing.random_event(draw);
  1030. } else {
  1031. leftRing.random_event();
  1032. rightRing.random_event();
  1033. }
  1034. }
  1035. }
  1036. last_random_check = millis();
  1037. }
  1038. }
  1039. void ws2812_prettyLED() {
  1040. /* Do something interesting */
  1041. /* cylon(YELLOW, 500); */
  1042. }
  1043. // Implements a little larson "cylon" sanner.
  1044. // This'll run one full cycle, down one way and back the other
  1045. void ws2812_cylon(unsigned long color, unsigned long wait)
  1046. {
  1047. Serial.println("Cylons are attacking.");
  1048. // weight determines how much lighter the outer "eye" colors are
  1049. const byte weight = 4;
  1050. // It'll be easier to decrement each of these colors individually
  1051. // so we'll split them out of the 24-bit color value
  1052. byte red = (color & 0xFF0000) >> 16;
  1053. byte green = (color & 0x00FF00) >> 8;
  1054. byte blue = (color & 0x0000FF);
  1055. // Start at closest LED, and move to the outside
  1056. for (int i = 0; i < LED_COUNT; i++)
  1057. {
  1058. clearLEDs();
  1059. rightRing.setPixelColor(i, red, green, blue); // Set the bright middle eye
  1060. leftRing.setPixelColor(i, red, green, blue); // Set the bright middle eye
  1061. // Now set two eyes to each side to get progressively dimmer
  1062. for (int j = 1; j < 3; j++)
  1063. {
  1064. if (i - j >= 0)
  1065. leftRing.setPixelColor(i - j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1066. rightRing.setPixelColor(i - j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1067. if (i - j < LED_COUNT)
  1068. leftRing.setPixelColor(i + j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1069. rightRing.setPixelColor(i + j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1070. }
  1071. leftRing.show(); // Turn the LEDs on
  1072. rightRing.show(); // Turn the LEDs on
  1073. delay(wait); // Delay for visibility
  1074. }
  1075. // Now we go back to where we came. Do the same thing.
  1076. for (int i = LED_COUNT - 2; i >= 1; i--)
  1077. {
  1078. clearLEDs();
  1079. leftRing.setPixelColor(i, red, green, blue);
  1080. rightRing.setPixelColor(i, red, green, blue);
  1081. for (int j = 1; j < 3; j++)
  1082. {
  1083. if (i - j >= 0)
  1084. leftRing.setPixelColor(i - j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1085. rightRing.setPixelColor(i - j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1086. if (i - j < LED_COUNT)
  1087. leftRing.setPixelColor(i + j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1088. rightRing.setPixelColor(i + j, red / (weight * j), green / (weight * j), blue / (weight * j));
  1089. }
  1090. leftRing.show();
  1091. rightRing.show();
  1092. delay(wait);
  1093. }
  1094. }
  1095. /* Song Easter Egg */
  1096. void easterEggSongCheck() {
  1097. /* Lets see if we should play a song */
  1098. if ( (millis() - lastSongCheck) > (songFrequency * 1000) ) {
  1099. lastSongCheck = millis();
  1100. if ( (random(0, 1000) < long(songProbability * 1000.0)) ) {
  1101. Serial.println("Song probability check approved. Never give up!");
  1102. playsong();
  1103. } else {
  1104. Serial.println("Song probability check declined.");
  1105. }
  1106. }
  1107. }
  1108. int frequency(char note)
  1109. {
  1110. // This function takes a note character (a-g), and returns the
  1111. // corresponding frequency in Hz for the tone() function.
  1112. int i;
  1113. const int numNotes = 8; // number of notes we're storing
  1114. // The following arrays hold the note characters and their
  1115. // corresponding frequencies. The last "C" note is uppercase
  1116. // to separate it from the first lowercase "c". If you want to
  1117. // add more notes, you'll need to use unique characters.
  1118. // For the "char" (character) type, we put single characters
  1119. // in single quotes.
  1120. char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  1121. int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523};
  1122. // Now we'll search through the letters in the array, and if
  1123. // we find it, we'll return the frequency for that note.
  1124. for (i = 0; i < numNotes; i++) // Step through the notes
  1125. {
  1126. if (names[i] == note) // Is this the one?
  1127. {
  1128. return (frequencies[i]); // Yes! Return the frequency
  1129. }
  1130. }
  1131. return (0); // We looked through everything and didn't find it,
  1132. // but we still need to return a value, so return 0.
  1133. }
  1134. void playWinner() {
  1135. /* TODO: Ideally, this is "Enjoy MonkeyBOX", but anything will do */
  1136. /* Also, ideally won't block */
  1137. if(random(0, 10) == 0) {
  1138. playsong2();
  1139. } else {
  1140. playsong();
  1141. }
  1142. Serial.println("Insert winner music here.");
  1143. }
  1144. void startsong() {
  1145. /* TODO: Make this something fancier */
  1146. beep();
  1147. delay(200);
  1148. beep();
  1149. delay(200);
  1150. beep();
  1151. delay(200);
  1152. }
  1153. void buzz() {
  1154. /* play a loud, annoying buzz */
  1155. Serial.println("*BUZZ*");
  1156. tone(buzzerPin, buzzerFrequency, buzzerDuration);
  1157. delay(buzzerDuration);
  1158. }
  1159. void buzz_nonblock() {
  1160. /* play a loud, annoying buzz */
  1161. Serial.println("*BUZZ*");
  1162. tone(buzzerPin, buzzerFrequency, buzzerDuration);
  1163. }
  1164. void beep() {
  1165. /* play a simple, pleasant beep */
  1166. Serial.println("*beep*");
  1167. tone(buzzerPin, beepFrequency, beepDuration);
  1168. delay(beepDuration);
  1169. }
  1170. void beep_nonblock() {
  1171. /* play a simple, pleasant beep, but don't wait for it to finish */
  1172. Serial.println("*beep* (but don't wait for it)");
  1173. tone(buzzerPin, beepFrequency, beepDuration);
  1174. }
  1175. void longbeep() {
  1176. /* play a simple, pleasant beep */
  1177. Serial.println("*beeeeeeeeeeeeeeeeeeeeeeeeeep*");
  1178. tone(buzzerPin, beepFrequency, beepDuration * beepMultiplier);
  1179. /* longbeep doesn't delay. Maybe that's inconsistent */
  1180. /* delay(beepDuration * beepMultiplier); */
  1181. }
  1182. void playsong() {
  1183. /* Plays a song.
  1184. Cut directly from the SparkFun tutorial at
  1185. https://learn.sparkfun.com/tutorials/sik-experiment-guide-for-arduino---v32/experiment-11-using-a-piezo-buzzer
  1186. */
  1187. int i, duration;
  1188. for (i = 0; i < songLength; i++) // step through the song arrays
  1189. {
  1190. duration = beats[i] * tempo; // length of note/rest in ms
  1191. if (notes[i] == ' ') // is this a rest?
  1192. {
  1193. delay(duration); // then pause for a moment
  1194. }
  1195. else // otherwise, play the note
  1196. {
  1197. tone(buzzerPin, frequency(notes[i]), duration);
  1198. delay(duration); // wait for tone to finish
  1199. }
  1200. delay(tempo / 10); // brief pause between notes
  1201. }
  1202. }
  1203. void playsong2() {
  1204. /* Plays a song.
  1205. Cut directly from the SparkFun tutorial at
  1206. https://learn.sparkfun.com/tutorials/sik-experiment-guide-for-arduino---v32/experiment-11-using-a-piezo-buzzer
  1207. */
  1208. int i, duration;
  1209. for (i = 0; i < songLength2; i++) // step through the song arrays
  1210. {
  1211. duration = beats2[i] * tempo2; // length of note/rest in ms
  1212. if (notes2[i] == ' ') // is this a rest?
  1213. {
  1214. delay(duration); // then pause for a moment
  1215. }
  1216. else // otherwise, play the note
  1217. {
  1218. tone(buzzerPin, frequency(notes2[i]), duration);
  1219. delay(duration); // wait for tone to finish
  1220. }
  1221. delay(tempo2 / 10); // brief pause between notes
  1222. }
  1223. }
  1224. /* Ring Functions */
  1225. void ring_setColor(Adafruit_NeoPixel& ring, unsigned long color) {
  1226. for(int i=0; i < LED_COUNT; i++) {
  1227. ring.setPixelColor(i, color);
  1228. }
  1229. ring.show();
  1230. }