001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package org.wpilib.hardware.hal; 006 007import org.wpilib.hardware.hal.struct.ControlWordStruct; 008 009/** A wrapper for the HALControlWord bitfield. */ 010public class ControlWord { 011 private static final long OPMODE_HASH_MASK = 0x00FFFFFFFFFFFFFFL; 012 private static final long ROBOT_MODE_MASK = 0x0300000000000000L; 013 private static final long ROBOT_MODE_SHIFT = 56; 014 private static final long ENABLED_MASK = 0x0400000000000000L; 015 private static final long ESTOP_MASK = 0x0800000000000000L; 016 private static final long FMS_ATTACHED_MASK = 0x1000000000000000L; 017 private static final long DS_ATTACHED_MASK = 0x2000000000000000L; 018 019 private long m_word; 020 private RobotMode m_robotMode = RobotMode.UNKNOWN; 021 022 /** Default constructor. */ 023 public ControlWord() {} 024 025 /** 026 * Updates from state values. 027 * 028 * @param opModeHash opmode hash 029 * @param robotMode robot mode 030 * @param enabled enabled 031 * @param emergencyStop emergency stopped 032 * @param fmsAttached FMS attached 033 * @param dsAttached DS attached 034 */ 035 public void update( 036 long opModeHash, 037 RobotMode robotMode, 038 boolean enabled, 039 boolean emergencyStop, 040 boolean fmsAttached, 041 boolean dsAttached) { 042 m_word = 043 (opModeHash & OPMODE_HASH_MASK) 044 | ((long) robotMode.getValue() << ROBOT_MODE_SHIFT) 045 | (enabled ? ENABLED_MASK : 0) 046 | (emergencyStop ? ESTOP_MASK : 0) 047 | (fmsAttached ? FMS_ATTACHED_MASK : 0) 048 | (dsAttached ? DS_ATTACHED_MASK : 0); 049 m_robotMode = robotMode; 050 } 051 052 /** 053 * Updates from the native HAL value. 054 * 055 * @param word value 056 */ 057 public void update(long word) { 058 m_word = word; 059 m_robotMode = RobotMode.fromInt((int) ((word & ROBOT_MODE_MASK) >> ROBOT_MODE_SHIFT)); 060 } 061 062 /** 063 * Updates from an existing word. 064 * 065 * @param word word to update from 066 */ 067 public void update(ControlWord word) { 068 m_word = word.m_word; 069 m_robotMode = word.m_robotMode; 070 } 071 072 /** 073 * Gets the opmode ID. 074 * 075 * @return the opmode ID 076 */ 077 public long getOpModeId() { 078 // if the hash portion is zero, return 0 079 if ((m_word & OPMODE_HASH_MASK) == 0) { 080 return 0; 081 } 082 // otherwise return the full ID (which includes the robot mode) 083 return m_word & (OPMODE_HASH_MASK | ROBOT_MODE_MASK); 084 } 085 086 /** 087 * Sets the opmode ID. 088 * 089 * @param id opmode ID 090 */ 091 public void setOpModeId(long id) { 092 m_word &= ~(OPMODE_HASH_MASK | ROBOT_MODE_MASK); 093 m_word |= id & (OPMODE_HASH_MASK | ROBOT_MODE_MASK); 094 // keep robot mode in sync 095 m_robotMode = RobotMode.fromInt((int) ((m_word & ROBOT_MODE_MASK) >> ROBOT_MODE_SHIFT)); 096 } 097 098 /** 099 * Gets the robot mode. 100 * 101 * @return the robot mode 102 */ 103 public RobotMode getRobotMode() { 104 return m_robotMode; 105 } 106 107 /** 108 * Gets the Enabled flag. 109 * 110 * @return the Enabled flag 111 */ 112 public boolean isEnabled() { 113 return (m_word & ENABLED_MASK) != 0; 114 } 115 116 /** 117 * Gets the E-Stop flag. 118 * 119 * @return the E-Stop flag 120 */ 121 public boolean isEStopped() { 122 return (m_word & ESTOP_MASK) != 0; 123 } 124 125 /** 126 * Gets the FMS attached flag. 127 * 128 * @return the FMS attached flag 129 */ 130 public boolean isFMSAttached() { 131 return (m_word & FMS_ATTACHED_MASK) != 0; 132 } 133 134 /** 135 * Gets the DS attached flag. 136 * 137 * @return the DS attached flag 138 */ 139 public boolean isDSAttached() { 140 return (m_word & DS_ATTACHED_MASK) != 0; 141 } 142 143 /** 144 * Gets a value indicating whether the Driver Station requires the robot to be running in 145 * autonomous mode. 146 * 147 * @return True if autonomous mode should be enabled, false otherwise. 148 */ 149 public boolean isAutonomous() { 150 return getRobotMode() == RobotMode.AUTONOMOUS; 151 } 152 153 /** 154 * Gets a value indicating whether the Driver Station requires the robot to be running in 155 * autonomous mode and enabled. 156 * 157 * @return True if autonomous should be set and the robot should be enabled. 158 */ 159 public boolean isAutonomousEnabled() { 160 return isAutonomous() && isEnabled() && isDSAttached(); 161 } 162 163 /** 164 * Gets a value indicating whether the Driver Station requires the robot to be running in 165 * operator-controlled mode. 166 * 167 * @return True if operator-controlled mode should be enabled, false otherwise. 168 */ 169 public boolean isTeleop() { 170 return getRobotMode() == RobotMode.TELEOPERATED; 171 } 172 173 /** 174 * Gets a value indicating whether the Driver Station requires the robot to be running in 175 * operator-controller mode and enabled. 176 * 177 * @return True if operator-controlled mode should be set and the robot should be enabled. 178 */ 179 public boolean isTeleopEnabled() { 180 return isTeleop() && isEnabled() && isDSAttached(); 181 } 182 183 /** 184 * Gets a value indicating whether the Driver Station requires the robot to be running in test 185 * mode. 186 * 187 * @return True if test mode should be enabled, false otherwise. 188 */ 189 public boolean isTest() { 190 return getRobotMode() == RobotMode.TEST; 191 } 192 193 /** 194 * Gets a value indicating whether the Driver Station requires the robot to be running in test 195 * mode and enabled. 196 * 197 * @return True if test mode should be set and the robot should be enabled. 198 */ 199 public boolean isTestEnabled() { 200 return isTest() && isEnabled() && isDSAttached(); 201 } 202 203 /** 204 * Gets the native HAL control word value. 205 * 206 * @return control word value 207 */ 208 public long getNative() { 209 return m_word; 210 } 211 212 @Override 213 public boolean equals(Object obj) { 214 return obj instanceof ControlWord word && m_word == word.m_word; 215 } 216 217 @Override 218 public int hashCode() { 219 return Long.hashCode(m_word); 220 } 221 222 public static final ControlWordStruct struct = new ControlWordStruct(); 223}