// V8.1 Adapted for Wokwi - (On Simulide Works, on Wokwi not yet - September 2023
// ***********************************************
// Original Project by Greg06 visit: https://www.instructables.com/Automated-Chessboard/
// This is adapted for Linear Hall Sensor, instead Reed Switch or Unipolar Hall Sensor
//            AUTOMATIC CHESSBOARD
//  To use in SimulIde
// ***********************************************
// Changes from Original
// Pins changed
// Use Arduino Mega (Memory Problems with Nano)
// Use Analog Hall Sensor (Solve White eating Problem)
// Test your own Linear Hall for define the parameters.
// added a Matrix Led 8x8 MAX7219 (For better check the Sensors)
// Added a H-Bridge L298 Added (For PMW the Electromagnet if needed)
// Start Interface Changed
//
// Changes in V8 ¡¡ (Not Finished - Work HvsH - Not Work HvsC after no valid move, no show on LCD not valid move and motors moves white and black like eating) !!
// Case Game Over implemented. Falta!!
// Fixed LCD show No Valid Move on HvsC Game. Falta !! Solo lo muestra en HvsH
// Fixed Motors have to move only on HvsC Black moves. Falta!! mueven luego de Jugada Invalida!! (Repiten ultimo novimiento Negras) 
// White Pieces one Magnet Force N32 (Diam: 6mmx3) - Black Other Magnet Force N52 same size (Diam: 6mmx3)
// B&W with the same Polarization. 
// So diferent Force magnets made diferent outputs from Hall Sensor
// Keep the same polarization for B&W avoid electromagnet problems
// Change polarization of the Electromagnet not work proprertly, so is better to keep same polarization for all pieces
// Sensors only works when the Player Turn's end. (Previous versions works all time)
// Record Sensors Positions only if Move is Valid (Previous versions change the position when Invalid move was made, and game can't continue)
//
//
// Detected Limitations
// Promotion: Only to Queen, other pieces not implemented yet 
// En passant eating, not implemented yet (Code need to recognize three sensor´s magnet changes)
//
// ******************************  INCLUDING FILES
#include "global_V3.h"  // SPK Adapted for Linear MUX and new devices
#include "Micro_Max.h"
#include <Wire.h>
#include "LedControl.h" // Added for Matrix Led based on MAX7219
 #include <LiquidCrystal_I2C.h>                   // put this line comment if you are on Simulide
 LiquidCrystal_I2C lcd(0x27,16,2);                // put this line comment if you are on Simulide // In Skolodi Case LCD is on 0x27 and not in 0x20
// #include <LiquidCrystal_AIP31068_I2C.h>        // erase this line comment if you are on Simulide
// LiquidCrystal_AIP31068_I2C lcd( 0x3E, 16, 2 ); // erase this line comment if you are on Simulide // 3E Changed for Simulide simulation
LedControl lc=LedControl(51,52,53,1); // For A Mega DIN=51 , CLK=52, CS=53, 1 Matrix Led

// ****************************************  SETUP
void setup() {
  Serial.begin(9600);

  //  Electromagnet H-Bridge V7
  	pinMode(IN1, OUTPUT);
  	pinMode(IN2, OUTPUT);	
	pinMode (MAGNET, OUTPUT);

// Matrix Led V7
	lc.shutdown(0,false);		// Turn on matriz Led
 	lc.setIntensity(0,4);		// Set Intensity of Led
 	lc.clearDisplay(0);			// Turn off leds

  //  Motor
  pinMode (MOTOR_WHITE_STEP, OUTPUT);
  pinMode (MOTOR_WHITE_DIR, OUTPUT);
  pinMode (MOTOR_BLACK_STEP, OUTPUT);
  pinMode (MOTOR_BLACK_DIR, OUTPUT);

  //  Multiplexer  
  // Option for reduce MUX from 4 to 2 analized, but lattence appears and a lot of Diodes needed, so decided Mantain 4 MUX
  for (byte i = 0; i < 4; i++) {
    pinMode (MUX_ADDR [i], OUTPUT);
    digitalWrite(MUX_ADDR [i], LOW);
    pinMode (MUX_SELECT [i], OUTPUT);
    digitalWrite(MUX_SELECT [i], HIGH);
  }
  pinMode (MUX_OUTPUT, INPUT_PULLUP);

  //  Set the sensors status V7
Serial.println("  Set Sensors Status V7");
Serial.println("  +-----------------+");
  for (byte i = 0; i < 2; i++) {
    Serial.print(' ');
    Serial.print(8 - i);
    Serial.print("| ");
    for (byte j = 0; j < 8; j++) {
      reed_sensor_status[7-i][j] = -1;  
      reed_sensor_status_memory[7-i][j] = -1;
      Serial.print(reed_sensor_status[7-i][j]);
      Serial.print(' ');  
    }
    Serial.println('|');
  }
  for (byte i = 2; i < 6; i++) {
    Serial.print(' ');
    Serial.print(8 - i);
    Serial.print("| ");
    for (byte j = 0; j < 8; j++) {
      reed_sensor_status[7-i][j] = 0;  
      reed_sensor_status_memory[7-i][j] = 0;
      Serial.print(reed_sensor_status[7-i][j]);
      Serial.print(' ');    
    }
     Serial.println('|');
  }
for (byte i = 6; i < 8; i++) {
  Serial.print(' ');
    Serial.print(8 - i);
    Serial.print("| ");
    for (byte j = 0; j < 8; j++) {
      reed_sensor_status[7-i][j] = 1;  
      reed_sensor_status_memory[7-i][j] = 1;
      Serial.print(reed_sensor_status[7-i][j]);
      Serial.print(' ');    
    }
     Serial.println('|');
  }
  Serial.println("  +-----------------+");
  Serial.println("   a b c d e f g h");
  //  MicroMax
  lastH[0] = 0;

  //  LCD
  lcd.init();

  //  Countdown
  timer = millis();

  //  Arcade button - Limit Switch
  pinMode (BUTTON_WHITE_SWITCH_MOTOR_WHITE, INPUT_PULLUP); 
  pinMode (BUTTON_BLACK_SWITCH_MOTOR_BLACK, INPUT_PULLUP); 
  lcd_display();

 }

// *****************************************  LOOP
void loop() 
{
  switch (sequence) 
  {
    case start:
      lcd_display();
      if (button(WHITE) == true) 
        {                                       // White=Down Button , Black Enter Button.
          MenuItemSelected=MenuItemSelected+2;
          if (MenuItemSelected>3) 
            {
            MenuItemSelected=0;
            }
  	   // game_mode = HvsH;
       lcd_display();
        }
      else if (button(BLACK) == true) 
        {                                       // Button Black is Enter
        switch (MenuItemSelected) 
          {
          case 0:
           game_mode=HvsH;
           initial_record_sensors(); // SPK V7
		        sequence= player_white;
            break;

           case 2:
           game_mode = HvsC;
           sequence = calibration;
		        initial_record_sensors(); // SPK V7
            break;
          }
	       }
    break;                            // break Case Start

    case calibration:
      lcd_display();
      calibrate();
      sequence = player_white;
      break;

    case player_white:
      if (millis() - timer > 995)   // When 1 second passed
      {                             
        countdown();                // Rest 1 second. If New Turn, save time and change turn
        lcd_display();              // Show the time
      }
      //detect_human_movement();    // V7 SPK Move down for check sensors only when the button is press
      if (button(WHITE) == true) 
      {                             // White player end turn
        detect_human_movement();    // V7 SPK move here - Check the sensors
		    player_displacement();      // Save and convert on coordinates the previous move and the last move
        if (game_mode == HvsH) 
        {
          AI_HvsH();                // Chekc is movement is valid
          if (no_valid_move == false) 
          {
		        record_sensors();       // SPK V7
		        new_turn_countdown = true;  // V8.1 Set the New turn, works when countdown is called
            sequence = player_black;
            break;                  // V8.1 go out of the sequence to start case Player Black
		      }
          else if (no_valid_move == true) // V8.1 change else for esle if
		      {				 		              // V8
		      serialBoard();            // V8.1 Show Serial Board
          lcd_display();            // Show No Valid Move, change state of No Valid Move and return
		      break;  	                // V8.1 Have to break to start Player White case again
		      }						              // V8
        }
        else if (game_mode == HvsC) 
        {
          AI_HvsC();                // Chekc is movement is valid
          if (no_valid_move == false) 
          {  	                      // V8
		      record_sensors(); 		    // V8
		      new_turn_countdown = true;  // V8.1 Set the New turn, works when countdown is called
          sequence = player_black;	// V8
		      break;                    // V8.1 go out of the sequence to start case Player Black
          }
		      else if (no_valid_move == true) // V8.1 change else for esle if
		      {						             // V8.1
      		serialBoard();            // V8.1 Show Serial Board
          lcd_display();       		 // V8
      		sequence = player_white; // V8.1
      		break;                   // V8.1 go out of the sequence to start case Player White
          }						             // V8.1
        }
      }                            // V8.1 close Button White
      break;                       // break case Player White

      case player_black:
        if (millis() - timer > 995)  // V8.1 clock for Computer Showed. 
        {                             
        countdown();                // Rest 1 second. If New Turn, save time and change turn
        lcd_display();              // Show the time
        }
        //  Game mode HvsH
        if (game_mode == HvsH) 
        {                          
          if (millis() - timer > 995) // When 1 second passed
          {                             
          countdown();                // Rest 1 second. If New Turn, save time and change turn
          lcd_display();              // Show the time
          }
          if (button(BLACK) == true) 
          {                           // Black human player end turn
            detect_human_movement();  // V7 moved here - detect sensors
		        player_displacement();    // Save and convert on coordinates the previous move and the last move
            AI_HvsH();                // Chekc is movement is valid
            if (no_valid_move == false) 
            {
      			record_sensors();         // SPK V7
      			new_turn_countdown = true;// V8.1 moved. Set the New turn, works when countdown is called
            sequence = player_white;
            break;                   // V8.1 go out of the sequence to start case Player White
      			}
            else if (no_valid_move == true) // V8.1 change else for esle if
            {
              lcd_display();
              sequence = player_black;//V8.1
              break;                  // V8.1 go out of the sequence to start again case Player black
            }
          }
        }                           // Close HvsH mode
        //  Game mode HvsC
        else if (game_mode == HvsC) 
        {
          black_player_movement();  //  Move the black chess piece
          record_sensors();         // SPK V7
		      new_turn_countdown = true;// V8.1 moved. Set the New turn, works when countdown is called
          sequence = player_white;
          break;                   // V8.1 go out of the sequence to start case Player White
        }
        break;                      // break player_black case

      // } // V8.1 moved up // Close "if (button(WHITE)" on Case Player_white If } moved up, (was here on Original Greg06 code) 

      case game_over:             // V8.1 added the Game Over case
      lcd_display();
      for (;;);                   // V8.1 infinite For, to collapse Arduino and have to restart when Game Over (Same as on Micromax)
      break; 
  } // Close Swich sequence
} // close Loop

// ***************************************  SWITCH
boolean button(byte type) {

  if (type == WHITE && digitalRead(BUTTON_WHITE_SWITCH_MOTOR_WHITE) != HIGH) {
    delay(250);
    return true;
  }
  if (type == BLACK && digitalRead(BUTTON_BLACK_SWITCH_MOTOR_BLACK) != HIGH) {
    delay(250);
    return true;
  }
  return false;
}

// ************************************  CALIBRATE
void calibrate() {

  //  Slow displacements up to touch the limit switches
  while (digitalRead(BUTTON_WHITE_SWITCH_MOTOR_WHITE) == HIGH) motor(B_T, SPEED_SLOW, calibrate_speed);
  while (digitalRead(BUTTON_BLACK_SWITCH_MOTOR_BLACK) == HIGH) motor(L_R, SPEED_SLOW, calibrate_speed);
  delay(500);

  //  Rapid displacements up to the Black start position (e7)
  motor(R_L, SPEED_FAST, TROLLEY_START_POSITION_X);
  motor(T_B, SPEED_FAST, TROLLEY_START_POSITION_Y);
  delay(500);
}

// ****************************************  MOTOR
void motor(byte direction, int speed, float distance) 
{

  float step_number = 0;

  //  Calcul the distance
  if (distance == calibrate_speed) step_number = 4;
  else if (direction == LR_BT || direction == RL_TB || direction == LR_TB || direction == RL_BT) step_number = distance * SQUARE_SIZE * 1.44; //  Add an extra length for the diagonal
  else step_number = distance * SQUARE_SIZE;

  //  Direction of the motor rotation
  if (direction == R_L || direction == T_B || direction == RL_TB) digitalWrite(MOTOR_WHITE_DIR, HIGH);
  else digitalWrite(MOTOR_WHITE_DIR, LOW);
  if (direction == B_T || direction == R_L || direction == RL_BT) digitalWrite(MOTOR_BLACK_DIR, HIGH);
  else digitalWrite(MOTOR_BLACK_DIR, LOW);

  //  Active the motors
  for (int x = 0; x < step_number; x++) 
  {
    if (direction == LR_TB || direction == RL_BT) digitalWrite(MOTOR_WHITE_STEP, LOW);
    else digitalWrite(MOTOR_WHITE_STEP, HIGH);
    if (direction == LR_BT || direction == RL_TB) digitalWrite(MOTOR_BLACK_STEP, LOW);
    else digitalWrite(MOTOR_BLACK_STEP, HIGH);
    delayMicroseconds(speed);
    digitalWrite(MOTOR_WHITE_STEP, LOW);   // SPK In Simulide after Calibrate this matain HIGH, but actualy the motor doesn't move
    digitalWrite(MOTOR_BLACK_STEP, LOW);
    delayMicroseconds(speed);
  }
}

// *******************************  ELECTROMAGNET H-Bridge
void electromagnet(boolean state) 
{
  if (state == true)  
	{
    	analogWrite(MAGNET, 200);		// V8 PWM Electromagnet
	delay(600);
	}
	else  
		{
    delay(600);
    digitalWrite(MAGNET, LOW);
		}
}
// ***********************************  COUNTDONW
void countdown() 
{

  //  Set the time of the current player
  if (new_turn_countdown == true ) 
    {
      new_turn_countdown = false;
      if (sequence == player_white) 
      {
        second = second_white;
        minute = minute_white;
        if (minute_white == 0 && second_white == 0)
        {                                           // V8.1 - When Player time is 0 -> Game Over sequence
        black_win = true;
        sequence = game_over;
        return;
        }
      }
      else if (sequence == player_black) 
        {
        second = second_black;
        minute = minute_black;
        if (minute_black == 0 && second_black == 0)
          {                                         // V8.1 - When Player time is 0 -> Game Over sequence
          white_win = true;
          sequence = game_over;
          return;
          }
        }
    }

  //  Countdown
  timer = millis();
  second = second - 1;
  if (second < 1) 
    {
      second = 60;
      minute = minute - 1;
    }

  //  Record the white player time
  if (sequence == player_white) 
    {
      second_white = second;
      minute_white = minute;
    }
  //  Record the black player time
  else if (sequence == player_black) 
    {
      second_black = second;
      minute_black = minute;
    }
}                                 // Close countdown()

// ***********************  BLACK PLAYER MOVEMENT
void black_player_movement() 
{

  //  Convert the AI characters in variables
  int departure_coord_X = lastM[0] - 'a' + 1;
  int departure_coord_Y = lastM[1] - '0';
  int arrival_coord_X = lastM[2] - 'a' + 1;
  int arrival_coord_Y = lastM[3] - '0';
  byte displacement_X = 0;
  byte displacement_Y = 0;

  //  Trolley displacement to the starting position
  int convert_table [] = {0, 7, 6, 5, 4, 3, 2, 1, 0};
  byte white_capturing = 1;
  if (abs(reed_sensor_status_memory[convert_table[arrival_coord_Y]][arrival_coord_X - 1]) == 1) white_capturing = 0;
// square with wite = 1
// square with black = -1
// square with no piecw = 0
  for (byte i = abs(white_capturing); i < 2; i++) 
  {
    if (i == 0) 
    {
      displacement_X = abs(arrival_coord_X - trolley_coordinate_X);
      displacement_Y = abs(arrival_coord_Y - trolley_coordinate_Y);
	    digitalWrite(IN1, LOW);	// SPK V7 Check the best Electromagnet polarization for set this
  	  digitalWrite(IN2, HIGH);	// SPK
	    Serial.println("Piece White moving");// for debug
    }
    else if (i == 1) 
    {
      displacement_X = abs(departure_coord_X - trolley_coordinate_X);
      displacement_Y = abs(departure_coord_Y - trolley_coordinate_Y);
	    digitalWrite(IN1, LOW);	// SPK V7 Same Polarization 
  	  digitalWrite(IN2, HIGH);	// SPK V7
	   Serial.println("Piece Black moving");// SPK for debug
    }
    if (departure_coord_X > trolley_coordinate_X) motor(T_B, SPEED_FAST, displacement_X);
    else if (departure_coord_X < trolley_coordinate_X) motor(B_T, SPEED_FAST, displacement_X);
    if (departure_coord_Y > trolley_coordinate_Y) motor(L_R, SPEED_FAST, displacement_Y);
    else if (departure_coord_Y < trolley_coordinate_Y) motor(R_L, SPEED_FAST, displacement_Y);
    if (i == 0) 
    {
      electromagnet(true);
      motor(R_L, SPEED_SLOW, 0.5);
      motor(B_T, SPEED_SLOW, arrival_coord_X - 0.5);
      electromagnet(false);
      motor(L_R, SPEED_FAST, 0.5);
      motor(T_B, SPEED_FAST, arrival_coord_X - 0.5);
      trolley_coordinate_X = arrival_coord_X;
      trolley_coordinate_Y = arrival_coord_Y;
    }
  }
  trolley_coordinate_X = arrival_coord_X;
  trolley_coordinate_Y = arrival_coord_Y;

  //  Move the Black chess piece to the arrival position
  displacement_X = abs(arrival_coord_X - departure_coord_X);
  displacement_Y = abs(arrival_coord_Y - departure_coord_Y);

  electromagnet(true);
  //  Bishop displacement
  if (displacement_X == 1 && displacement_Y == 2 || displacement_X == 2 && displacement_Y == 1) 
  {
    if (displacement_Y == 2) 
    {
      if (departure_coord_X < arrival_coord_X) 
      {
        motor(T_B, SPEED_SLOW, displacement_X * 0.5);
        if (departure_coord_Y < arrival_coord_Y) motor(L_R, SPEED_SLOW, displacement_Y);
        else motor(R_L, SPEED_SLOW, displacement_Y);
        motor(T_B, SPEED_SLOW, displacement_X * 0.5);
      }
      else if (departure_coord_X > arrival_coord_X) 
      {
        motor(B_T, SPEED_SLOW, displacement_X * 0.5);
        if (departure_coord_Y < arrival_coord_Y) motor(L_R, SPEED_SLOW, displacement_Y);
        else motor(R_L, SPEED_SLOW, displacement_Y);
        motor(B_T, SPEED_SLOW, displacement_X * 0.5);
      }
    }
    else if (displacement_X == 2) 
    {
      if (departure_coord_Y < arrival_coord_Y) 
      {
        motor(L_R, SPEED_SLOW, displacement_Y * 0.5);
        if (departure_coord_X < arrival_coord_X) motor(T_B, SPEED_SLOW, displacement_X);
        else motor(B_T, SPEED_SLOW, displacement_X);
        motor(L_R, SPEED_SLOW, displacement_Y * 0.5);
      }
      else if (departure_coord_Y > arrival_coord_Y) 
      {
        motor(R_L, SPEED_SLOW, displacement_Y * 0.5);
        if (departure_coord_X < arrival_coord_X) motor(T_B, SPEED_SLOW, displacement_X);
        else motor(B_T, SPEED_SLOW, displacement_X);
        motor(R_L, SPEED_SLOW, displacement_Y * 0.5);
      }
    }
  }
  //  Diagonal displacement
    else if (displacement_X == displacement_Y) 
    {
      if (departure_coord_X > arrival_coord_X && departure_coord_Y > arrival_coord_Y) motor(RL_BT, SPEED_SLOW, displacement_X);
      else if (departure_coord_X > arrival_coord_X && departure_coord_Y < arrival_coord_Y) motor(LR_BT, SPEED_SLOW, displacement_X);
      else if (departure_coord_X < arrival_coord_X && departure_coord_Y > arrival_coord_Y) motor(RL_TB, SPEED_SLOW, displacement_X);
      else if (departure_coord_X < arrival_coord_X && departure_coord_Y < arrival_coord_Y) motor(LR_TB, SPEED_SLOW, displacement_X);
    }
  //  Kingside castling
  else if (departure_coord_X == 5 && departure_coord_Y == 8 && arrival_coord_X == 7 && arrival_coord_Y == 8) 
  {                               //  Kingside castling
    motor(R_L, SPEED_SLOW, 0.5);
    motor(T_B, SPEED_SLOW, 2);
    electromagnet(false);
    motor(T_B, SPEED_FAST, 1);
    motor(L_R, SPEED_FAST, 0.5);
    electromagnet(true);
    motor(B_T, SPEED_SLOW, 2);
    electromagnet(false);
    motor(T_B, SPEED_FAST, 1);
    motor(R_L, SPEED_FAST, 0.5);
    electromagnet(true);
    motor(L_R, SPEED_SLOW, 0.5);
  }
  else if (departure_coord_X == 5 && departure_coord_Y == 8 && arrival_coord_X == 3 && arrival_coord_Y == 8) 
  {                             //  Queenside castling
    motor(R_L, SPEED_SLOW, 0.5);
    motor(B_T, SPEED_SLOW, 2);
    electromagnet(false);
    motor(B_T, SPEED_FAST, 2);
    motor(L_R, SPEED_FAST, 0.5);
    electromagnet(true);
    motor(T_B, SPEED_SLOW, 3);
    electromagnet(false);
    motor(B_T, SPEED_FAST, 1);
    motor(R_L, SPEED_FAST, 0.5);
    electromagnet(true);
    motor(L_R, SPEED_SLOW, 0.5);
  }
  //  Horizontal displacement
  else if (displacement_Y == 0) 
    {
      if (departure_coord_X > arrival_coord_X) motor(B_T, SPEED_SLOW, displacement_X);
      else if (departure_coord_X < arrival_coord_X) motor(T_B, SPEED_SLOW, displacement_X);
    }
  //  Vertical displacement
  else if (displacement_X == 0) 
    {
      if (departure_coord_Y > arrival_coord_Y) motor(R_L, SPEED_SLOW, displacement_Y);
      else if (departure_coord_Y < arrival_coord_Y) motor(L_R, SPEED_SLOW, displacement_Y);
    }
  electromagnet(false);

  //  Upadte the reed sensors states with the Balck move
  reed_sensor_status_memory[convert_table[departure_coord_Y]][departure_coord_X - 1] = 1;
  reed_sensor_status_memory[convert_table[arrival_coord_Y]][arrival_coord_X - 1] = 0;
  reed_sensor_status[convert_table[departure_coord_Y]][departure_coord_X - 1] = 1;
  reed_sensor_status[convert_table[arrival_coord_Y]][arrival_coord_X - 1] = 0;

}             // close black_player_movement


// **********************************  LCD DISPLAY
void lcd_display() 
{

  lcd.backlight();  // put this line comment if you are on Simulide

  if (no_valid_move == true) 
  {
    lcd.setCursor(0, 0);
    lcd.print("  NO VALID MOVE  ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    delay(2000);
    no_valid_move = false;            // V8.1 need to be adapted // HvsH with this line -> work. // HvsC with this line -> not work
    return;                           // V8.1 not sure if return go to the same line previous lcd_display() was called, or other place
  }

  switch (sequence) 
  {
    case start_up:
      lcd.setCursor(0, 0);
      lcd.print("   AUTOMATIC    ");
      lcd.setCursor(0, 1);
      lcd.print("   CHESSBOARD   ");
      sequence = start;
      delay(4000);
      break;                        // V8.1
    case start:
      lcd.setCursor(0, 0);
      //lcd.print(" PRESS A - HvsH ");
      lcd.print(MenuItems[MenuItemSelected]); // V7 Change
	    lcd.setCursor(0, 1);
      // lcd.print(" PRESS B - HvsC ");
      lcd.print(MenuItems[MenuItemSelected+1]); // V7 Change
	    break;                       // V8.1
    case calibration:
      lcd.setCursor(0, 0);
      lcd.print("  CALIBRATION   ");
      lcd.setCursor(0, 1);
      lcd.print("                ");
      break;
    case player_white:
      lcd.setCursor(0, 0);
      lcd.print("     WHITE      ");
      lcd.setCursor(0, 1);
      lcd.print("     " + String(minute) + " : " + String(second) + "     ");
      break;
    case player_black:
      lcd.setCursor(0, 0);
      lcd.print("     BLACK      ");
      lcd.setCursor(0, 1);
      lcd.print("     " + String(minute) + " : " + String(second) + "     ");
      break;
    case game_over:             // V8.1 added the Game Over case for timelapse. For other Issues is set on Micro Max
      if (white_win == true)              // V8.1 Not work. Counter go to 256
        {
          lcd.setCursor(0, 0);
          lcd.print("     WHITE      ");
          lcd.setCursor(0, 1);
          lcd.print("      WINS      ");
        }
        else if (black_win == true)         // V8.1 Not work. Counter go to 256
        {
            lcd.setCursor(0, 0);
            lcd.print("     BLACK      ");
            lcd.setCursor(0, 1);
            lcd.print("      WINS      ");
        }
    break;                              // V8.1                       
 }                                     // close sequence
}                                      // close lcd display 

// ************************  DETECT HUMAN MOVEMENT  V7 change to run this part only after press the button
void detect_human_movement() 
{

  //  Record the reed switches status
 
  byte column = 6;
  byte row = 0;

  for (byte i = 0; i < 4; i++) 
  {
    digitalWrite(MUX_SELECT[i], LOW);
    for (byte j = 0; j < 16; j++) 
    {
      for (byte k = 0; k < 4; k++) 
	     {
        digitalWrite(MUX_ADDR [k], MUX_CHANNEL [j][k]);
	      delay(5); 						// SPK Added for Recomendation on Questions See shuttle123
        int hallMeasure = analogRead(MUX_OUTPUT); // SPK TEST your own linear hall to set this parameters
		    if (hallMeasure > 540 && hallMeasure <= 740) 
        { // 540 & 740 for Simulide Set the Value manualy after test
          reed_sensor_record[column][row] = 1;
		      //hall_value[column][row]=hallMeasure; // SPK Added for take the Hall measure
       	}
        else if (hallMeasure > 840 && hallMeasure <= 1100) 
        { 
          // 840 & 1100 for Simulide, Set the Value manualy after test
          reed_sensor_record[column][row] = -1;
  		    //hall_value[column][row]=hallMeasure; // SPK Added for take the Hall measure
       	}
        else 
        { // Any other Value means no piece. Set the Value manualy after test
          reed_sensor_record[column][row] = 0;
		      //hall_value[column][row]=hallMeasure; // SPK Added for take the Hall measure
      	}
	     }
	
     // reed_sensor_record[column][row] = digitalRead(MUX_OUTPUT);
      row++;
      if (j == 7) 
      {
        column++;
        row = 0;
      }
    }
    for (byte l = 0; l < 4; l++) 
    {
      digitalWrite(MUX_SELECT[l], HIGH);
    }
    if (i == 0) column = 4;
    if (i == 1) column = 2;
    if (i == 2) column = 0;
    row = 0;
  }
  Serial.println("  Detect Human Movement");
  Serial.println("  +-----------------+");
  for (byte i = 0; i < 8; i++) 
  {
    Serial.print(' ');
    Serial.print(8 - i);
    Serial.print("| ");
    for (byte j = 0; j < 8; j++) 
    {
      Serial.print(reed_sensor_record[7-i][j]);
      Serial.print(' ');
    reed_sensor_status_memory[7 - i][j] = reed_sensor_record[i][j];
    }
    Serial.println('|');
  }
  Serial.println("  +-----------------+");
  Serial.println("   a b c d e f g h");

  //  Compare the old and new status of the reed switches

  for (byte i = 0; i < 8; i++) 
  {
    for (byte j = 0; j < 8; j++) 
    {
      if (reed_sensor_status[i][j] != reed_sensor_status_memory[i][j]) 
      {
        if (reed_sensor_status_memory[i][j] == 0) // SPK adapted for Linear Hall
	       {
          reed_colone[0] = i; 
          reed_line[0] = j;  
         }
        if (reed_sensor_status_memory[i][j] == 1) // 1=White SPK adapted for Linear Hall
	       {
          reed_colone[1] = i; 
          reed_line[1] = j; 
         }
		    if (reed_sensor_status_memory[i][j] == -1) // -1=Black SPK adapted for Linear Hall
	       {
          reed_colone[1] = i; 
          reed_line[1] = j; 
          }
      }
    }
  }
 //  Set the new status of the reed sensors
 // record_sensors(); // V7 moved to record_sensors()
 
}                 // close detect_human_movement


// **************************  RECORD SENSORS V7
void record_sensors() 
{
 lc.clearDisplay(0);			// blanquea matriz Led
   for (byte i = 0; i < 8; i++) 
   {
    	for (byte j = 0; j < 8; j++) 
      {
      reed_sensor_status[i][j] = reed_sensor_status_memory[i][j];
	    if(reed_sensor_status[i][j] ==1 || reed_sensor_status[i][j] ==-1) 
        {
	       lc.setLed(0,i,j,true); // Turn on Led where is a piece on
	      }
      }
    }
}
// **************************  INITIAL RECORD SENSORS V7
void initial_record_sensors()
{
lc.clearDisplay(0);			// blanquea matriz Led
detect_human_movement();
for (byte i = 0; i < 8; i++) 
  {
    for (byte j = 0; j < 8; j++) 
    {
      if(reed_sensor_status[i][j] ==1 || reed_sensor_status[i][j] ==-1) 
      {
    	 lc.setLed(0,i,j,true); // Turn on Led where is a piece on
    	}
  	}
  }
}
// **************************  PLAYER DISPLACEMENT
void player_displacement() 
{

  //  Convert the reed sensors switches coordinates in characters
  char table1[] = {'8', '7', '6', '5', '4', '3', '2', '1'};
  char table2[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};

  mov[0] = table2[reed_line[0]];  // For move e2 -> e4
 // Serial.print("mov[0]");  // added SPK for debug
 // Serial.println(mov[0]);    // added SPK for debug - Show letter e
  mov[1] = table1[reed_colone[0]];
// Serial.print("mov[1]");    // added SPK for debug
// Serial.println(mov[1]);    // added SPK for debug - Show number 2 (e2, previous move)
  mov[2] = table2[reed_line[1]];
// Serial.print("mov[2]");    // added SPK for debug
// Serial.println(mov[2]);    // added SPK for debug - Show letter e
  mov[3] = table1[reed_colone[1]];
// Serial.print("mov[3]");    // added SPK for debug
// Serial.println(mov[3]);    // added SPK for debug  - Show number 4 (e4, last move)
}
A4988
A4988
L298N Breakout
Loading
cd74hc4067
Loading
cd74hc4067
Loading
cd74hc4067
Loading
cd74hc4067