001/* 002 * Copyright (c) 2018-2021 REV Robotics 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 2. Redistributions in binary form must reproduce the above copyright 010 * notice, this list of conditions and the following disclaimer in the 011 * documentation and/or other materials provided with the distribution. 012 * 3. Neither the name of REV Robotics nor the names of its 013 * contributors may be used to endorse or promote products derived from 014 * this software without specific prior written permission. 015 * 016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 026 * POSSIBILITY OF SUCH DAMAGE. 027 */ 028 029package com.revrobotics; 030 031import com.revrobotics.jni.CANSparkMaxJNI; 032import java.util.Locale; 033 034/** 035 * Get an instance of this class by using {@link CANSparkMax#getForwardLimitSwitch(Type)} or {@link 036 * CANSparkMax#getReverseLimitSwitch(Type)}. 037 */ 038public class SparkMaxLimitSwitch implements CANDigitalInput { 039 // package-private (can only be used by other classes in this package) 040 enum Direction { 041 kForward(0), 042 kReverse(1); 043 044 @SuppressWarnings("MemberName") 045 public final int value; 046 047 Direction(int value) { 048 this.value = value; 049 } 050 } 051 052 public enum Type { 053 kNormallyOpen(0), 054 kNormallyClosed(1); 055 056 @SuppressWarnings("MemberName") 057 public final int value; 058 059 Type(int value) { 060 this.value = value; 061 } 062 } 063 064 private final CANSparkMax m_device; 065 private final Direction m_limitSwitch; 066 final Type m_switchType; 067 068 // package-private (can only be used by other classes in this package) 069 SparkMaxLimitSwitch(CANSparkMax device, Direction direction, Type switchType) { 070 m_device = device; 071 m_limitSwitch = direction; 072 m_switchType = switchType; 073 074 if (direction == null) { 075 throw new IllegalArgumentException("limitSwitch must not be null"); 076 } 077 078 if (switchType == null) { 079 throw new IllegalArgumentException("polarity must not be null"); 080 } 081 082 REVLibError error = 083 REVLibError.fromInt( 084 CANSparkMaxJNI.c_SparkMax_AttemptToSetDataPortConfig( 085 device.sparkMaxHandle, CANSparkMax.DataPortConfig.kLimitSwitches.m_value)); 086 if (error == REVLibError.kSparkMaxDataPortAlreadyConfiguredDifferently) { 087 CANSparkMax.DataPortConfig currentConfig = 088 CANSparkMax.DataPortConfig.fromInt( 089 CANSparkMaxJNI.c_SparkMax_GetDataPortConfig(device.sparkMaxHandle)); 090 throw new IllegalStateException( 091 String.format( 092 Locale.ENGLISH, 093 "Limit switches cannot be used while %s is active", 094 currentConfig.m_name)); 095 } 096 097 CANSparkMaxJNI.c_SparkMax_SetLimitPolarity( 098 m_device.sparkMaxHandle, direction.value, switchType.value); 099 } 100 101 /** 102 * Returns {@code true} if the limit switch is pressed, based on the selected polarity. 103 * 104 * <p>This method works even if the limit switch is not enabled for controller shutdown. 105 * 106 * @return {@code true} if the limit switch is pressed 107 */ 108 public boolean isPressed() { 109 m_device.throwIfClosed(); 110 if (m_limitSwitch == Direction.kForward) { 111 return m_device.getFault(CANSparkMax.FaultID.kHardLimitFwd); 112 } else { 113 return m_device.getFault(CANSparkMax.FaultID.kHardLimitRev); 114 } 115 } 116 117 /** 118 * Returns {@code true} if the limit switch is pressed, based on the selected polarity. 119 * 120 * <p>This method works even if the limit switch is not enabled. 121 * 122 * @return {@code true} if the limit switch is pressed 123 * @deprecated Use {@link #isPressed()} instead 124 */ 125 @Override 126 @Deprecated(forRemoval = true) 127 public boolean get() { 128 return isPressed(); 129 } 130 131 /** 132 * Enables or disables controller shutdown based on the limit switch. 133 * 134 * @param enable Enable/disable motor shutdown based on the limit switch state. This does not 135 * affect the result of the get() command. 136 * @return {@link REVLibError#kOk} if successful 137 */ 138 @Override 139 public REVLibError enableLimitSwitch(boolean enable) { 140 m_device.throwIfClosed(); 141 return REVLibError.fromInt( 142 CANSparkMaxJNI.c_SparkMax_EnableLimitSwitch( 143 m_device.sparkMaxHandle, m_limitSwitch.value, enable)); 144 } 145 146 /** @return {@code true} if the limit switch is enabled */ 147 @Override 148 public boolean isLimitSwitchEnabled() { 149 m_device.throwIfClosed(); 150 return CANSparkMaxJNI.c_SparkMax_IsLimitEnabled(m_device.sparkMaxHandle, m_limitSwitch.value); 151 } 152}