[wpilib] Make solenoids exclusive use, PCM act like old sendable compressor (#3464)

This commit is contained in:
Thad House
2021-07-09 15:11:12 -07:00
committed by GitHub
parent 6ddef1cca6
commit c154e5262e
9 changed files with 166 additions and 8 deletions

View File

@@ -6,6 +6,7 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.util.AllocationException;
import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
@@ -42,7 +43,13 @@ public class DoubleSolenoid implements Sendable, AutoCloseable {
public DoubleSolenoid(PneumaticsBase module, final int forwardChannel, final int reverseChannel) {
m_module = Objects.requireNonNull(module, "Module cannot be null");
// TODO check channels
if (!module.checkSolenoidChannel(forwardChannel)) {
throw new IllegalArgumentException("Channel " + forwardChannel + " out of range");
}
if (!module.checkSolenoidChannel(reverseChannel)) {
throw new IllegalArgumentException("Channel " + reverseChannel + " out of range");
}
m_forwardChannel = forwardChannel;
m_reverseChannel = reverseChannel;
@@ -51,6 +58,23 @@ public class DoubleSolenoid implements Sendable, AutoCloseable {
m_reverseMask = 1 << reverseChannel;
m_mask = m_forwardMask | m_reverseMask;
int allocMask = module.checkAndReserveSolenoids(m_mask);
if (allocMask != 0) {
if (allocMask == m_mask) {
throw new AllocationException(
"Channels " + forwardChannel + " and " + reverseChannel + " already allocated");
} else if (allocMask == m_forwardMask) {
throw new AllocationException("Channel " + forwardChannel + " already allocated");
} else {
throw new AllocationException("Channel " + reverseChannel + " already allocated");
}
}
if (module.checkAndReserveSolenoids(m_mask) != 0) {
throw new AllocationException("Solenoid(s) already allocated");
}
HAL.report(
tResourceType.kResourceType_Solenoid, forwardChannel + 1, module.getModuleNumber() + 1);
HAL.report(
@@ -61,6 +85,7 @@ public class DoubleSolenoid implements Sendable, AutoCloseable {
@Override
public synchronized void close() {
SendableRegistry.remove(this);
m_module.unreserveSolenoids(m_mask);
m_module = null;
}

View File

@@ -49,5 +49,26 @@ public interface PneumaticsBase extends AutoCloseable {
*/
void setOneShotDuration(int index, int durMs);
/**
* Check if a solenoid channel is valid.
*
* @param channel Channel to check
* @return True if channel exists
*/
boolean checkSolenoidChannel(int channel);
/**
* Check to see if the masked solenoids can be reserved, and if not reserve them.
*
* @param mask The solenoid mask to reserve
* @return 0 if successful, mask of solenoids that couldn't be allocated otherwise
*/
int checkAndReserveSolenoids(int mask);
/**
* Unreserve the masked solenoids.
*
* @param mask The solenoid mask to unreserve
*/
void unreserveSolenoids(int mask);
}

View File

@@ -5,23 +5,36 @@
package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.CTREPCMJNI;
import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
public class PneumaticsControlModule implements PneumaticsBase {
public class PneumaticsControlModule implements PneumaticsBase, Sendable {
private final int m_handle;
private final int m_module;
private int m_reservedMask;
private final Object m_reserveLock = new Object();
public PneumaticsControlModule() {
this(SensorUtil.getDefaultCTREPCMModule());
}
/**
* Constructs a PneumaticsControlModule.
*
* @param module module number to construct
*/
public PneumaticsControlModule(int module) {
m_handle = CTREPCMJNI.initialize(module);
m_module = module;
SendableRegistry.addLW(this, "Compressor", module);
}
@Override
public void close() throws Exception {
CTREPCMJNI.free(m_handle);
SendableRegistry.remove(this);
}
public boolean getCompressor() {
@@ -114,4 +127,31 @@ public class PneumaticsControlModule implements PneumaticsBase {
public boolean checkSolenoidChannel(int channel) {
return CTREPCMJNI.checkSolenoidChannel(channel);
}
@Override
public int checkAndReserveSolenoids(int mask) {
synchronized (m_reserveLock) {
if ((m_reservedMask & mask) != 0) {
return m_reservedMask & mask;
}
m_reservedMask |= mask;
return 0;
}
}
@Override
public void unreserveSolenoids(int mask) {
synchronized (m_reserveLock) {
m_reservedMask &= ~mask;
}
}
@Override
public void initSendable(SendableBuilder builder) {
builder.setSmartDashboardType("Compressor");
builder.addBooleanProperty(
"Closed Loop Control", this::getClosedLoopControl, this::setClosedLoopControl);
builder.addBooleanProperty("Enabled", this::getCompressor, null);
builder.addBooleanProperty("Pressure switch", this::getPressureSwitch, null);
}
}

View File

@@ -6,6 +6,7 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.util.AllocationException;
import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
@@ -38,6 +39,10 @@ public class Solenoid implements Sendable, AutoCloseable {
m_mask = 1 << channel;
m_channel = channel;
if (module.checkAndReserveSolenoids(m_mask) != 0) {
throw new AllocationException("Solenoid already allocated");
}
HAL.report(tResourceType.kResourceType_Solenoid, channel + 1, module.getModuleNumber() + 1);
SendableRegistry.addLW(this, "Solenoid", module.getModuleNumber(), channel);
}
@@ -45,6 +50,7 @@ public class Solenoid implements Sendable, AutoCloseable {
@Override
public void close() {
SendableRegistry.remove(this);
m_module.unreserveSolenoids(m_mask);
m_module = null;
}