#include <Adafruit_NeoPixel.h>
// Pin assignment
#define PIN_WS2812B 18 //Wemos Mini D6
#define PIN_BTN1 23 //Wemos Mini D2
#define PIN_BTN2 22 //Wemos Mini D5
#define NUMERO_LED 8
Adafruit_NeoPixel strip(NUMERO_LED, PIN_WS2812B, NEO_GRB + NEO_KHZ800);
// SW Global variables
enum gameStateEnum {INIT_RECYCLE, START_RECYCLE, GAME_RECYCLE, SCORE_RECYCLE, FINISH_RECYCLE};
enum gameStateEnum gameState = INIT_RECYCLE;
enum gameStateEnum gameStateOld = START_RECYCLE;
bool first = false;
const uint32_t colorGlass = 0x0000FF;
const uint32_t colorPaper = 0xFFFF00;
const uint32_t colorOrganic = 0x00FF00;
uint16_t scorePlay = 0;
bool btn1IsPressed() {
static bool btnPressed = false;
static uint32_t btnTimer = 0;
bool returnStatus = false;
if ((millis() - btnTimer) > 50) {
if ((!btnPressed) && (digitalRead(PIN_BTN1) == LOW)) {
btnPressed = true;
returnStatus = true;
btnTimer = millis();
}
else if ((btnPressed) && (digitalRead(PIN_BTN1) == HIGH)) {
btnPressed = false;
btnTimer = millis();
}
}
return returnStatus;
}
bool btn2IsPressed() {
static bool btnPressed = false;
static uint32_t btnTimer = 0;
bool returnStatus = false;
if ((millis() - btnTimer) > 50) {
if ((!btnPressed) && (digitalRead(PIN_BTN2) == LOW)) {
btnPressed = true;
returnStatus = true;
btnTimer = millis();
}
else if ((btnPressed) && (digitalRead(PIN_BTN2) == HIGH)) {
btnPressed = false;
btnTimer = millis();
}
}
return returnStatus;
}
void animInitRecycle() {
static uint32_t timerInit = 0;
uint8_t randNum;
if ((millis() - timerInit) > 200) {
// Scroll led
for (int i = 0; i < (NUMERO_LED-1); i++) {
strip.setPixelColor(i, strip.getPixelColor(i+1));
}
randNum = random(10);
switch (randNum) {
case 0:
strip.setPixelColor(NUMERO_LED-1, colorGlass);
break;
case 1:
strip.setPixelColor(NUMERO_LED-1, colorPaper);
break;
case 2:
strip.setPixelColor(NUMERO_LED-1, colorOrganic);
break;
default:
strip.setPixelColor(NUMERO_LED-1, 0);
break;
}
strip.show();
timerInit = millis();
}
}
bool animStartRecycle() {
static uint32_t timerStart = 0;
static uint8_t step = 5;
if ((millis() - timerStart) > 1000) {
switch (step) {
case 5:
for (int i=1; i<6; i++) {
strip.setPixelColor(i, 0xFF0000);
}
step--;
break;
case 1 ... 4:
strip.setPixelColor(step+1, 0);
step--;
break;
case 0:
step = 5;
return true;
break;
default:
step = 5;
break;
}
strip.show();
timerStart = millis();
}
return false;
}
bool animGameRecycle() {
static uint32_t timerGame = 0;
const uint16_t TIME_GAME = 60*1000;
static uint32_t timerAnimGame = 0;
uint8_t randNum;
if (timerGame == 0) timerGame = millis();
if ((millis() - timerGame) > TIME_GAME) {
timerGame = 0;
return true;
}
if ((millis() - timerAnimGame) > 500) {
// Check of led 0
if (strip.getPixelColor(0) == colorOrganic) {
scorePlay = scorePlay + 2;
}
else if (strip.getPixelColor(1) != 0) {
scorePlay = max(scorePlay-2, 0);
}
// Scroll led
for (int i = 0; i < (NUMERO_LED-1); i++) {
strip.setPixelColor(i, strip.getPixelColor(i+1));
}
randNum = random(10);
switch (randNum) {
case 0:
strip.setPixelColor(NUMERO_LED-1, colorGlass);
break;
case 1:
strip.setPixelColor(NUMERO_LED-1, colorPaper);
break;
case 2:
strip.setPixelColor(NUMERO_LED-1, colorOrganic);
break;
default:
strip.setPixelColor(NUMERO_LED-1, 0);
break;
}
strip.show();
timerAnimGame = millis();
}
return false;
}
bool animScoreRecycle() {
static uint32_t timerScoreAnim = 0;
static uint8_t step = 0;
int8_t diffScore = 0;
if ((millis() - timerScoreAnim) > 500) {
diffScore = scorePlay - step*10;
if (diffScore > 10) {
strip.setPixelColor(step, 0x00FF00);
}
else if (diffScore > 0) {
strip.setPixelColor(step, 0, map(scorePlay, 0, 10, 0, 255), 0);
}
else {
strip.setPixelColor(step, 0);
}
strip.show();
step++;
if (step >= NUMERO_LED) {
step = 0;
return true;
}
timerScoreAnim = millis();
}
return false;
}
void setup() {
Serial.begin(115200);
strip.begin();
strip.show();
pinMode(PIN_BTN1, INPUT_PULLUP);
pinMode(PIN_BTN2, INPUT_PULLUP);
randomSeed(analogRead(0));
}
void loop() {
// 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();
Serial.println("INIT_RECYCLE");
}
animInitRecycle();
if (btn1IsPressed() || btn2IsPressed()) {
gameState = START_RECYCLE;
}
break;
case START_RECYCLE:
if (first) {
first = false;
strip.clear();
strip.show();
Serial.println("START_RECYCLE");
}
if (animStartRecycle()) {
gameState = GAME_RECYCLE;
}
break;
case GAME_RECYCLE:
if (first) {
first = false;
strip.clear();
strip.show();
Serial.println("GAME_RECYCLE");
}
if (btn1IsPressed()) {
if (strip.getPixelColor(1) == colorGlass) {
scorePlay = scorePlay + 2;
}
else if (strip.getPixelColor(1) == 0) {
scorePlay = max(scorePlay-1, 0);
}
else {
scorePlay = max(scorePlay-2, 0);
}
strip.setPixelColor(1, 0);
strip.show();
}
if (btn2IsPressed()) {
if (strip.getPixelColor(1) == colorPaper) {
scorePlay = scorePlay + 2;
}
else if (strip.getPixelColor(1) == 0) {
scorePlay = max(scorePlay-1, 0);
}
else {
scorePlay = max(scorePlay-2, 0);
}
strip.setPixelColor(1, 0);
strip.show();
}
if (animGameRecycle()) {
gameState = SCORE_RECYCLE;
}
break;
case SCORE_RECYCLE:
if (first) {
first = false;
strip.clear();
strip.show();
Serial.println("SCORE_RECYCLE");
}
if (animScoreRecycle()) {
gameState = FINISH_RECYCLE;
}
break;
case FINISH_RECYCLE:
if (first) {
first = false;
Serial.println("FINISH_RECYCLE");
}
if (btn1IsPressed() || btn2IsPressed()) {
gameState = INIT_RECYCLE;
scorePlay = 0;
}
break;
default:
gameState = INIT_RECYCLE;
break;
}
}