001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003/* Open Source Software - may be modified and shared by FRC teams. The code */ 004/* must be accompanied by the FIRST BSD license file in the root directory of */ 005/* the project. */ 006/*----------------------------------------------------------------------------*/ 007 008package edu.wpi.first.wpilibj; 009 010import java.nio.ByteBuffer; 011import java.nio.ByteOrder; 012 013import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType; 014import edu.wpi.first.wpilibj.communication.UsageReporting; 015import edu.wpi.first.wpilibj.hal.HALUtil; 016import edu.wpi.first.wpilibj.hal.SolenoidJNI; 017import edu.wpi.first.wpilibj.livewindow.LiveWindow; 018import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable; 019import edu.wpi.first.wpilibj.tables.ITable; 020import edu.wpi.first.wpilibj.tables.ITableListener; 021import edu.wpi.first.wpilibj.util.AllocationException; 022import edu.wpi.first.wpilibj.util.CheckedAllocationException; 023 024/** 025 * Solenoid class for running high voltage Digital Output. 026 * 027 * The Solenoid class is typically used for pneumatics solenoids, but could be used 028 * for any device within the current spec of the PCM. 029 */ 030public class Solenoid extends SolenoidBase implements LiveWindowSendable { 031 032 private int m_channel; ///< The channel to control. 033 private ByteBuffer m_solenoid_port; 034 035 /** 036 * Common function to implement constructor behavior. 037 */ 038 private synchronized void initSolenoid() { 039 checkSolenoidModule(m_moduleNumber); 040 checkSolenoidChannel(m_channel); 041 042 ByteBuffer status = ByteBuffer.allocateDirect(4); 043 status.order(ByteOrder.LITTLE_ENDIAN); 044 045 ByteBuffer port = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) m_channel); 046 m_solenoid_port = SolenoidJNI.initializeSolenoidPort(port, status.asIntBuffer()); 047 HALUtil.checkStatus(status.asIntBuffer()); 048 049 LiveWindow.addActuator("Solenoid", m_moduleNumber, m_channel, this); 050 UsageReporting.report(tResourceType.kResourceType_Solenoid, m_channel, m_moduleNumber); 051 } 052 053 /** 054 * Constructor using the default PCM ID (0) 055 * 056 * @param channel The channel on the PCM to control (0..7). 057 */ 058 public Solenoid(final int channel) { 059 super(getDefaultSolenoidModule()); 060 m_channel = channel; 061 initSolenoid(); 062 } 063 064 /** 065 * Constructor. 066 * 067 * @param moduleNumber The CAN ID of the PCM the solenoid is attached to. 068 * @param channel The channel on the PCM to control (0..7). 069 */ 070 public Solenoid(final int moduleNumber, final int channel) { 071 super(moduleNumber); 072 m_channel = channel; 073 initSolenoid(); 074 } 075 076 /** 077 * Destructor. 078 */ 079 public synchronized void free() { 080 // m_allocated.free((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1); 081 } 082 083 /** 084 * Set the value of a solenoid. 085 * 086 * @param on Turn the solenoid output off or on. 087 */ 088 public void set(boolean on) { 089 byte value = (byte) (on ? 0xFF : 0x00); 090 byte mask = (byte) (1 << m_channel); 091 092 set(value, mask); 093 } 094 095 /** 096 * Read the current value of the solenoid. 097 * 098 * @return The current value of the solenoid. 099 */ 100 public boolean get() { 101 int value = getAll() & ( 1 << m_channel); 102 return (value != 0); 103 } 104 /** 105 * Check if solenoid is blacklisted. 106 * If a solenoid is shorted, it is added to the blacklist and 107 * disabled until power cycle, or until faults are cleared. 108 * @see clearAllPCMStickyFaults() 109 * 110 * @return If solenoid is disabled due to short. 111 */ 112 public boolean isBlackListed() { 113 int value = getPCMSolenoidBlackList() & ( 1 << m_channel); 114 return (value != 0); 115 } 116 /* 117 * Live Window code, only does anything if live window is activated. 118 */ 119 public String getSmartDashboardType() { 120 return "Solenoid"; 121 } 122 private ITable m_table; 123 private ITableListener m_table_listener; 124 125 /** 126 * {@inheritDoc} 127 */ 128 public void initTable(ITable subtable) { 129 m_table = subtable; 130 updateTable(); 131 } 132 133 /** 134 * {@inheritDoc} 135 */ 136 public ITable getTable() { 137 return m_table; 138 } 139 140 /** 141 * {@inheritDoc} 142 */ 143 public void updateTable() { 144 if (m_table != null) { 145 m_table.putBoolean("Value", get()); 146 } 147 } 148 149 150 /** 151 * {@inheritDoc} 152 */ 153 public void startLiveWindowMode() { 154 set(false); // Stop for safety 155 m_table_listener = new ITableListener() { 156 public void valueChanged(ITable itable, String key, Object value, boolean bln) { 157 set(((Boolean) value).booleanValue()); 158 } 159 }; 160 m_table.addTableListener("Value", m_table_listener, true); 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 public void stopLiveWindowMode() { 167 set(false); // Stop for safety 168 // TODO: Broken, should only remove the listener from "Value" only. 169 m_table.removeTableListener(m_table_listener); 170 } 171}