001/*
002 * Copyright (C) Cross The Road Electronics.  All rights reserved.
003 * License information can be found in CTRE_LICENSE.txt
004 * For support and suggestions contact support@ctr-electronics.com or file
005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
006 */
007package com.ctre.phoenix6.configs;
008
009import com.ctre.phoenix6.StatusCode;
010import com.ctre.phoenix6.configs.jni.ConfigJNI;
011import com.ctre.phoenix6.spns.*;
012import com.ctre.phoenix6.signals.*;
013
014import edu.wpi.first.units.*;
015
016import edu.wpi.first.units.measure.*;
017import static edu.wpi.first.units.Units.*;
018import com.ctre.phoenix6.hardware.core.CoreCANcoder;
019import com.ctre.phoenix6.hardware.core.CoreCANdi;
020
021/**
022 * Configs that affect the feedback of this motor controller.
023 * <p>
024 * Includes feedback sensor source, any offsets for the feedback
025 * sensor, and various ratios to describe the relationship between the
026 * sensor and the mechanism for closed looping.
027 */
028public class FeedbackConfigs implements ParentConfiguration
029{
030    /**
031     * The offset applied to the absolute integrated rotor sensor.  This
032     * can be used to zero the rotor in applications that are within one
033     * rotor rotation.
034     * 
035     * <ul>
036     *   <li> <b>Minimum Value:</b> -1
037     *   <li> <b>Maximum Value:</b> 1
038     *   <li> <b>Default Value:</b> 0.0
039     *   <li> <b>Units:</b> rotations
040     * </ul>
041     */
042    public double FeedbackRotorOffset = 0.0;
043    /**
044     * The ratio of sensor rotations to the mechanism's output, where a
045     * ratio greater than 1 is a reduction.
046     * <p>
047     * This is equivalent to the mechanism's gear ratio if the sensor is
048     * located on the input of a gearbox.  If sensor is on the output of a
049     * gearbox, then this is typically set to 1.
050     * <p>
051     * We recommend against using this config to perform onboard unit
052     * conversions.  Instead, unit conversions should be performed in
053     * robot code using the units library.
054     * <p>
055     * If this is set to zero, the device will reset back to one.
056     * 
057     * <ul>
058     *   <li> <b>Minimum Value:</b> -1000
059     *   <li> <b>Maximum Value:</b> 1000
060     *   <li> <b>Default Value:</b> 1.0
061     *   <li> <b>Units:</b> scalar
062     * </ul>
063     */
064    public double SensorToMechanismRatio = 1.0;
065    /**
066     * The ratio of motor rotor rotations to remote sensor rotations,
067     * where a ratio greater than 1 is a reduction.
068     * <p>
069     * The Talon FX is capable of fusing a remote CANcoder with its rotor
070     * sensor to produce a high-bandwidth sensor source.  This feature
071     * requires specifying the ratio between the motor rotor and the
072     * remote sensor.
073     * <p>
074     * If this is set to zero, the device will reset back to one.
075     * 
076     * <ul>
077     *   <li> <b>Minimum Value:</b> -1000
078     *   <li> <b>Maximum Value:</b> 1000
079     *   <li> <b>Default Value:</b> 1.0
080     *   <li> <b>Units:</b> scalar
081     * </ul>
082     */
083    public double RotorToSensorRatio = 1.0;
084    /**
085     * Choose what sensor source is reported via API and used by
086     * closed-loop and limit features.  The default is RotorSensor, which
087     * uses the internal rotor sensor in the Talon.
088     * <p>
089     * Choose Remote* to use another sensor on the same CAN bus (this also
090     * requires setting FeedbackRemoteSensorID).  Talon will update its
091     * position and velocity whenever the remote sensor publishes its
092     * information on CAN bus, and the Talon internal rotor will not be
093     * used.
094     * <p>
095     * Choose Fused* (requires Phoenix Pro) and Talon will fuse another
096     * sensor's information with the internal rotor, which provides the
097     * best possible position and velocity for accuracy and bandwidth
098     * (this also requires setting FeedbackRemoteSensorID).  This was
099     * developed for applications such as swerve-azimuth.
100     * <p>
101     * Choose Sync* (requires Phoenix Pro) and Talon will synchronize its
102     * internal rotor position against another sensor, then continue to
103     * use the rotor sensor for closed loop control (this also requires
104     * setting FeedbackRemoteSensorID).  The Talon will report if its
105     * internal position differs significantly from the reported remote
106     * sensor position.  This was developed for mechanisms where there is
107     * a risk of the sensor failing in such a way that it reports a
108     * position that does not match the mechanism, such as the sensor
109     * mounting assembly breaking off.
110     * <p>
111     * Choose RemotePigeon2_Yaw, RemotePigeon2_Pitch, and
112     * RemotePigeon2_Roll to use another Pigeon2 on the same CAN bus (this
113     * also requires setting FeedbackRemoteSensorID).  Talon will update
114     * its position to match the selected value whenever Pigeon2 publishes
115     * its information on CAN bus. Note that the Talon position will be in
116     * rotations and not degrees.
117     * <p>
118     * Note: When the feedback source is changed to Fused* or Sync*, the
119     * Talon needs a period of time to fuse before sensor-based
120     * (soft-limit, closed loop, etc.) features are used. This period of
121     * time is determined by the update frequency of the remote sensor's
122     * Position signal.
123     * 
124     */
125    public FeedbackSensorSourceValue FeedbackSensorSource = FeedbackSensorSourceValue.RotorSensor;
126    /**
127     * Device ID of which remote device to use.  This is not used if the
128     * Sensor Source is the internal rotor sensor.
129     * 
130     * <ul>
131     *   <li> <b>Minimum Value:</b> 0
132     *   <li> <b>Maximum Value:</b> 62
133     *   <li> <b>Default Value:</b> 0
134     *   <li> <b>Units:</b> 
135     * </ul>
136     */
137    public int FeedbackRemoteSensorID = 0;
138    /**
139     * The configurable time constant of the Kalman velocity filter. The
140     * velocity Kalman filter will adjust to act as a low-pass with this
141     * value as its time constant.
142     * <p>
143     * If the user is aiming for an expected cutoff frequency, the
144     * frequency is calculated as 1 / (2 * π * τ) with τ being the time
145     * constant.
146     * 
147     * <ul>
148     *   <li> <b>Minimum Value:</b> 0
149     *   <li> <b>Maximum Value:</b> 1
150     *   <li> <b>Default Value:</b> 0
151     *   <li> <b>Units:</b> seconds
152     * </ul>
153     */
154    public double VelocityFilterTimeConstant = 0;
155    
156    /**
157     * Modifies this configuration's FeedbackRotorOffset parameter and returns itself for
158     * method-chaining and easier to use config API.
159     * <p>
160     * The offset applied to the absolute integrated rotor sensor.  This
161     * can be used to zero the rotor in applications that are within one
162     * rotor rotation.
163     * 
164     * <ul>
165     *   <li> <b>Minimum Value:</b> -1
166     *   <li> <b>Maximum Value:</b> 1
167     *   <li> <b>Default Value:</b> 0.0
168     *   <li> <b>Units:</b> rotations
169     * </ul>
170     *
171     * @param newFeedbackRotorOffset Parameter to modify
172     * @return Itself
173     */
174    public FeedbackConfigs withFeedbackRotorOffset(double newFeedbackRotorOffset)
175    {
176        FeedbackRotorOffset = newFeedbackRotorOffset;
177        return this;
178    }
179    
180    /**
181     * Modifies this configuration's FeedbackRotorOffset parameter and returns itself for
182     * method-chaining and easier to use config API.
183     * <p>
184     * The offset applied to the absolute integrated rotor sensor.  This
185     * can be used to zero the rotor in applications that are within one
186     * rotor rotation.
187     * 
188     * <ul>
189     *   <li> <b>Minimum Value:</b> -1
190     *   <li> <b>Maximum Value:</b> 1
191     *   <li> <b>Default Value:</b> 0.0
192     *   <li> <b>Units:</b> rotations
193     * </ul>
194     *
195     * @param newFeedbackRotorOffset Parameter to modify
196     * @return Itself
197     */
198    public FeedbackConfigs withFeedbackRotorOffset(Angle newFeedbackRotorOffset)
199    {
200        FeedbackRotorOffset = newFeedbackRotorOffset.in(Rotations);
201        return this;
202    }
203    
204    /**
205     * Helper method to get this configuration's FeedbackRotorOffset parameter converted
206     * to a unit type. If not using the Java units library, {@link #FeedbackRotorOffset}
207     * can be accessed directly instead.
208     * <p>
209     * The offset applied to the absolute integrated rotor sensor.  This
210     * can be used to zero the rotor in applications that are within one
211     * rotor rotation.
212     * 
213     * <ul>
214     *   <li> <b>Minimum Value:</b> -1
215     *   <li> <b>Maximum Value:</b> 1
216     *   <li> <b>Default Value:</b> 0.0
217     *   <li> <b>Units:</b> rotations
218     * </ul>
219     *
220     * @return FeedbackRotorOffset
221     */
222    public Angle getFeedbackRotorOffsetMeasure()
223    {
224        return Rotations.of(FeedbackRotorOffset);
225    }
226    
227    /**
228     * Modifies this configuration's SensorToMechanismRatio parameter and returns itself for
229     * method-chaining and easier to use config API.
230     * <p>
231     * The ratio of sensor rotations to the mechanism's output, where a
232     * ratio greater than 1 is a reduction.
233     * <p>
234     * This is equivalent to the mechanism's gear ratio if the sensor is
235     * located on the input of a gearbox.  If sensor is on the output of a
236     * gearbox, then this is typically set to 1.
237     * <p>
238     * We recommend against using this config to perform onboard unit
239     * conversions.  Instead, unit conversions should be performed in
240     * robot code using the units library.
241     * <p>
242     * If this is set to zero, the device will reset back to one.
243     * 
244     * <ul>
245     *   <li> <b>Minimum Value:</b> -1000
246     *   <li> <b>Maximum Value:</b> 1000
247     *   <li> <b>Default Value:</b> 1.0
248     *   <li> <b>Units:</b> scalar
249     * </ul>
250     *
251     * @param newSensorToMechanismRatio Parameter to modify
252     * @return Itself
253     */
254    public FeedbackConfigs withSensorToMechanismRatio(double newSensorToMechanismRatio)
255    {
256        SensorToMechanismRatio = newSensorToMechanismRatio;
257        return this;
258    }
259    
260    /**
261     * Modifies this configuration's RotorToSensorRatio parameter and returns itself for
262     * method-chaining and easier to use config API.
263     * <p>
264     * The ratio of motor rotor rotations to remote sensor rotations,
265     * where a ratio greater than 1 is a reduction.
266     * <p>
267     * The Talon FX is capable of fusing a remote CANcoder with its rotor
268     * sensor to produce a high-bandwidth sensor source.  This feature
269     * requires specifying the ratio between the motor rotor and the
270     * remote sensor.
271     * <p>
272     * If this is set to zero, the device will reset back to one.
273     * 
274     * <ul>
275     *   <li> <b>Minimum Value:</b> -1000
276     *   <li> <b>Maximum Value:</b> 1000
277     *   <li> <b>Default Value:</b> 1.0
278     *   <li> <b>Units:</b> scalar
279     * </ul>
280     *
281     * @param newRotorToSensorRatio Parameter to modify
282     * @return Itself
283     */
284    public FeedbackConfigs withRotorToSensorRatio(double newRotorToSensorRatio)
285    {
286        RotorToSensorRatio = newRotorToSensorRatio;
287        return this;
288    }
289    
290    /**
291     * Modifies this configuration's FeedbackSensorSource parameter and returns itself for
292     * method-chaining and easier to use config API.
293     * <p>
294     * Choose what sensor source is reported via API and used by
295     * closed-loop and limit features.  The default is RotorSensor, which
296     * uses the internal rotor sensor in the Talon.
297     * <p>
298     * Choose Remote* to use another sensor on the same CAN bus (this also
299     * requires setting FeedbackRemoteSensorID).  Talon will update its
300     * position and velocity whenever the remote sensor publishes its
301     * information on CAN bus, and the Talon internal rotor will not be
302     * used.
303     * <p>
304     * Choose Fused* (requires Phoenix Pro) and Talon will fuse another
305     * sensor's information with the internal rotor, which provides the
306     * best possible position and velocity for accuracy and bandwidth
307     * (this also requires setting FeedbackRemoteSensorID).  This was
308     * developed for applications such as swerve-azimuth.
309     * <p>
310     * Choose Sync* (requires Phoenix Pro) and Talon will synchronize its
311     * internal rotor position against another sensor, then continue to
312     * use the rotor sensor for closed loop control (this also requires
313     * setting FeedbackRemoteSensorID).  The Talon will report if its
314     * internal position differs significantly from the reported remote
315     * sensor position.  This was developed for mechanisms where there is
316     * a risk of the sensor failing in such a way that it reports a
317     * position that does not match the mechanism, such as the sensor
318     * mounting assembly breaking off.
319     * <p>
320     * Choose RemotePigeon2_Yaw, RemotePigeon2_Pitch, and
321     * RemotePigeon2_Roll to use another Pigeon2 on the same CAN bus (this
322     * also requires setting FeedbackRemoteSensorID).  Talon will update
323     * its position to match the selected value whenever Pigeon2 publishes
324     * its information on CAN bus. Note that the Talon position will be in
325     * rotations and not degrees.
326     * <p>
327     * Note: When the feedback source is changed to Fused* or Sync*, the
328     * Talon needs a period of time to fuse before sensor-based
329     * (soft-limit, closed loop, etc.) features are used. This period of
330     * time is determined by the update frequency of the remote sensor's
331     * Position signal.
332     * 
333     *
334     * @param newFeedbackSensorSource Parameter to modify
335     * @return Itself
336     */
337    public FeedbackConfigs withFeedbackSensorSource(FeedbackSensorSourceValue newFeedbackSensorSource)
338    {
339        FeedbackSensorSource = newFeedbackSensorSource;
340        return this;
341    }
342    
343    /**
344     * Modifies this configuration's FeedbackRemoteSensorID parameter and returns itself for
345     * method-chaining and easier to use config API.
346     * <p>
347     * Device ID of which remote device to use.  This is not used if the
348     * Sensor Source is the internal rotor sensor.
349     * 
350     * <ul>
351     *   <li> <b>Minimum Value:</b> 0
352     *   <li> <b>Maximum Value:</b> 62
353     *   <li> <b>Default Value:</b> 0
354     *   <li> <b>Units:</b> 
355     * </ul>
356     *
357     * @param newFeedbackRemoteSensorID Parameter to modify
358     * @return Itself
359     */
360    public FeedbackConfigs withFeedbackRemoteSensorID(int newFeedbackRemoteSensorID)
361    {
362        FeedbackRemoteSensorID = newFeedbackRemoteSensorID;
363        return this;
364    }
365    
366    /**
367     * Modifies this configuration's VelocityFilterTimeConstant parameter and returns itself for
368     * method-chaining and easier to use config API.
369     * <p>
370     * The configurable time constant of the Kalman velocity filter. The
371     * velocity Kalman filter will adjust to act as a low-pass with this
372     * value as its time constant.
373     * <p>
374     * If the user is aiming for an expected cutoff frequency, the
375     * frequency is calculated as 1 / (2 * π * τ) with τ being the time
376     * constant.
377     * 
378     * <ul>
379     *   <li> <b>Minimum Value:</b> 0
380     *   <li> <b>Maximum Value:</b> 1
381     *   <li> <b>Default Value:</b> 0
382     *   <li> <b>Units:</b> seconds
383     * </ul>
384     *
385     * @param newVelocityFilterTimeConstant Parameter to modify
386     * @return Itself
387     */
388    public FeedbackConfigs withVelocityFilterTimeConstant(double newVelocityFilterTimeConstant)
389    {
390        VelocityFilterTimeConstant = newVelocityFilterTimeConstant;
391        return this;
392    }
393    
394    /**
395     * Modifies this configuration's VelocityFilterTimeConstant parameter and returns itself for
396     * method-chaining and easier to use config API.
397     * <p>
398     * The configurable time constant of the Kalman velocity filter. The
399     * velocity Kalman filter will adjust to act as a low-pass with this
400     * value as its time constant.
401     * <p>
402     * If the user is aiming for an expected cutoff frequency, the
403     * frequency is calculated as 1 / (2 * π * τ) with τ being the time
404     * constant.
405     * 
406     * <ul>
407     *   <li> <b>Minimum Value:</b> 0
408     *   <li> <b>Maximum Value:</b> 1
409     *   <li> <b>Default Value:</b> 0
410     *   <li> <b>Units:</b> seconds
411     * </ul>
412     *
413     * @param newVelocityFilterTimeConstant Parameter to modify
414     * @return Itself
415     */
416    public FeedbackConfigs withVelocityFilterTimeConstant(Time newVelocityFilterTimeConstant)
417    {
418        VelocityFilterTimeConstant = newVelocityFilterTimeConstant.in(Seconds);
419        return this;
420    }
421    
422    /**
423     * Helper method to get this configuration's VelocityFilterTimeConstant parameter converted
424     * to a unit type. If not using the Java units library, {@link #VelocityFilterTimeConstant}
425     * can be accessed directly instead.
426     * <p>
427     * The configurable time constant of the Kalman velocity filter. The
428     * velocity Kalman filter will adjust to act as a low-pass with this
429     * value as its time constant.
430     * <p>
431     * If the user is aiming for an expected cutoff frequency, the
432     * frequency is calculated as 1 / (2 * π * τ) with τ being the time
433     * constant.
434     * 
435     * <ul>
436     *   <li> <b>Minimum Value:</b> 0
437     *   <li> <b>Maximum Value:</b> 1
438     *   <li> <b>Default Value:</b> 0
439     *   <li> <b>Units:</b> seconds
440     * </ul>
441     *
442     * @return VelocityFilterTimeConstant
443     */
444    public Time getVelocityFilterTimeConstantMeasure()
445    {
446        return Seconds.of(VelocityFilterTimeConstant);
447    }
448    
449    /**
450     * Helper method to configure this feedback group to use
451     * RemoteCANcoder by passing in the CANcoder object.
452     * <p>
453     * When using RemoteCANcoder, the Talon will use another CANcoder on
454     * the same CAN bus. The Talon will update its position and velocity
455     * whenever CANcoder publishes its information on CAN bus, and the
456     * Talon internal rotor will not be used.
457     * 
458     * @param device CANcoder reference to use for RemoteCANcoder
459     * @return Itself
460     */
461    public FeedbackConfigs withRemoteCANcoder(CoreCANcoder device)
462    {
463        FeedbackSensorSource = FeedbackSensorSourceValue.RemoteCANcoder;
464        FeedbackRemoteSensorID = device.getDeviceID();
465        return this;
466    }
467    
468    /**
469     * Helper method to configure this feedback group to use FusedCANcoder
470     * by passing in the CANcoder object.
471     * <p>
472     * When using FusedCANcoder (requires Phoenix Pro), the Talon will
473     * fuse another CANcoder's information with the internal rotor, which
474     * provides the best possible position and velocity for accuracy and
475     * bandwidth. FusedCANcoder was developed for applications such as
476     * swerve-azimuth.
477     * 
478     * @param device CANcoder reference to use for FusedCANcoder
479     * @return Itself
480     */
481    public FeedbackConfigs withFusedCANcoder(CoreCANcoder device)
482    {
483        FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANcoder;
484        FeedbackRemoteSensorID = device.getDeviceID();
485        return this;
486    }
487    
488    /**
489     * Helper method to configure this feedback group to use SyncCANcoder
490     * by passing in the CANcoder object.
491     * <p>
492     * When using SyncCANcoder (requires Phoenix Pro), the Talon will
493     * synchronize its internal rotor position against another CANcoder,
494     * then continue to use the rotor sensor for closed loop control. The
495     * Talon will report if its internal position differs significantly
496     * from the reported CANcoder position. SyncCANcoder was developed for
497     * mechanisms where there is a risk of the CANcoder failing in such a
498     * way that it reports a position that does not match the mechanism,
499     * such as the sensor mounting assembly breaking off.
500     * 
501     * @param device CANcoder reference to use for SyncCANcoder
502     * @return Itself
503     */
504    public FeedbackConfigs withSyncCANcoder(CoreCANcoder device)
505    {
506        FeedbackSensorSource = FeedbackSensorSourceValue.SyncCANcoder;
507        FeedbackRemoteSensorID = device.getDeviceID();
508        return this;
509    }
510    
511    /**
512     * Helper method to configure this feedback group to use RemoteCANdi
513     * PWM 1 by passing in the CANdi object.
514     * 
515     * @param device CANdi reference to use for RemoteCANdi
516     * @return Itself
517     */
518    public FeedbackConfigs withRemoteCANdiPwm1(CoreCANdi device)
519    {
520        FeedbackSensorSource = FeedbackSensorSourceValue.RemoteCANdiPWM1;
521        FeedbackRemoteSensorID = device.getDeviceID();
522        return this;
523    }
524    
525    /**
526     * Helper method to configure this feedback group to use RemoteCANdi
527     * PWM 2 by passing in the CANdi object.
528     * 
529     * @param device CANdi reference to use for RemoteCANdi
530     * @return Itself
531     */
532    public FeedbackConfigs withRemoteCANdiPwm2(CoreCANdi device)
533    {
534        FeedbackSensorSource = FeedbackSensorSourceValue.RemoteCANdiPWM2;
535        FeedbackRemoteSensorID = device.getDeviceID();
536        return this;
537    }
538    
539    /**
540     * Helper method to configure this feedback group to use RemoteCANdi
541     * Quadrature by passing in the CANdi object.
542     * 
543     * @param device CANdi reference to use for RemoteCANdi
544     * @return Itself
545     */
546    public FeedbackConfigs withRemoteCANdiQuadrature(CoreCANdi device)
547    {
548        FeedbackSensorSource = FeedbackSensorSourceValue.RemoteCANdiQuadrature;
549        FeedbackRemoteSensorID = device.getDeviceID();
550        return this;
551    }
552    
553    /**
554     * Helper method to configure this feedback group to use FusedCANdi
555     * PWM 1 by passing in the CANdi object.
556     * <p>
557     * When using FusedCANdi (requires Phoenix Pro), the Talon will fuse
558     * another CANdi™ branded device's information with the internal
559     * rotor, which provides the best possible position and velocity for
560     * accuracy and bandwidth.
561     * 
562     * @param device CANdi reference to use for FusedCANdi
563     * @return Itself
564     */
565    public FeedbackConfigs withFusedCANdiPwm1(CoreCANdi device)
566    {
567        FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANdiPWM1;
568        FeedbackRemoteSensorID = device.getDeviceID();
569        return this;
570    }
571    
572    /**
573     * Helper method to configure this feedback group to use FusedCANdi
574     * PWM 2 by passing in the CANdi object.
575     * <p>
576     * When using FusedCANdi (requires Phoenix Pro), the Talon will fuse
577     * another CANdi™ branded device's information with the internal
578     * rotor, which provides the best possible position and velocity for
579     * accuracy and bandwidth.
580     * 
581     * @param device CANdi reference to use for FusedCANdi
582     * @return Itself
583     */
584    public FeedbackConfigs withFusedCANdiPwm2(CoreCANdi device)
585    {
586        FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANdiPWM2;
587        FeedbackRemoteSensorID = device.getDeviceID();
588        return this;
589    }
590    
591    /**
592     * Helper method to configure this feedback group to use FusedCANdi
593     * Quadrature by passing in the CANdi object.
594     * <p>
595     * When using FusedCANdi (requires Phoenix Pro), the Talon will fuse
596     * another CANdi™ branded device's information with the internal
597     * rotor, which provides the best possible position and velocity for
598     * accuracy and bandwidth.
599     * 
600     * @param device CANdi reference to use for FusedCANdi
601     * @return Itself
602     */
603    public FeedbackConfigs withFusedCANdiQuadrature(CoreCANdi device)
604    {
605        FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANdiQuadrature;
606        FeedbackRemoteSensorID = device.getDeviceID();
607        return this;
608    }
609    
610    /**
611     * Helper method to configure this feedback group to use SyncCANdi PWM
612     * 1 by passing in the CANdi object.
613     * <p>
614     * When using SyncCANdi (requires Phoenix Pro), the Talon will
615     * synchronize its internal rotor position against another CANdi™
616     * branded device, then continue to use the rotor sensor for closed
617     * loop control. The Talon will report if its internal position
618     * differs significantly from the reported CANdi™ branded device's
619     * position. SyncCANdi was developed for mechanisms where there is a
620     * risk of the CANdi™ branded device failing in such a way that it
621     * reports a position that does not match the mechanism, such as the
622     * sensor mounting assembly breaking off.
623     * 
624     * @param device CANdi reference to use for SyncCANdi
625     * @return Itself
626     */
627    public FeedbackConfigs withSyncCANdiPwm1(CoreCANdi device)
628    {
629        FeedbackSensorSource = FeedbackSensorSourceValue.SyncCANdiPWM1;
630        FeedbackRemoteSensorID = device.getDeviceID();
631        return this;
632    }
633    
634    /**
635     * Helper method to configure this feedback group to use SyncCANdi PWM
636     * 2 by passing in the CANdi object.
637     * <p>
638     * When using SyncCANdi (requires Phoenix Pro), the Talon will
639     * synchronize its internal rotor position against another CANdi™
640     * branded device, then continue to use the rotor sensor for closed
641     * loop control. The Talon will report if its internal position
642     * differs significantly from the reported CANdi™ branded device's
643     * position. SyncCANdi was developed for mechanisms where there is a
644     * risk of the CANdi™ branded device failing in such a way that it
645     * reports a position that does not match the mechanism, such as the
646     * sensor mounting assembly breaking off.
647     * 
648     * @param device CANdi reference to use for SyncCANdi
649     * @return Itself
650     */
651    public FeedbackConfigs withSyncCANdiPwm2(CoreCANdi device)
652    {
653        FeedbackSensorSource = FeedbackSensorSourceValue.SyncCANdiPWM2;
654        FeedbackRemoteSensorID = device.getDeviceID();
655        return this;
656    }
657    
658    
659
660    @Override
661    public String toString()
662    {
663        String ss = "Config Group: Feedback\n";
664        ss += "    FeedbackRotorOffset: " + FeedbackRotorOffset + " rotations" + "\n";
665        ss += "    SensorToMechanismRatio: " + SensorToMechanismRatio + " scalar" + "\n";
666        ss += "    RotorToSensorRatio: " + RotorToSensorRatio + " scalar" + "\n";
667        ss += "    FeedbackSensorSource: " + FeedbackSensorSource + "\n";
668        ss += "    FeedbackRemoteSensorID: " + FeedbackRemoteSensorID + "\n";
669        ss += "    VelocityFilterTimeConstant: " + VelocityFilterTimeConstant + " seconds" + "\n";
670        return ss;
671    }
672
673    /**
674     *
675     */
676    public StatusCode deserialize(String to_deserialize)
677    {
678        FeedbackRotorOffset = ConfigJNI.Deserializedouble(SpnValue.Config_FeedbackRotorOffset.value, to_deserialize);
679        SensorToMechanismRatio = ConfigJNI.Deserializedouble(SpnValue.Config_SensorToMechanismRatio.value, to_deserialize);
680        RotorToSensorRatio = ConfigJNI.Deserializedouble(SpnValue.Config_RotorToSensorRatio.value, to_deserialize);
681        FeedbackSensorSource = FeedbackSensorSourceValue.valueOf(ConfigJNI.Deserializeint(SpnValue.Config_FeedbackSensorSource.value, to_deserialize));
682        FeedbackRemoteSensorID = ConfigJNI.Deserializeint(SpnValue.Config_FeedbackRemoteSensorID.value, to_deserialize);
683        VelocityFilterTimeConstant = ConfigJNI.Deserializedouble(SpnValue.Config_VelocityFilterTimeConstant.value, to_deserialize);
684        return  StatusCode.OK;
685    }
686
687    /**
688     *
689     */
690    public String serialize()
691    {
692        String ss = "";
693        ss += ConfigJNI.Serializedouble(SpnValue.Config_FeedbackRotorOffset.value, FeedbackRotorOffset);
694        ss += ConfigJNI.Serializedouble(SpnValue.Config_SensorToMechanismRatio.value, SensorToMechanismRatio);
695        ss += ConfigJNI.Serializedouble(SpnValue.Config_RotorToSensorRatio.value, RotorToSensorRatio);
696        ss += ConfigJNI.Serializeint(SpnValue.Config_FeedbackSensorSource.value, FeedbackSensorSource.value);
697        ss += ConfigJNI.Serializeint(SpnValue.Config_FeedbackRemoteSensorID.value, FeedbackRemoteSensorID);
698        ss += ConfigJNI.Serializedouble(SpnValue.Config_VelocityFilterTimeConstant.value, VelocityFilterTimeConstant);
699        return ss;
700    }
701}
702