Squashed 'third_party/Phoenix-frc-lib/' content from commit 666d176

Change-Id: Ibaca2fc8ffb1177e786576cc1e4cc9f7a8c98f13
git-subtree-dir: third_party/Phoenix-frc-lib
git-subtree-split: 666d176a08151793044ab74e0005f13d3732ed96
diff --git a/java/src/com/ctre/CANTalon.java b/java/src/com/ctre/CANTalon.java
new file mode 100644
index 0000000..860c627
--- /dev/null
+++ b/java/src/com/ctre/CANTalon.java
@@ -0,0 +1,12 @@
+package com.ctre;
+
+/**
+*  @deprecated Use TalonSRX instead. This deprecated class will be removed in 2019.
+*  @see <a href="https://github.com/CrossTheRoadElec/Phoenix-Documentation/blob/master/Migration%20Guide.md">Phoenix 2018 Migration Guide</a>
+*/
+@Deprecated
+public class CANTalon extends com.ctre.phoenix.motorcontrol.can.TalonSRX {
+	public CANTalon(int deviceNumber) {
+		super(deviceNumber);
+	}
+}
diff --git a/java/src/com/ctre/phoenix/ButtonMonitor.java b/java/src/com/ctre/phoenix/ButtonMonitor.java
new file mode 100644
index 0000000..936fb7a
--- /dev/null
+++ b/java/src/com/ctre/phoenix/ButtonMonitor.java
@@ -0,0 +1,43 @@
+package com.ctre.phoenix;
+
+import edu.wpi.first.wpilibj.GenericHID;
+
+public class ButtonMonitor implements ILoopable
+{
+	GenericHID  _gameCntrlr;
+	int _btnIdx;
+	IButtonPressEventHandler  _handler;
+	boolean _isDown = false;
+	
+	public interface IButtonPressEventHandler {
+		void OnButtonPress(int idx, boolean isDown);
+	};
+
+	public ButtonMonitor(GenericHID controller, int buttonIndex,
+			IButtonPressEventHandler ButtonPressEventHandler) {
+		_gameCntrlr = controller;
+		_btnIdx = buttonIndex;
+		_handler = ButtonPressEventHandler;
+	}
+
+	public void process() {
+		boolean down = _gameCntrlr.getRawButton(_btnIdx);
+
+		if (!_isDown && down){
+			_handler.OnButtonPress(_btnIdx, down);
+		}
+
+		_isDown = down;
+	}
+
+	public void onStart() {
+	}
+	public void onLoop() {
+		process();
+	}
+	public boolean isDone() {
+		return false;
+	}
+	public void onStop() {
+	}
+}
diff --git a/java/src/com/ctre/phoenix/CANifier.java b/java/src/com/ctre/phoenix/CANifier.java
new file mode 100644
index 0000000..31d33ce
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CANifier.java
@@ -0,0 +1,616 @@
+/*
+ *  Software License Agreement
+ *
+ * Copyright (C) Cross The Road Electronics.  All rights
+ * reserved.
+ *
+ * Cross The Road Electronics (CTRE) licenses to you the right to
+ * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and Software
+ * API Libraries ONLY when in use with Cross The Road Electronics hardware products.
+ *
+ * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
+ * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
+ * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
+ * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
+ * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
+ * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE
+ */
+
+package com.ctre.phoenix;
+
+import edu.wpi.first.wpilibj.hal.HAL;
+
+/**
+ * CTRE CANifier
+ *
+ * Device for interfacing common devices to the CAN bus.
+ */
+public class CANifier {
+	private long m_handle;
+
+	/**
+	 * Enum for velocity periods
+	 */
+	public enum VelocityPeriod {
+		Period_1Ms(1),
+		Period_2Ms(2),
+		Period_5Ms(5),
+		Period_10Ms(10),
+		Period_20Ms(20),
+		Period_25Ms(25),
+		Period_50Ms(50),
+		Period_100Ms(100);
+		public static VelocityPeriod valueOf(int value) {
+			for(VelocityPeriod period : values()) {
+				if(period.value == value) {
+					return period;
+				}
+			}
+			return null;
+		}
+		public final int value;
+		VelocityPeriod(int initValue) {
+			this.value = initValue;
+		}
+	}
+	
+	/**
+	 * Enum for the LED Output Channels
+	 */
+	public enum LEDChannel {
+		LEDChannelA(0), LEDChannelB(1), LEDChannelC(2);
+		public static LEDChannel valueOf(int value) {
+			for (LEDChannel mode : values()) {
+				if (mode.value == value) {
+					return mode;
+				}
+			}
+			return null;
+		}
+
+		public final int value;
+
+		LEDChannel(int initValue) {
+			this.value = initValue;
+		}
+	}
+
+	/**
+	 * Enum for the PWM Input Channels
+	 */
+	public enum PWMChannel {
+		PWMChannel0(0), PWMChannel1(1), PWMChannel2(2), PWMChannel3(3);
+		public static PWMChannel valueOf(int value) {
+			for (PWMChannel mode : values()) {
+				if (mode.value == value) {
+					return mode;
+				}
+			}
+			return null;
+		}
+
+		public final int value;
+
+		PWMChannel(int initValue) {
+			this.value = initValue;
+		}
+	}
+
+	public final int PWMChannelCount = 4;
+
+	/**
+	 * General IO Pins on the CANifier
+	 */
+	public enum GeneralPin {
+		QUAD_IDX (CANifierJNI.GeneralPin.QUAD_IDX.value),
+		QUAD_B (CANifierJNI.GeneralPin.QUAD_B.value),
+		QUAD_A (CANifierJNI.GeneralPin.QUAD_A.value),
+		LIMR (CANifierJNI.GeneralPin.LIMR.value),
+		LIMF (CANifierJNI.GeneralPin.LIMF.value),
+		SDA (CANifierJNI.GeneralPin.SDA.value),
+		SCL (CANifierJNI.GeneralPin.SCL.value),
+		SPI_CS (CANifierJNI.GeneralPin.SPI_CS.value),
+		SPI_MISO_PWM2P (CANifierJNI.GeneralPin.SPI_MISO_PWM2P.value),
+		SPI_MOSI_PWM1P (CANifierJNI.GeneralPin.SPI_MOSI_PWM1P.value),
+		SPI_CLK_PWM0P (CANifierJNI.GeneralPin.SPI_CLK_PWM0P.value);
+		public static GeneralPin valueOf(int value) {
+			for (GeneralPin mode : values()) {
+				if (mode.value == value) {
+					return mode;
+				}
+			}
+			return null;
+		}
+
+		public final int value;
+
+		GeneralPin(int initValue) {
+			this.value = initValue;
+		}
+	}
+
+	/**
+	 * Class to hold the pin values.
+	 */
+	public static class PinValues {
+		public boolean QUAD_IDX;
+		public boolean QUAD_B;
+		public boolean QUAD_A;
+		public boolean LIMR;
+		public boolean LIMF;
+		public boolean SDA;
+		public boolean SCL;
+		public boolean SPI_CS_PWM3;
+		public boolean SPI_MISO_PWM2;
+		public boolean SPI_MOSI_PWM1;
+		public boolean SPI_CLK_PWM0;
+	}
+
+	private boolean[] _tempPins = new boolean[11];
+
+	private int m_deviceNumber;
+	/**
+	 * Constructor.
+	 * @param deviceId	The CAN Device ID of the CANifier.
+	 */
+	public CANifier(int deviceId) {
+		m_handle = CANifierJNI.JNI_new_CANifier(deviceId);
+		m_deviceNumber = deviceId;
+		HAL.report(63, deviceId + 1);
+	}
+
+	/**
+	 * Sets the LED Output
+	 * @param percentOutput Output duty cycle expressed as percentage.
+	 * @param ledChannel 		Channel to set the output of.
+	 */
+	public void setLEDOutput(double percentOutput, LEDChannel ledChannel) {
+		/* convert float to integral fixed pt */
+		if (percentOutput > 1) {
+			percentOutput = 1;
+		}
+		if (percentOutput < 0) {
+			percentOutput = 0;
+		}
+		int dutyCycle = (int) (percentOutput * 1023); // [0,1023]
+
+		CANifierJNI.JNI_SetLEDOutput(m_handle, dutyCycle, ledChannel.value);
+	}
+
+	/**
+	 * Sets the output of a General Pin
+	 * @param outputPin 		The pin to use as output.
+	 * @param outputValue 	The desired output state.
+	 * @param outputEnable	Whether this pin is an output. "True" enables output.
+	 */
+	public void setGeneralOutput(GeneralPin outputPin, boolean outputValue, boolean outputEnable) {
+		CANifierJNI.JNI_SetGeneralOutput(m_handle, outputPin.value, outputValue, outputEnable);
+	}
+
+	/**
+	 * Sets the output of all General Pins
+	 * @param outputBits 	A bit mask of all the output states.  LSB->MSB is in the order of the #GeneralPin enum.
+	 * @param isOutputBits A boolean bit mask that sets the pins to be outputs or inputs.  A bit of 1 enables output.
+	 */
+	public void setGeneralOutputs(int outputBits, int isOutputBits) {
+		CANifierJNI.JNI_SetGeneralOutputs(m_handle, outputBits, isOutputBits);
+	}
+
+	/**
+	 * Gets the state of all General Pins
+	 * @param allPins A structure to fill with the current state of all pins.
+	 */
+	public void getGeneralInputs(PinValues allPins) {
+		CANifierJNI.JNI_GetGeneralInputs(m_handle, _tempPins);
+		allPins.LIMF = _tempPins[GeneralPin.LIMF.value];
+		allPins.LIMR = _tempPins[GeneralPin.LIMR.value];
+		allPins.QUAD_A = _tempPins[GeneralPin.QUAD_A.value];
+		allPins.QUAD_B = _tempPins[GeneralPin.QUAD_B.value];
+		allPins.QUAD_IDX = _tempPins[GeneralPin.QUAD_IDX.value];
+		allPins.SCL = _tempPins[GeneralPin.SCL.value];
+		allPins.SDA = _tempPins[GeneralPin.SDA.value];
+		allPins.SPI_CLK_PWM0 = _tempPins[GeneralPin.SPI_CLK_PWM0P.value];
+		allPins.SPI_MOSI_PWM1 = _tempPins[GeneralPin.SPI_MOSI_PWM1P.value];
+		allPins.SPI_MISO_PWM2 = _tempPins[GeneralPin.SPI_MISO_PWM2P.value];
+		allPins.SPI_CS_PWM3 = _tempPins[GeneralPin.SPI_CS.value];
+	}
+
+	/**
+	 * Gets the state of the specified pin
+	 * @param inputPin  The index of the pin.
+	 * @return The state of the pin.
+	 */
+	public boolean getGeneralInput(GeneralPin inputPin) {
+		return CANifierJNI.JNI_GetGeneralInput(m_handle, inputPin.value);
+	}
+
+	/**
+	 * Call GetLastError() generated by this object.
+	 * Not all functions return an error code but can
+	 * potentially report errors.
+	 *
+	 * This function can be used to retrieve those error codes.
+	 *
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getLastError() {
+		int retval = CANifierJNI.JNI_GetLastError(m_handle);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the PWM Output
+	 * Currently supports PWM 0, PWM 1, and PWM 2
+	 * @param pwmChannel  Index of the PWM channel to output.
+	 * @param dutyCycle   Duty Cycle (0 to 1) to output.  Default period of the signal is 4.2 ms.
+	 */
+	public void setPWMOutput(int pwmChannel, double dutyCycle) {
+		if (dutyCycle < 0) {
+			dutyCycle = 0;
+		} else if (dutyCycle > 1) {
+			dutyCycle = 1;
+		}
+		if (pwmChannel < 0) {
+			pwmChannel = 0;
+		}
+
+		int dutyCyc10bit = (int) (1023 * dutyCycle);
+
+		CANifierJNI.JNI_SetPWMOutput(m_handle, (int) pwmChannel, dutyCyc10bit);
+	}
+
+	/**
+	 * Enables PWM Outputs
+	 * Currently supports PWM 0, PWM 1, and PWM 2
+	 * @param pwmChannel  Index of the PWM channel to enable.
+	 * @param bEnable			"True" enables output on the pwm channel.
+	 */
+	public void enablePWMOutput(int pwmChannel, boolean bEnable) {
+		if (pwmChannel < 0) {
+			pwmChannel = 0;
+		}
+
+		CANifierJNI.JNI_EnablePWMOutput(m_handle, (int) pwmChannel, bEnable);
+	}
+
+	/**
+	 * Gets the PWM Input
+	 * @param pwmChannel  PWM channel to get.
+	 * @param dutyCycleAndPeriod	Double array to hold Duty Cycle [0] and Period [1].
+	 */
+	public void getPWMInput(PWMChannel pwmChannel, double[] dutyCycleAndPeriod) {
+		CANifierJNI.JNI_GetPWMInput(m_handle, pwmChannel.value, dutyCycleAndPeriod);
+	}
+	
+	/**
+	 * Gets the quadrature encoder's position
+	 * @return Position of encoder 
+	 */
+	public int getQuadraturePosition() {
+		return CANifierJNI.JNI_GetQuadraturePosition(m_handle);
+	}
+	
+	/**
+	 * Sets the quadrature encoder's position
+	 * @param newPosition  Position to set
+	 * @param timeoutMs  
+					Timeout value in ms. If nonzero, function will wait for
+					config success and report an error if it times out.
+					If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setQuadraturePosition(int newPosition, int timeoutMs) {
+		return ErrorCode.valueOf(CANifierJNI.JNI_SetQuadraturePosition(m_handle, newPosition, timeoutMs));
+	}
+	
+	/**
+	 * Gets the quadrature encoder's velocity
+	 * @return Velocity of encoder
+	 */
+	public int getQuadratureVelocity() {
+		return CANifierJNI.JNI_GetQuadratureVelocity(m_handle);
+	}
+	
+	/**
+	 * Configures the period of each velocity sample.
+	 * Every 1ms a position value is sampled, and the delta between that sample
+	 * and the position sampled kPeriod ms ago is inserted into a filter.
+	 * kPeriod is configured with this function.
+	 *
+	 * @param period
+	 *            Desired period for the velocity measurement. @see
+	 *            #VelocityMeasPeriod
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVelocityMeasurementPeriod(VelocityPeriod period, int timeoutMs) {
+		int retval = CANifierJNI.JNI_ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	
+	/**
+	 * Sets the number of velocity samples used in the rolling average velocity
+	 * measurement.
+	 *
+	 * @param windowSize
+	 *            Number of samples in the rolling average of velocity
+	 *            measurement. Valid values are 1,2,4,8,16,32. If another
+	 *            value is specified, it will truncate to nearest support value.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs) {
+		int retval = CANifierJNI.JNI_ConfigVelocityMeasurementWindow(m_handle, windowSize, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the value of a custom parameter. This is for arbitrary use.
+   *
+   * Sometimes it is necessary to save calibration/duty cycle/output
+   * information in the device. Particularly if the
+   * device is part of a subsystem that can be replaced.
+	 *
+	 * @param newValue
+	 *            Value for custom parameter.
+	 * @param paramIndex
+	 *            Index of custom parameter. [0-1]
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs) {
+		int retval = CANifierJNI.JNI_ConfigSetCustomParam(m_handle, newValue, paramIndex, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the value of a custom parameter. This is for arbitrary use.
+   *
+   * Sometimes it is necessary to save calibration/duty cycle/output
+   * information in the device. Particularly if the
+   * device is part of a subsystem that can be replaced.
+	 *
+	 * @param paramIndex
+	 *            Index of custom parameter. [0-1]
+	 * @param timoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Value of the custom param.
+	 */
+	public int configGetCustomParam(int paramIndex, int timoutMs) {
+		int retval = CANifierJNI.JNI_ConfigGetCustomParam(m_handle, paramIndex, timoutMs);
+		return retval;
+	}
+
+	/**
+	 * Sets a parameter. Generally this is not used.
+   * This can be utilized in
+   * - Using new features without updating API installation.
+   * - Errata workarounds to circumvent API implementation.
+   * - Allows for rapid testing / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
+		return configSetParameter(param.value, value, subValue, ordinal, timeoutMs);
+	}
+
+	/**
+	 * Sets a parameter. Generally this is not used.
+   * This can be utilized in
+   * - Using new features without updating API installation.
+   * - Errata workarounds to circumvent API implementation.
+   * - Allows for rapid testing / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs) {
+		int retval = CANifierJNI.JNI_ConfigSetParameter(m_handle, param, value, subValue, ordinal,
+				timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Gets a parameter. Generally this is not used.
+   * This can be utilized in
+   * - Using new features without updating API installation.
+   * - Errata workarounds to circumvent API implementation.
+   * - Allows for rapid testing / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Value of parameter.
+	 */
+	public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
+		return CANifierJNI.JNI_ConfigGetParameter(m_handle, param.value, ordinal, timeoutMs);
+	}
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * @param statusFrame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(CANifierStatusFrame statusFrame, int periodMs, int timeoutMs) {
+		int retval = CANifierJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame.value, periodMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * @param statusFrame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(int statusFrame, int periodMs, int timeoutMs) {
+		int retval = CANifierJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame, periodMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Period of the given status frame.
+	 */
+	public int getStatusFramePeriod(CANifierStatusFrame frame, int timeoutMs) {
+		return CANifierJNI.JNI_GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
+	}
+
+	/**
+	 * Sets the period of the given control frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setControlFramePeriod(CANifierControlFrame frame, int periodMs) {
+		int retval = CANifierJNI.JNI_SetControlFramePeriod(m_handle, frame.value, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the period of the given control frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setControlFramePeriod(int frame, int periodMs) {
+		int retval = CANifierJNI.JNI_SetControlFramePeriod(m_handle, frame, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the firmware version of the device.
+	 *
+	 * @return Firmware version of device.
+	 */
+	public int getFirmwareVersion() {
+		return CANifierJNI.JNI_GetFirmwareVersion(m_handle);
+	}
+
+	/**
+	 * Returns true if the device has reset since last call.
+	 *
+	 * @return Has a Device Reset Occurred?
+	 */
+	public boolean hasResetOccurred() {
+		return CANifierJNI.JNI_HasResetOccurred(m_handle);
+	}
+
+	// ------ Faults ----------//
+	/**
+	 * Gets the CANifier fault status
+	 *
+	 * @param toFill
+	 *            Container for fault statuses.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode getFaults(CANifierFaults toFill) {
+		int bits = CANifierJNI.JNI_GetFaults(m_handle);
+		toFill.update(bits);
+		return getLastError();
+	}
+	/**
+	 * Gets the CANifier sticky fault status
+	 *
+	 * @param toFill
+	 *            Container for sticky fault statuses.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode getStickyFaults(CANifierStickyFaults toFill) {
+		int bits = CANifierJNI.JNI_GetStickyFaults(m_handle);
+		toFill.update(bits);
+		return getLastError();
+	}
+	/**
+	 * Clears the Sticky Faults
+	 *
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode clearStickyFaults(int timeoutMs) {
+		int retval = CANifierJNI.JNI_ClearStickyFaults(m_handle, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the bus voltage seen by the device.
+	 *
+	 * @return The bus voltage value (in volts).
+	 */
+	public double getBusVoltage() {
+		return CANifierJNI.JNI_GetBusVoltage(m_handle);
+	}
+
+	/**
+	 * @return The Device Number
+	 */
+	public int getDeviceID(){
+		return m_deviceNumber;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/CANifierControlFrame.java b/java/src/com/ctre/phoenix/CANifierControlFrame.java
new file mode 100644
index 0000000..c7ce0f0
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CANifierControlFrame.java
@@ -0,0 +1,21 @@
+package com.ctre.phoenix;
+
+public enum CANifierControlFrame {
+	Control_1_General(0x040000), 
+	Control_2_PwmOutput(0x040040);
+
+	public static CANifierControlFrame valueOf(int value) {
+		for (CANifierControlFrame frame : values()) {
+			if (frame.value == value) {
+				return frame;
+			}
+		}
+		return null;
+	}
+
+	public final int value;
+
+	CANifierControlFrame(int initValue) {
+		this.value = initValue;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/CANifierFaults.java b/java/src/com/ctre/phoenix/CANifierFaults.java
new file mode 100644
index 0000000..99a47b9
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CANifierFaults.java
@@ -0,0 +1,16 @@
+package com.ctre.phoenix;
+
+public class CANifierFaults {
+	//!< True iff any of the above flags are true.
+	public boolean hasAnyFault() {
+		return false;
+	}
+	public int toBitfield() {
+		int retval = 0;
+		return retval;
+	}
+	public void update(int bits) {
+	}
+	public CANifierFaults() {
+	}
+};
diff --git a/java/src/com/ctre/phoenix/CANifierJNI.java b/java/src/com/ctre/phoenix/CANifierJNI.java
new file mode 100644
index 0000000..086397d
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CANifierJNI.java
@@ -0,0 +1,107 @@
+/*
+ *  Software License Agreement
+ *
+ * Copyright (C) Cross The Road Electronics.  All rights
+ * reserved.
+ * 
+ * Cross The Road Electronics (CTRE) licenses to you the right to 
+ * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and Software
+ * API Libraries ONLY when in use with Cross The Road Electronics hardware products.
+ * 
+ * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
+ * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL, 
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
+ * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
+ * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
+ * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
+ * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE
+ */
+ package com.ctre.phoenix;
+ 
+ public class CANifierJNI extends CTREJNIWrapper {
+	 
+	public enum GeneralPin
+	{
+		QUAD_IDX(0),
+		QUAD_B (1),
+		QUAD_A (2),
+		LIMR (3),
+		LIMF (4),
+		SDA (5),
+		SCL (6),
+		SPI_CS (7),
+		SPI_MISO_PWM2P (8),
+		SPI_MOSI_PWM1P (9),
+		SPI_CLK_PWM0P (10);
+		
+		final public int value;
+
+		GeneralPin(int value) {
+			this.value = value;
+		}
+	}
+	
+	public static native long JNI_new_CANifier(int deviceNumber);
+
+	public static native void JNI_SetLEDOutput(long handle, int dutyCycle, int ledChannel);
+
+	public static native void JNI_SetGeneralOutputs(long handle, int outputBits, int isOutputBits);
+
+	public static native void JNI_SetGeneralOutput(long handle, int outputPin, boolean outputValue,
+			boolean outputEnable);
+
+	public static native void JNI_SetPWMOutput(long handle, int pwmChannel, int dutyCycle);
+
+	public static native void JNI_EnablePWMOutput(long handle, int pwmChannel, boolean bEnable);
+
+	public static native void JNI_GetGeneralInputs(long handle, boolean[] allPins);
+
+	public static native boolean JNI_GetGeneralInput(long handl, int inputPin);
+
+	public static native void JNI_GetPWMInput(long handle, int pwmChannel, double dutyCycleAndPeriod[]);
+
+	public static native int JNI_GetLastError(long handle);
+
+	public static native double JNI_GetBatteryVoltage(long handle);
+	
+	public static native int JNI_GetQuadraturePosition(long handle);
+	
+	public static native int JNI_SetQuadraturePosition(long handle, int newPosition, int timeoutMs);
+	
+	public static native int JNI_GetQuadratureVelocity(long handle);
+	
+	public static native int JNI_ConfigVelocityMeasurementPeriod(long handle, int period, int timeoutMs);
+	
+	public static native int JNI_ConfigVelocityMeasurementWindow(long handle, int windowSize, int timeoutMs);
+
+	public static native int JNI_ConfigSetCustomParam(long handle, int newValue, int paramIndex, int timeoutMs);
+
+	public static native int JNI_ConfigGetCustomParam(long handle, int paramIndex, int timoutMs);
+
+	public static native int JNI_ConfigSetParameter(long handle, int param, double value, int subValue, int ordinal,
+			int timeoutMs);
+
+	public static native double JNI_ConfigGetParameter(long handle, int param, int ordinal, int timeoutMs);
+
+	public static native int JNI_SetStatusFramePeriod(long handle, int statusFrame, int periodMs, int timeoutMs);
+
+	public static native int JNI_GetStatusFramePeriod(long handle, int frame, int timeoutMs);
+
+	public static native int JNI_SetControlFramePeriod(long handle, int frame, int periodMs);
+
+	public static native int JNI_GetFirmwareVersion(long handle);
+
+	public static native boolean JNI_HasResetOccurred(long handle);
+
+	public static native int JNI_GetFaults(long handle);
+
+	public static native int JNI_GetStickyFaults(long handle);
+
+	public static native int JNI_ClearStickyFaults(long handle, int timeoutMs);
+
+	public static native double JNI_GetBusVoltage(long handle);
+ }
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/CANifierStatusFrame.java b/java/src/com/ctre/phoenix/CANifierStatusFrame.java
new file mode 100644
index 0000000..904b9be
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CANifierStatusFrame.java
@@ -0,0 +1,26 @@
+package com.ctre.phoenix;
+
+public enum CANifierStatusFrame {
+	Status_1_General(0x041400), 
+	Status_2_General(0x041440), 
+	Status_3_PwmInputs0(0x041480), 
+	Status_4_PwmInputs1(0x0414C0), 
+	Status_5_PwmInputs2(0x041500), 
+	Status_6_PwmInputs3(0x041540), 
+	Status_8_Misc(0x0415C0);
+
+	public static CANifierStatusFrame valueOf(int value) {
+		for (CANifierStatusFrame frame : values()) {
+			if (frame.value == value) {
+				return frame;
+			}
+		}
+		return null;
+	}
+
+	public final int value;
+
+	CANifierStatusFrame(int initValue) {
+		this.value = initValue;
+	}
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/CANifierStickyFaults.java b/java/src/com/ctre/phoenix/CANifierStickyFaults.java
new file mode 100644
index 0000000..2cb8dac
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CANifierStickyFaults.java
@@ -0,0 +1,16 @@
+package com.ctre.phoenix;
+
+public class CANifierStickyFaults {
+	//!< True iff any of the above flags are true.
+	public boolean hasAnyFault() {
+		return false;
+	}
+	public int toBitfield() {
+		int retval = 0;
+		return retval;
+	}
+	public void update(int bits) {
+	}
+	public CANifierStickyFaults() {
+	}
+};
diff --git a/java/src/com/ctre/phoenix/CTREJNIWrapper.java b/java/src/com/ctre/phoenix/CTREJNIWrapper.java
new file mode 100644
index 0000000..8556ea5
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CTREJNIWrapper.java
@@ -0,0 +1,21 @@
+package com.ctre.phoenix;
+
+public class CTREJNIWrapper {
+  static boolean libraryLoaded = false;
+  
+  static {
+    if (!libraryLoaded) {
+      try {
+        System.loadLibrary("CTRE_PhoenixCCI");
+      } catch (UnsatisfiedLinkError e) {
+        e.printStackTrace();
+        System.exit(1);
+      }
+      libraryLoaded = true;
+    }
+  }
+
+  public static native int getPortWithModule(byte module, byte channel);
+
+  public static native int getPort(byte channel);
+}
diff --git a/java/src/com/ctre/phoenix/CTRLoggerJNI.java b/java/src/com/ctre/phoenix/CTRLoggerJNI.java
new file mode 100644
index 0000000..059494a
--- /dev/null
+++ b/java/src/com/ctre/phoenix/CTRLoggerJNI.java
@@ -0,0 +1,12 @@
+package com.ctre.phoenix;
+
+import com.ctre.phoenix.CTREJNIWrapper;
+
+/* package */ class CTRLoggerJNI extends CTREJNIWrapper {
+	/* package */ static native int JNI_Logger_Log(int code, String origin, String stackTrace);
+
+	// public static native void JNI_Logger_Close();
+	// public static native void JNI_Logger_Open(int language);
+	// public static native String JNI_Logger_GetShort(int code);
+	// public static native String JNI_Logger_GetLong(int code);
+}
diff --git a/java/src/com/ctre/phoenix/ErrorCode.java b/java/src/com/ctre/phoenix/ErrorCode.java
new file mode 100644
index 0000000..97a47c2
--- /dev/null
+++ b/java/src/com/ctre/phoenix/ErrorCode.java
@@ -0,0 +1,123 @@
+package com.ctre.phoenix;
+
+import java.util.HashMap;
+
+public enum ErrorCode {
+	OK(0), 						//!< No Error - Function executed as expected
+
+	//CAN-Related
+	CAN_MSG_STALE(1),
+	CAN_TX_FULL(-1),
+	TxFailed(-1),				//!< Could not transmit the CAN frame.
+	InvalidParamValue(-2), 	//!< Caller passed an invalid param
+	CAN_INVALID_PARAM(-2),
+	RxTimeout(-3),				//!< CAN frame has not been received within specified period of time.
+	CAN_MSG_NOT_FOUND(-3),
+	TxTimeout(-4),				//!< Not used.
+	CAN_NO_MORE_TX_JOBS(-4),
+	UnexpectedArbId(-5),		//!< Specified CAN Id is invalid.
+	CAN_NO_SESSIONS_AVAIL(-5),
+	BufferFull(+6),			//!< Caller attempted to insert data into a buffer that is full.
+	CAN_OVERFLOW(-6),
+	SensorNotPresent(-7),		//!< Sensor is not present
+	FirmwareTooOld (-8),
+
+
+	//General
+	GeneralError(-100),		//!< User Specified General Error
+	GENERAL_ERROR(-100),
+
+	//Signal
+	SIG_NOT_UPDATED(-200),
+	SigNotUpdated(-200),			//!< Have not received an value response for signal.
+	NotAllPIDValuesUpdated(-201),
+
+	//Gadgeteer Port Error Codes
+	//These include errors between ports and modules
+	GEN_PORT_ERROR(-300),
+	PORT_MODULE_TYPE_MISMATCH(-301),
+	//Gadgeteer Module Error Codes
+	//These apply only to the module units themselves
+	GEN_MODULE_ERROR(-400),
+	MODULE_NOT_INIT_SET_ERROR(-401),
+	MODULE_NOT_INIT_GET_ERROR(-402),
+
+
+	//API
+	WheelRadiusTooSmall(-500),
+	TicksPerRevZero(-501),
+	DistanceBetweenWheelsTooSmall(-502),
+	GainsAreNotSet(-503),
+
+	//Higher Level
+	IncompatibleMode(-600),
+	InvalidHandle(-601),		//!< Handle does not match stored map of handles
+
+
+	//CAN Related
+	PulseWidthSensorNotPresent (10),	//!< Special Code for "isSensorPresent"
+
+	//General
+	GeneralWarning(100),
+	FeatureNotSupported(101),
+	NotImplemented(102),
+	FirmVersionCouldNotBeRetrieved (103),
+	FeaturesNotAvailableYet(104),
+	ControlModeNotValid(105),
+
+	ControlModeNotSupportedYet(106),
+	CascadedPIDNotSupportedYet(107),
+	AuxiliaryPIDNotSupportedYet(107),
+	RemoteSensorsNotSupportedYet(108),
+	MotProfFirmThreshold(109),
+	MotProfFirmThreshold2(110);
+
+	//---------------------- Integral To Enum operators -----------//
+    public final int value; //!< Hold the integral value of an enum instance.
+    /** Keep singleton map to quickly lookup enum via int */
+    private static HashMap<Integer, ErrorCode> _map = null;
+    /** private c'tor for above declarations */
+	private ErrorCode(int initValue) {this.value = initValue;	}
+	/** static c'tor, prepare the map */
+    static {
+    	_map = new HashMap<Integer, ErrorCode>();
+		for (ErrorCode type : ErrorCode.values()) {
+			_map.put(type.value, type);
+		}
+    }
+    /** public lookup to convert int to enum */
+	public static ErrorCode valueOf(int value) {
+		ErrorCode retval = _map.get(value);
+		if (retval != null)
+			return retval;
+		return GeneralError;
+	}
+
+	/** @return the first nonzero error code */
+	public static ErrorCode worstOne(ErrorCode errorCode1, ErrorCode errorCode2) {
+		if (errorCode1.value != 0)
+			return errorCode1;
+		return errorCode2;
+	}
+
+	/** @return the first nonzero error code */
+	public static ErrorCode worstOne(ErrorCode errorCode1, ErrorCode errorCode2, ErrorCode errorCode3) {
+		if (errorCode1.value != 0)
+			return errorCode1;
+		if (errorCode2.value != 0)
+			return errorCode2;
+		return errorCode3;
+	}
+
+	/** @return the first nonzero error code */
+	public static ErrorCode worstOne(ErrorCode errorCode1, ErrorCode errorCode2, ErrorCode errorCode3,
+			ErrorCode errorCode4) {
+		if (errorCode1.value != 0)
+			return errorCode1;
+		if (errorCode2.value != 0)
+			return errorCode2;
+		if (errorCode3.value != 0)
+			return errorCode3;
+		return errorCode4;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/GadgeteerUartClient.java b/java/src/com/ctre/phoenix/GadgeteerUartClient.java
new file mode 100644
index 0000000..b40dad9
--- /dev/null
+++ b/java/src/com/ctre/phoenix/GadgeteerUartClient.java
@@ -0,0 +1,71 @@
+package com.ctre.phoenix;
+
+public interface GadgeteerUartClient
+{
+	public enum GadgeteerProxyType{
+		General(0), 
+		Pigeon(1), 
+		PC_HERO(2),
+		Unknown(-1);
+		private int value; private GadgeteerProxyType(int value) { this.value = value; } 
+		public static GadgeteerProxyType valueOf(int value) {
+			for (GadgeteerProxyType e : GadgeteerProxyType.values()) {
+				if (e.value == value) {
+					return e;
+				}
+			}
+			return Unknown;
+		}
+	};
+
+	public enum GadgeteerConnection	{
+		NotConnected (0),
+		Connecting (1),
+		Connected (2),
+		Unknown(-1);
+		private int value; private GadgeteerConnection(int value) { this.value = value; } 
+		public static GadgeteerConnection valueOf(int value) {
+			for (GadgeteerConnection e : GadgeteerConnection.values()) {
+				if (e.value == value) {
+					return e;
+				}
+			}
+			return Unknown;
+		}
+	};
+
+	public static class GadgeteerUartStatus {
+		public GadgeteerProxyType type;
+		public GadgeteerConnection conn;
+		public int bitrate;
+		public int resetCount;
+	};
+
+
+	enum GadgeteerState
+	{
+		GadState_WaitChirp1(0),
+		GadState_WaitBLInfo(1),
+		GadState_WaitBitrateResp(2),
+		GadState_WaitSwitchDelay(3),
+		GadState_WaitChirp2(4),
+		GadState_Connected_Idle(5),
+		GadState_Connected_ReqChirp(6),
+		GadState_Connected_RespChirp(7),
+		GadState_Connected_ReqCanBus(8),
+		GadState_Connected_RespCanBus(9),
+		GadState_Connected_RespIsoThenChirp(10),
+		GadState_Connected_RespIsoThenCanBus(11);
+		private int value; private GadgeteerState(int value) { this.value = value; } 
+		public static GadgeteerState valueOf(int value) {
+			for (GadgeteerState e : GadgeteerState.values()) {
+				if (e.value == value) {
+					return e;
+				}
+			}
+			return GadState_WaitChirp1;
+		}
+	};
+    int getGadgeteerStatus(GadgeteerUartStatus status);
+};
+
diff --git a/java/src/com/ctre/phoenix/ILoopable.java b/java/src/com/ctre/phoenix/ILoopable.java
new file mode 100644
index 0000000..1e52471
--- /dev/null
+++ b/java/src/com/ctre/phoenix/ILoopable.java
@@ -0,0 +1,9 @@
+package com.ctre.phoenix;
+
+public interface ILoopable
+{
+	public void onStart();
+	public void onLoop();
+	public boolean isDone();
+	public void onStop();
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/Logger.java b/java/src/com/ctre/phoenix/Logger.java
new file mode 100644
index 0000000..c1caaca
--- /dev/null
+++ b/java/src/com/ctre/phoenix/Logger.java
@@ -0,0 +1,38 @@
+package com.ctre.phoenix;
+
+public class Logger
+{
+	/**
+	 * Logs an entry into the Phoenix DS Error/Logger stream
+	 * @param code Error code to log.  If OKAY is passed, no action is taken.
+	 * @param origin Origin string to send to DS/Log
+	 * @return OKAY error code.
+	 */
+	public static ErrorCode log(ErrorCode code, String origin) {
+		/* only take action if the error code is nonzero */
+		if (code != ErrorCode.OK) {
+			String stack = java.util.Arrays.toString(Thread.currentThread().getStackTrace());
+			stack = stack.replaceAll(",", "\n");
+			int errCode = code.value;
+			return ErrorCode.valueOf(CTRLoggerJNI.JNI_Logger_Log(errCode, origin, stack));
+		}
+		/* otherwise return OK */
+		return ErrorCode.OK;
+	}
+
+	//public static void close() {
+	//	//CTRLoggerJNI.JNI_Logger_Close();
+	//}
+	//public static void open() {
+	//	//CTRLoggerJNI.JNI_Logger_Open(2);
+	//}
+	/*
+	public static String getVerbose(int code) {
+		return CTRLoggerJNI.JNI_Logger_GetLong(code);
+	}
+	public static String getShort(int code) {
+		return CTRLoggerJNI.JNI_Logger_GetShort(code);
+	}
+	*/
+}
+
diff --git a/java/src/com/ctre/phoenix/ParamEnum.java b/java/src/com/ctre/phoenix/ParamEnum.java
new file mode 100644
index 0000000..f6b3706
--- /dev/null
+++ b/java/src/com/ctre/phoenix/ParamEnum.java
@@ -0,0 +1,109 @@
+package com.ctre.phoenix;
+
+public enum ParamEnum
+	{
+	eOnBoot_BrakeMode ( 31),
+	eQuadFilterEn ( 91),
+	eQuadIdxPolarity(108),
+	eClearPositionOnIdx (100),
+    eMotionProfileHasUnderrunErr (119),
+	eClearPosOnLimitF (144),
+	eClearPosOnLimitR (145),
+
+	eStatusFramePeriod(300),
+	eOpenloopRamp(301),
+	eClosedloopRamp(302),
+	eNeutralDeadband(303),
+
+	ePeakPosOutput(305),
+	eNominalPosOutput(306),
+	ePeakNegOutput(307),
+	eNominalNegOutput(308),
+
+	eProfileParamSlot_P(310),
+	eProfileParamSlot_I(311),
+	eProfileParamSlot_D(312),
+	eProfileParamSlot_F(313),
+	eProfileParamSlot_IZone(314),
+	eProfileParamSlot_AllowableErr(315),
+	eProfileParamSlot_MaxIAccum(316),
+	eProfileParamSlot_PeakOutput(317),
+
+	eClearPositionOnLimitF(320),
+	eClearPositionOnLimitR(321),
+	eClearPositionOnQuadIdx(322),
+
+	eSampleVelocityPeriod(325),
+	eSampleVelocityWindow(326),
+
+	eFeedbackSensorType(330),
+    eSelectedSensorPosition(331),
+	eFeedbackNotContinuous (332),
+	eRemoteSensorSource (333), // RemoteSensorSource_t
+	eRemoteSensorDeviceID (334), // [0,62] DeviceID
+	eSensorTerm (335), // feedbackDevice_t (ordinal is the register)
+	eRemoteSensorClosedLoopDisableNeutralOnLOS (336),
+	ePIDLoopPolarity(337),
+	ePIDLoopPeriod(338),
+	eSelectedSensorCoefficient(339),
+
+	eForwardSoftLimitThreshold(340),
+	eReverseSoftLimitThreshold(341),
+	eForwardSoftLimitEnable(342),
+	eReverseSoftLimitEnable(343),
+
+	eNominalBatteryVoltage(350),
+	eBatteryVoltageFilterSize(351),
+
+	eContinuousCurrentLimitAmps(360),
+	ePeakCurrentLimitMs(361),
+	ePeakCurrentLimitAmps(362),
+
+	eClosedLoopIAccum(370),
+
+	eCustomParam(380),
+
+	eStickyFaults(390),
+
+	eAnalogPosition(400),
+	eQuadraturePosition(401),
+	ePulseWidthPosition(402),
+
+	eMotMag_Accel(410),
+	eMotMag_VelCruise(411),
+
+	eLimitSwitchSource (421), // ordinal (fwd=0,reverse=1), @see LimitSwitchSource_t
+	eLimitSwitchNormClosedAndDis ( 422), // ordinal (fwd=0,reverse=1). @see LimitSwitchNormClosedAndDis_t
+	eLimitSwitchDisableNeutralOnLOS ( 423),
+	eLimitSwitchRemoteDevID ( 424),
+	eSoftLimitDisableNeutralOnLOS(425),
+
+	ePulseWidthPeriod_EdgesPerRot(430),
+	ePulseWidthPeriod_FilterWindowSz(431),
+
+	eYawOffset(160),
+	eCompassOffset(161),
+	eBetaGain(162),
+	eEnableCompassFusion(163),
+	eGyroNoMotionCal (	164),
+	eEnterCalibration (	165),
+	eFusedHeadingOffset	( 166),
+	eStatusFrameRate	( 169),
+	eAccumZ	( 170),
+	eTempCompDisable	( 171),
+	eMotionMeas_tap_threshX ( 172),
+	eMotionMeas_tap_threshY ( 173),
+	eMotionMeas_tap_threshZ ( 174),
+	eMotionMeas_tap_count ( 175),
+	eMotionMeas_tap_time ( 176),
+	eMotionMeas_tap_time_multi ( 177),
+	eMotionMeas_shake_reject_thresh ( 178),
+	eMotionMeas_shake_reject_time ( 179),
+	eMotionMeas_shake_reject_timeout ( 180);
+
+	public final int value;
+	ParamEnum(int initValue)
+	{
+		this.value = initValue;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/Util.java b/java/src/com/ctre/phoenix/Util.java
new file mode 100644
index 0000000..4ccedc7
--- /dev/null
+++ b/java/src/com/ctre/phoenix/Util.java
@@ -0,0 +1,48 @@
+package com.ctre.phoenix;
+
+public class Util
+{
+	public static double cap(double value, double peak)
+	{
+		if(value < -peak) value = -peak;
+		if(value > peak) value = peak;
+		return value;
+	}
+	
+	public static int scaleRotationsToNativeUnits(double scalar, double fullRotations) {
+		/* first assume we don't have config info, prep the default return */
+		int retval = (int) fullRotations;
+		/* apply scalar if its available */
+		if (scalar > 0) {
+		  retval = (int) (fullRotations * scalar);
+		}
+		return retval;
+	}
+	public static int scaleVelocityToNativeUnits(double scalar, double rpm) {
+		/* first assume we don't have config info, prep the default return */
+		int retval = (int) rpm;
+		/* apply scalar if its available */
+		if (scalar > 0) {
+		  retval = (int) (rpm * scalar);
+		}
+		return retval;
+	}
+	public static double scaleNativeUnitsToRotations(double scalar, long nativePos) {
+		/* first assume we don't have config info, prep the default return */
+		double retval = (double) nativePos;
+		/* retrieve scaling info */
+		if (scalar > 0) {
+		  retval = ((double) nativePos) / scalar;
+		}
+		return retval;
+	}
+	public static double scaleNativeUnitsToRpm(double scalar, long nativeVel) {
+		/* first assume we don't have config info, prep the default return */
+		double retval = (double) nativeVel;
+		/* apply scalar if its available */
+		if (scalar > 0) {
+		  retval = (double) (nativeVel) / (scalar);
+		}
+		return retval;
+	}
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motion/MotionProfileStatus.java b/java/src/com/ctre/phoenix/motion/MotionProfileStatus.java
new file mode 100644
index 0000000..5901a75
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motion/MotionProfileStatus.java
@@ -0,0 +1,57 @@
+package com.ctre.phoenix.motion;
+
+/**
+ * Motion Profile Status This is simply a data transer object.
+ */
+public class MotionProfileStatus {
+	/**
+	 * The available empty slots in the trajectory buffer.
+	 *
+	 * The robot API holds a "top buffer" of trajectory points, so your
+	 * applicaion can dump several points at once. The API will then stream them
+	 * into the Talon's low-level buffer, allowing the Talon to act on them.
+	 */
+	public int topBufferRem;
+	/**
+	 * The number of points in the top trajectory buffer.
+	 */
+	public int topBufferCnt;
+	/**
+	 * The number of points in the low level Talon buffer.
+	 */
+	public int btmBufferCnt;
+	/**
+	 * Set if isUnderrun ever gets set. Only is cleared by
+	 * clearMotionProfileHasUnderrun() to ensure robot logic can react or
+	 * instrument it.
+	 *
+	 * @see com.ctre.phoenix.motorcontrol.can.BaseMotorController#clearMotionProfileHasUnderrun(int)
+	 */
+	public boolean hasUnderrun;
+	/**
+	 * This is set if Talon needs to shift a point from its buffer into the
+	 * active trajectory point however the buffer is empty. This gets cleared
+	 * automatically when is resolved.
+	 */
+	public boolean isUnderrun;
+	/**
+	 * True if the active trajectory point has not empty, false otherwise. The
+	 * members in activePoint are only valid if this signal is set.
+	 */
+	public boolean activePointValid;
+
+	public boolean isLast;
+
+	public int profileSlotSelect;
+	/**
+	 * The current output mode of the motion profile executer (disabled,
+	 * enabled, or hold). When changing the set() value in MP mode, it's
+	 * important to check this signal to confirm the change takes effect before
+	 * interacting with the top buffer.
+	 */
+	public SetValueMotionProfile outputEnable;
+	
+	public int timeDurMs;
+	
+	public int profileSlotSelect1;
+}
diff --git a/java/src/com/ctre/phoenix/motion/SetValueMotionProfile.java b/java/src/com/ctre/phoenix/motion/SetValueMotionProfile.java
new file mode 100644
index 0000000..82210c4
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motion/SetValueMotionProfile.java
@@ -0,0 +1,20 @@
+package com.ctre.phoenix.motion;
+
+public enum SetValueMotionProfile {
+	Invalid(-1), Disable(0), Enable(1), Hold(2);
+
+	public final int value;
+
+	SetValueMotionProfile(int initValue) {
+		this.value = initValue;
+	}
+	
+	public static SetValueMotionProfile valueOf(int value) {
+		for (SetValueMotionProfile e : SetValueMotionProfile.values()) {
+			if (e.value == value) {
+				return e;
+			}
+		}
+		return Invalid;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/motion/TrajectoryPoint.java b/java/src/com/ctre/phoenix/motion/TrajectoryPoint.java
new file mode 100644
index 0000000..293038f
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motion/TrajectoryPoint.java
@@ -0,0 +1,85 @@
+package com.ctre.phoenix.motion;
+
+/**
+ * Motion Profile Trajectory Point This is simply a data transfer object.
+ */
+public class TrajectoryPoint {
+	/**
+	 * Duration to apply to a particular trajectory pt.
+	 * This time unit is ADDED to the existing base time set by
+	 * configMotionProfileTrajectoryPeriod().
+	 */
+	public enum TrajectoryDuration
+	{
+		Trajectory_Duration_0ms(0),
+		Trajectory_Duration_5ms(5),
+		Trajectory_Duration_10ms(10),
+		Trajectory_Duration_20ms(20),
+		Trajectory_Duration_30ms(30),
+		Trajectory_Duration_40ms(40),
+		Trajectory_Duration_50ms(50),
+		Trajectory_Duration_100ms(100);
+
+		public int value = 5;
+
+		private TrajectoryDuration(int value)
+		{
+			this.value = value;
+		}
+
+		public TrajectoryDuration valueOf(int val)
+		{
+			for(TrajectoryDuration td: TrajectoryDuration.values())
+			{
+				if(td.value == val) return td;
+			}
+			return Trajectory_Duration_100ms;
+		}
+	}
+
+	public double position; // !< The position to servo to.
+	public double velocity; // !< The velocity to feed-forward.
+	public double headingDeg; // !< Not used.  Use auxiliaryPos instead.  @see auxiliaryPos
+	public double auxiliaryPos; // !< The position for auxiliary PID to target.
+
+	/**
+	 * Which slot to get PIDF gains. PID is used for position servo. F is used
+	 * as the Kv constant for velocity feed-forward. Typically this is hard-coded
+	 * to a particular slot, but you are free to gain schedule if need be.
+	 * Choose from [0,3]
+	 */
+	public int profileSlotSelect0;
+
+	/**
+	 * Which slot to get PIDF gains for auxiliary PId.
+	 * This only has impact during MotionProfileArc Control mode.
+	 * Choose from [0,1].
+	 */
+	public int profileSlotSelect1;
+
+	/**
+	 * Set to true to signal Talon that this is the final point, so do not
+	 * attempt to pop another trajectory point from out of the Talon buffer.
+	 * Instead continue processing this way point. Typically the velocity member
+	 * variable should be zero so that the motor doesn't spin indefinitely.
+	 */
+	public boolean isLastPoint;
+	/**
+	 * Set to true to signal Talon to zero the selected sensor. When generating
+	 * MPs, one simple method is to make the first target position zero, and the
+	 * final target position the target distance from the current position. Then
+	 * when you fire the MP, the current position gets set to zero. If this is
+	 * the intent, you can set zeroPos on the first trajectory point.
+	 *
+	 * Otherwise you can leave this false for all points, and offset the
+	 * positions of all trajectory points so they are correct.
+	 */
+	public boolean zeroPos;
+
+	/**
+	 * Duration to apply this trajectory pt.
+	 * This time unit is ADDED to the existing base time set by
+	 * configMotionProfileTrajectoryPeriod().
+	 */
+	public TrajectoryDuration timeDur;
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/ControlFrame.java b/java/src/com/ctre/phoenix/motorcontrol/ControlFrame.java
new file mode 100644
index 0000000..5b77424
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/ControlFrame.java
@@ -0,0 +1,14 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum ControlFrame
+{
+	Control_3_General(0x040080),
+	Control_4_Advanced(0x0400C0),
+	Control_6_MotProfAddTrajPoint(0x040140);
+	
+	public final int value;
+	ControlFrame(int initValue)
+	{
+		this.value = initValue;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/motorcontrol/ControlFrameEnhanced.java b/java/src/com/ctre/phoenix/motorcontrol/ControlFrameEnhanced.java
new file mode 100644
index 0000000..adc6512
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/ControlFrameEnhanced.java
@@ -0,0 +1,16 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum ControlFrameEnhanced
+{
+	Control_2_Enable_50m(0x040040),
+	Control_3_General(0x040080),
+	Control_4_Advanced(0x0400C0),
+	Control_5_FeedbackOutputOverride(0x040100),
+	Control_6_MotProfAddTrajPoint(0x040140);
+	
+	public final int value;
+	ControlFrameEnhanced(int initValue)
+	{
+		this.value = initValue;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/ControlMode.java b/java/src/com/ctre/phoenix/motorcontrol/ControlMode.java
new file mode 100644
index 0000000..834a8ce
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/ControlMode.java
@@ -0,0 +1,21 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum ControlMode
+{
+	PercentOutput(0),
+	Position(1),
+	Velocity(2),
+	Current(3),
+	Follower(5),
+	MotionProfile(6),
+	MotionMagic(7),
+	MotionProfileArc(10),
+
+	Disabled(15);
+
+	public final int value;
+	ControlMode(int initValue)
+	{
+		this.value = initValue;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/motorcontrol/DemandType.java b/java/src/com/ctre/phoenix/motorcontrol/DemandType.java
new file mode 100644
index 0000000..b0688bb
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/DemandType.java
@@ -0,0 +1,25 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum DemandType {
+  /**
+	 * Ignore the demand value and apply neutral/no-change.
+	 */
+	Neutral(0),
+	/**
+	 * When closed-looping, set the target of the aux PID loop to the demand value.
+	 *
+	 * When following, follow the processed output of the combined
+	 * primary/aux PID output.  The demand value is ignored.
+	 */
+	AuxPID(1), //!< Target value of PID loop 1.  When f
+	/**
+	 * When closed-looping, add this arbitrarily to the closed-loop output.
+	 */
+	ArbitraryFeedForward(2); //!< Simply add to the output
+
+	public int value;
+	DemandType(int value)
+	{
+		this.value = value;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/motorcontrol/Faults.java b/java/src/com/ctre/phoenix/motorcontrol/Faults.java
new file mode 100644
index 0000000..47f5c91
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/Faults.java
@@ -0,0 +1,88 @@
+package com.ctre.phoenix.motorcontrol;
+
+public class Faults {
+	public boolean UnderVoltage;
+	public boolean ForwardLimitSwitch;
+	public boolean ReverseLimitSwitch;
+	public boolean ForwardSoftLimit;
+	public boolean ReverseSoftLimit;
+	public boolean HardwareFailure;
+	public boolean ResetDuringEn;
+	public boolean SensorOverflow;
+	public boolean SensorOutOfPhase;
+	public boolean HardwareESDReset;
+	public boolean RemoteLossOfSignal;
+	//!< True iff any of the above flags are true.
+	public boolean hasAnyFault() {
+		return 	UnderVoltage |
+				ForwardLimitSwitch |
+				ReverseLimitSwitch |
+				ForwardSoftLimit |
+				ReverseSoftLimit |
+				HardwareFailure |
+				ResetDuringEn |
+				SensorOverflow |
+				SensorOutOfPhase |
+				HardwareESDReset |
+				RemoteLossOfSignal;
+	}
+	public int toBitfield() {
+		int retval = 0;
+		int mask = 1;
+		retval |= UnderVoltage ? mask : 0; mask <<= 1;
+		retval |= ForwardLimitSwitch ? mask : 0; mask <<= 1;
+		retval |= ReverseLimitSwitch ? mask : 0; mask <<= 1;
+		retval |= ForwardSoftLimit ? mask : 0; mask <<= 1;
+		retval |= ReverseSoftLimit ? mask : 0; mask <<= 1;
+		retval |= HardwareFailure ? mask : 0; mask <<= 1;
+		retval |= ResetDuringEn ? mask : 0; mask <<= 1;
+		retval |= SensorOverflow ? mask : 0; mask <<= 1;
+		retval |= SensorOutOfPhase ? mask : 0; mask <<= 1;
+		retval |= HardwareESDReset ? mask : 0; mask <<= 1;
+		retval |= RemoteLossOfSignal ? mask : 0; mask <<= 1;
+		return retval;
+	}
+	public void update(int bits) {
+		int mask = 1;
+		UnderVoltage = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ForwardLimitSwitch = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ReverseLimitSwitch = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ForwardSoftLimit = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ReverseSoftLimit = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		HardwareFailure = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ResetDuringEn = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		SensorOverflow = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		SensorOutOfPhase = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		HardwareESDReset = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		RemoteLossOfSignal = ((bits & mask)!=0) ? true : false; mask <<= 1;
+	}
+	public Faults() {
+		UnderVoltage = false;
+		ForwardLimitSwitch = false;
+		ReverseLimitSwitch = false;
+		ForwardSoftLimit = false;
+		ReverseSoftLimit = false;
+		HardwareFailure =false;
+		ResetDuringEn = false;
+		SensorOverflow = false;
+		SensorOutOfPhase = false;
+		HardwareESDReset = false;
+		RemoteLossOfSignal = false;
+	}
+	public String toString() {
+		StringBuilder work = new StringBuilder();
+		work.append(" UnderVoltage:"); work.append(UnderVoltage ? "1" : "0");
+		work.append( " ForwardLimitSwitch:"); work.append(ForwardLimitSwitch ? "1" : "0");
+		work.append( " ReverseLimitSwitch:"); work.append(ReverseLimitSwitch ? "1" : "0");
+		work.append( " ForwardSoftLimit:"); work.append(ForwardSoftLimit ? "1" : "0");
+		work.append( " ReverseSoftLimit:"); work.append(ReverseSoftLimit ? "1" : "0");
+		work.append( " HardwareFailure:"); work.append(HardwareFailure ? "1" : "0");
+		work.append( " ResetDuringEn:"); work.append(ResetDuringEn ? "1" : "0");
+		work.append( " SensorOverflow:"); work.append(SensorOverflow ? "1" : "0");
+		work.append( " SensorOutOfPhase:"); work.append(SensorOutOfPhase ? "1" : "0");
+		work.append( " HardwareESDReset:"); work.append(HardwareESDReset ? "1" : "0");
+		work.append( " RemoteLossOfSignal:"); work.append(RemoteLossOfSignal ? "1" : "0");
+		return work.toString();
+	}
+};
+
diff --git a/java/src/com/ctre/phoenix/motorcontrol/FeedbackDevice.java b/java/src/com/ctre/phoenix/motorcontrol/FeedbackDevice.java
new file mode 100644
index 0000000..56b457d
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/FeedbackDevice.java
@@ -0,0 +1,25 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum FeedbackDevice {
+	None(-1),
+
+	QuadEncoder(0),
+	Analog(2),
+	Tachometer(4),
+	PulseWidthEncodedPosition(8),
+
+	SensorSum(9),
+	SensorDifference(10),
+	RemoteSensor0(11),
+	RemoteSensor1(12),
+	SoftwareEmulatedSensor(15),
+
+	CTRE_MagEncoder_Absolute(8),
+	CTRE_MagEncoder_Relative(0);
+	
+	public final int value;
+	FeedbackDevice(int initValue)
+	{
+		this.value = initValue;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/FollowerType.java b/java/src/com/ctre/phoenix/motorcontrol/FollowerType.java
new file mode 100644
index 0000000..57a0d37
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/FollowerType.java
@@ -0,0 +1,12 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum FollowerType {
+  PercentOutput(0),
+  AuxOutput1(1);
+
+	public int value;
+	FollowerType(int value)
+	{
+		this.value = value;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/motorcontrol/GroupMotorControllers.java b/java/src/com/ctre/phoenix/motorcontrol/GroupMotorControllers.java
new file mode 100644
index 0000000..70bb15a
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/GroupMotorControllers.java
@@ -0,0 +1,23 @@
+package com.ctre.phoenix.motorcontrol;
+
+import java.util.*;
+
+public class GroupMotorControllers
+{
+	static List<IMotorController> _ms = new ArrayList<IMotorController>();
+	
+	public static void register(IMotorController mc)
+	{
+		_ms.add(mc);
+	}
+	
+	public static int getCount()
+	{
+		return _ms.size();
+	}
+	
+	public static IMotorController get(int idx)
+	{
+		return _ms.get(idx);
+	}
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/IFollower.java b/java/src/com/ctre/phoenix/motorcontrol/IFollower.java
new file mode 100644
index 0000000..c31ee04
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/IFollower.java
@@ -0,0 +1,8 @@
+package com.ctre.phoenix.motorcontrol;
+import com.ctre.phoenix.motorcontrol.IMotorController;
+
+public interface IFollower
+{
+	void follow(IMotorController masterToFollow);
+	void valueUpdated();
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/IMotorController.java b/java/src/com/ctre/phoenix/motorcontrol/IMotorController.java
new file mode 100644
index 0000000..8eb6a20
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/IMotorController.java
@@ -0,0 +1,204 @@
+package com.ctre.phoenix.motorcontrol;
+
+import com.ctre.phoenix.ErrorCode;
+import com.ctre.phoenix.ParamEnum;
+import com.ctre.phoenix.motion.MotionProfileStatus;
+import com.ctre.phoenix.motion.TrajectoryPoint;
+
+public interface IMotorController
+		extends com.ctre.phoenix.signals.IOutputSignal, com.ctre.phoenix.signals.IInvertable, IFollower {
+	// ------ Set output routines. ----------//
+	public void set(ControlMode Mode, double demand);
+
+	public void set(ControlMode Mode, double demand0, double demand1);
+
+	public void set(ControlMode Mode, double demand0, DemandType demand1Type, double demand1);
+
+	public void neutralOutput();
+
+	public void setNeutralMode(NeutralMode neutralMode);
+
+	// ------ Invert behavior ----------//
+	public void setSensorPhase(boolean PhaseSensor);
+
+	public void setInverted(boolean invert);
+
+	public boolean getInverted();
+
+	// ----- general output shaping ------------------//
+	public ErrorCode configOpenloopRamp(double secondsFromNeutralToFull, int timeoutMs);
+
+	public ErrorCode configClosedloopRamp(double secondsFromNeutralToFull, int timeoutMs);
+
+	public ErrorCode configPeakOutputForward(double percentOut, int timeoutMs);
+
+	public ErrorCode configPeakOutputReverse(double percentOut, int timeoutMs);
+
+	public ErrorCode configNominalOutputForward(double percentOut, int timeoutMs);
+
+	public ErrorCode configNominalOutputReverse(double percentOut, int timeoutMs);
+
+	public ErrorCode configNeutralDeadband(double percentDeadband, int timeoutMs);
+
+	// ------ Voltage Compensation ----------//
+	public ErrorCode configVoltageCompSaturation(double voltage, int timeoutMs);
+
+	public ErrorCode configVoltageMeasurementFilter(int filterWindowSamples, int timeoutMs);
+
+	public void enableVoltageCompensation(boolean enable);
+
+	// ------ General Status ----------//
+	public double getBusVoltage() ;
+
+	public double getMotorOutputPercent() ;
+
+	public double getMotorOutputVoltage() ;
+
+	public double getOutputCurrent() ;
+
+	public double getTemperature() ;
+
+	// ------ sensor selection ----------//
+	public ErrorCode configSelectedFeedbackSensor(RemoteFeedbackDevice feedbackDevice, int pidIdx, int timeoutMs);
+
+	public ErrorCode configSelectedFeedbackCoefficient(double coefficient, int pidIdx, int timeoutMs);
+
+	public ErrorCode configRemoteFeedbackFilter(int deviceID, RemoteSensorSource remoteSensorSource, int remoteOrdinal,
+			int timeoutMs);
+
+	public ErrorCode configSensorTerm(SensorTerm sensorTerm, FeedbackDevice feedbackDevice, int timeoutMs);
+
+	// ------- sensor status --------- //
+	public int getSelectedSensorPosition(int pidIdx);
+
+	public int getSelectedSensorVelocity(int pidIdx);
+
+	public ErrorCode setSelectedSensorPosition(int sensorPos, int pidIdx, int timeoutMs);
+
+	// ------ status frame period changes ----------//
+	public ErrorCode setControlFramePeriod(ControlFrame frame, int periodMs);
+
+	public ErrorCode setStatusFramePeriod(StatusFrame frame, int periodMs, int timeoutMs);
+
+	public int getStatusFramePeriod(StatusFrame frame, int timeoutMs);
+
+	//----- velocity signal conditionaing ------//
+	/* not supported */
+
+	//------ remote limit switch ----------//
+	public ErrorCode configForwardLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int deviceID, int timeoutMs);
+
+	public ErrorCode configReverseLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int deviceID, int timeoutMs);
+
+	public void overrideLimitSwitchesEnable(boolean enable);
+
+	// ------ local limit switch ----------//
+	/* not supported */
+
+	// ------ soft limit ----------//
+	public ErrorCode configForwardSoftLimitThreshold(int forwardSensorLimit, int timeoutMs);
+
+	public ErrorCode configReverseSoftLimitThreshold(int reverseSensorLimit, int timeoutMs);
+
+	public ErrorCode configForwardSoftLimitEnable(boolean enable, int timeoutMs);
+
+	public ErrorCode configReverseSoftLimitEnable(boolean enable, int timeoutMs);
+
+	public void overrideSoftLimitsEnable(boolean enable);
+
+	// ------ Current Lim ----------//
+	/* not supported */
+
+	// ------ General Close loop ----------//
+	public ErrorCode config_kP(int slotIdx, double value, int timeoutMs);
+
+	public ErrorCode config_kI(int slotIdx, double value, int timeoutMs);
+
+	public ErrorCode config_kD(int slotIdx, double value, int timeoutMs);
+
+	public ErrorCode config_kF(int slotIdx, double value, int timeoutMs);
+
+	public ErrorCode config_IntegralZone(int slotIdx, int izone, int timeoutMs);
+
+	public ErrorCode configAllowableClosedloopError(int slotIdx, int allowableCloseLoopError, int timeoutMs);
+
+	public ErrorCode configMaxIntegralAccumulator(int slotIdx, double iaccum, int timeoutMs);
+
+	public ErrorCode configClosedLoopPeakOutput(int slotIdx, double percentOut, int timeoutMs);
+
+	public ErrorCode configClosedLoopPeriod(int slotIdx, int loopTimeMs, int timeoutMs);
+
+	public ErrorCode configAuxPIDPolarity(boolean invert, int timeoutMs);
+
+	//------ Close loop State ----------//
+	public ErrorCode setIntegralAccumulator(double iaccum, int pidIdx, int timeoutMs);
+
+	public int getClosedLoopError(int pidIdx);
+
+	public double getIntegralAccumulator(int pidIdx) ;
+
+	public double getErrorDerivative(int pidIdx) ;
+
+	public void selectProfileSlot(int slotIdx, int pidIdx);
+
+	public int getClosedLoopTarget(int pidIdx); // will be added to JNI
+
+	public int getActiveTrajectoryPosition();
+
+	public int getActiveTrajectoryVelocity();
+
+	public double getActiveTrajectoryHeading();
+
+	// ------ Motion Profile Settings used in Motion Magic and Motion Profile
+	public ErrorCode configMotionCruiseVelocity(int sensorUnitsPer100ms, int timeoutMs);
+
+	public ErrorCode configMotionAcceleration(int sensorUnitsPer100msPerSec, int timeoutMs);
+	
+	public ErrorCode configMotionProfileTrajectoryPeriod(int baseTrajDurationMs, int timeoutMs);
+
+	// ------ Motion Profile Buffer ----------//
+	public ErrorCode clearMotionProfileTrajectories();
+	public int getMotionProfileTopLevelBufferCount();
+	public ErrorCode pushMotionProfileTrajectory(TrajectoryPoint trajPt);
+	public boolean isMotionProfileTopLevelBufferFull();
+	public void processMotionProfileBuffer();
+	public ErrorCode getMotionProfileStatus(MotionProfileStatus statusToFill);
+	public ErrorCode clearMotionProfileHasUnderrun(int timeoutMs);
+	public ErrorCode changeMotionControlFramePeriod(int periodMs);
+
+	// ------ error ----------//
+	public ErrorCode getLastError();
+
+	// ------ Faults ----------//
+	public ErrorCode getFaults(Faults toFill) ;
+
+	public ErrorCode getStickyFaults(StickyFaults toFill) ;
+
+	public ErrorCode clearStickyFaults(int timeoutMs);
+
+	// ------ Firmware ----------//
+	public int getFirmwareVersion();
+
+	public boolean hasResetOccurred();
+
+	// ------ Custom Persistent Params ----------//
+	public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs);
+
+	public int configGetCustomParam(int paramIndex, int timoutMs);
+
+	//------ Generic Param API, typically not used ----------//
+	public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs);
+	public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs);
+
+	public double configGetParameter(ParamEnum paramEnum, int ordinal, int timeoutMs) ;
+	public double configGetParameter(int paramEnum, int ordinal, int timeoutMs) ;
+
+	//------ Misc. ----------//
+	public int getBaseID();
+	public int getDeviceID();
+	public ControlMode getControlMode();
+	// ----- Follower ------//
+	/* in parent interface */
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/IMotorControllerEnhanced.java b/java/src/com/ctre/phoenix/motorcontrol/IMotorControllerEnhanced.java
new file mode 100644
index 0000000..5f93c2d
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/IMotorControllerEnhanced.java
@@ -0,0 +1,86 @@
+package com.ctre.phoenix.motorcontrol;
+
+import com.ctre.phoenix.ErrorCode;
+
+public interface IMotorControllerEnhanced extends IMotorController {
+	 //------ Set output routines. ----------//
+    /* in parent */
+
+    //------ Invert behavior ----------//
+    /* in parent */
+
+    //----- general output shaping ------------------//
+    /* in parent */
+
+    //------ Voltage Compensation ----------//
+    /* in parent */
+
+    //------ General Status ----------//
+    /* in parent */
+
+    //------ sensor selection ----------//
+    /* expand the options */
+	 public ErrorCode configSelectedFeedbackSensor(FeedbackDevice feedbackDevice, int pidIdx, int timeoutMs );
+
+    //------- sensor status --------- //
+    /* in parent */
+
+    //------ status frame period changes ----------//
+    public ErrorCode setStatusFramePeriod(StatusFrameEnhanced frame, int periodMs, int timeoutMs );
+    public int getStatusFramePeriod(StatusFrameEnhanced frame, int timeoutMs );
+
+    //----- velocity signal conditionaing ------//
+    public ErrorCode configVelocityMeasurementPeriod(VelocityMeasPeriod period, int timeoutMs );
+    public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs );
+
+    //------ remote limit switch ----------//
+    /* in parent */
+
+    //------ local limit switch ----------//
+    public ErrorCode configForwardLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose, int timeoutMs );
+    public ErrorCode configReverseLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose, int timeoutMs );
+
+    //------ soft limit ----------//
+    /* in parent */
+
+    //------ Current Lim ----------//
+    public ErrorCode configPeakCurrentLimit(int amps, int timeoutMs );
+    public ErrorCode configPeakCurrentDuration(int milliseconds, int timeoutMs );
+    public ErrorCode configContinuousCurrentLimit(int amps, int timeoutMs );
+    public void enableCurrentLimit(boolean enable);
+
+    //------ General Close loop ----------//
+    /* in parent */
+
+    //------ Motion Profile Settings used in Motion Magic and Motion Profile ----------//
+    /* in parent */
+
+    //------ Motion Profile Buffer ----------//
+    /* in parent */
+
+    //------ error ----------//
+    /* in parent */
+
+    //------ Faults ----------//
+    /* in parent */
+
+    //------ Firmware ----------//
+    /* in parent */
+
+    //------ Custom Persistent Params ----------//
+    /* in parent */
+
+    //------ Generic Param API, typically not used ----------//
+    /* in parent */
+
+    //------ Misc. ----------//
+    /* in parent */
+
+    //------ RAW Sensor API ----------//
+    /**
+     * @retrieve object that can get/set individual RAW sensor values.
+     */
+    //SensorCollection SensorCollection { get; }
+    
+    
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/LimitSwitchNormal.java b/java/src/com/ctre/phoenix/motorcontrol/LimitSwitchNormal.java
new file mode 100644
index 0000000..139de84
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/LimitSwitchNormal.java
@@ -0,0 +1,11 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum LimitSwitchNormal {
+	NormallyOpen(0), NormallyClosed(1), Disabled(2);
+
+	public int value;
+
+	LimitSwitchNormal(int value) {
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/LimitSwitchSource.java b/java/src/com/ctre/phoenix/motorcontrol/LimitSwitchSource.java
new file mode 100644
index 0000000..5118402
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/LimitSwitchSource.java
@@ -0,0 +1,11 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum LimitSwitchSource {
+	FeedbackConnector(0), RemoteTalonSRX(1), RemoteCANifier(2), Deactivated(3);
+
+	public int value;
+
+	LimitSwitchSource(int value) {
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/NeutralMode.java b/java/src/com/ctre/phoenix/motorcontrol/NeutralMode.java
new file mode 100644
index 0000000..e2f56c2
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/NeutralMode.java
@@ -0,0 +1,17 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum NeutralMode {
+	/** Use the NeutralMode that is set by the jumper wire on the CAN device */
+	EEPROMSetting(0),
+	/** Do not attempt to stop the motor. Instead allow it to coast to a stop
+	 without applying resistance. */
+	Coast(1),
+	/** Stop the motor's rotation by applying a force. */
+	Brake(2);
+	
+	public int value;
+	NeutralMode(int value)
+	{
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/RemoteFeedbackDevice.java b/java/src/com/ctre/phoenix/motorcontrol/RemoteFeedbackDevice.java
new file mode 100644
index 0000000..e2c54aa
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/RemoteFeedbackDevice.java
@@ -0,0 +1,17 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum RemoteFeedbackDevice {
+	None(-1),
+
+	SensorSum(9),
+	SensorDifference(10),
+	RemoteSensor0(11),
+	RemoteSensor1(12),
+	SoftwareEmulatedSensor(15);
+	
+	public final int value;
+	RemoteFeedbackDevice(int initValue)
+	{
+		this.value = initValue;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/RemoteLimitSwitchSource.java b/java/src/com/ctre/phoenix/motorcontrol/RemoteLimitSwitchSource.java
new file mode 100644
index 0000000..f634561
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/RemoteLimitSwitchSource.java
@@ -0,0 +1,11 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum RemoteLimitSwitchSource {
+	RemoteTalonSRX(1), RemoteCANifier(2), Deactivated(3);
+
+	public int value;
+
+	RemoteLimitSwitchSource(int value) {
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/RemoteSensorSource.java b/java/src/com/ctre/phoenix/motorcontrol/RemoteSensorSource.java
new file mode 100644
index 0000000..dfdd4a8
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/RemoteSensorSource.java
@@ -0,0 +1,23 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum RemoteSensorSource {
+	Off(0),
+	TalonSRX_SelectedSensor(1),
+	Pigeon_Yaw(2),
+	Pigeon_Pitch(3),
+	Pigeon_Roll(4),
+	CANifier_Quadrature(5),
+	CANifier_PWMInput0(6),
+	CANifier_PWMInput1(7),
+	CANifier_PWMInput2(8),
+	CANifier_PWMInput3(9),
+	GadgeteerPigeon_Yaw(10),
+	GadgeteerPigeon_Pitch(11),
+	GadgeteerPigeon_Roll(12);
+
+	public int value;
+	RemoteSensorSource(int value)
+	{
+		this.value = value;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/motorcontrol/SensorCollection.java b/java/src/com/ctre/phoenix/motorcontrol/SensorCollection.java
new file mode 100644
index 0000000..7045229
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/SensorCollection.java
@@ -0,0 +1,218 @@
+package com.ctre.phoenix.motorcontrol;
+
+import com.ctre.phoenix.ErrorCode;
+import com.ctre.phoenix.motorcontrol.can.BaseMotorController;
+import com.ctre.phoenix.motorcontrol.can.MotControllerJNI;
+
+public class SensorCollection {
+
+	private long _handle;
+
+	public SensorCollection(BaseMotorController motorController) {
+		_handle = motorController.getHandle();
+
+	}
+
+	/**
+	 * Get the position of whatever is in the analog pin of the Talon, regardless of
+	 *   whether it is actually being used for feedback.
+	 *
+	 * @return  the 24bit analog value.  The bottom ten bits is the ADC (0 - 1023)
+	 *          on the analog pin of the Talon. The upper 14 bits tracks the overflows and underflows
+	 *          (continuous sensor).
+	 */
+
+	public int getAnalogIn() {
+		return MotControllerJNI.GetAnalogIn(_handle);
+	}
+
+	/**
+	 * Sets analog position.
+	 *
+	 * @param   newPosition The new position.
+	 * @param   timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 *
+	 * @return  an ErrorCode.
+	 */
+
+	public ErrorCode setAnalogPosition(int newPosition, int timeoutMs) {
+		int retval = MotControllerJNI.SetAnalogPosition(_handle, newPosition, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Get the position of whatever is in the analog pin of the Talon, regardless of whether
+	 *   it is actually being used for feedback.
+	 *
+	 * @return  the ADC (0 - 1023) on analog pin of the Talon.
+	 */
+
+	public int getAnalogInRaw() {
+		return MotControllerJNI.GetAnalogInRaw(_handle);
+	}
+
+	/**
+	 * Get the velocity of whatever is in the analog pin of the Talon, regardless of
+	 *   whether it is actually being used for feedback.
+	 *
+	 * @return  the speed in units per 100ms where 1024 units is one rotation.
+	 */
+
+	public int getAnalogInVel() {
+		return MotControllerJNI.GetAnalogInVel(_handle);
+	}
+
+	/**
+	 * Get the quadrature position of the Talon, regardless of whether
+	 *   it is actually being used for feedback.
+	 *
+	 * @return  the quadrature position.
+	 */
+
+	public int getQuadraturePosition() {
+		return MotControllerJNI.GetQuadraturePosition(_handle);
+	}
+
+	/**
+	 * Change the quadrature reported position.  Typically this is used to "zero" the
+	 *   sensor. This only works with Quadrature sensor.  To set the selected sensor position
+	 *   regardless of what type it is, see SetSelectedSensorPosition in the motor controller class.
+	 *
+	 * @param   newPosition The position value to apply to the sensor.
+	 * @param   timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 *
+	 * @return  error code.
+	 */
+
+	public ErrorCode setQuadraturePosition(int newPosition, int timeoutMs) {
+		int retval = MotControllerJNI.SetQuadraturePosition(_handle, newPosition, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Get the quadrature velocity, regardless of whether
+	 *   it is actually being used for feedback.
+	 *
+	 * @return  the quadrature velocity in units per 100ms.
+	 */
+
+	public int getQuadratureVelocity() {
+		return MotControllerJNI.GetQuadratureVelocity(_handle);
+	}
+
+	/**
+	 * Gets pulse width position, regardless of whether
+	 *   it is actually being used for feedback.
+	 *
+	 * @return  the pulse width position.
+	 */
+
+	public int getPulseWidthPosition() {
+		return MotControllerJNI.GetPulseWidthPosition(_handle);
+	}
+
+	/**
+	 * Sets pulse width position.
+	 *
+	 * @param   newPosition The position value to apply to the sensor.
+	 * @param   timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 *
+	 * @return  an ErrErrorCode
+	 */
+	public ErrorCode setPulseWidthPosition(int newPosition, int timeoutMs) {
+		int retval = MotControllerJNI.SetPulseWidthPosition(_handle, newPosition, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets pulse width velocity, regardless of whether
+	 *   it is actually being used for feedback.
+	 *
+	 * @return  the pulse width velocity in units per 100ms (where 4096 units is 1 rotation).
+	 */
+
+	public int getPulseWidthVelocity() {
+		return MotControllerJNI.GetPulseWidthVelocity(_handle);
+	}
+
+	/**
+	 * Gets pulse width rise to fall time.
+	 *
+	 * @return  the pulse width rise to fall time in microseconds.
+	 */
+
+	public int getPulseWidthRiseToFallUs() {
+		return MotControllerJNI.GetPulseWidthRiseToFallUs(_handle);
+	}
+
+	/**
+	 * Gets pulse width rise to rise time.
+	 *
+	 * @return  the pulse width rise to rise time in microseconds.
+	 */
+
+	public int getPulseWidthRiseToRiseUs() {
+		return MotControllerJNI.GetPulseWidthRiseToRiseUs(_handle);
+	}
+
+	/**
+	 * Gets pin state quad a.
+	 *
+	 * @return  the pin state of quad a (1 if asserted, 0 if not asserted).
+	 */
+
+	public boolean getPinStateQuadA() {
+		return MotControllerJNI.GetPinStateQuadA(_handle) != 0;
+	}
+
+	/**
+	 * Gets pin state quad b.
+	 *
+	 * @return  Digital level of QUADB pin (1 if asserted, 0 if not asserted).
+	 */
+
+	public boolean getPinStateQuadB() {
+		return MotControllerJNI.GetPinStateQuadB(_handle) != 0;
+	}
+
+	/**
+	 * Gets pin state quad index.
+	 *
+	 * @return  Digital level of QUAD Index pin (1 if asserted, 0 if not asserted).
+	 */
+
+	public boolean getPinStateQuadIdx() {
+		return MotControllerJNI.GetPinStateQuadIdx(_handle) != 0;
+	}
+
+	/**
+	 * Is forward limit switch closed.
+	 *
+	 * @return  '1' iff forward limit switch is closed, 0 iff switch is open. This function works
+	 *          regardless if limit switch feature is enabled.
+	 */
+
+	public boolean isFwdLimitSwitchClosed() {
+		return MotControllerJNI.IsFwdLimitSwitchClosed(_handle) != 0;
+	}
+
+	/**
+	 * Is reverse limit switch closed.
+	 *
+	 * @return  '1' iff reverse limit switch is closed, 0 iff switch is open. This function works
+	 *          regardless if limit switch feature is enabled.
+	 */
+
+	public boolean isRevLimitSwitchClosed() {
+		return MotControllerJNI.IsRevLimitSwitchClosed(_handle) != 0;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/SensorTerm.java b/java/src/com/ctre/phoenix/motorcontrol/SensorTerm.java
new file mode 100644
index 0000000..8419a0d
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/SensorTerm.java
@@ -0,0 +1,14 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum SensorTerm {
+	Sum0(0),
+	Sum1(1),
+	Diff0(2),
+	Diff1(3);
+	
+	public int value;
+	SensorTerm(int value)
+	{
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/StatusFrame.java b/java/src/com/ctre/phoenix/motorcontrol/StatusFrame.java
new file mode 100644
index 0000000..e6108d6
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/StatusFrame.java
@@ -0,0 +1,30 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum StatusFrame {
+	Status_1_General(0x1400),
+	Status_2_Feedback0(0x1440),
+	Status_4_AinTempVbat(0x14C0),
+	Status_6_Misc(0x1540),
+	Status_7_CommStatus(0x1580),
+	Status_9_MotProfBuffer(0x1600),
+	/**
+	 * Old name for Status 10 Frame.
+	 * Use Status_10_Targets instead.
+	 */
+	Status_10_MotionMagic(0x1640),
+	/**
+	 * Correct name for Status 10 Frame.
+	 * Functionally equivalent to Status_10_MotionMagic
+	 */
+	Status_10_Targets(0x1640),
+	Status_12_Feedback1(0x16C0),
+	Status_13_Base_PIDF0(0x1700),
+	Status_14_Turn_PIDF1(0x1740),
+	Status_15_FirmwareApiStatus(0x1780);
+
+	public int value;
+	StatusFrame(int value)
+	{
+		this.value = value;
+	}
+};
diff --git a/java/src/com/ctre/phoenix/motorcontrol/StatusFrameEnhanced.java b/java/src/com/ctre/phoenix/motorcontrol/StatusFrameEnhanced.java
new file mode 100644
index 0000000..0a8c3c0
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/StatusFrameEnhanced.java
@@ -0,0 +1,25 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum StatusFrameEnhanced {
+	Status_1_General(0x1400),
+	Status_2_Feedback0(0x1440),
+	Status_4_AinTempVbat(0x14C0),
+	Status_6_Misc(0x1540),
+	Status_7_CommStatus(0x1580),
+	Status_9_MotProfBuffer(0x1600),
+	Status_10_MotionMagic(0x1640),
+	Status_12_Feedback1(0x16C0),
+	Status_13_Base_PIDF0(0x1700),
+	Status_14_Turn_PIDF1(0x1740),
+	Status_15_FirmareApiStatus(0x1780),
+
+	Status_3_Quadrature(0x1480),
+	Status_8_PulseWidth(0x15C0),
+	Status_11_UartGadgeteer(0x1680);
+	
+	public int value;
+	StatusFrameEnhanced(int value)
+	{
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/StickyFaults.java b/java/src/com/ctre/phoenix/motorcontrol/StickyFaults.java
new file mode 100644
index 0000000..e18f581
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/StickyFaults.java
@@ -0,0 +1,83 @@
+package com.ctre.phoenix.motorcontrol;
+
+public class StickyFaults {
+	public boolean UnderVoltage;
+	public boolean ForwardLimitSwitch;
+	public boolean ReverseLimitSwitch;
+	public boolean ForwardSoftLimit;
+	public boolean ReverseSoftLimit;
+	public boolean ResetDuringEn;
+	public boolean SensorOverflow;
+	public boolean SensorOutOfPhase;
+	public boolean HardwareESDReset;
+	public boolean RemoteLossOfSignal;
+
+	//!< True iff any of the above flags are true.
+	public boolean hasAnyFault() {
+		return 	UnderVoltage |
+				ForwardLimitSwitch |
+				ReverseLimitSwitch |
+				ForwardSoftLimit |
+				ReverseSoftLimit |
+				ResetDuringEn |
+				SensorOverflow |
+				SensorOutOfPhase |
+				HardwareESDReset |
+				RemoteLossOfSignal;
+	}
+	public int toBitfield() {
+		int retval = 0;
+		int mask = 1;
+		retval |= UnderVoltage ? mask : 0; mask <<= 1;
+		retval |= ForwardLimitSwitch ? mask : 0; mask <<= 1;
+		retval |= ReverseLimitSwitch ? mask : 0; mask <<= 1;
+		retval |= ForwardSoftLimit ? mask : 0; mask <<= 1;
+		retval |= ReverseSoftLimit ? mask : 0; mask <<= 1;
+		retval |= ResetDuringEn ? mask : 0; mask <<= 1;
+		retval |= SensorOverflow ? mask : 0; mask <<= 1;
+		retval |= SensorOutOfPhase ? mask : 0; mask <<= 1;
+		retval |= HardwareESDReset ? mask : 0; mask <<= 1;
+		retval |= RemoteLossOfSignal ? mask : 0; mask <<= 1;
+		return retval;
+	}
+	public void update(int bits) {
+		int mask = 1;
+		UnderVoltage = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ForwardLimitSwitch = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ReverseLimitSwitch = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ForwardSoftLimit = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ReverseSoftLimit = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		ResetDuringEn = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		SensorOverflow = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		SensorOutOfPhase = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		HardwareESDReset = ((bits & mask)!=0) ? true : false; mask <<= 1;
+		RemoteLossOfSignal = ((bits & mask)!=0) ? true : false; mask <<= 1;
+	}
+	public StickyFaults() {
+		UnderVoltage = false;
+		ForwardLimitSwitch = false;
+		ReverseLimitSwitch = false;
+		ForwardSoftLimit = false;
+		ReverseSoftLimit = false;
+		ResetDuringEn = false;
+		SensorOverflow = false;
+		SensorOutOfPhase = false;
+		HardwareESDReset = false;
+		RemoteLossOfSignal = false;
+	}
+	public String toString() {
+		StringBuilder work = new StringBuilder();
+		work.append(" UnderVoltage:"); work.append(UnderVoltage ? "1" : "0");
+		work.append( " ForwardLimitSwitch:"); work.append(ForwardLimitSwitch ? "1" : "0");
+		work.append( " ReverseLimitSwitch:"); work.append(ReverseLimitSwitch ? "1" : "0");
+		work.append( " ForwardSoftLimit:"); work.append(ForwardSoftLimit ? "1" : "0");
+		work.append( " ReverseSoftLimit:"); work.append(ReverseSoftLimit ? "1" : "0");
+		work.append( " ResetDuringEn:"); work.append(ResetDuringEn ? "1" : "0");
+		work.append( " SensorOverflow:"); work.append(SensorOverflow ? "1" : "0");
+		work.append( " SensorOutOfPhase:"); work.append(SensorOutOfPhase ? "1" : "0");
+		work.append( " HardwareESDReset:"); work.append(HardwareESDReset ? "1" : "0");
+		work.append( " RemoteLossOfSignal:"); work.append(RemoteLossOfSignal ? "1" : "0");
+		return work.toString();
+	}
+};
+
diff --git a/java/src/com/ctre/phoenix/motorcontrol/VelocityMeasPeriod.java b/java/src/com/ctre/phoenix/motorcontrol/VelocityMeasPeriod.java
new file mode 100644
index 0000000..b708bb1
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/VelocityMeasPeriod.java
@@ -0,0 +1,18 @@
+package com.ctre.phoenix.motorcontrol;
+
+public enum VelocityMeasPeriod {
+	Period_1Ms(1),
+	Period_2Ms(2),
+	Period_5Ms(5),
+	Period_10Ms(10),
+	Period_20Ms(20),
+	Period_25Ms(25),
+	Period_50Ms(50),
+	Period_100Ms(100);
+	
+	public int value;
+	VelocityMeasPeriod(int value)
+	{
+		this.value = value;
+	}
+};
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/motorcontrol/can/BaseMotorController.java b/java/src/com/ctre/phoenix/motorcontrol/can/BaseMotorController.java
new file mode 100644
index 0000000..0e15160
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/can/BaseMotorController.java
@@ -0,0 +1,1787 @@
+package com.ctre.phoenix.motorcontrol.can;
+
+import com.ctre.phoenix.motorcontrol.ControlFrame;
+import com.ctre.phoenix.motorcontrol.ControlMode;
+import com.ctre.phoenix.motorcontrol.DemandType;
+import com.ctre.phoenix.motorcontrol.Faults;
+import com.ctre.phoenix.motorcontrol.FeedbackDevice;
+import com.ctre.phoenix.motorcontrol.FollowerType;
+import com.ctre.phoenix.motorcontrol.IMotorController;
+import com.ctre.phoenix.motorcontrol.LimitSwitchNormal;
+import com.ctre.phoenix.motorcontrol.LimitSwitchSource;
+import com.ctre.phoenix.motorcontrol.NeutralMode;
+import com.ctre.phoenix.motorcontrol.RemoteFeedbackDevice;
+import com.ctre.phoenix.motorcontrol.RemoteLimitSwitchSource;
+import com.ctre.phoenix.motorcontrol.RemoteSensorSource;
+import com.ctre.phoenix.motorcontrol.SensorCollection;
+import com.ctre.phoenix.motorcontrol.SensorTerm;
+import com.ctre.phoenix.motorcontrol.StatusFrame;
+import com.ctre.phoenix.motorcontrol.StatusFrameEnhanced;
+import com.ctre.phoenix.motorcontrol.StickyFaults;
+import com.ctre.phoenix.motorcontrol.VelocityMeasPeriod;
+import com.ctre.phoenix.motorcontrol.can.MotControllerJNI;
+import com.ctre.phoenix.ParamEnum;
+import com.ctre.phoenix.motion.MotionProfileStatus;
+import com.ctre.phoenix.motion.SetValueMotionProfile;
+import com.ctre.phoenix.motion.TrajectoryPoint;
+import com.ctre.phoenix.ErrorCode;
+
+/**
+ * Base motor controller features for all CTRE CAN motor controllers.
+ */
+public abstract class BaseMotorController implements com.ctre.phoenix.motorcontrol.IMotorController {
+
+	private ControlMode m_controlMode = ControlMode.PercentOutput;
+	private ControlMode m_sendMode = ControlMode.PercentOutput;
+
+	private int _arbId = 0;
+	private boolean _invert = false;
+
+	protected long m_handle;
+
+	private int [] _motionProfStats = new int[11];
+
+	private SensorCollection _sensorColl;
+
+	// --------------------- Constructors -----------------------------//
+	/**
+	 * Constructor for motor controllers.
+	 *
+	 * @param arbId
+	 */
+	public BaseMotorController(int arbId) {
+		m_handle = MotControllerJNI.Create(arbId);
+		_arbId = arbId;
+
+		_sensorColl = new SensorCollection(this);
+	}
+	/**
+	 * @return CCI handle for child classes.
+	 */
+	public long getHandle() {
+		return m_handle;
+	}
+
+	/**
+	 * Returns the Device ID
+	 *
+	 * @return Device number.
+	 */
+	public int getDeviceID() {
+		return MotControllerJNI.GetDeviceNumber(m_handle);
+	}
+
+	// ------ Set output routines. ----------//
+	/**
+	 * Sets the appropriate output on the talon, depending on the mode.
+	 * @param mode The output mode to apply.
+	 * In PercentOutput, the output is between -1.0 and 1.0, with 0.0 as stopped.
+	 * In Current mode, output value is in amperes.
+	 * In Velocity mode, output value is in position change / 100ms.
+	 * In Position mode, output value is in encoder ticks or an analog value,
+	 *   depending on the sensor.
+	 * In Follower mode, the output value is the integer device ID of the talon to
+	 * duplicate.
+	 *
+	 * @param outputValue The setpoint value, as described above.
+	 *
+	 *
+	 *	Standard Driving Example:
+	 *	_talonLeft.set(ControlMode.PercentOutput, leftJoy);
+	 *	_talonRght.set(ControlMode.PercentOutput, rghtJoy);
+	 */
+	public void set(ControlMode mode, double outputValue) {
+		set(mode, outputValue, DemandType.Neutral, 0);
+	}
+	/**
+	 * @param mode Sets the appropriate output on the talon, depending on the mode.
+	 * @param demand0 The output value to apply.
+	 * 	such as advanced feed forward and/or auxiliary close-looping in firmware.
+	 * In PercentOutput, the output is between -1.0 and 1.0, with 0.0 as stopped.
+	 * In Current mode, output value is in amperes.
+	 * In Velocity mode, output value is in position change / 100ms.
+	 * In Position mode, output value is in encoder ticks or an analog value,
+	 *   depending on the sensor. See
+	 * In Follower mode, the output value is the integer device ID of the talon to
+	 * duplicate.
+	 *
+	 * @param demand1 Supplemental value.  This will also be control mode specific for future features.
+	 */
+	public void set(ControlMode mode, double demand0, double demand1) {
+		set(mode, demand0, DemandType.Neutral, demand1);
+	}
+	/**
+	 * @param mode Sets the appropriate output on the talon, depending on the mode.
+	 * @param demand0 The output value to apply.
+	 * 	such as advanced feed forward and/or auxiliary close-looping in firmware.
+	 * In PercentOutput, the output is between -1.0 and 1.0, with 0.0 as stopped.
+	 * In Current mode, output value is in amperes.
+	 * In Velocity mode, output value is in position change / 100ms.
+	 * In Position mode, output value is in encoder ticks or an analog value,
+	 *   depending on the sensor. See
+	 * In Follower mode, the output value is the integer device ID of the talon to
+	 * duplicate.
+	 *
+	 * @param demand1Type The demand type for demand1.
+	 * Neutral: Ignore demand1 and apply no change to the demand0 output.
+	 * AuxPID: Use demand1 to set the target for the auxiliary PID 1.
+	 * ArbitraryFeedForward: Use demand1 as an arbitrary additive value to the
+	 *	 demand0 output.  In PercentOutput the demand0 output is the motor output,
+	 *   and in closed-loop modes the demand0 output is the output of PID0.
+	 * @param demand1 Supplmental output value.  Units match the set mode.
+	 *
+	 *
+	 *  Arcade Drive Example:
+	 *		_talonLeft.set(ControlMode.PercentOutput, joyForward, DemandType.ArbitraryFeedForward, +joyTurn);
+	 *		_talonRght.set(ControlMode.PercentOutput, joyForward, DemandType.ArbitraryFeedForward, -joyTurn);
+	 *
+	 *	Drive Straight Example:
+	 *	Note: Selected Sensor Configuration is necessary for both PID0 and PID1.
+	 *		_talonLeft.follow(_talonRght, FollwerType.AuxOutput1);
+	 *		_talonRght.set(ControlMode.PercentOutput, joyForward, DemandType.AuxPID, desiredRobotHeading);
+	 *
+	 *	Drive Straight to a Distance Example:
+	 *	Note: Other configurations (sensor selection, PID gains, etc.) need to be set.
+	 *		_talonLeft.follow(_talonRght, FollwerType.AuxOutput1);
+	 *		_talonRght.set(ControlMode.MotionMagic, targetDistance, DemandType.AuxPID, desiredRobotHeading);
+	 */
+	public void set(ControlMode mode, double demand0, DemandType demand1Type, double demand1){
+		m_controlMode = mode;
+		m_sendMode = mode;
+		int work;
+
+		switch (m_controlMode) {
+		case PercentOutput:
+			// case TimedPercentOutput:
+			MotControllerJNI.Set_4(m_handle, m_sendMode.value, demand0, demand1, demand1Type.value);
+			break;
+		case Follower:
+			/* did caller specify device ID */
+			if ((0 <= demand0) && (demand0 <= 62)) { // [0,62]
+				work = getBaseID();
+				work >>= 16;
+				work <<= 8;
+				work |= ((int) demand0) & 0xFF;
+			} else {
+				work = (int) demand0;
+			}
+			/* single precision guarantees 16bits of integral precision,
+		   * so float/double cast on work is safe */
+			MotControllerJNI.Set_4(m_handle, m_sendMode.value, (double)work, demand1, demand1Type.value);
+			break;
+		case Velocity:
+		case Position:
+		case MotionMagic:
+		case MotionProfile:
+		case MotionProfileArc:
+			MotControllerJNI.Set_4(m_handle, m_sendMode.value, demand0, demand1, demand1Type.value);
+			break;
+		case Current:
+			MotControllerJNI.SetDemand(m_handle, m_sendMode.value, (int) (1000. * demand0), 0); /* milliamps */
+			break;
+		case Disabled:
+			/* fall thru... */
+		default:
+			MotControllerJNI.SetDemand(m_handle, m_sendMode.value, 0, 0);
+			break;
+		}
+
+	}
+
+	/**
+	 * Neutral the motor output by setting control mode to disabled.
+	 */
+	public void neutralOutput() {
+		set(ControlMode.Disabled, 0);
+	}
+
+	/**
+	 * Sets the mode of operation during neutral throttle output.
+	 *
+	 * @param neutralMode
+	 *            The desired mode of operation when the Controller output
+	 *            throttle is neutral (ie brake/coast)
+	 **/
+	public void setNeutralMode(NeutralMode neutralMode) {
+		MotControllerJNI.SetNeutralMode(m_handle, neutralMode.value);
+	}
+	/**
+	 * Enables a future feature called "Heading Hold".
+	 * For now this simply updates the CAN signal to the motor controller.
+	 * Future firmware updates will use this.
+	 *
+	 *	@param enable true/false enable
+	 */
+	public void enableHeadingHold(boolean enable) {
+		/* this routine is moot as the Set() call updates the signal on each call */
+		//MotControllerJNI.EnableHeadingHold(m_handle, enable ? 1 : 0);
+	}
+	/**
+	 * For now this simply updates the CAN signal to the motor controller.
+	 * Future firmware updates will use this to control advanced auxiliary loop behavior.
+	 *
+	 *	@param value
+	 */
+	public void selectDemandType(boolean value) {
+		/* this routine is moot as the Set() call updates the signal on each call */
+		//MotControllerJNI.SelectDemandType(m_handle, value ? 1 : 0);
+	}
+
+	// ------ Invert behavior ----------//
+	/**
+	 * Sets the phase of the sensor. Use when controller forward/reverse output
+	 * doesn't correlate to appropriate forward/reverse reading of sensor.
+	 * Pick a value so that positive PercentOutput yields a positive change in sensor.
+	 * After setting this, user can freely call SetInvert() with any value.
+	 *
+	 * @param PhaseSensor
+	 *            Indicates whether to invert the phase of the sensor.
+	 */
+	public void setSensorPhase(boolean PhaseSensor) {
+		MotControllerJNI.SetSensorPhase(m_handle, PhaseSensor);
+	}
+
+	/**
+	 * Inverts the hbridge output of the motor controller.
+	 *
+	 * This does not impact sensor phase and should not be used to correct sensor polarity.
+	 *
+	 * This will invert the hbridge output but NOT the LEDs.
+	 * This ensures....
+	 *  - Green LEDs always represents positive request from robot-controller/closed-looping mode.
+	 *  - Green LEDs correlates to forward limit switch.
+	 *  - Green LEDs correlates to forward soft limit.
+	 *
+	 * @param invert
+	 *            Invert state to set.
+	 */
+	public void setInverted(boolean invert) {
+		_invert = invert; /* cache for getter */
+		MotControllerJNI.SetInverted(m_handle, invert);
+	}
+	/**
+	 * @return invert setting of motor output.
+	 */
+	public boolean getInverted() {
+		return _invert;
+	}
+
+	// ----- general output shaping ------------------//
+	/**
+	 * Configures the open-loop ramp rate of throttle output.
+	 *
+	 * @param secondsFromNeutralToFull
+	 *            Minimum desired time to go from neutral to full throttle. A
+	 *            value of '0' will disable the ramp.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configOpenloopRamp(double secondsFromNeutralToFull, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigOpenLoopRamp(m_handle, secondsFromNeutralToFull, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the closed-loop ramp rate of throttle output.
+	 *
+	 * @param secondsFromNeutralToFull
+	 *            Minimum desired time to go from neutral to full throttle. A
+	 *            value of '0' will disable the ramp.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configClosedloopRamp(double secondsFromNeutralToFull, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigClosedLoopRamp(m_handle, secondsFromNeutralToFull, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the forward peak output percentage.
+	 *
+	 * @param percentOut
+	 *            Desired peak output percentage. [0,1]
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configPeakOutputForward(double percentOut, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigPeakOutputForward(m_handle, percentOut, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the reverse peak output percentage.
+	 *
+	 * @param percentOut
+	 *            Desired peak output percentage.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configPeakOutputReverse(double percentOut, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigPeakOutputReverse(m_handle, percentOut, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Configures the forward nominal output percentage.
+	 *
+	 * @param percentOut
+	 *            Nominal (minimum) percent output. [0,+1]
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configNominalOutputForward(double percentOut, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigNominalOutputForward(m_handle, percentOut, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the reverse nominal output percentage.
+	 *
+	 * @param percentOut
+	 *            Nominal (minimum) percent output. [-1,0]
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configNominalOutputReverse(double percentOut, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigNominalOutputReverse(m_handle, percentOut, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the output deadband percentage.
+	 *
+	 * @param percentDeadband
+	 *            Desired deadband percentage. Minimum is 0.1%, Maximum is 25%.
+	 *            Pass 0.04 for 4% (factory default).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configNeutralDeadband(double percentDeadband, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigNeutralDeadband(m_handle, percentDeadband, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------ Voltage Compensation ----------//
+	/**
+	 * Configures the Voltage Compensation saturation voltage.
+	 *
+	 * @param voltage
+	 *            This is the max voltage to apply to the hbridge when voltage
+	 *            compensation is enabled.  For example, if 10 (volts) is specified
+	 *            and a TalonSRX is commanded to 0.5 (PercentOutput, closed-loop, etc)
+	 *            then the TalonSRX will attempt to apply a duty-cycle to produce 5V.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVoltageCompSaturation(double voltage, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigVoltageCompSaturation(m_handle, voltage, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the voltage measurement filter.
+	 *
+	 * @param filterWindowSamples
+	 *            Number of samples in the rolling average of voltage
+	 *            measurement.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVoltageMeasurementFilter(int filterWindowSamples, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigVoltageMeasurementFilter(m_handle, filterWindowSamples, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Enables voltage compensation. If enabled, voltage compensation works in
+	 * all control modes.
+	 *
+	 * @param enable
+	 *            Enable state of voltage compensation.
+	 **/
+	public void enableVoltageCompensation(boolean enable) {
+		MotControllerJNI.EnableVoltageCompensation(m_handle, enable);
+	}
+
+	// ------ General Status ----------//
+	/**
+	 * Gets the bus voltage seen by the device.
+	 *
+	 * @return The bus voltage value (in volts).
+	 */
+	public double getBusVoltage() {
+		return MotControllerJNI.GetBusVoltage(m_handle);
+	}
+
+	/**
+	 * Gets the output percentage of the motor controller.
+	 *
+	 * @return Output of the motor controller (in percent).
+	 */
+	public double getMotorOutputPercent() {
+		return MotControllerJNI.GetMotorOutputPercent(m_handle);
+	}
+
+	/**
+	 * @return applied voltage to motor  in volts.
+	 */
+	public double getMotorOutputVoltage() {
+		return getBusVoltage() * getMotorOutputPercent();
+	}
+
+	/**
+	 * Gets the output current of the motor controller.
+	 *
+	 * @return The output current (in amps).
+	 */
+	public double getOutputCurrent() {
+		return MotControllerJNI.GetOutputCurrent(m_handle);
+	}
+
+	/**
+	 * Gets the temperature of the motor controller.
+	 *
+	 * @return Temperature of the motor controller (in 'C)
+	 */
+	public double getTemperature() {
+		return MotControllerJNI.GetTemperature(m_handle);
+	}
+
+	// ------ sensor selection ----------//
+	/**
+	 * Select the remote feedback device for the motor controller.
+	 * Most CTRE CAN motor controllers will support remote sensors over CAN.
+	 *
+	 * @param feedbackDevice
+	 *            Remote Feedback Device to select.
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSelectedFeedbackSensor(RemoteFeedbackDevice feedbackDevice, int pidIdx, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigSelectedFeedbackSensor(m_handle, feedbackDevice.value, pidIdx, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Select the feedback device for the motor controller.
+	 *
+	 * @param feedbackDevice
+	 *            Feedback Device to select.
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSelectedFeedbackSensor(FeedbackDevice feedbackDevice, int pidIdx, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigSelectedFeedbackSensor(m_handle, feedbackDevice.value, pidIdx, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * The Feedback Coefficient is a scalar applied to the value of the
+	 * feedback sensor.  Useful when you need to scale your sensor values
+	 * within the closed-loop calculations.  Default value is 1.
+	 *
+	 * Selected Feedback Sensor register in firmware is the decoded sensor value
+	 * multiplied by the Feedback Coefficient.
+	 *
+	 * @param coefficient
+	 *            Feedback Coefficient value.  Maximum value of 1.
+	 *						Resolution is 1/(2^16).  Cannot be 0.
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSelectedFeedbackCoefficient(double coefficient, int pidIdx, int timeoutMs) {
+	  int retval = MotControllerJNI.ConfigSelectedFeedbackCoefficient(m_handle, coefficient, pidIdx, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Select what remote device and signal to assign to Remote Sensor 0 or Remote Sensor 1.
+	 * After binding a remote device and signal to Remote Sensor X, you may select Remote Sensor X
+	 * as a PID source for closed-loop features.
+	 *
+	 * @param deviceID
+ 	 *            The CAN ID of the remote sensor device.
+	 * @param remoteSensorSource
+	 *            The remote sensor device and signal type to bind.
+	 * @param remoteOrdinal
+	 *            0 for configuring Remote Sensor 0
+	 *            1 for configuring Remote Sensor 1
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configRemoteFeedbackFilter(int deviceID, RemoteSensorSource remoteSensorSource, int remoteOrdinal,
+			int timeoutMs) {
+		int retval = MotControllerJNI.ConfigRemoteFeedbackFilter(m_handle, deviceID, remoteSensorSource.value, remoteOrdinal,
+				timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Select what sensor term should be bound to switch feedback device.
+	 * Sensor Sum = Sensor Sum Term 0 - Sensor Sum Term 1
+	 * Sensor Difference = Sensor Diff Term 0 - Sensor Diff Term 1
+	 * The four terms are specified with this routine.  Then Sensor Sum/Difference
+	 * can be selected for closed-looping.
+	 *
+	 * @param sensorTerm Which sensor term to bind to a feedback source.
+	 * @param feedbackDevice The sensor signal to attach to sensorTerm.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSensorTerm(SensorTerm sensorTerm, FeedbackDevice feedbackDevice, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigSensorTerm(m_handle, sensorTerm.value, feedbackDevice.value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------- sensor status --------- //
+	/**
+	 * Get the selected sensor position (in raw sensor units).
+	 *
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop. See
+	 *            Phoenix-Documentation for how to interpret.
+	 *
+	 * @return Position of selected sensor (in raw sensor units).
+	 */
+	public int getSelectedSensorPosition(int pidIdx) {
+		return MotControllerJNI.GetSelectedSensorPosition(m_handle, pidIdx);
+	}
+
+	/**
+	 * Get the selected sensor velocity.
+	 *
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @return selected sensor (in raw sensor units) per 100ms.
+	 * See Phoenix-Documentation for how to interpret.
+	 */
+	public int getSelectedSensorVelocity(int pidIdx) {
+		return MotControllerJNI.GetSelectedSensorVelocity(m_handle, pidIdx);
+	}
+
+	/**
+	 * Sets the sensor position to the given value.
+	 *
+	 * @param sensorPos
+	 *            Position to set for the selected sensor (in raw sensor units).
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setSelectedSensorPosition(int sensorPos, int pidIdx, int timeoutMs) {
+		int retval = MotControllerJNI.SetSelectedSensorPosition(m_handle, sensorPos, pidIdx, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------ status frame period changes ----------//
+	/**
+	 * Sets the period of the given control frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setControlFramePeriod(ControlFrame frame, int periodMs) {
+		int retval = MotControllerJNI.SetControlFramePeriod(m_handle, frame.value, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * User ensure CAN Bus utilization is not high.
+	 *
+	 * This setting is not persistent and is lost when device is reset.
+	 * If this is a concern, calling application can use HasReset()
+	 * to determine if the status frame needs to be reconfigured.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setControlFramePeriod(int frame, int periodMs) {
+		int retval = MotControllerJNI.SetControlFramePeriod(m_handle, frame, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * User ensure CAN Bus utilization is not high.
+	 *
+	 * This setting is not persistent and is lost when device is reset. If this
+	 * is a concern, calling application can use HasReset() to determine if the
+	 * status frame needs to be reconfigured.
+	 *
+	 * @param frameValue
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(int frameValue, int periodMs, int timeoutMs) {
+		int retval = MotControllerJNI.SetStatusFramePeriod(m_handle, frameValue, periodMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(StatusFrame frame, int periodMs, int timeoutMs) {
+		return setStatusFramePeriod(frame.value, periodMs, timeoutMs);
+	}
+
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Period of the given status frame.
+	 */
+	public int getStatusFramePeriod(int frame, int timeoutMs) {
+		return MotControllerJNI.GetStatusFramePeriod(m_handle, frame, timeoutMs);
+	}
+
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Period of the given status frame.
+	 */
+	public int getStatusFramePeriod(StatusFrame frame, int timeoutMs) {
+		return MotControllerJNI.GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
+	}
+
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Period of the given status frame.
+	 */
+	public int getStatusFramePeriod(StatusFrameEnhanced frame, int timeoutMs) {
+		return MotControllerJNI.GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
+	}
+
+	// ----- velocity signal conditionaing ------//
+
+	/**
+	 * Sets the period over which velocity measurements are taken.
+	 *
+	 * @param period
+	 *            Desired period for the velocity measurement. @see
+	 *            #VelocityMeasPeriod
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVelocityMeasurementPeriod(VelocityMeasPeriod period, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the number of velocity samples used in the rolling average velocity
+	 * measurement.
+	 *
+	 * @param windowSize
+	 *            Number of samples in the rolling average of velocity
+	 *            measurement. Valid values are 1,2,4,8,16,32. If another value
+	 *            is specified, it will truncate to nearest support value.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigVelocityMeasurementWindow(m_handle, windowSize, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------ remote limit switch ----------//
+	/**
+	 * Configures the forward limit switch for a remote source. For example, a
+	 * CAN motor controller may need to monitor the Limit-F pin of another Talon
+	 * or CANifier.
+	 *
+	 * @param type
+	 *            Remote limit switch source. User can choose between a remote
+	 *            Talon SRX, CANifier, or deactivate the feature.
+	 * @param normalOpenOrClose
+	 *            Setting for normally open, normally closed, or disabled. This
+	 *            setting matches the web-based configuration drop down.
+	 * @param deviceID
+	 *            Device ID of remote source (Talon SRX or CANifier device ID).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configForwardLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int deviceID, int timeoutMs) {
+		return configForwardLimitSwitchSource(type.value, normalOpenOrClose.value, deviceID, timeoutMs);
+	}
+
+	/**
+	 * Configures the reverse limit switch for a remote source. For example, a
+	 * CAN motor controller may need to monitor the Limit-R pin of another Talon
+	 * or CANifier.
+	 *
+	 * @param type
+	 *            Remote limit switch source. User can choose between a remote
+	 *            Talon SRX, CANifier, or deactivate the feature.
+	 * @param normalOpenOrClose
+	 *            Setting for normally open, normally closed, or disabled. This
+	 *            setting matches the web-based configuration drop down.
+	 * @param deviceID
+	 *            Device ID of remote source (Talon SRX or CANifier device ID).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configReverseLimitSwitchSource(RemoteLimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int deviceID, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigReverseLimitSwitchSource(m_handle, type.value, normalOpenOrClose.value,
+				deviceID, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures a limit switch for a local/remote source.
+	 *
+	 * For example, a CAN motor controller may need to monitor the Limit-R pin
+	 * of another Talon, CANifier, or local Gadgeteer feedback connector.
+	 *
+	 * If the sensor is remote, a device ID of zero is assumed. If that's not
+	 * desired, use the four parameter version of this function.
+	 *
+	 * @param type
+	 *            Limit switch source. @see #LimitSwitchSource User can choose
+	 *            between the feedback connector, remote Talon SRX, CANifier, or
+	 *            deactivate the feature.
+	 * @param normalOpenOrClose
+	 *            Setting for normally open, normally closed, or disabled. This
+	 *            setting matches the web-based configuration drop down.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configForwardLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int timeoutMs) {
+		return configForwardLimitSwitchSource(type.value, normalOpenOrClose.value, 0x00000000, timeoutMs);
+	}
+
+	protected ErrorCode configForwardLimitSwitchSource(int typeValue, int normalOpenOrCloseValue, int deviceID,
+			int timeoutMs) {
+		int retval = MotControllerJNI.ConfigForwardLimitSwitchSource(m_handle, typeValue, normalOpenOrCloseValue,
+				deviceID, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures a limit switch for a local/remote source.
+	 *
+	 * For example, a CAN motor controller may need to monitor the Limit-R pin
+	 * of another Talon, CANifier, or local Gadgeteer feedback connector.
+	 *
+	 * If the sensor is remote, a device ID of zero is assumed. If that's not
+	 * desired, use the four parameter version of this function.
+	 *
+	 * @param typeValue
+	 *            Limit switch source. @see #LimitSwitchSource User can choose
+	 *            between the feedback connector, remote Talon SRX, CANifier, or
+	 *            deactivate the feature.
+	 * @param normalOpenOrCloseValue
+	 *            Setting for normally open, normally closed, or disabled. This
+	 *            setting matches the web-based configuration drop down.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	protected ErrorCode configReverseLimitSwitchSource(int typeValue, int normalOpenOrCloseValue, int deviceID,
+			int timeoutMs) {
+		int retval = MotControllerJNI.ConfigReverseLimitSwitchSource(m_handle, typeValue, normalOpenOrCloseValue,
+				deviceID, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the enable state for limit switches.
+	 *
+	 * @param enable
+	 *            Enable state for limit switches.
+	 **/
+	public void overrideLimitSwitchesEnable(boolean enable) {
+		MotControllerJNI.OverrideLimitSwitchesEnable(m_handle, enable);
+	}
+
+	// ------ soft limit ----------//
+	/**
+	 * Configures the forward soft limit threhold.
+	 *
+	 * @param forwardSensorLimit
+	 *            Forward Sensor Position Limit (in raw sensor units).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configForwardSoftLimitThreshold(int forwardSensorLimit, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigForwardSoftLimitThreshold(m_handle, forwardSensorLimit, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the reverse soft limit threshold.
+	 *
+	 * @param reverseSensorLimit
+	 *            Reverse Sensor Position Limit (in raw sensor units).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configReverseSoftLimitThreshold(int reverseSensorLimit, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigReverseSoftLimitThreshold(m_handle, reverseSensorLimit, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the forward soft limit enable.
+	 *
+	 * @param enable
+	 *            Forward Sensor Position Limit Enable.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configForwardSoftLimitEnable(boolean enable, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigForwardSoftLimitEnable(m_handle, enable, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the reverse soft limit enable.
+	 *
+	 * @param enable
+	 *            Reverse Sensor Position Limit Enable.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configReverseSoftLimitEnable(boolean enable, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigReverseSoftLimitEnable(m_handle, enable, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Can be used to override-disable the soft limits.
+	 * This function can be used to quickly disable soft limits without
+	 * having to modify the persistent configuration.
+	 *
+	 * @param enable
+	 *            Enable state for soft limit switches.
+	 */
+	public void overrideSoftLimitsEnable(boolean enable) {
+		MotControllerJNI.OverrideSoftLimitsEnable(m_handle, enable);
+	}
+
+	// ------ Current Lim ----------//
+	/* not available in base */
+
+	// ------ General Close loop ----------//
+	/**
+	 * Sets the 'P' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the P constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode config_kP(int slotIdx, double value, int timeoutMs) {
+		int retval = MotControllerJNI.Config_kP(m_handle, slotIdx,  value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the 'I' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the I constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode config_kI(int slotIdx, double value, int timeoutMs) {
+		int retval = MotControllerJNI.Config_kI(m_handle, slotIdx,  value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the 'D' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the D constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode config_kD(int slotIdx, double value, int timeoutMs) {
+		int retval = MotControllerJNI.Config_kD(m_handle, slotIdx,  value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the 'F' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the F constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode config_kF(int slotIdx, double value, int timeoutMs) {
+		int retval = MotControllerJNI.Config_kF(m_handle, slotIdx,  value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the Integral Zone constant in the given parameter slot. If the
+	 * (absolute) closed-loop error is outside of this zone, integral
+	 * accumulator is automatically cleared. This ensures than integral wind up
+	 * events will stop after the sensor gets far enough from its target.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param izone
+	 *            Value of the Integral Zone constant (closed loop error units X
+	 *            1ms).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode config_IntegralZone(int slotIdx, int izone, int timeoutMs) {
+		int retval = MotControllerJNI.Config_IntegralZone(m_handle, slotIdx,  izone, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the allowable closed-loop error in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param allowableClosedLoopError
+	 *            Value of the allowable closed-loop error.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configAllowableClosedloopError(int slotIdx, int allowableClosedLoopError, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigAllowableClosedloopError(m_handle, slotIdx, allowableClosedLoopError,
+				timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the maximum integral accumulator in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param iaccum
+	 *            Value of the maximum integral accumulator (closed loop error
+	 *            units X 1ms).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configMaxIntegralAccumulator(int slotIdx, double iaccum, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigMaxIntegralAccumulator(m_handle, slotIdx, iaccum, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the peak closed-loop output.  This peak output is slot-specific and
+	 *   is applied to the output of the associated PID loop.
+	 * This setting is seperate from the generic Peak Output setting.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param percentOut
+	 *            Peak Percent Output from 0 to 1.  This value is absolute and
+	 *						the magnitude will apply in both forward and reverse directions.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configClosedLoopPeakOutput(int slotIdx, double percentOut, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigClosedLoopPeakOutput(m_handle, slotIdx, percentOut, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the loop time (in milliseconds) of the PID closed-loop calculations.
+	 * Default value is 1 ms.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param loopTimeMs
+	 *            Loop timing of the closed-loop calculations.  Minimum value of
+	 *						1 ms, maximum of 64 ms.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+  public ErrorCode configClosedLoopPeriod(int slotIdx, int loopTimeMs, int timeoutMs) {
+	  int retval = MotControllerJNI.ConfigClosedLoopPeriod(m_handle, slotIdx, loopTimeMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configures the Polarity of the Auxiliary PID (PID1).
+	 *
+	 * Standard Polarity:
+	 *    Primary Output = PID0 + PID1
+	 *    Auxiliary Output = PID0 - PID1
+	 *
+	 * Inverted Polarity:
+	 *    Primary Output = PID0 - PID1
+	 *    Auxiliary Output = PID0 + PID1
+	 *
+	 * @param invert
+	 *            If true, use inverted PID1 output polarity.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code
+	 */
+	public ErrorCode configAuxPIDPolarity(boolean invert, int timeoutMs){
+		return configSetParameter(ParamEnum.ePIDLoopPolarity, invert ? 1:0, 0, 1, timeoutMs);
+	}
+
+	/**
+	 * Sets the integral accumulator. Typically this is used to clear/zero the
+	 * integral accumulator, however some use cases may require seeding the
+	 * accumulator for a faster response.
+	 *
+	 * @param iaccum
+	 *            Value to set for the integral accumulator (closed loop error
+	 *            units X 1ms).
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setIntegralAccumulator(double iaccum, int pidIdx, int timeoutMs) {
+		int retval = MotControllerJNI.SetIntegralAccumulator(m_handle,  iaccum, pidIdx, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the closed-loop error. The units depend on which control mode is in
+	 * use. See Phoenix-Documentation information on units.
+	 *
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @return Closed-loop error value.
+	 */
+	public int getClosedLoopError(int pidIdx) {
+		return MotControllerJNI.GetClosedLoopError(m_handle, pidIdx);
+	}
+
+	/**
+	 * Gets the iaccum value.
+	 *
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @return Integral accumulator value (Closed-loop error X 1ms).
+	 */
+	public double getIntegralAccumulator(int pidIdx) {
+		return MotControllerJNI.GetIntegralAccumulator(m_handle, pidIdx);
+	}
+
+
+	/**
+	 * Gets the derivative of the closed-loop error.
+	 *
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @return The error derivative value.
+	 */
+	public double getErrorDerivative(int pidIdx) {
+		return MotControllerJNI.GetErrorDerivative(m_handle, pidIdx);
+	}
+
+	/**
+	 * Selects which profile slot to use for closed-loop control.
+	 *
+	 * @param slotIdx
+	 *            Profile slot to select.
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 **/
+	public void selectProfileSlot(int slotIdx, int pidIdx) {
+		MotControllerJNI.SelectProfileSlot(m_handle, slotIdx, pidIdx);
+	}
+
+	/**
+	 * Gets the current target of a given closed loop.
+	 *
+	 * @param pidIdx
+	 *            0 for Primary closed-loop. 1 for auxiliary closed-loop.
+	 * @return The closed loop target.
+	 */
+	public int getClosedLoopTarget(int pidIdx) {
+		return MotControllerJNI.GetClosedLoopTarget(m_handle, pidIdx);
+	}
+
+	/**
+	 * Gets the active trajectory target position using
+	 * MotionMagic/MotionProfile control modes.
+	 *
+	 * @return The Active Trajectory Position in sensor units.
+	 */
+	public int getActiveTrajectoryPosition() {
+		return MotControllerJNI.GetActiveTrajectoryPosition(m_handle);
+	}
+
+	/**
+	 * Gets the active trajectory target velocity using
+	 * MotionMagic/MotionProfile control modes.
+	 *
+	 * @return The Active Trajectory Velocity in sensor units per 100ms.
+	 */
+	public int getActiveTrajectoryVelocity() {
+		return MotControllerJNI.GetActiveTrajectoryVelocity(m_handle);
+	}
+
+	/**
+	 * Gets the active trajectory target heading using
+	 * MotionMagicArc/MotionProfileArc control modes.
+	 *
+	 * @return The Active Trajectory Heading in degreees.
+	 */
+	public double getActiveTrajectoryHeading() {
+		return MotControllerJNI.GetActiveTrajectoryHeading(m_handle);
+	}
+
+	// ------ Motion Profile Settings used in Motion Magic and Motion Profile ----------//
+
+	/**
+	 * Sets the Motion Magic Cruise Velocity. This is the peak target velocity
+	 * that the motion magic curve generator can use.
+	 *
+	 * @param sensorUnitsPer100ms
+	 *            Motion Magic Cruise Velocity (in raw sensor units per 100 ms).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configMotionCruiseVelocity(int sensorUnitsPer100ms, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigMotionCruiseVelocity(m_handle, sensorUnitsPer100ms, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the Motion Magic Acceleration. This is the target acceleration that
+	 * the motion magic curve generator can use.
+	 *
+	 * @param sensorUnitsPer100msPerSec
+	 *            Motion Magic Acceleration (in raw sensor units per 100 ms per
+	 *            second).
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configMotionAcceleration(int sensorUnitsPer100msPerSec, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigMotionAcceleration(m_handle, sensorUnitsPer100msPerSec, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	//------ Motion Profile Buffer ----------//
+	/**
+	 * Clear the buffered motion profile in both controller's RAM (bottom), and in the
+	 * API (top).
+	 */
+	public ErrorCode clearMotionProfileTrajectories() {
+		int retval = MotControllerJNI.ClearMotionProfileTrajectories(m_handle);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Retrieve just the buffer count for the api-level (top) buffer. This
+	 * routine performs no CAN or data structure lookups, so its fast and ideal
+	 * if caller needs to quickly poll the progress of trajectory points being
+	 * emptied into controller's RAM. Otherwise just use GetMotionProfileStatus.
+	 *
+	 * @return number of trajectory points in the top buffer.
+	 */
+	public int getMotionProfileTopLevelBufferCount() {
+		return MotControllerJNI.GetMotionProfileTopLevelBufferCount(m_handle);
+	}
+	/**
+	 * Push another trajectory point into the top level buffer (which is emptied
+	 * into the motor controller's bottom buffer as room allows).
+	 * @param trajPt to push into buffer.
+	 * The members should be filled in with these values...
+	 *
+	 * 		targPos:  servo position in sensor units.
+	 *		targVel:  velocity to feed-forward in sensor units
+	 *                 per 100ms.
+	 * 		profileSlotSelect0  Which slot to get PIDF gains. PID is used for position servo. F is used
+	 *						   as the Kv constant for velocity feed-forward. Typically this is hardcoded
+	 *						   to the a particular slot, but you are free gain schedule if need be.
+	 *						   Choose from [0,3]
+	 *		profileSlotSelect1 Which slot to get PIDF gains for auxiliary PId.
+	 *						   This only has impact during MotionProfileArc Control mode.
+	 *						   Choose from [0,1].
+	 * 	   isLastPoint  set to nonzero to signal motor controller to keep processing this
+	 *                     trajectory point, instead of jumping to the next one
+	 *                     when timeDurMs expires.  Otherwise MP executer will
+	 *                     eventually see an empty buffer after the last point
+	 *                     expires, causing it to assert the IsUnderRun flag.
+	 *                     However this may be desired if calling application
+	 *                     never wants to terminate the MP.
+	 *		zeroPos  set to nonzero to signal motor controller to "zero" the selected
+	 *                 position sensor before executing this trajectory point.
+	 *                 Typically the first point should have this set only thus
+	 *                 allowing the remainder of the MP positions to be relative to
+	 *                 zero.
+	 *		timeDur Duration to apply this trajectory pt.
+	 * 				This time unit is ADDED to the exising base time set by
+	 * 				configMotionProfileTrajectoryPeriod().
+	 * @return CTR_OKAY if trajectory point push ok. ErrorCode if buffer is
+	 *         full due to kMotionProfileTopBufferCapacity.
+	 */
+	public ErrorCode pushMotionProfileTrajectory(TrajectoryPoint trajPt) {
+		int retval = MotControllerJNI.PushMotionProfileTrajectory2(m_handle,
+				trajPt.position, trajPt.velocity, trajPt.auxiliaryPos,
+				trajPt.profileSlotSelect0, trajPt.profileSlotSelect1,
+				trajPt.isLastPoint, trajPt.zeroPos, trajPt.timeDur.value);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Retrieve just the buffer full for the api-level (top) buffer. This
+	 * routine performs no CAN or data structure lookups, so its fast and ideal
+	 * if caller needs to quickly poll. Otherwise just use
+	 * GetMotionProfileStatus.
+	 *
+	 * @return number of trajectory points in the top buffer.
+	 */
+	public boolean isMotionProfileTopLevelBufferFull() {
+		return MotControllerJNI.IsMotionProfileTopLevelBufferFull(m_handle);
+	}
+
+	/**
+	 * This must be called periodically to funnel the trajectory points from the
+	 * API's top level buffer to the controller's bottom level buffer. Recommendation
+	 * is to call this twice as fast as the execution rate of the motion
+	 * profile. So if MP is running with 20ms trajectory points, try calling
+	 * this routine every 10ms. All motion profile functions are thread-safe
+	 * through the use of a mutex, so there is no harm in having the caller
+	 * utilize threading.
+	 */
+	public void processMotionProfileBuffer() {
+		MotControllerJNI.ProcessMotionProfileBuffer(m_handle);
+	}
+	/**
+	 * Retrieve all status information.
+	 * For best performance, Caller can snapshot all status information regarding the
+	 * motion profile executer.
+	 *
+	 * @param statusToFill  Caller supplied object to fill.
+	 *
+	 * The members are filled, as follows...
+	 *
+	 *	topBufferRem:	The available empty slots in the trajectory buffer.
+	 * 	 				The robot API holds a "top buffer" of trajectory points, so your applicaion
+	 * 	 				can dump several points at once.  The API will then stream them into the
+	 * 	 		 		low-level buffer, allowing the motor controller to act on them.
+	 *
+	 *	topBufferRem: The number of points in the top trajectory buffer.
+	 *
+	 *	btmBufferCnt: The number of points in the low level controller buffer.
+	 *
+	 *	hasUnderrun: 	Set if isUnderrun ever gets set.
+	 * 	 	 	 	 	Only is cleared by clearMotionProfileHasUnderrun() to ensure
+	 *
+	 *	isUnderrun:		This is set if controller needs to shift a point from its buffer into
+	 *					the active trajectory point however
+	 *					the buffer is empty.
+	 *					This gets cleared automatically when is resolved.
+	 *
+	 *	activePointValid:	True if the active trajectory point has not empty, false otherwise. The members in activePoint are only valid if this signal is set.
+	 *
+	 *	isLast:	is set/cleared based on the MP executer's current
+	 *                trajectory point's IsLast value.  This assumes
+	 *                IsLast was set when PushMotionProfileTrajectory
+	 *                was used to insert the currently processed trajectory
+	 *                point.
+	 *
+	 *	profileSlotSelect: The currently processed trajectory point's
+	 *      			  selected slot.  This can differ in the currently selected slot used
+	 *       				 for Position and Velocity servo modes
+	 *
+	 *	outputEnable:		The current output mode of the motion profile
+	 *						executer (disabled, enabled, or hold).  When changing the set()
+	 *						value in MP mode, it's important to check this signal to
+	 *						confirm the change takes effect before interacting with the top buffer.
+	 */
+	public ErrorCode getMotionProfileStatus(MotionProfileStatus statusToFill) {
+		int retval = MotControllerJNI.GetMotionProfileStatus2(m_handle, _motionProfStats);
+		statusToFill.topBufferRem = _motionProfStats[0];
+		statusToFill.topBufferCnt = _motionProfStats[1];
+		statusToFill.btmBufferCnt = _motionProfStats[2];
+		statusToFill.hasUnderrun = _motionProfStats[3] != 0;
+		statusToFill.isUnderrun = _motionProfStats[4] != 0;
+		statusToFill.activePointValid = _motionProfStats[5] != 0;
+		statusToFill.isLast = _motionProfStats[6] != 0;
+		statusToFill.profileSlotSelect = _motionProfStats[7];
+		statusToFill.outputEnable = SetValueMotionProfile.valueOf(_motionProfStats[8]);
+		statusToFill.timeDurMs = _motionProfStats[9];
+		statusToFill.profileSlotSelect1 = _motionProfStats[10];
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Clear the "Has Underrun" flag. Typically this is called after application
+	 * has confirmed an underrun had occured.
+	 *
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode clearMotionProfileHasUnderrun(int timeoutMs) {
+		int retval = MotControllerJNI.ClearMotionProfileHasUnderrun(m_handle, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Calling application can opt to speed up the handshaking between the robot
+	 * API and the controller to increase the download rate of the controller's Motion
+	 * Profile. Ideally the period should be no more than half the period of a
+	 * trajectory point.
+	 *
+	 * @param periodMs
+	 *            The transmit period in ms.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode changeMotionControlFramePeriod(int periodMs) {
+		int retval = MotControllerJNI.ChangeMotionControlFramePeriod(m_handle, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * When trajectory points are processed in the motion profile executer, the MPE determines
+	 * how long to apply the active trajectory point by summing baseTrajDurationMs with the
+	 * timeDur of the trajectory point (see TrajectoryPoint).
+	 *
+	 * This allows general selection of the execution rate of the points with 1ms resolution,
+	 * while allowing some degree of change from point to point.
+	 * @param baseTrajDurationMs The base duration time of every trajectory point.
+	 * 							This is summed with the trajectory points unique timeDur.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configMotionProfileTrajectoryPeriod(int baseTrajDurationMs, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigMotionProfileTrajectoryPeriod(m_handle, baseTrajDurationMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	// ------ error ----------//
+	/**
+	 * Gets the last error generated by this object. Not all functions return an
+	 * error code but can potentially report errors. This function can be used
+	 * to retrieve those error codes.
+	 *
+	 * @return Last Error Code generated by a function.
+	 */
+	public ErrorCode getLastError() {
+		int retval = MotControllerJNI.GetLastError(m_handle);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------ Faults ----------//
+	/**
+	 * Polls the various fault flags.
+	 *
+	 * @param toFill
+	 *            Caller's object to fill with latest fault flags.
+	 * @return Last Error Code generated by a function.
+	 */
+	public ErrorCode getFaults(Faults toFill) {
+		int bits = MotControllerJNI.GetFaults(m_handle);
+		toFill.update(bits);
+		return getLastError();
+	}
+
+	/**
+	 * Polls the various sticky fault flags.
+	 *
+	 * @param toFill
+	 *            Caller's object to fill with latest sticky fault flags.
+	 * @return Last Error Code generated by a function.
+	 */
+	public ErrorCode getStickyFaults(StickyFaults toFill) {
+		int bits = MotControllerJNI.GetStickyFaults(m_handle);
+		toFill.update(bits);
+		return getLastError();
+	}
+
+	/**
+	 * Clears all sticky faults.
+	 *
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Last Error Code generated by a function.
+	 */
+	public ErrorCode clearStickyFaults(int timeoutMs) {
+		int retval = MotControllerJNI.ClearStickyFaults(m_handle, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------ Firmware ----------//
+	/**
+	 * Gets the firmware version of the device.
+	 *
+	 * @return Firmware version of device. For example: version 1-dot-2 is
+	 *         0x0102.
+	 */
+	public int getFirmwareVersion() {
+		return MotControllerJNI.GetFirmwareVersion(m_handle);
+	}
+
+	/**
+	 * Returns true if the device has reset since last call.
+	 *
+	 * @return Has a Device Reset Occurred?
+	 */
+	public boolean hasResetOccurred() {
+		return MotControllerJNI.HasResetOccurred(m_handle);
+	}
+
+	//------ Custom Persistent Params ----------//
+	/**
+	 * Sets the value of a custom parameter. This is for arbitrary use.
+	 *
+	 * Sometimes it is necessary to save calibration/limit/target information in
+	 * the device. Particularly if the device is part of a subsystem that can be
+	 * replaced.
+	 *
+	 * @param newValue
+	 *            Value for custom parameter.
+	 * @param paramIndex
+	 *            Index of custom parameter [0,1]
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigSetCustomParam(m_handle, newValue, paramIndex, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the value of a custom parameter.
+	 *
+	 * @param paramIndex
+	 *            Index of custom parameter [0,1].
+	 * @param timoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Value of the custom param.
+	 */
+	public int configGetCustomParam(int paramIndex, int timoutMs) {
+		int retval = MotControllerJNI.ConfigGetCustomParam(m_handle, paramIndex, timoutMs);
+		return retval;
+	}
+
+	// ------ Generic Param API ----------//
+	/**
+	 * Sets a parameter. Generally this is not used. This can be utilized in -
+	 * Using new features without updating API installation. - Errata
+	 * workarounds to circumvent API implementation. - Allows for rapid testing
+	 * / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
+		return configSetParameter(param.value, value, subValue, ordinal, timeoutMs);
+	}
+	/**
+	 * Sets a parameter.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigSetParameter(m_handle, param,  value, subValue, ordinal,
+				timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Gets a parameter.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Value of parameter.
+	 */
+	public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
+		return configGetParameter(param.value, ordinal, timeoutMs);
+	}
+	/**
+	 * Gets a parameter.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Value of parameter.
+	 */
+	public double configGetParameter(int param, int ordinal, int timeoutMs) {
+		return MotControllerJNI.ConfigGetParameter(m_handle, param, ordinal, timeoutMs);
+	}
+
+	// ------ Misc. ----------//
+	public int getBaseID() {
+		return _arbId;
+	}
+
+	/**
+	 * @return control mode motor controller is in
+	 */
+	public ControlMode getControlMode() {
+		return m_controlMode;
+	}
+
+	// ----- Follower ------//
+	/**
+	 * Set the control mode and output value so that this motor controller will
+	 * follow another motor controller. Currently supports following Victor SPX
+	 * and Talon SRX.
+	 *
+	 * @param masterToFollow
+	 *						Motor Controller object to follow.
+	 * @param followerType
+	 *						Type of following control.  Use AuxOutput1 to follow the master
+	 *						device's auxiliary output 1.
+	 *						Use PercentOutput for standard follower mode.
+	 */
+	public void follow(IMotorController masterToFollow, FollowerType followerType) {
+		int id32 = masterToFollow.getBaseID();
+		int id24 = id32;
+		id24 >>= 16;
+		id24 = (short) id24;
+		id24 <<= 8;
+		id24 |= (id32 & 0xFF);
+		set(ControlMode.Follower, id24);
+
+		switch (followerType){
+			case PercentOutput:
+				set(ControlMode.Follower, (double)id24);
+				break;
+			case AuxOutput1:
+			  /* follow the motor controller, but set the aux flag
+		     * to ensure we follow the processed output */
+			  set(ControlMode.Follower, (double)id24, DemandType.AuxPID, 0);
+				break;
+			default:
+			  neutralOutput();
+				break;
+		}
+	}
+	/**
+	 * Set the control mode and output value so that this motor controller will
+	 * follow another motor controller. Currently supports following Victor SPX
+	 * and Talon SRX.
+	 */
+	public void follow(IMotorController masterToFollow) {
+    follow(masterToFollow, FollowerType.PercentOutput);
+	}
+	/**
+	 * When master makes a device, this routine is called to signal the update.
+	 */
+	public void valueUpdated() {
+		// MT
+	}
+
+	/**
+	 * @return object that can get/set individual raw sensor values.
+	 */
+	public SensorCollection getSensorCollection() {
+		return _sensorColl;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/can/MotControllerJNI.java b/java/src/com/ctre/phoenix/motorcontrol/can/MotControllerJNI.java
new file mode 100644
index 0000000..635ce39
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/can/MotControllerJNI.java
@@ -0,0 +1,762 @@
+package com.ctre.phoenix.motorcontrol.can;
+
+import com.ctre.phoenix.CTREJNIWrapper;
+
+public class MotControllerJNI extends CTREJNIWrapper {
+
+	public static native long Create(int baseArbId);
+
+	/**
+	 * Returns the Device ID
+	 *
+	 * @return Device number.
+	 */
+	public static native int GetDeviceNumber(long handle);
+
+	/**
+	 * Sets the demand (output) of the motor controller.
+	 *
+	 * @param mode
+	 *            Control Mode of the Motor Controller
+	 * @param demand0
+	 *            Primary Demand value
+	 * @param demand1
+	 *            Secondary Demand value
+	 **/
+	public static native void SetDemand(long handle, int mode, int demand0, int demand1);
+
+	/**
+	 * Sets the demand (output) of the motor controller.
+	 **/
+	public static native void Set_4(long handle, int mode, double demand0, double demand1, int demand1Type);
+
+	/**
+	 * Sets the mode of operation during neutral throttle output.
+	 *
+	 * @param neutralMode
+	 *            The desired mode of operation when the Controller output
+	 *            throttle is neutral (ie brake/coast)
+	 **/
+	public static native void SetNeutralMode(long handle, int neutralMode);
+
+	/**
+	 * Sets the phase of the sensor. Use when controller forward/reverse output
+	 * doesn't correlate to appropriate forward/reverse reading of sensor.
+	 *
+	 * @param PhaseSensor
+	 *            Indicates whether to invert the phase of the sensor.
+	 **/
+	public static native void SetSensorPhase(long handle, boolean PhaseSensor);
+
+	/**
+	 * Inverts the output of the motor controller. LEDs, sensor phase, and limit
+	 * switches will also be inverted to match the new forward/reverse
+	 * directions.
+	 *
+	 * @param invert
+	 *            Invert state to set.
+	 **/
+	public static native void SetInverted(long handle, boolean invert);
+
+	/**
+	 * Configures the open-loop ramp rate of throttle output.
+	 *
+	 * @param secondsFromNeutralToFull
+	 *            Minimum desired time to go from neutral to full throttle. A
+	 *            value of '0' will disable the ramp.
+	 * @param timeoutMs
+	 *            Timeout value in ms. Function will generate error if config is
+	 *            not successful within timeout.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigOpenLoopRamp(long handle, double secondsFromNeutralToFull, int timeoutMs);
+
+	/**
+	 * Configures the closed-loop ramp rate of throttle output.
+	 *
+	 * @param secondsFromNeutralToFull
+	 *            Minimum desired time to go from neutral to full throttle. A
+	 *            value of '0' will disable the ramp.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigClosedLoopRamp(long handle, double secondsFromNeutralToFull, int timeoutMs);
+
+	/**
+	 * Configures the forward peak output percentage.
+	 *
+	 * @param percentOut
+	 *            Desired peak output percentage.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigPeakOutputForward(long handle, double percentOut, int timeoutMs);
+
+	/**
+	 * Configures the reverse peak output percentage.
+	 *
+	 * @param percentOut
+	 *            Desired peak output percentage.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigPeakOutputReverse(long handle, double percentOut, int timeoutMs);
+
+	/**
+	 * Configures the forward nominal output percentage.
+	 *
+	 * @param percentOut
+	 *            Nominal (minimum) percent output.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigNominalOutputForward(long handle, double percentOut, int timeoutMs);
+
+	/**
+	 * Configures the reverse nominal output percentage.
+	 *
+	 * @param percentOut
+	 *            Nominal (minimum) percent output.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigNominalOutputReverse(long handle, double percentOut, int timeoutMs);
+
+	/**
+	 * Configures the output deadband percentage.
+	 *
+	 * @param percentDeadband
+	 *            Desired deadband percentage. Minimum is 0.1%, Maximum is 25%.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigNeutralDeadband(long handle, double percentDeadband, int timeoutMs);
+
+	/**
+	 * Configures the Voltage Compensation saturation voltage.
+	 *
+	 * @param voltage
+	 *            TO-DO: Comment me!
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigVoltageCompSaturation(long handle, double voltage, int timeoutMs);
+
+	/**
+	 * Configures the voltage measurement filter.
+	 *
+	 * @param filterWindowSamples
+	 *            Number of samples in the rolling average of voltage
+	 *            measurement.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigVoltageMeasurementFilter(long handle, int filterWindowSamples, int timeoutMs);
+
+	/**
+	 * Enables voltage compensation. If enabled, voltage compensation works in
+	 * all control modes.
+	 *
+	 * @param enable
+	 *            Enable state of voltage compensation.
+	 **/
+	public static native void EnableVoltageCompensation(long handle, boolean enable);
+
+	/**
+	 * Gets the bus voltage seen by the motor controller.
+	 *
+	 * @return The bus voltage value (in volts).
+	 */
+	public static native double GetBusVoltage(long handle);
+
+	/**
+	 * Gets the output percentage of the motor controller.
+	 *
+	 * @return Output of the motor controller (in percent).
+	 */
+	public static native double GetMotorOutputPercent(long handle);
+
+	/**
+	 * Gets the output current of the motor controller.
+	 *
+	 * @return Output current (in amps).
+	 */
+	public static native double GetOutputCurrent(long handle);
+
+	/**
+	 * Gets the temperature of the motor controller.
+	 *
+	 * @return The temperature of the motor controller (in 'C)
+	 */
+	public static native double GetTemperature(long handle);
+
+	/**
+	 * Configures the remote feedback filter.
+	 *
+	 * @param handle
+	 *            handle of device.
+	 * @param deviceID
+	 *            ID of remote device.
+	 * @param remoteSensorSource
+	 *            Type of remote sensor.
+	 * @param remoteOrdinal
+	 *            Ordinal of remote source [0-1].
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigRemoteFeedbackFilter(long handle, int deviceID, int remoteSensorSource,
+			int remoteOrdinal, int timeoutMs);
+
+	/**
+	 * Select the feedback device for the motor controller.
+	 *
+	 * @param feedbackDevice
+	 *            Feedback Device to select.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigSelectedFeedbackSensor(long handle, int feedbackDevice, int pidIdx, int timeoutMs);
+
+	public static native int ConfigSensorTerm(long handle, int sensorTerm, int feedbackDevice, int timeoutMs);
+
+	/**
+	 * Get the selected sensor position.
+	 *
+	 * @return Position of selected sensor (in Raw Sensor Units).
+	 */
+	public static native int GetSelectedSensorPosition(long handle, int pidIdx);
+
+	/**
+	 * Get the selected sensor velocity.
+	 *
+	 * @return Velocity of selected sensor (in Raw Sensor Units per 100 ms).
+	 */
+	public static native int GetSelectedSensorVelocity(long handle, int pidIdx);
+
+	/**
+	 * Sets the sensor position to the given value.
+	 *
+	 * @param sensorPos
+	 *            Position to set for the selected sensor (in Raw Sensor Units).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int SetSelectedSensorPosition(long handle, int sensorPos, int pidIdx, int timeoutMs);
+
+	/**
+	 * Sets the period of the given control frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int SetControlFramePeriod(long handle, int frame, int periodMs);
+
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int SetStatusFramePeriod(long handle, int frame, int periodMs, int timeoutMs);
+
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return The period of the given status frame.
+	 */
+	public static native int GetStatusFramePeriod(long handle, int frame, int timeoutMs);
+
+	/**
+	 * Sets the period over which velocity measurements are taken.
+	 *
+	 * @param period
+	 *            Desired period for the velocity measurement. @see
+	 *            #VelocityMeasPeriod
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigVelocityMeasurementPeriod(long handle, int period, int timeoutMs);
+
+	/**
+	 * Sets the number of velocity samples used in the rolling average velocity
+	 * measurement.
+	 *
+	 * @param windowSize
+	 *            Number of samples in the rolling average of velocity
+	 *            measurement.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigVelocityMeasurementWindow(long handle, int windowSize, int timeoutMs);
+
+	/**
+	 * Configures the forward limit switch for a remote source.
+	 *
+	 * @param type
+	 *            Remote limit switch source. @see #LimitSwitchSource
+	 * @param normalOpenOrClose
+	 *            Setting for normally open or normally closed.
+	 * @param deviceID
+	 *            Device ID of remote source.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigForwardLimitSwitchSource(long handle, int type, int normalOpenOrClose, int deviceID,
+			int timeoutMs);
+
+	/**
+	 * Configures the reverse limit switch for a remote source.
+	 *
+	 * @param type
+	 *            Remote limit switch source. @see #LimitSwitchSource
+	 * @param normalOpenOrClose
+	 *            Setting for normally open or normally closed.
+	 * @param deviceID
+	 *            Device ID of remote source.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigReverseLimitSwitchSource(long handle, int type, int normalOpenOrClose, int deviceID,
+			int timeoutMs);
+
+	/**
+	 * Sets the enable state for limit switches.
+	 *
+	 * @param enable
+	 *            Enable state for limit switches.
+	 **/
+	public static native void OverrideLimitSwitchesEnable(long handle, boolean enable);
+
+	/**
+	 * Configures the forward soft limit.
+	 *
+	 * @param forwardSensorLimit
+	 *            Forward Sensor Position Limit (in Raw Sensor Units).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigForwardSoftLimitThreshold(long handle, int forwardSensorLimit, int timeoutMs);
+
+	/**
+	 * Configures the reverse soft limit.
+	 *
+	 * @param reverseSensorLimit
+	 *            Reverse Sensor Position Limit (in Raw Sensor Units).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigReverseSoftLimitThreshold(long handle, int reverseSensorLimit, int timeoutMs);
+
+	public static native int ConfigForwardSoftLimitEnable(long handle, boolean enable, int timeoutMs);
+
+	public static native int ConfigReverseSoftLimitEnable(long handle, boolean enable, int timeoutMs);
+
+	/**
+	 * Sets the enable state for soft limit switches.
+	 *
+	 * @param enable
+	 *            Enable state for soft limit switches.
+	 **/
+	public static native void OverrideSoftLimitsEnable(long handle, boolean enable);
+
+	/**
+	 * Sets the 'P' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the P constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int Config_kP(long handle, int slotIdx, double value, int timeoutMs);
+
+	/**
+	 * Sets the 'I' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the I constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int Config_kI(long handle, int slotIdx, double value, int timeoutMs);
+
+	/**
+	 * Sets the 'D' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the D constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int Config_kD(long handle, int slotIdx, double value, int timeoutMs);
+
+	/**
+	 * Sets the 'F' constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param value
+	 *            Value of the F constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int Config_kF(long handle, int slotIdx, double value, int timeoutMs);
+
+	/**
+	 * Sets the Integral Zone constant in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param izone
+	 *            Value of the Integral Zone constant.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int Config_IntegralZone(long handle, int slotIdx, double izone, int timeoutMs);
+
+	/**
+	 * Sets the allowable closed-loop error in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param allowableClosedLoopError
+	 *            Value of the allowable closed-loop error.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigAllowableClosedloopError(long handle, int slotIdx, int allowableClosedLoopError,
+			int timeoutMs);
+
+	/**
+	 * Sets the maximum integral accumulator in the given parameter slot.
+	 *
+	 * @param slotIdx
+	 *            Parameter slot for the constant.
+	 * @param iaccum
+	 *            Value of the maximum integral accumulator.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigMaxIntegralAccumulator(long handle, int slotIdx, double iaccum, int timeoutMs);
+
+	/**
+	 * Sets the integral accumulator.
+	 *
+	 * @param iaccum
+	 *            Value to set for the integral accumulator.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @param pidIdx
+	 *            Which closed loop to manipulate. 0 for primary, 1 for auxiliary
+	 *            secondary loop.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int SetIntegralAccumulator(long handle, double iaccum, int pidIdx, int timeoutMs);
+
+	/**
+	 * Gets the closed-loop error.
+	 *
+	 * @param pidIdx
+	 *            Which closed loop to manipulate. 0 for primary, 1 for auxiliary
+	 *            secondary loop.
+	 * @return Closed-loop error value.
+	 */
+	public static native int GetClosedLoopError(long handle, int pidIdx);
+
+	/**
+	 * Gets the iaccum value.
+	 *
+	 * @param pidIdx
+	 *            Which closed loop to manipulate. 0 for primary, 1 for auxiliary
+	 *            secondary loop.
+	 * @return Integral accumulator value.
+	 */
+	public static native double GetIntegralAccumulator(long handle, int pidIdx);
+
+	/**
+	 * Gets the derivative of the closed-loop error.
+	 *
+	 * @param pidIdx
+	 *            Which closed loop to manipulate. 0 for primary, 1 for auxiliary
+	 *            secondary loop.
+	 * @return Error derivative value.
+	 */
+	public static native double GetErrorDerivative(long handle, int pidIdx);
+
+	/**
+	 * Selects which profile slot to use for closed-loop control.
+	 *
+	 * @param slotIdx
+	 *            Profile slot to select.
+	 * @param pidIdx
+	 *            Which closed loop to manipulate. 0 for primary, 1 for auxiliary
+	 *            secondary loop.
+	 **/
+	public static native void SelectProfileSlot(long handle, int slotIdx, int pidIdx);
+
+	public static native int GetActiveTrajectoryPosition(long handle);
+
+	public static native int GetActiveTrajectoryVelocity(long handle);
+
+	public static native double GetActiveTrajectoryHeading(long handle);
+
+	/**
+	 * Sets the Motion Magic Cruise Velocity.
+	 *
+	 * @param sensorUnitsPer100ms
+	 *            Motion Magic Cruise Velocity (in Raw Sensor Units per 100 ms).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigMotionCruiseVelocity(long handle, int sensorUnitsPer100ms, int timeoutMs);
+
+	/**
+	 * Sets the Motion Magic Acceleration.
+	 *
+	 * @param sensorUnitsPer100msPerSec
+	 *            Motion Magic Acceleration (in Raw Sensor Units per 100 ms per
+	 *            second).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigMotionAcceleration(long handle, int sensorUnitsPer100msPerSec, int timeoutMs);
+
+	public static native int ClearMotionProfileTrajectories(long handle);
+
+	public static native int GetMotionProfileTopLevelBufferCount(long handle);
+
+	public static native int PushMotionProfileTrajectory(long handle, double position, double velocity,
+			double headingDeg, int profileSlotSelect, boolean isLastPoint, boolean zeroPos);
+
+	public static native int PushMotionProfileTrajectory2(long handle, double position, double velocity, double headingDeg,
+			int profileSlotSelect0, int profileSlotSelect1, boolean isLastPoint, boolean zeroPos, int durationMs);
+
+	public static native boolean IsMotionProfileTopLevelBufferFull(long handle);
+
+	public static native int ProcessMotionProfileBuffer(long handle);
+
+	public static native int GetMotionProfileStatus(long handle, int[] toFill_9);
+
+	public static native int GetMotionProfileStatus2(long handle, int[] toFill_11);
+
+	public static native int ClearMotionProfileHasUnderrun(long handle, int timeoutMs);
+
+	public static native int ChangeMotionControlFramePeriod(long handle, int periodMs);
+
+	public static native int ConfigMotionProfileTrajectoryPeriod(long handle, int periodMs, int timeoutMs);
+
+	/**
+	 * Gets the last error generated by this object.
+	 *
+	 * @return Last Error Code generated by a function.
+	 */
+	public static native int GetLastError(long handle);
+
+	/**
+	 * Gets the firmware version of the device.
+	 *
+	 * @return Firmware version of device.
+	 */
+	public static native int GetFirmwareVersion(long handle);
+
+	/**
+	 * Returns true if the device has reset.
+	 *
+	 * @return Has a Device Reset Occurred?
+	 */
+	public static native boolean HasResetOccurred(long handle);
+
+	/**
+	 * Sets the value of a custom parameter.
+	 *
+	 * @param newValue
+	 *            Value for custom parameter.
+	 * @param paramIndex
+	 *            Index of custom parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigSetCustomParam(long handle, int newValue, int paramIndex, int timeoutMs);
+
+	/**
+	 * Gets the value of a custom parameter.
+	 *
+	 * @param paramIndex
+	 *            Index of custom parameter.
+	 * @param timoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Value of the custom param.
+	 */
+	public static native int ConfigGetCustomParam(long handle, int paramIndex, int timoutMs);
+
+	/**
+	 * Sets a parameter.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigSetParameter(long handle, int param, double value, int subValue, int ordinal,
+			int timeoutMs);
+
+	/**
+	 * Gets a parameter.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Value of parameter.
+	 */
+	public static native double ConfigGetParameter(long handle, int param, int ordinal, int timeoutMs);
+
+	/**
+	 * Configures the peak current limit of the motor controller.
+	 *
+	 * @param amps
+	 *            Peak current limit (in amps).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigPeakCurrentLimit(long handle, int amps, int timeoutMs);
+
+	/**
+	 * Configures the maximum time allowed at peak current limit of the motor
+	 * controller.
+	 *
+	 * @param milliseconds
+	 *            Maximum time allowed at peak current limit (in milliseconds).
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigPeakCurrentDuration(long handle, int milliseconds, int timeoutMs);
+
+	/**
+	 * Configures the continuous current limit.
+	 *
+	 * @param amps
+	 *            Continuous Current Limit.
+	 * @param timeoutMs
+	 *            Timeout value in ms. @see #ConfigOpenLoopRamp
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public static native int ConfigContinuousCurrentLimit(long handle, int amps, int timeoutMs);
+
+	/**
+	 * Enables the current limit feature.
+	 *
+	 * @param enable
+	 *            Enable state of current limit.
+	 **/
+	public static native int EnableCurrentLimit(long handle, boolean enable);
+
+	public static native int GetAnalogIn(long handle);
+
+	public static native int SetAnalogPosition(long handle, int newPosition, int timeoutMs);
+
+	public static native int GetAnalogInRaw(long handle);
+
+	public static native int GetAnalogInVel(long handle);
+
+	public static native int GetQuadraturePosition(long handle);
+
+	public static native int SetQuadraturePosition(long handle, int newPosition, int timeoutMs);
+
+	public static native int GetQuadratureVelocity(long handle);
+
+	public static native int GetPulseWidthPosition(long handle);
+
+	public static native int SetPulseWidthPosition(long handle, int newPosition, int timeoutMs);
+
+	public static native int GetPulseWidthVelocity(long handle);
+
+	public static native int GetPulseWidthRiseToFallUs(long handle);
+
+	public static native int GetPulseWidthRiseToRiseUs(long handle);
+
+	public static native int GetPinStateQuadA(long handle);
+
+	public static native int GetPinStateQuadB(long handle);
+
+	public static native int GetPinStateQuadIdx(long handle);
+
+	public static native int IsFwdLimitSwitchClosed(long handle);
+
+	public static native int IsRevLimitSwitchClosed(long handle);
+
+	public static native int GetFaults(long handle);
+
+	public static native int GetStickyFaults(long handle);
+
+	public static native int ClearStickyFaults(long handle, int timeoutMs);
+
+	public static native int SelectDemandType(long handle, int enable);
+
+	public static native int SetMPEOutput(long handle, int mpeOutput);
+
+	public static native int EnableHeadingHold(long handle, int enable);
+
+	public static native int GetClosedLoopTarget(long handle, int pidIdx);
+
+	public static native int ConfigSelectedFeedbackCoefficient(long handle, double coefficient, int pidIdx, int timeoutMs);
+
+	public static native int ConfigClosedLoopPeakOutput(long handle, int slotIdx, double percentOut, int timeoutMs);
+
+	public static native int ConfigClosedLoopPeriod(long handle, int slotIdx, int loopTimeMs, int timeoutMs);
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/can/TalonSRX.java b/java/src/com/ctre/phoenix/motorcontrol/can/TalonSRX.java
new file mode 100644
index 0000000..1bbc149
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/can/TalonSRX.java
@@ -0,0 +1,232 @@
+package com.ctre.phoenix.motorcontrol.can;
+import com.ctre.phoenix.ErrorCode;
+import com.ctre.phoenix.motorcontrol.IMotorControllerEnhanced;
+import com.ctre.phoenix.motorcontrol.LimitSwitchNormal;
+import com.ctre.phoenix.motorcontrol.LimitSwitchSource;
+import com.ctre.phoenix.motorcontrol.StatusFrameEnhanced;
+import com.ctre.phoenix.motorcontrol.VelocityMeasPeriod;
+import com.ctre.phoenix.motorcontrol.can.MotControllerJNI;
+
+import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
+import edu.wpi.first.wpilibj.hal.HAL;
+/**
+ * CTRE Talon SRX Motor Controller when used on CAN Bus.
+ */
+public class TalonSRX extends com.ctre.phoenix.motorcontrol.can.BaseMotorController
+		implements IMotorControllerEnhanced {
+
+	public TalonSRX(int deviceNumber) {
+		super(deviceNumber | 0x02040000);
+		HAL.report(tResourceType.kResourceType_CANTalonSRX, deviceNumber + 1);
+	}
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * User ensure CAN Bus utilization is not high.
+	 *
+	 * This setting is not persistent and is lost when device is reset.
+	 * If this is a concern, calling application can use HasReset()
+	 * to determine if the status frame needs to be reconfigured.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(StatusFrameEnhanced frame, int periodMs, int timeoutMs) {
+		return super.setStatusFramePeriod(frame.value, periodMs, timeoutMs);
+	}
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Period of the given status frame.
+	 */
+	public int getStatusFramePeriod(StatusFrameEnhanced frame, int timeoutMs) {
+
+		return super.getStatusFramePeriod(frame, timeoutMs);
+	}
+	/**
+	 * Configures the period of each velocity sample.
+	 * Every 1ms a position value is sampled, and the delta between that sample
+	 * and the position sampled kPeriod ms ago is inserted into a filter.
+	 * kPeriod is configured with this function.
+	 *
+	 * @param period
+	 *            Desired period for the velocity measurement. @see
+	 *            #VelocityMeasPeriod
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVelocityMeasurementPeriod(VelocityMeasPeriod period, int timeoutMs) {
+		return super.configVelocityMeasurementPeriod(period, timeoutMs);
+	}
+	/**
+	 * Sets the number of velocity samples used in the rolling average velocity
+	 * measurement.
+	 *
+	 * @param windowSize
+	 *            Number of samples in the rolling average of velocity
+	 *            measurement. Valid values are 1,2,4,8,16,32. If another
+	 *            value is specified, it will truncate to nearest support value.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs) {
+		return super.configVelocityMeasurementWindow(windowSize, timeoutMs);
+	}
+	/**
+	 * Configures a limit switch for a local/remote source.
+	 *
+	 * For example, a CAN motor controller may need to monitor the Limit-R pin
+	 * of another Talon, CANifier, or local Gadgeteer feedback connector.
+	 *
+	 * If the sensor is remote, a device ID of zero is assumed.
+	 * If that's not desired, use the four parameter version of this function.
+	 *
+	 * @param type
+	 *            Limit switch source.
+	 *            User can choose between the feedback connector, remote Talon SRX, CANifier, or deactivate the feature.
+	 * @param normalOpenOrClose
+	 *            Setting for normally open, normally closed, or disabled. This setting
+	 *            matches the web-based configuration drop down.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for
+	 *            config success and report an error if it times out.
+	 *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configForwardLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int timeoutMs) {
+
+		return super.configForwardLimitSwitchSource(type.value, normalOpenOrClose.value, 0x00000000, timeoutMs);
+	}
+	/**
+	 * Configures a limit switch for a local/remote source.
+	 *
+	 * For example, a CAN motor controller may need to monitor the Limit-R pin
+	 * of another Talon, CANifier, or local Gadgeteer feedback connector.
+	 *
+	 * If the sensor is remote, a device ID of zero is assumed. If that's not
+	 * desired, use the four parameter version of this function.
+	 *
+	 * @param type
+	 *            Limit switch source. @see #LimitSwitchSource User can choose
+	 *            between the feedback connector, remote Talon SRX, CANifier, or
+	 *            deactivate the feature.
+	 * @param normalOpenOrClose
+	 *            Setting for normally open, normally closed, or disabled. This
+	 *            setting matches the web-based configuration drop down.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configReverseLimitSwitchSource(LimitSwitchSource type, LimitSwitchNormal normalOpenOrClose,
+			int timeoutMs) {
+		return super.configReverseLimitSwitchSource(type.value, normalOpenOrClose.value, 0x00000000, timeoutMs);
+	}
+
+	// ------ Current Lim ----------//
+	/**
+	 * Configure the peak allowable current (when current limit is enabled).
+	 * 
+	 * Current limit is activated when current exceeds the peak limit for longer
+	 * than the peak duration. Then software will limit to the continuous limit.
+	 * This ensures current limiting while allowing for momentary excess current
+	 * events.
+	 *
+	 * For simpler current-limiting (single threshold) use
+	 * ConfigContinuousCurrentLimit() and set the peak to zero:
+	 * ConfigPeakCurrentLimit(0).
+	 * 
+	 * @param amps
+	 *            Amperes to limit.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 */
+	public ErrorCode configPeakCurrentLimit(int amps, int timeoutMs) {
+		int retval =  MotControllerJNI.ConfigPeakCurrentLimit(m_handle, amps, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configure the peak allowable duration (when current limit is enabled).
+	 *
+	 * Current limit is activated when current exceeds the peak limit for longer
+	 * than the peak duration. Then software will limit to the continuous limit.
+	 * This ensures current limiting while allowing for momentary excess current
+	 * events.
+	 *
+	 * For simpler current-limiting (single threshold) use
+	 * ConfigContinuousCurrentLimit() and set the peak to zero:
+	 * ConfigPeakCurrentLimit(0).
+	 * 
+	 * @param milliseconds
+	 *            How long to allow current-draw past peak limit.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 */
+	public ErrorCode configPeakCurrentDuration(int milliseconds, int timeoutMs) {
+		int retval = MotControllerJNI.ConfigPeakCurrentDuration(m_handle, milliseconds, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Configure the continuous allowable current-draw (when current limit is
+	 * enabled).
+	 *
+	 * Current limit is activated when current exceeds the peak limit for longer
+	 * than the peak duration. Then software will limit to the continuous limit.
+	 * This ensures current limiting while allowing for momentary excess current
+	 * events.
+	 *
+	 * For simpler current-limiting (single threshold) use
+	 * ConfigContinuousCurrentLimit() and set the peak to zero:
+	 * ConfigPeakCurrentLimit(0).
+	 * 
+	 * @param amps
+	 *            Amperes to limit.
+	 * @param timeoutMs
+	 *            Timeout value in ms. If nonzero, function will wait for config
+	 *            success and report an error if it times out. If zero, no
+	 *            blocking or checking is performed.
+	 */
+	public ErrorCode configContinuousCurrentLimit(int amps, int timeoutMs) {
+		int retval =  MotControllerJNI.ConfigContinuousCurrentLimit(m_handle, amps, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Enable or disable Current Limit.
+	 * 
+	 * @param enable
+	 *            Enable state of current limit.
+	 * @see ConfigPeakCurrentLimit, ConfigPeakCurrentDuration,
+	 *      ConfigContinuousCurrentLimit
+	 */
+	public void enableCurrentLimit(boolean enable) {
+		MotControllerJNI.EnableCurrentLimit(m_handle, enable);
+	}
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/can/VictorSPX.java b/java/src/com/ctre/phoenix/motorcontrol/can/VictorSPX.java
new file mode 100644
index 0000000..5bf8313
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/can/VictorSPX.java
@@ -0,0 +1,21 @@
+package com.ctre.phoenix.motorcontrol.can;
+
+import com.ctre.phoenix.motorcontrol.IMotorController;
+
+import edu.wpi.first.wpilibj.hal.HAL;
+/**
+ * VEX Victor SPX Motor Controller when used on CAN Bus.
+ */
+public class VictorSPX extends com.ctre.phoenix.motorcontrol.can.BaseMotorController
+    implements IMotorController {
+	/**
+	 * Constructor
+	 * 
+	 * @param deviceNumber
+	 *            [0,62]
+	 */
+	public VictorSPX(int deviceNumber) {
+		super(deviceNumber | 0x01040000);
+		HAL.report(65, deviceNumber + 1);
+	}
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/can/WPI_TalonSRX.java b/java/src/com/ctre/phoenix/motorcontrol/can/WPI_TalonSRX.java
new file mode 100644
index 0000000..5fd93f2
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/can/WPI_TalonSRX.java
@@ -0,0 +1,231 @@
+/**
+ * WPI Compliant motor controller class.
+ * WPILIB's object model requires many interfaces to be implemented to use
+ * the various features.
+ * This includes...
+ * - Software PID loops running in the robot controller
+ * - LiveWindow/Test mode features
+ * - Motor Safety (auto-turn off of motor if Set stops getting called)
+ * - Single Parameter set that assumes a simple motor controller.
+ */
+package com.ctre.phoenix.motorcontrol.can;
+
+import edu.wpi.first.wpilibj.SpeedController;
+import edu.wpi.first.wpilibj.livewindow.LiveWindow;
+import com.ctre.phoenix.motorcontrol.ControlMode;
+import edu.wpi.first.wpilibj.MotorSafety;
+import edu.wpi.first.wpilibj.MotorSafetyHelper;
+import edu.wpi.first.wpilibj.Sendable;
+import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
+import edu.wpi.first.wpilibj.hal.HAL;
+
+public class WPI_TalonSRX extends TalonSRX implements SpeedController, Sendable, MotorSafety {
+
+	private String _description;
+	private double _speed;
+	private MotorSafetyHelper _safetyHelper;
+
+	/** Constructor */
+	public WPI_TalonSRX(int deviceNumber) {
+		super(deviceNumber);
+		HAL.report(66, deviceNumber + 1);
+		_description = "Talon SRX " + deviceNumber;
+		/* prep motor safety */
+		_safetyHelper = new MotorSafetyHelper(this);
+		_safetyHelper.setExpiration(0.0);
+		_safetyHelper.setSafetyEnabled(false);
+
+		LiveWindow.add(this);
+		setName("Talon SRX ", deviceNumber);
+	}
+
+	// ------ set/get routines for WPILIB interfaces ------//
+	@Override
+	public void set(double speed) {
+		_speed = speed;
+		set(ControlMode.PercentOutput, _speed);
+		_safetyHelper.feed();
+	}
+
+	@Override
+	public void pidWrite(double output) {
+		set(output);
+	}
+
+	/**
+	 * Common interface for getting the current set speed of a speed controller.
+	 *
+	 * @return The current set speed. Value is between -1.0 and 1.0.
+	 */
+	@Override
+	public double get() {
+		return _speed;
+	}
+
+	// ---------Intercept CTRE calls for motor safety ---------//
+	public void set(ControlMode mode, double value) {
+		/* intercept the advanced Set and feed motor-safety */
+		super.set(mode, value);
+		_safetyHelper.feed();
+	}
+
+	public void set(ControlMode mode, double demand0, double demand1) {
+		/* intercept the advanced Set and feed motor-safety */
+		super.set(mode, demand0, demand1);
+		_safetyHelper.feed();
+	}
+
+	// ----------------------- Invert routines -------------------//
+	@Override
+	public void setInverted(boolean isInverted) {
+		super.setInverted(isInverted);
+	}
+
+	@Override
+	public boolean getInverted() {
+		return super.getInverted();
+	}
+
+	// ----------------------- turn-motor-off routines-------------------//
+	@Override
+	public void disable() {
+		neutralOutput();
+	}
+
+	/**
+	 * Common interface to stop the motor until Set is called again.
+	 */
+	@Override
+	public void stopMotor() {
+		neutralOutput();
+	}
+	// -------- Motor Safety--------//
+
+	/**
+	 * Set the safety expiration time.
+	 *
+	 * @param timeout
+	 *            The timeout (in seconds) for this motor object
+	 */
+	@Override
+	public void setExpiration(double timeout) {
+		_safetyHelper.setExpiration(timeout);
+	}
+
+	/**
+	 * Return the safety expiration time.
+	 *
+	 * @return The expiration time value.
+	 */
+	@Override
+	public double getExpiration() {
+		return _safetyHelper.getExpiration();
+	}
+
+	/**
+	 * Check if the motor is currently alive or stopped due to a timeout.
+	 *
+	 * @return a bool value that is true if the motor has NOT timed out and
+	 *         should still be running.
+	 */
+	@Override
+	public boolean isAlive() {
+		return _safetyHelper.isAlive();
+	}
+
+	/**
+	 * Check if motor safety is enabled.
+	 *
+	 * @return True if motor safety is enforced for this object
+	 */
+	@Override
+	public boolean isSafetyEnabled() {
+		return _safetyHelper.isSafetyEnabled();
+	}
+
+	@Override
+	public void setSafetyEnabled(boolean enabled) {
+		_safetyHelper.setSafetyEnabled(enabled);
+	}
+
+	// ---- essentially a copy of SendableBase -------//
+	private String m_name = "";
+	private String m_subsystem = "Ungrouped";
+
+	/**
+	 * Free the resources used by this object.
+	 */
+	public void free() {
+		LiveWindow.remove(this);
+	}
+
+	@Override
+	public final synchronized String getName() {
+		return m_name;
+	}
+
+	@Override
+	public final synchronized void setName(String name) {
+		m_name = name;
+	}
+
+	/**
+	 * Sets the name of the sensor with a channel number.
+	 *
+	 * @param moduleType
+	 *            A string that defines the module name in the label for the
+	 *            value
+	 * @param channel
+	 *            The channel number the device is plugged into
+	 */
+	protected final void setName(String moduleType, int channel) {
+		setName(moduleType + "[" + channel + "]");
+	}
+
+	/**
+	 * Sets the name of the sensor with a module and channel number.
+	 *
+	 * @param moduleType
+	 *            A string that defines the module name in the label for the
+	 *            value
+	 * @param moduleNumber
+	 *            The number of the particular module type
+	 * @param channel
+	 *            The channel number the device is plugged into (usually PWM)
+	 */
+	protected final void setName(String moduleType, int moduleNumber, int channel) {
+		setName(moduleType + "[" + moduleNumber + "," + channel + "]");
+	}
+
+	@Override
+	public final synchronized String getSubsystem() {
+		return m_subsystem;
+	}
+
+	@Override
+	public final synchronized void setSubsystem(String subsystem) {
+		m_subsystem = subsystem;
+	}
+
+	/**
+	 * Add a child component.
+	 *
+	 * @param child
+	 *            child component
+	 */
+	protected final void addChild(Object child) {
+		LiveWindow.addChild(this, child);
+	}
+
+	@Override
+	public void initSendable(SendableBuilder builder) {
+		builder.setSmartDashboardType("Speed Controller");
+		builder.setSafeState(this::stopMotor);
+		builder.addDoubleProperty("Value", this::get, this::set);
+	}
+
+	@Override
+	public String getDescription() {
+		return _description;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/motorcontrol/can/WPI_VictorSPX.java b/java/src/com/ctre/phoenix/motorcontrol/can/WPI_VictorSPX.java
new file mode 100644
index 0000000..9c7436f
--- /dev/null
+++ b/java/src/com/ctre/phoenix/motorcontrol/can/WPI_VictorSPX.java
@@ -0,0 +1,231 @@
+/**
+ * WPI Compliant motor controller class.
+ * WPILIB's object model requires many interfaces to be implemented to use
+ * the various features.
+ * This includes...
+ * - Software PID loops running in the robot controller
+ * - LiveWindow/Test mode features
+ * - Motor Safety (auto-turn off of motor if Set stops getting called)
+ * - Single Parameter set that assumes a simple motor controller.
+ */
+package com.ctre.phoenix.motorcontrol.can;
+
+import edu.wpi.first.wpilibj.SpeedController;
+import edu.wpi.first.wpilibj.livewindow.LiveWindow;
+import com.ctre.phoenix.motorcontrol.ControlMode;
+import edu.wpi.first.wpilibj.MotorSafety;
+import edu.wpi.first.wpilibj.MotorSafetyHelper;
+import edu.wpi.first.wpilibj.Sendable;
+import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
+import edu.wpi.first.wpilibj.hal.HAL;
+
+public class WPI_VictorSPX extends VictorSPX implements SpeedController, Sendable, MotorSafety {
+
+	private String _description;
+	private double _speed;
+	private MotorSafetyHelper _safetyHelper;
+
+	/** Constructor */
+	public WPI_VictorSPX(int deviceNumber) {
+		super(deviceNumber);
+		HAL.report(67, deviceNumber + 1);
+		_description = "Victor SPX " + deviceNumber;
+		/* prep motor safety */
+		_safetyHelper = new MotorSafetyHelper(this);
+		_safetyHelper.setExpiration(0.0);
+		_safetyHelper.setSafetyEnabled(false);
+
+		LiveWindow.add(this);
+		setName("Victor SPX ", deviceNumber);
+	}
+
+	// ------ set/get routines for WPILIB interfaces ------//
+	@Override
+	public void set(double speed) {
+		_speed = speed;
+		set(ControlMode.PercentOutput, _speed);
+		_safetyHelper.feed();
+	}
+
+	@Override
+	public void pidWrite(double output) {
+		set(output);
+	}
+
+	/**
+	 * Common interface for getting the current set speed of a speed controller.
+	 *
+	 * @return The current set speed. Value is between -1.0 and 1.0.
+	 */
+	@Override
+	public double get() {
+		return _speed;
+	}
+
+	// ---------Intercept CTRE calls for motor safety ---------//
+	public void set(ControlMode mode, double value) {
+		/* intercept the advanced Set and feed motor-safety */
+		super.set(mode, value);
+		_safetyHelper.feed();
+	}
+
+	public void set(ControlMode mode, double demand0, double demand1) {
+		/* intercept the advanced Set and feed motor-safety */
+		super.set(mode, demand0, demand1);
+		_safetyHelper.feed();
+	}
+
+	// ----------------------- Invert routines -------------------//
+	@Override
+	public void setInverted(boolean isInverted) {
+		super.setInverted(isInverted);
+	}
+
+	@Override
+	public boolean getInverted() {
+		return super.getInverted();
+	}
+
+	// ----------------------- turn-motor-off routines-------------------//
+	@Override
+	public void disable() {
+		neutralOutput();
+	}
+
+	/**
+	 * Common interface to stop the motor until Set is called again.
+	 */
+	@Override
+	public void stopMotor() {
+		neutralOutput();
+	}
+	// -------- Motor Safety--------//
+
+	/**
+	 * Set the safety expiration time.
+	 *
+	 * @param timeout
+	 *            The timeout (in seconds) for this motor object
+	 */
+	@Override
+	public void setExpiration(double timeout) {
+		_safetyHelper.setExpiration(timeout);
+	}
+
+	/**
+	 * Return the safety expiration time.
+	 *
+	 * @return The expiration time value.
+	 */
+	@Override
+	public double getExpiration() {
+		return _safetyHelper.getExpiration();
+	}
+
+	/**
+	 * Check if the motor is currently alive or stopped due to a timeout.
+	 *
+	 * @return a bool value that is true if the motor has NOT timed out and
+	 *         should still be running.
+	 */
+	@Override
+	public boolean isAlive() {
+		return _safetyHelper.isAlive();
+	}
+
+	/**
+	 * Check if motor safety is enabled.
+	 *
+	 * @return True if motor safety is enforced for this object
+	 */
+	@Override
+	public boolean isSafetyEnabled() {
+		return _safetyHelper.isSafetyEnabled();
+	}
+
+	@Override
+	public void setSafetyEnabled(boolean enabled) {
+		_safetyHelper.setSafetyEnabled(enabled);
+	}
+
+	// ---- essentially a copy of SendableBase -------//
+	private String m_name = "";
+	private String m_subsystem = "Ungrouped";
+
+	/**
+	 * Free the resources used by this object.
+	 */
+	public void free() {
+		LiveWindow.remove(this);
+	}
+
+	@Override
+	public final synchronized String getName() {
+		return m_name;
+	}
+
+	@Override
+	public final synchronized void setName(String name) {
+		m_name = name;
+	}
+
+	/**
+	 * Sets the name of the sensor with a channel number.
+	 *
+	 * @param moduleType
+	 *            A string that defines the module name in the label for the
+	 *            value
+	 * @param channel
+	 *            The channel number the device is plugged into
+	 */
+	protected final void setName(String moduleType, int channel) {
+		setName(moduleType + "[" + channel + "]");
+	}
+
+	/**
+	 * Sets the name of the sensor with a module and channel number.
+	 *
+	 * @param moduleType
+	 *            A string that defines the module name in the label for the
+	 *            value
+	 * @param moduleNumber
+	 *            The number of the particular module type
+	 * @param channel
+	 *            The channel number the device is plugged into (usually PWM)
+	 */
+	protected final void setName(String moduleType, int moduleNumber, int channel) {
+		setName(moduleType + "[" + moduleNumber + "," + channel + "]");
+	}
+
+	@Override
+	public final synchronized String getSubsystem() {
+		return m_subsystem;
+	}
+
+	@Override
+	public final synchronized void setSubsystem(String subsystem) {
+		m_subsystem = subsystem;
+	}
+
+	/**
+	 * Add a child component.
+	 *
+	 * @param child
+	 *            child component
+	 */
+	protected final void addChild(Object child) {
+		LiveWindow.addChild(this, child);
+	}
+
+	@Override
+	public void initSendable(SendableBuilder builder) {
+		builder.setSmartDashboardType("Speed Controller");
+		builder.setSafeState(this::stopMotor);
+		builder.addDoubleProperty("Value", this::get, this::set);
+	}
+
+	@Override
+	public String getDescription() {
+		return _description;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/schedulers/ConcurrentScheduler.java b/java/src/com/ctre/phoenix/schedulers/ConcurrentScheduler.java
new file mode 100644
index 0000000..bfc0a5d
--- /dev/null
+++ b/java/src/com/ctre/phoenix/schedulers/ConcurrentScheduler.java
@@ -0,0 +1,95 @@
+package com.ctre.phoenix.schedulers;
+import java.util.ArrayList;
+
+import com.ctre.phoenix.ILoopable;
+
+public class ConcurrentScheduler implements ILoopable {
+	ArrayList<ILoopable> _loops = new ArrayList<ILoopable>();
+	ArrayList<Boolean> _enabs = new ArrayList<Boolean>();
+
+	public void add(ILoopable aLoop, boolean enable) {
+		_loops.add(aLoop);
+		_enabs.add(enable);
+	}
+	public void add(ILoopable aLoop) {
+		add(aLoop, true);
+	}
+
+	public void removeAll() {
+		_loops.clear();
+		_enabs.clear();
+	}
+
+	public void start(ILoopable toStart) {
+		for (int i = 0; i < _loops.size(); ++i) {
+			ILoopable lp = (ILoopable) _loops.get(i);
+
+			if (lp == toStart) {
+				_enabs.set(i, true);
+				lp.onStart();
+				return;
+			}
+		}
+
+	}
+
+	public void stop(ILoopable toStop) {
+		for (int i = 0; i < (int) _loops.size(); ++i) {
+			ILoopable lp = (ILoopable) _loops.get(i);
+
+			if (lp == toStop) {
+				_enabs.set(i, false);
+				lp.onStop();
+				return;
+			}
+		}
+	}
+
+	public void startAll() { // All Loops
+
+		for (ILoopable loop : _loops) {
+			loop.onStart();
+		}
+		for (int i = 0; i < _enabs.size(); ++i) {
+			_enabs.set(i,  true);
+		}
+	}
+
+	public void stopAll() { // All Loops
+		for (ILoopable loop : _loops) {
+			loop.onStop();
+		}
+		for (int i = 0; i < _enabs.size(); ++i) {
+			_enabs.set(i,  false);
+		}
+	}
+
+	public void process() {
+		for (int i = 0; i < (int) _loops.size(); ++i) {
+			ILoopable loop = (ILoopable) _loops.get(i);
+			boolean en = (boolean) _enabs.get(i);
+			if (en) {
+				loop.onLoop();
+			} else {
+				/* Current ILoopable is turned off, don't call onLoop for it */
+			}
+		}
+	}
+
+	/* ILoopable */
+	public void onStart() {
+		startAll();
+	}
+
+	public void onLoop() {
+		process();
+	}
+
+	public void onStop() {
+		stopAll();
+	}
+
+	public boolean isDone() {
+		return false;
+	}
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/schedulers/SequentialScheduler.java b/java/src/com/ctre/phoenix/schedulers/SequentialScheduler.java
new file mode 100644
index 0000000..ba2b238
--- /dev/null
+++ b/java/src/com/ctre/phoenix/schedulers/SequentialScheduler.java
@@ -0,0 +1,97 @@
+package com.ctre.phoenix.schedulers;
+import java.util.ArrayList;
+
+public class SequentialScheduler implements com.ctre.phoenix.ILoopable
+{
+	boolean _running = false;
+	ArrayList<com.ctre.phoenix.ILoopable> _loops = new ArrayList<com.ctre.phoenix.ILoopable>();
+	int _periodMs;
+	int _idx;
+	boolean _iterated = false;
+
+	public SequentialScheduler(int periodMs)
+	{
+		_periodMs = periodMs;
+	}
+	public void add(com.ctre.phoenix.ILoopable aLoop)
+	{
+		_loops.add(aLoop);
+	}
+
+	public com.ctre.phoenix.ILoopable getCurrent()
+	{
+		return null;
+	}
+
+	public void removeAll()
+	{
+		_loops.clear();
+	}
+
+	public void start()
+	{
+		_idx = 0;
+		if(_loops.size() > 0)
+			_loops.get(0).onStart();
+		
+		_running = true;
+	}
+	public void stop()
+	{
+		for (int i = 0; i < _loops.size(); i++)
+		{
+			_loops.get(i).onStop();
+		}
+		_running = false;
+	}
+	public void process()
+	{
+		_iterated = false;
+		if (_idx < _loops.size())
+		{
+			if (_running)
+			{
+				com.ctre.phoenix.ILoopable loop = _loops.get(_idx);
+				loop.onLoop();
+				if (loop.isDone())
+				{
+					_iterated = true;
+					++_idx;
+					if (_idx < _loops.size()) _loops.get(_idx).onStart();
+				}
+			}
+		}
+		else
+		{
+			_running = false;
+		}
+	}
+	public boolean iterated()
+	{
+		return _iterated;
+	}
+	//--- Loopable ---/
+	public void onStart()
+	{
+		start();
+	}
+
+	public void onLoop()
+	{
+		process();
+	}
+
+	public boolean isDone()
+	{
+		/* Have to return something to know if we are done */
+		if (_running == false)
+			return true;
+		else
+			return false;
+	}
+
+	public void onStop()
+	{
+		stop();
+	}
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/sensors/PigeonIMU.java b/java/src/com/ctre/phoenix/sensors/PigeonIMU.java
new file mode 100644
index 0000000..981b457
--- /dev/null
+++ b/java/src/com/ctre/phoenix/sensors/PigeonIMU.java
@@ -0,0 +1,908 @@
+/*
+ *  Software License Agreement
+ *
+ * Copyright (C) Cross The Road Electronics.  All rights
+ * reserved.
+ *
+ * Cross The Road Electronics (CTRE) licenses to you the right to
+ * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and Software
+ * API Libraries ONLY when in use with Cross The Road Electronics hardware products.
+ *
+ * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
+ * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
+ * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
+ * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
+ * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
+ * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE
+ */
+package com.ctre.phoenix.sensors;
+import com.ctre.phoenix.ErrorCode;
+import com.ctre.phoenix.ParamEnum;
+import com.ctre.phoenix.motorcontrol.can.TalonSRX;
+
+import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
+import edu.wpi.first.wpilibj.hal.HAL;
+
+/**
+ * Pigeon IMU Class. Class supports communicating over CANbus and over
+ * ribbon-cable (CAN Talon SRX).
+ */
+public class PigeonIMU {
+	private long m_handle;
+
+	/** Data object for holding fusion information. */
+	public static class FusionStatus {
+		public double heading;
+		public boolean bIsValid;
+		public boolean bIsFusing;
+
+		/**
+		 * Same as getLastError()
+		 */
+		public ErrorCode lastError;
+
+		public String toString() {
+			String description;
+			if (lastError != ErrorCode.OK) {
+				description = "Could not receive status frame.  Check wiring and web-config.";
+			} else if (bIsValid == false) {
+				description = "Fused Heading is not valid.";
+			} else if (bIsFusing == false) {
+				description = "Fused Heading is valid.";
+			} else {
+				description = "Fused Heading is valid and is fusing compass.";
+			}
+			return description;
+		}
+	}
+
+	/** Various calibration modes supported by Pigeon. */
+	public enum CalibrationMode {
+		BootTareGyroAccel(0), Temperature(1), Magnetometer12Pt(2), Magnetometer360(3), Accelerometer(5), Unknown(-1);
+		public final int value;
+
+		private CalibrationMode(int initValue) {
+			this.value = initValue;
+		}
+
+		public static CalibrationMode valueOf(int value) {
+			for (CalibrationMode e : CalibrationMode.values()) {
+				if (e.value == value) {
+					return e;
+				}
+			}
+			return Unknown;
+		}
+	};
+
+	/** Overall state of the Pigeon. */
+	public enum PigeonState {
+		NoComm(0), Initializing(1), Ready(2), UserCalibration(3), Unknown(-1);
+		public final int value;
+
+		private PigeonState(int initValue) {
+			this.value = initValue;
+		}
+
+		public static PigeonState valueOf(int value) {
+			for (PigeonState e : PigeonState.values()) {
+				if (e.value == value) {
+					return e;
+				}
+			}
+			return Unknown;
+		}
+	};
+
+	/**
+	 * Data object for status on current calibration and general status.
+	 *
+	 * Pigeon has many calibration modes supported for a variety of uses. The
+	 * modes generally collects and saves persistently information that makes
+	 * the Pigeon signals more accurate. This includes collecting temperature,
+	 * gyro, accelerometer, and compass information.
+	 *
+	 * For FRC use-cases, typically compass and temperature calibration is not
+	 * required.
+	 *
+	 * Additionally when motion driver software in the Pigeon boots, it will
+	 * perform a fast boot calibration to initially bias gyro and setup
+	 * accelerometer.
+	 *
+	 * These modes can be enabled with the EnterCalibration mode.
+	 *
+	 * When a calibration mode is entered, caller can expect...
+	 *
+	 * - PigeonState to reset to Initializing and bCalIsBooting is set to true.
+	 * Pigeon LEDs will blink the boot pattern. This is similar to the normal
+	 * boot cal, however it can an additional ~30 seconds since calibration
+	 * generally requires more information. currentMode will reflect the user's
+	 * selected calibration mode.
+	 *
+	 * - PigeonState will eventually settle to UserCalibration and Pigeon LEDs
+	 * will show cal specific blink patterns. bCalIsBooting is now false.
+	 *
+	 * - Follow the instructions in the Pigeon User Manual to meet the
+	 * calibration specific requirements. When finished calibrationError will
+	 * update with the result. Pigeon will solid-fill LEDs with red (for
+	 * failure) or green (for success) for ~5 seconds. Pigeon then perform
+	 * boot-cal to cleanly apply the newly saved calibration data.
+	 */
+	public static class GeneralStatus {
+		/**
+		 * The current state of the motion driver. This reflects if the sensor
+		 * signals are accurate. Most calibration modes will force Pigeon to
+		 * reinit the motion driver.
+		 */
+		public PigeonState state;
+		/**
+		 * The currently applied calibration mode if state is in UserCalibration
+		 * or if bCalIsBooting is true. Otherwise it holds the last selected
+		 * calibration mode (when calibrationError was updated).
+		 */
+		public CalibrationMode currentMode;
+		/**
+		 * The error code for the last calibration mode. Zero represents a
+		 * successful cal (with solid green LEDs at end of cal) and nonzero is a
+		 * failed calibration (with solid red LEDs at end of cal). Different
+		 * calibration
+		 */
+		public int calibrationError;
+		/**
+		 * After caller requests a calibration mode, pigeon will perform a
+		 * boot-cal before entering the requested mode. During this period, this
+		 * flag is set to true.
+		 */
+		public boolean bCalIsBooting;
+		/**
+		 * Temperature in Celsius
+		 */
+		public double tempC;
+		/**
+		 * Number of seconds Pigeon has been up (since boot). This register is
+		 * reset on power boot or processor reset. Register is capped at 255
+		 * seconds with no wrap around.
+		 */
+		public int upTimeSec;
+		/**
+		 * Number of times the Pigeon has automatically rebiased the gyro. This
+		 * counter overflows from 15 -> 0 with no cap.
+		 */
+		public int noMotionBiasCount;
+		/**
+		 * Number of times the Pigeon has temperature compensated the various
+		 * signals. This counter overflows from 15 -> 0 with no cap.
+		 */
+		public int tempCompensationCount;
+		/**
+		 * Same as getLastError()
+		 */
+		public ErrorCode lastError;
+
+		/**
+		 * general string description of current status
+		 */
+		public String toString() {
+			String description;
+			/* build description string */
+			if (lastError != ErrorCode.OK) { // same as NoComm
+				description = "Status frame was not received, check wired connections and web-based config.";
+			} else if (bCalIsBooting) {
+				description = "Pigeon is boot-caling to properly bias accel and gyro.  Do not move Pigeon.  When finished biasing, calibration mode will start.";
+			} else if (state == PigeonState.UserCalibration) {
+				/* mode specific descriptions */
+				switch (currentMode) {
+				case BootTareGyroAccel:
+					description = "Boot-Calibration: Gyro and Accelerometer are being biased.";
+					break;
+				case Temperature:
+					description = "Temperature-Calibration: Pigeon is collecting temp data and will finish when temp range is reached. \n";
+					description += "Do not move Pigeon.";
+					break;
+				case Magnetometer12Pt:
+					description = "Magnetometer Level 1 calibration: Orient the Pigeon PCB in the 12 positions documented in the User's Manual.";
+					break;
+				case Magnetometer360:
+					description = "Magnetometer Level 2 calibration: Spin robot slowly in 360' fashion.  ";
+					break;
+				case Accelerometer:
+					description = "Accelerometer Calibration: Pigeon PCB must be placed on a level source.  Follow User's Guide for how to level surfacee.  ";
+					break;
+				default:
+				case Unknown:
+					description = "Unknown status";
+					break;
+				}
+			} else if (state == PigeonState.Ready) {
+				/*
+				 * definitely not doing anything cal-related. So just instrument
+				 * the motion driver state
+				 */
+				description = "Pigeon is running normally.  Last CAL error code was ";
+				description += Integer.toString(calibrationError);
+				description += ".";
+			} else if (state == PigeonState.Initializing) {
+				/*
+				 * definitely not doing anything cal-related. So just instrument
+				 * the motion driver state
+				 */
+				description = "Pigeon is boot-caling to properly bias accel and gyro.  Do not move Pigeon.";
+			} else {
+				description = "Not enough data to determine status.";
+			}
+			return description;
+		}
+	};
+
+	private int m_deviceNumber = 0;
+
+	private double[] _generalStatus = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	private double[] _fusionStatus = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+	/**
+	 * Create a Pigeon object that communicates with Pigeon on CAN Bus.
+	 *
+	 * @param deviceNumber
+	 *            CAN Device Id of Pigeon [0,62]
+	 */
+	public PigeonIMU(int deviceNumber) {
+		m_handle = PigeonImuJNI.JNI_new_PigeonImu(deviceNumber);
+		m_deviceNumber = deviceNumber;
+		HAL.report(tResourceType.kResourceType_PigeonIMU, m_deviceNumber + 1);
+	}
+
+	/**
+	 * Create a Pigeon object that communciates with Pigeon through the
+	 * Gadgeteer ribbon cable connected to a Talon on CAN Bus.
+	 *
+	 * @param talonSrx
+	 *            Object for the TalonSRX connected via ribbon cable.
+	 */
+	public PigeonIMU(TalonSRX talonSrx) {
+		m_deviceNumber = talonSrx.getDeviceID();
+		m_handle = PigeonImuJNI.JNI_new_PigeonImu_Talon(m_deviceNumber);
+		HAL.report(tResourceType.kResourceType_PigeonIMU, m_deviceNumber + 1);
+		HAL.report(64, m_deviceNumber + 1);
+	}
+
+	/**
+	 * Sets the Yaw register to the specified value.
+	 *
+	 * @param angleDeg  Degree of Yaw [+/- 23040 degrees]
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setYaw(double angleDeg, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetYaw(m_handle, angleDeg, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Atomically add to the Yaw register.
+	 *
+	 * @param angleDeg  Degrees to add to the Yaw register.
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode addYaw(double angleDeg, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_AddYaw(m_handle, angleDeg, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the Yaw register to match the current compass value.
+	 *
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setYawToCompass(int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetYawToCompass(m_handle, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the Fused Heading to the specified value.
+	 *
+	 * @param angleDeg  Degree of heading [+/- 23040 degrees]
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setFusedHeading(double angleDeg, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetFusedHeading(m_handle, angleDeg, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Atomically add to the Fused Heading register.
+	 *
+	 * @param angleDeg  Degrees to add to the Fused Heading register.
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode addFusedHeading(double angleDeg, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_AddFusedHeading(m_handle, angleDeg, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the Fused Heading register to match the current compass value.
+	 *
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setFusedHeadingToCompass(int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetFusedHeadingToCompass(m_handle, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the AccumZAngle.
+	 *
+	 * @param angleDeg  Degrees to set AccumZAngle to.
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setAccumZAngle(double angleDeg, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetAccumZAngle(m_handle, angleDeg, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Enable/Disable Temp compensation. Pigeon defaults with this on at boot.
+	 *
+	 * @param bTempCompEnable Set to "True" to enable temperature compensation.
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configTemperatureCompensationEnable(boolean bTempCompEnable, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_ConfigTemperatureCompensationEnable(m_handle, bTempCompEnable ? 1 : 0, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Set the declination for compass. Declination is the difference between
+	 * Earth Magnetic north, and the geographic "True North".
+	 *
+	 * @param angleDegOffset  Degrees to set Compass Declination to.
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setCompassDeclination(double angleDegOffset, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetCompassDeclination(m_handle, angleDegOffset, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Sets the compass angle. Although compass is absolute [0,360) degrees, the
+	 * continuous compass register holds the wrap-arounds.
+	 *
+	 * @param angleDeg  Degrees to set continuous compass angle to.
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setCompassAngle(double angleDeg, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetCompassAngle(m_handle, angleDeg, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ----------------------- Calibration routines -----------------------//
+	/**
+	 * Enters the Calbration mode.  See the Pigeon IMU documentation for More
+	 * information on Calibration.
+	 *
+	 * @param calMode  Calibration to execute
+	 * @param timeoutMs
+   *            Timeout value in ms. If nonzero, function will wait for
+   *            config success and report an error if it times out.
+   *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode enterCalibrationMode(CalibrationMode calMode, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_EnterCalibrationMode(m_handle, calMode.value, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Get the status of the current (or previousley complete) calibration.
+	 *
+	 * @param toFill Container for the status information.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode getGeneralStatus(GeneralStatus toFill) {
+		int retval = PigeonImuJNI.JNI_GetGeneralStatus(m_handle, _generalStatus);
+		toFill.state = PigeonState.valueOf((int) _generalStatus[0]);
+		toFill.currentMode = CalibrationMode.valueOf((int) _generalStatus[1]);
+		toFill.calibrationError = (int) _generalStatus[2];
+		toFill.bCalIsBooting = _generalStatus[3] != 0;
+		toFill.tempC = _generalStatus[4];
+		toFill.upTimeSec = (int) _generalStatus[5];
+		toFill.noMotionBiasCount = (int) _generalStatus[6];
+		toFill.tempCompensationCount = (int) _generalStatus[7];
+		toFill.lastError = ErrorCode.valueOf(retval);
+		return toFill.lastError;
+	}
+
+	// ----------------------- General Error status -----------------------//
+	/**
+	 * Call GetLastError() generated by this object.
+	 * Not all functions return an error code but can
+	 * potentially report errors.
+	 *
+	 * This function can be used to retrieve those error codes.
+	 *
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getLastError() {
+		int retval = PigeonImuJNI.JNI_GetLastError(m_handle);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ----------------------- Strongly typed Signal decoders
+	// -----------------------//
+	/**
+	 * Get 6d Quaternion data.
+	 *
+	 * @param wxyz Array to fill with quaternion data w[0], x[1], y[2], z[3]
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode get6dQuaternion(double[] wxyz) {
+		int retval = PigeonImuJNI.JNI_Get6dQuaternion(m_handle, wxyz);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get Yaw, Pitch, and Roll data.
+	 *
+	 * @param ypr_deg Array to fill with yaw[0], pitch[1], and roll[2] data
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getYawPitchRoll(double[] ypr_deg) {
+		int retval = PigeonImuJNI.JNI_GetYawPitchRoll(m_handle, ypr_deg);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get AccumGyro data.
+	 * AccumGyro is the integrated gyro value on each axis.
+	 *
+	 * @param xyz_deg Array to fill with x[0], y[1], and z[2] AccumGyro data
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getAccumGyro(double[] xyz_deg) {
+		int retval = PigeonImuJNI.JNI_GetAccumGyro(m_handle, xyz_deg);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Get the absolute compass heading.
+	 * @return compass heading [0,360) degrees.
+	 */
+	public double getAbsoluteCompassHeading() {
+		double retval = PigeonImuJNI.JNI_GetAbsoluteCompassHeading(m_handle);
+		return retval;
+	}
+
+	/**
+	 * Get the continuous compass heading.
+	 * @return continuous compass heading [-23040, 23040) degrees. Use
+	 *         SetCompassHeading to modify the wrap-around portion.
+	 */
+	public double getCompassHeading() {
+		double retval = PigeonImuJNI.JNI_GetCompassHeading(m_handle);
+		return retval;
+	}
+
+	/**
+	 * Gets the compass' measured magnetic field strength.
+	 * @return field strength in Microteslas (uT).
+	 */
+	public double getCompassFieldStrength() {
+		double retval = PigeonImuJNI.JNI_GetCompassFieldStrength(m_handle);
+		return retval;
+	}
+	/**
+	 * Gets the temperature of the pigeon.
+	 *
+	 * @return Temperature in ('C)
+	 */
+	public double getTemp() {
+		double retval = PigeonImuJNI.JNI_GetTemp(m_handle);
+		return retval;
+	}
+
+	/**
+	 * Gets the current Pigeon state
+	 *
+	 * @return PigeonState enum
+	 */
+	public PigeonState getState() {
+		int retval = PigeonImuJNI.JNI_GetState(m_handle);
+		return PigeonState.valueOf(retval);
+	}
+
+	/**
+	 * Gets the current Pigeon uptime.
+	 *
+	 * @return How long has Pigeon been running in whole seconds. Value caps at
+	 *         255.
+	 */
+	public int getUpTime() {
+		int retval = PigeonImuJNI.JNI_GetUpTime(m_handle);
+		return retval;
+	}
+	/**
+	 * Get Raw Magnetometer data.
+	 *
+	 * @param rm_xyz Array to fill with x[0], y[1], and z[2] data
+	 * 				Number is equal to 0.6 microTeslas per unit.
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getRawMagnetometer(short[] rm_xyz) {
+		int retval = PigeonImuJNI.JNI_GetRawMagnetometer(m_handle, rm_xyz);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get Biased Magnetometer data.
+	 *
+	 * @param bm_xyz Array to fill with x[0], y[1], and z[2] data
+	 * 				Number is equal to 0.6 microTeslas per unit.
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getBiasedMagnetometer(short[] bm_xyz) {
+		int retval = PigeonImuJNI.JNI_GetBiasedMagnetometer(m_handle, bm_xyz);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get Biased Accelerometer data.
+	 *
+	 * @param ba_xyz Array to fill with x[0], y[1], and z[2] data.
+	 * 			These are in fixed point notation Q2.14.  eg. 16384 = 1G
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getBiasedAccelerometer(short[] ba_xyz) {
+		int retval = PigeonImuJNI.JNI_GetBiasedAccelerometer(m_handle, ba_xyz);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get Raw Gyro data.
+	 *
+	 * @param xyz_dps Array to fill with x[0], y[1], and z[2] data in degrees per second.
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getRawGyro(double[] xyz_dps) {
+		int retval = PigeonImuJNI.JNI_GetRawGyro(m_handle, xyz_dps);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get Accelerometer tilt angles.
+	 *
+	 * @param tiltAngles Array to fill with x[0], y[1], and z[2] angles in degrees.
+	 * @return The last ErrorCode generated.
+	 */
+	public ErrorCode getAccelerometerAngles(double[] tiltAngles) {
+		int retval = PigeonImuJNI.JNI_GetAccelerometerAngles(m_handle, tiltAngles);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Get the current Fusion Status (including fused heading)
+	 *
+	 * @param toFill 	object reference to fill with fusion status flags.
+	 *					Caller may pass null if flags are not needed.
+	 * @return The fused heading in degrees.
+	 */
+	public double getFusedHeading(FusionStatus toFill) {
+		int errorCode = PigeonImuJNI.JNI_GetFusedHeading(m_handle, _fusionStatus);
+
+		if (toFill != null) {
+			toFill.heading = _fusionStatus[0];
+			toFill.bIsFusing = (_fusionStatus[1] != 0);
+			toFill.bIsValid = (_fusionStatus[2] != 0);
+			toFill.lastError = ErrorCode.valueOf(errorCode);
+		}
+
+		return _fusionStatus[0];
+	}
+	/**
+	 * Gets the Fused Heading
+	 *
+	 * @return The fused heading in degrees.
+	 */
+	public double getFusedHeading() {
+		PigeonImuJNI.JNI_GetFusedHeading(m_handle, _fusionStatus);
+
+		return _fusionStatus[0];
+	}
+
+	/**
+	 * Gets the firmware version of the device.
+	 *
+	 * @return param holds the firmware version of the device. Device must be powered
+	 * cycled at least once.
+	 */
+	public int getFirmwareVersion() {
+		int k = PigeonImuJNI.JNI_GetFirmwareVersion(m_handle);
+		return k;
+	}
+
+	/**
+	 * @return true iff a reset has occurred since last call.
+	 */
+	public boolean hasResetOccurred() {
+		boolean k = PigeonImuJNI.JNI_HasResetOccurred(m_handle);
+		return k;
+	}
+
+	/**
+	 * Sets the value of a custom parameter. This is for arbitrary use.
+   *
+   * Sometimes it is necessary to save calibration/declination/offset
+   * information in the device. Particularly if the
+   * device is part of a subsystem that can be replaced.
+	 *
+	 * @param newValue
+	 *            Value for custom parameter.
+	 * @param paramIndex
+	 *            Index of custom parameter. [0-1]
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_ConfigSetCustomParam(m_handle, newValue, paramIndex, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the value of a custom parameter. This is for arbitrary use.
+   *
+   * Sometimes it is necessary to save calibration/declination/offset
+   * information in the device. Particularly if the
+   * device is part of a subsystem that can be replaced.
+	 *
+	 * @param paramIndex
+	 *            Index of custom parameter. [0-1]
+	 * @param timoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Value of the custom param.
+	 */
+	public int configGetCustomParam(int paramIndex, int timoutMs) {
+		int retval = PigeonImuJNI.JNI_ConfigGetCustomParam(m_handle, paramIndex, timoutMs);
+		return retval;
+	}
+
+	/**
+	 * Sets a parameter. Generally this is not used.
+   * This can be utilized in
+   * - Using new features without updating API installation.
+   * - Errata workarounds to circumvent API implementation.
+   * - Allows for rapid testing / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
+		return configSetParameter(param.value, value, subValue, ordinal, timeoutMs);
+	}
+	/**
+	 * Sets a parameter. Generally this is not used.
+   * This can be utilized in
+   * - Using new features without updating API installation.
+   * - Errata workarounds to circumvent API implementation.
+   * - Allows for rapid testing / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param value
+	 *            Value of parameter.
+	 * @param subValue
+	 *            Subvalue for parameter. Maximum value of 255.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_ConfigSetParameter(m_handle, param, value, subValue, ordinal,
+				timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Gets a parameter. Generally this is not used.
+   * This can be utilized in
+   * - Using new features without updating API installation.
+   * - Errata workarounds to circumvent API implementation.
+   * - Allows for rapid testing / unit testing of firmware.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Value of parameter.
+	 */
+	public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
+		return configGetParameter(param.value, ordinal, timeoutMs);
+	}
+	/**
+	 * Gets a parameter.
+	 *
+	 * @param param
+	 *            Parameter enumeration.
+	 * @param ordinal
+	 *            Ordinal of parameter.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Value of parameter.
+	 */
+	public double configGetParameter(int param, int ordinal, int timeoutMs) {
+		return PigeonImuJNI.JNI_ConfigGetParameter(m_handle, param, ordinal, timeoutMs);
+	}
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * @param statusFrame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(PigeonIMU_StatusFrame statusFrame, int periodMs, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame.value, periodMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the period of the given status frame.
+	 *
+	 * @param statusFrame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setStatusFramePeriod(int statusFrame, int periodMs, int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame, periodMs, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * Gets the period of the given status frame.
+	 *
+	 * @param frame
+	 *            Frame to get the period of.
+	 * @param timeoutMs
+ *            Timeout value in ms. If nonzero, function will wait for
+ *            config success and report an error if it times out.
+ *            If zero, no blocking or checking is performed.
+	 * @return Period of the given status frame.
+	 */
+	public int getStatusFramePeriod(PigeonIMU_StatusFrame frame, int timeoutMs) {
+		return PigeonImuJNI.JNI_GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
+	}
+	/**
+	 * Sets the period of the given control frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setControlFramePeriod(PigeonIMU_ControlFrame frame, int periodMs) {
+		int retval = PigeonImuJNI.JNI_SetControlFramePeriod(m_handle, frame.value, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+	/**
+	 * Sets the period of the given control frame.
+	 *
+	 * @param frame
+	 *            Frame whose period is to be changed.
+	 * @param periodMs
+	 *            Period in ms for the given frame.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode setControlFramePeriod(int frame, int periodMs) {
+		int retval = PigeonImuJNI.JNI_SetControlFramePeriod(m_handle, frame, periodMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	// ------ Faults ----------//
+	/**
+	 * Gets the fault status
+	 *
+	 * @param toFill
+	 *            Container for fault statuses.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode getFaults(PigeonIMU_Faults toFill) {
+		int bits = PigeonImuJNI.JNI_GetFaults(m_handle);
+		toFill.update(bits);
+		return getLastError();
+	}
+	/**
+	 * Gets the sticky fault status
+	 *
+	 * @param toFill
+	 *            Container for sticky fault statuses.
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode getStickyFaults(PigeonIMU_StickyFaults toFill) {
+		int bits = PigeonImuJNI.JNI_GetStickyFaults(m_handle);
+		toFill.update(bits);
+		return getLastError();
+	}
+	/**
+	 * Clears the Sticky Faults
+	 *
+	 * @return Error Code generated by function. 0 indicates no error.
+	 */
+	public ErrorCode clearStickyFaults(int timeoutMs) {
+		int retval = PigeonImuJNI.JNI_ClearStickyFaults(m_handle, timeoutMs);
+		return ErrorCode.valueOf(retval);
+	}
+
+	/**
+	 * @return The Device Number
+	 */
+	public int getDeviceID(){
+		return m_deviceNumber;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/sensors/PigeonIMU_ControlFrame.java b/java/src/com/ctre/phoenix/sensors/PigeonIMU_ControlFrame.java
new file mode 100644
index 0000000..21ee565
--- /dev/null
+++ b/java/src/com/ctre/phoenix/sensors/PigeonIMU_ControlFrame.java
@@ -0,0 +1,21 @@
+package com.ctre.phoenix.sensors;
+
+/** Enumerated type for control frame types. */
+public enum PigeonIMU_ControlFrame {
+	Control_1(0x00042800);
+
+	public final int value;
+
+	PigeonIMU_ControlFrame(int initValue) {
+		this.value = initValue;
+	}
+
+	public static PigeonIMU_ControlFrame valueOf(int value) {
+		for (PigeonIMU_ControlFrame mode : values()) {
+			if (mode.value == value) {
+				return mode;
+			}
+		}
+		return null;
+	}
+}
diff --git a/java/src/com/ctre/phoenix/sensors/PigeonIMU_Faults.java b/java/src/com/ctre/phoenix/sensors/PigeonIMU_Faults.java
new file mode 100644
index 0000000..8628608
--- /dev/null
+++ b/java/src/com/ctre/phoenix/sensors/PigeonIMU_Faults.java
@@ -0,0 +1,16 @@
+package com.ctre.phoenix.sensors;
+
+public class PigeonIMU_Faults {
+	//!< True iff any of the above flags are true.
+	public boolean hasAnyFault() {
+		return false;
+	}
+	public int toBitfield() {
+		int retval = 0;
+		return retval;
+	}
+	public void update(int bits) {
+	}
+	public PigeonIMU_Faults() {
+	}
+};
diff --git a/java/src/com/ctre/phoenix/sensors/PigeonIMU_StatusFrame.java b/java/src/com/ctre/phoenix/sensors/PigeonIMU_StatusFrame.java
new file mode 100644
index 0000000..cec0b94
--- /dev/null
+++ b/java/src/com/ctre/phoenix/sensors/PigeonIMU_StatusFrame.java
@@ -0,0 +1,33 @@
+package com.ctre.phoenix.sensors;
+
+/**
+ * Enumerated types for frame rate ms.
+ */
+public enum PigeonIMU_StatusFrame {
+	CondStatus_1_General(0x042000), 
+	CondStatus_9_SixDeg_YPR(0x042200), 
+	CondStatus_6_SensorFusion(0x042140), 
+	CondStatus_11_GyroAccum(0x042280), 
+	CondStatus_2_GeneralCompass(0x042040), 
+	CondStatus_3_GeneralAccel(0x042080), 
+	CondStatus_10_SixDeg_Quat(0x042240), 
+	RawStatus_4_Mag(0x041CC0), 
+	BiasedStatus_2_Gyro(0x041C40), 
+	BiasedStatus_4_Mag(0x041CC0), 
+	BiasedStatus_6_Accel(0x41D40);
+
+	public final int value;
+
+	PigeonIMU_StatusFrame(int initValue) {
+		this.value = initValue;
+	}
+
+	public static PigeonIMU_StatusFrame valueOf(int value) {
+		for (PigeonIMU_StatusFrame mode : values()) {
+			if (mode.value == value) {
+				return mode;
+			}
+		}
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/sensors/PigeonIMU_StickyFaults.java b/java/src/com/ctre/phoenix/sensors/PigeonIMU_StickyFaults.java
new file mode 100644
index 0000000..77a99e2
--- /dev/null
+++ b/java/src/com/ctre/phoenix/sensors/PigeonIMU_StickyFaults.java
@@ -0,0 +1,16 @@
+package com.ctre.phoenix.sensors;
+
+public class PigeonIMU_StickyFaults {
+	//!< True iff any of the above flags are true.
+	public boolean hasAnyFault() {
+		return false;
+	}
+	public int toBitfield() {
+		int retval = 0;
+		return retval;
+	}
+	public void update(int bits) {
+	}
+	public PigeonIMU_StickyFaults() {
+	}
+};
diff --git a/java/src/com/ctre/phoenix/sensors/PigeonImuJNI.java b/java/src/com/ctre/phoenix/sensors/PigeonImuJNI.java
new file mode 100644
index 0000000..11932d8
--- /dev/null
+++ b/java/src/com/ctre/phoenix/sensors/PigeonImuJNI.java
@@ -0,0 +1,118 @@
+/*
+ *  Software License Agreement
+ *
+ * Copyright (C) Cross The Road Electronics.  All rights
+ * reserved.
+ * 
+ * Cross The Road Electronics (CTRE) licenses to you the right to 
+ * use, publish, and distribute copies of CRF (Cross The Road) firmware files ( *.crf) and Software
+ * API Libraries ONLY when in use with Cross The Road Electronics hardware products.
+ * 
+ * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
+ * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL, 
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
+ * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
+ * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
+ * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
+ * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE
+ */
+package com.ctre.phoenix.sensors;
+import com.ctre.phoenix.CTREJNIWrapper;
+
+
+public class PigeonImuJNI extends CTREJNIWrapper {
+  
+	public static native long JNI_new_PigeonImu_Talon(int talonID);
+
+	public static native long JNI_new_PigeonImu(int deviceNumber);
+
+	public static native int JNI_ConfigSetCustomParam(long handle, int newValue, int paramIndex, int timeoutMs);
+
+	public static native int JNI_ConfigGetCustomParam(long handle, int paramIndex, int timoutMs);
+
+	public static native int JNI_ConfigSetParameter(long handle, int param, double value, int subValue, int ordinal,
+			int timeoutMs);
+
+	public static native double JNI_ConfigGetParameter(long handle, int param, int ordinal, int timeoutMs);
+
+	public static native int JNI_SetStatusFramePeriod(long handle, int statusFrame, int periodMs, int timeoutMs);
+
+	public static native int JNI_SetYaw(long handle, double angleDeg, int timeoutMs);
+
+	public static native int JNI_AddYaw(long handle, double angleDeg, int timeoutMs);
+	
+	public static native int JNI_SetYawToCompass(long handle, int timeoutMs);
+	
+	public static native int JNI_SetFusedHeading(long handle, double angleDeg, int timeoutMs);
+	
+	public static native int JNI_AddFusedHeading(long handle, double angleDeg, int timeoutMs);
+	
+	public static native int JNI_SetFusedHeadingToCompass(long handle, int timeoutMs);
+	
+	public static native int JNI_SetAccumZAngle(long handle, double angleDeg, int timeoutMs);
+	
+	public static native int JNI_ConfigTemperatureCompensationEnable(long handle, int bTempCompEnable, int timeoutMs);
+	
+	public static native int JNI_SetCompassDeclination(long handle, double angleDegOffset, int timeoutMs);
+	
+	public static native int JNI_SetCompassAngle(long handle, double angleDeg, int timeoutMs);
+	
+	public static native int JNI_EnterCalibrationMode(long handle, int calMode, int timeoutMs);
+	  
+	public static native int JNI_GetGeneralStatus(long handle, double [] params);
+	
+	public static native int JNI_Get6dQuaternion(long handle, double [] wxyz );
+	
+	public static native int JNI_GetYawPitchRoll(long handle, double [] ypr);
+	
+	public static native int JNI_GetAccumGyro(long handle, double [] xyz_deg);
+	
+	public static native double JNI_GetAbsoluteCompassHeading(long handle);
+	
+	public static native double JNI_GetCompassHeading(long handle);
+	
+	public static native double JNI_GetCompassFieldStrength(long handle);
+	
+	public static native double JNI_GetTemp(long handle);
+	
+	public static native int JNI_GetUpTime(long handle);
+	
+	public static native int JNI_GetRawMagnetometer(long handle, short [] rm_xyz);
+	
+	public static native int JNI_GetBiasedMagnetometer(long handle, short [] bm_xyz);
+	
+	public static native int JNI_GetBiasedAccelerometer(long handle, short [] ba_xyz);
+	
+	public static native int JNI_GetRawGyro(long handle, double [] xyz_dps);
+	
+	public static native int JNI_GetAccelerometerAngles(long handle, double [] tiltAngles);
+	  
+	public static native int JNI_GetFusedHeading(long handle, double [] params);
+	  
+	public static native int JNI_GetState(long handle);
+	
+	public static native int JNI_GetResetCount(long handle);
+	
+	public static native int JNI_GetResetFlags(long handle);
+	
+	public static native int JNI_GetFirmwareVersion(long handle);
+	  
+	public static native int JNI_GetLastError(long handle);
+	  
+	public static native boolean JNI_HasResetOccurred(long handle);
+	
+	public static native int JNI_GetStatusFramePeriod(long handle, int frame, int timeoutMs);
+
+	public static native int JNI_SetControlFramePeriod(long handle, int frame, int periodMs);
+
+	public static native int JNI_GetFaults(long handle);
+
+	public static native int JNI_GetStickyFaults(long handle);
+
+	public static native int JNI_ClearStickyFaults(long handle, int timeoutMs);
+	
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/signals/IInvertable.java b/java/src/com/ctre/phoenix/signals/IInvertable.java
new file mode 100644
index 0000000..e30a48d
--- /dev/null
+++ b/java/src/com/ctre/phoenix/signals/IInvertable.java
@@ -0,0 +1,7 @@
+package com.ctre.phoenix.signals;
+
+public interface IInvertable
+{
+	void setInverted(boolean invert);
+	boolean getInverted();
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/signals/IOutputSignal.java b/java/src/com/ctre/phoenix/signals/IOutputSignal.java
new file mode 100644
index 0000000..13e6ced
--- /dev/null
+++ b/java/src/com/ctre/phoenix/signals/IOutputSignal.java
@@ -0,0 +1,6 @@
+package com.ctre.phoenix.signals;
+
+public interface IOutputSignal
+{
+	//void set(double value);
+}
\ No newline at end of file
diff --git a/java/src/com/ctre/phoenix/time/StopWatch.java b/java/src/com/ctre/phoenix/time/StopWatch.java
new file mode 100644
index 0000000..fc41340
--- /dev/null
+++ b/java/src/com/ctre/phoenix/time/StopWatch.java
@@ -0,0 +1,25 @@
+package com.ctre.phoenix.time;
+
+public class StopWatch
+{
+	private long _t0 = 0;
+	private long _t1 = 0;
+	
+	public void start()
+	{
+		_t0 = System.currentTimeMillis();
+	}
+	
+	public double getDuration()
+	{
+		return (double)getDurationMs() / 1000;
+	}
+	public int getDurationMs()
+	{
+		_t1 = System.currentTimeMillis();
+		long retval = _t1 - _t0;
+		if(retval < 0)
+			retval = 0;
+		return (int)retval;
+	}
+}
\ No newline at end of file