001/*
002 *  Software License Agreement
003 *
004 * Copyright (C) Cross The Road Electronics.  All rights
005 * reserved.
006 *
007 * Cross The Road Electronics (CTRE) licenses to you the right to
008 * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and Software
009 * API Libraries ONLY when in use with Cross The Road Electronics hardware products.
010 *
011 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
012 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
013 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
014 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
015 * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
016 * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
017 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
018 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
019 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
020 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
021 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE
022 */
023
024package com.ctre.phoenix;
025
026import com.ctre.phoenix.CANifierConfiguration;
027import com.ctre.phoenix.VelocityPeriod;
028import com.ctre.phoenix.ErrorCollection;
029import com.ctre.phoenix.ParamEnum;
030import com.ctre.phoenix.sensors.SensorVelocityMeasPeriod;
031
032/**
033 * CTRE CANifier
034 *
035 * Device for interfacing common devices to the CAN bus.
036 */
037public class CANifier {
038        private long m_handle;
039
040
041        
042        /**
043         * Enum for the LED Output Channels
044         */
045        public enum LEDChannel {
046                /**
047                 * LED Channel A
048                 */
049                LEDChannelA(0), 
050                /**
051                 * LED Channel B
052                 */
053                LEDChannelB(1), 
054                /**
055                 * LED Channel C
056                 */
057                LEDChannelC(2);
058
059                /**
060                 * Get the LED Channel from a specified value
061                 * @param value integer value to get LEDChannel from
062                 * @return LEDChannel of specified value
063                 */
064                public static LEDChannel valueOf(int value) {
065                        for (LEDChannel mode : values()) {
066                                if (mode.value == value) {
067                                        return mode;
068                                }
069                        }
070                        return null;
071                }
072
073                /**
074                 * Value of LEDChannel
075                 */
076                public final int value;
077
078                /**
079                 * Create LEDChannel from initValue
080                 * @param initValue LEDChannel value
081                 */
082                LEDChannel(int initValue) {
083                        this.value = initValue;
084                }
085        }
086
087        /**
088         * Enum for the PWM Input Channels
089         */
090        public enum PWMChannel {
091                /**
092                 * PWM Channel 0
093                 */
094                PWMChannel0(0), 
095                /**
096                 * PWM Channel 1
097                 */
098                PWMChannel1(1), 
099                /**
100                 * PWM Channel 2
101                 */
102                PWMChannel2(2), 
103                /** 
104                 * PWM Channel 3
105                 */
106                PWMChannel3(3);
107
108                /**
109                 * Get the PWM Channel from a specified value
110                 * @param value integer value to get pwm channel from
111                 * @return PWM Channel of specified value
112                 */
113                public static PWMChannel valueOf(int value) {
114                        for (PWMChannel mode : values()) {
115                                if (mode.value == value) {
116                                        return mode;
117                                }
118                        }
119                        return null;
120                }
121
122                /**
123                 * Value of PWM Channel
124                 */
125                public final int value;
126
127                /**
128                 * Create a PWM Channel of initValue
129                 * @param initValue PWM Channel value
130                 */
131                PWMChannel(int initValue) {
132                        this.value = initValue;
133                }
134        }
135
136        /**
137         * Number of PWM channels available to CANifier
138         */
139        public final int PWMChannelCount = 4;
140
141        /**
142         * General IO Pins on the CANifier
143         */
144        public enum GeneralPin {
145                /**
146                 * Quadrature Idx pin
147                 */
148                QUAD_IDX (CANifierJNI.GeneralPin.QUAD_IDX.value),
149                /**
150                 * Quadrature B pin
151                 */
152                QUAD_B (CANifierJNI.GeneralPin.QUAD_B.value),
153                /**
154                 * Quadrature A pin
155                 */
156                QUAD_A (CANifierJNI.GeneralPin.QUAD_A.value),
157                /**
158                 * Reverse limit pin
159                 */
160                LIMR (CANifierJNI.GeneralPin.LIMR.value),
161                /**
162                 * Forward limit pin
163                 */
164                LIMF (CANifierJNI.GeneralPin.LIMF.value),
165                /**
166                 * SDA pin
167                 */
168                SDA (CANifierJNI.GeneralPin.SDA.value),
169                /**
170                 * SCL pin
171                 */
172                SCL (CANifierJNI.GeneralPin.SCL.value),
173                /**
174                 * SPI_CS pin
175                 */
176                SPI_CS (CANifierJNI.GeneralPin.SPI_CS.value),
177                /**
178                 * SPI_MISO_PWM2 pin
179                 */
180                SPI_MISO_PWM2P (CANifierJNI.GeneralPin.SPI_MISO_PWM2P.value),
181                /**
182                 * SPI_MOSI_PWM1 pin
183                 */
184                SPI_MOSI_PWM1P (CANifierJNI.GeneralPin.SPI_MOSI_PWM1P.value),
185                /**
186                 * SPI_CLK_PWM0 pin
187                 */
188                SPI_CLK_PWM0P (CANifierJNI.GeneralPin.SPI_CLK_PWM0P.value);
189
190                /**
191                 * Gets the GeneralPin of a specified value
192                 * @param value integer value of GeneralPin
193                 * @return GeneralPin of specified value
194                 */
195                public static GeneralPin valueOf(int value) {
196                        for (GeneralPin mode : values()) {
197                                if (mode.value == value) {
198                                        return mode;
199                                }
200                        }
201                        return null;
202                }
203
204                /**
205                 * Value of specified pin
206                 */
207                public final int value;
208
209                /**
210                 * Create GeneralPin of initValue value
211                 * @param initValue Value of Pin
212                 */
213                GeneralPin(int initValue) {
214                        this.value = initValue;
215                }
216        }
217
218        /**
219         * Class to hold the pin values.
220         */
221        public static class PinValues {
222                /**
223                 * Quadrature Idx pin
224                 */
225                public boolean QUAD_IDX;
226                /**
227                 * Quadrature B pin
228                 */
229                public boolean QUAD_B;
230                /**
231                 * Quadrature A pin
232                 */
233                public boolean QUAD_A;
234                /**
235                 * Reverse limit pin
236                 */
237                public boolean LIMR;
238                /**
239                 * Forward limit pin
240                 */
241                public boolean LIMF;
242                /**
243                 * SDA pin
244                 */
245                public boolean SDA;
246                /**
247                 * SCL pin
248                 */
249                public boolean SCL;
250                /**
251                 * SPI_CS_PWM3 pin
252                 */
253                public boolean SPI_CS_PWM3;
254                /**
255                 * SPI_MISO_PWM2 pin
256                 */
257                public boolean SPI_MISO_PWM2;
258                /**
259                 * SPI_MOSI_PWM1 pin
260                 */
261                public boolean SPI_MOSI_PWM1;
262                /**
263                 * SPI_CLK_PWM0 pin
264                 */
265                public boolean SPI_CLK_PWM0;
266        }
267
268        private boolean[] _tempPins = new boolean[11];
269
270        private int m_deviceNumber;
271        /**
272         * Constructor.
273         * @param deviceId      The CAN Device ID of the CANifier.
274         */
275        public CANifier(int deviceId) {
276                m_handle = CANifierJNI.JNI_new_CANifier(deviceId);
277                m_deviceNumber = deviceId;
278        }
279
280        /**
281         * Destructor
282         * @return Error Code generated by function. 0 indicates no error.
283         */
284    public ErrorCode DestroyObject() {
285        return ErrorCode.valueOf(CANifierJNI.JNI_destroy_CANifier(m_handle));
286    }
287
288        /**
289         * Sets the LED Output
290         * @param percentOutput Output duty cycle expressed as percentage.
291         * @param ledChannel            Channel to set the output of.
292         */
293        public void setLEDOutput(double percentOutput, LEDChannel ledChannel) {
294                /* convert float to integral fixed pt */
295                if (percentOutput > 1) {
296                        percentOutput = 1;
297                }
298                if (percentOutput < 0) {
299                        percentOutput = 0;
300                }
301                int dutyCycle = (int) (percentOutput * 1023); // [0,1023]
302
303                CANifierJNI.JNI_SetLEDOutput(m_handle, dutyCycle, ledChannel.value);
304        }
305
306        /**
307         * Sets the output of a General Pin
308         * @param outputPin             The pin to use as output.
309         * @param outputValue   The desired output state.
310         * @param outputEnable  Whether this pin is an output. "True" enables output.
311         */
312        public void setGeneralOutput(GeneralPin outputPin, boolean outputValue, boolean outputEnable) {
313                CANifierJNI.JNI_SetGeneralOutput(m_handle, outputPin.value, outputValue, outputEnable);
314        }
315
316        /**
317         * Sets the output of all General Pins
318         * @param outputBits    A bit mask of all the output states.  LSB->MSB is in the order of the com.ctre.phoenix.CANifier.GeneralPin enum.
319         * @param isOutputBits A boolean bit mask that sets the pins to be outputs or inputs.  A bit of 1 enables output.
320         */
321        public void setGeneralOutputs(int outputBits, int isOutputBits) {
322                CANifierJNI.JNI_SetGeneralOutputs(m_handle, outputBits, isOutputBits);
323        }
324
325        /**
326         * Gets the state of all General Pins
327         * @param allPins A structure to fill with the current state of all pins.
328         */
329        public void getGeneralInputs(PinValues allPins) {
330                CANifierJNI.JNI_GetGeneralInputs(m_handle, _tempPins);
331                allPins.LIMF = _tempPins[GeneralPin.LIMF.value];
332                allPins.LIMR = _tempPins[GeneralPin.LIMR.value];
333                allPins.QUAD_A = _tempPins[GeneralPin.QUAD_A.value];
334                allPins.QUAD_B = _tempPins[GeneralPin.QUAD_B.value];
335                allPins.QUAD_IDX = _tempPins[GeneralPin.QUAD_IDX.value];
336                allPins.SCL = _tempPins[GeneralPin.SCL.value];
337                allPins.SDA = _tempPins[GeneralPin.SDA.value];
338                allPins.SPI_CLK_PWM0 = _tempPins[GeneralPin.SPI_CLK_PWM0P.value];
339                allPins.SPI_MOSI_PWM1 = _tempPins[GeneralPin.SPI_MOSI_PWM1P.value];
340                allPins.SPI_MISO_PWM2 = _tempPins[GeneralPin.SPI_MISO_PWM2P.value];
341                allPins.SPI_CS_PWM3 = _tempPins[GeneralPin.SPI_CS.value];
342        }
343
344        /**
345         * Gets the state of the specified pin
346         * @param inputPin  The index of the pin.
347         * @return The state of the pin.
348         */
349        public boolean getGeneralInput(GeneralPin inputPin) {
350                return CANifierJNI.JNI_GetGeneralInput(m_handle, inputPin.value);
351        }
352
353        /**
354         * Call GetLastError() generated by this object.
355         * Not all functions return an error code but can
356         * potentially report errors.
357         *
358         * This function can be used to retrieve those error codes.
359         *
360         * @return The last ErrorCode generated.
361         */
362        public ErrorCode getLastError() {
363                int retval = CANifierJNI.JNI_GetLastError(m_handle);
364                return ErrorCode.valueOf(retval);
365        }
366
367        /**
368         * Sets the PWM Output
369         * Currently supports PWM 0, PWM 1, and PWM 2
370         * @param pwmChannel  Index of the PWM channel to output.
371         * @param dutyCycle   Duty Cycle (0 to 1) to output.  Default period of the signal is 4.2 ms.
372         */
373        public void setPWMOutput(int pwmChannel, double dutyCycle) {
374                if (dutyCycle < 0) {
375                        dutyCycle = 0;
376                } else if (dutyCycle > 1) {
377                        dutyCycle = 1;
378                }
379                if (pwmChannel < 0) {
380                        pwmChannel = 0;
381                }
382
383                int dutyCyc10bit = (int) (1023 * dutyCycle);
384
385                CANifierJNI.JNI_SetPWMOutput(m_handle, (int) pwmChannel, dutyCyc10bit);
386        }
387
388        /**
389         * Enables PWM Outputs
390         * Currently supports PWM 0, PWM 1, and PWM 2
391         * @param pwmChannel  Index of the PWM channel to enable.
392         * @param bEnable                       "True" enables output on the pwm channel.
393         */
394        public void enablePWMOutput(int pwmChannel, boolean bEnable) {
395                if (pwmChannel < 0) {
396                        pwmChannel = 0;
397                }
398
399                CANifierJNI.JNI_EnablePWMOutput(m_handle, (int) pwmChannel, bEnable);
400        }
401
402        /**
403         * Gets the PWM Input
404         * @param pwmChannel  PWM channel to get.
405         * @param pulseWidthAndPeriod   Double array to hold Duty Cycle [0] and Period [1].
406         */
407        public void getPWMInput(PWMChannel pwmChannel, double[] pulseWidthAndPeriod) {
408                CANifierJNI.JNI_GetPWMInput(m_handle, pwmChannel.value, pulseWidthAndPeriod);
409        }
410        
411        /**
412         * Gets the quadrature encoder's position
413         * @return Position of encoder 
414         */
415        public int getQuadraturePosition() {
416                return CANifierJNI.JNI_GetQuadraturePosition(m_handle);
417        }
418        
419        /**
420         * Sets the quadrature encoder's position
421         * @param newPosition  Position to set
422         * @param timeoutMs  
423                                        Timeout value in ms. If nonzero, function will wait for
424                                        config success and report an error if it times out.
425                                        If zero, no blocking or checking is performed.
426         * @return Error Code generated by function. 0 indicates no error.
427         */
428        public ErrorCode setQuadraturePosition(int newPosition, int timeoutMs) {
429                return ErrorCode.valueOf(CANifierJNI.JNI_SetQuadraturePosition(m_handle, newPosition, timeoutMs));
430        }
431        
432        /**
433         * Gets the quadrature encoder's velocity
434         * @return Velocity of encoder
435         */
436        public int getQuadratureVelocity() {
437                return CANifierJNI.JNI_GetQuadratureVelocity(m_handle);
438        }
439        
440        /**
441         * Configures the period of each velocity sample.
442         * Every 1ms a position value is sampled, and the delta between that sample
443         * and the position sampled kPeriod ms ago is inserted into a filter.
444         * kPeriod is configured with this function.
445         *
446         * @param period
447         *            Desired period for the velocity measurement. @see
448         *            com.ctre.phoenix.sensors.SensorVelocityMeasPeriod
449         * @param timeoutMs
450         *            Timeout value in ms. If nonzero, function will wait for
451         *            config success and report an error if it times out.
452         *            If zero, no blocking or checking is performed.
453         * @return Error Code generated by function. 0 indicates no error.
454         */
455        public ErrorCode configVelocityMeasurementPeriod(SensorVelocityMeasPeriod period, int timeoutMs) {
456                int retval = CANifierJNI.JNI_ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
457                return ErrorCode.valueOf(retval);
458        }
459
460        /**
461         * Configures the period of each velocity sample.
462         * Every 1ms a position value is sampled, and the delta between that sample
463         * and the position sampled kPeriod ms ago is inserted into a filter.
464         * kPeriod is configured with this function.
465         * 
466         * @deprecated Use the overload with SensorVelocityMeasPeriod instead.
467         *
468         * @param period
469         *            Desired period for the velocity measurement. @see
470         *            com.ctre.phoenix.VelocityMeasPeriod
471         * @param timeoutMs
472         *            Timeout value in ms. If nonzero, function will wait for
473         *            config success and report an error if it times out.
474         *            If zero, no blocking or checking is performed.
475         * @return Error Code generated by function. 0 indicates no error.
476         */
477        @Deprecated
478        public ErrorCode configVelocityMeasurementPeriod(VelocityPeriod period, int timeoutMs) {
479                int retval = CANifierJNI.JNI_ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
480                return ErrorCode.valueOf(retval);
481        }
482        /**
483         * Configures the period of each velocity sample.
484         * Every 1ms a position value is sampled, and the delta between that sample
485         * and the position sampled kPeriod ms ago is inserted into a filter.
486         * kPeriod is configured with this function.
487         *
488         * @param period
489         *            Desired period for the velocity measurement. @see
490         *            com.ctre.phoenix.sensor.SensorVelocityMeasPeriod
491         * @return Error Code generated by function. 0 indicates no error.
492         */
493        public ErrorCode configVelocityMeasurementPeriod(SensorVelocityMeasPeriod period) {
494                int timeoutMs = 0;
495                return configVelocityMeasurementPeriod(period, timeoutMs);      
496        }
497        /**
498         * Configures the period of each velocity sample.
499         * Every 1ms a position value is sampled, and the delta between that sample
500         * and the position sampled kPeriod ms ago is inserted into a filter.
501         * kPeriod is configured with this function.
502         * 
503         * @deprecated Use the overload with SensorVelocityMeasPeriod instead.
504         *
505         * @param period
506         *            Desired period for the velocity measurement. @see
507         *            com.ctre.phoenix.motorcontrol.VelocityMeasPeriod
508         * @return Error Code generated by function. 0 indicates no error.
509         */
510        @Deprecated
511        public ErrorCode configVelocityMeasurementPeriod(VelocityPeriod period) {
512                int timeoutMs = 0;
513                return configVelocityMeasurementPeriod(period, timeoutMs);      
514        }
515        
516        /**
517         * Sets the number of velocity samples used in the rolling average velocity
518         * measurement.
519         *
520         * @param windowSize
521         *            Number of samples in the rolling average of velocity
522         *            measurement. Valid values are 1,2,4,8,16,32. If another
523         *            value is specified, it will truncate to nearest support value.
524         * @param timeoutMs
525         *            Timeout value in ms. If nonzero, function will wait for
526         *            config success and report an error if it times out.
527         *            If zero, no blocking or checking is performed.
528         * @return Error Code generated by function. 0 indicates no error.
529         */
530        public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs) {
531                int retval = CANifierJNI.JNI_ConfigVelocityMeasurementWindow(m_handle, windowSize, timeoutMs);
532                return ErrorCode.valueOf(retval);
533        }
534        /**
535         * Sets the number of velocity samples used in the rolling average velocity
536         * measurement.
537         *
538         * @param windowSize
539         *            Number of samples in the rolling average of velocity
540         *            measurement. Valid values are 1,2,4,8,16,32. If another
541         *            value is specified, it will truncate to nearest support value.
542         * @return Error Code generated by function. 0 indicates no error.
543         */
544        public ErrorCode configVelocityMeasurementWindow(int windowSize) {
545                int timeoutMs = 0;
546                return configVelocityMeasurementWindow( windowSize,  timeoutMs);
547        }
548
549    /**
550     * Enables clearing the position of the feedback sensor when the forward 
551     * limit switch is triggered
552     *
553     * @param clearPositionOnLimitF     Whether clearing is enabled, defaults false
554     * @param timeoutMs
555     *            Timeout value in ms. If nonzero, function will wait for
556     *            config success and report an error if it times out.
557     *            If zero, no blocking or checking is performed.
558     * @return Error Code generated by function. 0 indicates no error.
559     */
560    public ErrorCode configClearPositionOnLimitF(boolean clearPositionOnLimitF, int timeoutMs) {
561        int retval = CANifierJNI.JNI_ConfigClearPositionOnLimitF(m_handle, clearPositionOnLimitF, timeoutMs);
562        return ErrorCode.valueOf(retval);
563    }
564    /**
565     * Enables clearing the position of the feedback sensor when the reverse 
566     * limit switch is triggered
567     *
568     * @param clearPositionOnLimitR     Whether clearing is enabled, defaults false
569     * @param timeoutMs
570     *            Timeout value in ms. If nonzero, function will wait for
571     *            config success and report an error if it times out.
572     *            If zero, no blocking or checking is performed.
573     * @return Error Code generated by function. 0 indicates no error.
574     */
575    public ErrorCode configClearPositionOnLimitR(boolean clearPositionOnLimitR, int timeoutMs) {
576        int retval = CANifierJNI.JNI_ConfigClearPositionOnLimitR(m_handle, clearPositionOnLimitR, timeoutMs);
577        return ErrorCode.valueOf(retval);
578    }
579    /**
580     * Enables clearing the position of the feedback sensor when the quadrature index signal
581     * is detected
582     *
583     * @param clearPositionOnQuadIdx    Whether clearing is enabled, defaults false
584     * @param timeoutMs
585     *            Timeout value in ms. If nonzero, function will wait for
586     *            config success and report an error if it times out.
587     *            If zero, no blocking or checking is performed.
588     * @return Error Code generated by function. 0 indicates no error.
589     */
590    public ErrorCode configClearPositionOnQuadIdx(boolean clearPositionOnQuadIdx, int timeoutMs) {
591        int retval = CANifierJNI.JNI_ConfigClearPositionOnQuadIdx(m_handle, clearPositionOnQuadIdx, timeoutMs);
592        return ErrorCode.valueOf(retval);
593    }
594        /**
595         * Sets the value of a custom parameter. This is for arbitrary use.
596     *
597     * Sometimes it is necessary to save calibration/duty cycle/output
598     * information in the device. Particularly if the
599     * device is part of a subsystem that can be replaced.
600         *
601         * @param newValue
602         *            Value for custom parameter.
603         * @param paramIndex
604         *            Index of custom parameter. [0-1]
605         * @param timeoutMs
606         *            Timeout value in ms. If nonzero, function will wait for
607     *            config success and report an error if it times out.
608     *            If zero, no blocking or checking is performed.
609         * @return Error Code generated by function. 0 indicates no error.
610         */
611        public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs) {
612                int retval = CANifierJNI.JNI_ConfigSetCustomParam(m_handle, newValue, paramIndex, timeoutMs);
613                return ErrorCode.valueOf(retval);
614        }
615        /**
616         * Sets the value of a custom parameter. This is for arbitrary use.
617     *
618     * Sometimes it is necessary to save calibration/duty cycle/output
619     * information in the device. Particularly if the
620     * device is part of a subsystem that can be replaced.
621         *
622         * @param newValue
623         *            Value for custom parameter.
624         * @param paramIndex
625         *            Index of custom parameter. [0-1]
626         * @return Error Code generated by function. 0 indicates no error.
627         */
628        public ErrorCode configSetCustomParam(int newValue, int paramIndex) {
629
630                int timeoutMs = 0;
631                return configSetCustomParam( newValue,  paramIndex,  timeoutMs);
632        }
633
634        /**
635         * Gets the value of a custom parameter. This is for arbitrary use.
636     *
637     * Sometimes it is necessary to save calibration/duty cycle/output
638     * information in the device. Particularly if the
639     * device is part of a subsystem that can be replaced.
640         *
641         * @param paramIndex
642         *            Index of custom parameter. [0-1]
643         * @param timeoutMs
644         *            Timeout value in ms. If nonzero, function will wait for
645     *            config success and report an error if it times out.
646     *            If zero, no blocking or checking is performed.
647         * @return Value of the custom param.
648         */
649        public int configGetCustomParam(int paramIndex, int timeoutMs) {
650                int retval = CANifierJNI.JNI_ConfigGetCustomParam(m_handle, paramIndex, timeoutMs);
651                return retval;
652        }
653        /**
654         * Gets the value of a custom parameter. This is for arbitrary use.
655     *
656     * Sometimes it is necessary to save calibration/duty cycle/output
657     * information in the device. Particularly if the
658     * device is part of a subsystem that can be replaced.
659         *
660         * @param paramIndex
661         *            Index of custom parameter. [0-1]
662         * @return Value of the custom param.
663         */
664        public int configGetCustomParam(int paramIndex) {
665                int timeoutMs = 0;
666                return configGetCustomParam( paramIndex,  timeoutMs);
667        }
668
669        /**
670         * Sets a parameter. Generally this is not used.
671     * This can be utilized in
672     * - Using new features without updating API installation.
673     * - Errata workarounds to circumvent API implementation.
674     * - Allows for rapid testing / unit testing of firmware.
675         *
676         * @param param
677         *            Parameter enumeration.
678         * @param value
679         *            Value of parameter.
680         * @param subValue
681         *            Subvalue for parameter. Maximum value of 255.
682         * @param ordinal
683         *            Ordinal of parameter.
684         * @param timeoutMs
685         *            Timeout value in ms. If nonzero, function will wait for
686     *            config success and report an error if it times out.
687     *            If zero, no blocking or checking is performed.
688         * @return Error Code generated by function. 0 indicates no error.
689         */
690        public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
691                return configSetParameter(param.value, value, subValue, ordinal, timeoutMs);
692        }
693        /**
694         * Sets a parameter. Generally this is not used.
695     * This can be utilized in
696     * - Using new features without updating API installation.
697     * - Errata workarounds to circumvent API implementation.
698     * - Allows for rapid testing / unit testing of firmware.
699         *
700         * @param param
701         *            Parameter enumeration.
702         * @param value
703         *            Value of parameter.
704         * @param subValue
705         *            Subvalue for parameter. Maximum value of 255.
706         * @param ordinal
707         *            Ordinal of parameter.
708         * @return Error Code generated by function. 0 indicates no error.
709         */
710        public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal) {
711                int timeoutMs = 0;
712                return configSetParameter(param, value, subValue, ordinal, timeoutMs);
713        }
714
715        /**
716         * Sets a parameter. Generally this is not used.
717     * This can be utilized in
718     * - Using new features without updating API installation.
719     * - Errata workarounds to circumvent API implementation.
720     * - Allows for rapid testing / unit testing of firmware.
721         *
722         * @param param
723         *            Parameter enumeration.
724         * @param value
725         *            Value of parameter.
726         * @param subValue
727         *            Subvalue for parameter. Maximum value of 255.
728         * @param ordinal
729         *            Ordinal of parameter.
730         * @param timeoutMs
731         *            Timeout value in ms. If nonzero, function will wait for
732     *            config success and report an error if it times out.
733     *            If zero, no blocking or checking is performed.
734         * @return Error Code generated by function. 0 indicates no error.
735         */
736        public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs) {
737                int retval = CANifierJNI.JNI_ConfigSetParameter(m_handle, param, value, subValue, ordinal,
738                                timeoutMs);
739                return ErrorCode.valueOf(retval);
740        }
741        /**
742         * Sets a parameter. Generally this is not used.
743     * This can be utilized in
744     * - Using new features without updating API installation.
745     * - Errata workarounds to circumvent API implementation.
746     * - Allows for rapid testing / unit testing of firmware.
747         *
748         * @param param
749         *            Parameter enumeration.
750         * @param value
751         *            Value of parameter.
752         * @param subValue
753         *            Subvalue for parameter. Maximum value of 255.
754         * @param ordinal
755         *            Ordinal of parameter.
756         * @return Error Code generated by function. 0 indicates no error.
757         */
758        public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal) {
759                int timeoutMs = 0;
760                return configSetParameter( param,  value,  subValue,  ordinal,  timeoutMs);
761        }
762        /**
763         * Gets a parameter. Generally this is not used.
764     * This can be utilized in
765     * - Using new features without updating API installation.
766     * - Errata workarounds to circumvent API implementation.
767     * - Allows for rapid testing / unit testing of firmware.
768         *
769         * @param param
770         *            Parameter enumeration.
771         * @param ordinal
772         *            Ordinal of parameter.
773         * @param timeoutMs
774         *            Timeout value in ms. If nonzero, function will wait for
775     *            config success and report an error if it times out.
776     *            If zero, no blocking or checking is performed.
777         * @return Value of parameter.
778         */
779        public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
780                return CANifierJNI.JNI_ConfigGetParameter(m_handle, param.value, ordinal, timeoutMs);
781        }
782        /**
783         * Gets a parameter. Generally this is not used.
784     * This can be utilized in
785     * - Using new features without updating API installation.
786     * - Errata workarounds to circumvent API implementation.
787     * - Allows for rapid testing / unit testing of firmware.
788         *
789         * @param param
790         *            Parameter enumeration.
791         * @param ordinal
792         *            Ordinal of parameter.
793         * @return Value of parameter.
794         */
795        public double configGetParameter(ParamEnum param, int ordinal) {
796                int timeoutMs = 0;
797                return configGetParameter(param,  ordinal,  timeoutMs);
798        }
799        /**
800         * Sets the period of the given status frame.
801         *
802         * @param statusFrame
803         *            Frame whose period is to be changed.
804         * @param periodMs
805         *            Period in ms for the given frame.
806         * @param timeoutMs
807         *            Timeout value in ms. If nonzero, function will wait for
808     *            config success and report an error if it times out.
809     *            If zero, no blocking or checking is performed.
810         * @return Error Code generated by function. 0 indicates no error.
811         */
812        public ErrorCode setStatusFramePeriod(CANifierStatusFrame statusFrame, int periodMs, int timeoutMs) {
813                int retval = CANifierJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame.value, periodMs, timeoutMs);
814                return ErrorCode.valueOf(retval);
815        }
816        /**
817         * Sets the period of the given status frame.
818         *
819         * @param statusFrame
820         *            Frame whose period is to be changed.
821         * @param periodMs
822         *            Period in ms for the given frame.
823         * @return Error Code generated by function. 0 indicates no error.
824         */
825        public ErrorCode setStatusFramePeriod(CANifierStatusFrame statusFrame, int periodMs) {
826                int timeoutMs = 0;
827                return setStatusFramePeriod(statusFrame,  periodMs,  timeoutMs);
828        }
829        /**
830         * Sets the period of the given status frame.
831         *
832         * @param statusFrame
833         *            Frame whose period is to be changed.
834         * @param periodMs
835         *            Period in ms for the given frame.
836         * @param timeoutMs
837         *            Timeout value in ms. If nonzero, function will wait for
838     *            config success and report an error if it times out.
839     *            If zero, no blocking or checking is performed.
840         * @return Error Code generated by function. 0 indicates no error.
841         */
842        public ErrorCode setStatusFramePeriod(int statusFrame, int periodMs, int timeoutMs) {
843                int retval = CANifierJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame, periodMs, timeoutMs);
844                return ErrorCode.valueOf(retval);
845        }
846        /**
847         * Sets the period of the given status frame.
848         *
849         * @param statusFrame
850         *            Frame whose period is to be changed.
851         * @param periodMs
852         *            Period in ms for the given frame.
853         * @return Error Code generated by function. 0 indicates no error.
854         */
855        public ErrorCode setStatusFramePeriod(int statusFrame, int periodMs) {
856                int timeoutMs = 0;
857                return setStatusFramePeriod( statusFrame,  periodMs,  timeoutMs);
858        }
859
860        /**
861         * Gets the period of the given status frame.
862         *
863         * @param frame
864         *            Frame to get the period of.
865         * @param timeoutMs
866         *            Timeout value in ms. If nonzero, function will wait for
867     *            config success and report an error if it times out.
868     *            If zero, no blocking or checking is performed.
869         * @return Period of the given status frame.
870         */
871        public int getStatusFramePeriod(CANifierStatusFrame frame, int timeoutMs) {
872                return CANifierJNI.JNI_GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
873        }
874        /**
875         * Gets the period of the given status frame.
876         *
877         * @param frame
878         *            Frame to get the period of.
879         * @return Period of the given status frame.
880         */
881        public int getStatusFramePeriod(CANifierStatusFrame frame) {
882                int timeoutMs = 0;
883                return getStatusFramePeriod(frame, timeoutMs);  
884        }
885
886        /**
887         * Sets the period of the given control frame.
888         *
889         * @param frame
890         *            Frame whose period is to be changed.
891         * @param periodMs
892         *            Period in ms for the given frame.
893         * @return Error Code generated by function. 0 indicates no error.
894         */
895        public ErrorCode setControlFramePeriod(CANifierControlFrame frame, int periodMs) {
896                int retval = CANifierJNI.JNI_SetControlFramePeriod(m_handle, frame.value, periodMs);
897                return ErrorCode.valueOf(retval);
898        }
899        /**
900         * Sets the period of the given control frame.
901         *
902         * @param frame
903         *            Frame whose period is to be changed.
904         * @param periodMs
905         *            Period in ms for the given frame.
906         * @return Error Code generated by function. 0 indicates no error.
907         */
908        public ErrorCode setControlFramePeriod(int frame, int periodMs) {
909                int retval = CANifierJNI.JNI_SetControlFramePeriod(m_handle, frame, periodMs);
910                return ErrorCode.valueOf(retval);
911        }
912
913        /**
914         * Gets the firmware version of the device.
915         *
916         * @return Firmware version of device.
917         */
918        public int getFirmwareVersion() {
919                return CANifierJNI.JNI_GetFirmwareVersion(m_handle);
920        }
921
922        /**
923         * Returns true if the device has reset since last call.
924         *
925         * @return Has a Device Reset Occurred?
926         */
927        public boolean hasResetOccurred() {
928                return CANifierJNI.JNI_HasResetOccurred(m_handle);
929        }
930
931        // ------ Faults ----------//
932        /**
933         * Gets the CANifier fault status
934         *
935         * @param toFill
936         *            Container for fault statuses.
937         * @return Error Code generated by function. 0 indicates no error.
938         */
939        public ErrorCode getFaults(CANifierFaults toFill) {
940                int bits = CANifierJNI.JNI_GetFaults(m_handle);
941                toFill.update(bits);
942                return getLastError();
943        }
944        /**
945         * Gets the CANifier sticky fault status
946         *
947         * @param toFill
948         *            Container for sticky fault statuses.
949         * @return Error Code generated by function. 0 indicates no error.
950         */
951        public ErrorCode getStickyFaults(CANifierStickyFaults toFill) {
952                int bits = CANifierJNI.JNI_GetStickyFaults(m_handle);
953                toFill.update(bits);
954                return getLastError();
955        }
956        /**
957         * Clears the Sticky Faults
958         * 
959         * @param timeoutMs
960         *            Timeout value in ms. If nonzero, function will wait for
961     *            config success and report an error if it times out.
962     *            If zero, no blocking or checking is performed.
963         *
964         * @return Error Code generated by function. 0 indicates no error.
965         */
966        public ErrorCode clearStickyFaults(int timeoutMs) {
967                int retval = CANifierJNI.JNI_ClearStickyFaults(m_handle, timeoutMs);
968                return ErrorCode.valueOf(retval);
969        }
970
971        /**
972         * Gets the bus voltage seen by the device.
973         *
974         * @return The bus voltage value (in volts).
975         */
976        public double getBusVoltage() {
977                return CANifierJNI.JNI_GetBusVoltage(m_handle);
978        }
979
980        /**
981         * @return The Device Number
982         */
983        public int getDeviceID(){
984                return m_deviceNumber;
985        }
986
987        //------ All Configs ----------//
988    /**
989     * Configures all persistent settings.
990     *
991         * @param allConfigs        Object with all of the persistant settings
992     * @param timeoutMs
993     *              Timeout value in ms. If nonzero, function will wait for
994     *              config success and report an error if it times out.
995     *              If zero, no blocking or checking is performed.
996     *
997     * @return Error Code generated by function. 0 indicates no error. 
998     */
999        public ErrorCode configAllSettings(CANifierConfiguration allConfigs, int timeoutMs) {
1000        ErrorCollection errorCollection = new ErrorCollection();
1001                
1002                errorCollection.NewError(configFactoryDefault(timeoutMs));
1003                
1004                if(CANifierConfigUtil.velocityMeasurementPeriodDifferent(allConfigs)) errorCollection.NewError(configVelocityMeasurementPeriod(allConfigs.velocityMeasurementPeriod, timeoutMs));
1005                if(CANifierConfigUtil.velocityMeasurementWindowDifferent(allConfigs)) errorCollection.NewError(configVelocityMeasurementWindow(allConfigs.velocityMeasurementWindow, timeoutMs));
1006                if(CANifierConfigUtil.clearPositionOnLimitFDifferent(allConfigs)) errorCollection.NewError(configClearPositionOnLimitF(allConfigs.clearPositionOnLimitF, timeoutMs));
1007                if(CANifierConfigUtil.clearPositionOnLimitRDifferent(allConfigs)) errorCollection.NewError(configClearPositionOnLimitR(allConfigs.clearPositionOnLimitR, timeoutMs));
1008                if(CANifierConfigUtil.clearPositionOnQuadIdxDifferent(allConfigs)) errorCollection.NewError(configClearPositionOnQuadIdx(allConfigs.clearPositionOnQuadIdx, timeoutMs));
1009
1010                //Custom Parameters
1011                if(CustomParamConfigUtil.customParam0Different(allConfigs)) errorCollection.NewError(configSetCustomParam(allConfigs.customParam0, 0, timeoutMs));
1012                if(CustomParamConfigUtil.customParam1Different(allConfigs)) errorCollection.NewError(configSetCustomParam(allConfigs.customParam1, 1, timeoutMs));
1013        
1014    
1015        return errorCollection._worstError;
1016
1017        }
1018    /**
1019     * Configures all persistent settings (overloaded so timeoutMs is 50 ms).
1020     *
1021         * @param allConfigs        Object with all of the persistant settings
1022     *
1023     * @return Error Code generated by function. 0 indicates no error. 
1024     */
1025        public ErrorCode configAllSettings(CANifierConfiguration allConfigs) {
1026                int timeoutMs = 50;
1027                return configAllSettings(allConfigs, timeoutMs);
1028        }
1029    /**
1030     * Gets all persistant settings.
1031     *
1032         * @param allConfigs        Object with all of the persistant settings
1033     * @param timeoutMs
1034     *              Timeout value in ms. If nonzero, function will wait for
1035     *              config success and report an error if it times out.
1036     *              If zero, no blocking or checking is performed.
1037     */
1038    public void getAllConfigs(CANifierConfiguration allConfigs, int timeoutMs) {
1039
1040        allConfigs.velocityMeasurementPeriod = VelocityPeriod.valueOf( (int) configGetParameter(ParamEnum.eSampleVelocityPeriod, 0,  timeoutMs));
1041        allConfigs.velocityMeasurementWindow = (int) configGetParameter(ParamEnum.eSampleVelocityWindow, 0,  timeoutMs);
1042        allConfigs.clearPositionOnLimitF  = configGetParameter(ParamEnum.eClearPositionOnLimitF, 0, timeoutMs) != 0.0;
1043        allConfigs.clearPositionOnLimitR  = configGetParameter(ParamEnum.eClearPositionOnLimitR, 0, timeoutMs) != 0.0;
1044        allConfigs.clearPositionOnQuadIdx = configGetParameter(ParamEnum.eClearPositionOnQuadIdx, 0, timeoutMs) != 0.0;
1045        allConfigs.customParam0 = (int) configGetParameter(ParamEnum.eCustomParam, 0,  timeoutMs);
1046        allConfigs.customParam1 = (int) configGetParameter(ParamEnum.eCustomParam, 1,  timeoutMs);
1047    }
1048    /**
1049     * Gets all persistant settings (overloaded so timeoutMs is 50 ms).
1050     *
1051         * @param allConfigs        Object with all of the persistant settings
1052     */
1053    public void getAllConfigs(CANifierConfiguration allConfigs) {
1054        int timeoutMs = 50;
1055        getAllConfigs(allConfigs, timeoutMs);
1056    }
1057    /**
1058     * Configures all persistent settings to defaults.
1059     *
1060     * @param timeoutMs
1061     *              Timeout value in ms. If nonzero, function will wait for
1062     *              config success and report an error if it times out.
1063     *              If zero, no blocking or checking is performed.
1064     *
1065     * @return Error Code generated by function. 0 indicates no error. 
1066     */
1067        public ErrorCode configFactoryDefault(int timeoutMs) {
1068            return ErrorCode.valueOf(CANifierJNI.JNI_ConfigFactoryDefault(m_handle, timeoutMs));
1069        }
1070    /**
1071     * Configures all persistent settings to defaults (overloaded so timeoutMs is 50 ms).
1072     *
1073     * @return Error Code generated by function. 0 indicates no error. 
1074     */
1075        public ErrorCode configFactoryDefault() {
1076                int timeoutMs = 50;     
1077                return configFactoryDefault( timeoutMs);
1078        }
1079
1080
1081}