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