#
# This file is autogenerated, do not edit manually. Instead,
# edit gen/MotController_data.yml
#

import typing

from hal_impl.data import hal_data, NotifyDict

from .ctre_sim_enums import ErrorCode

from .ctre_sim_enums import ControlMode, DemandType, FeedbackDevice, LimitSwitchSource, ParamEnum
from wpilib import Notifier

_feedback2key = {
   FeedbackDevice.QuadEncoder: 'quad_',
   FeedbackDevice.Analog: 'analog_',
   FeedbackDevice.PulseWidthEncodedPosition: 'pulse_width_',
 }


class MotController:

    def __init__(self):
        self.create_called = False

    def _create1(self, baseArbId: int) -> None:
        assert isinstance(baseArbId, int)
        self.create_called = True

        deviceId = baseArbId & 0xFFFF
        deviceType = (baseArbId >> 16) & 0xFFFF
        if deviceType == 0x0104:
          deviceType = 'victorspx'
        elif deviceType == 0x0204:
          deviceType = 'talonsrx'
        else:
          raise ValueError("Invalid device id `%s`" % deviceType)
          
        self._deviceId = deviceId

        self.hal_data = NotifyDict({
          'type': deviceType,
          'sim_display': False, # used in sim
          
          'sensor_phase': False,
          'temp': 0.0,
          'bus_voltage': 12.0,
          'output_current': 0.1,
          
          'inverted': False,
          'last_error': ErrorCode.OK,
          
          # Configuration
          'voltage_comp_saturation': 0,
          'voltage_measurement_filter': 0,
          'voltage_comp_enabled': False,
          
          'current_limit_peak': 0,
          'current_peak_duration': 0,
          'current_limit_continuous': 0,
          'current_limit_enabled': False,
          
          'peak_fwd_output': 1.0,
          'peak_rev_output': -1.0,
          'nom_fwd_output': 0.0,
          'nom_rev_output': 0.0,
          'neutral_deadband': 0.0,
          
          'sensor_term': (0, 0),
          
          'vel_measurement_period': 0,
          'vel_measurement_window': 0,
          
          # Quadrature encoder data
          'quad_position': 0,
          'quad_velocity': 0,
          'quad_pin_a': 0,
          'quad_pin_b': 0,
          'quad_pin_idx': 0,
          
          # Analog position data
          'analog_position': 0,
          'analog_velocity': 0,
          'analog_in_raw': 0,
          'analog_in': 0,
          
          # Pulse width position data
          'pulse_width_position': 0,
          'pulse_width_velocity': 0,
          'pulse_width_rise_to_rise': 0,
          'pulse_width_rise_to_fall': 0,
          
          # Soft limits
          'soft_limit_usable': True,
          'soft_limit_for': 0,
          'soft_limit_for_enable': False,
          'soft_limit_rev': 0,
          'soft_limit_rev_enable': False,
          
          # Hard limits
          'limit_switch_usable': True,
          'limit_switch_closed_for': False,
          'limit_switch_closed_rev': False,
          
          # Remote limit switches?
          'limit_switch_source_for': LimitSwitchSource.Deactivated,
          'limit_switch_source_rev': LimitSwitchSource.Deactivated,
          'limit_switch_follow_for': deviceId,
          'limit_switch_follow_rev': deviceId,

          'clear_pos_on_limit_fwd': 0,
          'clear_pos_on_limit_rev': 0,
          
          # These two values are set when the set()/setDemand() functions are called
          'control_mode': 0,
          'value': 0.0, # percent throttle
          
          'neutral_mode': self.NeutralMode.EEPROMSetting,
          
          'follow_target': 0,
          'followers': set(),
          'open_loop_ramp': 0.0,
          'closed_loop_ramp': 0.0,
          
          # PIDF parameters
          'profile0_p': 0.0,
          'profile0_i': 0.0,
          'profile0_d': 0.0,
          'profile0_f': 0.0,
          'profile0_izone': 0.0,
          'profile0_allowableError': 0,
          'profile0_max_iaccum': 0.0,
          'profile0_peakOutput': 1.0,
          'profile0_period': 0.001,
          
          'profile1_p': 0.0,
          'profile1_i': 0.0,
          'profile1_d': 0.0,
          'profile1_f': 0.0,
          'profile1_izone': 0.0,
          'profile1_allowableError': 0,
          'profile1_max_iaccum': 0.0,
          'profile1_peakOutput': 1.0,
          'profile1_period': 0.001,
          
          # PIDF stored computations
          # -> 0/1 refers to pidIdx
          'pid0_iaccum': 0.0,
          'pid0_error': 0,
          'pid0_prevErr': 0,
          'pid0_errorDerivative': 0.0,
          'pid0_feedback': FeedbackDevice.None_,
          'pid0_notFirst': False,
          'pid0_outBeforRmp': 0,
          'pid0_target': 0,
          'pid0_coefficient': 1.0,
          
          'pid1_iaccum': 0.0,
          'pid1_error': 0,
          'pid1_prevErr': 0,
          'pid1_errorDerivative': 0.0,
          'pid1_feedback': FeedbackDevice.None_,
          'pid1_notFirst': False,
          'pid1_outBeforRmp': 0,
          'pid1_target': 0,
          'pid1_coefficient': 1.0,
          
          # slotIdx
          'profile_slot_select': 0,
          # pidIdx
          'pid_slot_select': 0,
          
          # motion magic parameters
          'motionmagic_cruise_velocity': 0,
          'motionmagic_acceleration': 0,
          'motionmagic_target': 0,
          'motionmagic_velocity': 0,
          
        })

        hal_data['CAN'][deviceId] = self.hal_data

        self._notifier = None

    def getDeviceNumber(self) -> int:
        retval = self._deviceId
        assert isinstance(retval, int)
        return retval

    def setDemand(self, mode: int, demand0: int, demand1: int) -> ErrorCode:
        assert isinstance(mode, int)
        assert isinstance(demand0, int)
        assert isinstance(demand1, int)
        retval = ErrorCode.OK
        if self.hal_data['control_mode'] == ControlMode.Follower and mode != ControlMode.Follower:
            follow_target = self.hal_data['follow_target']
            hal_data['CAN'][follow_target]['followers'].remove(self._deviceId)

        calc_modes = [
            ControlMode.MotionMagic, ControlMode.Position,
            ControlMode.Velocity, ControlMode.Current]
        prev_mode = self.hal_data['control_mode']
        if mode in calc_modes and prev_mode not in calc_modes:
            if self.Notifier and self._notifier is None:
                self._notifier = Notifier(self._calculate_1ms)
            if self._notifier is not None:
                self._notifier.startPeriodic(0.001)
        elif mode not in calc_modes and prev_mode in calc_modes:
            if self._notifier is not None:
                self._notifier.stop()

        self.hal_data['control_mode'] = mode
        if mode == ControlMode.PercentOutput:
            self._out = demand0
        elif mode == ControlMode.Follower:
            follow_target = demand0 & 0xFF
            assert follow_target != self._deviceId
            self.hal_data['follow_target'] = follow_target
            hal_data['CAN'][follow_target]['followers'].add(self._deviceId)
            self.hal_data['value'] = hal_data['CAN'][follow_target]['value']
        elif mode == ControlMode.MotionMagic:
            self.hal_data['motionmagic_target'] = demand0
            if prev_mode != ControlMode.MotionMagic:
                assert self.hal_data['motionmagic_acceleration'] != 0
                assert self.hal_data['motionmagic_cruise_velocity'] != 0
                self._target = self.getSelectedSensorPosition(self._pidIdx)
                self.hal_data['motionmagic_velocity'] = self.getSelectedSensorVelocity(self._pidIdx)
        elif mode in calc_modes:
            self._target = demand0
        else:
            self.hal_data['value'] = demand0

        for follower_id in self.hal_data['followers']:
            hal_data['CAN'][follower_id]['value'] = self.hal_data['value']
        assert isinstance(retval, ErrorCode)
        return retval

    def _set_4(self, mode: int, demand0: float, demand1: float, demand1Type: int) -> ErrorCode:
        assert isinstance(mode, int)
        assert isinstance(demand0, (int, float))
        assert isinstance(demand1, (int, float))
        assert isinstance(demand1Type, int)
        retval = ErrorCode.OK
        if mode == ControlMode.PercentOutput:
            demand0 = int(1023 * demand0)
        self.setDemand(mode, int(demand0), int(demand1))
        assert isinstance(retval, ErrorCode)
        return retval

    def setNeutralMode(self, neutralMode: int) -> None:
        '''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)

        '''
        assert isinstance(neutralMode, int)
        self.hal_data['neutral_mode'] = neutralMode

    def setSensorPhase(self, PhaseSensor: bool) -> None:
        '''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.

        '''
        assert isinstance(PhaseSensor, bool)
        self.hal_data['sensor_phase'] = PhaseSensor

    def setInverted(self, invert: bool) -> None:
        assert isinstance(invert, bool)
        self.hal_data['inverted'] = invert

    def configOpenLoopRamp(self, secondsFromNeutralToFull: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(secondsFromNeutralToFull, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['open_loop_ramp'] = secondsFromNeutralToFull
        assert isinstance(retval, ErrorCode)
        return retval

    def configClosedLoopRamp(self, secondsFromNeutralToFull: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(secondsFromNeutralToFull, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        if secondsFromNeutralToFull == 0:
            self.hal_data['closed_loop_ramp'] = 0
        else:
            self.hal_data['closed_loop_ramp'] = 1023. / secondsFromNeutralToFull * 0.001
        assert isinstance(retval, ErrorCode)
        return retval

    def configPeakOutputForward(self, percentOut: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(percentOut, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        assert 0 <= percentOut <= 1
        self.hal_data['peak_fwd_output'] = percentOut
        assert isinstance(retval, ErrorCode)
        return retval

    def configPeakOutputReverse(self, percentOut: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(percentOut, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        assert -1 <= percentOut <= 0
        self.hal_data['peak_rev_output'] = percentOut
        assert isinstance(retval, ErrorCode)
        return retval

    def configNominalOutputForward(self, percentOut: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(percentOut, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        assert 0 <= percentOut <= 1
        self.hal_data['nom_fwd_output'] = percentOut
        assert isinstance(retval, ErrorCode)
        return retval

    def configNominalOutputReverse(self, percentOut: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(percentOut, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        assert -1 <= percentOut <= 0
        self.hal_data['nom_rev_output'] = percentOut
        assert isinstance(retval, ErrorCode)
        return retval

    def configNeutralDeadband(self, percentDeadband: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(percentDeadband, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['neutral_deadband'] = percentDeadband
        assert isinstance(retval, ErrorCode)
        return retval

    def configVoltageCompSaturation(self, voltage: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(voltage, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['voltage_comp_saturation'] = voltage
        assert isinstance(retval, ErrorCode)
        return retval

    def configVoltageMeasurementFilter(self, filterWindowSamples: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(filterWindowSamples, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['voltage_measurement_filter'] = filterWindowSamples
        assert isinstance(retval, ErrorCode)
        return retval

    def enableVoltageCompensation(self, enable: bool) -> None:
        '''Enables voltage compensation. If enabled, voltage compensation works in
        all control modes.

        :param enable:
            Enable state of voltage compensation.

        '''
        assert isinstance(enable, bool)
        self.hal_data['voltage_comp_enabled'] = enable

    def getBusVoltage(self) -> float:
        '''Gets the bus voltage seen by the device.

        :returns: The bus voltage value (in volts).

        '''
        retval = self.hal_data['bus_voltage']
        assert isinstance(retval, (float))
        return retval

    def getMotorOutputPercent(self) -> float:
        '''Gets the output percentage of the motor controller.

        :returns: Output of the motor controller (in percent).

        '''
        retval = self.hal_data['value']
        assert isinstance(retval, (float))
        return retval

    def getOutputCurrent(self) -> float:
        '''Gets the output current of the motor controller.

        :returns: The output current (in amps).

        '''
        retval = self.hal_data['output_current']
        assert isinstance(retval, (float))
        return retval

    def getTemperature(self) -> float:
        '''Gets the temperature of the motor controller.

        :returns: Temperature of the motor controller (in 'C)

        '''
        retval = self.hal_data['temp']
        assert isinstance(retval, (float))
        return retval

    def configSelectedFeedbackSensor(self, feedbackDevice: int, pidIdx: int, timeoutMs: int) -> ErrorCode:
        '''Select the feedback device for the motor controller.
        Most CTRE CAN motor controllers will support remote sensors over CAN.

        :param feedbackDevice:
            Feedback Device to select.
        :type: feedbackDevice: :class:`.FeedbackDevice` or :class:`.RemoteFeedbackDevice`
        :param pidIdx:
            0 for Primary closed-loop. 1 for auxiliary closed-loop.
            See Phoenix-Documentation for how to interpret.
        :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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(feedbackDevice, int)
        assert isinstance(pidIdx, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['pid%d_feedback' % pidIdx] = feedbackDevice
        assert isinstance(retval, ErrorCode)
        return retval

    def configSelectedFeedbackCoefficient(self, coefficient: float, pidIdx: int, timeoutMs: int) -> ErrorCode:
        '''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.

        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(coefficient, (int, float))
        assert isinstance(pidIdx, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['pid%d_coefficient' % pidIdx] = coefficient
        assert isinstance(retval, ErrorCode)
        return retval

    def configRemoteFeedbackFilter(self, deviceID: int, remoteSensorSource: int, remoteOrdinal: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(deviceID, int)
        assert isinstance(remoteSensorSource, int)
        assert isinstance(remoteOrdinal, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def configSensorTerm(self, sensorTerm: int, feedbackDevice: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(sensorTerm, int)
        assert isinstance(feedbackDevice, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['sensor_term'] = (sensorTerm, feedbackDevice)
        assert isinstance(retval, ErrorCode)
        return retval

    def getSelectedSensorPosition(self, pidIdx: int) -> int:
        '''Get the selected sensor position.

        :param pidIdx:
            0 for Primary closed-loop. 1 for auxiliary closed-loop.
            See Phoenix-Documentation for how to interpret.
        :returns: Position of selected sensor (in Raw Sensor Units).

        '''
        assert isinstance(pidIdx, int)
        retval = 0
        fd = self.hal_data['pid%d_feedback' % pidIdx]
        prefix = _feedback2key.get(fd)
        if prefix is None:
            if fd != FeedbackDevice.None_:
               raise NotImplementedError("getSelectedSensorPosition not implemented for %s" % fd)
        else:
            retval = self.hal_data['%sposition' % prefix]
        assert isinstance(retval, int)
        return retval

    def getSelectedSensorVelocity(self, pidIdx: int) -> int:
        '''Get the selected sensor velocity.

        :param pidIdx:
            0 for Primary closed-loop. 1 for auxiliary closed-loop.
            See Phoenix-Documentation for how to interpret.
        :returns: selected sensor (in raw sensor units) per 100ms.

        '''
        assert isinstance(pidIdx, int)
        retval = 0
        fd = self.hal_data['pid%d_feedback' % pidIdx]
        prefix = _feedback2key.get(fd)
        if prefix is None:
            if fd != FeedbackDevice.None_:
               raise NotImplementedError("getSelectedSensorVelocity not implemented for %s" % fd)
        else:
            retval = self.hal_data['%svelocity' % prefix]
        assert isinstance(retval, int)
        return retval

    def setSelectedSensorPosition(self, sensorPos: int, pidIdx: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(sensorPos, int)
        assert isinstance(pidIdx, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        fd = self.hal_data['pid%d_feedback' % pidIdx]
        prefix = _feedback2key.get(fd)
        if prefix is None:
            if fd != FeedbackDevice.None_:
               raise NotImplementedError("setSelectedSensorPosition not implemented for %s" % fd)
        else:
            self.hal_data['%sposition' % prefix] = sensorPos
        assert isinstance(retval, ErrorCode)
        return retval

    def setControlFramePeriod(self, frame: int, periodMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(frame, int)
        assert isinstance(periodMs, int)
        retval = ErrorCode.OK
        pass
        assert isinstance(retval, ErrorCode)
        return retval

    def setStatusFramePeriod(self, frame: int, periodMs: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(frame, int)
        assert isinstance(periodMs, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        pass
        assert isinstance(retval, ErrorCode)
        return retval

    def getStatusFramePeriod(self, frame: int, timeoutMs: int) -> int:
        '''Gets the period of the given status frame.

        :param frame:
            Frame to get the period of.
        :type frame: :class:`.StatusFrame` or :class:`.StatusFrameEnhanced`
        :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.
        :returns: Period of the given status frame.

        '''
        assert isinstance(frame, int)
        assert isinstance(timeoutMs, int)
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def configVelocityMeasurementPeriod(self, period: int, timeoutMs: int) -> ErrorCode:
        '''Sets the period over which velocity measurements are taken.

        :param period:
            Desired period for the velocity measurement. see :class:`.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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(period, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['vel_measurement_period'] = period
        assert isinstance(retval, ErrorCode)
        return retval

    def configVelocityMeasurementWindow(self, windowSize: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(windowSize, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['vel_measurement_window'] = windowSize
        assert isinstance(retval, ErrorCode)
        return retval

    def configForwardLimitSwitchSource(self, type: int, normalOpenOrClose: int, deviceID: int, timeoutMs: int) -> ErrorCode:
        '''Configures the forward limit switch for a local/remote source. For example,
        a CAN motor controller may need to monitor the Limit-F pin of another Talon,
        CANifier, or local Gadgeteer feedback connector.

        :param type:
            Limit switch source. User can choose between the feedback connector,
            a remote Talon SRX, CANifier, or deactivate the feature.
        :type type: :class:`LimitSwitchSource`
        :param normalOpenOrClose:
            Setting for normally open, normally closed, or disabled. This
            setting matches the web-based configuration drop down.
        :type normalOpenOrClose: :class:`LimitSwitchNormal`
        :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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(type, int)
        assert isinstance(normalOpenOrClose, int)
        assert isinstance(deviceID, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['limit_switch_source_for'] = type
        self.hal_data['limit_switch_follow_for'] = deviceID
        assert isinstance(retval, ErrorCode)
        return retval

    def configReverseLimitSwitchSource(self, type: int, normalOpenOrClose: int, deviceID: int, timeoutMs: int) -> ErrorCode:
        '''Configures the reverse 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.

        :param type:
            Limit switch source. User can choose between the feedback connector,
            a remote Talon SRX, CANifier, or deactivate the feature.
        :type type: :class:`LimitSwitchSource`
        :param normalOpenOrClose:
            Setting for normally open, normally closed, or disabled. This
            setting matches the web-based configuration drop down.
        :type normalOpenOrClose: :class:`LimitSwitchNormal`
        :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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(type, int)
        assert isinstance(normalOpenOrClose, int)
        assert isinstance(deviceID, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['limit_switch_source_rev'] = type
        self.hal_data['limit_switch_follow_rev'] = deviceID
        assert isinstance(retval, ErrorCode)
        return retval

    def overrideLimitSwitchesEnable(self, enable: bool) -> None:
        '''Sets the enable state for limit switches.

        :param enable:
            Enable state for limit switches.

        '''
        assert isinstance(enable, bool)
        self.hal_data['limit_switch_usable'] = enable

    def configForwardSoftLimitThreshold(self, forwardSensorLimit: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(forwardSensorLimit, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['soft_limit_for'] = forwardSensorLimit
        assert isinstance(retval, ErrorCode)
        return retval

    def configReverseSoftLimitThreshold(self, reverseSensorLimit: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(reverseSensorLimit, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['soft_limit_rev'] = reverseSensorLimit
        assert isinstance(retval, ErrorCode)
        return retval

    def configForwardSoftLimitEnable(self, enable: bool, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(enable, bool)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['soft_limit_for_enable'] = enable
        assert isinstance(retval, ErrorCode)
        return retval

    def configReverseSoftLimitEnable(self, enable: bool, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(enable, bool)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['soft_limit_rev_enable'] = enable
        assert isinstance(retval, ErrorCode)
        return retval

    def overrideSoftLimitsEnable(self, enable: bool) -> None:
        '''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.

        '''
        assert isinstance(enable, bool)
        self.hal_data['soft_limit_usable'] = enable

    def config_kP(self, slotIdx: int, value: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(value, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_p' % slotIdx] = value
        assert isinstance(retval, ErrorCode)
        return retval

    def config_kI(self, slotIdx: int, value: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(value, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_i' % slotIdx] = value
        assert isinstance(retval, ErrorCode)
        return retval

    def config_kD(self, slotIdx: int, value: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(value, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_d' % slotIdx] = value
        assert isinstance(retval, ErrorCode)
        return retval

    def config_kF(self, slotIdx: int, value: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(value, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_f' % slotIdx] = value
        assert isinstance(retval, ErrorCode)
        return retval

    def config_IntegralZone(self, slotIdx: int, izone: float, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(izone, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_izone' % slotIdx] = izone
        assert isinstance(retval, ErrorCode)
        return retval

    def configAllowableClosedloopError(self, slotIdx: int, allowableClosedLoopError: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(allowableClosedLoopError, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_allowableError' % slotIdx] = allowableClosedLoopError
        assert isinstance(retval, ErrorCode)
        return retval

    def configMaxIntegralAccumulator(self, slotIdx: int, iaccum: float, timeoutMs: int) -> ErrorCode:
        '''Sets the maximum integral accumulator in the given parameter slot.

        :param slotIdx:
            Parameter slot for the constant.
        :param iaccum:
            Value to set for the 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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(iaccum, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_max_iaccum' % slotIdx] = iaccum
        assert isinstance(retval, ErrorCode)
        return retval

    def configClosedLoopPeakOutput(self, slotIdx: int, percentOut: float, timeoutMs: int) -> ErrorCode:
        '''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.

        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(percentOut, (int, float))
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_peakOutput' % slotIdx] = percentOut
        assert isinstance(retval, ErrorCode)
        return retval

    def configClosedLoopPeriod(self, slotIdx: int, loopTimeMs: int, timeoutMs: int) -> ErrorCode:
        '''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.

        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(loopTimeMs, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['profile%d_period' % slotIdx] = loopTimeMs / 1000.0
        assert isinstance(retval, ErrorCode)
        return retval

    def setIntegralAccumulator(self, iaccum: float, pidIdx: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(iaccum, (int, float))
        assert isinstance(pidIdx, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['pid%d_iaccum' % pidIdx] = iaccum
        assert isinstance(retval, ErrorCode)
        return retval

    def getClosedLoopError(self, pidIdx: int) -> int:
        '''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.
        :returns: Closed-loop error value.

        '''
        assert isinstance(pidIdx, int)
        retval = int(self.hal_data['pid%d_error' % pidIdx])
        assert isinstance(retval, int)
        return retval

    def getIntegralAccumulator(self, pidIdx: int) -> float:
        '''Gets the iaccum value.

        :param pidIdx:
            0 for Primary closed-loop. 1 for auxiliary closed-loop.
        :returns: Integral accumulator value.

        '''
        assert isinstance(pidIdx, int)
        retval = self.hal_data['pid%d_iaccum' % pidIdx]
        assert isinstance(retval, (float))
        return retval

    def getErrorDerivative(self, pidIdx: int) -> float:
        '''Gets the derivative of the closed-loop error.

        :param pidIdx:
            0 for Primary closed-loop. 1 for auxiliary closed-loop.
        :returns: The error derivative value.

        '''
        assert isinstance(pidIdx, int)
        retval = self.hal_data['pid%d_errorDerivative' % pidIdx]
        assert isinstance(retval, (float))
        return retval

    def selectProfileSlot(self, slotIdx: int, pidIdx: int) -> ErrorCode:
        '''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.

        '''
        assert isinstance(slotIdx, int)
        assert isinstance(pidIdx, int)
        retval = ErrorCode.OK
        self.hal_data['profile_slot_select'] = slotIdx
        self.hal_data['pid_slot_select'] = pidIdx
        assert isinstance(retval, ErrorCode)
        return retval

    def getActiveTrajectoryPosition(self) -> int:
        '''Gets the active trajectory target position using
        MotionMagic/MotionProfile control modes.

        :returns: The Active Trajectory Position in sensor units.

        '''
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def getActiveTrajectoryVelocity(self) -> int:
        '''Gets the active trajectory target velocity using
        MotionMagic/MotionProfile control modes.

        :returns: The Active Trajectory Velocity in sensor units per 100ms.

        '''
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def getActiveTrajectoryHeading(self) -> float:
        '''Gets the active trajectory target heading using
        MotionMagicArc/MotionProfileArc control modes.

        :returns: The Active Trajectory Heading in degreees.

        '''
        raise NotImplementedError
        assert isinstance(retval, (float))
        return retval

    def getActiveTrajectoryAll(self) -> typing.Tuple[int, int, float]:
        raise NotImplementedError
        assert isinstance(retval, tuple) and len(retval) == 3
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        assert isinstance(retval[2], (float))
        return retval

    def configMotionCruiseVelocity(self, sensorUnitsPer100ms: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(sensorUnitsPer100ms, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['motionmagic_cruise_velocity'] = sensorUnitsPer100ms
        assert isinstance(retval, ErrorCode)
        return retval

    def configMotionAcceleration(self, sensorUnitsPer100msPerSec: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(sensorUnitsPer100msPerSec, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['motionmagic_acceleration'] = sensorUnitsPer100msPerSec
        assert isinstance(retval, ErrorCode)
        return retval

    def clearMotionProfileTrajectories(self) -> ErrorCode:
        '''Clear the buffered motion profile in both controller's RAM (bottom), and in the
        API (top).

        '''
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def getMotionProfileTopLevelBufferCount(self) -> int:
        '''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.

        :returns: number of trajectory points in the top buffer.

        '''
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def _pushMotionProfileTrajectory(self, position: float, velocity: float, headingDeg: float, profileSlotSelect: int, isLastPoint: bool, zeroPos: bool) -> ErrorCode:
        '''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.
            profileSlotSelect  which slot to pull PIDF gains from.  Currently
            supports 0,1,2,3.
            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.
        :returns:
            CTR_OKAY if trajectory point push ok. ErrorCode if buffer is
            full due to kMotionProfileTopBufferCapacity.

        '''
        assert isinstance(position, (int, float))
        assert isinstance(velocity, (int, float))
        assert isinstance(headingDeg, (int, float))
        assert isinstance(profileSlotSelect, int)
        assert isinstance(isLastPoint, bool)
        assert isinstance(zeroPos, bool)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def _pushMotionProfileTrajectory_2(self, position: float, velocity: float, headingDeg: float, profileSlotSelect0: int, profileSlotSelect1: int, isLastPoint: bool, zeroPos: bool, durationMs: int) -> ErrorCode:
        assert isinstance(position, (int, float))
        assert isinstance(velocity, (int, float))
        assert isinstance(headingDeg, (int, float))
        assert isinstance(profileSlotSelect0, int)
        assert isinstance(profileSlotSelect1, int)
        assert isinstance(isLastPoint, bool)
        assert isinstance(zeroPos, bool)
        assert isinstance(durationMs, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def isMotionProfileTopLevelBufferFull(self) -> bool:
        '''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.

        :returns: number of trajectory points in the top buffer.

        '''
        raise NotImplementedError
        assert isinstance(retval, bool)
        return retval

    def processMotionProfileBuffer(self) -> ErrorCode:
        '''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.

        '''
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def _getMotionProfileStatus(self) -> typing.Tuple[int, int, int, bool, bool, bool, bool, int, int]:
        '''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.

        '''
        raise NotImplementedError
        assert isinstance(retval, tuple) and len(retval) == 9
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        assert isinstance(retval[2], int)
        assert isinstance(retval[3], bool)
        assert isinstance(retval[4], bool)
        assert isinstance(retval[5], bool)
        assert isinstance(retval[6], bool)
        assert isinstance(retval[7], int)
        assert isinstance(retval[8], int)
        return retval

    def _getMotionProfileStatus_2(self) -> typing.Tuple[int, int, int, bool, bool, bool, bool, int, int, int, int]:
        raise NotImplementedError
        assert isinstance(retval, tuple) and len(retval) == 11
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        assert isinstance(retval[2], int)
        assert isinstance(retval[3], bool)
        assert isinstance(retval[4], bool)
        assert isinstance(retval[5], bool)
        assert isinstance(retval[6], bool)
        assert isinstance(retval[7], int)
        assert isinstance(retval[8], int)
        assert isinstance(retval[9], int)
        assert isinstance(retval[10], int)
        return retval

    def clearMotionProfileHasUnderrun(self, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def changeMotionControlFramePeriod(self, periodMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(periodMs, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def configMotionProfileTrajectoryPeriod(self, durationMs: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(durationMs, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def getLastError(self) -> ErrorCode:
        '''Gets the last error generated by this object.

        :returns: Last Error Code generated by a function.

        '''
        retval = ErrorCode.OK
        retval = self.hal_data['last_error']
        assert isinstance(retval, ErrorCode)
        return retval

    def getFirmwareVersion(self) -> int:
        '''Gets the firmware version of the device.

        :returns: Firmware version of device. For example: version 1-dot-2
            is 0x0102.

        '''
        retval = 0
        assert isinstance(retval, int)
        return retval

    def hasResetOccurred(self) -> bool:
        ''':returns: Returns true if the device has reset since last call

        '''
        retval = False
        assert isinstance(retval, bool)
        return retval

    def configSetCustomParam(self, newValue: int, paramIndex: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(newValue, int)
        assert isinstance(paramIndex, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def configGetCustomParam(self, paramIndex: int, timoutMs: int) -> int:
        '''Gets the value of a 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.
        :returns: Value of the custom param.

        '''
        assert isinstance(paramIndex, int)
        assert isinstance(timoutMs, int)
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def configSetParameter(self, param: int, value: float, subValue: int, ordinal: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Error Code generated by function. 0 indicates no error.

        '''
        assert isinstance(param, int)
        assert isinstance(value, (int, float))
        assert isinstance(subValue, int)
        assert isinstance(ordinal, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        if param == ParamEnum.eOpenloopRamp:
            self.hal_data['open_loop_ramp'] = value
        elif param == ParamEnum.eClosedloopRamp:
            self.hal_data['closed_loop_ramp'] = value
        elif param == ParamEnum.eNeutralDeadband:
            self.hal_data['neutral_deadband'] = value
        elif param == ParamEnum.ePeakPosOutput:
            self.hal_data['peak_fwd_output'] = value
        elif param == ParamEnum.eNominalPosOutput:
            self.hal_data['nom_fwd_output'] = value
        elif param == ParamEnum.ePeakNegOutput:
            self.hal_data['peak_rev_output'] = value
        elif param == ParamEnum.eNominalNegOutput:
            self.hal_data['nom_rev_output'] = value
        elif param == ParamEnum.eProfileParamSlot_P:
            self.hal_data['profile%d_p' % ordinal] = float(value)
        elif param == ParamEnum.eProfileParamSlot_I:
            self.hal_data['profile%d_i' % ordinal] = float(value)
        elif param == ParamEnum.eProfileParamSlot_D:
            self.hal_data['profile%d_d' % ordinal] = float(value)
        elif param == ParamEnum.eProfileParamSlot_F:
            self.hal_data['profile%d_f' % ordinal] = float(value)
        elif param == ParamEnum.eProfileParamSlot_IZone:
            self.hal_data['profile%d_izone' % ordinal] = float(value)
        elif param == ParamEnum.eProfileParamSlot_AllowableErr:
            self.hal_data['profile%d_allowableError' % ordinal] = float(value)
        elif param == ParamEnum.eProfileParamSlot_MaxIAccum:
            self.hal_data['profile%d_max_iaccum' % ordinal] = float(value)
        elif param == ParamEnum.eSampleVelocityPeriod:
            self.hal_data['vel_measurement_period'] = int(value)
        elif param == ParamEnum.eSampleVelocityWindow:
            self.hal_data['vel_measurement_window'] = int(value)
        elif param == ParamEnum.eMotMag_Accel:
            self.hal_data['motionmagic_acceleration'] = value
        elif param == ParamEnum.eMotMag_VelCruise:
            self.hal_data['motionmagic_velocity'] = value
        elif param == ParamEnum.eClearPositionOnLimitF:
            self.hal_data['clear_pos_on_limit_fwd'] = int(value)
        elif param == ParamEnum.eClearPositionOnLimitR:
            self.hal_data['clear_pos_on_limit_rev'] = int(value)
        else:
            raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def configGetParameter(self, param: int, ordinal: int, timeoutMs: int) -> float:
        '''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.

        :returns: Value of parameter.

        '''
        assert isinstance(param, int)
        assert isinstance(ordinal, int)
        assert isinstance(timeoutMs, int)
        if param == ParamEnum.eOpenloopRamp:
            retval = self.hal_data['open_loop_ramp']
        elif param == ParamEnum.eClosedloopRamp:
            retval = self.hal_data['closed_loop_ramp']
        elif param == ParamEnum.eNeutralDeadband:
            retval = self.hal_data['neutral_deadband']
        elif param == ParamEnum.ePeakPosOutput:
            retval = self.hal_data['peak_fwd_output']
        elif param == ParamEnum.eNominalPosOutput:
            retval = self.hal_data['nom_fwd_output']
        elif param == ParamEnum.ePeakNegOutput:
            retval = self.hal_data['peak_rev_output']
        elif param == ParamEnum.eNominalNegOutput:
            retval = self.hal_data['nom_rev_output']
        elif param == ParamEnum.eProfileParamSlot_P:
            retval = self.hal_data['profile%d_p' % ordinal]
        elif param == ParamEnum.eProfileParamSlot_I:
            retval = self.hal_data['profile%d_i' % ordinal]
        elif param == ParamEnum.eProfileParamSlot_D:
            retval = self.hal_data['profile%d_d' % ordinal]
        elif param == ParamEnum.eProfileParamSlot_F:
            retval = self.hal_data['profile%d_f' % ordinal]
        elif param == ParamEnum.eProfileParamSlot_IZone:
            retval = self.hal_data['profile%d_izone' % ordinal]
        elif param == ParamEnum.eProfileParamSlot_AllowableErr:
            retval = self.hal_data['profile%d_allowableError' % ordinal]
        elif param == ParamEnum.eProfileParamSlot_MaxIAccum:
            retval = self.hal_data['profile%d_max_iaccum' % ordinal]
        elif param == ParamEnum.eSampleVelocityPeriod:
            retval = self.hal_data['vel_measurement_period']
        elif param == ParamEnum.eSampleVelocityWindow:
            retval = self.hal_data['vel_measurement_window']
        elif param == ParamEnum.eMotMag_Accel:
            retval = self.hal_data['motionmagic_acceleration']
        elif param == ParamEnum.eMotMag_VelCruise:
            retval = self.hal_data['motionmagic_velocity']
        elif param == ParamEnum.eClearPositionOnLimitF:
            retval = self.hal_data['clear_pos_on_limit_fwd']
        elif param == ParamEnum.eClearPositionOnLimitR:
            retval = self.hal_data['clear_pos_on_limit_rev']
        else:
            raise NotImplementedError
        assert isinstance(retval, (float))
        return retval

    def configPeakCurrentLimit(self, amps: int, timeoutMs: int) -> ErrorCode:
        '''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).

        Not available on the Victor SPX

        :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.

        '''
        assert isinstance(amps, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['current_limit_peak'] = amps
        assert isinstance(retval, ErrorCode)
        return retval

    def configPeakCurrentDuration(self, milliseconds: int, timeoutMs: int) -> ErrorCode:
        '''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).

        Not available on the Victor SPX

        :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.

        '''
        assert isinstance(milliseconds, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['current_peak_duration'] = milliseconds
        assert isinstance(retval, ErrorCode)
        return retval

    def configContinuousCurrentLimit(self, amps: int, timeoutMs: int) -> ErrorCode:
        '''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).

        Not available on the Victor SPX

        :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.

        '''
        assert isinstance(amps, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['current_limit_continuous'] = amps
        assert isinstance(retval, ErrorCode)
        return retval

    def enableCurrentLimit(self, enable: bool) -> ErrorCode:
        '''Enable or disable Current Limit.

        :param enable:
            Enable state of current limit.

        Not available on the Victor SPX

        see :meth:`.configPeakCurrentLimit`, :meth:`.configPeakCurrentDuration`,
        :meth:`.configContinuousCurrentLimit`

        '''
        assert isinstance(enable, bool)
        retval = ErrorCode.OK
        self.hal_data['current_limit_enabled'] = enable
        assert isinstance(retval, ErrorCode)
        return retval

    def setLastError(self, error: int) -> ErrorCode:
        assert isinstance(error, int)
        retval = ErrorCode.OK
        self.hal_data['last_error'] = ErrorCode(error)
        assert isinstance(retval, ErrorCode)
        return retval

    def getAnalogIn(self) -> int:
        '''Get the position of whatever is in the analog pin of the Talon,
        regardless of whether it is actually being used for feedback.

        :returns:
            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).

        '''
        retval = self.hal_data['analog_in']
        assert isinstance(retval, int)
        return retval

    def setAnalogPosition(self, newPosition: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: an ErrorCode.

        '''
        assert isinstance(newPosition, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['analog_position'] = newPosition
        assert isinstance(retval, ErrorCode)
        return retval

    def getAnalogInRaw(self) -> int:
        '''Get the position of whatever is in the analog pin of the Talon,
        regardless of whether it is actually being used for feedback.

        :returns: the ADC (0 - 1023) on analog pin of the Talon.

        '''
        retval = self.hal_data['analog_in_raw']
        assert isinstance(retval, int)
        return retval

    def getAnalogInVel(self) -> int:
        '''Get the velocity of whatever is in the analog pin of the Talon,
        regardless of whether it is actually being used for feedback.

        :returns: the speed in units per 100ms where 1024 units is one rotation.

        '''
        retval = self.hal_data['analog_velocity']
        assert isinstance(retval, int)
        return retval

    def getQuadraturePosition(self) -> int:
        '''Get the quadrature position of the Talon, regardless of whether
        it is actually being used for feedback.

        :returns: Quadrature encoder position

        '''
        retval = self.hal_data['quad_position']
        assert isinstance(retval, int)
        return retval

    def setQuadraturePosition(self, newPosition: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: error code.

        '''
        assert isinstance(newPosition, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['quad_position'] = newPosition
        assert isinstance(retval, ErrorCode)
        return retval

    def getQuadratureVelocity(self) -> int:
        '''Get the quadrature velocity, regardless of whether
        it is actually being used for feedback.

        :returns: the quadrature encoder velocity

        '''
        retval = self.hal_data['quad_velocity']
        assert isinstance(retval, int)
        return retval

    def getPulseWidthPosition(self) -> int:
        '''Gets pulse width position, regardless of whether
        it is actually being used for feedback.

        :returns: the pulse width position.

        '''
        retval = self.hal_data['pulse_width_position']
        assert isinstance(retval, int)
        return retval

    def setPulseWidthPosition(self, newPosition: int, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: an ErrorCode

        '''
        assert isinstance(newPosition, int)
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        self.hal_data['pulse_width_position'] = newPosition
        assert isinstance(retval, ErrorCode)
        return retval

    def getPulseWidthVelocity(self) -> int:
        '''Gets pulse width velocity, regardless of whether
        it is actually being used for feedback.

        :returns: the pulse width velocity  in units per 100ms (where 4096 units is 1 rotation).

        '''
        retval = self.hal_data['pulse_width_velocity']
        assert isinstance(retval, int)
        return retval

    def getPulseWidthRiseToFallUs(self) -> int:
        '''Gets pulse width rise to fall time.

        :returns: the pulse width rise to fall time in microseconds.

        '''
        retval = self.hal_data['pulse_width_rise_to_fall']
        assert isinstance(retval, int)
        return retval

    def getPulseWidthRiseToRiseUs(self) -> int:
        '''Gets pulse width rise to rise time.

        :returns: the pulse width rise to rise time in microseconds.

        '''
        retval = self.hal_data['pulse_width_rise_to_rise']
        assert isinstance(retval, int)
        return retval

    def getPinStateQuadA(self) -> int:
        retval = self.hal_data['quad_pin_a']
        assert isinstance(retval, int)
        return retval

    def getPinStateQuadB(self) -> int:
        retval = self.hal_data['quad_pin_b']
        assert isinstance(retval, int)
        return retval

    def getPinStateQuadIdx(self) -> int:
        retval = self.hal_data['quad_pin_idx']
        assert isinstance(retval, int)
        return retval

    def isFwdLimitSwitchClosed(self) -> int:
        data = self.hal_data
        if self.hal_data['limit_switch_source_for'] not in (LimitSwitchSource.Deactivated, LimitSwitchSource.FeedbackConnector):
            data = hal_data['CAN'][self.hal_data['limit_switch_follow_for']]
        retval = 1 if data['limit_switch_closed_for'] else 0
        assert isinstance(retval, int)
        return retval

    def isRevLimitSwitchClosed(self) -> int:
        data = self.hal_data
        if self.hal_data['limit_switch_source_rev'] not in (LimitSwitchSource.Deactivated, LimitSwitchSource.FeedbackConnector):
            data = hal_data['CAN'][self.hal_data['limit_switch_follow_rev']]
        retval = 1 if data['limit_switch_closed_rev'] else 0
        assert isinstance(retval, int)
        return retval

    def getFaults(self) -> int:
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def getStickyFaults(self) -> int:
        raise NotImplementedError
        assert isinstance(retval, int)
        return retval

    def clearStickyFaults(self, timeoutMs: int) -> ErrorCode:
        '''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.
        :returns: Last Error Code generated by a function.

        '''
        assert isinstance(timeoutMs, int)
        retval = ErrorCode.OK
        pass
        assert isinstance(retval, ErrorCode)
        return retval

    def selectDemandType(self, enable: bool) -> ErrorCode:
        '''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:

        '''
        assert isinstance(enable, bool)
        retval = ErrorCode.OK
        pass
        assert isinstance(retval, ErrorCode)
        return retval

    def setMPEOutput(self, MpeOutput: int) -> ErrorCode:
        assert isinstance(MpeOutput, int)
        retval = ErrorCode.OK
        raise NotImplementedError
        assert isinstance(retval, ErrorCode)
        return retval

    def enableHeadingHold(self, enable: bool) -> ErrorCode:
        '''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

        '''
        assert isinstance(enable, bool)
        retval = ErrorCode.OK
        pass
        assert isinstance(retval, ErrorCode)
        return retval

    def getAnalogInAll(self) -> typing.Tuple[int, int, int]:
        retval = (self.hal_data['analog_in'],
                  self.hal_data['analog_in_raw'],
                  self.hal_data['analog_velocity'])
        assert isinstance(retval, tuple) and len(retval) == 3
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        assert isinstance(retval[2], int)
        return retval

    def getQuadratureSensor(self) -> typing.Tuple[int, int]:
        retval = (self.hal_data['quad_position'], self.hal_data['quad_velocity'])
        assert isinstance(retval, tuple) and len(retval) == 2
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        return retval

    def getPulseWidthAll(self) -> typing.Tuple[int, int, int, int]:
        retval = (self.hal_data['pulse_width_position'],
                  self.hal_data['pulse_width_velocity'],
                  self.hal_data['pulse_width_rise_to_rise'],
                  self.hal_data['pulse_width_rise_to_fall'])
        assert isinstance(retval, tuple) and len(retval) == 4
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        assert isinstance(retval[2], int)
        assert isinstance(retval[3], int)
        return retval

    def getQuadPinStates(self) -> typing.Tuple[int, int, int]:
        retval = (self.hal_data['quad_pin_a'],
                  self.hal_data['quad_pin_b'],
                  self.hal_data['quad_pin_idx'])
        assert isinstance(retval, tuple) and len(retval) == 3
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        assert isinstance(retval[2], int)
        return retval

    def getLimitSwitchState(self) -> typing.Tuple[int, int]:
        ''':returns: Forward Limit switch closed, Reverse Limit switch closed

        '''
        fwd_data = rev_data = self.hal_data
        if self.hal_data['limit_switch_source_for'] not in (LimitSwitchSource.Deactivated, LimitSwitchSource.FeedbackConnector):
            fwd_data = hal_data['CAN'][self.hal_data['limit_switch_follow_for']]
        if self.hal_data['limit_switch_source_rev'] not in (LimitSwitchSource.Deactivated, LimitSwitchSource.FeedbackConnector):
            rev_data = hal_data['CAN'][self.hal_data['limit_switch_follow_rev']]
        retval = fwd_data['limit_switch_closed_for'], rev_data['limit_switch_closed_rev']
        assert isinstance(retval, tuple) and len(retval) == 2
        assert isinstance(retval[0], int)
        assert isinstance(retval[1], int)
        return retval

    def getClosedLoopTarget(self, pidIdx: int) -> int:
        '''Gets the current target of a given closed loop.

        :param pidIdx:
            0 for Primary closed-loop. 1 for auxiliary closed-loop.
        :returns: Closed-loop error value.

        '''
        assert isinstance(pidIdx, int)
        retval = self.hal_data['pid%d_target' % pidIdx]
        assert isinstance(retval, int)
        return retval


    def _set_out(self, out):
        self.hal_data['value'] = out / 1023.

    def _get_out(self):
        return int(self.hal_data['value'] * 1023.)

    _out = property(_get_out, _set_out)

    @property
    def _pidIdx(self):
        return self.hal_data['pid_slot_select']

    @property
    def _slotIdx(self):
        return self.hal_data['profile_slot_select']

    def _get_target(self):
        return self.hal_data['pid%d_target' % self._pidIdx]

    def _set_target(self, t):
        self.hal_data['pid%d_target' % self._pidIdx] = int(t)

    _target = property(_get_target, _set_target)

    def _get_outBeforRmp(self):
        return self.hal_data['pid%d_outBeforRmp' % self._pidIdx]

    def _set_outBeforRmp(self, rmp):
        self.hal_data['pid%d_outBeforRmp' % self._pidIdx] = rmp

    _outBeforRmp = property(_get_outBeforRmp, _set_outBeforRmp)

    def _get_prevErr(self):
        return self.hal_data['pid%d_prevErr' % self._pidIdx]

    def _set_prevErr(self, err):
        self.hal_data['pid%d_prevErr' % self._pidIdx] = err

    _prevErr = property(_get_prevErr, _set_prevErr)

    def _get_err(self):
        return self.hal_data['pid%d_error' % self._pidIdx]

    def _set_err(self, err):
        self.hal_data['pid%d_error' % self._pidIdx] = err

    _err = property(_get_err, _set_err)

    def _get_notFirst(self):
        return self.hal_data['pid%d_notFirst' % self._pidIdx]

    def _set_notFirst(self, notFirst):
        self.hal_data['pid%d_notFirst' % self._pidIdx] = notFirst

    _notFirst = property(_get_notFirst, _set_notFirst)

    def _get_iAccum(self):
        return self.hal_data['pid%d_iaccum' % self._pidIdx]

    def _set_iAccum(self, accum):
        self.hal_data['pid%d_iaccum' % self._pidIdx] = accum

    _iAccum = property(_get_iAccum, _set_iAccum)

    Notifier = Notifier

    def _calculate_1ms(self):
        if self.hal_data['clear_pos_on_limit_fwd'] and self.hal_data['limit_switch_closed_for']:
            self.setSelectedSensorPosition(0, self.hal_data['pid_slot_select'], 0)
        if self.hal_data['clear_pos_on_limit_rev'] and self.hal_data['limit_switch_closed_rev']:
            self.setSelectedSensorPosition(0, self.hal_data['pid_slot_select'], 0)
        calculating = True
        if self.hal_data['control_mode'] == ControlMode.Position:
            pos = self.getSelectedSensorPosition(self._pidIdx)
            out, = self._calculate_pid(pos, False, False)
        elif self.hal_data['control_mode'] == ControlMode.Velocity:
            pos = self.getSelectedSensorVelocity(self._pidIdx)
            out, = self._calculate_pid(pos, False, False)
        elif self.hal_data['control_mode'] == ControlMode.Current:
            pos = self.getOutputCurrent()
            out, = self._calculate_pid(pos, False, False)
        elif self.hal_data['control_mode'] == ControlMode.MotionMagic:
            self._target = self._motion_magic_next_target()
            pos = self.getSelectedSensorPosition(self._pidIdx)
            out, = self._calculate_pid(pos, False, False)
        else:
            calculating = False

        if calculating:
            peak_profile = self.hal_data['profile%d_peakOutput' % self._slotIdx]
            out = min(out, 1023 * self.hal_data['peak_fwd_output'] * peak_profile)
            out = max(out, 1023 * self.hal_data['peak_rev_output'] * peak_profile)
            if out >= 0:
                out = max(out, 1023 * self.hal_data['nom_fwd_output'])
            if out <= 0:
                out = min(out, 1023 * self.hal_data['nom_rev_output'])
            self._out = out

    def _motion_magic_next_target(self):
        a = self.hal_data['motionmagic_acceleration'] / 0.1 # sensor / sec^2
        cruise_v = self.hal_data['motionmagic_cruise_velocity'] / 0.1 # sensor / sec
        target = self.hal_data['motionmagic_target'] # sensor
        pos = self._target
        v = self.hal_data['motionmagic_velocity'] / 0.1 # sensor / sec
        okerr = self.hal_data['profile%d_allowableError' % self._slotIdx]
        dt = 0.001 # sec

        if a == 0:
            adist = v * 100
        else:
            adist = 0.5 * v ** 2 / a

        err = target - pos

        if abs(err) < okerr:
            if v > 0:
                v -= min(v, dt * a)
            elif v < 0:
                v -= max(v, -dt * a)
        elif okerr <= err < adist and v > 0:
            v -= dt * a
        elif okerr <= err < adist and v < 0:
            v += dt * a
        elif -okerr >= err > -adist and v < 0:
            v += dt * a
        elif -okerr >= err > -adist and v > 0:
            v -= dt * a
        elif err > adist and v >= 0:
            if v < cruise_v:
                v += dt * a
            elif v > cruise_v:
                v -= dt * a
        elif err < -adist and v <= 0:
            if v > -cruise_v:
                v -= dt * a
            elif v < -cruise_v:
                v += dt * a
        elif err > adist and v < 0:
            v += dt * a
        elif err < -adist and v > 0:
            v -= dt * a

        self.hal_data['motionmagic_velocity'] = v * 0.1
        return self._target + v * dt

    def _calculate_pid(self, pos, revMotDuringCloseLoopEn, oneDirOnly):
        self._err = self._target - pos
        absErr = abs(self._err)
        P = self.hal_data['profile%d_p' % self._slotIdx]
        I = self.hal_data['profile%d_i' % self._slotIdx]
        D = self.hal_data['profile%d_d' % self._slotIdx]
        F = self.hal_data['profile%d_f' % self._slotIdx]
        CloseLoopRampRate = self.hal_data['closed_loop_ramp']
        IZone = self.hal_data['profile%d_izone' % self._slotIdx]

        if not self._notFirst:
            self._iAccum = 0
            self._out = 0 #BDC_GetThrot() #????? brake mode or something?
        elif not IZone or absErr < IZone:
            self._iAccum += self._err
        else:
            self._iAccum = 0

        if self._notFirst:
            dErr = (self._err - self._prevErr)
        else:
            dErr = 0

        self.hal_data['pid%d_errorDerivative' % self._pidIdx] = dErr

        self._outBeforRmp = P * self._err

        if self._iAccum and I:
            self._outBeforRmp += I * self._iAccum

        self._outBeforRmp += dErr * D
        self._outBeforRmp += self._target * F

        self._prevErr = self._err
        self._notFirst = True

        if oneDirOnly:
            if self._outBeforRmp < 0:
                self._outBeforRmp = 0

        if revMotDuringCloseLoopEn:
            self._outBeforRmp = -self._outBeforRmp

        if CloseLoopRampRate:
            out = self._out
            if self._outBeforRmp >= out:
                deltaUp = min(self._outBeforRmp - out, CloseLoopRampRate)
                out += deltaUp
            else:
                deltaDn = min(out - self._outBeforRmp, CloseLoopRampRate)
                out -= deltaDn
        else:
            out = self._outBeforRmp

        return out,

