// ================================================================
//  Educational Game Platform - with a top level Menu selection
//  using a Micro Controller, 8 LED 4 color bar and 4 Button module
//

//  include Library of Hardware Support functions
#include "Mini_STEM_Platform.h"

// the setup routine runs once on power up or when you press reset:
//=================================================================
void setup() {
  int aVal, val;

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  Serial.println("Arduino Educational Mini Game Platform - Lesson 10");

  // ------------ setup the Mini Game/STEM platform (8LEDs, 4Btns, and Audio)
  gPlatform_setup();

  beep(50,50); beep(50,50); beep(150);  // announce "it is alive!"
}

// the loop routine runs over and over again forever:
//=================================================================
void loop() { // Top Menu level, for selecting a activity
  while(1) {
    clearDisp();
    while(Btn) {buZZ(1); scanBtns();}  // wait for no button

    while(!Btn) {
      for (int i=1; i<=nleds; i++) {  // flash odd & even LEDs in opposition while waiting 
        dim[i] = ((msCnt/333+i)%2);   // every 1/3 sec switch which LEDs are dim / lit
      }
      refreshDisp();
      delay(1);
      scanBtns();
    }
    Serial.print("Function: ");
    Serial.println(btnNum);
    
    clearDisp();
/***    
    if (btn1) HW_Support_Demo();   // Demonstrates LED display and audio support functionality
    else if (btn2) Speed_Scan_ver4();   // hit it on the right spot to speed things up to a winning max
    else if (btn3) React_Now_ver2();    // Test your Reaction time 
    else if (btn4) btnReporting();    // exercises the buttons and Leds, and reports via Serial 
***/
    if (btn1) Magic_8_ball_0();
    if (btn2) Magic_8_ball_1();
    if (btn3) Magic_8_ball();
  }
}


// Various selection of mini APPs / Games
//=================================================================

// ------------------
void btnReporting() {
  // =================================  Button - LED exercise & Reporting
  int icnt=0; // iteration count, lsb~=1msec
  clearDisp();
  while (Btn) scanBtns();  // wait for button release
  while (1) {
    refreshWait(1);
    icnt++;
    scanBtns();
    // ------------------- button reporting
    if (BtnChanged) {
      Serial.println(" ");
      if (btn1) Serial.print("[Btn1] "); else Serial.print("       ");
      if (btn2) Serial.print("[Btn2] "); else Serial.print("       ");
      if (btn3) Serial.print("[Btn3] "); else Serial.print("       ");
      if (btn4) Serial.print("[Btn4] "); else Serial.print("       ");
      Serial.print(btnState);

      // ------------------ LED reflection of button state
      lit[1] = lit[2] = btn1; // set Red LEDs
      lit[3] = lit[4] = btn2; // set Yel LEDs
      lit[5] = lit[6] = btn3; // set Blu LEDs
      lit[7] = lit[8] = btn4; // set Grn LEDs
      brightOne=0;

      beep(15); // make a key press click, for up&down
      icnt=0;
    } else if (icnt>10000) {  // if ignorned for 10 seconds
      icnt=0;
      brightOne=1;
      beep(15,200);
      clearDisp();
    }
    if (ESC && brightOne==0 && btn4 ) Serial.print(" [ESC] ");    
    brightOne = (ESC)? 8 : 0;
    if (ESC && btn1) break;    // only leave Btn Reporting if btn1 is also held.
  }
}

void HW_Support_Demo() {  // Demonstrates use of set of Hardware support functions
  while(true) {
    scanBtns();

    if (BtnPressed) {
      clearDisp();
      for (int i=1; i<=nleds; i++) {  // set all LEDs to a given level
        if (btn1Pressed) dim[i]=true;
        if (btn2Pressed) lit[i]=true;
        if (btn3Pressed) brt[i]=true;        
      }
    }
    //if (btn4Pressed) {clearDisp();}   // not needed
    
    // produce sound while btn1-3 is held
    while (Btn) {
      if (btn1 || btn3) boop(2);
      if (btn2 || btn3) beep(2);
      if (btn4) break;  // don't get stuck here
      scanBtns();
    }
    
    refreshDisp();
    delay(1);
//
    if (ESC) break;
  } 
}

void Speed_Scan_ver4() {  // hit it on the right spot to speed things up to a winning max
  int onMSecs, stRate=150;
  int hits=0, goal=9;

  litLED=1;
  onMSecs=stRate;
  while(true) { 
    refreshWait(onMSecs);     // flash the LED (blip) for a bit

    // allow use of left or right most button
    scanBtns();

    if (BtnPressed && (litLED==5 || litLED==6)) {
        beep(100);    
        hits++;
        if (hits==goal) {
          beep(100,50); beep(100,50); beep(250);  // you did it
          hits=0; // start over
          refreshWait(1000);
          clearDisp();
        }
    }

    // added block for support of a missed penalty
    if (BtnPressed && !(litLED==5 || litLED==6)) {
      refreshWait(300);
      hits--;     // slow down update rate
      clearDisp();
    }
    
    onMSecs = stRate - (15*hits); // more hits he get faster the blip scans
    for (int i=1; i<=hits; i++) dim[i]=true;    // display as, dim, the hit progress
    litLED = (litLED % nleds) + 1;    // advance to next LED

    if (ESC) break;
  }
}

//----------------  React_Now - Swat Quickly as LEDs light up
void React_Now_ver2() { // attemp to hit the button when the first LED lights up
                   // 1st LED is lit for 100 msecs, additional LEDs lite every 20ms
                   // challenge: if one pushes & holds before the first LED get wrong win; how to fix ?
  int min_Period = 100;
  int LEDptr;
  
  while(true) {
    // insure that the button is not already pressed
    while (Btn && !ESC) scanBtns();
    if (ESC) return;
    
    // insure all LEDs are off
    clearDisp();

    delay(random(2000,5000));       // wait for 2 - 5 seconds
    lit[1]=1;
    refreshDisp();
    beep(10); // takes 2x msecs
    delay(min_Period-20-20);    // account for the 20ms beep time and 20ms in for loop

    for (LEDptr=1; LEDptr<=8; LEDptr++) {
      lit[LEDptr]=true;
      refreshWait(20);
      scanBtns();
      if (BtnPressed) { // they pressed the button
        brightOne=LEDptr;
        refreshWait(1000);
        break;
      }
    }
    if (LEDptr>8) beep(100);
    if (ESC) break;
  }
}

// ==========================================  Magic-8-Ball
// hold down btn1 ... ponder question, let go.  Red: NO,  YEL: Maybe,  Grn: YES  Blue: Try again
void Magic_8_ball() {
  int cnt;
  byte color;
  static byte ccycle[] = {0,1,0,3,0,2,0,4};
  
  while (1) {
    clearDisp();
    while(Btn) scanBtns(); // wait for previous button press to be released
    while(!Btn) {
      scanBtns();
      litLED=(msCnt/1000)%2;    // toggles first LED once per second
      refreshWait(1);
    }

    while(Btn) {  // flash potential answers while button is being pressed
      scanBtns();
      if (ESC || btn4) return;
      if (cnt != (msCnt/400)%8) {  // flash LEDs (1-3-2-4)
        clearDisp();
        cnt = (msCnt/400)%8;
        // determine next color set to light or not to light
/***
        if ((cnt%2)==0) color=0;
        else if (cnt>3) color=cnt-3;
        else color=cnt;
***/
        color = ccycle[cnt];
        showColor(color);
      }
      refreshWait(1); 
    }

    delay(300 + random(900));  // make them wait alittle
    
//    litLED = 2*random(1,5)+1; // select and show one of 4 possible
    showColor(random(1,5));   // select and show one of 4 possible 
    refreshWait(3000);
  }
}

// ==== early versions of  Magic-8-Ball
// One of Four responses:   Red: NO   YEL: Maybe   Grn: YES    Blue: Try again
void Magic_8_ball_0() {
  while (1) {
    clearDisp();
    while(Btn) scanBtns();   // wait for previous button press to be released
    while(!Btn) {
      scanBtns();
      litLED=(msCnt/1000)%2;    // toggles first LED once per second
      refreshWait(1);
    }
    if (btn4) return;

//    litLED = 2*random(1,5)+1;   // select and show one of 4 possible outcomes
    while(Btn) scanBtns();         // wait while button is being pressed
    delay(300 + random(900));  // make them wait a little more as if divining the answer
    showColor(random(1,5));     // select and show one of 4 colors as the possible answer

    refreshWait(3000);
  }
}


void Magic_8_ball_1() {
// One of Four responses:   Red: NO   YEL: Maybe   Grn: YES    Blue: Try again
int cnt;  byte color; 
  while (1) {
    clearDisp();
    while(Btn) scanBtns();   // wait for previous button press to be released
    while(!Btn) {
      scanBtns();
      litLED=(msCnt/1000)%2;    // toggles first LED once per second
      refreshWait(1);
    }

//    litLED = 2*random(1,5)+1;   // select and show one of 4 possible outcomes
//    while(Btn) scanBtns();         // wait while button is being pressed

    while(Btn) {         // flash potential answers while button is being pressed
      scanBtns();
      if (ESC || btn4) return;
      if (cnt != (msCnt/400)%8) {  // flash LEDs (1-3-2-4)
        clearDisp();
        cnt = (msCnt/400) %8;
        // determine next color set to light or not to light        
        if ((cnt%2)==0) color=0;
//        else if (cnt>3) color=cnt-3;
//        else if (cnt==5 || cnt==7)  color=cnt-3;
        else if (cnt==5)  color=2; else  if  (cnt==7)  color=4;

        else color=cnt;
        showColor(color);
      }
      refreshWait(1); 
    }
    
    delay(300 + random(900));  // make them wait a little more as if divining the answer
    showColor(random(1,5));     // select and show one of 4 colors as the possible answer

    refreshWait(3000);
  }
}


// ================== Local Support Functions =====================
void showColor(byte color) {  // 1-4: light LED color set 1-4,  5: All 
  clearDisp();
  if (color==0) return;
  if (color==1 || color==5)  lit[1] = lit[2] = true; // set 1 LEDs
  if (color==2 || color==5)  lit[3] = lit[4] = true; // set 2 LEDs
  if (color==3 || color==5)  lit[5] = lit[6] = true; // set 3 LEDs
  if (color==4 || color==5)  lit[7] = lit[8] = true; // set 4 LEDs
}
