#define SW_VERS "v1.0"
// TARGET
// LOLIN(WEMOS) D1 R2 & mini
// DEBUG Const
#define DEBUG true //set to true for debug output, false for no debug output
#define DEBUG_SERIAL \
if (DEBUG) Serial
// Add HW target (eventually boards installed)
// Add External Library
// Adafruit Neopixel
#include <Adafruit_NeoPixel.h>
// Add Internal Library
#include "MyBtn.h"
// Pin assignment
#define PIN_WS2812B 18 //Wemos Mini D7
#define PIN_BTN1 23 //Wemos Mini D4
#define PIN_BTN2 22 //Wemos Mini D3
// HW Constants
#define NUM_LEDS 8 // number of LEDs (pixels) on WS2812B LED strip
#define BRIGHTNESS 255 // 255 max
// SW Constants
#define NUM_TRASH 3
#define COL_GLASS 0x00007F
#define COL_PAPER 0x7F7F00
#define COL_ORGANIC 0x007F00
//uint32_t const trashColors[NUM_TRASH_COLORS] = {COL_GLASS, COL_PAPER, COL_ORGANIC};
#define COL_GLASS_FULL 0x0000FF
#define COL_PAPER_FULL 0xFFFF00
#define COL_ORGANIC_FULL 0x00FF00
//uint32_t const trashColorsFull[NUM_TRASH_COLORS] = {COL_GLASS_FULL, COL_PAPER_FULL, COL_ORGANIC_FULL};
#define COL_BOMB 0x7F0000
#define COL_BOMB_FULL 0xFF0000
// HW Global variables
Adafruit_NeoPixel strip(NUM_LEDS, PIN_WS2812B, NEO_GRB + NEO_KHZ800);
MyBtn btn1(PIN_BTN1);
MyBtn btn2(PIN_BTN2);
// SW Global variables
enum gameStateEnum {INIT_RECYCLE, SINGLE_MULTI_CHOICE, START_RECYCLE_SINGLE, START_RECYCLE_MULTI, GAME_RECYCLE_SINGLE, GAME_RECYCLE_MULTI, WINNER_RECYCLE_SINGLE, WINNER_RECYCLE_MULTI, FINISH_RECYCLE_SINGLE, FINISH_RECYCLE_MULTI};
enum gameStateEnum gameState = INIT_RECYCLE;
enum gameStateEnum gameStateOld = START_RECYCLE_SINGLE;
bool first = false;
enum trashEnum {EMPTY, GLASS, PAPER, ORGANIC, BOMB, GLASS_BLINK, PAPER_BLINK, ORGANIC_BLINK, BOMB_BLINK, BOMB_DEFUSE_SX, BOMB_DEFUSE_DX};
enum trashEnum trashConveyor[NUM_LEDS] = {EMPTY};
uint16_t scorePlay = 0;
const uint8_t NUM_LED_COMBO = 3;
uint8_t numComboOK = 0;
bool blinkOn = false;
bool waitPress = false;
// Add usefull methods
#include "LedRecycle.h"
void setup() {
Serial.begin(9600);
DEBUG_SERIAL.println("SETUP");
strip.begin();
pinMode(PIN_BTN1, INPUT_PULLUP);
pinMode(PIN_BTN2, INPUT_PULLUP);
randomSeed(analogRead(0));
}
void loop() {
btn1.readBtn();
btn2.readBtn();
// First evaluation for first time in new state
if (gameStateOld != gameState) {
first = true;
gameStateOld = gameState;
}
switch (gameState) {
case INIT_RECYCLE:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("INIT_RECYCLE");
}
animInitRecycle();
if (btn1.wasPressed() || btn2.wasPressed()) {
gameState = SINGLE_MULTI_CHOICE;
}
break;
case SINGLE_MULTI_CHOICE:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("SINGLE_MULTI_CHOICE");
}
animSingleMultiChoice();
if (btn1.wasPressed()) {
gameState = START_RECYCLE_MULTI;
}
if (btn2.wasPressed()) {
gameState = START_RECYCLE_SINGLE;
}
break;
case START_RECYCLE_SINGLE:
if (first) {
first = false;
strip.clear();
strip.show();
scorePlay = 0;
numComboOK = 0;
for (int i=0; i<NUM_LEDS; i++) {
trashConveyor[i] = EMPTY;
}
DEBUG_SERIAL.println("START_RECYCLE_SINGLE");
}
if (animStartRecycleSingle()) {
gameState = GAME_RECYCLE_SINGLE;
}
break;
case START_RECYCLE_MULTI:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("START_RECYCLE_MULTI");
}
break;
case GAME_RECYCLE_SINGLE:
if (first) {
first = false;
strip.clear();
strip.show();
btn1.wasPressed();
btn2.wasPressed();
DEBUG_SERIAL.println("GAME_RECYCLE_SINGLE");
}
if (animGameRecycleSingle()) {
gameState = WINNER_RECYCLE_SINGLE;
}
if (btn1.wasPressed()) {
switch (trashConveyor[1]) {
case BOMB:
case BOMB_BLINK:
trashConveyor[1] = BOMB_DEFUSE_SX;
break;
case BOMB_DEFUSE_DX:
trashConveyor[1] = EMPTY;
break;
case GLASS_BLINK:
numComboOK++;
case GLASS:
trashConveyor[1] = EMPTY;
scorePlay = scorePlay + 1;
break;
case PAPER_BLINK:
case ORGANIC_BLINK:
numComboOK = 0;
for (int i=2; i<NUM_LEDS; i++) {
switch (trashConveyor[i]) {
case GLASS_BLINK:
trashConveyor[i] = GLASS;
break;
case PAPER_BLINK:
trashConveyor[i] = PAPER;
break;
case ORGANIC_BLINK:
trashConveyor[i] = ORGANIC;
break;
default:
// Do nothing
break;
}
}
break;
case PAPER:
case ORGANIC:
trashConveyor[1] = EMPTY;
if (scorePlay >= 2)
scorePlay = scorePlay - 2;
break;
case EMPTY:
if (scorePlay >= 1)
scorePlay = scorePlay - 1;
break;
case BOMB_DEFUSE_SX:
default:
// Do nothing
break;
}
updateLeds();
if (numComboOK >= NUM_LED_COMBO) {
scorePlay = scorePlay + 5;
numComboOK = 0;
}
}
if (btn2.wasPressed()) {
switch (trashConveyor[1]) {
case BOMB:
case BOMB_BLINK:
trashConveyor[1] = BOMB_DEFUSE_DX;
break;
case BOMB_DEFUSE_SX:
trashConveyor[1] = EMPTY;
break;
case PAPER_BLINK:
numComboOK++;
case PAPER:
trashConveyor[1] = EMPTY;
scorePlay = scorePlay + 1;
break;
case GLASS_BLINK:
case ORGANIC_BLINK:
numComboOK = 0;
for (int i=2; i<NUM_LEDS; i++) {
switch (trashConveyor[i]) {
case GLASS_BLINK:
trashConveyor[i] = GLASS;
break;
case PAPER_BLINK:
trashConveyor[i] = PAPER;
break;
case ORGANIC_BLINK:
trashConveyor[i] = ORGANIC;
break;
default:
// Do nothing
break;
}
}
break;
case GLASS:
case ORGANIC:
trashConveyor[1] = EMPTY;
if (scorePlay >= 2)
scorePlay = scorePlay - 2;
break;
case EMPTY:
if (scorePlay >= 1)
scorePlay = scorePlay - 1;
break;
case BOMB_DEFUSE_DX:
default:
// Do nothing
break;
}
updateLeds();
if (numComboOK >= NUM_LED_COMBO) {
scorePlay = scorePlay + 5;
numComboOK = 0;
}
}
break;
case GAME_RECYCLE_MULTI:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("GAME_RECYCLE_MULTI");
}
break;
case WINNER_RECYCLE_SINGLE:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("WINNER_RECYCLE_SINGLE");
}
if (animWinnerRecycleSingle()) {
gameState = FINISH_RECYCLE_SINGLE;
}
break;
case WINNER_RECYCLE_MULTI:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("WINNER_RECYCLE_MULTI");
}
break;
case FINISH_RECYCLE_SINGLE:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("FINISH_RECYCLE_SINGLE");
}
DEBUG_SERIAL.println(scorePlay);
if (!waitPress) {
if (animFinishRecycleSingle()) {
waitPress = true;
}
btn1.wasPressed();
btn2.wasPressed();
}
else {
if (btn1.wasPressed() || btn2.wasPressed()) {
waitPress = false;
gameState = INIT_RECYCLE;
}
}
break;
case FINISH_RECYCLE_MULTI:
if (first) {
first = false;
strip.clear();
strip.show();
DEBUG_SERIAL.println("FINISH_RECYCLE_MULTI");
}
break;
default:
break;
}
}