001/* Copyright (C) Cross The Road Electronics 2024 */
002package com.ctre.phoenix.motorcontrol.can;
003
004import com.ctre.phoenix.motorcontrol.ControlFrame;
005import com.ctre.phoenix.motorcontrol.ControlMode;
006import com.ctre.phoenix.motorcontrol.DemandType;
007import com.ctre.phoenix.motorcontrol.Faults;
008import com.ctre.phoenix.motorcontrol.FeedbackDevice;
009import com.ctre.phoenix.motorcontrol.FollowerType;
010import com.ctre.phoenix.motorcontrol.IMotorController;
011import com.ctre.phoenix.motorcontrol.InvertType;
012import com.ctre.phoenix.motorcontrol.LimitSwitchNormal;
013import com.ctre.phoenix.motorcontrol.LimitSwitchSource;
014import com.ctre.phoenix.motorcontrol.NeutralMode;
015import com.ctre.phoenix.motorcontrol.RemoteFeedbackDevice;
016import com.ctre.phoenix.motorcontrol.RemoteLimitSwitchSource;
017import com.ctre.phoenix.motorcontrol.RemoteSensorSource;
018import com.ctre.phoenix.motorcontrol.SensorTerm;
019import com.ctre.phoenix.motorcontrol.StatusFrame;
020import com.ctre.phoenix.motorcontrol.StatusFrameEnhanced;
021import com.ctre.phoenix.motorcontrol.StickyFaults;
022import com.ctre.phoenix.motorcontrol.VelocityMeasPeriod;
023import com.ctre.phoenix.motorcontrol.VictorSPXSimCollection;
024import com.ctre.phoenix.motorcontrol.can.MotControllerJNI;
025import com.ctre.phoenix.sensors.CANCoder;
026import com.ctre.phoenix.ParamEnum;
027import com.ctre.phoenix.motion.BufferedTrajectoryPointStream;
028import com.ctre.phoenix.motion.MotionProfileStatus;
029import com.ctre.phoenix.motion.SetValueMotionProfile;
030import com.ctre.phoenix.motion.TrajectoryPoint;
031import com.ctre.phoenix.ErrorCode;
032import com.ctre.phoenix.ErrorCollection;
033import com.ctre.phoenix.ParamEnum;
034import com.ctre.phoenix.sensors.SensorVelocityMeasPeriod;
035
036/**
037 * Base motor controller features for all CTRE CAN motor controllers.
038 */
039public abstract class BaseMotorController implements com.ctre.phoenix.motorcontrol.IMotorController {
040
041        private ControlMode m_controlMode = ControlMode.PercentOutput;
042        private ControlMode m_sendMode = ControlMode.PercentOutput;
043
044        private InvertType _invert = InvertType.None;
045
046        private boolean _isVcompEn = false; //off by default
047
048        /**
049         * Device handle
050         */
051        protected long m_handle;
052
053        private int [] _motionProfStats = new int[11];
054
055        private VictorSPXSimCollection _simCollSpx;
056
057        // --------------------- Constructors -----------------------------//
058        /**
059         * Constructor for motor controllers.
060         *
061         * @param arbId Device ID [0,62]
062         * @param model String specifying device model
063         */
064        public BaseMotorController(int arbId, String model, String canbus) {
065                m_handle = MotControllerJNI.Create2(arbId, model, canbus);
066                _simCollSpx = new VictorSPXSimCollection(this);
067        }
068
069        /**
070         * Constructor for motor controllers.
071         *
072         * @param arbId Device ID [0,62]
073         * @param model String specifying device model
074         */
075        public BaseMotorController(int arbId, String model) {
076                this(arbId, model, "");
077        }
078
079        protected VictorSPXSimCollection getVictorSPXSimCollection() {return _simCollSpx;}
080
081        /**
082         * Destructor for motor controllers
083         * @return Error Code generated by function. 0 indicates no error.
084         */
085    public ErrorCode DestroyObject() {
086        return ErrorCode.valueOf(MotControllerJNI.JNI_destroy_MotController(m_handle));
087    }
088
089    //public static void DestroyAllMotControllers() {
090    //    MotControllerJNI.JNI_destroy_AllMotControllers();
091    //}
092
093        /**
094         * @return CCI handle for child classes.
095         */
096        public long getHandle() {
097                return m_handle;
098        }
099
100        /**
101         * Returns the Device ID
102         *
103         * @return Device number.
104         */
105        public int getDeviceID() {
106                return MotControllerJNI.GetDeviceNumber(m_handle);
107        }
108
109        // ------ Set output routines. ----------//
110        /**
111         * Sets the appropriate output on the talon, depending on the mode.
112         * @param mode The output mode to apply.
113         * In PercentOutput, the output is between -1.0 and 1.0, with 0.0 as stopped.
114         * In Current mode, output value is in amperes.
115         * In Velocity mode, output value is in position change / 100ms.
116         * In Position mode, output value is in encoder ticks or an analog value,
117         *   depending on the sensor.
118         * In Follower mode, the output value is the integer device ID of the talon to
119         * duplicate.
120         *
121         * @param outputValue The setpoint value, as described above.
122         *
123         *
124         *      Standard Driving Example:
125         *      _talonLeft.set(ControlMode.PercentOutput, leftJoy);
126         *      _talonRght.set(ControlMode.PercentOutput, rghtJoy);
127         */
128        public void set(ControlMode mode, double outputValue) {
129                set(mode, outputValue, DemandType.Neutral, 0);
130        }
131        /**
132         * @param mode Sets the appropriate output on the talon, depending on the mode.
133         * @param demand0 The output value to apply.
134         *      such as advanced feed forward and/or auxiliary close-looping in firmware.
135         * In PercentOutput, the output is between -1.0 and 1.0, with 0.0 as stopped.
136         * In Current mode, output value is in amperes.
137         * In Velocity mode, output value is in position change / 100ms.
138         * In Position mode, output value is in encoder ticks or an analog value,
139         *   depending on the sensor. See
140         * In Follower mode, the output value is the integer device ID of the talon to
141         * duplicate.
142         *
143         * @param demand1Type The demand type for demand1.
144         * Neutral: Ignore demand1 and apply no change to the demand0 output.
145         * AuxPID: Use demand1 to set the target for the auxiliary PID 1.  Auxiliary
146         *   PID is always executed as standard Position PID control.
147         * ArbitraryFeedForward: Use demand1 as an arbitrary additive value to the
148         *       demand0 output.  In PercentOutput the demand0 output is the motor output,
149         *   and in closed-loop modes the demand0 output is the output of PID0.
150         * @param demand1 Supplmental output value.
151         * AuxPID: Target position in Sensor Units
152         * ArbitraryFeedForward: Percent Output between -1.0 and 1.0
153         *
154         *
155         *  Arcade Drive Example:
156         *              _talonLeft.set(ControlMode.PercentOutput, joyForward, DemandType.ArbitraryFeedForward, +joyTurn);
157         *              _talonRght.set(ControlMode.PercentOutput, joyForward, DemandType.ArbitraryFeedForward, -joyTurn);
158         *
159         *      Drive Straight Example:
160         *      Note: Selected Sensor Configuration is necessary for both PID0 and PID1.
161         *              _talonLeft.follow(_talonRght, FollwerType.AuxOutput1);
162         *              _talonRght.set(ControlMode.PercentOutput, joyForward, DemandType.AuxPID, desiredRobotHeading);
163         *
164         *      Drive Straight to a Distance Example:
165         *      Note: Other configurations (sensor selection, PID gains, etc.) need to be set.
166         *              _talonLeft.follow(_talonRght, FollwerType.AuxOutput1);
167         *              _talonRght.set(ControlMode.MotionMagic, targetDistance, DemandType.AuxPID, desiredRobotHeading);
168         */
169        public void set(ControlMode mode, double demand0, DemandType demand1Type, double demand1){
170                m_controlMode = mode;
171                m_sendMode = mode;
172                int work;
173
174                switch (m_controlMode) {
175                case PercentOutput:
176                        // case TimedPercentOutput:
177                        MotControllerJNI.Set_4(m_handle, m_sendMode.value, demand0, demand1, demand1Type.value);
178                        break;
179                case Follower:
180                        /* did caller specify device ID */
181                        if ((0 <= demand0) && (demand0 <= 62)) { // [0,62]
182                                work = getBaseID();
183                                work >>= 16;
184                                work <<= 8;
185                                work |= ((int) demand0) & 0xFF;
186                        } else {
187                                work = (int) demand0;
188                        }
189                        /* single precision guarantees 16bits of integral precision,
190                   * so float/double cast on work is safe */
191                        MotControllerJNI.Set_4(m_handle, m_sendMode.value, (double)work, demand1, demand1Type.value);
192                        break;
193                case Velocity:
194                case Position:
195                case MotionMagic:
196                case MotionProfile:
197                case MotionProfileArc:
198                        MotControllerJNI.Set_4(m_handle, m_sendMode.value, demand0, demand1, demand1Type.value);
199                        break;
200                case Current:
201                        MotControllerJNI.SetDemand(m_handle, m_sendMode.value, (int) (1000. * demand0), 0); /* milliamps */
202                        break;
203                case MusicTone:
204                        MotControllerJNI.Set_4(m_handle, m_sendMode.value, demand0, demand1, demand1Type.value);
205                        break;
206                case Disabled:
207                        /* fall thru... */
208                default:
209                        MotControllerJNI.SetDemand(m_handle, m_sendMode.value, 0, 0);
210                        break;
211                }
212
213        }
214
215        /**
216         * Neutral the motor output by setting control mode to disabled.
217         */
218        public void neutralOutput() {
219                set(ControlMode.Disabled, 0);
220        }
221
222        /**
223         * Sets the mode of operation during neutral throttle output.
224         *
225         * @param neutralMode
226         *            The desired mode of operation when the Controller output
227         *            throttle is neutral (ie brake/coast)
228         **/
229        public void setNeutralMode(NeutralMode neutralMode) {
230                MotControllerJNI.SetNeutralMode(m_handle, neutralMode.value);
231        }
232
233        // ------ Invert behavior ----------//
234        /**
235         * Sets the phase of the sensor. Use when controller forward/reverse output
236         * doesn't correlate to appropriate forward/reverse reading of sensor.
237         * Pick a value so that positive PercentOutput yields a positive change in sensor.
238         * After setting this, user can freely call SetInverted() with any value.
239         *
240         * @param PhaseSensor
241         *            Indicates whether to invert the phase of the sensor.
242         */
243        public void setSensorPhase(boolean PhaseSensor) {
244                MotControllerJNI.SetSensorPhase(m_handle, PhaseSensor);
245        }
246
247        /**
248         * Inverts the hbridge output of the motor controller.
249         *
250         * This does not impact sensor phase and should not be used to correct sensor polarity.
251         *
252         * This will invert the hbridge output but NOT the LEDs.
253         * This ensures....
254         *  - Green LEDs always represents positive request from robot-controller/closed-looping mode.
255         *  - Green LEDs correlates to forward limit switch.
256         *  - Green LEDs correlates to forward soft limit.
257         *
258         * @param invert
259         *            Invert state to set.
260         */
261        public void setInverted(boolean invert) {
262                if(invert){
263                        setInverted(InvertType.InvertMotorOutput);
264                }
265                else{
266                        setInverted(InvertType.None);
267                }
268        }
269
270        /**
271         * Inverts the hbridge output of the motor controller in relation to the master if present
272         *
273         * This does not impact sensor phase and should not be used to correct sensor polarity.
274         *
275         * This will allow you to either:
276         *  - Not invert the motor
277         *  - Invert the motor
278         *  - Always follow the master regardless of master's inversion
279         *  - Always oppose the master regardless of master's inversion
280         *
281         * @param invertType
282         *            Invert state to set.
283         */
284        public void setInverted(InvertType invertType){
285                _invert = invertType;
286                MotControllerJNI.SetInverted_2(m_handle, invertType.value);
287        }
288
289        /**
290         * @return invert setting of motor output.
291         */
292        public boolean getInverted() {
293                switch(_invert){
294                        case None:{
295                                return false;
296                        }
297                        case InvertMotorOutput:{
298                                return true;
299                        }
300                        default:{
301                                break;
302                        }
303                }
304                return MotControllerJNI.GetInverted(m_handle);
305        }
306
307    //----- Factory Default Configuration -----//
308        /**
309         * Revert all configurations to factory default values.
310         * Use this before your individual config* calls to avoid having to config every single param.
311         *
312         * Alternatively you can use the configAllSettings routine.
313         *
314         * @param timeoutMs
315         *            Timeout value in ms. Function will generate error if config is
316         *            not successful within timeout.
317         * @return Error Code generated by function. 0 indicates no error.
318         */
319        public ErrorCode configFactoryDefault(int timeoutMs){
320                int retval = MotControllerJNI.ConfigFactoryDefault(m_handle, timeoutMs);
321                return ErrorCode.valueOf(retval);
322        }
323        /**
324         * Revert all configurations to factory default values.
325         * Use this before your individual config* calls to avoid having to config every single param.
326         *
327         * Alternatively you can use the configAllSettings routine.
328         *
329         * @return Error Code generated by function. 0 indicates no error.
330         */
331        public ErrorCode configFactoryDefault() {
332        int timeoutMs = 50;
333                int retval = MotControllerJNI.ConfigFactoryDefault(m_handle, timeoutMs);
334                return ErrorCode.valueOf(retval);
335        }
336
337        // ----- general output shaping ------------------//
338        /**
339         * Configures the open-loop ramp rate of throttle output.
340         *
341         * @param secondsFromNeutralToFull
342         *            Minimum desired time to go from neutral to full throttle. A
343         *            value of '0' will disable the ramp.
344         * @param timeoutMs
345         *            Timeout value in ms. If nonzero, function will wait for
346         *            config success and report an error if it times out.
347         *            If zero, no blocking or checking is performed.
348         * @return Error Code generated by function. 0 indicates no error.
349         */
350        public ErrorCode configOpenloopRamp(double secondsFromNeutralToFull, int timeoutMs) {
351                int retval = MotControllerJNI.ConfigOpenLoopRamp(m_handle, secondsFromNeutralToFull, timeoutMs);
352                return ErrorCode.valueOf(retval);
353        }
354        /**
355         * Configures the open-loop ramp rate of throttle output.
356         *
357         * @param secondsFromNeutralToFull
358         *            Minimum desired time to go from neutral to full throttle. A
359         *            value of '0' will disable the ramp.
360         * @return Error Code generated by function. 0 indicates no error.
361         */
362        public ErrorCode configOpenloopRamp(double secondsFromNeutralToFull) {
363                int timeoutMs = 0;
364                return configOpenloopRamp(secondsFromNeutralToFull, timeoutMs);
365        }
366
367        /**
368         * Configures the closed-loop ramp rate of throttle output.
369         *
370         * @param secondsFromNeutralToFull
371         *            Minimum desired time to go from neutral to full throttle. A
372         *            value of '0' will disable the ramp.
373         * @param timeoutMs
374         *            Timeout value in ms. If nonzero, function will wait for
375         *            config success and report an error if it times out.
376         *            If zero, no blocking or checking is performed.
377         * @return Error Code generated by function. 0 indicates no error.
378         */
379        public ErrorCode configClosedloopRamp(double secondsFromNeutralToFull, int timeoutMs) {
380                int retval = MotControllerJNI.ConfigClosedLoopRamp(m_handle, secondsFromNeutralToFull, timeoutMs);
381                return ErrorCode.valueOf(retval);
382        }
383        /**
384         * Configures the closed-loop ramp rate of throttle output.
385         *
386         * @param secondsFromNeutralToFull
387         *            Minimum desired time to go from neutral to full throttle. A
388         *            value of '0' will disable the ramp.
389         * @return Error Code generated by function. 0 indicates no error.
390         */
391        public ErrorCode configClosedloopRamp(double secondsFromNeutralToFull) {
392                int timeoutMs = 0;
393                return configClosedloopRamp(secondsFromNeutralToFull, timeoutMs);
394        }
395
396        /**
397         * Configures the forward peak output percentage.
398         *
399         * @param percentOut
400         *            Desired peak output percentage. [0,1]
401         * @param timeoutMs
402         *            Timeout value in ms. If nonzero, function will wait for
403         *            config success and report an error if it times out.
404         *            If zero, no blocking or checking is performed.
405         * @return Error Code generated by function. 0 indicates no error.
406         */
407        public ErrorCode configPeakOutputForward(double percentOut, int timeoutMs) {
408                int retval = MotControllerJNI.ConfigPeakOutputForward(m_handle, percentOut, timeoutMs);
409                return ErrorCode.valueOf(retval);
410        }
411        /**
412         * Configures the forward peak output percentage.
413         *
414         * @param percentOut
415         *            Desired peak output percentage. [0,1]
416         * @return Error Code generated by function. 0 indicates no error.
417         */
418        public ErrorCode configPeakOutputForward(double percentOut) {
419                int timeoutMs = 0;
420                return configPeakOutputForward(percentOut, timeoutMs);
421        }
422
423        /**
424         * Configures the reverse peak output percentage.
425         *
426         * @param percentOut
427         *            Desired peak output percentage.
428         * @param timeoutMs
429         *            Timeout value in ms. If nonzero, function will wait for
430         *            config success and report an error if it times out.
431         *            If zero, no blocking or checking is performed.
432         * @return Error Code generated by function. 0 indicates no error.
433         */
434        public ErrorCode configPeakOutputReverse(double percentOut, int timeoutMs) {
435                int retval = MotControllerJNI.ConfigPeakOutputReverse(m_handle, percentOut, timeoutMs);
436                return ErrorCode.valueOf(retval);
437        }
438        /**
439         * Configures the reverse peak output percentage.
440         *
441         * @param percentOut
442         *            Desired peak output percentage.
443         * @return Error Code generated by function. 0 indicates no error.
444         */
445        public ErrorCode configPeakOutputReverse(double percentOut) {
446                int timeoutMs = 0;
447                return configPeakOutputReverse(percentOut, timeoutMs);
448        }
449        /**
450         * Configures the forward nominal output percentage.
451         *
452         * @param percentOut
453         *            Nominal (minimum) percent output. [0,+1]
454         * @param timeoutMs
455         *            Timeout value in ms. If nonzero, function will wait for
456         *            config success and report an error if it times out.
457         *            If zero, no blocking or checking is performed.
458         * @return Error Code generated by function. 0 indicates no error.
459         */
460        public ErrorCode configNominalOutputForward(double percentOut, int timeoutMs) {
461                int retval = MotControllerJNI.ConfigNominalOutputForward(m_handle, percentOut, timeoutMs);
462                return ErrorCode.valueOf(retval);
463        }
464        /**
465         * Configures the forward nominal output percentage.
466         *
467         * @param percentOut
468         *            Nominal (minimum) percent output. [0,+1]
469         * @return Error Code generated by function. 0 indicates no error.
470         */
471        public ErrorCode configNominalOutputForward(double percentOut) {
472                int timeoutMs = 0;
473                return configNominalOutputForward(percentOut, timeoutMs);
474        }
475
476        /**
477         * Configures the reverse nominal output percentage.
478         *
479         * @param percentOut
480         *            Nominal (minimum) percent output. [-1,0]
481         * @param timeoutMs
482         *            Timeout value in ms. If nonzero, function will wait for
483         *            config success and report an error if it times out.
484         *            If zero, no blocking or checking is performed.
485         * @return Error Code generated by function. 0 indicates no error.
486         */
487        public ErrorCode configNominalOutputReverse(double percentOut, int timeoutMs) {
488                int retval = MotControllerJNI.ConfigNominalOutputReverse(m_handle, percentOut, timeoutMs);
489                return ErrorCode.valueOf(retval);
490        }
491        /**
492         * Configures the reverse nominal output percentage.
493         *
494         * @param percentOut
495         *            Nominal (minimum) percent output. [-1,0]
496         * @return Error Code generated by function. 0 indicates no error.
497         */
498        public ErrorCode configNominalOutputReverse(double percentOut) {
499                int timeoutMs = 0;
500                return configNominalOutputReverse(percentOut, timeoutMs);
501        }
502
503        /**
504         * Configures the output deadband percentage.
505         *
506         * @param percentDeadband
507         *            Desired deadband percentage. Minimum is 0.1%, Maximum is 25%.
508         *            Pass 0.04 for 4% (factory default).
509         * @param timeoutMs
510         *            Timeout value in ms. If nonzero, function will wait for
511         *            config success and report an error if it times out.
512         *            If zero, no blocking or checking is performed.
513         * @return Error Code generated by function. 0 indicates no error.
514         */
515        public ErrorCode configNeutralDeadband(double percentDeadband, int timeoutMs) {
516                int retval = MotControllerJNI.ConfigNeutralDeadband(m_handle, percentDeadband, timeoutMs);
517                return ErrorCode.valueOf(retval);
518        }
519        /**
520         * Configures the output deadband percentage.
521         *
522         * @param percentDeadband
523         *            Desired deadband percentage. Minimum is 0.1%, Maximum is 25%.
524         *            Pass 0.04 for 4% (factory default).
525         * @return Error Code generated by function. 0 indicates no error.
526         */
527        public ErrorCode configNeutralDeadband(double percentDeadband) {
528                int timeoutMs = 0;
529                return configNeutralDeadband(percentDeadband, timeoutMs);
530        }
531
532        // ------ Voltage Compensation ----------//
533        /**
534         * Configures the Voltage Compensation saturation voltage.
535         *
536         * @param voltage
537         *            This is the max voltage to apply to the hbridge when voltage
538         *            compensation is enabled.  For example, if 10 (volts) is specified
539         *            and a TalonSRX is commanded to 0.5 (PercentOutput, closed-loop, etc)
540         *            then the TalonSRX will attempt to apply a duty-cycle to produce 5V.
541         * @param timeoutMs
542         *            Timeout value in ms. If nonzero, function will wait for
543         *            config success and report an error if it times out.
544         *            If zero, no blocking or checking is performed.
545         * @return Error Code generated by function. 0 indicates no error.
546         */
547        public ErrorCode configVoltageCompSaturation(double voltage, int timeoutMs) {
548                int retval = MotControllerJNI.ConfigVoltageCompSaturation(m_handle, voltage, timeoutMs);
549                return ErrorCode.valueOf(retval);
550        }
551        /**
552         * Configures the Voltage Compensation saturation voltage.
553         *
554         * @param voltage
555         *            This is the max voltage to apply to the hbridge when voltage
556         *            compensation is enabled.  For example, if 10 (volts) is specified
557         *            and a TalonSRX is commanded to 0.5 (PercentOutput, closed-loop, etc)
558         *            then the TalonSRX will attempt to apply a duty-cycle to produce 5V.
559         * @return Error Code generated by function. 0 indicates no error.
560         */
561        public ErrorCode configVoltageCompSaturation(double voltage) {
562                int timeoutMs = 0;
563                return configVoltageCompSaturation(voltage, timeoutMs);
564        }
565
566        /**
567         * Configures the voltage measurement filter.
568         *
569         * @param filterWindowSamples
570         *            Number of samples in the rolling average of voltage
571         *            measurement.
572         * @param timeoutMs
573         *            Timeout value in ms. If nonzero, function will wait for
574         *            config success and report an error if it times out.
575         *            If zero, no blocking or checking is performed.
576         * @return Error Code generated by function. 0 indicates no error.
577         */
578        public ErrorCode configVoltageMeasurementFilter(int filterWindowSamples, int timeoutMs) {
579                int retval = MotControllerJNI.ConfigVoltageMeasurementFilter(m_handle, filterWindowSamples, timeoutMs);
580                return ErrorCode.valueOf(retval);
581        }
582        /**
583         * Configures the voltage measurement filter.
584         *
585         * @param filterWindowSamples
586         *            Number of samples in the rolling average of voltage
587         *            measurement.
588         * @return Error Code generated by function. 0 indicates no error.
589         */
590        public ErrorCode configVoltageMeasurementFilter(int filterWindowSamples) {
591                int timeoutMs = 0;
592                return configVoltageMeasurementFilter(filterWindowSamples, timeoutMs);
593        }
594
595        /**
596         * Enables voltage compensation. If enabled, voltage compensation works in
597         * all control modes.
598         *
599         * Be sure to configure the saturation voltage before enabling this.
600         *
601         * @param enable
602         *            Enable state of voltage compensation.
603         **/
604        public void enableVoltageCompensation(boolean enable) {
605                _isVcompEn = enable;
606                MotControllerJNI.EnableVoltageCompensation(m_handle, enable);
607        }
608
609        /**
610         * Returns the enable state of Voltage Compensation that the caller has set.
611         *
612         * @return TRUE if voltage compensation is enabled.
613         */
614        public boolean isVoltageCompensationEnabled(){
615                return _isVcompEn;
616        }
617
618        // ------ General Status ----------//
619        /**
620         * Gets the bus voltage seen by the device.
621         *
622         * @return The bus voltage value (in volts).
623         */
624        public double getBusVoltage() {
625                return MotControllerJNI.GetBusVoltage(m_handle);
626        }
627
628        /**
629         * Gets the output percentage of the motor controller.
630         *
631         * @return Output of the motor controller (in percent).
632         */
633        public double getMotorOutputPercent() {
634                return MotControllerJNI.GetMotorOutputPercent(m_handle);
635        }
636
637        /**
638         * @return applied voltage to motor  in volts.
639         */
640        public double getMotorOutputVoltage() {
641                return getBusVoltage() * getMotorOutputPercent();
642        }
643
644        /**
645         * Gets the output current of the motor controller.
646         * In the case of TalonSRX class, this routine returns supply current for legacy reasons.  In order to get the "true" output current, call GetStatorCurrent().
647         * In the case of TalonFX class, this routine returns the true output stator current.
648         *
649         * @deprecated Use getStatorCurrent/getSupplyCurrent instead.
650         *
651         * @return The output current (in amps).
652         */
653        @Deprecated
654        protected double getOutputCurrent() {
655                return MotControllerJNI.GetOutputCurrent(m_handle);
656        }
657
658        /**
659         * Gets the temperature of the motor controller.
660         *
661         * @return Temperature of the motor controller (in 'C)
662         */
663        public double getTemperature() {
664                return MotControllerJNI.GetTemperature(m_handle);
665        }
666
667        // ------ sensor selection ----------//
668        /**
669         * Select the remote feedback device for the motor controller.
670         * Most CTRE CAN motor controllers will support remote sensors over CAN.
671         *
672         * @param feedbackDevice
673         *            Remote Feedback Device to select.
674         * @param pidIdx
675         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
676         * @param timeoutMs
677         *            Timeout value in ms. If nonzero, function will wait for
678         *            config success and report an error if it times out.
679         *            If zero, no blocking or checking is performed.
680         * @return Error Code generated by function. 0 indicates no error.
681         */
682        public ErrorCode configSelectedFeedbackSensor(RemoteFeedbackDevice feedbackDevice, int pidIdx, int timeoutMs) {
683                int retval = MotControllerJNI.ConfigSelectedFeedbackSensor(m_handle, feedbackDevice.value, pidIdx, timeoutMs);
684                return ErrorCode.valueOf(retval);
685        }
686        /**
687         * Select the remote feedback device for the motor controller.
688         * Most CTRE CAN motor controllers will support remote sensors over CAN.
689         *
690         * @param feedbackDevice
691         *            Remote Feedback Device to select.
692         * @return Error Code generated by function. 0 indicates no error.
693         */
694        public ErrorCode configSelectedFeedbackSensor(RemoteFeedbackDevice feedbackDevice) {
695                int pidIdx = 0;
696                int timeoutMs = 0;
697                return configSelectedFeedbackSensor(feedbackDevice, pidIdx, timeoutMs);
698        }
699
700        /**
701         * Select the feedback device for the motor controller.
702         *
703         * @param feedbackDevice
704         *            Feedback Device to select.
705         * @param pidIdx
706         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
707         * @param timeoutMs
708         *            Timeout value in ms. If nonzero, function will wait for
709         *            config success and report an error if it times out.
710         *            If zero, no blocking or checking is performed.
711         * @return Error Code generated by function. 0 indicates no error.
712         */
713        public ErrorCode configSelectedFeedbackSensor(FeedbackDevice feedbackDevice, int pidIdx, int timeoutMs) {
714                int retval = MotControllerJNI.ConfigSelectedFeedbackSensor(m_handle, feedbackDevice.value, pidIdx, timeoutMs);
715                return ErrorCode.valueOf(retval);
716        }
717        /**
718         * Select the feedback device for the motor controller.
719         *
720         * @param feedbackDevice
721         *            Feedback Device to select.
722         * @return Error Code generated by function. 0 indicates no error.
723         */
724        public ErrorCode configSelectedFeedbackSensor(FeedbackDevice feedbackDevice) {
725                int pidIdx = 0;
726                int timeoutMs = 0;
727                return configSelectedFeedbackSensor(feedbackDevice, pidIdx, timeoutMs);
728        }
729
730        /**
731         * The Feedback Coefficient is a scalar applied to the value of the
732         * feedback sensor.  Useful when you need to scale your sensor values
733         * within the closed-loop calculations.  Default value is 1.
734         *
735         * Selected Feedback Sensor register in firmware is the decoded sensor value
736         * multiplied by the Feedback Coefficient.
737         *
738         * @param coefficient
739         *            Feedback Coefficient value.  Maximum value of 1.
740         *                                              Resolution is 1/(2^16).  Cannot be 0.
741         * @param pidIdx
742         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
743         * @param timeoutMs
744         *            Timeout value in ms. If nonzero, function will wait for
745         *            config success and report an error if it times out.
746         *            If zero, no blocking or checking is performed.
747         * @return Error Code generated by function. 0 indicates no error.
748         */
749        public ErrorCode configSelectedFeedbackCoefficient(double coefficient, int pidIdx, int timeoutMs) {
750          int retval = MotControllerJNI.ConfigSelectedFeedbackCoefficient(m_handle, coefficient, pidIdx, timeoutMs);
751                return ErrorCode.valueOf(retval);
752        }
753        /**
754         * The Feedback Coefficient is a scalar applied to the value of the
755         * feedback sensor.  Useful when you need to scale your sensor values
756         * within the closed-loop calculations.  Default value is 1.
757         *
758         * Selected Feedback Sensor register in firmware is the decoded sensor value
759         * multiplied by the Feedback Coefficient.
760         *
761         * @param coefficient
762         *            Feedback Coefficient value.  Maximum value of 1.
763         *                                              Resolution is 1/(2^16).  Cannot be 0.
764         * @return Error Code generated by function. 0 indicates no error.
765         */
766        public ErrorCode configSelectedFeedbackCoefficient(double coefficient) {
767                int pidIdx = 0;
768        int timeoutMs = 0;
769                return configSelectedFeedbackCoefficient(coefficient, pidIdx, timeoutMs);
770        }
771        /**
772         * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
773         * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
774         * as a PID source for closed-loop features.
775         *
776         * @param deviceID
777         *            The device ID of the remote sensor device.
778         * @param remoteSensorSource
779         *            The remote sensor device and signal type to bind.
780         * @param remoteOrdinal
781         *            0 for configuring Remote Sensor 0,
782         *            1 for configuring Remote Sensor 1
783         * @param timeoutMs
784         *            Timeout value in ms. If nonzero, function will wait for
785         *            config success and report an error if it times out.
786         *            If zero, no blocking or checking is performed.
787         * @return Error Code generated by function. 0 indicates no error.
788         */
789        public ErrorCode configRemoteFeedbackFilter(int deviceID, RemoteSensorSource remoteSensorSource, int remoteOrdinal,
790                        int timeoutMs) {
791                int retval = MotControllerJNI.ConfigRemoteFeedbackFilter(m_handle, deviceID, remoteSensorSource.value, remoteOrdinal,
792                                timeoutMs);
793                return ErrorCode.valueOf(retval);
794        }
795        /**
796         * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
797         * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
798         * as a PID source for closed-loop features.
799         *
800         * @param deviceID
801         *            The device ID of the remote sensor device.
802         * @param remoteSensorSource
803         *            The remote sensor device and signal type to bind.
804         * @param remoteOrdinal
805         *            0 for configuring Remote Sensor 0,
806         *            1 for configuring Remote Sensor 1
807         * @return Error Code generated by function. 0 indicates no error.
808         */
809        public ErrorCode configRemoteFeedbackFilter(int deviceID, RemoteSensorSource remoteSensorSource, int remoteOrdinal) {
810        int timeoutMs = 0;
811                return configRemoteFeedbackFilter(deviceID, remoteSensorSource, remoteOrdinal, timeoutMs);
812        }
813        /**
814         * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
815         * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
816         * as a PID source for closed-loop features.
817         *
818         * @param canCoderRef
819         *            CANCoder device reference to use.
820         * @param remoteOrdinal
821         *            0 for configuring Remote Sensor 0,
822         *            1 for configuring Remote Sensor 1
823         * @param timeoutMs
824         *            Timeout value in ms. If nonzero, function will wait for
825         *            config success and report an error if it times out.
826         *            If zero, no blocking or checking is performed.
827         * @return Error Code generated by function. 0 indicates no error.
828         */
829        public ErrorCode configRemoteFeedbackFilter(CANCoder canCoderRef, int remoteOrdinal, int timeoutMs) {
830                return configRemoteFeedbackFilter(canCoderRef.getDeviceID(), RemoteSensorSource.CANCoder, remoteOrdinal, timeoutMs);
831        }
832        /**
833         * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
834         * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
835         * as a PID source for closed-loop features.
836         *
837         * @param canCoderRef
838         *            CANCoder device reference to use.
839         * @param remoteOrdinal
840         *            0 for configuring Remote Sensor 0,
841         *            1 for configuring Remote Sensor 1
842         * @return Error Code generated by function. 0 indicates no error.
843         */
844        public ErrorCode configRemoteFeedbackFilter(CANCoder canCoderRef, int remoteOrdinal) {
845                int timeoutMs = 0;
846                return configRemoteFeedbackFilter(canCoderRef, remoteOrdinal, timeoutMs);
847        }
848        /**
849         * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
850         * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
851         * as a PID source for closed-loop features.
852         *
853         * @param talonRef
854         *            Talon device reference to use.
855         * @param remoteOrdinal
856         *            0 for configuring Remote Sensor 0,
857         *            1 for configuring Remote Sensor 1
858         * @param timeoutMs
859         *            Timeout value in ms. If nonzero, function will wait for
860         *            config success and report an error if it times out.
861         *            If zero, no blocking or checking is performed.
862         * @return Error Code generated by function. 0 indicates no error.
863         */
864        public ErrorCode configRemoteFeedbackFilter(BaseTalon talonRef, int remoteOrdinal, int timeoutMs) {
865                return configRemoteFeedbackFilter(talonRef.getDeviceID(), RemoteSensorSource.TalonSRX_SelectedSensor, remoteOrdinal, timeoutMs);
866        }
867        /**
868         * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
869         * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
870         * as a PID source for closed-loop features.
871         *
872         * @param talonRef
873         *            Talon device reference to use.
874         * @param remoteOrdinal
875         *            0 for configuring Remote Sensor 0,
876         *            1 for configuring Remote Sensor 1
877         * @return Error Code generated by function. 0 indicates no error.
878         */
879        public ErrorCode configRemoteFeedbackFilter(BaseTalon talonRef, int remoteOrdinal) {
880                int timeoutMs = 0;
881                return configRemoteFeedbackFilter(talonRef, remoteOrdinal, timeoutMs);
882        }
883        /**
884         * Select what sensor term should be bound to switch feedback device.
885         * Sensor Sum = Sensor Sum Term 0 - Sensor Sum Term 1
886         * Sensor Difference = Sensor Diff Term 0 - Sensor Diff Term 1
887         * The four terms are specified with this routine.  Then Sensor Sum/Difference
888         * can be selected for closed-looping.
889         *
890         * @param sensorTerm Which sensor term to bind to a feedback source.
891         * @param feedbackDevice The sensor signal to attach to sensorTerm.
892         * @param timeoutMs
893         *            Timeout value in ms. If nonzero, function will wait for
894         *            config success and report an error if it times out.
895         *            If zero, no blocking or checking is performed.
896         * @return Error Code generated by function. 0 indicates no error.
897         */
898        public ErrorCode configSensorTerm(SensorTerm sensorTerm, FeedbackDevice feedbackDevice, int timeoutMs) {
899                int retval = MotControllerJNI.ConfigSensorTerm(m_handle, sensorTerm.value, feedbackDevice.value, timeoutMs);
900                return ErrorCode.valueOf(retval);
901        }
902        /**
903         * Select what sensor term should be bound to switch feedback device.
904         * Sensor Sum = Sensor Sum Term 0 - Sensor Sum Term 1
905         * Sensor Difference = Sensor Diff Term 0 - Sensor Diff Term 1
906         * The four terms are specified with this routine.  Then Sensor Sum/Difference
907         * can be selected for closed-looping.
908         *
909         * @param sensorTerm Which sensor term to bind to a feedback source.
910         * @param feedbackDevice The sensor signal to attach to sensorTerm.
911         * @return Error Code generated by function. 0 indicates no error.
912         */
913        public ErrorCode configSensorTerm(SensorTerm sensorTerm, FeedbackDevice feedbackDevice) {
914                int timeoutMs = 0;
915                return configSensorTerm(sensorTerm, feedbackDevice, timeoutMs);
916        }
917        /**
918         * Select what sensor term should be bound to switch feedback device.
919         * Sensor Sum = Sensor Sum Term 0 - Sensor Sum Term 1
920         * Sensor Difference = Sensor Diff Term 0 - Sensor Diff Term 1
921         * The four terms are specified with this routine.  Then Sensor Sum/Difference
922         * can be selected for closed-looping.
923         *
924         * @param sensorTerm Which sensor term to bind to a feedback source.
925         * @param feedbackDevice The sensor signal to attach to sensorTerm.
926         * @param timeoutMs
927         *            Timeout value in ms. If nonzero, function will wait for
928         *            config success and report an error if it times out.
929         *            If zero, no blocking or checking is performed.
930         * @return Error Code generated by function. 0 indicates no error.
931         */
932        public ErrorCode configSensorTerm(SensorTerm sensorTerm, RemoteFeedbackDevice feedbackDevice, int timeoutMs) {
933                return configSensorTerm(sensorTerm, feedbackDevice.getFeedbackDevice(), timeoutMs);
934        }
935        /**
936         * Select what sensor term should be bound to switch feedback device.
937         * Sensor Sum = Sensor Sum Term 0 - Sensor Sum Term 1
938         * Sensor Difference = Sensor Diff Term 0 - Sensor Diff Term 1
939         * The four terms are specified with this routine.  Then Sensor Sum/Difference
940         * can be selected for closed-looping.
941         *
942         * @param sensorTerm Which sensor term to bind to a feedback source.
943         * @param feedbackDevice The sensor signal to attach to sensorTerm.
944         * @return Error Code generated by function. 0 indicates no error.
945         */
946        public ErrorCode configSensorTerm(SensorTerm sensorTerm, RemoteFeedbackDevice feedbackDevice) {
947                int timeoutMs = 0;
948                return configSensorTerm(sensorTerm, feedbackDevice.getFeedbackDevice(), timeoutMs);
949        }
950
951        // ------- sensor status --------- //
952        /**
953         * Get the selected sensor position (in raw sensor units).
954         *
955         * @param pidIdx
956         *            0 for Primary closed-loop. 1 for auxiliary closed-loop. See
957         *            Phoenix-Documentation for how to interpret.
958         *
959         * @return Position of selected sensor (in raw sensor units).
960         */
961        public double getSelectedSensorPosition(int pidIdx) {
962                return (double)MotControllerJNI.GetSelectedSensorPosition(m_handle, pidIdx);
963        }
964        /**
965         * Get the selected sensor position (in raw sensor units).
966         *
967         * @return Position of selected sensor (in raw sensor units).
968         */
969        public double getSelectedSensorPosition() {
970                int pidIdx = 0;
971                return getSelectedSensorPosition(pidIdx);
972        }
973
974        /**
975         * Get the selected sensor velocity.
976         *
977         * @param pidIdx
978         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
979         * @return selected sensor (in raw sensor units) per 100ms.
980         * See Phoenix-Documentation for how to interpret.
981         */
982        public double getSelectedSensorVelocity(int pidIdx) {
983                return (double)MotControllerJNI.GetSelectedSensorVelocity(m_handle, pidIdx);
984        }
985        /**
986         * Get the selected sensor velocity.
987         *
988         * @return selected sensor (in raw sensor units) per 100ms.
989         * See Phoenix-Documentation for how to interpret.
990         */
991        public double getSelectedSensorVelocity() {
992                int pidIdx = 0;
993                return getSelectedSensorVelocity(pidIdx);
994        }
995
996        /**
997         * Sets the sensor position to the given value.
998         *
999         * @param sensorPos
1000         *            Position to set for the selected sensor (in raw sensor units).
1001         * @param pidIdx
1002         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
1003         * @param timeoutMs
1004         *            Timeout value in ms. If nonzero, function will wait for
1005         *            config success and report an error if it times out.
1006         *            If zero, no blocking or checking is performed.
1007         * @return Error Code generated by function. 0 indicates no error.
1008         */
1009        public ErrorCode setSelectedSensorPosition(double sensorPos, int pidIdx, int timeoutMs) {
1010                int retval = MotControllerJNI.SetSelectedSensorPosition(m_handle, (int)sensorPos, pidIdx, timeoutMs);
1011                return ErrorCode.valueOf(retval);
1012        }
1013        /**
1014         * Sets the sensor position to the given value.
1015         *
1016         * @param sensorPos
1017         *            Position to set for the selected sensor (in raw sensor units).
1018         * @return Error Code generated by function. 0 indicates no error.
1019         */
1020        public ErrorCode setSelectedSensorPosition(double sensorPos) {
1021                int pidIdx = 0;
1022                int timeoutMs = 0;
1023                return setSelectedSensorPosition(sensorPos, pidIdx, timeoutMs);
1024        }
1025
1026        // ------ status frame period changes ----------//
1027        /**
1028         * Sets the period of the given control frame.
1029         *
1030         * @param frame
1031         *            Frame whose period is to be changed.
1032         * @param periodMs
1033         *            Period in ms for the given frame.
1034         * @return Error Code generated by function. 0 indicates no error.
1035         */
1036        public ErrorCode setControlFramePeriod(ControlFrame frame, int periodMs) {
1037                int retval = MotControllerJNI.SetControlFramePeriod(m_handle, frame.value, periodMs);
1038                return ErrorCode.valueOf(retval);
1039        }
1040
1041        /**
1042         * Sets the period of the given status frame.
1043         *
1044         * User ensure CAN Bus utilization is not high.
1045         *
1046         * This setting is not persistent and is lost when device is reset.
1047         * If this is a concern, calling application can use hasResetOccurred()
1048         * to determine if the status frame needs to be reconfigured.
1049         *
1050         * @param frame
1051         *            Frame whose period is to be changed.
1052         * @param periodMs
1053         *            Period in ms for the given frame.
1054         * @return Error Code generated by function. 0 indicates no error.
1055         */
1056        public ErrorCode setControlFramePeriod(int frame, int periodMs) {
1057                int retval = MotControllerJNI.SetControlFramePeriod(m_handle, frame, periodMs);
1058                return ErrorCode.valueOf(retval);
1059        }
1060
1061        /**
1062         * Sets the period of the given status frame.
1063         *
1064         * User ensure CAN Bus utilization is not high.
1065         *
1066         * This setting is not persistent and is lost when device is reset. If this
1067         * is a concern, calling application can use hasResetOccurred() to determine if the
1068         * status frame needs to be reconfigured.
1069         *
1070         * @param frameValue
1071         *            Frame whose period is to be changed.
1072         * @param periodMs
1073         *            Period in ms for the given frame.
1074         * @param timeoutMs
1075         *            Timeout value in ms. If nonzero, function will wait for config
1076         *            success and report an error if it times out. If zero, no
1077         *            blocking or checking is performed.
1078         * @return Error Code generated by function. 0 indicates no error.
1079         */
1080        public ErrorCode setStatusFramePeriod(int frameValue, int periodMs, int timeoutMs) {
1081                int retval = MotControllerJNI.SetStatusFramePeriod(m_handle, frameValue, periodMs, timeoutMs);
1082                return ErrorCode.valueOf(retval);
1083        }
1084        /**
1085         * Sets the period of the given status frame.
1086         *
1087         * User ensure CAN Bus utilization is not high.
1088         *
1089         * This setting is not persistent and is lost when device is reset. If this
1090         * is a concern, calling application can use hasResetOccurred() to determine if the
1091         * status frame needs to be reconfigured.
1092         *
1093         * @param frameValue
1094         *            Frame whose period is to be changed.
1095         * @param periodMs
1096         *            Period in ms for the given frame.
1097         * @return Error Code generated by function. 0 indicates no error.
1098         */
1099        public ErrorCode setStatusFramePeriod(int frameValue, int periodMs) {
1100                int timeoutMs = 0;
1101                return  setStatusFramePeriod(frameValue, periodMs,timeoutMs);
1102        }
1103
1104        /**
1105         * Sets the period of the given status frame.
1106         *
1107         * @param frame
1108         *            Frame whose period is to be changed.
1109         * @param periodMs
1110         *            Period in ms for the given frame.
1111         * @param timeoutMs
1112         *            Timeout value in ms. If nonzero, function will wait for
1113         *            config success and report an error if it times out.
1114         *            If zero, no blocking or checking is performed.
1115         * @return Error Code generated by function. 0 indicates no error.
1116         */
1117        public ErrorCode setStatusFramePeriod(StatusFrame frame, int periodMs, int timeoutMs) {
1118                return setStatusFramePeriod(frame.value, periodMs, timeoutMs);
1119        }
1120        /**
1121         * Sets the period of the given status frame.
1122         *
1123         * @param frame
1124         *            Frame whose period is to be changed.
1125         * @param periodMs
1126         *            Period in ms for the given frame.
1127         * @return Error Code generated by function. 0 indicates no error.
1128         */
1129        public ErrorCode setStatusFramePeriod(StatusFrame frame, int periodMs) {
1130                int timeoutMs = 0;
1131                return setStatusFramePeriod(frame,periodMs, timeoutMs);
1132        }
1133
1134        /**
1135         * Gets the period of the given status frame.
1136         *
1137         * @param frame
1138         *            Frame to get the period of.
1139         * @param timeoutMs
1140         *            Timeout value in ms. If nonzero, function will wait for
1141         *            config success and report an error if it times out.
1142         *            If zero, no blocking or checking is performed.
1143         * @return Period of the given status frame.
1144         */
1145        public int getStatusFramePeriod(int frame, int timeoutMs) {
1146                return MotControllerJNI.GetStatusFramePeriod(m_handle, frame, timeoutMs);
1147        }
1148        /**
1149         * Gets the period of the given status frame.
1150         *
1151         * @param frame
1152         *            Frame to get the period of.
1153         * @return Period of the given status frame.
1154         */
1155        public int getStatusFramePeriod(int frame) {
1156                int timeoutMs = 0;
1157                return getStatusFramePeriod(frame, timeoutMs);
1158        }
1159
1160        /**
1161         * Gets the period of the given status frame.
1162         *
1163         * @param frame
1164         *            Frame to get the period of.
1165         * @param timeoutMs
1166         *            Timeout value in ms. If nonzero, function will wait for
1167         *            config success and report an error if it times out.
1168         *            If zero, no blocking or checking is performed.
1169         * @return Period of the given status frame.
1170         */
1171        public int getStatusFramePeriod(StatusFrame frame, int timeoutMs) {
1172                return MotControllerJNI.GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
1173        }
1174        /**
1175         * Gets the period of the given status frame.
1176         *
1177         * @param frame
1178         *            Frame to get the period of.
1179         * @return Period of the given status frame.
1180         */
1181        public int getStatusFramePeriod(StatusFrame frame) {
1182                int timeoutMs = 0;
1183                return getStatusFramePeriod(frame, timeoutMs);
1184        }
1185
1186        /**
1187         * Gets the period of the given status frame.
1188         *
1189         * @param frame
1190         *            Frame to get the period of.
1191         * @param timeoutMs
1192         *            Timeout value in ms. If nonzero, function will wait for
1193         *            config success and report an error if it times out.
1194         *            If zero, no blocking or checking is performed.
1195         * @return Period of the given status frame.
1196         */
1197        public int getStatusFramePeriod(StatusFrameEnhanced frame, int timeoutMs) {
1198                return MotControllerJNI.GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
1199        }
1200        /**
1201         * Gets the period of the given status frame.
1202         *
1203         * @param frame
1204         *            Frame to get the period of.
1205         * @return Period of the given status frame.
1206         */
1207        public int getStatusFramePeriod(StatusFrameEnhanced frame) {
1208                int timeoutMs = 0;
1209                return  getStatusFramePeriod(frame, timeoutMs);
1210        }
1211
1212        // ----- velocity signal conditionaing ------//
1213
1214        /**
1215         * Sets the period over which velocity measurements are taken.
1216         *
1217         * @param period
1218         *            Desired period for the velocity measurement. @see
1219         *            com.ctre.phoenix.sensors.SensorVelocityMeasPeriod
1220         * @param timeoutMs
1221         *            Timeout value in ms. If nonzero, function will wait for
1222         *            config success and report an error if it times out.
1223         *            If zero, no blocking or checking is performed.
1224         * @return Error Code generated by function. 0 indicates no error.
1225         */
1226        public ErrorCode configVelocityMeasurementPeriod(SensorVelocityMeasPeriod period, int timeoutMs) {
1227                int retval = MotControllerJNI.ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
1228                return ErrorCode.valueOf(retval);
1229        }
1230        /**
1231         * Sets the period over which velocity measurements are taken.
1232         *
1233         * @deprecated Use the overload with SensorVelocityMeasPeriod instead.
1234         *
1235         * @param period
1236         *            Desired period for the velocity measurement. @see
1237         *            com.ctre.phoenix.motorcontrol.VelocityMeasPeriod
1238         * @param timeoutMs
1239         *            Timeout value in ms. If nonzero, function will wait for
1240         *            config success and report an error if it times out.
1241         *            If zero, no blocking or checking is performed.
1242         * @return Error Code generated by function. 0 indicates no error.
1243         */
1244        @Deprecated
1245        public ErrorCode configVelocityMeasurementPeriod(VelocityMeasPeriod period, int timeoutMs) {
1246                int retval = MotControllerJNI.ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
1247                return ErrorCode.valueOf(retval);
1248        }
1249        /**
1250         * Sets the period over which velocity measurements are taken.
1251         *
1252         * @param period
1253         *            Desired period for the velocity measurement. @see
1254         *            com.ctre.phoenix.sensors.SensorVelocityMeasPeriod
1255         * @return Error Code generated by function. 0 indicates no error.
1256         */
1257        public ErrorCode configVelocityMeasurementPeriod(SensorVelocityMeasPeriod period) {
1258                int timeoutMs = 0;
1259                return configVelocityMeasurementPeriod(period, timeoutMs);
1260        }
1261        /**
1262         * Sets the period over which velocity measurements are taken.
1263         *
1264         * @deprecated Use the overload with SensorVelocityMeasPeriod instead.
1265         *
1266         * @param period
1267         *            Desired period for the velocity measurement. @see
1268         *            com.ctre.phoenix.motorcontrol.VelocityMeasPeriod
1269         * @return Error Code generated by function. 0 indicates no error.
1270         */
1271        @Deprecated
1272        public ErrorCode configVelocityMeasurementPeriod(VelocityMeasPeriod period) {
1273                int timeoutMs = 0;
1274                return configVelocityMeasurementPeriod(period, timeoutMs);
1275        }
1276
1277        /**
1278         * Sets the number of velocity samples used in the rolling average velocity
1279         * measurement.
1280         *
1281         * @param windowSize
1282         *            Number of samples in the rolling average of velocity
1283         *            measurement. Valid values are 1,2,4,8,16,32. If another value
1284         *            is specified, it will truncate to nearest support value.
1285         * @param timeoutMs
1286         *            Timeout value in ms. If nonzero, function will wait for config
1287         *            success and report an error if it times out. If zero, no
1288         *            blocking or checking is performed.
1289         * @return Error Code generated by function. 0 indicates no error.
1290         */
1291        public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs) {
1292                int retval = MotControllerJNI.ConfigVelocityMeasurementWindow(m_handle, windowSize, timeoutMs);
1293                return ErrorCode.valueOf(retval);
1294        }
1295        /**
1296         * Sets the number of velocity samples used in the rolling average velocity
1297         * measurement.
1298         *
1299         * @param windowSize
1300         *            Number of samples in the rolling average of velocity
1301         *            measurement. Valid values are 1,2,4,8,16,32. If another value
1302         *            is specified, it will truncate to nearest support value.
1303         * @return Error Code generated by function. 0 indicates no error.
1304         */
1305        public ErrorCode configVelocityMeasurementWindow(int windowSize) {
1306                int timeoutMs = 0;
1307                return configVelocityMeasurementWindow(windowSize, timeoutMs);
1308        }
1309
1310        // ------ remote limit switch ----------//
1311        /**
1312         * Configures the forward limit switch for a remote source. For example, a
1313         * CAN motor controller may need to monitor the Limit-F pin of another Talon
1314         * or CANifier.
1315         *
1316         * @param type
1317         *            Remote limit switch source. User can choose between a remote
1318         *            Talon SRX, CANifier, or deactivate the feature.
1319         * @param normalOpenOrClose
1320         *            Setting for normally open, normally closed, or disabled. This
1321         *            setting matches the Phoenix Tuner drop down.
1322         * @param deviceID
1323         *            Device ID of remote source (Talon SRX or CANifier device ID).
1324         * @param timeoutMs
1325         *            Timeout value in ms. If nonzero, function will wait for config
1326         *            success and report an error if it times out. If zero, no
1327         *            blocking or checking is performed.
1328         * @return Error Code generated by function. 0 indicates no error.
1329         */
1330        public ErrorCode configForwardLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
1331                        int deviceID, int timeoutMs) {
1332                return configForwardLimitSwitchSource(type.value, normalOpenOrClose.value, deviceID, timeoutMs);
1333        }
1334        /**
1335         * Configures the forward limit switch for a remote source. For example, a
1336         * CAN motor controller may need to monitor the Limit-F pin of another Talon
1337         * or CANifier.
1338         *
1339         * @param type
1340         *            Remote limit switch source. User can choose between a remote
1341         *            Talon SRX, CANifier, or deactivate the feature.
1342         * @param normalOpenOrClose
1343         *            Setting for normally open, normally closed, or disabled. This
1344         *            setting matches the Phoenix Tuner drop down.
1345         * @param deviceID
1346         *            Device ID of remote source (Talon SRX or CANifier device ID).
1347         * @return Error Code generated by function. 0 indicates no error.
1348         */
1349        public ErrorCode configForwardLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
1350                        int deviceID) {
1351                int timeoutMs = 0;
1352                return configForwardLimitSwitchSource(type, normalOpenOrClose, deviceID, timeoutMs);
1353        }
1354
1355        /**
1356         * Configures the reverse limit switch for a remote source. For example, a
1357         * CAN motor controller may need to monitor the Limit-R pin of another Talon
1358         * or CANifier.
1359         *
1360         * @param type
1361         *            Remote limit switch source. User can choose between a remote
1362         *            Talon SRX, CANifier, or deactivate the feature.
1363         * @param normalOpenOrClose
1364         *            Setting for normally open, normally closed, or disabled. This
1365         *            setting matches the Phoenix Tuner drop down.
1366         * @param deviceID
1367         *            Device ID of remote source (Talon SRX or CANifier device ID).
1368         * @param timeoutMs
1369         *            Timeout value in ms. If nonzero, function will wait for config
1370         *            success and report an error if it times out. If zero, no
1371         *            blocking or checking is performed.
1372         * @return Error Code generated by function. 0 indicates no error.
1373         */
1374        public ErrorCode configReverseLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
1375                        int deviceID, int timeoutMs) {
1376                int retval = MotControllerJNI.ConfigReverseLimitSwitchSource(m_handle, type.value, normalOpenOrClose.value,
1377                                deviceID, timeoutMs);
1378                return ErrorCode.valueOf(retval);
1379        }
1380        /**
1381         * Configures the reverse limit switch for a remote source. For example, a
1382         * CAN motor controller may need to monitor the Limit-R pin of another Talon
1383         * or CANifier.
1384         *
1385         * @param type
1386         *            Remote limit switch source. User can choose between a remote
1387         *            Talon SRX, CANifier, or deactivate the feature.
1388         * @param normalOpenOrClose
1389         *            Setting for normally open, normally closed, or disabled. This
1390         *            setting matches the Phoenix Tuner drop down.
1391         * @param deviceID
1392         *            Device ID of remote source (Talon SRX or CANifier device ID).
1393         * @return Error Code generated by function. 0 indicates no error.
1394         */
1395        public ErrorCode configReverseLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
1396                        int deviceID) {
1397                int timeoutMs = 0;
1398                return configReverseLimitSwitchSource(type, normalOpenOrClose, deviceID, timeoutMs);
1399        }
1400
1401        /**
1402         * Configures a limit switch for a local/remote source.
1403         *
1404         * For example, a CAN motor controller may need to monitor the Limit-R pin
1405         * of another Talon, CANifier, or local Gadgeteer feedback connector.
1406         *
1407         * If the sensor is remote, a device ID of zero is assumed. If that's not
1408         * desired, use the four parameter version of this function.
1409         *
1410         * @param type
1411         *            Limit switch source. @see com.ctre.phoenix.motorcontrol.LimitSwitchSource User can choose
1412         *            between the feedback connector, remote Talon SRX, CANifier, or
1413         *            deactivate the feature.
1414         * @param normalOpenOrClose
1415         *            Setting for normally open, normally closed, or disabled. This
1416         *            setting matches the Phoenix Tuner drop down.
1417         * @param timeoutMs
1418         *            Timeout value in ms. If nonzero, function will wait for config
1419         *            success and report an error if it times out. If zero, no
1420         *            blocking or checking is performed.
1421         * @return Error Code generated by function. 0 indicates no error.
1422         */
1423        public ErrorCode configForwardLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
1424                        int timeoutMs) {
1425                return configForwardLimitSwitchSource(type.value, normalOpenOrClose.value, -1, timeoutMs);
1426        }
1427        /**
1428         * Configures a limit switch for a local/remote source.
1429         *
1430         * For example, a CAN motor controller may need to monitor the Limit-R pin
1431         * of another Talon, CANifier, or local Gadgeteer feedback connector.
1432         *
1433         * If the sensor is remote, a device ID of zero is assumed. If that's not
1434         * desired, use the four parameter version of this function.
1435         *
1436         * @param type
1437         *            Limit switch source. @see com.ctre.phoenix.motorcontrol.LimitSwitchSource User can choose
1438         *            between the feedback connector, remote Talon SRX, CANifier, or
1439         *            deactivate the feature.
1440         * @param normalOpenOrClose
1441         *            Setting for normally open, normally closed, or disabled. This
1442         *            setting matches the Phoenix Tuner drop down.
1443         * @return Error Code generated by function. 0 indicates no error.
1444         */
1445        public ErrorCode configForwardLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose) {
1446                int timeoutMs = 0;
1447                return configForwardLimitSwitchSource(type, normalOpenOrClose, timeoutMs);
1448        }
1449
1450        /**
1451         * Configures a limit switch for a local/remote source.
1452         *
1453         * For example, a CAN motor controller may need to monitor the Limit-R pin
1454         * of another Talon, CANifier, or local Gadgeteer feedback connector.
1455         *
1456         * If the sensor is remote, a device ID of zero is assumed. If that's not
1457         * desired, use the four parameter version of this function.
1458         *
1459         * @param typeValue
1460         *            Limit switch source. @see com.ctre.phoenix.motorcontrol.LimitSwitchSource User can choose
1461         *            between the feedback connector, remote Talon SRX, CANifier, or
1462         *            deactivate the feature.
1463         * @param normalOpenOrCloseValue
1464         *            Setting for normally open, normally closed, or disabled. This
1465         *            setting matches the Phoenix Tuner drop down.
1466         * @param deviceID
1467         *            Device ID of remote source (Talon SRX or CANifier device ID).
1468         * @param timeoutMs
1469         *            Timeout value in ms. If nonzero, function will wait for config
1470         *            success and report an error if it times out. If zero, no
1471         *            blocking or checking is performed.
1472         * @return Error Code generated by function. 0 indicates no error.
1473         */
1474        protected ErrorCode configForwardLimitSwitchSource(int typeValue, int normalOpenOrCloseValue, int deviceID,
1475                        int timeoutMs) {
1476                int retval = MotControllerJNI.ConfigForwardLimitSwitchSource(m_handle, typeValue, normalOpenOrCloseValue,
1477                                deviceID, timeoutMs);
1478                return ErrorCode.valueOf(retval);
1479        }
1480
1481        /**
1482         * Configures a limit switch for a local/remote source.
1483         *
1484         * For example, a CAN motor controller may need to monitor the Limit-R pin
1485         * of another Talon, CANifier, or local Gadgeteer feedback connector.
1486         *
1487         * If the sensor is remote, a device ID of zero is assumed. If that's not
1488         * desired, use the four parameter version of this function.
1489         *
1490         * @param typeValue
1491         *            Limit switch source. @see com.ctre.phoenix.motorcontrol.LimitSwitchSource User can choose
1492         *            between the feedback connector, remote Talon SRX, CANifier, or
1493         *            deactivate the feature.
1494         * @param normalOpenOrCloseValue
1495         *            Setting for normally open, normally closed, or disabled. This
1496         *            setting matches the Phoenix Tuner drop down.
1497         * @param deviceID
1498         *            The device ID of the remote sensor device.
1499         * @param timeoutMs
1500         *            Timeout value in ms. If nonzero, function will wait for config
1501         *            success and report an error if it times out. If zero, no
1502         *            blocking or checking is performed.
1503         * @return Error Code generated by function. 0 indicates no error.
1504         */
1505        protected ErrorCode configReverseLimitSwitchSource(int typeValue, int normalOpenOrCloseValue, int deviceID,
1506                        int timeoutMs) {
1507                int retval = MotControllerJNI.ConfigReverseLimitSwitchSource(m_handle, typeValue, normalOpenOrCloseValue,
1508                                deviceID, timeoutMs);
1509                return ErrorCode.valueOf(retval);
1510        }
1511
1512        /**
1513         * Sets the enable state for limit switches.
1514         *
1515         * @param enable
1516         *            Enable state for limit switches.
1517         **/
1518        public void overrideLimitSwitchesEnable(boolean enable) {
1519                MotControllerJNI.OverrideLimitSwitchesEnable(m_handle, enable);
1520        }
1521
1522        // ------ soft limit ----------//
1523        /**
1524         * Configures the forward soft limit threhold.
1525         *
1526         * @param forwardSensorLimit
1527         *            Forward Sensor Position Limit (in raw sensor units).
1528         * @param timeoutMs
1529         *            Timeout value in ms. If nonzero, function will wait for
1530         *            config success and report an error if it times out.
1531         *            If zero, no blocking or checking is performed.
1532         * @return Error Code generated by function. 0 indicates no error.
1533         */
1534        public ErrorCode configForwardSoftLimitThreshold(double forwardSensorLimit, int timeoutMs) {
1535                int retval = MotControllerJNI.ConfigForwardSoftLimitThreshold(m_handle, (int)forwardSensorLimit, timeoutMs);
1536                return ErrorCode.valueOf(retval);
1537        }
1538        /**
1539         * Configures the forward soft limit threhold.
1540         *
1541         * @param forwardSensorLimit
1542         *            Forward Sensor Position Limit (in raw sensor units).
1543         * @return Error Code generated by function. 0 indicates no error.
1544         */
1545        public ErrorCode configForwardSoftLimitThreshold(double forwardSensorLimit) {
1546                int timeoutMs = 0;
1547                return configForwardSoftLimitThreshold(forwardSensorLimit, timeoutMs);
1548        }
1549
1550        /**
1551         * Configures the reverse soft limit threshold.
1552         *
1553         * @param reverseSensorLimit
1554         *            Reverse Sensor Position Limit (in raw sensor units).
1555         * @param timeoutMs
1556         *            Timeout value in ms. If nonzero, function will wait for
1557         *            config success and report an error if it times out.
1558         *            If zero, no blocking or checking is performed.
1559         * @return Error Code generated by function. 0 indicates no error.
1560         */
1561        public ErrorCode configReverseSoftLimitThreshold(double reverseSensorLimit, int timeoutMs) {
1562                int retval = MotControllerJNI.ConfigReverseSoftLimitThreshold(m_handle, (int)reverseSensorLimit, timeoutMs);
1563                return ErrorCode.valueOf(retval);
1564        }
1565        /**
1566         * Configures the reverse soft limit threshold.
1567         *
1568         * @param reverseSensorLimit
1569         *            Reverse Sensor Position Limit (in raw sensor units).
1570         * @return Error Code generated by function. 0 indicates no error.
1571         */
1572        public ErrorCode configReverseSoftLimitThreshold(double reverseSensorLimit) {
1573                int timeoutMs = 0;
1574                return configReverseSoftLimitThreshold(reverseSensorLimit, timeoutMs);
1575        }
1576
1577        /**
1578         * Configures the forward soft limit enable.
1579         *
1580         * @param enable
1581         *            Forward Sensor Position Limit Enable.
1582         * @param timeoutMs
1583         *            Timeout value in ms. If nonzero, function will wait for
1584         *            config success and report an error if it times out.
1585         *            If zero, no blocking or checking is performed.
1586         * @return Error Code generated by function. 0 indicates no error.
1587         */
1588        public ErrorCode configForwardSoftLimitEnable(boolean enable, int timeoutMs) {
1589                int retval = MotControllerJNI.ConfigForwardSoftLimitEnable(m_handle, enable, timeoutMs);
1590                return ErrorCode.valueOf(retval);
1591        }
1592        /**
1593         * Configures the forward soft limit enable.
1594         *
1595         * @param enable
1596         *            Forward Sensor Position Limit Enable.
1597         * @return Error Code generated by function. 0 indicates no error.
1598         */
1599        public ErrorCode configForwardSoftLimitEnable(boolean enable) {
1600                int timeoutMs = 0;
1601                return configForwardSoftLimitEnable(enable, timeoutMs);
1602        }
1603
1604        /**
1605         * Configures the reverse soft limit enable.
1606         *
1607         * @param enable
1608         *            Reverse Sensor Position Limit Enable.
1609         * @param timeoutMs
1610         *            Timeout value in ms. If nonzero, function will wait for config
1611         *            success and report an error if it times out. If zero, no
1612         *            blocking or checking is performed.
1613         * @return Error Code generated by function. 0 indicates no error.
1614         */
1615        public ErrorCode configReverseSoftLimitEnable(boolean enable, int timeoutMs) {
1616                int retval = MotControllerJNI.ConfigReverseSoftLimitEnable(m_handle, enable, timeoutMs);
1617                return ErrorCode.valueOf(retval);
1618        }
1619        /**
1620         * Configures the reverse soft limit enable.
1621         *
1622         * @param enable
1623         *            Reverse Sensor Position Limit Enable.
1624         * @return Error Code generated by function. 0 indicates no error.
1625         */
1626        public ErrorCode configReverseSoftLimitEnable(boolean enable) {
1627                int timeoutMs = 0;
1628                return configReverseSoftLimitEnable(enable, timeoutMs);
1629        }
1630
1631        /**
1632         * Can be used to override-disable the soft limits.
1633         * This function can be used to quickly disable soft limits without
1634         * having to modify the persistent configuration.
1635         *
1636         * @param enable
1637         *            Enable state for soft limit switches.
1638         */
1639        public void overrideSoftLimitsEnable(boolean enable) {
1640                MotControllerJNI.OverrideSoftLimitsEnable(m_handle, enable);
1641        }
1642
1643        // ------ Current Lim ----------//
1644        /* not available in base */
1645
1646        // ------ General Close loop ----------//
1647        /**
1648         * Sets the 'P' constant in the given parameter slot.
1649         * This is multiplied by closed loop error in sensor units.
1650         * Note the closed loop output interprets a final value of 1023 as full output.
1651         * So use a gain of '0.25' to get full output if err is 4096u (Mag Encoder 1 rotation)
1652         *
1653         * @param slotIdx
1654         *            Parameter slot for the constant.
1655         * @param value
1656         *            Value of the P constant.
1657         * @param timeoutMs
1658         *            Timeout value in ms. If nonzero, function will wait for
1659         *            config success and report an error if it times out.
1660         *            If zero, no blocking or checking is performed.
1661         * @return Error Code generated by function. 0 indicates no error.
1662         */
1663        public ErrorCode config_kP(int slotIdx, double value, int timeoutMs) {
1664                int retval = MotControllerJNI.Config_kP(m_handle, slotIdx,  value, timeoutMs);
1665                return ErrorCode.valueOf(retval);
1666        }
1667        /**
1668         * Sets the 'P' constant in the given parameter slot.
1669         * This is multiplied by closed loop error in sensor units.
1670         * Note the closed loop output interprets a final value of 1023 as full output.
1671         * So use a gain of '0.25' to get full output if err is 4096u (Mag Encoder 1 rotation)
1672         *
1673         * @param slotIdx
1674         *            Parameter slot for the constant.
1675         * @param value
1676         *            Value of the P constant.
1677         * @return Error Code generated by function. 0 indicates no error.
1678         */
1679        public ErrorCode config_kP(int slotIdx, double value) {
1680                int timeoutMs = 0;
1681                return config_kP( slotIdx,  value,  timeoutMs);
1682        }
1683
1684        /**
1685         * Sets the 'I' constant in the given parameter slot.
1686         * This is multiplied by accumulated closed loop error in sensor units every PID Loop.
1687         * Note the closed loop output interprets a final value of 1023 as full output.
1688         * So use a gain of '0.00025' to get full output if err is 4096u for 1000 loops (accumulater holds 4,096,000),
1689         * [which is equivalent to one CTRE mag encoder rotation for 1000 milliseconds].
1690         *
1691         * @param slotIdx
1692         *            Parameter slot for the constant.
1693         * @param value
1694         *            Value of the I constant.
1695         * @param timeoutMs
1696         *            Timeout value in ms. If nonzero, function will wait for
1697         *            config success and report an error if it times out.
1698         *            If zero, no blocking or checking is performed.
1699         * @return Error Code generated by function. 0 indicates no error.
1700         */
1701        public ErrorCode config_kI(int slotIdx, double value, int timeoutMs) {
1702                int retval = MotControllerJNI.Config_kI(m_handle, slotIdx,  value, timeoutMs);
1703                return ErrorCode.valueOf(retval);
1704        }
1705        /**
1706         * Sets the 'I' constant in the given parameter slot.
1707         * This is multiplied by accumulated closed loop error in sensor units every PID Loop.
1708         * Note the closed loop output interprets a final value of 1023 as full output.
1709         * So use a gain of '0.00025' to get full output if err is 4096u for 1000 loops (accumulater holds 4,096,000),
1710         * [which is equivalent to one CTRE mag encoder rotation for 1000 milliseconds].
1711         *
1712         * @param slotIdx
1713         *            Parameter slot for the constant.
1714         * @param value
1715         *            Value of the I constant.
1716         * @return Error Code generated by function. 0 indicates no error.
1717         */
1718        public ErrorCode config_kI(int slotIdx, double value) {
1719        int timeoutMs = 0;
1720
1721                return config_kI( slotIdx,  value,  timeoutMs);
1722        }
1723
1724        /**
1725         * Sets the 'D' constant in the given parameter slot.
1726         *
1727         * This is multiplied by derivative error (sensor units per PID loop, typically 1ms).
1728         * Note the closed loop output interprets a final value of 1023 as full output.
1729         * So use a gain of '250' to get full output if derr is 4096u (Mag Encoder 1 rotation) per 1000 loops (typ 1 sec)
1730         *
1731         * @param slotIdx
1732         *            Parameter slot for the constant.
1733         * @param value
1734         *            Value of the D constant.
1735         * @param timeoutMs
1736         *            Timeout value in ms. If nonzero, function will wait for
1737         *            config success and report an error if it times out.
1738         *            If zero, no blocking or checking is performed.
1739         * @return Error Code generated by function. 0 indicates no error.
1740         */
1741        public ErrorCode config_kD(int slotIdx, double value, int timeoutMs) {
1742                int retval = MotControllerJNI.Config_kD(m_handle, slotIdx,  value, timeoutMs);
1743                return ErrorCode.valueOf(retval);
1744        }
1745        /**
1746         * Sets the 'D' constant in the given parameter slot.
1747         *
1748         * This is multiplied by derivative error (sensor units per PID loop, typically 1ms).
1749         * Note the closed loop output interprets a final value of 1023 as full output.
1750         * So use a gain of '250' to get full output if derr is 4096u (Mag Encoder 1 rotation) per 1000 loops (typ 1 sec)
1751         *
1752         * @param slotIdx
1753         *            Parameter slot for the constant.
1754         * @param value
1755         *            Value of the D constant.
1756         * @return Error Code generated by function. 0 indicates no error.
1757         */
1758        public ErrorCode config_kD(int slotIdx, double value) {
1759        int timeoutMs = 0;
1760                return config_kD( slotIdx,  value,  timeoutMs);
1761        }
1762
1763        /**
1764         * Sets the 'F' constant in the given parameter slot.
1765         *
1766         * See documentation for calculation details.
1767         * If using velocity, motion magic, or motion profile,
1768         * use (1023 * duty-cycle / sensor-velocity-sensor-units-per-100ms).
1769         *
1770         * @param slotIdx
1771         *            Parameter slot for the constant.
1772         * @param value
1773         *            Value of the F constant.
1774         * @param timeoutMs
1775         *            Timeout value in ms. If nonzero, function will wait for
1776         *            config success and report an error if it times out.
1777         *            If zero, no blocking or checking is performed.
1778         * @return Error Code generated by function. 0 indicates no error.
1779         */
1780        public ErrorCode config_kF(int slotIdx, double value, int timeoutMs) {
1781                int retval = MotControllerJNI.Config_kF(m_handle, slotIdx,  value, timeoutMs);
1782                return ErrorCode.valueOf(retval);
1783        }
1784        /**
1785         * Sets the 'F' constant in the given parameter slot.
1786         *
1787         * See documentation for calculation details.
1788         * If using velocity, motion magic, or motion profile,
1789         * use (1023 * duty-cycle / sensor-velocity-sensor-units-per-100ms).
1790         *
1791         * @param slotIdx
1792         *            Parameter slot for the constant.
1793         * @param value
1794         *            Value of the F constant.
1795         * @return Error Code generated by function. 0 indicates no error.
1796         */
1797        public ErrorCode config_kF(int slotIdx,  double value) {
1798        int timeoutMs = 0;
1799                return config_kF( slotIdx,  value,  timeoutMs);
1800        }
1801
1802        /**
1803         * Sets the Integral Zone constant in the given parameter slot. If the
1804         * (absolute) closed-loop error is outside of this zone, integral
1805         * accumulator is automatically cleared. This ensures than integral wind up
1806         * events will stop after the sensor gets far enough from its target.
1807         *
1808         * @param slotIdx
1809         *            Parameter slot for the constant.
1810         * @param izone
1811         *            Value of the Integral Zone constant (closed loop error units X
1812         *            1ms).
1813         * @param timeoutMs
1814         *            Timeout value in ms. If nonzero, function will wait for config
1815         *            success and report an error if it times out. If zero, no
1816         *            blocking or checking is performed.
1817         * @return Error Code generated by function. 0 indicates no error.
1818         */
1819        public ErrorCode config_IntegralZone(int slotIdx, double izone, int timeoutMs) {
1820                int retval = MotControllerJNI.Config_IntegralZone(m_handle, slotIdx,  (int)izone, timeoutMs);
1821                return ErrorCode.valueOf(retval);
1822        }
1823        /**
1824         * Sets the Integral Zone constant in the given parameter slot. If the
1825         * (absolute) closed-loop error is outside of this zone, integral
1826         * accumulator is automatically cleared. This ensures than integral wind up
1827         * events will stop after the sensor gets far enough from its target.
1828         *
1829         * @param slotIdx
1830         *            Parameter slot for the constant.
1831         * @param izone
1832         *            Value of the Integral Zone constant (closed loop error units X
1833         *            1ms).
1834         * @return Error Code generated by function. 0 indicates no error.
1835         */
1836        public ErrorCode config_IntegralZone(int slotIdx, double izone) {
1837        int timeoutMs = 0;
1838                return config_IntegralZone( slotIdx,  izone,  timeoutMs);
1839        }
1840
1841        /**
1842         * Sets the allowable closed-loop error in the given parameter slot.
1843         *
1844         * @param slotIdx
1845         *            Parameter slot for the constant.
1846         * @param allowableClosedLoopError
1847         *            Value of the allowable closed-loop error in sensor units (or sensor units per 100ms for velocity).
1848         * @param timeoutMs
1849         *            Timeout value in ms. If nonzero, function will wait for
1850         *            config success and report an error if it times out.
1851         *            If zero, no blocking or checking is performed.
1852         * @return Error Code generated by function. 0 indicates no error.
1853         */
1854        public ErrorCode configAllowableClosedloopError(int slotIdx, double allowableClosedLoopError, int timeoutMs) {
1855                int retval = MotControllerJNI.ConfigAllowableClosedloopError(m_handle, slotIdx, (int)allowableClosedLoopError,
1856                                timeoutMs);
1857                return ErrorCode.valueOf(retval);
1858        }
1859        /**
1860         * Sets the allowable closed-loop error in the given parameter slot.
1861         *
1862         * @param slotIdx
1863         *            Parameter slot for the constant.
1864         * @param allowableClosedLoopError
1865         *            Value of the allowable closed-loop error in sensor units (or sensor units per 100ms for velocity).
1866         * @return Error Code generated by function. 0 indicates no error.
1867         */
1868        public ErrorCode configAllowableClosedloopError(int slotIdx, double allowableClosedLoopError) {
1869        int timeoutMs = 0;
1870
1871                return configAllowableClosedloopError( slotIdx,  allowableClosedLoopError,  timeoutMs);
1872        }
1873
1874        /**
1875         * Sets the maximum integral accumulator in the given parameter slot.
1876         *
1877         * @param slotIdx
1878         *            Parameter slot for the constant.
1879         * @param iaccum
1880         *            Value of the maximum integral accumulator (closed loop error
1881         *            units X 1ms).
1882         * @param timeoutMs
1883         *            Timeout value in ms. If nonzero, function will wait for config
1884         *            success and report an error if it times out. If zero, no
1885         *            blocking or checking is performed.
1886         * @return Error Code generated by function. 0 indicates no error.
1887         */
1888        public ErrorCode configMaxIntegralAccumulator(int slotIdx, double iaccum, int timeoutMs) {
1889                int retval = MotControllerJNI.ConfigMaxIntegralAccumulator(m_handle, slotIdx, iaccum, timeoutMs);
1890                return ErrorCode.valueOf(retval);
1891        }
1892        /**
1893         * Sets the maximum integral accumulator in the given parameter slot.
1894         *
1895         * @param slotIdx
1896         *            Parameter slot for the constant.
1897         * @param iaccum
1898         *            Value of the maximum integral accumulator (closed loop error
1899         *            units X 1ms).
1900         * @return Error Code generated by function. 0 indicates no error.
1901         */
1902        public ErrorCode configMaxIntegralAccumulator(int slotIdx, double iaccum) {
1903        int timeoutMs = 0;
1904                return configMaxIntegralAccumulator( slotIdx,  iaccum,  timeoutMs);
1905        }
1906
1907        /**
1908         * Sets the peak closed-loop output.  This peak output is slot-specific and
1909         *   is applied to the output of the associated PID loop.
1910         * This setting is seperate from the generic Peak Output setting.
1911         *
1912         * @param slotIdx
1913         *            Parameter slot for the constant.
1914         * @param percentOut
1915         *            Peak Percent Output from 0 to 1.  This value is absolute and
1916         *                                              the magnitude will apply in both forward and reverse directions.
1917         * @param timeoutMs
1918         *            Timeout value in ms. If nonzero, function will wait for
1919         *            config success and report an error if it times out.
1920         *            If zero, no blocking or checking is performed.
1921         * @return Error Code generated by function. 0 indicates no error.
1922         */
1923        public ErrorCode configClosedLoopPeakOutput(int slotIdx, double percentOut, int timeoutMs) {
1924                int retval = MotControllerJNI.ConfigClosedLoopPeakOutput(m_handle, slotIdx, percentOut, timeoutMs);
1925                return ErrorCode.valueOf(retval);
1926        }
1927        /**
1928         * Sets the peak closed-loop output.  This peak output is slot-specific and
1929         *   is applied to the output of the associated PID loop.
1930         * This setting is seperate from the generic Peak Output setting.
1931         *
1932         * @param slotIdx
1933         *            Parameter slot for the constant.
1934         * @param percentOut
1935         *            Peak Percent Output from 0 to 1.  This value is absolute and
1936         *                                              the magnitude will apply in both forward and reverse directions.
1937         * @return Error Code generated by function. 0 indicates no error.
1938         */
1939        public ErrorCode configClosedLoopPeakOutput(int slotIdx, double percentOut) {
1940        int timeoutMs = 0;
1941
1942                return configClosedLoopPeakOutput( slotIdx,  percentOut,  timeoutMs);
1943        }
1944
1945        /**
1946         * Sets the loop time (in milliseconds) of the PID closed-loop calculations.
1947         * Default value is 1 ms.
1948         *
1949         * @param slotIdx
1950         *            Parameter slot for the constant.
1951         * @param loopTimeMs
1952         *            Loop timing of the closed-loop calculations.  Minimum value of
1953         *                                              1 ms, maximum of 64 ms.
1954         * @param timeoutMs
1955         *            Timeout value in ms. If nonzero, function will wait for
1956         *            config success and report an error if it times out.
1957         *            If zero, no blocking or checking is performed.
1958         * @return Error Code generated by function. 0 indicates no error.
1959         */
1960        public ErrorCode configClosedLoopPeriod(int slotIdx, int loopTimeMs, int timeoutMs) {
1961                int retval = MotControllerJNI.ConfigClosedLoopPeriod(m_handle, slotIdx, loopTimeMs, timeoutMs);
1962                return ErrorCode.valueOf(retval);
1963        }
1964        /**
1965         * Sets the loop time (in milliseconds) of the PID closed-loop calculations.
1966         * Default value is 1 ms.
1967         *
1968         * @param slotIdx
1969         *            Parameter slot for the constant.
1970         * @param loopTimeMs
1971         *            Loop timing of the closed-loop calculations.  Minimum value of
1972         *                                              1 ms, maximum of 64 ms.
1973         * @return Error Code generated by function. 0 indicates no error.
1974         */
1975        public ErrorCode configClosedLoopPeriod(int slotIdx, int loopTimeMs) {
1976        int timeoutMs = 0;
1977                return configClosedLoopPeriod( slotIdx,  loopTimeMs,  timeoutMs);
1978        }
1979
1980        /**
1981         * Configures the Polarity of the Auxiliary PID (PID1).
1982         *
1983         * Standard Polarity:
1984         *    Primary Output = PID0 + PID1,
1985         *    Auxiliary Output = PID0 - PID1,
1986         *
1987         * Inverted Polarity:
1988         *    Primary Output = PID0 - PID1,
1989         *    Auxiliary Output = PID0 + PID1,
1990         *
1991         * @param invert
1992         *            If true, use inverted PID1 output polarity.
1993         * @param timeoutMs
1994         *            Timeout value in ms. If nonzero, function will wait for config
1995         *            success and report an error if it times out. If zero, no
1996         *            blocking or checking is performed.
1997         * @return Error Code
1998         */
1999        public ErrorCode configAuxPIDPolarity(boolean invert, int timeoutMs){
2000                return configSetParameter(ParamEnum.ePIDLoopPolarity, invert ? 1:0, 0, 1, timeoutMs);
2001        }
2002        /**
2003         * Configures the Polarity of the Auxiliary PID (PID1).
2004         *
2005         * Standard Polarity:
2006         *    Primary Output = PID0 + PID1,
2007         *    Auxiliary Output = PID0 - PID1,
2008         *
2009         * Inverted Polarity:
2010         *    Primary Output = PID0 - PID1,
2011         *    Auxiliary Output = PID0 + PID1,
2012         *
2013         * @param invert
2014         *            If true, use inverted PID1 output polarity.
2015         * @return Error Code
2016         */
2017        public ErrorCode configAuxPIDPolarity(boolean invert){
2018                int timeoutMs = 0;
2019                return configAuxPIDPolarity(invert,  timeoutMs);
2020        }
2021
2022        /**
2023         * Sets the integral accumulator. Typically this is used to clear/zero the
2024         * integral accumulator, however some use cases may require seeding the
2025         * accumulator for a faster response.
2026         *
2027         * @param iaccum
2028         *            Value to set for the integral accumulator (closed loop error
2029         *            units X 1ms).
2030         * @param pidIdx
2031         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2032         * @param timeoutMs
2033         *            Timeout value in ms. If nonzero, function will wait for config
2034         *            success and report an error if it times out. If zero, no
2035         *            blocking or checking is performed.
2036         * @return Error Code generated by function. 0 indicates no error.
2037         */
2038        public ErrorCode setIntegralAccumulator(double iaccum, int pidIdx, int timeoutMs) {
2039                int retval = MotControllerJNI.SetIntegralAccumulator(m_handle,  iaccum, pidIdx, timeoutMs);
2040                return ErrorCode.valueOf(retval);
2041        }
2042        /**
2043         * Sets the integral accumulator. Typically this is used to clear/zero the
2044         * integral accumulator, however some use cases may require seeding the
2045         * accumulator for a faster response.
2046         *
2047         * @param iaccum
2048         *            Value to set for the integral accumulator (closed loop error
2049         *            units X 1ms).
2050         * @return Error Code generated by function. 0 indicates no error.
2051         */
2052        public ErrorCode setIntegralAccumulator(double iaccum) {
2053                int pidIdx = 0;
2054                int timeoutMs = 0;
2055                return setIntegralAccumulator( iaccum,  pidIdx,  timeoutMs);
2056        }
2057
2058        /**
2059         * Gets the closed-loop error. The units depend on which control mode is in
2060         * use.
2061         *
2062         * If closed-loop is seeking a target sensor position, closed-loop error is the difference between target
2063         * and current sensor value (in sensor units.  Example 4096 units per rotation for CTRE Mag Encoder).
2064         *
2065         * If closed-loop is seeking a target sensor velocity, closed-loop error is the difference between target
2066         * and current sensor value (in sensor units per 100ms).
2067         *
2068         * If using motion profiling or Motion Magic, closed loop error is calculated against the current target,
2069         * and not the "final" target at the end of the profile/movement.
2070         *
2071         * See Phoenix-Documentation information on units.
2072         *
2073         * @param pidIdx
2074         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2075         * @return Closed-loop error value.
2076         */
2077        public double getClosedLoopError(int pidIdx) {
2078                return (double)MotControllerJNI.GetClosedLoopError(m_handle, pidIdx);
2079        }
2080        /**
2081         * Gets the closed-loop error. The units depend on which control mode is in
2082         * use.
2083         *
2084         * If closed-loop is seeking a target sensor position, closed-loop error is the difference between target
2085         * and current sensor value (in sensor units.  Example 4096 units per rotation for CTRE Mag Encoder).
2086         *
2087         * If closed-loop is seeking a target sensor velocity, closed-loop error is the difference between target
2088         * and current sensor value (in sensor units per 100ms).
2089         *
2090         * If using motion profiling or Motion Magic, closed loop error is calculated against the current target,
2091         * and not the "final" target at the end of the profile/movement.
2092         *
2093         * See Phoenix-Documentation information on units.
2094         *
2095         * @return Closed-loop error value.
2096         */
2097        public double getClosedLoopError() {
2098                int pidIdx = 0;
2099                return getClosedLoopError( pidIdx);
2100        }
2101
2102        /**
2103         * Gets the iaccum value.
2104         *
2105         * @param pidIdx
2106         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2107         * @return Integral accumulator value (Closed-loop error X 1ms).
2108         */
2109        public double getIntegralAccumulator(int pidIdx) {
2110                return MotControllerJNI.GetIntegralAccumulator(m_handle, pidIdx);
2111        }
2112        /**
2113         * Gets the iaccum value.
2114         *
2115         * @return Integral accumulator value (Closed-loop error X 1ms).
2116         */
2117        public double getIntegralAccumulator() {
2118                int pidIdx = 0;
2119                return getIntegralAccumulator(pidIdx);
2120        }
2121
2122
2123        /**
2124         * Gets the derivative of the closed-loop error.
2125         *
2126         * @param pidIdx
2127         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2128         * @return The error derivative value.
2129         */
2130        public double getErrorDerivative(int pidIdx) {
2131                return MotControllerJNI.GetErrorDerivative(m_handle, pidIdx);
2132        }
2133        /**
2134         * Gets the derivative of the closed-loop error.
2135         *
2136         * @return The error derivative value.
2137         */
2138        public double getErrorDerivative() {
2139                int pidIdx = 0;
2140
2141                return getErrorDerivative(pidIdx);
2142        }
2143
2144        /**
2145         * Selects which profile slot to use for closed-loop control.
2146         *
2147         * @param slotIdx
2148         *            Profile slot to select.
2149         * @param pidIdx
2150         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2151         **/
2152        public void selectProfileSlot(int slotIdx, int pidIdx) {
2153                MotControllerJNI.SelectProfileSlot(m_handle, slotIdx, pidIdx);
2154        }
2155
2156        /**
2157         * Gets the current target of a given closed loop.
2158         *
2159         * @param pidIdx
2160         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2161         * @return The closed loop target.
2162         */
2163        public double getClosedLoopTarget(int pidIdx) {
2164                double value = MotControllerJNI.GetClosedLoopTarget(m_handle, pidIdx);
2165                if(m_controlMode == ControlMode.Current){
2166                        value = value / 1000; //convert back to amps
2167                }
2168                return value;
2169        }
2170        /**
2171         * Gets the current target of a given closed loop.
2172         *
2173         * @return The closed loop target.
2174         */
2175        public double getClosedLoopTarget() {
2176                int pidIdx = 0;
2177                return getClosedLoopTarget(pidIdx);
2178        }
2179
2180        /**
2181         * Gets the active trajectory target position for pid0 using
2182         * MotionMagic/MotionProfile control modes.
2183         *
2184         * @return The Active Trajectory Position in sensor units.
2185         */
2186        public double getActiveTrajectoryPosition() {
2187                return (double)MotControllerJNI.GetActiveTrajectoryPosition(m_handle);
2188        }
2189
2190        /**
2191         * Gets the active trajectory target position using
2192         * MotionMagic/MotionProfile control modes.
2193         *
2194         * @param pidIdx
2195         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2196         * @return The Active Trajectory Position in sensor units.
2197         */
2198        public double getActiveTrajectoryPosition(int pidIdx) {
2199                return (double)MotControllerJNI.GetActiveTrajectoryPosition3(m_handle, pidIdx);
2200        }
2201
2202        /**
2203         * Gets the active trajectory target velocity for pid0 using
2204         * MotionMagic/MotionProfile control modes.
2205         *
2206         * @return The Active Trajectory Velocity in sensor units per 100ms.
2207         */
2208        public double getActiveTrajectoryVelocity() {
2209                return (double)MotControllerJNI.GetActiveTrajectoryVelocity(m_handle);
2210        }
2211
2212        /**
2213         * Gets the active trajectory target velocity using
2214         * MotionMagic/MotionProfile control modes.
2215         *
2216         * @param pidIdx
2217         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2218         * @return The Active Trajectory Velocity in sensor units per 100ms.
2219         */
2220        public double getActiveTrajectoryVelocity(int pidIdx) {
2221                return (double)MotControllerJNI.GetActiveTrajectoryVelocity3(m_handle, pidIdx);
2222        }
2223
2224        /**
2225         * Gets the active trajectory arbitrary feedforward for pid0 using
2226         * MotionMagic/MotionProfile control modes.
2227         *
2228         * @return The Active Trajectory ArbFeedFwd in units of percent output
2229         *                      (where 0.01 is 1%).
2230         */
2231        public double getActiveTrajectoryArbFeedFwd() {
2232                return MotControllerJNI.GetActiveTrajectoryArbFeedFwd3(m_handle, 0);
2233        }
2234
2235        /**
2236         * Gets the active trajectory arbitrary feedforward using
2237         * MotionMagic/MotionProfile control modes.
2238         *
2239         * @param pidIdx
2240         *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
2241         * @return The Active Trajectory ArbFeedFwd in units of percent output
2242         *                      (where 0.01 is 1%).
2243         */
2244        public double getActiveTrajectoryArbFeedFwd(int pidIdx) {
2245                return MotControllerJNI.GetActiveTrajectoryArbFeedFwd3(m_handle, pidIdx);
2246        }
2247
2248        // ------ Motion Profile Settings used in Motion Magic and Motion Profile ----------//
2249
2250        /**
2251         * Sets the Motion Magic Cruise Velocity. This is the peak target velocity
2252         * that the motion magic curve generator can use.
2253         *
2254         * @param sensorUnitsPer100ms
2255         *            Motion Magic Cruise Velocity (in raw sensor units per 100 ms).
2256         * @param timeoutMs
2257         *            Timeout value in ms. If nonzero, function will wait for config
2258         *            success and report an error if it times out. If zero, no
2259         *            blocking or checking is performed.
2260         * @return Error Code generated by function. 0 indicates no error.
2261         */
2262        public ErrorCode configMotionCruiseVelocity(double sensorUnitsPer100ms, int timeoutMs) {
2263                int retval = MotControllerJNI.ConfigMotionCruiseVelocity(m_handle, (int)sensorUnitsPer100ms, timeoutMs);
2264                return ErrorCode.valueOf(retval);
2265        }
2266        /**
2267         * Sets the Motion Magic Cruise Velocity. This is the peak target velocity
2268         * that the motion magic curve generator can use.
2269         *
2270         * @param sensorUnitsPer100ms
2271         *            Motion Magic Cruise Velocity (in raw sensor units per 100 ms).
2272         * @return Error Code generated by function. 0 indicates no error.
2273         */
2274        public ErrorCode configMotionCruiseVelocity(double sensorUnitsPer100ms) {
2275                int timeoutMs = 0;
2276                return configMotionCruiseVelocity( sensorUnitsPer100ms,  timeoutMs);
2277        }
2278
2279        /**
2280         * Sets the Motion Magic Acceleration. This is the target acceleration that
2281         * the motion magic curve generator can use.
2282         *
2283         * @param sensorUnitsPer100msPerSec
2284         *            Motion Magic Acceleration (in raw sensor units per 100 ms per
2285         *            second).
2286         * @param timeoutMs
2287         *            Timeout value in ms. If nonzero, function will wait for config
2288         *            success and report an error if it times out. If zero, no
2289         *            blocking or checking is performed.
2290         * @return Error Code generated by function. 0 indicates no error.
2291         */
2292        public ErrorCode configMotionAcceleration(double sensorUnitsPer100msPerSec, int timeoutMs) {
2293                int retval = MotControllerJNI.ConfigMotionAcceleration(m_handle, (int)sensorUnitsPer100msPerSec, timeoutMs);
2294                return ErrorCode.valueOf(retval);
2295        }
2296        /**
2297         * Sets the Motion Magic Acceleration. This is the target acceleration that
2298         * the motion magic curve generator can use.
2299         *
2300         * @param sensorUnitsPer100msPerSec
2301         *            Motion Magic Acceleration (in raw sensor units per 100 ms per
2302         *            second).
2303         * @return Error Code generated by function. 0 indicates no error.
2304         */
2305        public ErrorCode configMotionAcceleration(double sensorUnitsPer100msPerSec) {
2306                int timeoutMs = 0;
2307                return configMotionAcceleration( sensorUnitsPer100msPerSec,  timeoutMs);
2308        }
2309
2310        /**
2311         * Sets the Motion Magic S Curve Strength.
2312         * Call this before using Motion Magic.
2313         * Modifying this during a Motion Magic action should be avoided.
2314         *
2315         * @param curveStrength
2316         *            0 to use Trapezoidal Motion Profile. [1,8] for S-Curve (greater value yields greater smoothing).
2317         * @param timeoutMs
2318         *            Timeout value in ms. If nonzero, function will wait for config
2319         *            success and report an error if it times out. If zero, no
2320         *            blocking or checking is performed.
2321         * @return Error Code generated by function. 0 indicates no error.
2322         */
2323        public ErrorCode configMotionSCurveStrength(int curveStrength, int timeoutMs) {
2324                int retval = MotControllerJNI.ConfigMotionSCurveStrength(m_handle, curveStrength, timeoutMs);
2325                return ErrorCode.valueOf(retval);
2326        }
2327
2328        /**
2329         * Sets the Motion Magic S Curve Strength.
2330         * Call this before using Motion Magic.
2331         * Modifying this during a Motion Magic action should be avoided.
2332         *
2333         * @param curveStrength
2334         *            0 to use Trapezoidal Motion Profile. [1,8] for S-Curve (greater value yields greater smoothing).
2335         * @return Error Code generated by function. 0 indicates no error.
2336         */
2337        public ErrorCode configMotionSCurveStrength(int curveStrength) {
2338                int timeoutMs = 0;
2339                return configMotionSCurveStrength(curveStrength, timeoutMs);
2340        }
2341
2342        //------ Motion Profile Buffer ----------//
2343        /**
2344         * Clear the buffered motion profile in both controller's RAM (bottom), and in the
2345         * API (top).
2346         * @return Error Code generated by function. 0 indicates no error.
2347         */
2348        public ErrorCode clearMotionProfileTrajectories() {
2349                int retval = MotControllerJNI.ClearMotionProfileTrajectories(m_handle);
2350                return ErrorCode.valueOf(retval);
2351        }
2352
2353        /**
2354         * Retrieve just the buffer count for the api-level (top) buffer. This
2355         * routine performs no CAN or data structure lookups, so its fast and ideal
2356         * if caller needs to quickly poll the progress of trajectory points being
2357         * emptied into controller's RAM. Otherwise just use GetMotionProfileStatus.
2358         *
2359         * @return number of trajectory points in the top buffer.
2360         */
2361        public int getMotionProfileTopLevelBufferCount() {
2362                return MotControllerJNI.GetMotionProfileTopLevelBufferCount(m_handle);
2363        }
2364        /**
2365         * Push another trajectory point into the top level buffer (which is emptied
2366         * into the motor controller's bottom buffer as room allows).
2367         * @param trajPt to push into buffer.
2368         * The members should be filled in with these values...
2369         *
2370         *              targPos:  servo position in sensor units.
2371         *              targVel:  velocity to feed-forward in sensor units
2372         *                 per 100ms.
2373         *              profileSlotSelect0  Which slot to get PIDF gains. PID is used for position servo. F is used
2374         *                                                 as the Kv constant for velocity feed-forward. Typically this is hardcoded
2375         *                                                 to the a particular slot, but you are free gain schedule if need be.
2376         *                                                 Choose from [0,3]
2377         *              profileSlotSelect1 Which slot to get PIDF gains for auxiliary PId.
2378         *                                                 This only has impact during MotionProfileArc Control mode.
2379         *                                                 Choose from [0,1].
2380         *         isLastPoint  set to nonzero to signal motor controller to keep processing this
2381         *                     trajectory point, instead of jumping to the next one
2382         *                     when timeDurMs expires.  Otherwise MP executer will
2383         *                     eventually see an empty buffer after the last point
2384         *                     expires, causing it to assert the IsUnderRun flag.
2385         *                     However this may be desired if calling application
2386         *                     never wants to terminate the MP.
2387         *              zeroPos  set to nonzero to signal motor controller to "zero" the selected
2388         *                 position sensor before executing this trajectory point.
2389         *                 Typically the first point should have this set only thus
2390         *                 allowing the remainder of the MP positions to be relative to
2391         *                 zero.
2392         *              timeDur Duration to apply this trajectory pt.
2393         *                              This time unit is ADDED to the exising base time set by
2394         *                              configMotionProfileTrajectoryPeriod().
2395         * @return CTR_OKAY if trajectory point push ok. ErrorCode if buffer is
2396         *         full due to kMotionProfileTopBufferCapacity.
2397         */
2398        public ErrorCode pushMotionProfileTrajectory(TrajectoryPoint trajPt) {
2399                int retval = MotControllerJNI.PushMotionProfileTrajectory3(m_handle, trajPt.position, trajPt.velocity, trajPt.arbFeedFwd, trajPt.auxiliaryPos, trajPt.auxiliaryVel, trajPt.auxiliaryArbFeedFwd, trajPt.profileSlotSelect0, trajPt.profileSlotSelect1, trajPt.isLastPoint, trajPt.zeroPos, trajPt.timeDur, trajPt.useAuxPID);
2400                return ErrorCode.valueOf(retval);
2401        }
2402
2403        /**
2404         * Simple one-shot firing of a complete MP.
2405         * Starting in 2019, MPs can be fired by building a Buffered Trajectory Point Stream, and calling this routine.
2406         *
2407         * Once called, the motor controller software will automatically ...
2408         * [1] Clear the firmware buffer of trajectory points.
2409         * [2] Clear the underrun flags
2410         * [3] Reset an index within the Buffered Trajectory Point Stream (so that the same profile can be run again and again).
2411         * [4] Start a background thread to manage MP streaming (if not already running).
2412         * [5a] If current control mode already matches motionProfControlMode, set MPE Output to "Hold".
2413         * [5b] If current control mode does not matches motionProfControlMode, apply motionProfControlMode and set MPE Output to "Disable".
2414         * [6] Stream the trajectory points into the device's firmware buffer.
2415         * [7] Once motor controller has at least minBufferedPts worth in the firmware buffer, MP will automatically start (MPE Output set to "Enable").
2416         * [8] Wait until MP finishes, then transitions the Motion Profile Executor's output to "Hold".
2417         * [9] IsMotionProfileFinished() will now return true.
2418         *
2419         * Calling application can use IsMotionProfileFinished() to determine when internal state machine reaches [7].
2420         * Calling application can cancel MP by calling set().  Otherwise do not call set() until MP has completed.
2421         *
2422         * The legacy API from previous years requires the calling application to pass points via the ProcessMotionProfileBuffer and PushMotionProfileTrajectory.
2423         * This is no longer required if using this StartMotionProfile/IsMotionProfileFinished API.
2424         *
2425         * @param stream        A buffer that will be used to stream the trajectory points.  Caller can fill this container with the entire trajectory point, regardless of size.
2426         * @param minBufferedPts        Minimum number of firmware buffered points before starting MP.
2427         *                                                      Do not exceed device's firmware buffer capacity or MP will never fire (120 for Motion Profile, or 60 for Motion Profile Arc).
2428         *                                                      Recommendation value for this would be five to ten samples depending on timeDur of the trajectory point.
2429         * @param motionProfControlMode         Pass MotionProfile or MotionProfileArc.
2430         * @return nonzero error code if operation fails.
2431     */
2432        public ErrorCode startMotionProfile(BufferedTrajectoryPointStream stream, int minBufferedPts, ControlMode motionProfControlMode) {
2433                int retval = MotControllerJNI.StartMotionProfile(m_handle, stream.getHandle(), minBufferedPts, motionProfControlMode.value);
2434                return ErrorCode.valueOf(retval);
2435        }
2436        /**
2437         * Determine if running MP is complete.
2438         * This requires using the StartMotionProfile routine to start the MP.
2439         * That is because managing the trajectory points is now done in a background thread (if StartMotionProfile is called).
2440         *
2441         * If calling application uses the legacy API  (more-complex buffering API) from previous years, than this API will
2442         * not return true.
2443         *
2444         * @return true if MP was started using StartMotionProfile, and it has completed execution (MPE is now in "hold").
2445         */
2446        public boolean isMotionProfileFinished() {
2447                return MotControllerJNI.IsMotionProfileFinished(m_handle);
2448        }
2449
2450        /**
2451         * Retrieve just the buffer full for the api-level (top) buffer. This
2452         * routine performs no CAN or data structure lookups, so its fast and ideal
2453         * if caller needs to quickly poll. Otherwise just use
2454         * GetMotionProfileStatus.
2455         *
2456         * @return number of trajectory points in the top buffer.
2457         */
2458        public boolean isMotionProfileTopLevelBufferFull() {
2459                return MotControllerJNI.IsMotionProfileTopLevelBufferFull(m_handle);
2460        }
2461
2462        /**
2463         * This must be called periodically to funnel the trajectory points from the
2464         * API's top level buffer to the controller's bottom level buffer. Recommendation
2465         * is to call this twice as fast as the execution rate of the motion
2466         * profile. So if MP is running with 20ms trajectory points, try calling
2467         * this routine every 10ms. All motion profile functions are thread-safe
2468         * through the use of a mutex, so there is no harm in having the caller
2469         * utilize threading.
2470         */
2471        public void processMotionProfileBuffer() {
2472                MotControllerJNI.ProcessMotionProfileBuffer(m_handle);
2473        }
2474        /**
2475         * Retrieve all status information.
2476         * For best performance, Caller can snapshot all status information regarding the
2477         * motion profile executer.
2478         *
2479         * @param statusToFill  Caller supplied object to fill.
2480         *
2481         * The members are filled, as follows...
2482         *
2483         *      topBufferRem:   The available empty slots in the trajectory buffer.
2484         *                                      The robot API holds a "top buffer" of trajectory points, so your applicaion
2485         *                                      can dump several points at once.  The API will then stream them into the
2486         *                                      low-level buffer, allowing the motor controller to act on them.
2487         *
2488         *      topBufferRem: The number of points in the top trajectory buffer.
2489         *
2490         *      btmBufferCnt: The number of points in the low level controller buffer.
2491         *
2492         *      hasUnderrun:    Set if isUnderrun ever gets set.
2493         *                                      Can be manually cleared by clearMotionProfileHasUnderrun() or automatically cleared by startMotionProfile().
2494         *
2495         *      isUnderrun:             This is set if controller needs to shift a point from its buffer into
2496         *                                      the active trajectory point however
2497         *                                      the buffer is empty.
2498         *                                      This gets cleared automatically when is resolved.
2499         *
2500         *      activePointValid:       True if the active trajectory point is not empty, false otherwise. The members in activePoint are only valid if this signal is set.
2501         *
2502         *      isLast: is set/cleared based on the MP executer's current
2503         *                trajectory point's IsLast value.  This assumes
2504         *                IsLast was set when PushMotionProfileTrajectory
2505         *                was used to insert the currently processed trajectory
2506         *                point.
2507         *
2508         *      profileSlotSelect: The currently processed trajectory point's
2509         *                                selected slot.  This can differ in the currently selected slot used
2510         *                                       for Position and Velocity servo modes
2511         *
2512         *      outputEnable:           The current output mode of the motion profile
2513         *                                              executer (disabled, enabled, or hold).  When changing the set()
2514         *                                              value in MP mode, it's important to check this signal to
2515         *                                              confirm the change takes effect before interacting with the top buffer.
2516         *
2517         * @return Error Code generated by function. 0 indicates no error.
2518         */
2519        public ErrorCode getMotionProfileStatus(MotionProfileStatus statusToFill) {
2520                int retval = MotControllerJNI.GetMotionProfileStatus2(m_handle, _motionProfStats);
2521                statusToFill.topBufferRem = _motionProfStats[0];
2522                statusToFill.topBufferCnt = _motionProfStats[1];
2523                statusToFill.btmBufferCnt = _motionProfStats[2];
2524                statusToFill.hasUnderrun = _motionProfStats[3] != 0;
2525                statusToFill.isUnderrun = _motionProfStats[4] != 0;
2526                statusToFill.activePointValid = _motionProfStats[5] != 0;
2527                statusToFill.isLast = _motionProfStats[6] != 0;
2528                statusToFill.profileSlotSelect = _motionProfStats[7];
2529                statusToFill.outputEnable = SetValueMotionProfile.valueOf(_motionProfStats[8]);
2530                statusToFill.timeDurMs = _motionProfStats[9];
2531                statusToFill.profileSlotSelect1 = _motionProfStats[10];
2532                return ErrorCode.valueOf(retval);
2533        }
2534
2535        /**
2536         * Clear the "Has Underrun" flag. Typically this is called after application
2537         * has confirmed an underrun had occured.
2538         *
2539         * @param timeoutMs
2540         *            Timeout value in ms. If nonzero, function will wait for config
2541         *            success and report an error if it times out. If zero, no
2542         *            blocking or checking is performed.
2543         * @return Error Code generated by function. 0 indicates no error.
2544         */
2545        public ErrorCode clearMotionProfileHasUnderrun(int timeoutMs) {
2546                int retval = MotControllerJNI.ClearMotionProfileHasUnderrun(m_handle, timeoutMs);
2547                return ErrorCode.valueOf(retval);
2548        }
2549        /**
2550         * Clear the "Has Underrun" flag. Typically this is called after application
2551         * has confirmed an underrun had occured.
2552         *
2553         * @return Error Code generated by function. 0 indicates no error.
2554         */
2555        public ErrorCode clearMotionProfileHasUnderrun() {
2556                int timeoutMs = 0;
2557                return clearMotionProfileHasUnderrun(timeoutMs);
2558        }
2559
2560        /**
2561         * Calling application can opt to speed up the handshaking between the robot
2562         * API and the controller to increase the download rate of the controller's Motion
2563         * Profile. Ideally the period should be no more than half the period of a
2564         * trajectory point.
2565         *
2566         * @param periodMs
2567         *            The transmit period in ms.
2568         * @return Error Code generated by function. 0 indicates no error.
2569         */
2570        public ErrorCode changeMotionControlFramePeriod(int periodMs) {
2571                int retval = MotControllerJNI.ChangeMotionControlFramePeriod(m_handle, periodMs);
2572                return ErrorCode.valueOf(retval);
2573        }
2574
2575        /**
2576         * When trajectory points are processed in the motion profile executer, the MPE determines
2577         * how long to apply the active trajectory point by summing baseTrajDurationMs with the
2578         * timeDur of the trajectory point (see TrajectoryPoint).
2579         *
2580         * This allows general selection of the execution rate of the points with 1ms resolution,
2581         * while allowing some degree of change from point to point.
2582         * @param baseTrajDurationMs The base duration time of every trajectory point.
2583         *                                                      This is summed with the trajectory points unique timeDur.
2584         * @param timeoutMs
2585         *            Timeout value in ms. If nonzero, function will wait for
2586         *            config success and report an error if it times out.
2587         *            If zero, no blocking or checking is performed.
2588         * @return Error Code generated by function. 0 indicates no error.
2589         */
2590        public ErrorCode configMotionProfileTrajectoryPeriod(int baseTrajDurationMs, int timeoutMs) {
2591                int retval = MotControllerJNI.ConfigMotionProfileTrajectoryPeriod(m_handle, baseTrajDurationMs, timeoutMs);
2592                return ErrorCode.valueOf(retval);
2593        }
2594        /**
2595         * When trajectory points are processed in the motion profile executer, the MPE determines
2596         * how long to apply the active trajectory point by summing baseTrajDurationMs with the
2597         * timeDur of the trajectory point (see TrajectoryPoint).
2598         *
2599         * This allows general selection of the execution rate of the points with 1ms resolution,
2600         * while allowing some degree of change from point to point.
2601         * @param baseTrajDurationMs The base duration time of every trajectory point.
2602         *                                                      This is summed with the trajectory points unique timeDur.
2603         * @return Error Code generated by function. 0 indicates no error.
2604         */
2605        public ErrorCode configMotionProfileTrajectoryPeriod(int baseTrajDurationMs) {
2606                int timeoutMs = 0;
2607                return configMotionProfileTrajectoryPeriod( baseTrajDurationMs,  timeoutMs);
2608        }
2609
2610        /**
2611         * When trajectory points are processed in the buffer, the motor controller can
2612         * linearly interpolate additional trajectory points between the buffered
2613         * points.  The time delta between these interpolated points is 1 ms.
2614         *
2615         * By default this feature is enabled.
2616         *
2617         * @param enable Whether to enable the trajectory point interpolation feature.
2618         * @param timeoutMs
2619         *            Timeout value in ms. If nonzero, function will wait for
2620         *            config success and report an error if it times out.
2621         *            If zero, no blocking or checking is performed.
2622         * @return Error Code generated by function. 0 indicates no error.
2623         */
2624        public ErrorCode configMotionProfileTrajectoryInterpolationEnable(boolean enable, int timeoutMs) {
2625                int retval = MotControllerJNI.ConfigMotionProfileTrajectoryInterpolationEnable(m_handle, enable, timeoutMs);
2626                return ErrorCode.valueOf(retval);
2627        }
2628        /**
2629         * When trajectory points are processed in the buffer, the motor controller can
2630         * linearly interpolate additional trajectory points between the buffered
2631         * points.  The time delta between these interpolated points is 1 ms.
2632         *
2633         * By default this feature is enabled.
2634         *
2635         * @param enable Whether to enable the trajectory point interpolation feature.
2636         * @return Error Code generated by function. 0 indicates no error.
2637         */
2638        public ErrorCode configMotionProfileTrajectoryInterpolationEnable(boolean enable) {
2639                int timeoutMs = 0;
2640                return configMotionProfileTrajectoryInterpolationEnable(enable, timeoutMs);
2641        }
2642
2643    //------Feedback Device Interaction Settings---------//
2644
2645    /**
2646     * Disables continuous tracking of the position for analog and pulse-width.
2647         * If the signal goes from 4095 to 0 (pulse-width) a motor controller will continue to read 4096 by default.
2648         * If overflow tracking is disabled, it will wrap to 0 (not continuous)
2649         *
2650         * If using pulse-width on CTRE Mag Encoder (within one rotation) or absolute analog sensor (within one rotation),
2651         * setting feedbackNotContinuous to true is recommended, to prevent intermittent
2652         * connections from causing sensor "jumps" of 4096 (or 1024 for analog) units.
2653     *
2654     * @param feedbackNotContinuous     True to disable the overflow tracking.
2655     *
2656     * @param timeoutMs
2657     *            Timeout value in ms. If nonzero, function will wait for
2658     *            config success and report an error if it times out.
2659     *            If zero, no blocking or checking is performed.
2660     * @return Error Code generated by function. 0 indicates no error.
2661     */
2662    public ErrorCode configFeedbackNotContinuous(boolean feedbackNotContinuous, int timeoutMs) {
2663        int retval = MotControllerJNI.ConfigFeedbackNotContinuous(m_handle, feedbackNotContinuous, timeoutMs);
2664        return ErrorCode.valueOf(retval);
2665    }
2666
2667    /**
2668     * Disables going to neutral (brake/coast) when a remote sensor is no longer detected.
2669     *
2670     * @param remoteSensorClosedLoopDisableNeutralOnLOS     disable going to neutral
2671     *
2672     * @param timeoutMs
2673     *            Timeout value in ms. If nonzero, function will wait for
2674     *            config success and report an error if it times out.
2675     *            If zero, no blocking or checking is performed.
2676     * @return Error Code generated by function. 0 indicates no error.
2677     */
2678    public ErrorCode configRemoteSensorClosedLoopDisableNeutralOnLOS(boolean remoteSensorClosedLoopDisableNeutralOnLOS, int timeoutMs) {
2679        int retval = MotControllerJNI.ConfigRemoteSensorClosedLoopDisableNeutralOnLOS(m_handle, remoteSensorClosedLoopDisableNeutralOnLOS, timeoutMs);
2680        return ErrorCode.valueOf(retval);
2681    }
2682    /**
2683     * Enables clearing the position of the feedback sensor when the forward
2684     * limit switch is triggered.
2685     *
2686     * @param clearPositionOnLimitF     Whether clearing is enabled, defaults false
2687     * @param timeoutMs
2688     *            Timeout value in ms. If nonzero, function will wait for
2689     *            config success and report an error if it times out.
2690     *            If zero, no blocking or checking is performed.
2691     * @return Error Code generated by function. 0 indicates no error.
2692     */
2693    public ErrorCode configClearPositionOnLimitF(boolean clearPositionOnLimitF, int timeoutMs) {
2694        int retval = MotControllerJNI.ConfigClearPositionOnLimitF(m_handle, clearPositionOnLimitF, timeoutMs);
2695        return ErrorCode.valueOf(retval);
2696    }
2697
2698    /**
2699     * Enables clearing the position of the feedback sensor when the reverse
2700     * limit switch is triggered
2701     *
2702     * @param clearPositionOnLimitR     Whether clearing is enabled, defaults false
2703     * @param timeoutMs
2704     *            Timeout value in ms. If nonzero, function will wait for
2705     *            config success and report an error if it times out.
2706     *            If zero, no blocking or checking is performed.
2707     * @return Error Code generated by function. 0 indicates no error.
2708     */
2709    public ErrorCode configClearPositionOnLimitR(boolean clearPositionOnLimitR, int timeoutMs) {
2710        int retval = MotControllerJNI.ConfigClearPositionOnLimitR(m_handle, clearPositionOnLimitR, timeoutMs);
2711        return ErrorCode.valueOf(retval);
2712    }
2713
2714    /**
2715     * Enables clearing the position of the feedback sensor when the quadrature index signal
2716     * is detected
2717     *
2718     * @param clearPositionOnQuadIdx    Whether clearing is enabled, defaults false
2719     * @param timeoutMs
2720     *            Timeout value in ms. If nonzero, function will wait for
2721     *            config success and report an error if it times out.
2722     *            If zero, no blocking or checking is performed.
2723     * @return Error Code generated by function. 0 indicates no error.
2724     */
2725    public ErrorCode configClearPositionOnQuadIdx(boolean clearPositionOnQuadIdx, int timeoutMs) {
2726        int retval = MotControllerJNI.ConfigClearPositionOnQuadIdx(m_handle, clearPositionOnQuadIdx, timeoutMs);
2727        return ErrorCode.valueOf(retval);
2728    }
2729
2730    /**
2731     * Disables limit switches triggering (if enabled) when the sensor is no longer detected.
2732     *
2733     * @param limitSwitchDisableNeutralOnLOS    disable triggering
2734     *
2735     * @param timeoutMs
2736     *            Timeout value in ms. If nonzero, function will wait for
2737     *            config success and report an error if it times out.
2738     *            If zero, no blocking or checking is performed.
2739     * @return Error Code generated by function. 0 indicates no error.
2740     */
2741    public ErrorCode configLimitSwitchDisableNeutralOnLOS(boolean limitSwitchDisableNeutralOnLOS, int timeoutMs) {
2742        int retval = MotControllerJNI.ConfigLimitSwitchDisableNeutralOnLOS(m_handle, limitSwitchDisableNeutralOnLOS, timeoutMs);
2743        return ErrorCode.valueOf(retval);
2744    }
2745
2746    /**
2747     * Disables soft limits triggering (if enabled) when the sensor is no longer detected.
2748     *
2749     * @param softLimitDisableNeutralOnLOS    disable triggering
2750     *
2751     * @param timeoutMs
2752     *            Timeout value in ms. If nonzero, function will wait for
2753     *            config success and report an error if it times out.
2754     *            If zero, no blocking or checking is performed.
2755     * @return Error Code generated by function. 0 indicates no error.
2756     */
2757    public ErrorCode configSoftLimitDisableNeutralOnLOS(boolean softLimitDisableNeutralOnLOS, int timeoutMs) {
2758        int retval = MotControllerJNI.ConfigSoftLimitDisableNeutralOnLOS(m_handle, softLimitDisableNeutralOnLOS, timeoutMs);
2759        return ErrorCode.valueOf(retval);
2760    }
2761
2762    /**
2763     * Sets the edges per rotation of a pulse width sensor. (This should be set for
2764     * tachometer use).
2765     *
2766     * @param pulseWidthPeriod_EdgesPerRot    edges per rotation
2767     *
2768     * @param timeoutMs
2769     *            Timeout value in ms. If nonzero, function will wait for
2770     *            config success and report an error if it times out.
2771     *            If zero, no blocking or checking is performed.
2772     * @return Error Code generated by function. 0 indicates no error.
2773     */
2774    public ErrorCode configPulseWidthPeriod_EdgesPerRot(int pulseWidthPeriod_EdgesPerRot, int timeoutMs) {
2775        int retval = MotControllerJNI.ConfigPulseWidthPeriod_EdgesPerRot(m_handle, pulseWidthPeriod_EdgesPerRot, timeoutMs);
2776        return ErrorCode.valueOf(retval);
2777    }
2778
2779    /**
2780     * Sets the number of samples to use in smoothing a pulse width sensor with a rolling
2781     * average. Default is 1 (no smoothing).
2782     *
2783     * @param pulseWidthPeriod_FilterWindowSz   samples for rolling avg
2784     *
2785     * @param timeoutMs
2786     *            Timeout value in ms. If nonzero, function will wait for
2787     *            config success and report an error if it times out.
2788     *            If zero, no blocking or checking is performed.
2789     * @return Error Code generated by function. 0 indicates no error.
2790     */
2791    public ErrorCode configPulseWidthPeriod_FilterWindowSz(int pulseWidthPeriod_FilterWindowSz, int timeoutMs) {
2792        int retval = MotControllerJNI.ConfigPulseWidthPeriod_FilterWindowSz(m_handle, pulseWidthPeriod_FilterWindowSz, timeoutMs);
2793        return ErrorCode.valueOf(retval);
2794    }
2795        // ------ error ----------//
2796        /**
2797         * Gets the last error generated by this object. Not all functions return an
2798         * error code but can potentially report errors. This function can be used
2799         * to retrieve those error codes.
2800         *
2801         * @return Last Error Code generated by a function.
2802         */
2803        public ErrorCode getLastError() {
2804                int retval = MotControllerJNI.GetLastError(m_handle);
2805                return ErrorCode.valueOf(retval);
2806        }
2807
2808        // ------ Faults ----------//
2809        /**
2810         * Polls the various fault flags.
2811         *
2812         * @param toFill
2813         *            Caller's object to fill with latest fault flags.
2814         * @return Last Error Code generated by a function.
2815         */
2816        public ErrorCode getFaults(Faults toFill) {
2817                int bits = MotControllerJNI.GetFaults(m_handle);
2818                toFill.update(bits);
2819                return getLastError();
2820        }
2821
2822        /**
2823         * Polls the various sticky fault flags.
2824         *
2825         * @param toFill
2826         *            Caller's object to fill with latest sticky fault flags.
2827         * @return Last Error Code generated by a function.
2828         */
2829        public ErrorCode getStickyFaults(StickyFaults toFill) {
2830                int bits = MotControllerJNI.GetStickyFaults(m_handle);
2831                toFill.update(bits);
2832                return getLastError();
2833        }
2834
2835        /**
2836         * Clears all sticky faults.
2837         *
2838         * @param timeoutMs
2839         *            Timeout value in ms. If nonzero, function will wait for config
2840         *            success and report an error if it times out. If zero, no
2841         *            blocking or checking is performed.
2842         * @return Last Error Code generated by a function.
2843         */
2844        public ErrorCode clearStickyFaults(int timeoutMs) {
2845                int retval = MotControllerJNI.ClearStickyFaults(m_handle, timeoutMs);
2846                return ErrorCode.valueOf(retval);
2847        }
2848        /**
2849         * Clears all sticky faults.
2850         *
2851         * @return Last Error Code generated by a function.
2852         */
2853        public ErrorCode clearStickyFaults() {
2854                int timeoutMs = 0;
2855                return clearStickyFaults(timeoutMs);
2856        }
2857
2858        // ------ Firmware ----------//
2859        /**
2860         * Gets the firmware version of the device.
2861         *
2862         * @return Firmware version of device. For example: version 1-dot-2 is
2863         *         0x0102.
2864         */
2865        public int getFirmwareVersion() {
2866                return MotControllerJNI.GetFirmwareVersion(m_handle);
2867        }
2868
2869        /**
2870         * Returns true if the device has reset since last call.
2871         *
2872         * @return Has a Device Reset Occurred?
2873         */
2874        public boolean hasResetOccurred() {
2875                return MotControllerJNI.HasResetOccurred(m_handle);
2876        }
2877
2878        //------ Custom Persistent Params ----------//
2879        /**
2880         * Sets the value of a custom parameter. This is for arbitrary use.
2881         *
2882         * Sometimes it is necessary to save calibration/limit/target information in
2883         * the device. Particularly if the device is part of a subsystem that can be
2884         * replaced.
2885         *
2886         * @param newValue
2887         *            Value for custom parameter.
2888         * @param paramIndex
2889         *            Index of custom parameter [0,1]
2890         * @param timeoutMs
2891         *            Timeout value in ms. If nonzero, function will wait for config
2892         *            success and report an error if it times out. If zero, no
2893         *            blocking or checking is performed.
2894         * @return Error Code generated by function. 0 indicates no error.
2895         */
2896        public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs) {
2897                int retval = MotControllerJNI.ConfigSetCustomParam(m_handle, newValue, paramIndex, timeoutMs);
2898                return ErrorCode.valueOf(retval);
2899        }
2900        /**
2901         * Sets the value of a custom parameter. This is for arbitrary use.
2902         *
2903         * Sometimes it is necessary to save calibration/limit/target information in
2904         * the device. Particularly if the device is part of a subsystem that can be
2905         * replaced.
2906         *
2907         * @param newValue
2908         *            Value for custom parameter.
2909         * @param paramIndex
2910         *            Index of custom parameter [0,1]
2911         * @return Error Code generated by function. 0 indicates no error.
2912         */
2913        public ErrorCode configSetCustomParam(int newValue, int paramIndex) {
2914                int timeoutMs = 0;
2915                return configSetCustomParam( newValue,  paramIndex,  timeoutMs);
2916        }
2917
2918        /**
2919         * Gets the value of a custom parameter.
2920         *
2921         * @param paramIndex
2922         *            Index of custom parameter [0,1].
2923         * @param timeoutMs
2924         *            Timeout value in ms. If nonzero, function will wait for config
2925         *            success and report an error if it times out. If zero, no
2926         *            blocking or checking is performed.
2927         * @return Value of the custom param.
2928         */
2929        public int configGetCustomParam(int paramIndex, int timeoutMs) {
2930                int retval = MotControllerJNI.ConfigGetCustomParam(m_handle, paramIndex, timeoutMs);
2931                return retval;
2932        }
2933        /**
2934         * Gets the value of a custom parameter.
2935         *
2936         * @param paramIndex
2937         *            Index of custom parameter [0,1].
2938         * @return Value of the custom param.
2939         */
2940        public int configGetCustomParam(int paramIndex) {
2941                int timeoutMs = 0;
2942                return configGetCustomParam( paramIndex,  timeoutMs);
2943        }
2944
2945        // ------ Generic Param API ----------//
2946        /**
2947         * Sets a parameter. Generally this is not used. This can be utilized in -
2948         * Using new features without updating API installation. - Errata
2949         * workarounds to circumvent API implementation. - Allows for rapid testing
2950         * / unit testing of firmware.
2951         *
2952         * @param param
2953         *            Parameter enumeration.
2954         * @param value
2955         *            Value of parameter.
2956         * @param subValue
2957         *            Subvalue for parameter. Maximum value of 255.
2958         * @param ordinal
2959         *            Ordinal of parameter.
2960         * @param timeoutMs
2961         *            Timeout value in ms. If nonzero, function will wait for config
2962         *            success and report an error if it times out. If zero, no
2963         *            blocking or checking is performed.
2964         * @return Error Code generated by function. 0 indicates no error.
2965         */
2966        public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
2967                return configSetParameter(param.value, value, subValue, ordinal, timeoutMs);
2968        }
2969        /**
2970         * Sets a parameter. Generally this is not used. This can be utilized in -
2971         * Using new features without updating API installation. - Errata
2972         * workarounds to circumvent API implementation. - Allows for rapid testing
2973         * / unit testing of firmware.
2974         *
2975         * @param param
2976         *            Parameter enumeration.
2977         * @param value
2978         *            Value of parameter.
2979         * @param subValue
2980         *            Subvalue for parameter. Maximum value of 255.
2981         * @param ordinal
2982         *            Ordinal of parameter.
2983         * @return Error Code generated by function. 0 indicates no error.
2984         */
2985        public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal) {
2986                int timeoutMs = 0;
2987                return configSetParameter(param, value,  subValue,  ordinal,  timeoutMs);
2988        }
2989        /**
2990         * Sets a parameter.
2991         *
2992         * @param param
2993         *            Parameter enumeration.
2994         * @param value
2995         *            Value of parameter.
2996         * @param subValue
2997         *            Subvalue for parameter. Maximum value of 255.
2998         * @param ordinal
2999         *            Ordinal of parameter.
3000         * @param timeoutMs
3001         *            Timeout value in ms. If nonzero, function will wait for
3002         *            config success and report an error if it times out.
3003         *            If zero, no blocking or checking is performed.
3004         * @return Error Code generated by function. 0 indicates no error.
3005         */
3006        public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs) {
3007                int retval = MotControllerJNI.ConfigSetParameter(m_handle, param,  value, subValue, ordinal,
3008                                timeoutMs);
3009                return ErrorCode.valueOf(retval);
3010        }
3011        /**
3012         * Sets a parameter.
3013         *
3014         * @param param
3015         *            Parameter enumeration.
3016         * @param value
3017         *            Value of parameter.
3018         * @param subValue
3019         *            Subvalue for parameter. Maximum value of 255.
3020         * @param ordinal
3021         *            Ordinal of parameter.
3022         * @return Error Code generated by function. 0 indicates no error.
3023         */
3024        public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal) {
3025                int timeoutMs = 0;
3026                return configSetParameter( param,  value,  subValue,  ordinal,  timeoutMs);
3027        }
3028        /**
3029         * Gets a parameter.
3030         *
3031         * @param param
3032         *            Parameter enumeration.
3033         * @param ordinal
3034         *            Ordinal of parameter.
3035         * @param timeoutMs
3036         *            Timeout value in ms. If nonzero, function will wait for
3037         *            config success and report an error if it times out.
3038         *            If zero, no blocking or checking is performed.
3039         * @return Value of parameter.
3040         */
3041        public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
3042                return configGetParameter(param.value, ordinal, timeoutMs);
3043        }
3044        /**
3045         * Gets a parameter.
3046         *
3047         * @param param
3048         *            Parameter enumeration.
3049         * @param ordinal
3050         *            Ordinal of parameter.
3051         * @return Value of parameter.
3052         */
3053        public double configGetParameter(ParamEnum param, int ordinal) {
3054                int timeoutMs = 0;
3055                return configGetParameter(param, ordinal, timeoutMs);
3056        }
3057        /**
3058         * Gets a parameter.
3059         *
3060         * @param param
3061         *            Parameter enumeration.
3062         * @param ordinal
3063         *            Ordinal of parameter.
3064         * @param timeoutMs
3065         *            Timeout value in ms. If nonzero, function will wait for
3066         *            config success and report an error if it times out.
3067         *            If zero, no blocking or checking is performed.
3068         * @return Value of parameter.
3069         */
3070        public double configGetParameter(int param, int ordinal, int timeoutMs) {
3071                return MotControllerJNI.ConfigGetParameter(m_handle, param, ordinal, timeoutMs);
3072        }
3073        /**
3074         * Gets a parameter.
3075         *
3076         * @param param
3077         *            Parameter enumeration.
3078         * @param ordinal
3079         *            Ordinal of parameter.
3080         * @return Value of parameter.
3081         */
3082        public double configGetParameter(int param, int ordinal) {
3083                int timeoutMs = 0;
3084                return configGetParameter( param,  ordinal,  timeoutMs);
3085        }
3086
3087        // ------ Misc. ----------//
3088        public int getBaseID() {
3089                return MotControllerJNI.GetBaseID(m_handle);
3090        }
3091
3092        /**
3093         * @return control mode motor controller is in
3094         */
3095        public ControlMode getControlMode() {
3096                return m_controlMode;
3097        }
3098
3099        // ----- Follower ------//
3100        /**
3101         * Set the control mode and output value so that this motor controller will
3102         * follow another motor controller. Currently supports following Victor SPX,
3103         * Talon SRX, and Talon FX.
3104         *
3105         * @param masterToFollow
3106         *                                              Motor Controller object to follow.
3107         * @param followerType
3108         *                                              Type of following control.  Use AuxOutput1 to follow the master
3109         *                                              device's auxiliary output 1.
3110         *                                              Use PercentOutput for standard follower mode.
3111         */
3112        public void follow(IMotorController masterToFollow, FollowerType followerType) {
3113                int id32 = masterToFollow.getBaseID();
3114                int id24 = id32;
3115                id24 >>= 16;
3116                id24 = (short) id24;
3117                id24 <<= 8;
3118                id24 |= (id32 & 0xFF);
3119
3120                switch (followerType){
3121                        case PercentOutput:
3122                                set(ControlMode.Follower, (double)id24);
3123                                break;
3124                        case AuxOutput1:
3125                          /* follow the motor controller, but set the aux flag
3126                     * to ensure we follow the processed output */
3127                          set(ControlMode.Follower, (double)id24, DemandType.AuxPID, 0);
3128                                break;
3129                        default:
3130                          neutralOutput();
3131                                break;
3132                }
3133        }
3134        /**
3135         * Set the control mode and output value so that this motor controller will
3136         * follow another motor controller. Currently supports following Victor SPX,
3137         * Talon SRX, and Talon FX.
3138         *
3139         * @param masterToFollow Motor Controller to follow
3140         */
3141        public void follow(IMotorController masterToFollow) {
3142    follow(masterToFollow, FollowerType.PercentOutput);
3143        }
3144        /**
3145         * When master makes a device, this routine is called to signal the update.
3146         */
3147        public void valueUpdated() {
3148                // MT
3149        }
3150
3151    //------Config All------//
3152
3153    /**
3154     * Configures all base persistant settings.
3155     *
3156         * @param allConfigs        Object with all of the base persistant settings
3157     * @param timeoutMs
3158     *              Timeout value in ms. If nonzero, function will wait for
3159     *              config success and report an error if it times out.
3160     *              If zero, no blocking or checking is performed.
3161     *
3162     * @return Error Code generated by function. 0 indicates no error.
3163     */
3164    protected ErrorCode baseConfigAllSettings(BaseMotorControllerConfiguration allConfigs, int timeoutMs) {
3165
3166
3167        ErrorCollection errorCollection = new ErrorCollection();
3168
3169        errorCollection.NewError(configFactoryDefault(timeoutMs));
3170
3171        if(BaseMotorControllerUtil.openloopRampDifferent(allConfigs)) errorCollection.NewError(configOpenloopRamp(allConfigs.openloopRamp, timeoutMs));
3172                if(BaseMotorControllerUtil.closedloopRampDifferent(allConfigs)) errorCollection.NewError(configClosedloopRamp(allConfigs.closedloopRamp, timeoutMs));
3173                if(BaseMotorControllerUtil.peakOutputForwardDifferent(allConfigs)) errorCollection.NewError(configPeakOutputForward(allConfigs.peakOutputForward, timeoutMs));
3174                if(BaseMotorControllerUtil.peakOutputReverseDifferent(allConfigs)) errorCollection.NewError(configPeakOutputReverse(allConfigs.peakOutputReverse, timeoutMs));
3175                if(BaseMotorControllerUtil.nominalOutputForwardDifferent(allConfigs)) errorCollection.NewError(configNominalOutputForward(allConfigs.nominalOutputForward, timeoutMs));
3176                if(BaseMotorControllerUtil.nominalOutputReverseDifferent(allConfigs)) errorCollection.NewError(configNominalOutputReverse(allConfigs.nominalOutputReverse, timeoutMs));
3177                if(BaseMotorControllerUtil.neutralDeadbandDifferent(allConfigs)) errorCollection.NewError(configNeutralDeadband(allConfigs.neutralDeadband, timeoutMs));
3178                if(BaseMotorControllerUtil.voltageCompSaturationDifferent(allConfigs)) errorCollection.NewError(configVoltageCompSaturation(allConfigs.voltageCompSaturation, timeoutMs));
3179                if(BaseMotorControllerUtil.voltageMeasurementFilterDifferent(allConfigs)) errorCollection.NewError(configVoltageMeasurementFilter(allConfigs.voltageMeasurementFilter, timeoutMs));
3180                if(BaseMotorControllerUtil.velocityMeasurementPeriodDifferent(allConfigs)) errorCollection.NewError(configVelocityMeasurementPeriod(allConfigs.velocityMeasurementPeriod, timeoutMs));
3181                if(BaseMotorControllerUtil.velocityMeasurementWindowDifferent(allConfigs)) errorCollection.NewError(configVelocityMeasurementWindow(allConfigs.velocityMeasurementWindow, timeoutMs));
3182                if(BaseMotorControllerUtil.forwardSoftLimitThresholdDifferent(allConfigs)) errorCollection.NewError(configForwardSoftLimitThreshold(allConfigs.forwardSoftLimitThreshold, timeoutMs));
3183                if(BaseMotorControllerUtil.reverseSoftLimitThresholdDifferent(allConfigs)) errorCollection.NewError(configReverseSoftLimitThreshold(allConfigs.reverseSoftLimitThreshold, timeoutMs));
3184                if(BaseMotorControllerUtil.forwardSoftLimitEnableDifferent(allConfigs)) errorCollection.NewError(configForwardSoftLimitEnable(allConfigs.forwardSoftLimitEnable, timeoutMs));
3185                if(BaseMotorControllerUtil.reverseSoftLimitEnableDifferent(allConfigs)) errorCollection.NewError(configReverseSoftLimitEnable(allConfigs.reverseSoftLimitEnable, timeoutMs));
3186                if(BaseMotorControllerUtil.auxPIDPolarityDifferent(allConfigs)) errorCollection.NewError(configAuxPIDPolarity(allConfigs.auxPIDPolarity, timeoutMs));
3187                if(BaseMotorControllerUtil.motionCruiseVelocityDifferent(allConfigs)) errorCollection.NewError(configMotionCruiseVelocity(allConfigs.motionCruiseVelocity, timeoutMs));
3188                if(BaseMotorControllerUtil.motionAccelerationDifferent(allConfigs)) errorCollection.NewError(configMotionAcceleration(allConfigs.motionAcceleration, timeoutMs));
3189                if(BaseMotorControllerUtil.motionSCurveStrength(allConfigs)) errorCollection.NewError(configMotionSCurveStrength(allConfigs.motionCurveStrength, timeoutMs));
3190                if(BaseMotorControllerUtil.motionProfileTrajectoryPeriodDifferent(allConfigs)) errorCollection.NewError(configMotionProfileTrajectoryPeriod(allConfigs.motionProfileTrajectoryPeriod, timeoutMs));
3191                if(BaseMotorControllerUtil.feedbackNotContinuousDifferent(allConfigs)) errorCollection.NewError(configFeedbackNotContinuous(allConfigs.feedbackNotContinuous, timeoutMs));
3192                if(BaseMotorControllerUtil.remoteSensorClosedLoopDisableNeutralOnLOSDifferent(allConfigs)) errorCollection.NewError(configRemoteSensorClosedLoopDisableNeutralOnLOS(allConfigs.remoteSensorClosedLoopDisableNeutralOnLOS, timeoutMs));
3193                if(BaseMotorControllerUtil.clearPositionOnLimitFDifferent(allConfigs)) errorCollection.NewError(configClearPositionOnLimitF(allConfigs.clearPositionOnLimitF, timeoutMs));
3194                if(BaseMotorControllerUtil.clearPositionOnLimitRDifferent(allConfigs)) errorCollection.NewError(configClearPositionOnLimitR(allConfigs.clearPositionOnLimitR, timeoutMs));
3195                if(BaseMotorControllerUtil.clearPositionOnQuadIdxDifferent(allConfigs)) errorCollection.NewError(configClearPositionOnQuadIdx(allConfigs.clearPositionOnQuadIdx, timeoutMs));
3196                if(BaseMotorControllerUtil.limitSwitchDisableNeutralOnLOSDifferent(allConfigs)) errorCollection.NewError(configLimitSwitchDisableNeutralOnLOS(allConfigs.limitSwitchDisableNeutralOnLOS, timeoutMs));
3197                if(BaseMotorControllerUtil.softLimitDisableNeutralOnLOSDifferent(allConfigs)) errorCollection.NewError(configSoftLimitDisableNeutralOnLOS(allConfigs.softLimitDisableNeutralOnLOS, timeoutMs));
3198                if(BaseMotorControllerUtil.pulseWidthPeriod_EdgesPerRotDifferent(allConfigs)) errorCollection.NewError(configPulseWidthPeriod_EdgesPerRot(allConfigs.pulseWidthPeriod_EdgesPerRot, timeoutMs));
3199                if(BaseMotorControllerUtil.pulseWidthPeriod_FilterWindowSzDifferent(allConfigs)) errorCollection.NewError(configPulseWidthPeriod_FilterWindowSz(allConfigs.pulseWidthPeriod_FilterWindowSz, timeoutMs));
3200                if(BaseMotorControllerUtil.trajectoryInterpolationEnableDifferent(allConfigs)) errorCollection.NewError(configMotionProfileTrajectoryInterpolationEnable(allConfigs.trajectoryInterpolationEnable, timeoutMs));
3201
3202                //Custom Parameters
3203                if(BaseMotorControllerUtil.customParam0Different(allConfigs)) errorCollection.NewError(configSetCustomParam(allConfigs.customParam0, 0, timeoutMs));
3204                if(BaseMotorControllerUtil.customParam1Different(allConfigs)) errorCollection.NewError(configSetCustomParam(allConfigs.customParam1, 1, timeoutMs));
3205
3206        //--------Slots---------------//
3207        errorCollection.NewError(configureSlotPrivate(allConfigs.slot0, 0, timeoutMs, allConfigs.enableOptimizations));
3208        errorCollection.NewError(configureSlotPrivate(allConfigs.slot1, 1, timeoutMs, allConfigs.enableOptimizations));
3209        errorCollection.NewError(configureSlotPrivate(allConfigs.slot2, 2, timeoutMs, allConfigs.enableOptimizations));
3210        errorCollection.NewError(configureSlotPrivate(allConfigs.slot3, 3, timeoutMs, allConfigs.enableOptimizations));
3211
3212        //----------Remote Feedback Filters----------//
3213                errorCollection.NewError(configureFilter(allConfigs.remoteFilter0, 0, timeoutMs, allConfigs.enableOptimizations));
3214        errorCollection.NewError(configureFilter(allConfigs.remoteFilter1, 1, timeoutMs, allConfigs.enableOptimizations));
3215
3216        return errorCollection._worstError;
3217    }
3218
3219
3220    private ErrorCode configureSlotPrivate( SlotConfiguration slot, int slotIdx, int timeoutMs, boolean enableOptimization) {
3221
3222        ErrorCollection errorCollection = new ErrorCollection();
3223        //------ General Close loop ----------//
3224
3225
3226
3227                if(SlotConfigurationUtil.kPDifferent(slot) || !enableOptimization) errorCollection.NewError(config_kP(slotIdx, slot.kP, timeoutMs));
3228                if(SlotConfigurationUtil.kIDifferent(slot) || !enableOptimization) errorCollection.NewError(config_kI(slotIdx, slot.kI, timeoutMs));
3229                if(SlotConfigurationUtil.kDDifferent(slot) || !enableOptimization) errorCollection.NewError(config_kD(slotIdx, slot.kD, timeoutMs));
3230                if(SlotConfigurationUtil.kFDifferent(slot) || !enableOptimization) errorCollection.NewError(config_kF(slotIdx, slot.kF, timeoutMs));
3231                if(SlotConfigurationUtil.integralZoneDifferent(slot) || !enableOptimization) errorCollection.NewError(config_IntegralZone(slotIdx, slot.integralZone, timeoutMs));
3232                if(SlotConfigurationUtil.allowableClosedloopErrorDifferent(slot) || !enableOptimization) errorCollection.NewError(configAllowableClosedloopError(slotIdx, slot.allowableClosedloopError, timeoutMs));
3233                if(SlotConfigurationUtil.maxIntegralAccumulatorDifferent(slot) || !enableOptimization) errorCollection.NewError(configMaxIntegralAccumulator(slotIdx, slot.maxIntegralAccumulator, timeoutMs));
3234                if(SlotConfigurationUtil.closedLoopPeakOutputDifferent(slot) || !enableOptimization) errorCollection.NewError(configClosedLoopPeakOutput(slotIdx, slot.closedLoopPeakOutput, timeoutMs));
3235                if(SlotConfigurationUtil.closedLoopPeriodDifferent(slot) || !enableOptimization) errorCollection.NewError(configClosedLoopPeriod(slotIdx, slot.closedLoopPeriod, timeoutMs));
3236
3237        return errorCollection._worstError;
3238
3239    }
3240
3241
3242    /**
3243     * Configures all slot persistant settings (overloaded so timeoutMs is 50 ms
3244     * and slotIdx is 0
3245     *
3246         * @param slot        Object with all of the slot persistant settings
3247     *
3248     * @return Error Code generated by function. 0 indicates no error.
3249     */
3250    public ErrorCode configureSlot( SlotConfiguration slot) {
3251        int slotIdx = 0;
3252        int timeoutMs = 50;
3253        return configureSlotPrivate(slot, slotIdx, timeoutMs, false);
3254        }
3255        /**
3256     * Configures all slot persistant settings
3257     *
3258         * @param slot        Object with all of the slot persistant settings
3259         * @param slotIdx         Index of slot to configure
3260         * @param timeoutMs
3261     *              Timeout value in ms. If nonzero, function will wait for
3262     *              config success and report an error if it times out.
3263     *              If zero, no blocking or checking is performed.
3264     *
3265     * @return Error Code generated by function. 0 indicates no error.
3266     */
3267    public ErrorCode configureSlot( SlotConfiguration slot, int slotIdx, int timeoutMs) {
3268        return configureSlotPrivate(slot, slotIdx, timeoutMs, false);
3269    }
3270    /**
3271     * Gets all slot persistant settings.
3272     *
3273         * @param slot        Object with all of the slot persistant settings
3274         * @param slotIdx     Parameter slot for the constant.
3275     * @param timeoutMs
3276     *              Timeout value in ms. If nonzero, function will wait for
3277     *              config success and report an error if it times out.
3278     *              If zero, no blocking or checking is performed.
3279     */
3280    public void getSlotConfigs(SlotConfiguration slot, int slotIdx, int timeoutMs) {
3281        slot.kP = (double) configGetParameter(ParamEnum.eProfileParamSlot_P, slotIdx, timeoutMs);
3282        slot.kI = (double) configGetParameter(ParamEnum.eProfileParamSlot_I, slotIdx, timeoutMs);
3283        slot.kD = (double) configGetParameter(ParamEnum.eProfileParamSlot_D, slotIdx, timeoutMs);
3284        slot.kF = (double) configGetParameter(ParamEnum.eProfileParamSlot_F, slotIdx, timeoutMs);
3285        slot.integralZone = (int) configGetParameter(ParamEnum.eProfileParamSlot_IZone, slotIdx, timeoutMs);
3286        slot.allowableClosedloopError = (int) configGetParameter(ParamEnum.eProfileParamSlot_AllowableErr, slotIdx, timeoutMs);
3287        slot.maxIntegralAccumulator = (double) configGetParameter(ParamEnum.eProfileParamSlot_MaxIAccum, slotIdx, timeoutMs);
3288        slot.closedLoopPeakOutput = (double) configGetParameter(ParamEnum.eProfileParamSlot_PeakOutput, slotIdx, timeoutMs);
3289        slot.closedLoopPeriod = (int) configGetParameter(ParamEnum.ePIDLoopPeriod, slotIdx, timeoutMs);
3290    }
3291    /**
3292     * Gets all slot persistant settings (overloaded so timeoutMs is 50 ms
3293     * and slotIdx is 0
3294     *
3295         * @param slot        Object with all of the slot persistant settings
3296     */
3297    public void getSlotConfigs( SlotConfiguration slot) {
3298        int slotIdx = 0;
3299        int timeoutMs = 50;
3300        getSlotConfigs(slot, slotIdx, timeoutMs);
3301    }
3302
3303
3304    /**
3305     * Configures all filter persistant settings.
3306     *
3307         * @deprecated Use the 3-parameter configureFilter.  4-param version is deprecated and will be removed.
3308         * @param filter        Object with all of the filter persistant settings
3309     * @param ordinal       0 for remote sensor 0 and 1 for remote sensor 1.
3310     * @param timeoutMs
3311     *              Timeout value in ms. If nonzero, function will wait for
3312     *              config success and report an error if it times out.
3313     *              If zero, no blocking or checking is performed.
3314         * @param enableOptimizations   Enable the optimization technique
3315     *
3316     * @return Error Code generated by function. 0 indicates no error.
3317     */
3318        @Deprecated
3319    public ErrorCode configureFilter( FilterConfiguration filter, int ordinal, int timeoutMs, boolean enableOptimizations) {
3320                if(FilterConfigUtil.filterConfigurationDifferent(filter) || !enableOptimizations)
3321                        return configRemoteFeedbackFilter(filter.remoteSensorDeviceID, filter.remoteSensorSource, ordinal, timeoutMs);
3322
3323                return ErrorCode.OK;
3324        }
3325        /**
3326     * Configures all filter persistant settings.
3327     *
3328         * @deprecated Use configAll instead.
3329         * @param filter        Object with all of the filter persistant settings
3330     * @param ordinal       0 for remote sensor 0 and 1 for remote sensor 1.
3331     * @param timeoutMs
3332     *              Timeout value in ms. If nonzero, function will wait for
3333     *              config success and report an error if it times out.
3334     *              If zero, no blocking or checking is performed.
3335     *
3336     * @return Error Code generated by function. 0 indicates no error.
3337     */
3338        @Deprecated
3339    public ErrorCode configureFilter( FilterConfiguration filter, int ordinal, int timeoutMs) {
3340                return configureFilter(filter, ordinal, timeoutMs, false);
3341    }
3342    /**
3343     * Configures all filter persistant settings (overloaded so timeoutMs is 50 ms
3344     * and ordinal is 0).
3345     *
3346         * @deprecated Use configAll instead.
3347         * @param filter        Object with all of the filter persistant settings
3348     *
3349     * @return Error Code generated by function. 0 indicates no error.
3350     */
3351        @Deprecated
3352    public ErrorCode configureFilter( FilterConfiguration filter) {
3353        int ordinal = 0;
3354        int timeoutMs = 50;
3355        return configureFilter(filter, ordinal, timeoutMs, false);
3356    }
3357
3358    /**
3359     * Gets all filter persistant settings.
3360     *
3361         * @param filter        Object with all of the filter persistant settings
3362     * @param ordinal       0 for remote sensor 0 and 1 for remote sensor 1.
3363     * @param timeoutMs
3364     *              Timeout value in ms. If nonzero, function will wait for
3365     *              config success and report an error if it times out.
3366     *              If zero, no blocking or checking is performed.
3367     */
3368    public void getFilterConfigs(FilterConfiguration filter, int ordinal, int timeoutMs) {
3369
3370        filter.remoteSensorDeviceID = (int) configGetParameter(ParamEnum.eRemoteSensorDeviceID, ordinal, timeoutMs);
3371        filter.remoteSensorSource = RemoteSensorSource.valueOf(configGetParameter(ParamEnum.eRemoteSensorSource, ordinal, timeoutMs));
3372
3373    }
3374    /**
3375     * Gets all filter persistant settings (overloaded so timeoutMs is 50 ms
3376     * and ordinal is 0).
3377     *
3378         * @param filter        Object with all of the filter persistant settings
3379     */
3380    public void getFilterConfigs(FilterConfiguration filter) {
3381        int ordinal = 0;
3382        int timeoutMs = 50;
3383        getFilterConfigs(filter, ordinal, timeoutMs);
3384    }
3385    /**
3386     * Configures all base PID set persistant settings.
3387     *
3388         * @param pid           Object with all of the base PID set persistant settings
3389     * @param pidIdx        0 for Primary closed-loop. 1 for auxiliary closed-loop.
3390     * @param timeoutMs
3391     *              Timeout value in ms. If nonzero, function will wait for
3392     *              config success and report an error if it times out.
3393     *              If zero, no blocking or checking is performed.
3394     *
3395     * @return Error Code generated by function. 0 indicates no error.
3396     */
3397    protected ErrorCode baseConfigurePID(BasePIDSetConfiguration pid, int pidIdx, int timeoutMs) {
3398
3399        return configSelectedFeedbackCoefficient(pid.selectedFeedbackCoefficient, pidIdx, timeoutMs);
3400
3401    }
3402    /**
3403     * Gets all base PID set persistant settings.
3404     *
3405         * @param pid           Object with all of the base PID set persistant settings
3406     * @param pidIdx        0 for Primary closed-loop. 1 for auxiliary closed-loop.
3407     * @param timeoutMs
3408     *              Timeout value in ms. If nonzero, function will wait for
3409     *              config success and report an error if it times out.
3410     *              If zero, no blocking or checking is performed.
3411     */
3412    protected void baseGetPIDConfigs(BasePIDSetConfiguration pid, int pidIdx, int timeoutMs) {
3413
3414        pid.selectedFeedbackCoefficient = (double) configGetParameter(ParamEnum.eSelectedSensorCoefficient, pidIdx, timeoutMs);
3415
3416    }
3417    /**
3418     * Gets all base persistant settings.
3419     *
3420         * @param allConfigs        Object with all of the base persistant settings
3421     * @param timeoutMs
3422     *              Timeout value in ms. If nonzero, function will wait for
3423     *              config success and report an error if it times out.
3424     *              If zero, no blocking or checking is performed.
3425     */
3426    protected void baseGetAllConfigs(BaseMotorControllerConfiguration allConfigs, int timeoutMs) {
3427
3428
3429        allConfigs.openloopRamp = (double) configGetParameter(ParamEnum.eOpenloopRamp, 0, timeoutMs);
3430        allConfigs.closedloopRamp = (double) configGetParameter(ParamEnum.eClosedloopRamp, 0, timeoutMs);
3431        allConfigs.peakOutputForward = (double) configGetParameter(ParamEnum.ePeakPosOutput, 0, timeoutMs);
3432        allConfigs.peakOutputReverse = (double) configGetParameter(ParamEnum.ePeakNegOutput, 0, timeoutMs);
3433        allConfigs.nominalOutputForward = (double) configGetParameter(ParamEnum.eNominalPosOutput, 0, timeoutMs);
3434        allConfigs.nominalOutputReverse = (double) configGetParameter(ParamEnum.eNominalNegOutput, 0, timeoutMs);
3435        allConfigs.neutralDeadband = (double) configGetParameter(ParamEnum.eNeutralDeadband, 0, timeoutMs);
3436        allConfigs.voltageCompSaturation = (double) configGetParameter(ParamEnum.eNominalBatteryVoltage, 0, timeoutMs);
3437        allConfigs.voltageMeasurementFilter = (int) configGetParameter(ParamEnum.eBatteryVoltageFilterSize, 0, timeoutMs);
3438        allConfigs.velocityMeasurementPeriod = SensorVelocityMeasPeriod.valueOf(configGetParameter(ParamEnum.eSampleVelocityPeriod, 0, timeoutMs));
3439        allConfigs.velocityMeasurementWindow = (int) configGetParameter(ParamEnum.eSampleVelocityWindow, 0, timeoutMs);
3440        allConfigs.forwardSoftLimitThreshold = (int) configGetParameter(ParamEnum.eForwardSoftLimitThreshold, 0, timeoutMs);
3441        allConfigs.reverseSoftLimitThreshold = (int) configGetParameter(ParamEnum.eReverseSoftLimitThreshold, 0, timeoutMs);
3442        allConfigs.forwardSoftLimitEnable = configGetParameter(ParamEnum.eForwardSoftLimitEnable, 0, timeoutMs) != 0.0;
3443        allConfigs.reverseSoftLimitEnable = configGetParameter(ParamEnum.eReverseSoftLimitEnable, 0, timeoutMs) != 0.0; //Note, fix in firmware
3444
3445        getSlotConfigs(allConfigs.slot0, 0, timeoutMs);
3446        getSlotConfigs(allConfigs.slot1, 1, timeoutMs);
3447        getSlotConfigs(allConfigs.slot2, 2, timeoutMs);
3448        getSlotConfigs(allConfigs.slot3, 3, timeoutMs);
3449
3450        allConfigs.auxPIDPolarity = configGetParameter(ParamEnum.ePIDLoopPolarity, 1, timeoutMs) != 0.0;
3451
3452        getFilterConfigs(allConfigs.remoteFilter0, 0, timeoutMs);
3453        getFilterConfigs(allConfigs.remoteFilter1, 1, timeoutMs);
3454
3455        allConfigs.motionCruiseVelocity = (int) configGetParameter(ParamEnum.eMotMag_VelCruise, 0, timeoutMs);
3456                allConfigs.motionAcceleration = (int) configGetParameter(ParamEnum.eMotMag_Accel, 0, timeoutMs);
3457                allConfigs.motionCurveStrength = (int) configGetParameter(ParamEnum.eMotMag_SCurveLevel, 0, timeoutMs);
3458        allConfigs.motionProfileTrajectoryPeriod = (int) configGetParameter(ParamEnum.eMotionProfileTrajectoryPointDurationMs, 0, timeoutMs);
3459        allConfigs.customParam0 = (int) configGetParameter(ParamEnum.eCustomParam, 0,  timeoutMs);
3460        allConfigs.customParam1 = (int) configGetParameter(ParamEnum.eCustomParam, 1,  timeoutMs);
3461
3462
3463        allConfigs.feedbackNotContinuous = configGetParameter(ParamEnum.eFeedbackNotContinuous, 0, timeoutMs) != 0.0;
3464        allConfigs.remoteSensorClosedLoopDisableNeutralOnLOS = configGetParameter(ParamEnum.eRemoteSensorClosedLoopDisableNeutralOnLOS, 0, timeoutMs) != 0.0;
3465        allConfigs.clearPositionOnLimitF = configGetParameter(ParamEnum.eClearPositionOnLimitF, 0, timeoutMs) != 0.0;
3466        allConfigs.clearPositionOnLimitR = configGetParameter(ParamEnum.eClearPositionOnLimitR, 0, timeoutMs) != 0.0;
3467        allConfigs.clearPositionOnQuadIdx = configGetParameter(ParamEnum.eClearPositionOnQuadIdx, 0, timeoutMs) != 0.0;
3468        allConfigs.limitSwitchDisableNeutralOnLOS = configGetParameter(ParamEnum.eLimitSwitchDisableNeutralOnLOS, 0, timeoutMs) != 0.0;
3469        allConfigs.softLimitDisableNeutralOnLOS = configGetParameter(ParamEnum.eSoftLimitDisableNeutralOnLOS, 0, timeoutMs) != 0.0;
3470        allConfigs.pulseWidthPeriod_EdgesPerRot = (int) configGetParameter(ParamEnum.ePulseWidthPeriod_EdgesPerRot, 0, timeoutMs);
3471        allConfigs.pulseWidthPeriod_FilterWindowSz = (int) configGetParameter(ParamEnum.ePulseWidthPeriod_FilterWindowSz, 0, timeoutMs);
3472
3473
3474    }
3475
3476}