// Download this in a .zip file.


/* Test the freetronics 16x2 LCD shield 
http://www.freetronics.com/pages/16x2-lcd-shield-quickstart-guide#.UBKMm7T9OK9

MTG Life Counter
by eturnerx@gmail.com 201208

*/
/*--------------------------------------------------------------------------------------
  Includes
--------------------------------------------------------------------------------------*/
#include    // include LCD library
/*--------------------------------------------------------------------------------------
  Defines
--------------------------------------------------------------------------------------*/
// Pins in use
#define BUTTON_ADC_PIN           A0  // A0 is the button ADC input
#define LCD_BACKLIGHT_PIN         3  // D3 controls LCD backlight
// ADC readings expected for the 5 buttons on the ADC input
#define RIGHT_10BIT_ADC           0  // right
#define UP_10BIT_ADC            145  // up
#define DOWN_10BIT_ADC          329  // down
#define LEFT_10BIT_ADC          505  // left
#define SELECT_10BIT_ADC        741  // right
#define BUTTONHYSTERESIS         10  // hysteresis for valid button sensing window
//return values for ReadButtons()
#define BUTTON_NONE               0  // 
#define BUTTON_RIGHT              1  // 
#define BUTTON_UP                 2  // 
#define BUTTON_DOWN               3  // 
#define BUTTON_LEFT               4  // 
#define BUTTON_SELECT             5  // 
/*--------------------------------------------------------------------------------------
  Variables
--------------------------------------------------------------------------------------*/
byte buttonJustPressed  = false;         //this will be true after a ReadButtons() call if triggered
byte buttonJustReleased = false;         //this will be true after a ReadButtons() call if triggered
byte buttonWas          = BUTTON_NONE;   //used by ReadButtons() for detection of button events

int life1 = 20;
int life2 = 20;
int who = 0;
int resetcounter = 0;
/*--------------------------------------------------------------------------------------
  Init the LCD library with the LCD pins to be used
--------------------------------------------------------------------------------------*/
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );   //Pins for the freetronics 16x2 LCD shield. LCD: ( RS, E, LCD-D4, LCD-D5, LCD-D6, LCD-D7 )
/*--------------------------------------------------------------------------------------
  setup()
  Called by the Arduino framework once, before the main loop begins
--------------------------------------------------------------------------------------*/
void setup()
{
   //button adc input
   pinMode( BUTTON_ADC_PIN, INPUT );         //ensure A0 is an input
   digitalWrite( BUTTON_ADC_PIN, LOW );      //ensure pullup is off on A0
   //lcd backlight control
   digitalWrite( LCD_BACKLIGHT_PIN, HIGH );  //backlight control pin D3 is high (on)
   pinMode( LCD_BACKLIGHT_PIN, OUTPUT );     //D3 is an output
   //set up the LCD number of columns and rows: 
   lcd.begin( 16, 2 );
   //Print some initial text to the LCD.
   lcd.setCursor( 0, 0 );   //top left
   //          1234567890123456
   lcd.print( "MTG Life Counter" );
   updateLifeCounts();
}
/*--------------------------------------------------------------------------------------
  loop()
  Arduino main loop
--------------------------------------------------------------------------------------*/
void loop()
{
   byte button;
   
   button = ReadButtons();
   //show text label for the button pressed
   switch(button) {
     case BUTTON_NONE: 
       resetcounter = 0; 
       break;

     case BUTTON_LEFT: if(buttonJustPressed) {
         who = 0;
       } break;

     case BUTTON_RIGHT: if(buttonJustPressed) {
         who = 1;
       } break;

     case BUTTON_UP: if(buttonJustPressed) {
         if(who == 0) life1++; else life2++;
       } break;

     case BUTTON_DOWN: if(buttonJustPressed) {
         if(who == 0) life1--; else life2--;
       } break;

     case BUTTON_SELECT:
       //SELECT is a special case, it pulses the LCD backlight off and on for demo
       digitalWrite( LCD_BACKLIGHT_PIN, LOW );
       delay( 150 );
       digitalWrite( LCD_BACKLIGHT_PIN, HIGH );   //leave the backlight on at exit
       delay( 150 );
        
       resetcounter++;
       if(resetcounter > 10) {
         resetcounter = 0;
         life1 = 20;
         life2 = 20;
         updateLifeCounts();
       }
       break;
       
      default: break;
   }

   //Output the update life totals.
   if(buttonJustPressed || buttonJustReleased ) updateLifeCounts();

   //clear the buttonJustPressed or buttonJustReleased flags, they've already done their job now.
   if(buttonJustPressed)  buttonJustPressed  = false;
   if(buttonJustReleased) buttonJustReleased = false;
   delay(20);
}
/*--------------------------------------------------------------------------------------
  ReadButtons()
  Detect the button pressed and return the value
  Uses global values buttonWas, buttonJustPressed, buttonJustReleased.
--------------------------------------------------------------------------------------*/
byte ReadButtons() {
   unsigned int buttonVoltage;
   byte button = BUTTON_NONE;   // return no button pressed if the below checks don't write to btn
   
   //read the button ADC pin voltage
   buttonVoltage = analogRead( BUTTON_ADC_PIN );
   //sense if the voltage falls within valid voltage windows
   if( buttonVoltage < ( RIGHT_10BIT_ADC + BUTTONHYSTERESIS ) )
   {
      button = BUTTON_RIGHT;
   }
   else if(   buttonVoltage >= ( UP_10BIT_ADC - BUTTONHYSTERESIS )
           && buttonVoltage <= ( UP_10BIT_ADC + BUTTONHYSTERESIS ) )
   {
      button = BUTTON_UP;
   }
   else if(   buttonVoltage >= ( DOWN_10BIT_ADC - BUTTONHYSTERESIS )
           && buttonVoltage <= ( DOWN_10BIT_ADC + BUTTONHYSTERESIS ) )
   {
      button = BUTTON_DOWN;
   }
   else if(   buttonVoltage >= ( LEFT_10BIT_ADC - BUTTONHYSTERESIS )
           && buttonVoltage <= ( LEFT_10BIT_ADC + BUTTONHYSTERESIS ) )
   {
      button = BUTTON_LEFT;
   }
   else if(   buttonVoltage >= ( SELECT_10BIT_ADC - BUTTONHYSTERESIS )
           && buttonVoltage <= ( SELECT_10BIT_ADC + BUTTONHYSTERESIS ) )
   {
      button = BUTTON_SELECT;
   }
   //handle button flags for just pressed and just released events
   if( ( buttonWas == BUTTON_NONE ) && ( button != BUTTON_NONE ) )
   {
      //the button was just pressed, set buttonJustPressed, this can optionally be used to trigger a once-off action for a button press event
      //it's the duty of the receiver to clear these flags if it wants to detect a new button change event
      buttonJustPressed  = true;
      buttonJustReleased = false;
   }
   if( ( buttonWas != BUTTON_NONE ) && ( button == BUTTON_NONE ) )
   {
      buttonJustPressed  = false;
      buttonJustReleased = true;
   }
   
   //save the latest button value, for change event detection next time round
   buttonWas = button;
   
   return( button );
}

void updateLifeCounts() {
  lcd.setCursor( 0, 1 );
  if(life1 < 10 && life1 > 0) lcd.print(" ");
  if(life1 <= 0) lcd.print("XX"); else if(life1 > 99) lcd.print("99"); else lcd.print(life1);
  if(who == 0) lcd.print("*"); else lcd.print(" ");

   //        1234567890123456
  lcd.print("         ");

  lcd.setCursor( 13, 1 );
  if(who == 1) lcd.print("*"); else lcd.print(" ");
  if(life2 < 10 && life2 > 0) lcd.print(" ");
  if(life2 <= 0) lcd.print("XX"); else if(life2 > 99) lcd.print("99"); else lcd.print(life2);
}