// not the buzzer, I removed it and yet.
/* nutshell ezButton
# include <ezButton.h>
ezButton button[2] = {3, 2};
button[1].setDebounceTime(21);
button[1].loop();
if (button[1].isPressed()) {
*/
/* nutshell jButton ARGH!
# include "jbutton.h"
jButton kButton[SIZE] = {2, 3, 4, 5}; // sorry mom.
kButton[ii].begin();
kButton[ii].loop();
if (kButton[ii].isPress()) {
*/
# include "jbutton.h"
# define SIZE 4
# define k100 100
byte theSequence[k100];
byte currentLength = 0;
byte randomIndex;
unsigned long seeds[] = {
1,
374989, 378023, 381167, 384247, 387307, 390419, 393311, 396443,
424549, 427781, 430847, 433729, 436739, 440023, 442973, 445943,
474433, 477523, 480541, 483709, 487057, 490097, 493243, 496283,
};
const byte nGames = sizeof seeds / sizeof *seeds;
byte gameNumber;
byte userPress = 0;
unsigned long now; // only one call to millis()
const int RATE = 277;
const byte lamps[] = {7, 8, 9, 10};
// no longer needed
//const byte buttons[] = {2, 3, 4, 5};
# define BEEP 6
bool noisy = true;
const int notes[SIZE] = {300, 500, 700, 900};
jButton kButton[SIZE] = {2, 3, 4, 5}; // sorry mom.
void setup()
{
for (byte ii = 0; ii < SIZE; ii++) {
kButton[ii].begin(); // ezButton cheats and has no begin method
pinMode(lamps[ii], OUTPUT);
// jButton are already always timed, but ezButton myEZButton[ii].setDebounceTime(20);
}
pinMode(BEEP, OUTPUT);
Serial.begin(115200);
Serial.println("\nSETUP, 'K?\n");
// this is deterministic with prejudice
}
void makeSequence()
{
static bool fixed = true;
static bool has;
if (!has || !fixed) {
randomSeed(seeds[gameNumber]);
for (byte ii = 0; ii < k100; ii++) // theSequence[ii] = (ii & 2) ? 0 : 3;
theSequence[ii] = random(0, SIZE);
gameNumber++; if (gameNumber > nGames) gameNumber = 0;
}
has = true;
}
void heartBeat(const uint8_t theLED, uint32_t onTime = 333, uint32_t offTime = 444)
{
static bool setUp = false;
static bool heart;
static unsigned long lastTime;
if (now - lastTime < (heart ? onTime : offTime)) return;
heart = !heart;
lastTime = now;
if (setUp == false) pinMode (theLED, OUTPUT), setUp = true;
digitalWrite(theLED, heart ? HIGH : LOW);
}
enum lampStates {IDLE, START, ON, OFF, NONE};
const char *lTags[] = {"Idle", "Start", "On", "Off", "NONE/WTF"};
bool lampFSM()
{
return lampFSM(-1);
}
// returns true if busy
bool lampFSM(int theLamp)
{
static unsigned long lastTime;
static int lastCode = -1;
static byte lampState;
static byte theCode;
static unsigned long dwell;
static byte printedState = NONE;
if (printedState != lampState) {
Serial.print(" lamp : ");
Serial.println(lTags[lampState]);
printedState = lampState;
}
if (theLamp >= 0) {
lampState = START;
dwell = 0;
theCode = theLamp;
}
// unsigned long now = millis();
if (now - lastTime < dwell) return lampState != IDLE;
lastTime = now;
switch (lampState) {
case IDLE :
break;
case START :
if (lastCode >= 0) {
digitalWrite(lamps[lastCode], LOW);
if (noisy) noTone(BEEP);
}
digitalWrite(lamps[theCode], HIGH);
if (noisy) tone(BEEP, notes[theCode]);
dwell = RATE;
lampState = ON;
lastCode = theCode;
break;
case ON :
digitalWrite(lamps[theCode], LOW);
if (noisy) noTone(BEEP);
dwell = RATE;
lampState = OFF;
break;
case OFF :
lastCode = 0;
dwell = 0;
lampState = IDLE;
break;
}
return lampState != IDLE;
}
int userInput()
{
int theButton = -1;
for (byte ii = 0; ii < SIZE; ii++) {
kButton[ii].loop();
if (kButton[ii].isPress())
theButton = ii;
}
return theButton; // -1 or button 0 .. SIZE - 1
}
void loop() {
now = millis();
heartBeat(A2); // after @paulpaulson
bool busyQ = lampFSM();
static bool lastLamping;
if (0) // you know what I mean.
if (lastLamping != busyQ) {
lastLamping = !lastLamping;
Serial.println(lastLamping ? " BUSY" : " IDLE");
}
simonFSM();
}
// FSM for game control
enum states {SHOW = 0, SHOWING, TEST, TESTING, WON, LOST, AGAIN, NOSTATE};
const char *tags[] ={"Show", "Showing", "Test", "Testing", "Won!", "Lost.", "Again", "hi Mom!"};
void simonFSM()
{
static unsigned long lastTime;
static unsigned long dwell;
static byte index;
static byte simonState = AGAIN;
static byte printedState = NOSTATE;
if (printedState != simonState) {
Serial.print("state is ");
Serial.println(tags[simonState]);
printedState = simonState;
}
if (now - lastTime < dwell) return;
lastTime = now;
dwell = 0;
int theInput;
switch (simonState) {
case SHOW :
index = 0;
Serial.println("first");
simonState = SHOWING;
// break; // not.
case SHOWING :
if (!lampFSM()) { // extra service just to see if it is busy yet
lampFSM(theSequence[index]);
Serial.print(now); Serial.print(" playing ");
Serial.println(theSequence[index]);
index++;
}
if (index >= currentLength) {
simonState = TEST;
}
break;
case TEST :
index = 0;
simonState = TESTING;
// break; // not.
case TESTING :
theInput = userInput();
if (theInput == -1) break;
lampFSM(theInput); // right?
if (theInput == theSequence[index])
index++;
else
simonState = LOST;
if (index == currentLength) simonState = WON;
break;
case WON :
Serial.print("you did it! ");
// series advance logic here.
// now there is no global WIN of anything,
// just sequences out to 100 steps boom!
currentLength++;
simonState = SHOW;
dwell = 1777;
break;
case LOST :
Serial.print("you lose. ");
simonState = AGAIN; // hmmm this is odd
case AGAIN :
currentLength = 1;
makeSequence();
simonState = SHOW;
dwell = 2000;
break;
default :
Serial.println(". ambitious .");
Serial.flush();
for (; ; );
}
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
led1:A
led1:C
led2:A
led2:C
led3:A
led3:C
led4:A
led4:C
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r
bz1:1
bz1:2
led5:A
led5:C
sw1:1
sw1:2
sw1:3