text: /*----------------------------------------------------------------------------*/
  /* Copyright (c) 2016-2018 FIRST. All Rights Reserved.                        */
  /* Open Source Software - may be modified and shared by FRC teams. The code   */
  /* must be accompanied by the FIRST BSD license file in the root directory of */
  /* the project.                                                               */
  /*----------------------------------------------------------------------------*/
  
  #pragma once
  
  #include <stdint.h>
  
  #include "hal/AnalogTrigger.h"
  #include "hal/Types.h"
  
  /**
   * @defgroup hal_encoder Encoder Functions
   * @ingroup hal_capi
   * @{
   */
  
  // clang-format off
  /**
   * The type of index pulse for the encoder.
   */
  HAL_ENUM(HAL_EncoderIndexingType) {
    HAL_kResetWhileHigh,
    HAL_kResetWhileLow,
    HAL_kResetOnFallingEdge,
    HAL_kResetOnRisingEdge
  };
  
  /**
   * The encoding scaling of the encoder.
   */
  HAL_ENUM(HAL_EncoderEncodingType) {
    HAL_Encoder_k1X,
    HAL_Encoder_k2X,
    HAL_Encoder_k4X
  };
  // clang-format on
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * Initializes an encoder.
   *
   * @param digitalSourceHandleA the A source (either a HAL_DigitalHandle or a
   * HAL_AnalogTriggerHandle)
   * @param analogTriggerTypeA   the analog trigger type of the A source if it is
   * an analog trigger
   * @param digitalSourceHandleB the B source (either a HAL_DigitalHandle or a
   * HAL_AnalogTriggerHandle)
   * @param analogTriggerTypeB   the analog trigger type of the B source if it is
   * an analog trigger
   * @param reverseDirection     true to reverse the counting direction from
   * standard, otherwise false
   * @param encodingType         the encoding type
     @return                     the created encoder handle
   */
  HAL_EncoderHandle HAL_InitializeEncoder(
      HAL_Handle digitalSourceHandleA, HAL_AnalogTriggerType analogTriggerTypeA,
      HAL_Handle digitalSourceHandleB, HAL_AnalogTriggerType analogTriggerTypeB,
      HAL_Bool reverseDirection, HAL_EncoderEncodingType encodingType,
      int32_t* status);
  
  /**
   * Frees an encoder.
   *
   * @param encoderHandle the encoder handle
   */
  void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /**
   * Gets the current counts of the encoder after encoding type scaling.
   *
   * This is scaled by the value passed duing initialization to encodingType.
   *
   * @param encoderHandle the encoder handle
   * @return the current scaled count
   */
  int32_t HAL_GetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /**
   * Gets the raw counts of the encoder.
   *
   * This is not scaled by any values.
   *
   * @param encoderHandle the encoder handle
   * @return              the raw encoder count
   */
  int32_t HAL_GetEncoderRaw(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /**
   * Gets the encoder scale value.
   *
   * This is set by the value passed during initialization to encodingType.
   *
   * @param encoderHandle the encoder handle
   * @return              the encoder scale value
   */
  int32_t HAL_GetEncoderEncodingScale(HAL_EncoderHandle encoderHandle,
                                      int32_t* status);
  
  /**
   * Reads the current encoder value.
   *
   * Read the value at this instant. It may still be running, so it reflects the
   * current value. Next time it is read, it might have a different value.
   *
   * @param encoderHandle the encoder handle
   * @return              the current encoder value
   */
  void HAL_ResetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /*
   * Gets the Period of the most recent count.
   *
   * Returns the time interval of the most recent count. This can be used for
   * velocity calculations to determine shaft speed.
   *
   * @param encoderHandle the encoder handle
   * @returns             the period of the last two pulses in units of seconds
   */
  double HAL_GetEncoderPeriod(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /**
   * Sets the maximum period where the device is still considered "moving".
   *
   * Sets the maximum period where the device is considered moving. This value is
   * used to determine the "stopped" state of the encoder using the
   * HAL_GetEncoderStopped method.
   *
   * @param encoderHandle the encoder handle
   * @param maxPeriod     the maximum period where the counted device is
   * considered moving in seconds
   */
  void HAL_SetEncoderMaxPeriod(HAL_EncoderHandle encoderHandle, double maxPeriod,
                               int32_t* status);
  
  /**
   * Determines if the clock is stopped.
   *
   * Determines if the clocked input is stopped based on the MaxPeriod value set
   * using the SetMaxPeriod method. If the clock exceeds the MaxPeriod, then the
   * device (and encoder) are assumed to be stopped and it returns true.
   *
   * @param encoderHandle the encoder handle
   * @return              true if the most recent encoder period exceeds the
   * MaxPeriod value set by SetMaxPeriod
   */
  HAL_Bool HAL_GetEncoderStopped(HAL_EncoderHandle encoderHandle,
                                 int32_t* status);
  
  /**
   * Gets the last direction the encoder value changed.
   *
   * @param encoderHandle the encoder handle
   * @return              the last direction the encoder value changed
   */
  HAL_Bool HAL_GetEncoderDirection(HAL_EncoderHandle encoderHandle,
                                   int32_t* status);
  
  /**
   * Gets the current distance traveled by the encoder.
   *
   * This is the encoder count scaled by the distance per pulse set for the
   * encoder.
   *
   * @param encoderHandle the encoder handle
   * @return              the encoder distance (units are determined by the units
   * passed to HAL_SetEncoderDistancePerPulse)
   */
  double HAL_GetEncoderDistance(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /**
   * Gets the current rate of the encoder.
   *
   * This is the encoder period scaled by the distance per pulse set for the
   * encoder.
   *
   * @param encoderHandle the encoder handle
   * @return              the encoder rate (units are determined by the units
   * passed to HAL_SetEncoderDistancePerPulse, time value is seconds)
   */
  double HAL_GetEncoderRate(HAL_EncoderHandle encoderHandle, int32_t* status);
  
  /**
   * Sets the minimum rate to be considered moving by the encoder.
   *
   * Units need to match what is set by HAL_SetEncoderDistancePerPulse, with time
   * as seconds.
   *
   * @param encoderHandle the encoder handle
   * @param minRate       the minimum rate to be considered moving (units are
   * determined by the units passed to HAL_SetEncoderDistancePerPulse, time value
   * is seconds)
   */
  void HAL_SetEncoderMinRate(HAL_EncoderHandle encoderHandle, double minRate,
                             int32_t* status);
  
  /**
   * Sets the distance traveled per encoder pulse. This is used as a scaling
   * factor for the rate and distance calls.
   *
   * @param encoderHandle    the encoder handle
   * @param distancePerPulse the distance traveled per encoder pulse (units user
   * defined)
   */
  void HAL_SetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
                                      double distancePerPulse, int32_t* status);
  
  /**
   * Sets if to reverse the direction of the encoder.
   *
   * Note that this is not a toggle. It is an absolute set.
   *
   * @param encoderHandle    the encoder handle
   * @param reverseDirection true to reverse the direction, false to not.
   */
  void HAL_SetEncoderReverseDirection(HAL_EncoderHandle encoderHandle,
                                      HAL_Bool reverseDirection, int32_t* status);
  
  /**
   * Sets the number of encoder samples to average when calculating encoder rate.
   *
   * @param encoderHandle    the encoder handle
   * @param samplesToAverage the number of samples to average
   */
  void HAL_SetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
                                      int32_t samplesToAverage, int32_t* status);
  
  /**
   * Gets the current samples to average value.
   *
   * @param encoderHandle the encoder handle
   * @return              the current samples to average value
   */
  int32_t HAL_GetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
                                         int32_t* status);
  
  /**
   * Sets the source for an index pulse on the encoder.
   *
   * The index pulse can be used to cause an encoder to reset based on an external
   * input.
   *
   * @param encoderHandle       the encoder handle
   * @param digitalSourceHandle the index source handle (either a
   * HAL_AnalogTriggerHandle of a HAL_DigitalHandle)
   * @param analogTriggerType   the analog trigger type if the source is an analog
   * trigger
   * @param type                the index triggering type
   */
  void HAL_SetEncoderIndexSource(HAL_EncoderHandle encoderHandle,
                                 HAL_Handle digitalSourceHandle,
                                 HAL_AnalogTriggerType analogTriggerType,
                                 HAL_EncoderIndexingType type, int32_t* status);
  
  /**
   * Gets the FPGA index of the encoder.
   *
   * @param encoderHandle the encoder handle
   * @return              the FPGA index of the encoder
   */
  int32_t HAL_GetEncoderFPGAIndex(HAL_EncoderHandle encoderHandle,
                                  int32_t* status);
  
  /**
   * Gets the decoding scale factor of the encoder.
   *
   * This is used to perform the scaling from raw to type scaled values.
   *
   * @param encoderHandle the encoder handle
   * @return              the scale value for the encoder
   */
  double HAL_GetEncoderDecodingScaleFactor(HAL_EncoderHandle encoderHandle,
                                           int32_t* status);
  
  /**
   * Gets the user set distance per pulse of the encoder.
   *
   * @param encoderHandle the encoder handle
   * @return              the set distance per pulse
   */
  double HAL_GetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
                                        int32_t* status);
  
  /**
   * Gets the encoding type of the encoder.
   *
   * @param encoderHandle the encoder handle
   * @return              the encoding type
   */
  HAL_EncoderEncodingType HAL_GetEncoderEncodingType(
      HAL_EncoderHandle encoderHandle, int32_t* status);
  #ifdef __cplusplus
  }  // extern "C"
  #endif
  /** @} */
  