src/main/java/com/kennedyrobotics/hardware/sensors/ctre/ICANCoder.java
package com.kennedyrobotics.hardware.sensors.ctre;

import com.ctre.phoenix.ErrorCode;
import com.ctre.phoenix.ParamEnum;
import com.ctre.phoenix.sensors.*;

public interface ICANCoder {

    public int getDeviceID();

    /**
     * Gets the position of the sensor.  This may be relative or absolute depending on configuration.
     * The units are determined by the coefficient and unit-string configuration params, default is degrees.
     * @return The position of the sensor.
     */
    public double getPosition();

    /**
     * Sets the position of the sensor.
     * The units are determined by the coefficient and unit-string configuration params, default is degrees.
     * @param newPosition
     * @return ErrorCode generated by function. 0 indicates no error.
     */
    public ErrorCode setPosition(double newPosition, int timeoutMs);

    /**
     * Sets the position of the sensor.
     * The units are determined by the coefficient and unit-string configuration params, default is degrees.
     * @param newPosition
     * @return ErrorCode generated by function. 0 indicates no error.
     */
    public ErrorCode setPosition(double newPosition);

    /**
     * Sets the position of the sensor to match the magnet's "Absolute Sensor".
     * The units are determined by the coefficient and unit-string configuration params, default is degrees.
     * @return ErrorCode generated by function. 0 indicates no error.
     */
    public ErrorCode setPositionToAbsolute(int timeoutMs);

    /**
     * Sets the position of the sensor to match the magnet's "Absolute Sensor".
     * The units are determined by the coefficient and unit-string configuration params, default is degrees.
     * @return ErrorCode generated by function. 0 indicates no error.
     */
    public ErrorCode setPositionToAbsolute();

    /**
     * Gets the velocity of the sensor.
     * The units are determined by the coefficient and unit-string configuration params, default is degrees per second.
     * @return The Velocity of the sensor.
     */
    public double getVelocity();

    /**
     * Gets the absolute position of the sensor.
     * The absolute position may be unsigned (for example: [0,360) deg), or signed (for example: [-180,+180) deg).  This is determined by a configuration.  The default selection is unsigned.
     * The units are determined by the coefficient and unit-string configuration params, default is degrees.
     * Note: this signal is not affected by calls to SetPosition().
     * @return The position of the sensor.
     */
    public double getAbsolutePosition();

    /**
     * Configures the period of each velocity sample.
     * Every 1ms a position value is sampled, and the delta between that sample
     * and the position sampled kPeriod ms ago is inserted into a filter.
     * kPeriod is configured with this function.
     *
     * @param period
     *            Desired period for the velocity measurement.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configVelocityMeasurementPeriod(SensorVelocityMeasPeriod period, int timeoutMs);

    /**
     * Configures the period of each velocity sample.
     * Every 1ms a position value is sampled, and the delta between that sample
     * and the position sampled kPeriod ms ago is inserted into a filter.
     * kPeriod is configured with this function.
     *
     * @param period
     *            Desired period for the velocity measurement.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configVelocityMeasurementPeriod(SensorVelocityMeasPeriod period);

    /**
     * Sets the number of velocity samples used in the rolling average velocity
     * measurement.
     *
     * @param windowSize
     *            Number of samples in the rolling average of velocity
     *            measurement. Valid values are 1,2,4,8,16,32. If another
     *            value is specified, it will truncate to nearest support value.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs);

    /**
     * Sets the number of velocity samples used in the rolling average velocity
     * measurement.
     *
     * @param windowSize
     *            Number of samples in the rolling average of velocity
     *            measurement. Valid values are 1,2,4,8,16,32. If another
     *            value is specified, it will truncate to nearest support value.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configVelocityMeasurementWindow(int windowSize);

    /**
     * Sets the signage and range of the "Absolute Position" signal.
     * Choose unsigned for an absolute range of [0,+1) rotations, [0,360) deg, etc...
     * Choose signed for an absolute range of [-0.5,+0.5) rotations, [-180,+180) deg, etc...
     * @param absoluteSensorRange
     *            Desired Sign/Range for the absolute position register.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configAbsoluteSensorRange(AbsoluteSensorRange absoluteSensorRange, int timeoutMs);

    /**
     * Sets the signage and range of the "Absolute Position" signal.
     * Choose unsigned for an absolute range of [0,+1) rotations, [0,360) deg, etc...
     * Choose signed for an absolute range of [-0.5,+0.5) rotations, [-180,+180) deg, etc...
     * @param absoluteSensorRange
     *            Desired Sign/Range for the absolute position register.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configAbsoluteSensorRange(AbsoluteSensorRange absoluteSensorRange);

    /**
     * Adjusts the zero point for the absolute position register.
     * The absolute position of the sensor will always have a discontinuity (360 -> 0 deg) or (+180 -> -180)
     * and a hard-limited mechanism may have such a discontinuity in its functional range.
     * In which case use this config to move the discontinuity outside of the function range.
     * @param offsetDegrees
     *            Offset in degrees (unit string and coefficient DO NOT apply for this config).
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configMagnetOffset(double offsetDegrees, int timeoutMs);

    /**
     * Adjusts the zero point for the absolute position register.
     * The absolute position of the sensor will always have a discontinuity (360 -> 0 deg) or (+180 -> -180)
     * and a hard-limited mechanism may have such a discontinuity in its functional range.
     * In which case use this config to move the discontinuity outside of the function range.
     * @param offsetDegrees
     *            Offset in degrees (unit string and coefficient DO NOT apply for this config).
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configMagnetOffset(double offsetDegrees);

    /**
     * Pick the strategy on how to initialize the CANCoder's "Position" register.  Depending on the mechanism,
     * it may be desirable to auto set the Position register to match the Absolute Position (swerve for example).
     * Or it may be desired to zero the sensor on boot (drivetrain translation sensor or a relative servo).
     *
     * TIP: Tuner's self-test feature will report what the boot sensor value will be in the event the CANCoder is reset.
     *
     * @param initializationStrategy
     *            The sensor initialization strategy to use.  This will impact the behavior the next time CANCoder boots up.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSensorInitializationStrategy(SensorInitializationStrategy initializationStrategy, int timeoutMs);

    /**
     * Pick the strategy on how to initialize the CANCoder's "Position" register.  Depending on the mechanism,
     * it may be desirable to auto set the Position register to match the Absolute Position (swerve for example).
     * Or it may be desired to zero the sensor on boot (drivetrain translation sensor or a relative servo).
     *
     * TIP: Tuner's self-test feature will report what the boot sensor value will be in the event the CANCoder is reset.
     *
     * @param initializationStrategy
     *            The sensor initialization strategy to use.  This will impact the behavior the next time CANCoder boots up.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSensorInitializationStrategy(SensorInitializationStrategy initializationStrategy);

    /**
     * Choose what units you want the API to get/set.  This also impacts the units displayed in Self-Test in Tuner.
     * Depending on your mechanism, you may want to scale rotational units (deg, radians, rotations), or scale to a distance (inches, centimeters).
     * @param sensorCoefficient
     *            Scalar to multiply the CANCoder's native 12-bit resolute sensor. Defaults to 0.087890625 to produce degrees.
     * @param unitString
     *            String holding the unit to report in.  This impacts all routines (except for ConfigMagnetOffset) and the self-test in Tuner.
     *            The string value itself is arbitrary.  The max number of letters will depend on firmware versioning, but generally CANCoder
     *            supports up to eight letters.  However, common units such as "centimeters" are supported explicitly despite exceeding the eight-letter limit.
     *			  Default is "deg"
     * @param sensorTimeBase
     *            Desired denominator to report velocity in.  This impacts GetVelocity and the reported velocity in self-test in Tuner.
     *            Default is "Per Second".
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configFeedbackCoefficient(double sensorCoefficient, String unitString, SensorTimeBase sensorTimeBase, int timeoutMs);

    /**
     * Choose what units you want the API to get/set.  This also impacts the units displayed in Self-Test in Tuner.
     * Depending on your mechanism, you may want to scale rotational units (deg, radians, rotations), or scale to a distance (inches, centimeters).
     * @param sensorCoefficient
     *            Scalar to multiply the CANCoder's native 12-bit resolute sensor. Defaults to 0.087890625 to produce degrees.
     * @param unitString
     *            String holding the unit to report in.  This impacts all routines (except for ConfigMagnetOffset) and the self-test in Tuner.
     *            The string value itself is arbitrary.  The max number of letters will depend on firmware versioning, but generally CANCoder
     *            supports up to eight letters.  However, common units such as "centimeters" are supported explicitly despite exceeding the eight-letter limit.
     *			  Default is "deg"
     * @param sensorTimeBase
     *            Desired denominator to report velocity in.  This impacts GetVelocity and the reported velocity in self-test in Tuner.
     *            Default is "Per Second".
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configFeedbackCoefficient(double sensorCoefficient, String unitString, SensorTimeBase sensorTimeBase);

    /**
     * Gets the bus voltage seen by the device.
     *
     * @return The bus voltage value (in volts).
     */
    public double getBusVoltage();

    /**
     * Gets the magnet's health.
     *
     * @return The magnet health code (red/orange/green).
     */
    public MagnetFieldStrength getMagnetFieldStrength();

    /**
     * Choose which direction is interpreted as positive displacement.
     * This affects both "Position" and "Absolute Position".
     * @param bSensorDirection
     *            False (default) means positive rotation occurs when magnet
     *            is spun counter-clockwise when observer is facing the LED side of CANCoder.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSensorDirection(boolean bSensorDirection, int timeoutMs);

    /**
     * Choose which direction is interpreted as positive displacement.
     * This affects both "Position" and "Absolute Position".
     * @param bSensorDirection
     *            False (default) means positive rotation occurs when magnet
     *            is spun counter-clockwise when observer is facing the LED side of CANCoder.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSensorDirection(boolean bSensorDirection);

    /**
     * Call GetLastError() generated by this object.
     * Not all functions return an error code but can
     * potentially report errors.
     *
     * This function can be used to retrieve those error codes.
     *
     * @return The last ErrorCode generated.
     */
    public ErrorCode getLastError();

    /**
     * Get the units for the signal retrieved in the last called get routine.
     */
    public String getLastUnitString();

    /**
     * Get the timestamp of the CAN frame retrieved in the last called get routine.
     */
    public double getLastTimestamp();

    /**
     * Sets the value of a custom parameter. This is for arbitrary use.
     *
     * Sometimes it is necessary to save calibration/duty cycle/output
     * information in the device. Particularly if the
     * device is part of a subsystem that can be replaced.
     *
     * @param newValue
     *            Value for custom parameter.
     * @param paramIndex
     *            Index of custom parameter. [0-1]
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSetCustomParam(int newValue,
                                          int paramIndex, int timeoutMs);

    /**
     * Sets the value of a custom parameter. This is for arbitrary use.
     *
     * Sometimes it is necessary to save calibration/duty cycle/output
     * information in the device. Particularly if the
     * device is part of a subsystem that can be replaced.
     *
     * @param newValue
     *            Value for custom parameter.
     * @param paramIndex
     *            Index of custom parameter. [0-1]
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSetCustomParam(int newValue,
                                          int paramIndex);

    /**
     * Gets the value of a custom parameter. This is for arbitrary use.
     *
     * Sometimes it is necessary to save calibration/duty cycle/output
     * information in the device. Particularly if the
     * device is part of a subsystem that can be replaced.
     *
     * @param paramIndex
     *            Index of custom parameter. [0-1]
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Value of the custom param.
     */
    public int configGetCustomParam(int paramIndex, int timeoutMs);

    /**
     * Gets the value of a custom parameter. This is for arbitrary use.
     *
     * Sometimes it is necessary to save calibration/duty cycle/output
     * information in the device. Particularly if the
     * device is part of a subsystem that can be replaced.
     *
     * @param paramIndex
     *            Index of custom parameter. [0-1]
     * @return Value of the custom param.
     */
    public int configGetCustomParam(int paramIndex);

    /**
     * Sets a parameter. Generally this is not used.
     * This can be utilized in
     * - Using new features without updating API installation.
     * - Errata workarounds to circumvent API implementation.
     * - Allows for rapid testing / unit testing of firmware.
     *
     * @param param
     *            Parameter enumeration.
     * @param value
     *            Value of parameter.
     * @param subValue
     *            Subvalue for parameter. Maximum value of 255.
     * @param ordinal
     *            Ordinal of parameter.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSetParameter(ParamEnum param, double value,
                                        int subValue, int ordinal, int timeoutMs);

    /**
     * Sets a parameter. Generally this is not used.
     * This can be utilized in
     * - Using new features without updating API installation.
     * - Errata workarounds to circumvent API implementation.
     * - Allows for rapid testing / unit testing of firmware.
     *
     * @param param
     *            Parameter enumeration.
     * @param value
     *            Value of parameter.
     * @param subValue
     *            Subvalue for parameter. Maximum value of 255.
     * @param ordinal
     *            Ordinal of parameter.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configSetParameter(ParamEnum param, double value,
                                        int subValue, int ordinal);
    /**
     * Gets a parameter. Generally this is not used.
     * This can be utilized in
     * - Using new features without updating API installation.
     * - Errata workarounds to circumvent API implementation.
     * - Allows for rapid testing / unit testing of firmware.
     *
     * @param param
     *            Parameter enumeration.
     * @param ordinal
     *            Ordinal of parameter.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Value of parameter.
     */
    public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs);

    /**
     * Gets a parameter. Generally this is not used.
     * This can be utilized in
     * - Using new features without updating API installation.
     * - Errata workarounds to circumvent API implementation.
     * - Allows for rapid testing / unit testing of firmware.
     *
     * @param param
     *            Parameter enumeration.
     * @param ordinal
     *            Ordinal of parameter.
     * @return Value of parameter.
     */
    public double configGetParameter(ParamEnum param, int ordinal);

    /**
     * Sets the period of the given status frame.
     *
     * @param statusFrame
     *            Frame whose period is to be changed.
     * @param periodMs
     *            Period in ms for the given frame.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode setStatusFramePeriod(CANCoderStatusFrame statusFrame, int periodMs, int timeoutMs);

    /**
     * Sets the period of the given status frame.
     *
     * @param statusFrame
     *            Frame whose period is to be changed.
     * @param periodMs
     *            Period in ms for the given frame.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode setStatusFramePeriod(CANCoderStatusFrame statusFrame, int periodMs);

    /**
     * Gets the period of the given status frame.
     *
     * @param frame
     *            Frame to get the period of.
     * @param timeoutMs
     *            Timeout value in ms. If nonzero, function will wait for
     *            config success and report an error if it times out.
     *            If zero, no blocking or checking is performed.
     * @return Period of the given status frame.
     */
    public int getStatusFramePeriod(CANCoderStatusFrame frame,
                                    int timeoutMs);

    /**
     * Gets the period of the given status frame.
     *
     * @param frame
     *            Frame to get the period of.
     * @return Period of the given status frame.
     */
    public int getStatusFramePeriod(CANCoderStatusFrame frame);

    /**
     * Gets the firmware version of the device.
     *
     * @return Firmware version of device.
     */
    public int getFirmwareVersion();

    /**
     * Returns true if the device has reset since last call.
     *
     * @return Has a Device Reset Occurred?
     */
    public boolean hasResetOccurred();

    /**
     * Gets the CANCoder fault status
     *
     * @param toFill
     *            Container for fault statuses.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode getFaults(CANCoderFaults toFill);

    /**
     * Gets the CANCoder sticky fault status
     *
     * @param toFill
     *            Container for sticky fault statuses.
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode getStickyFaults(CANCoderStickyFaults toFill);

    /**
     * Clears the Sticky Faults
     *
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode clearStickyFaults(int timeoutMs);

    /**
     * Clears the Sticky Faults
     *
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode clearStickyFaults();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public SensorVelocityMeasPeriod configGetVelocityMeasurementPeriod(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public SensorVelocityMeasPeriod configGetVelocityMeasurementPeriod();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public int configGetVelocityMeasurementWindow(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public int configGetVelocityMeasurementWindow();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public AbsoluteSensorRange configGetAbsoluteSensorRange(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public AbsoluteSensorRange configGetAbsoluteSensorRange();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public double configGetMagnetOffset(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public double configGetMagnetOffset();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public boolean configGetSensorDirection(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public boolean configGetSensorDirection();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public SensorInitializationStrategy configGetSensorInitializationStrategy(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public SensorInitializationStrategy configGetSensorInitializationStrategy();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public double configGetFeedbackCoefficient(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public double configGetFeedbackCoefficient();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public String configGetFeedbackUnitString(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public String configGetFeedbackUnitString();

    /**
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     * @return Read value of the config param.
     */
    public SensorTimeBase configGetFeedbackTimeBase(int timeoutMs);

    /**
     * @return Read value of the config param.
     */
    public SensorTimeBase configGetFeedbackTimeBase();

    /**
     * Configures all persistent settings.
     *
     * @param allConfigs        Object with all of the persistant settings
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     *              If zero, no blocking or checking is performed.
     *
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configAllSettings(CANCoderConfiguration allConfigs, int timeoutMs);

    /**
     * Configures all persistent settings (overloaded so timeoutMs is 50 ms).
     *
     * @param allConfigs        Object with all of the persistant settings
     *
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configAllSettings(CANCoderConfiguration allConfigs);

    /**
     * Gets all persistant settings.
     *
     * @param allConfigs        Object with all of the persistant settings
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     *              If zero, no blocking or checking is performed.
     */
    public void getAllConfigs(CANCoderConfiguration allConfigs, int timeoutMs);

    /**
     * Gets all persistant settings (overloaded so timeoutMs is 50 ms).
     *
     * @param allConfigs        Object with all of the persistant settings
     */
    public void getAllConfigs(CANCoderConfiguration allConfigs);

    /**
     * Configures all persistent settings to defaults.
     *
     * @param timeoutMs
     *              Timeout value in ms. If nonzero, function will wait for
     *              config success and report an error if it times out.
     *              If zero, no blocking or checking is performed.
     *
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configFactoryDefault(int timeoutMs);

    /**
     * Configures all persistent settings to defaults.
     *
     * @return Error Code generated by function. 0 indicates no error.
     */
    public ErrorCode configFactoryDefault();
}
