001/* Copyright (C) Cross The Road Electronics 2024 */
002package com.ctre.phoenix.led;
003
004import java.util.HashMap;
005
006import com.ctre.phoenix.ErrorCode;
007import com.ctre.phoenix.ErrorCollection;
008import com.ctre.phoenix.ParamEnum;
009
010/**
011 * CTRE CANdle
012 *
013 * Device for controlling LEDs from the CAN bus.
014 *
015 * <pre>
016 * {@code
017 * // Example usage of a CANdle
018 * CANdle candle = new CANdle(0); // creates a new CANdle with ID 0
019 *
020 * CANdleConfiguration config = new CANdleConfiguration();
021 * config.stripType = LEDStripType.RGB; // set the strip type to RGB
022 * config.brightnessScalar = 0.5; // dim the LEDs to half brightness
023 * candle.configAllSettings(config);
024 *
025 * candle.setLEDs(255, 255, 255); // set the CANdle LEDs to white
026 *
027 * // create a rainbow animation:
028 * // - max brightness
029 * // - half speed
030 * // - 64 LEDs
031 * RainbowAnimation rainbowAnim = new RainbowAnimation(1, 0.5, 64);
032 * candle.animate(rainbowAnim);
033 *
034 * ErrorCode error = candle.getLastError(); // gets the last error generated by the CANdle
035 * CANdleFaults faults = new CANdleFaults();
036 * ErrorCode faultsError = candle.getFaults(faults); // fills faults with the current CANdle faults; returns the last error generated
037 * }
038 * </pre>
039 *
040 * @deprecated This device's Phoenix 5 API is deprecated for removal in the
041 * 2027 season. Users should update to Phoenix 6 firmware and migrate to the
042 * Phoenix 6 API. A migration guide is available at
043 * https://v6.docs.ctr-electronics.com/en/stable/docs/migration/migration-guide/index.html.
044 * <p>
045 * If the Phoenix 5 API must be used for this device, the device must have 22.X
046 * firmware. This firmware is available in Tuner X after selecting Phoenix 5 in
047 * the firmware year dropdown.
048 */
049@Deprecated(since = "2026", forRemoval = true)
050public class CANdle {
051    private long _handle;
052
053    /**
054     * The various LED types that the CANdle can support
055     */
056    public enum LEDStripType {
057        /**
058         * LEDs that are controlled by Green-Red-Blue values
059         */
060        GRB(0),
061        /**
062         * LEDs that are controlled by Red-Green-Blue values
063         */
064        RGB(1),
065        /**
066         * LEDs that are controlled by Blue-Red-Green values
067         */
068        BRG(2),
069        /**
070         * LEDs that are controlled by Green-Red-Blue-White values
071         */
072        GRBW(6),
073        /**
074         * LEDs that are controlled by Red-Green-Blue-White values
075         */
076        RGBW(7),
077        /**
078         * LEDs that are controlled by Blue-Red-Green-White values
079         */
080        BRGW(8);
081
082        final public int value;
083
084        LEDStripType(int value) {
085            this.value = value;
086        }
087        /** Keep singleton map to quickly lookup enum via int */
088        private static HashMap<Integer, LEDStripType> _map = null;
089        /** static c'tor, prepare the map */
090        static {
091            _map = new HashMap<Integer, LEDStripType>();
092            for (LEDStripType type : LEDStripType.values()) {
093                _map.put(type.value, type);
094            }
095        }
096        /**
097         * Get LEDStripType of specified value
098         * @param value value of LEDStripType
099         * @return LEDStripType of specified value
100         */
101        public static LEDStripType valueOf(int value) {
102            LEDStripType retval = _map.get(value);
103            if (retval != null)
104                return retval;
105            return GRB;
106        }
107        /**
108         * Get LEDStripType of specified value
109         * @param value value of LEDStripType
110         * @return LEDStripType of specified value
111         */
112        public static LEDStripType valueOf(double value) {
113            return valueOf((int) value); 
114        }
115    }
116
117    /**
118     * The various methods of managing the VBat output behavior
119     */
120    public enum VBatOutputMode {
121        /**
122         * VBat output is on at full power, no modulation
123         */
124        On(0),
125        /**
126         * VBat output is off, no modulation
127         */
128        Off(1),
129        /**
130         * VBat output is on at the specified modulation
131         */
132        Modulated(2);
133
134        final public int value;
135
136        VBatOutputMode(int value) {
137            this.value = value;
138        }
139        /** Keep singleton map to quickly lookup enum via int */
140        private static HashMap<Integer, VBatOutputMode> _map = null;
141        /** static c'tor, prepare the map */
142        static {
143            _map = new HashMap<Integer, VBatOutputMode>();
144            for (VBatOutputMode type : VBatOutputMode.values()) {
145                _map.put(type.value, type);
146            }
147        }
148        /**
149         * Get VBatOutputMode of specified value
150         * @param value value of VBatOutputMode
151         * @return VBatOutputMode of specified value
152         */
153        public static VBatOutputMode valueOf(int value) {
154            VBatOutputMode retval = _map.get(value);
155            if (retval != null)
156                return retval;
157            return On;
158        }
159        /**
160         * Get VBatOutputMode of specified value
161         * @param value value of VBatOutputMode
162         * @return VBatOutputMode of specified value
163         */
164        public static VBatOutputMode valueOf(double value) {
165            return valueOf((int) value); 
166        }
167    }
168    
169    /**
170     * Constructor for a CANdle Device
171     * @param deviceId The Device ID of the CANdle
172     * @param canbus Name of the CANbus; can be a SocketCAN interface (on Linux),
173     *               or a CANivore device name or serial number
174     */
175    public CANdle(int deviceId, String canbus) {
176        _handle = CANdleJNI.Create(deviceId, canbus);
177    }
178    /**
179     * Constructor for a CANdle Device
180     * @param deviceId The Device ID of the CANdle
181     */
182    public CANdle(int deviceId) {
183        this(deviceId, "");
184    }
185    
186    public ErrorCode destroyObject() {
187        return ErrorCode.valueOf(0);
188    }
189
190    /**
191     * Gets the Voltage of VBat as measured by CANdle
192     * @return Voltage of VBat
193     */
194    public double getBusVoltage() {
195        return CANdleJNI.GetBusVoltage(_handle);
196    }
197    /**
198     * Gets the Voltage of the 5V line as measured by CANdle
199     * @return Voltage of the 5V line
200     */
201    public double get5VRailVoltage() {
202        return CANdleJNI.Get5VRailVoltage(_handle);
203    }
204    /**
205     * Gets the low-side current as measured by CANdle
206     * @return Current in Amps
207     */
208    public double getCurrent() {
209        return CANdleJNI.GetCurrent(_handle);
210    }
211    /**
212     * Gets the temperature of the CANdle in Celcius
213     * @return Temperature in Celcius
214     */
215    public double getTemperature() {
216        return CANdleJNI.GetTemperature(_handle);
217    }
218    /**
219     * Gets the applied vbat modulation in percent.
220     * If the CANdle is configured to always enable VBat, this returns 1
221     * If the CANdle is confgigured to always disable VBat, this returns 0
222     * Otherwise it returns the last set Modulation as a value [0, 1]
223     * @return VBat Output Modulation
224     */
225    public double getVBatModulation() {
226        return CANdleJNI.GetVbatModulation(_handle);
227    }
228    /**
229     * Gets the maximum number of simultaneous animations this version of CANdle firmware supports.
230     * If you specify an animation slot >= to this return, Phoenix will error out.
231     * You can also get the maximum count from a self-test snapshot.
232     * @return Maximum number of simultaneous animations this version of firmware supports.
233     */
234    public int getMaxSimultaneousAnimationCount() {
235        return CANdleJNI.GetMaxSimultaneousAnimationCount(_handle);
236    }
237
238    /**
239     * Animates the CANdle with the passed-in animation
240     * If the animation changes after calling this function, 
241     *  it must be passed into animate again for the changes to take effect
242     * @param animation The animation that CANdle will run. If this is null, it will clear the animation at the specified slot
243     * @return ErrorCode generated by function. OK indicates no error.
244     */
245    public ErrorCode animate(Animation animation) {
246        return animate(animation, 0);
247    }
248    /**
249     * Animates the CANdle with the passed-in animation
250     * If the animation changes after calling this function, 
251     *  it must be passed into animate again for the changes to take effect
252     * @param animation The animation that CANdle will run. If this is null, it will clear the animation at the specified slot
253     * @param animSlot The animation slot to use for the animation, range is [0, getMaxSimultaneousAnimationCount()) exclusive
254     * @return ErrorCode generated by function. OK indicates no error.
255     */
256    public ErrorCode animate(Animation animation, int animSlot) {
257        if(animation == null) return clearAnimation(animSlot);
258
259        BaseStandardAnimation baseStandard = animation.getBaseStandardAnimation();
260        if(baseStandard != null) return animate(baseStandard, animSlot);
261
262        BaseTwoSizeAnimation baseTwoSize = animation.getBaseTwoSizeAnimation();
263        if(baseTwoSize != null) return animate(baseTwoSize, animSlot);
264
265        return ErrorCode.InvalidParamValue;
266    }
267
268    /**
269     * Clears the animation occurring in the selected selected animSlot.
270     * @param animSlot Animation slot to clear
271     * @return ErrorCode generated by function. OK indicates no error.
272     */
273    public ErrorCode clearAnimation(int animSlot) {
274        return ErrorCode.valueOf(CANdleJNI.ClearAnimation(_handle, animSlot));
275    }
276
277    private ErrorCode animate(BaseStandardAnimation animation, int animSlot) {
278        return ErrorCode.valueOf(
279            CANdleJNI.SetStandardAnimation(_handle, 
280                animation.getAnimationIdx(), 
281                animation.getBrightness(), 
282                animation.getSpeed(), 
283                animation.getNumLed(),
284                animation.getLedOffset(),
285                animation.getParam4(),
286                animation.getParam5(),
287                animation.getReverseDirection(),
288                animSlot));
289    }
290    private ErrorCode animate(BaseTwoSizeAnimation animation, int animSlot) {
291        return ErrorCode.valueOf(
292            CANdleJNI.SetTwoSizeAnimation(_handle, 
293                animation.getAnimationIdx(), 
294                animation.getR(), 
295                animation.getG(), 
296                animation.getB(),
297                animation.getW(),
298                animation.getSpeed(),
299                animation.getNumLed(),
300                animation.getLedOffset(),
301                animation.getDirection(),
302                animation.getSize(),
303                animSlot));
304    }
305
306    /**
307     * Sets a block of LEDs to the specified color
308     * @param r The amount of Red to set, range is [0, 255]
309     * @param g The amount of Green to set, range is [0, 255]
310     * @param b The amount of Blue to set, range is [0, 255]
311     * @param w The amount of White to set, range is [0, 255]. This only applies for LED strips with white in them.
312     * @param startIdx Where to start setting the LEDs 
313     * @param count The number of LEDs to apply this to
314     * @return ErrorCode generated by function. OK indicates no error.
315     */
316    public ErrorCode setLEDs(int r, int g, int b, int w, int startIdx, int count) {
317        return ErrorCode.valueOf(CANdleJNI.BlockSet(_handle, r, g, b, w, startIdx, count));
318    }
319    /**
320     * Sets a block of LEDs to the specified color.
321     * @param r The amount of Red to set, range is [0, 255]
322     * @param g The amount of Green to set, range is [0, 255]
323     * @param b The amount of Blue to set, range is [0, 255]
324     * @return ErrorCode generated by function. OK indicates no error.
325     */
326    public ErrorCode setLEDs(int r, int g, int b) {
327        return setLEDs(r, g, b, 0, 0, 512);
328    }
329
330    /**
331     * Modulates the VBat output to the specified duty cycle percentage
332     * This function will only do something if the CANdle's VBatOutput is configured to Modulated
333     * @param dutyCyclePrcnt The duty cycle of the output modulation [0, 1]
334     * @return ErrorCode generated by function. OK indicates no error.
335     */
336    public ErrorCode modulateVBatOutput(double dutyCyclePrcnt) {
337        return ErrorCode.valueOf(CANdleJNI.ModulateVBatOutput(_handle, dutyCyclePrcnt));
338    }
339
340    /**
341     * Configures what the CANdle should do if it loses communications to the Controller
342     * @param disableWhenLOS Set to true to disable the LEDs on Loss of Signal.
343     * @param timeoutMs
344     *            Timeout value in ms. If nonzero, function will wait for
345     *            config success and report an error if it times out.
346     *            If zero, no blocking or checking is performed.
347     * @return ErrorCode generated by function. OK indicates no error.
348     */
349    public ErrorCode configLOSBehavior(boolean disableWhenLOS, int timeoutMs) {
350        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, ParamEnum.eLossOfSignalBehavior.value, disableWhenLOS ? 1 : 0, 0, 0, timeoutMs));
351    }
352    /**
353     * Configures what the CANdle should do if it loses communications to the Controller
354     * @param disableWhenLOS Set to true to disable the LEDs on Loss of Signal.
355     * @return ErrorCode generated by function. OK indicates no error.
356     */
357    public ErrorCode configLOSBehavior(boolean disableWhenLOS) {
358        int timeoutMs = 0;
359        return configLOSBehavior(disableWhenLOS, timeoutMs);
360    }
361    /**
362     * Configures the type of LED the CANdle controls
363     * @param type The type of the LEDs the CANdle controls
364     * @param timeoutMs
365     *            Timeout value in ms. If nonzero, function will wait for
366     *            config success and report an error if it times out.
367     *            If zero, no blocking or checking is performed.
368     * @return ErrorCode generated by function. OK indicates no error.
369     */
370    public ErrorCode configLEDType(LEDStripType type, int timeoutMs) {
371        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, ParamEnum.eLEDStripType.value, type.value, 0, 0, timeoutMs));
372    }
373    /**
374     * Configures the type of LED the CANdle controls
375     * @param type The type of the LEDs the CANdle controls
376     * @return ErrorCode generated by function. OK indicates no error.
377     */
378    public ErrorCode configLEDType(LEDStripType type) {
379        int timeoutMs = 0;
380        return configLEDType(type, timeoutMs);
381    }
382    /**
383     * Configures the brightness scalar to be applied to every LED output.
384     * This value is bounded to [0, 1].
385     * 
386     * Setting this to 1 will allow the LEDs to function at max brightness.
387     * Setting this to 0.5 will scale all values to half their applied value.
388     * Setting this to 0 will turn off the LEDs.
389     * 
390     * Forcing the LEDs off this way may be useful in certain testing circumstances 
391     * but is generally not necessary. Self-test (Tuner) may be used to verify what 
392     * the effective scalar is in case user forgot to restore the scalar to a 
393     * non-zero value.
394     * 
395     * @param brightness Value from [0, 1] that will scale the LED output.
396     * @param timeoutMs
397                    Timeout value in ms. If nonzero, function will wait for
398                    config success and report an error if it times out.
399                    If zero, no blocking or checking is performed.
400     * @return Error Code generated by function. 0 indicates no error.
401     */
402    public ErrorCode configBrightnessScalar(double brightness, int timeoutMs) {
403        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, ParamEnum.eBrightnessCoefficient.value, brightness, 0, 0, timeoutMs));
404    }
405    /**
406     * Configures the brightness scalar to be applied to every LED output.
407     * This value is bounded to [0, 1].
408     * 
409     * Setting this to 1 will allow the LEDs to function at max brightness.
410     * Setting this to 0.5 will scale all values to half their applied value.
411     * Setting this to 0 will turn off the LEDs.
412     * 
413     * Forcing the LEDs off this way may be useful in certain testing circumstances 
414     * but is generally not necessary. Self-test (Tuner) may be used to verify what 
415     * the effective scalar is in case user forgot to restore the scalar to a 
416     * non-zero value.
417     * 
418     * @param brightness Value from [0, 1] that will scale the LED output.
419     * @return Error Code generated by function. 0 indicates no error.
420     */
421    public ErrorCode configBrightnessScalar(double brightness) {
422        int timeoutMs = 0;
423        return configBrightnessScalar(brightness, timeoutMs);
424    }
425
426    /**
427     * Configures how the status led will behave when the CANdle is actively controlling LEDs
428     * If the CANdle is LOS or not actively commanded a value, it will always turn on its status LED.
429     * @param disableWhenRunning Disables the status LED when the CANdle is running
430     * @param timeoutMs
431                    Timeout value in ms. If nonzero, function will wait for
432                    config success and report an error if it times out.
433                    If zero, no blocking or checking is performed.
434     * @return Error Code generated by function. 0 indicates no error.
435     */
436    public ErrorCode configStatusLedState(boolean disableWhenRunning, int timeoutMs) {
437        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, ParamEnum.eStatusLedState.value, disableWhenRunning ? 1 : 0, 0, 0, timeoutMs));
438    }
439    /**
440     * Configures how the status led will behave when the CANdle is actively controlling LEDs
441     * If the CANdle is LOS or not actively commanded a value, it will always turn on its status LED.
442     * @param disableWhenRunning Disables the status LED when the CANdle is running
443     * @return Error Code generated by function. 0 indicates no error.
444     */
445    public ErrorCode configStatusLedState(boolean disableWhenRunning) {
446        int timeoutMs = 0;
447        return configStatusLedState(disableWhenRunning, timeoutMs);
448    }
449    /**
450     * Configures how the VBat Output will behave
451     * @param mode VBat Output Behavior
452     * @param timeoutMs
453                    Timeout value in ms. If nonzero, function will wait for
454                    config success and report an error if it times out.
455                    If zero, no blocking or checking is performed.
456     * @return Error Code generated by function. 0 indicates no error.
457     */
458    public ErrorCode configVBatOutput(VBatOutputMode mode, int timeoutMs) {
459        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, ParamEnum.eVBatOutput.value, mode.value, 0, 0, timeoutMs));
460    }
461    /**
462     * Configures how the VBat Output will behave
463     * @param mode VBat Output Behavior
464     * @return Error Code generated by function. 0 indicates no error.
465     */
466    public ErrorCode configVBatOutput(VBatOutputMode mode) {
467        int timeoutMs = 0;
468        return configVBatOutput(mode, timeoutMs);
469    }
470    /**
471     * Configures the enable state for the 5V rail. This also affects the on-board LEDs.
472     * @param enable5V True to enable the 5V rail.
473     * @param timeoutMs
474     *            Timeout value in ms. If nonzero, function will wait for
475     *            config success and report an error if it times out.
476     *            If zero, no blocking or checking is performed.
477     * @return ErrorCode generated by function. OK indicates no error.
478     */
479    public ErrorCode configV5Enabled(boolean enable5V, int timeoutMs) {
480        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, ParamEnum.eV5Enabled.value, enable5V ? 1 : 0, 0, 0, timeoutMs));
481    }
482    /**
483     * Configures the enable state for the 5V rail. This also disables the on-board LEDs.
484     * @param enable5V True to enable the 5V rail.
485     * @return ErrorCode generated by function. OK indicates no error.
486     */
487    public ErrorCode configV5Enabled(boolean enable5V) {
488        int timeoutMs = 0;
489        return configV5Enabled(enable5V, timeoutMs);
490    }
491
492    /**
493     * Gets a parameter. Generally this is not used.
494     * This can be utilized in
495     * - Using new features without updating API installation.
496     * - Errata workarounds to circumvent API implementation.
497     * - Allows for rapid testing / unit testing of firmware.
498     *
499     * @param param
500     *            Parameter enumeration.
501     * @param ordinal
502     *            Ordinal of parameter.
503     * @param timeoutMs
504     *            Timeout value in ms. If nonzero, function will wait for
505     *            config success and report an error if it times out.
506     *            If zero, no blocking or checking is performed.
507     * @return Value of parameter.
508     */
509    public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
510        return CANdleJNI.ConfigGetParameter(_handle, param.value, ordinal, timeoutMs);
511    }
512    /**
513     * Gets a parameter. Generally this is not used.
514     * This can be utilized in
515     * - Using new features without updating API installation.
516     * - Errata workarounds to circumvent API implementation.
517     * - Allows for rapid testing / unit testing of firmware.
518     *
519     * @param param
520     *            Parameter enumeration.
521     * @param ordinal
522     *            Ordinal of parameter.
523     * @return Value of parameter.
524     */
525    public double configGetParameter(ParamEnum param, int ordinal) {
526        int timeoutMs = 0;
527        return configGetParameter(param, ordinal, timeoutMs);
528    }
529    /**
530     * Sets a parameter. Generally this is not used.
531     * This can be utilized in
532     * - Using new features without updating API installation.
533     * - Errata workarounds to circumvent API implementation.
534     * - Allows for rapid testing / unit testing of firmware.
535     *
536     * @param param
537     *            Parameter enumeration.
538     * @param value
539     *            Value of parameter.
540     * @param subValue
541     *            Subvalue for parameter. Maximum value of 255.
542     * @param ordinal
543     *            Ordinal of parameter.
544     * @param timeoutMs
545     *            Timeout value in ms. If nonzero, function will wait for
546     *            config success and report an error if it times out.
547     *            If zero, no blocking or checking is performed.
548     * @return Error Code generated by function. 0 indicates no error.
549     */
550    public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
551        return ErrorCode.valueOf(CANdleJNI.ConfigSetParameter(_handle, param.value, value, subValue, ordinal, timeoutMs));
552    }
553    /**
554     * Sets a parameter. Generally this is not used.
555     * This can be utilized in
556     * - Using new features without updating API installation.
557     * - Errata workarounds to circumvent API implementation.
558     * - Allows for rapid testing / unit testing of firmware.
559     *
560     * @param param
561     *            Parameter enumeration.
562     * @param value
563     *            Value of parameter.
564     * @param subValue
565     *            Subvalue for parameter. Maximum value of 255.
566     * @param ordinal
567     *            Ordinal of parameter.
568     * @return Error Code generated by function. 0 indicates no error.
569     */
570    public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal) {
571        int timeoutMs = 0;
572        return configSetParameter(param, value, subValue, ordinal, timeoutMs);
573    }
574    /**
575     * Gets the value of a custom parameter. This is for arbitrary use.
576     *
577     * Sometimes it is necessary to save calibration/duty cycle/output
578     * information in the device. Particularly if the
579     * device is part of a subsystem that can be replaced.
580     *
581     * @param paramIndex
582     *            Index of custom parameter. [0-1]
583     * @param timeoutMs
584     *            Timeout value in ms. If nonzero, function will wait for
585     *            config success and report an error if it times out.
586     *            If zero, no blocking or checking is performed.
587     * @return Value of the custom param.
588     */
589    public int configGetCustomParam(int paramIndex, int timeoutMs) {
590        return CANdleJNI.ConfigGetCustomParam(_handle, paramIndex, timeoutMs);
591    }
592    /**
593     * Gets the value of a custom parameter. This is for arbitrary use.
594     *
595     * Sometimes it is necessary to save calibration/duty cycle/output
596     * information in the device. Particularly if the
597     * device is part of a subsystem that can be replaced.
598     *
599     * @param paramIndex
600     *            Index of custom parameter. [0-1]
601     * @return Value of the custom param.
602     */
603    public int configGetCustomParam(int paramIndex) {
604        int timeoutMs = 0;
605        return configGetCustomParam(paramIndex, timeoutMs);
606    }
607    /**
608     * Sets the value of a custom parameter. This is for arbitrary use.
609     *
610     * Sometimes it is necessary to save calibration/duty cycle/output
611     * information in the device. Particularly if the
612     * device is part of a subsystem that can be replaced.
613     *
614     * @param paramIndex
615     *            Index of custom parameter. [0-1]
616     * @param value
617     *            Value for custom parameter.
618     * @param timeoutMs
619     *            Timeout value in ms. If nonzero, function will wait for
620     *            config success and report an error if it times out.
621     *            If zero, no blocking or checking is performed.
622     * @return Error Code generated by function. 0 indicates no error.
623     */
624    public ErrorCode configSetCustomParam(int paramIndex, int value, int timeoutMs) {
625        return ErrorCode.valueOf(CANdleJNI.ConfigSetCustomParam(_handle, value, paramIndex, timeoutMs));
626    }
627    /**
628     * Sets the value of a custom parameter. This is for arbitrary use.
629     *
630     * Sometimes it is necessary to save calibration/duty cycle/output
631     * information in the device. Particularly if the
632     * device is part of a subsystem that can be replaced.
633     *
634     * @param paramIndex
635     *            Index of custom parameter. [0-1]
636     * @param value
637     *            Value for custom parameter.
638     * @return Error Code generated by function. 0 indicates no error.
639     */
640    public ErrorCode configSetCustomParam(int paramIndex, int value) {
641        int timeoutMs = 0;
642        return configSetCustomParam(value, paramIndex, timeoutMs);
643    }
644    /**
645     * Configures all persistent settings to defaults.
646     *
647     * @param timeoutMs
648     *              Timeout value in ms. If nonzero, function will wait for
649     *              config success and report an error if it times out.
650     *              If zero, no blocking or checking is performed.
651     *
652     * @return Error Code generated by function. 0 indicates no error. 
653     */
654    public ErrorCode configFactoryDefault(int timeoutMs) {
655        return ErrorCode.valueOf(CANdleJNI.ConfigFactoryDefault(_handle, timeoutMs));
656    }
657    /**
658     * Configures all persistent settings to defaults.
659     *
660     * @return Error Code generated by function. 0 indicates no error. 
661     */
662    public ErrorCode configFactoryDefault() {
663        int timeoutMs = 50;
664        return configFactoryDefault(timeoutMs);
665    }
666    /**
667     * Gets the CANdle fault status
668     *
669     * @param toFill Container for fault statuses.
670     * @return Error Code generated by function. OK indicates no error.
671     */
672    public ErrorCode getFaults(CANdleFaults toFill) {
673        int faults = CANdleJNI.GetFaults(_handle);
674        toFill.update(faults);
675        return getLastError();
676    }
677    /**
678     * Gets the CANdle sticky fault status
679     *
680     * @param toFill Container for sticky fault statuses.
681     * @return Error Code generated by function. OK indicates no error.
682     */
683    public ErrorCode getStickyFaults(CANdleStickyFaults toFill) {
684        int faults = CANdleJNI.GetStickyFaults(_handle);
685        toFill.update(faults);
686        return getLastError();
687    }
688    /**
689     * Clears the sticky faults.
690     * 
691     * @param timeoutMs
692     *            Timeout value in ms. If nonzero, function will wait for
693     *            config success and report an error if it times out.
694     *            If zero, no blocking or checking is performed.
695     * @return Error Code generated by function. 0 indicates no error.
696     */
697    public ErrorCode clearStickyFaults(int timeoutMs) {
698        return ErrorCode.valueOf(CANdleJNI.ClearStickyFaults(_handle, timeoutMs));
699    }
700    /**
701     * Clears the sticky faults.
702     * 
703     * @return Error Code generated by function. 0 indicates no error.
704     */
705    public ErrorCode clearStickyFaults() {
706        int timeoutMs = 0;
707        return clearStickyFaults(timeoutMs);
708    }
709    /**
710     * Returns true if the device has reset since last call.
711     *
712     * @return Has a Device Reset Occurred?
713     */
714    public boolean hasResetOccurred() {
715        return CANdleJNI.HasResetOccurred(_handle);
716    }
717    /**
718     * Sets the period of the given status frame.
719     *
720     * @param frame
721     *            Frame whose period is to be changed.
722     * @param periodMs
723     *            Period in ms for the given frame.
724     * @param timeoutMs
725     *            Timeout value in ms. If nonzero, function will wait for
726     *            config success and report an error if it times out.
727     *            If zero, no blocking or checking is performed.
728     * @return Error Code generated by function. 0 indicates no error.
729     */
730    public ErrorCode setStatusFramePeriod(CANdleStatusFrame frame, int periodMs, int timeoutMs) {
731        return ErrorCode.valueOf(CANdleJNI.SetStatusFramePeriod(_handle, frame.value, periodMs, timeoutMs));
732    }
733    /**
734     * Sets the period of the given status frame.
735     *
736     * @param frame
737     *            Frame whose period is to be changed.
738     * @param periodMs
739     *            Period in ms for the given frame.
740     * @return Error Code generated by function. 0 indicates no error.
741     */
742    public ErrorCode setStatusFramePeriod(CANdleStatusFrame frame, int periodMs) {
743        int timeoutMs = 0;
744        return setStatusFramePeriod(frame, periodMs, timeoutMs);
745    }
746    /**
747     * Gets the period of the given status frame.
748     *
749     * @param frame
750     *            Frame to get the period of.
751     * @param timeoutMs
752     *            Timeout value in ms. If nonzero, function will wait for
753     *            config success and report an error if it times out.
754     *            If zero, no blocking or checking is performed.
755     * @return Period of the given status frame.
756     */
757    public int getStatusFramePeriod(CANdleStatusFrame frame, int timeoutMs) {
758        return CANdleJNI.GetStatusFramePeriod(_handle, frame.value, timeoutMs);
759    }
760    /**
761     * Gets the period of the given status frame.
762     *
763     * @param frame
764     *            Frame to get the period of.
765     * @return Period of the given status frame.
766     */
767    public int getStatusFramePeriod(CANdleStatusFrame frame) {
768        int timeoutMs = 0;
769        return getStatusFramePeriod(frame, timeoutMs);
770    }
771    /**
772     * Sets the period of the given control frame.
773     *
774     * @param frame
775     *            Frame whose period is to be changed.
776     * @param periodMs
777     *            Period in ms for the given frame.
778     * @return Error Code generated by function. 0 indicates no error.
779     */
780    public ErrorCode setControlFramePeriod(CANdleControlFrame frame, int periodMs) {
781        return ErrorCode.valueOf(CANdleJNI.SetControlFramePeriod(_handle, frame.value, periodMs));
782    }
783
784    /**
785     * Configures all persistent settings.
786     *
787     * @param allConfigs        Object with all of the persistant settings
788     * @param timeoutMs
789     *              Timeout value in ms. If nonzero, function will wait for
790     *              config success and report an error if it times out.
791     *              If zero, no blocking or checking is performed.
792     * @return Error Code generated by function. 0 indicates no error.
793     */
794    public ErrorCode configAllSettings(CANdleConfiguration allConfigs, int timeoutMs) {
795        ErrorCollection errorCollection = new ErrorCollection();
796        
797        errorCollection.NewError(configFactoryDefault(timeoutMs));
798        if(CANdleConfigUtil.stripTypeDifferent(allConfigs)) errorCollection.NewError(configLEDType(allConfigs.stripType, timeoutMs));
799        if(CANdleConfigUtil.brightnessScalarDifferent(allConfigs)) errorCollection.NewError(configBrightnessScalar(allConfigs.brightnessScalar, timeoutMs));
800        if(CANdleConfigUtil.disableWhenLOSDifferent(allConfigs)) errorCollection.NewError(configLOSBehavior(allConfigs.disableWhenLOS, timeoutMs));
801        if(CANdleConfigUtil.statusLedOffWhenActiveDifferent(allConfigs)) errorCollection.NewError(configStatusLedState(allConfigs.statusLedOffWhenActive, timeoutMs));
802        if(CANdleConfigUtil.vBatOutputModeDifferent(allConfigs)) errorCollection.NewError(configVBatOutput(allConfigs.vBatOutputMode, timeoutMs));
803        if(CANdleConfigUtil.v5EnabledDifferent(allConfigs)) errorCollection.NewError(configV5Enabled(allConfigs.v5Enabled, timeoutMs));
804
805        if(CANdleConfigUtil.customParam0Different(allConfigs)) errorCollection.NewError(configSetCustomParam(0, allConfigs.customParam0, timeoutMs));
806        if(CANdleConfigUtil.customParam1Different(allConfigs)) errorCollection.NewError(configSetCustomParam(1, allConfigs.customParam1, timeoutMs));
807
808        return errorCollection._worstError;   
809    }
810    /**
811     * Configures all persistent settings.
812     *
813     * @param allConfigs        Object with all of the persistant settings
814     * @return Error Code generated by function. 0 indicates no error.
815     */
816    public ErrorCode configAllSettings(CANdleConfiguration allConfigs) {
817        int timeoutMs = 50;
818        return configAllSettings(allConfigs, timeoutMs);
819    }
820
821    /**
822     * Gets all persistant settings.
823     *
824     * @param allConfigs        Object with all of the persistant settings
825     * @param timeoutMs
826     *              Timeout value in ms. If nonzero, function will wait for
827     *              config success and report an error if it times out.
828     *              If zero, no blocking or checking is performed.
829     */
830    public void getAllConfigs(CANdleConfiguration allConfigs, int timeoutMs) {
831        allConfigs.brightnessScalar = configGetParameter(ParamEnum.eBrightnessCoefficient, 0, timeoutMs);
832        allConfigs.disableWhenLOS = configGetParameter(ParamEnum.eLossOfSignalBehavior, 0, timeoutMs) != 0;
833        allConfigs.statusLedOffWhenActive = configGetParameter(ParamEnum.eStatusLedState, 0, timeoutMs) != 0;
834        allConfigs.stripType = LEDStripType.valueOf(configGetParameter(ParamEnum.eLEDStripType, 0, timeoutMs));
835        allConfigs.vBatOutputMode = VBatOutputMode.valueOf(configGetParameter(ParamEnum.eVBatOutput, 0, timeoutMs));
836        allConfigs.v5Enabled = configGetParameter(ParamEnum.eV5Enabled, 0, timeoutMs) != 0;
837
838        allConfigs.customParam0 = (int)configGetParameter(ParamEnum.eCustomParam, 0, timeoutMs);
839        allConfigs.customParam1 = (int)configGetParameter(ParamEnum.eCustomParam, 1, timeoutMs);
840    }
841    /**
842     * Gets all persistant settings.
843     *
844     * @param allConfigs        Object with all of the persistant settings
845     */
846    public void getAllConfigs(CANdleConfiguration allConfigs) {
847        int timeoutMs = 50;
848        getAllConfigs(allConfigs, timeoutMs);
849    }
850
851    /**
852     * Call GetLastError() generated by this object.
853     * Not all functions return an error code but can
854     * potentially report errors.
855     *
856     * This function can be used to retrieve those error codes.
857     *
858     * @return The last ErrorCode generated.
859     */
860    public ErrorCode getLastError() {
861        return ErrorCode.valueOf(CANdleJNI.GetLastError(_handle));
862    }
863}