#include "Define.h"
//
#include "Switch.h"
#include "StepperDRV8825.h"
//
enum EMainAction
{
  maIdle            = 0,
  maMovePositive    = 1,
  maMoveNegative    = 2,
  maLeaveLimitHigh  = 3,
  maExitLimitHigh   = 4,
  maLeaveLimitLow   = 5,
  maExitLimitLow    = 6
};
//
EMainAction MainAction = maIdle;
long unsigned MillisPreset;
long int DistancePreset = 0L;
//
CStepperDRV8825 StepperDRV8825(PIN_MOTOR_STEP, 
                               PIN_MOTOR_DIRECTION, 
                               PIN_MOTOR_PRECISIONM0, 
                               PIN_MOTOR_PRECISIONM1, 
                               PIN_MOTOR_PRECISIONM2,
                               PIN_MOTOR_ENABLEN);
//
void OnSwitchLimitHighChanged(EStateSwitch state);
void OnSwitchReferenceChanged(EStateSwitch state);
void OnSwitchLimitLowChanged(EStateSwitch state);
//
CSwitch SwitchLimitHigh(PIN_SWITCH_LIMITHIGH, false,
                        OnSwitchLimitHighChanged);                        
CSwitch SwitchReference(PIN_SWITCH_REFERENCE, false,
                       OnSwitchReferenceChanged);
CSwitch SwitchLimitLow(PIN_SWITCH_LIMITLOW, false,
                       OnSwitchLimitLowChanged);
//
//---------------------------------------------------
//  Callback - SwitchLimitHigh
//---------------------------------------------------
void OnSwitchLimitHighChanged(EStateSwitch state)
{
  switch (state)
  {
    case sswOff: // LSHigh opened!
      SerialPC.println("\r\nSwitchLimitHigh: ..opened..");
      if (StepperDRV8825.IsOpened())
      {
        MainAction = maLeaveLimitHigh;
        SerialPC.println(">>>MainAction: LeaveLimitHigh");
        SerialPC.println(":::StepperMotor: MoveNegative-LeaveLimitHigh");
        StepperDRV8825.Move(sdNegative, srThirtyTwo, 
                            STEPPERIOD_LIMIT_US, STEPCOUNT_FULL);
      }
      break;
    case sswOn:
      SerialPC.println("\r\nSwitchLimitHigh: __closed__");
      if (maLeaveLimitHigh == MainAction)
      {
        SerialPC.println(":::StepperMotor: Halt");
        StepperDRV8825.Halt();
        SerialPC.println(">>>MainAction: ExitLimitHigh");
        MainAction = maExitLimitHigh;        
      }
      break;
    default: //
      SerialPC.println("nc");
      break;
  }
}
//
//---------------------------------------------------
//  Callback - SwitchReference
//---------------------------------------------------
void OnSwitchReferenceChanged(EStateSwitch state)
{
  switch (state)
  {
    case sswOff: // SR opened!
      SerialPC.println("\r\nSwitchReference: ..opened..");
      if (StepperDRV8825.IsOpened())
      {
        SerialPC.println("StepScale: *** Negative ***");
      }
      break;
    case sswOn:
      SerialPC.println("\r\nSwitchReference: __closed__");
      if (StepperDRV8825.IsOpened())
      {
        SerialPC.println("StepScale: --- Zero Position ---");
        StepperDRV8825.SetDistance(0L);
        SerialPC.println("StepScale: *** Positive ***");
      }
      break;
    default: //
      SerialPC.println("nc");
      break;
  }
}
//
//---------------------------------------------------
//  Callback - SwitchLimitLow
//---------------------------------------------------
void OnSwitchLimitLowChanged(EStateSwitch state)
{
  switch (state)
  {
    case sswOff: // LSLow opened!
      SerialPC.println("\r\nSwitchLimitLow: ..opened..");
      if (StepperDRV8825.IsOpened())
      {
        MainAction = maLeaveLimitLow;
        SerialPC.println(">>>MainAction: LeaveLimitLow");
        SerialPC.println(":::StepperMotor: MovePositive-LeaveLimitLow");
        StepperDRV8825.Move(sdPositive, srThirtyTwo, 
                            STEPPERIOD_LIMIT_US, STEPCOUNT_FULL);
      }
      break;
    case sswOn:
      SerialPC.println("\r\nSwitchLimitLow: __closed__");
      if (maLeaveLimitLow == MainAction)
      {
        SerialPC.println(":::StepperMotor: Halt");
        StepperDRV8825.Halt();
        SerialPC.println(">>>MainAction: ExitLimitLow");
        MainAction = maExitLimitLow;
      }
      break;
    default: //
      SerialPC.println("nc");
      break;
  }
}
//
//---------------------------------------------------
//  Setup
//---------------------------------------------------
void setup() 
{
  SerialPC.begin(115200);
  delay(333);
  SerialPC.println("");
  SerialPC.println("***************************");
  SerialPC.println("* Esp32StepperMotorSwitch *");
  SerialPC.println("* Version....: 01V05      *");
  SerialPC.println("* DateTime...: 2207221715 *");
  SerialPC.println("* Author.....: OMdevelop  *");
  SerialPC.println("***************************");
  //
  pinMode(PIN_LEDSYSTEM, OUTPUT);
  digitalWrite(PIN_LEDSYSTEM, HIGH);
  //
  SerialPC.println("Init Switches");
  SwitchLimitHigh.Open();
  SwitchReference.Open();
  SwitchLimitLow.Open();
  //
  SerialPC.println("Init StepperDRV8825");
  StepperDRV8825.Open();
  DistancePreset = StepperDRV8825.GetDistance();
  //
  delay(100);
  digitalWrite(PIN_LEDSYSTEM, LOW);
  SerialPC.println("Initialisation done");
  MainAction = maIdle;
  SerialPC.println("MotorState: --- Idle ---");
}
//
//---------------------------------------------------
//  MainLoop
//---------------------------------------------------
void loop()
{
  SwitchLimitHigh.Execute();
  SwitchReference.Execute();
  SwitchLimitLow.Execute();
  //
  StepperDRV8825.Execute();
  //
  if (DistancePreset != StepperDRV8825.GetDistance())
  {
    DistancePreset = StepperDRV8825.GetDistance();
    SerialPC.printf("\r...Distance: %+7ld", DistancePreset);
  }
  //
  if (ssIdle == StepperDRV8825.GetStateStep())
  {
    switch (MainAction)
    {
      case maIdle:
        if (MILLIS_IDLE <= (millis() - MillisPreset))
        {
          MainAction = maMovePositive;
          SerialPC.println(">>>MainAction: MovePositive...");
          SerialPC.println(":::StepperMotor: MovePositive");
          StepperDRV8825.Move(sdPositive, srHalf,//srThirtyTwo, 
                              STEPPERIOD_NORMAL_US, STEPCOUNT_FULL);
        }
        break;
      //----------------------------------------------------------
      case maMoveNegative:
        break;
      case maLeaveLimitLow:
        break;
      case maExitLimitLow:
        MainAction = maMovePositive;
        SerialPC.println(">>>MainAction: MovePositive");
        SerialPC.println(":::StepperMotor: MovePositive...");
        StepperDRV8825.Move(sdPositive, srHalf,//srThirtyTwo, 
                            STEPPERIOD_NORMAL_US, STEPCOUNT_FULL);
        break;
      //----------------------------------------------------------
      case maMovePositive:
        break;
      case maLeaveLimitHigh:
        break;
      case maExitLimitHigh:
        MainAction = maMoveNegative;
        SerialPC.println(">>>MainAction: MoveNegative");
        SerialPC.println(":::StepperMotor: MoveNegative...");
        StepperDRV8825.Move(sdNegative, srHalf,//srThirtyTwo, 
                            STEPPERIOD_NORMAL_US, STEPCOUNT_FULL);
        break;
    }
  }
}
//
