text: /*
   * Title: MovePositionRelative
   *
   * Objective:
   *    This example demonstrates control of a ClearPath motor in Step and
   *    Direction mode.
   *
   * Description:
   *    This example enables a ClearPath then commands a series of repeating
   *    moves to the motor.
   *
   * Requirements:
   * 1. A ClearPath motor must be connected to Connector M-0.
   * 2. The connected ClearPath motor must be configured through the MSP software
   *    for Step and Direction mode (In MSP select Mode>>Step and Direction).
   * 3. The ClearPath motor must be set to use the HLFB mode "ASG-Position"
   *    through the MSP software (select Advanced>>High Level Feedback [Mode]...
   *    then choose "All Systems Go (ASG) - Position" from the dropdown and hit
   *    the OK button).
   * 4. Set the Input Format in MSP for "Step + Direction".
   *
   * ** Note: Homing is optional, and not required in this operational mode or in
   *    this example. This example makes its first move in the positive direction,
   *    assuming any homing move occurs in the negative direction.
   *
   * ** Note: Set the Input Resolution in MSP the same as your motor's Positioning
   *    Resolution spec if you'd like the pulses sent by ClearCore to command a
   *    move of the same number of Encoder Counts, a 1:1 ratio.
   *
   * Links:
   * ** ClearCore Documentation: https://teknic-inc.github.io/ClearCore-library/
   * ** ClearCore Manual: https://www.teknic.com/files/downloads/clearcore_user_manual.pdf
   * ** ClearPath Manual (DC Power): https://www.teknic.com/files/downloads/clearpath_user_manual.pdf
   * ** ClearPath Manual (AC Power): https://www.teknic.com/files/downloads/ac_clearpath-mc-sd_manual.pdf
   *
   * 
   * Copyright (c) 2020 Teknic Inc. This work is free to use, copy and distribute under the terms of
   * the standard MIT permissive software license which can be found at https://opensource.org/licenses/MIT
   */
  
  #include "ClearCore.h"
  
  // Specifies which motor to move.
  // Options are: ConnectorM0, ConnectorM1, ConnectorM2, or ConnectorM3.
  #define motor ConnectorM0
  
  // Select the baud rate to match the target serial device
  #define baudRate 9600
  
  // Specify which serial to use: ConnectorUsb, ConnectorCOM0, or ConnectorCOM1.
  #define SerialPort ConnectorUsb
  
  // Define the velocity and acceleration limits to be used for each move
  int32_t velocityLimit = 10000; // pulses per sec
  int32_t accelerationLimit = 100000; // pulses per sec^2
  
  // Declares our user-defined helper function, which is used to command moves to
  // the motor. The definition/implementation of this function is at the  bottom
  // of the example
  void MoveDistance(int32_t distance);
  
  int main() {
      // Sets the input clocking rate. This normal rate is ideal for ClearPath
      // step and direction applications.
      MotorMgr.MotorInputClocking(MotorManager::CLOCK_RATE_NORMAL);
  
      // Sets all motor connectors into step and direction mode.
      MotorMgr.MotorModeSet(MotorManager::MOTOR_ALL,
                            Connector::CPM_MODE_STEP_AND_DIR);
  
      // Sets the maximum velocity for each move
      motor.VelMax(velocityLimit);
  
      // Set the maximum acceleration for each move
      motor.AccelMax(accelerationLimit);
  
      // Sets up serial communication and waits up to 5 seconds for a port to open.
      // Serial communication is not required for this example to run.
      SerialPort.Mode(Connector::USB_CDC);
      SerialPort.Speed(baudRate);
      uint32_t timeout = 5000;
      uint32_t startTime = Milliseconds();
      SerialPort.PortOpen();
      while (!SerialPort && Milliseconds() - startTime < timeout) {
          continue;
      }
  
      // Enables the motor; homing will begin automatically if enabled
      motor.EnableRequest(true);
      SerialPort.SendLine("Motor Enabled");
  
      // Waits for HLFB to assert (waits for homing to complete if applicable)
      SerialPort.SendLine("Waiting for HLFB...");
      while (motor.HlfbState() != MotorDriver::HLFB_ASSERTED) {
          continue;
      }
      SerialPort.SendLine("Motor Ready");
  
      while (true) {
          // Move 6400 counts (positive direction), then wait 2000ms
          MoveDistance(6400);
          Delay_ms(2000);
          // Move 19200 counts farther positive, then wait 2000ms
          MoveDistance(19200);
          Delay_ms(2000);
          // Move back 12800 counts (negative direction), then wait 2000ms
          MoveDistance(-12800);
          Delay_ms(2000);
          // Move back 6400 counts (negative direction), then wait 2000ms
          MoveDistance(-6400);
          Delay_ms(2000);
          // Move back to the start (negative 6400 pulses), then wait 2000ms
          MoveDistance(-6400);
          Delay_ms(2000);
      }
  }
  
  /*------------------------------------------------------------------------------
   * MoveDistance
   *
   *    Command "distance" number of step pulses away from the current position
   *    Prints the move status to the USB serial port
   *    Returns when HLFB asserts (indicating the motor has reached the commanded
   *    position)
   *
   * Parameters:
   *    int distance  - The distance, in step pulses, to move
   *
   * Returns: None
   */
  void MoveDistance(int32_t distance) {
      SerialPort.Send("Moving distance: ");
      SerialPort.SendLine(distance);
  
      // Command the move of incremental distance
      motor.Move(distance);
  
      // Waits for HLFB to assert (signaling the move has successfully completed)
      SerialPort.SendLine("Moving.. Waiting for HLFB");
      while (!motor.StepsComplete() || motor.HlfbState() != MotorDriver::HLFB_ASSERTED) {
          continue;
      }
  
      SerialPort.SendLine("Move Done");
  }
  //------------------------------------------------------------------------------
  