diff --git a/hal/include/HAL/Handles.h b/hal/include/HAL/Handles.h index 6451ec0d0d..1466cc5974 100644 --- a/hal/include/HAL/Handles.h +++ b/hal/include/HAL/Handles.h @@ -34,3 +34,5 @@ typedef HalHandle HalDigitalPWMHandle; typedef HalHandle HalCounterHandle; typedef HalHandle HalCompressorHandle; + +typedef HalHandle HalSolenoidHandle; diff --git a/hal/include/HAL/Solenoid.h b/hal/include/HAL/Solenoid.h index 41f4ccb4d1..723a8d927a 100644 --- a/hal/include/HAL/Solenoid.h +++ b/hal/include/HAL/Solenoid.h @@ -12,17 +12,18 @@ #include "Handles.h" extern "C" { -void* initializeSolenoidPort(HalPortHandle port_handle, int32_t* status); -void freeSolenoidPort(void* solenoid_port_pointer); +HalSolenoidHandle initializeSolenoidPort(HalPortHandle port_handle, + int32_t* status); +void freeSolenoidPort(HalSolenoidHandle solenoid_port_handle); bool checkSolenoidModule(uint8_t module); -bool getSolenoid(void* solenoid_port_pointer, int32_t* status); -uint8_t getAllSolenoids(void* solenoid_port_pointer, int32_t* status); -void setSolenoid(void* solenoid_port_pointer, bool value, int32_t* status); +bool getSolenoid(HalSolenoidHandle solenoid_port_handle, int32_t* status); +uint8_t getAllSolenoids(uint8_t module, int32_t* status); +void setSolenoid(HalSolenoidHandle solenoid_port_handle, bool value, + int32_t* status); -int getPCMSolenoidBlackList(void* solenoid_port_pointer, int32_t* status); -bool getPCMSolenoidVoltageStickyFault(void* solenoid_port_pointer, - int32_t* status); -bool getPCMSolenoidVoltageFault(void* solenoid_port_pointer, int32_t* status); -void clearAllPCMStickyFaults_sol(void* solenoid_port_pointer, int32_t* status); +int getPCMSolenoidBlackList(uint8_t module, int32_t* status); +bool getPCMSolenoidVoltageStickyFault(uint8_t module, int32_t* status); +bool getPCMSolenoidVoltageFault(uint8_t module, int32_t* status); +void clearAllPCMStickyFaults_sol(uint8_t module, int32_t* status); } diff --git a/hal/lib/athena/Solenoid.cpp b/hal/lib/athena/Solenoid.cpp index 75a693e52e..bfbfda5c26 100644 --- a/hal/lib/athena/Solenoid.cpp +++ b/hal/lib/athena/Solenoid.cpp @@ -12,15 +12,19 @@ #include "HAL/Errors.h" #include "ctre/PCM.h" #include "handles/HandlesInternal.h" +#include "handles/IndexedHandleResource.h" -static const int NUM_MODULE_NUMBERS = 63; +static constexpr int NUM_MODULE_NUMBERS = 63; +static constexpr int NUM_SOLENOID_PINS = 8; PCM* PCM_modules[NUM_MODULE_NUMBERS] = {nullptr}; -struct solenoid_port_t { - PCM* module; - uint32_t pin; +namespace { +struct Solenoid { + uint8_t module; + uint8_t pin; }; +} void initializePCM(int module) { if (!PCM_modules[module]) { @@ -30,85 +34,127 @@ void initializePCM(int module) { using namespace hal; +static IndexedHandleResource + solenoidHandles; + extern "C" { -void* initializeSolenoidPort(HalPortHandle port_handle, int32_t* status) { +HalSolenoidHandle initializeSolenoidPort(HalPortHandle port_handle, + int32_t* status) { int16_t pin = getPortHandlePin(port_handle); int16_t module = getPortHandleModule(port_handle); if (pin == InvalidHandleIndex) { + *status = PARAMETER_OUT_OF_RANGE; // Change to Handle Error + return HAL_INVALID_HANDLE; + } + + if (module >= NUM_MODULE_NUMBERS || pin >= NUM_SOLENOID_PINS) { *status = PARAMETER_OUT_OF_RANGE; - return nullptr; + return HAL_INVALID_HANDLE; } initializePCM(module); - solenoid_port_t* solenoid_port = new solenoid_port_t; - solenoid_port->module = PCM_modules[module]; - solenoid_port->pin = pin; + auto handle = + solenoidHandles.Allocate(module * NUM_SOLENOID_PINS + pin, status); + if (handle == HAL_INVALID_HANDLE) { // out of resources + *status = NO_AVAILABLE_RESOURCES; + return HAL_INVALID_HANDLE; + } + auto solenoid_port = solenoidHandles.Get(handle); + if (solenoid_port == nullptr) { // would only occur on thread issues + *status = PARAMETER_OUT_OF_RANGE; + return HAL_INVALID_HANDLE; + } + solenoid_port->module = static_cast(module); + solenoid_port->pin = static_cast(pin); - return solenoid_port; + return handle; } -void freeSolenoidPort(void* solenoid_port_pointer) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; - delete port; +void freeSolenoidPort(HalSolenoidHandle solenoid_port_handle) { + solenoidHandles.Free(solenoid_port_handle); } bool checkSolenoidModule(uint8_t module) { return module < NUM_MODULE_NUMBERS; } -bool getSolenoid(void* solenoid_port_pointer, int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +bool getSolenoid(HalSolenoidHandle solenoid_port_handle, int32_t* status) { + auto port = solenoidHandles.Get(solenoid_port_handle); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } bool value; - *status = port->module->GetSolenoid(port->pin, value); + *status = PCM_modules[port->module]->GetSolenoid(port->pin, value); return value; } -uint8_t getAllSolenoids(void* solenoid_port_pointer, int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +uint8_t getAllSolenoids(uint8_t module, int32_t* status) { + if (module >= NUM_MODULE_NUMBERS) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } uint8_t value; - *status = port->module->GetAllSolenoids(value); + *status = PCM_modules[module]->GetAllSolenoids(value); return value; } -void setSolenoid(void* solenoid_port_pointer, bool value, int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +void setSolenoid(HalSolenoidHandle solenoid_port_handle, bool value, + int32_t* status) { + auto port = solenoidHandles.Get(solenoid_port_handle); + if (port == nullptr) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } - *status = port->module->SetSolenoid(port->pin, value); + *status = PCM_modules[port->module]->SetSolenoid(port->pin, value); } -int getPCMSolenoidBlackList(void* solenoid_port_pointer, int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +int getPCMSolenoidBlackList(uint8_t module, int32_t* status) { + if (module >= NUM_MODULE_NUMBERS) { + *status = PARAMETER_OUT_OF_RANGE; + return 0; + } UINT8 value; - *status = port->module->GetSolenoidBlackList(value); + *status = PCM_modules[module]->GetSolenoidBlackList(value); return value; } -bool getPCMSolenoidVoltageStickyFault(void* solenoid_port_pointer, - int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +bool getPCMSolenoidVoltageStickyFault(uint8_t module, int32_t* status) { + if (module >= NUM_MODULE_NUMBERS) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } bool value; - *status = port->module->GetSolenoidStickyFault(value); + *status = PCM_modules[module]->GetSolenoidStickyFault(value); return value; } -bool getPCMSolenoidVoltageFault(void* solenoid_port_pointer, int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +bool getPCMSolenoidVoltageFault(uint8_t module, int32_t* status) { + if (module >= NUM_MODULE_NUMBERS) { + *status = PARAMETER_OUT_OF_RANGE; + return false; + } bool value; - *status = port->module->GetSolenoidFault(value); + *status = PCM_modules[module]->GetSolenoidFault(value); return value; } -void clearAllPCMStickyFaults_sol(void* solenoid_port_pointer, int32_t* status) { - solenoid_port_t* port = (solenoid_port_t*)solenoid_port_pointer; +void clearAllPCMStickyFaults_sol(uint8_t module, int32_t* status) { + if (module >= NUM_MODULE_NUMBERS) { + *status = PARAMETER_OUT_OF_RANGE; + return; + } - *status = port->module->ClearStickyFaults(); + *status = PCM_modules[module]->ClearStickyFaults(); } } // extern "C" diff --git a/hal/lib/athena/handles/HandlesInternal.h b/hal/lib/athena/handles/HandlesInternal.h index 6e9510a18e..46539f519c 100644 --- a/hal/lib/athena/handles/HandlesInternal.h +++ b/hal/lib/athena/handles/HandlesInternal.h @@ -38,7 +38,8 @@ enum class HalHandleEnum { PWM = 9, DigitalPWM = 10, Counter = 11, - Compressor = 14 + Compressor = 14, + Solenoid = 15 }; static inline int16_t getHandleIndex(HalHandle handle) { diff --git a/wpilibc/athena/include/DoubleSolenoid.h b/wpilibc/athena/include/DoubleSolenoid.h index b389da157b..1473ff3eb7 100644 --- a/wpilibc/athena/include/DoubleSolenoid.h +++ b/wpilibc/athena/include/DoubleSolenoid.h @@ -9,6 +9,7 @@ #include +#include "HAL/Handles.h" #include "LiveWindow/LiveWindowSendable.h" #include "SolenoidBase.h" #include "tables/ITableListener.h" @@ -49,6 +50,8 @@ class DoubleSolenoid : public SolenoidBase, uint32_t m_reverseChannel; ///< The reverse channel on the module to control. uint8_t m_forwardMask; ///< The mask for the forward channel. uint8_t m_reverseMask; ///< The mask for the reverse channel. + HalSolenoidHandle m_forwardHandle = HAL_INVALID_HANDLE; + HalSolenoidHandle m_reverseHandle = HAL_INVALID_HANDLE; std::shared_ptr m_table; }; diff --git a/wpilibc/athena/include/Solenoid.h b/wpilibc/athena/include/Solenoid.h index 17bc52cfbf..559013caca 100644 --- a/wpilibc/athena/include/Solenoid.h +++ b/wpilibc/athena/include/Solenoid.h @@ -9,6 +9,7 @@ #include +#include "HAL/Handles.h" #include "LiveWindow/LiveWindowSendable.h" #include "SolenoidBase.h" #include "tables/ITableListener.h" @@ -40,6 +41,7 @@ class Solenoid : public SolenoidBase, std::shared_ptr GetTable() const; private: + HalSolenoidHandle m_solenoidHandle = HAL_INVALID_HANDLE; uint32_t m_channel; ///< The channel on the module to control. std::shared_ptr m_table; }; diff --git a/wpilibc/athena/include/SolenoidBase.h b/wpilibc/athena/include/SolenoidBase.h index ec539936e5..29e5ed1b69 100644 --- a/wpilibc/athena/include/SolenoidBase.h +++ b/wpilibc/athena/include/SolenoidBase.h @@ -28,11 +28,9 @@ class SolenoidBase : public SensorBase { protected: explicit SolenoidBase(uint8_t pcmID); - void Set(uint8_t value, uint8_t mask, int module); const static int m_maxModules = 63; const static int m_maxPorts = 8; - static void* m_ports[m_maxModules][m_maxPorts]; - uint32_t m_moduleNumber; ///< Slot number where the module is plugged into - /// the chassis. - static std::unique_ptr m_allocated; + // static void* m_ports[m_maxModules][m_maxPorts]; + uint8_t m_moduleNumber; ///< Slot number where the module is plugged into + /// the chassis. }; diff --git a/wpilibc/athena/src/DoubleSolenoid.cpp b/wpilibc/athena/src/DoubleSolenoid.cpp index 1f6d192079..819cc8dd3c 100644 --- a/wpilibc/athena/src/DoubleSolenoid.cpp +++ b/wpilibc/athena/src/DoubleSolenoid.cpp @@ -52,28 +52,30 @@ DoubleSolenoid::DoubleSolenoid(uint8_t moduleNumber, uint32_t forwardChannel, wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str()); return; } - Resource::CreateResourceObject(m_allocated, m_maxModules * m_maxPorts); - - buf << "Solenoid " << m_forwardChannel << " (Module: " << m_moduleNumber - << ")"; - if (m_allocated->Allocate( - m_moduleNumber * kSolenoidChannels + m_forwardChannel, buf.str()) == - std::numeric_limits::max()) { - CloneError(*m_allocated); + int32_t status = 0; + m_forwardHandle = initializeSolenoidPort( + getPortWithModule(moduleNumber, m_forwardChannel), &status); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_forwardHandle = HAL_INVALID_HANDLE; + m_reverseHandle = HAL_INVALID_HANDLE; return; } - buf << "Solenoid " << m_reverseChannel << " (Module: " << m_moduleNumber - << ")"; - if (m_allocated->Allocate( - m_moduleNumber * kSolenoidChannels + m_reverseChannel, buf.str()) == - std::numeric_limits::max()) { - CloneError(*m_allocated); + m_reverseHandle = initializeSolenoidPort( + getPortWithModule(moduleNumber, m_reverseChannel), &status); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + // free forward solenoid + freeSolenoidPort(m_forwardHandle); + m_forwardHandle = HAL_INVALID_HANDLE; + m_reverseHandle = HAL_INVALID_HANDLE; return; } m_forwardMask = 1 << m_forwardChannel; m_reverseMask = 1 << m_reverseChannel; + HALReport(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel, m_moduleNumber); HALReport(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel, @@ -86,10 +88,8 @@ DoubleSolenoid::DoubleSolenoid(uint8_t moduleNumber, uint32_t forwardChannel, * Destructor. */ DoubleSolenoid::~DoubleSolenoid() { - if (CheckSolenoidModule(m_moduleNumber)) { - m_allocated->Free(m_moduleNumber * kSolenoidChannels + m_forwardChannel); - m_allocated->Free(m_moduleNumber * kSolenoidChannels + m_reverseChannel); - } + freeSolenoidPort(m_forwardHandle); + freeSolenoidPort(m_reverseHandle); if (m_table != nullptr) m_table->RemoveTableListener(this); } @@ -100,21 +100,30 @@ DoubleSolenoid::~DoubleSolenoid() { */ void DoubleSolenoid::Set(Value value) { if (StatusIsFatal()) return; - uint8_t rawValue = 0x00; + bool forward = false; + bool reverse = false; switch (value) { case kOff: - rawValue = 0x00; + forward = false; + reverse = false; break; case kForward: - rawValue = m_forwardMask; + forward = true; + reverse = false; break; case kReverse: - rawValue = m_reverseMask; + forward = false; + reverse = true; break; } + int32_t fstatus = 0; + setSolenoid(m_forwardHandle, forward, &fstatus); + int32_t rstatus = 0; + setSolenoid(m_reverseHandle, reverse, &rstatus); - SolenoidBase::Set(rawValue, m_forwardMask | m_reverseMask, m_moduleNumber); + wpi_setErrorWithContext(fstatus, getHALErrorMessage(fstatus)); + wpi_setErrorWithContext(rstatus, getHALErrorMessage(rstatus)); } /** @@ -124,10 +133,16 @@ void DoubleSolenoid::Set(Value value) { */ DoubleSolenoid::Value DoubleSolenoid::Get() const { if (StatusIsFatal()) return kOff; - uint8_t value = GetAll(m_moduleNumber); + int32_t fstatus = 0; + int32_t rstatus = 0; + bool valueForward = getSolenoid(m_forwardHandle, &fstatus); + bool valueReverse = getSolenoid(m_reverseHandle, &rstatus); - if (value & m_forwardMask) return kForward; - if (value & m_reverseMask) return kReverse; + wpi_setErrorWithContext(fstatus, getHALErrorMessage(fstatus)); + wpi_setErrorWithContext(rstatus, getHALErrorMessage(rstatus)); + + if (valueForward) return kForward; + if (valueReverse) return kReverse; return kOff; } /** diff --git a/wpilibc/athena/src/Solenoid.cpp b/wpilibc/athena/src/Solenoid.cpp index 177159c7e2..1355ec9ee6 100644 --- a/wpilibc/athena/src/Solenoid.cpp +++ b/wpilibc/athena/src/Solenoid.cpp @@ -39,12 +39,13 @@ Solenoid::Solenoid(uint8_t moduleNumber, uint32_t channel) wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str()); return; } - Resource::CreateResourceObject(m_allocated, m_maxModules * m_maxPorts); - buf << "Solenoid " << m_channel << " (Module: " << m_moduleNumber << ")"; - if (m_allocated->Allocate(m_moduleNumber * kSolenoidChannels + m_channel, - buf.str()) == - std::numeric_limits::max()) { - CloneError(*m_allocated); + + int32_t status = 0; + m_solenoidHandle = + initializeSolenoidPort(getPortWithModule(moduleNumber, channel), &status); + if (status != 0) { + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_solenoidHandle = HAL_INVALID_HANDLE; return; } @@ -58,9 +59,7 @@ Solenoid::Solenoid(uint8_t moduleNumber, uint32_t channel) * Destructor. */ Solenoid::~Solenoid() { - if (CheckSolenoidModule(m_moduleNumber)) { - m_allocated->Free(m_moduleNumber * kSolenoidChannels + m_channel); - } + freeSolenoidPort(m_solenoidHandle); if (m_table != nullptr) m_table->RemoveTableListener(this); } @@ -71,10 +70,9 @@ Solenoid::~Solenoid() { */ void Solenoid::Set(bool on) { if (StatusIsFatal()) return; - uint8_t value = on ? 0xFF : 0x00; - uint8_t mask = 1 << m_channel; - - SolenoidBase::Set(value, mask, m_moduleNumber); + int32_t status = 0; + setSolenoid(m_solenoidHandle, on, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); } /** @@ -84,8 +82,10 @@ void Solenoid::Set(bool on) { */ bool Solenoid::Get() const { if (StatusIsFatal()) return false; - uint8_t value = GetAll(m_moduleNumber) & (1 << m_channel); - return (value != 0); + int32_t status = 0; + bool value = getSolenoid(m_solenoidHandle, &status); + wpi_setErrorWithContext(status, getHALErrorMessage(status)); + return value; } /** diff --git a/wpilibc/athena/src/SolenoidBase.cpp b/wpilibc/athena/src/SolenoidBase.cpp index 8679296a0f..aa6fcf8715 100644 --- a/wpilibc/athena/src/SolenoidBase.cpp +++ b/wpilibc/athena/src/SolenoidBase.cpp @@ -9,40 +9,13 @@ #include "HAL/HAL.h" -void* SolenoidBase::m_ports[m_maxModules][m_maxPorts]; -std::unique_ptr SolenoidBase::m_allocated; - /** * Constructor * * @param moduleNumber The CAN PCM ID. */ SolenoidBase::SolenoidBase(uint8_t moduleNumber) - : m_moduleNumber(moduleNumber) { - for (uint32_t i = 0; i < kSolenoidChannels; i++) { - HalPortHandle port = getPortWithModule(moduleNumber, i); - int32_t status = 0; - SolenoidBase::m_ports[moduleNumber][i] = - initializeSolenoidPort(port, &status); - wpi_setErrorWithContext(status, getHALErrorMessage(status)); - } -} - -/** - * Set the value of a solenoid. - * - * @param value The value you want to set on the module. - * @param mask The channels you want to be affected. - */ -void SolenoidBase::Set(uint8_t value, uint8_t mask, int module) { - int32_t status = 0; - for (int i = 0; i < m_maxPorts; i++) { - uint8_t local_mask = 1 << i; - if (mask & local_mask) - setSolenoid(m_ports[module][i], value & local_mask, &status); - } - wpi_setErrorWithContext(status, getHALErrorMessage(status)); -} + : m_moduleNumber(moduleNumber) {} /** * Read all 8 solenoids as a single byte @@ -52,7 +25,7 @@ void SolenoidBase::Set(uint8_t value, uint8_t mask, int module) { uint8_t SolenoidBase::GetAll(int module) const { uint8_t value = 0; int32_t status = 0; - value = getAllSolenoids(m_ports[module][0], &status); + value = getAllSolenoids(static_cast(module), &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); return value; } @@ -68,7 +41,7 @@ uint8_t SolenoidBase::GetAll(int module) const { */ uint8_t SolenoidBase::GetPCMSolenoidBlackList(int module) const { int32_t status = 0; - return getPCMSolenoidBlackList(m_ports[module][0], &status); + return getPCMSolenoidBlackList(static_cast(module), &status); } /** @@ -77,7 +50,8 @@ uint8_t SolenoidBase::GetPCMSolenoidBlackList(int module) const { */ bool SolenoidBase::GetPCMSolenoidVoltageStickyFault(int module) const { int32_t status = 0; - return getPCMSolenoidVoltageStickyFault(m_ports[module][0], &status); + return getPCMSolenoidVoltageStickyFault(static_cast(module), + &status); } /** @@ -86,7 +60,7 @@ bool SolenoidBase::GetPCMSolenoidVoltageStickyFault(int module) const { */ bool SolenoidBase::GetPCMSolenoidVoltageFault(int module) const { int32_t status = 0; - return getPCMSolenoidVoltageFault(m_ports[module][0], &status); + return getPCMSolenoidVoltageFault(static_cast(module), &status); } /** @@ -101,5 +75,5 @@ bool SolenoidBase::GetPCMSolenoidVoltageFault(int module) const { */ void SolenoidBase::ClearAllPCMStickyFaults(int module) { int32_t status = 0; - return clearAllPCMStickyFaults_sol(m_ports[module][0], &status); + return clearAllPCMStickyFaults_sol(static_cast(module), &status); } diff --git a/wpilibj/src/athena/cpp/lib/SolenoidJNI.cpp b/wpilibj/src/athena/cpp/lib/SolenoidJNI.cpp index 2a85ea9e56..8206e672b6 100644 --- a/wpilibj/src/athena/cpp/lib/SolenoidJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/SolenoidJNI.cpp @@ -26,75 +26,67 @@ extern "C" { /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: initializeSolenoidPort - * Signature: (I)J + * Signature: (I)I */ -JNIEXPORT jlong JNICALL +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_initializeSolenoidPort( JNIEnv *env, jclass, jint port_handle) { SOLENOIDJNI_LOG(logDEBUG) << "Calling SolenoidJNI initializeSolenoidPort"; SOLENOIDJNI_LOG(logDEBUG) << "Port Handle = " << (HalPortHandle)port_handle; - char *aschars = (char *)port_handle; - SOLENOIDJNI_LOG(logDEBUG) << '\t' << (int)aschars[0] << '\t' - << (int)aschars[1] << std::endl; int32_t status = 0; - void *solenoid_port_pointer = + HalSolenoidHandle handle = initializeSolenoidPort((HalPortHandle)port_handle, &status); SOLENOIDJNI_LOG(logDEBUG) << "Status = " << status; - SOLENOIDJNI_LOG(logDEBUG) << "Solenoid Port Pointer = " - << solenoid_port_pointer; - - int *asints = (int *)solenoid_port_pointer; - SOLENOIDJNI_LOG(logDEBUG) << '\t' << asints[0] << '\t' << asints[1] - << std::endl; + SOLENOIDJNI_LOG(logDEBUG) << "Solenoid Port Handle = " << handle; CheckStatus(env, status); - return (jlong)solenoid_port_pointer; + return (jint)handle; } /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: freeSolenoidPort - * Signature: (J)V + * Signature: (I)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_freeSolenoidPort( - JNIEnv *env, jclass, jlong id) { + JNIEnv *env, jclass, jint id) { SOLENOIDJNI_LOG(logDEBUG) << "Calling SolenoidJNI initializeSolenoidPort"; - SOLENOIDJNI_LOG(logDEBUG) << "Port Ptr = " << (void *)id; - freeSolenoidPort((void *)id); + SOLENOIDJNI_LOG(logDEBUG) << "Port Handle = " << (HalSolenoidHandle)id; + freeSolenoidPort((HalSolenoidHandle)id); } /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: setSolenoid - * Signature: (JZ)V + * Signature: (IZ)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_setSolenoid( - JNIEnv *env, jclass, jlong solenoid_port, jboolean value) { + JNIEnv *env, jclass, jint solenoid_port, jboolean value) { SOLENOIDJNI_LOG(logDEBUG) << "Calling SolenoidJNI SetSolenoid"; - SOLENOIDJNI_LOG(logDEBUG) << "Solenoid Port Pointer = " - << (void *)solenoid_port; + SOLENOIDJNI_LOG(logDEBUG) << "Solenoid Port Handle = " + << (HalSolenoidHandle)solenoid_port; int32_t status = 0; - setSolenoid((void *)solenoid_port, value, &status); + setSolenoid((HalSolenoidHandle)solenoid_port, value, &status); CheckStatus(env, status); } /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: getSolenoid - * Signature: (J)Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getSolenoid( - JNIEnv *env, jclass, jlong solenoid_port) { + JNIEnv *env, jclass, jint solenoid_port) { int32_t status = 0; - jboolean val = getSolenoid((void *)solenoid_port, &status); + jboolean val = getSolenoid((HalSolenoidHandle)solenoid_port, &status); CheckStatus(env, status); return val; } @@ -102,13 +94,13 @@ Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getSolenoid( /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: getAllSolenoids - * Signature: (J)Z + * Signature: (B)Z */ JNIEXPORT jbyte JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getAllSolenoids( - JNIEnv *env, jclass, jlong solenoid_port) { + JNIEnv *env, jclass, jbyte module) { int32_t status = 0; - jbyte val = getAllSolenoids((void *)solenoid_port, &status); + jbyte val = getAllSolenoids(module, &status); CheckStatus(env, status); return val; } @@ -116,52 +108,52 @@ Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getAllSolenoids( /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: getPCMSolenoidBlackList - * Signature: (J)I + * Signature: (B)I */ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getPCMSolenoidBlackList( - JNIEnv *env, jclass, jlong solenoid_port) { + JNIEnv *env, jclass, jbyte module) { int32_t status = 0; - jint val = getPCMSolenoidBlackList((void *)solenoid_port, &status); + jint val = getPCMSolenoidBlackList(module, &status); CheckStatus(env, status); return val; } /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: getPCMSolenoidVoltageStickyFault - * Signature: (J)Z + * Signature: (B)Z */ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getPCMSolenoidVoltageStickyFault( - JNIEnv *env, jclass, jlong solenoid_port) { + JNIEnv *env, jclass, jbyte module) { int32_t status = 0; - bool val = getPCMSolenoidVoltageStickyFault((void *)solenoid_port, &status); + bool val = getPCMSolenoidVoltageStickyFault(module, &status); CheckStatus(env, status); return val; } /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: getPCMSolenoidVoltageFault - * Signature: (J)Z + * Signature: (B)Z */ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_getPCMSolenoidVoltageFault( - JNIEnv *env, jclass, jlong solenoid_port) { + JNIEnv *env, jclass, jbyte module) { int32_t status = 0; - bool val = getPCMSolenoidVoltageFault((void *)solenoid_port, &status); + bool val = getPCMSolenoidVoltageFault(module, &status); CheckStatus(env, status); return val; } /* * Class: edu_wpi_first_wpilibj_hal_SolenoidJNI * Method: clearAllPCMStickyFaults - * Signature: (J)V + * Signature: (B)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_clearAllPCMStickyFaults( - JNIEnv *env, jclass, jlong solenoid_port) { + JNIEnv *env, jclass, jbyte module) { int32_t status = 0; - clearAllPCMStickyFaults_sol((void *)solenoid_port, &status); + clearAllPCMStickyFaults_sol(module, &status); CheckStatus(env, status); } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DoubleSolenoid.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DoubleSolenoid.java index d008387892..06cca2fbb6 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DoubleSolenoid.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/DoubleSolenoid.java @@ -9,6 +9,7 @@ package edu.wpi.first.wpilibj; import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType; import edu.wpi.first.wpilibj.communication.UsageReporting; +import edu.wpi.first.wpilibj.hal.SolenoidJNI; import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable; import edu.wpi.first.wpilibj.tables.ITable; @@ -37,6 +38,8 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable { private int m_reverseChannel; // /< The reverse channel on the module to control. private byte m_forwardMask; // /< The mask for the forward channel. private byte m_reverseMask; // /< The mask for the reverse channel. + private int m_forwardHandle = 0; + private int m_reverseHandle = 0; /** * Constructor. Uses the default PCM ID of 0. @@ -65,18 +68,20 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable { checkSolenoidChannel(m_forwardChannel); checkSolenoidChannel(m_reverseChannel); + int portHandle = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) m_forwardChannel); + m_forwardHandle = SolenoidJNI.initializeSolenoidPort(portHandle); + try { - allocated.allocate(m_moduleNumber * kSolenoidChannels + m_forwardChannel); - } catch (CheckedAllocationException exception) { - throw new AllocationException("Solenoid channel " + m_forwardChannel + " on module " - + m_moduleNumber + " is already allocated"); - } - try { - allocated.allocate(m_moduleNumber * kSolenoidChannels + m_reverseChannel); - } catch (CheckedAllocationException exception) { - throw new AllocationException("Solenoid channel " + m_reverseChannel + " on module " - + m_moduleNumber + " is already allocated"); + portHandle = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) m_reverseChannel); + m_reverseHandle = SolenoidJNI.initializeSolenoidPort(portHandle); + } catch (RuntimeException ex) { + // free the forward handle on exception, then rethrow + SolenoidJNI.freeSolenoidPort(m_forwardHandle); + m_forwardHandle = 0; + m_reverseHandle = 0; + throw ex; } + m_forwardMask = (byte) (1 << m_forwardChannel); m_reverseMask = (byte) (1 << m_reverseChannel); @@ -89,8 +94,8 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable { * Destructor. */ public synchronized void free() { - allocated.free(m_moduleNumber * kSolenoidChannels + m_forwardChannel); - allocated.free(m_moduleNumber * kSolenoidChannels + m_reverseChannel); + SolenoidJNI.freeSolenoidPort(m_forwardHandle); + SolenoidJNI.freeSolenoidPort(m_reverseChannel); super.free(); } @@ -100,24 +105,29 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable { * @param value The value to set (Off, Forward, Reverse) */ public void set(final Value value) { - final byte rawValue; - + boolean forward = false; + boolean reverse = false; + switch (value) { case kOff: - rawValue = 0x00; + forward = false; + reverse = false; break; case kForward: - rawValue = m_forwardMask; + forward = true; + reverse = false; break; case kReverse: - rawValue = m_reverseMask; + forward = false; + reverse = true; break; default: throw new AssertionError("Illegal value: " + value); } - set(rawValue, m_forwardMask | m_reverseMask); + SolenoidJNI.setSolenoid(m_forwardHandle, forward); + SolenoidJNI.setSolenoid(m_reverseHandle, reverse); } /** @@ -126,12 +136,13 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable { * @return The current value of the solenoid. */ public Value get() { - byte value = getAll(); - - if ((value & m_forwardMask) != 0) { + boolean valueForward = SolenoidJNI.getSolenoid(m_forwardHandle); + boolean valueReverse = SolenoidJNI.getSolenoid(m_reverseHandle); + + if (valueForward) { return Value.kForward; } - if ((value & m_reverseMask) != 0) { + if (valueReverse) { return Value.kReverse; } return Value.kOff; diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Solenoid.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Solenoid.java index 9113f5feba..a45333dcd7 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Solenoid.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/Solenoid.java @@ -26,7 +26,7 @@ import edu.wpi.first.wpilibj.util.CheckedAllocationException; public class Solenoid extends SolenoidBase implements LiveWindowSendable { private final int m_channel; // /< The channel to control. - private long m_solenoidPort; + private int m_solenoidHandle; /** * Constructor using the default PCM ID (0) @@ -50,15 +50,8 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable { checkSolenoidModule(m_moduleNumber); checkSolenoidChannel(m_channel); - try { - allocated.allocate(m_moduleNumber * kSolenoidChannels + m_channel); - } catch (CheckedAllocationException ex) { - throw new AllocationException("Solenoid channel " + m_channel + " on module " - + m_moduleNumber + " is already allocated"); - } - int portHandle = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) m_channel); - m_solenoidPort = SolenoidJNI.initializeSolenoidPort(portHandle); + m_solenoidHandle = SolenoidJNI.initializeSolenoidPort(portHandle); LiveWindow.addActuator("Solenoid", m_moduleNumber, m_channel, this); UsageReporting.report(tResourceType.kResourceType_Solenoid, m_channel, m_moduleNumber); @@ -68,9 +61,11 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable { * Destructor. */ public synchronized void free() { - allocated.free(m_moduleNumber * kSolenoidChannels + m_channel); - SolenoidJNI.freeSolenoidPort(m_solenoidPort); - m_solenoidPort = 0; + SolenoidJNI.freeSolenoidPort(m_solenoidHandle); + m_solenoidHandle = 0; + if (m_table != null) { + m_table.removeTableListener(m_tableListener); + } super.free(); } @@ -80,10 +75,7 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable { * @param on Turn the solenoid output off or on. */ public void set(boolean on) { - byte value = (byte) (on ? 0xFF : 0x00); - byte mask = (byte) (1 << m_channel); - - set(value, mask); + SolenoidJNI.setSolenoid(m_solenoidHandle, on); } /** @@ -92,8 +84,7 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable { * @return The current value of the solenoid. */ public boolean get() { - int value = getAll() & (1 << m_channel); - return (value != 0); + return SolenoidJNI.getSolenoid(m_solenoidHandle); } /** diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SolenoidBase.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SolenoidBase.java index 50b3eb055f..e79b684e9f 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SolenoidBase.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SolenoidBase.java @@ -13,11 +13,8 @@ import edu.wpi.first.wpilibj.hal.SolenoidJNI; * SolenoidBase class is the common base class for the Solenoid and DoubleSolenoid classes. */ public abstract class SolenoidBase extends SensorBase { - - private final long[] m_ports; - protected final int m_moduleNumber; // /< The number of the solenoid module being + protected final byte m_moduleNumber; // /< The number of the solenoid module being // used. - protected static final Resource allocated = new Resource(63 * SensorBase.kSolenoidChannels); /** * Constructor. @@ -25,38 +22,7 @@ public abstract class SolenoidBase extends SensorBase { * @param moduleNumber The PCM CAN ID */ public SolenoidBase(final int moduleNumber) { - m_moduleNumber = moduleNumber; - m_ports = new long[SensorBase.kSolenoidChannels]; - for (int i = 0; i < SensorBase.kSolenoidChannels; i++) { - int portHandle = SolenoidJNI.getPortWithModule((byte) moduleNumber, (byte) i); - m_ports[i] = SolenoidJNI.initializeSolenoidPort(portHandle); - } - } - - /** - * Free the resources associated with by the solenoid base. - */ - @Override - public void free() { - for (int i = 0; i < m_ports.length; i++) { - SolenoidJNI.freeSolenoidPort(m_ports[i]); - m_ports[i] = 0; - } - } - - /** - * Set the value of a solenoid. - * - * @param value The value you want to set on the module. - * @param mask The channels you want to be affected. - */ - protected synchronized void set(int value, int mask) { - for (int i = 0; i < SensorBase.kSolenoidChannels; i++) { - int localMask = 1 << i; - if ((mask & localMask) != 0) { - SolenoidJNI.setSolenoid(m_ports[i], (value & localMask) != 0); - } - } + m_moduleNumber = (byte)moduleNumber; } /** @@ -65,7 +31,7 @@ public abstract class SolenoidBase extends SensorBase { * @return The current value of all 8 solenoids on this module. */ public byte getAll() { - return SolenoidJNI.getAllSolenoids(m_ports[0]); + return SolenoidJNI.getAllSolenoids(m_moduleNumber); } /** @@ -77,7 +43,7 @@ public abstract class SolenoidBase extends SensorBase { * @see #clearAllPCMStickyFaults() */ public byte getPCMSolenoidBlackList() { - return (byte) SolenoidJNI.getPCMSolenoidBlackList(m_ports[0]); + return (byte) SolenoidJNI.getPCMSolenoidBlackList(m_moduleNumber); } /** @@ -87,7 +53,7 @@ public abstract class SolenoidBase extends SensorBase { * @return true if PCM sticky fault is set */ public boolean getPCMSolenoidVoltageStickyFault() { - return SolenoidJNI.getPCMSolenoidVoltageStickyFault(m_ports[0]); + return SolenoidJNI.getPCMSolenoidVoltageStickyFault(m_moduleNumber); } /** @@ -97,7 +63,7 @@ public abstract class SolenoidBase extends SensorBase { * @return true if PCM is in fault state. */ public boolean getPCMSolenoidVoltageFault() { - return SolenoidJNI.getPCMSolenoidVoltageFault(m_ports[0]); + return SolenoidJNI.getPCMSolenoidVoltageFault(m_moduleNumber); } /** @@ -110,6 +76,6 @@ public abstract class SolenoidBase extends SensorBase { *

If no sticky faults are set then this call will have no effect. */ public void clearAllPCMStickyFaults() { - SolenoidJNI.clearAllPCMStickyFaults(m_ports[0]); + SolenoidJNI.clearAllPCMStickyFaults(m_moduleNumber); } } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/SolenoidJNI.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/SolenoidJNI.java index d660c33a03..924983a20c 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/SolenoidJNI.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/SolenoidJNI.java @@ -8,21 +8,21 @@ package edu.wpi.first.wpilibj.hal; public class SolenoidJNI extends JNIWrapper { - public static native long initializeSolenoidPort(int halPortHandle); + public static native int initializeSolenoidPort(int halPortHandle); - public static native void freeSolenoidPort(long portPointer); + public static native void freeSolenoidPort(int portHandle); - public static native void setSolenoid(long port, boolean on); + public static native void setSolenoid(int portHandle, boolean on); - public static native boolean getSolenoid(long port); + public static native boolean getSolenoid(int portHandle); - public static native byte getAllSolenoids(long port); + public static native byte getAllSolenoids(byte module); - public static native int getPCMSolenoidBlackList(long pcmPointer); + public static native int getPCMSolenoidBlackList(byte module); - public static native boolean getPCMSolenoidVoltageStickyFault(long pcmPointer); + public static native boolean getPCMSolenoidVoltageStickyFault(byte module); - public static native boolean getPCMSolenoidVoltageFault(long pcmPointer); + public static native boolean getPCMSolenoidVoltageFault(byte module); - public static native void clearAllPCMStickyFaults(long pcmPointer); + public static native void clearAllPCMStickyFaults(byte module); }