Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 1 | // Copyright (c) FIRST and other WPILib contributors. |
| 2 | // Open Source Software; you can modify and/or share it under the terms of |
| 3 | // the WPILib BSD license file in the root directory of this project. |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 4 | |
| 5 | #include "frc/DoubleSolenoid.h" |
| 6 | |
| 7 | #include <utility> |
| 8 | |
| 9 | #include <hal/FRCUsageReporting.h> |
| 10 | #include <hal/HALBase.h> |
| 11 | #include <hal/Ports.h> |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 12 | #include <wpi/NullDeleter.h> |
| 13 | #include <wpi/sendable/SendableBuilder.h> |
| 14 | #include <wpi/sendable/SendableRegistry.h> |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 15 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 16 | #include "frc/Errors.h" |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 17 | #include "frc/SensorUtil.h" |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 18 | |
| 19 | using namespace frc; |
| 20 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 21 | DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType, |
| 22 | int forwardChannel, int reverseChannel) |
| 23 | : m_module{PneumaticsBase::GetForType(module, moduleType)}, |
| 24 | m_forwardChannel{forwardChannel}, |
| 25 | m_reverseChannel{reverseChannel} { |
| 26 | if (!m_module->CheckSolenoidChannel(m_forwardChannel)) { |
| 27 | throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", |
| 28 | m_forwardChannel); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 29 | } |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 30 | if (!m_module->CheckSolenoidChannel(m_reverseChannel)) { |
| 31 | throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", |
| 32 | m_reverseChannel); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 33 | } |
| 34 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 35 | m_forwardMask = 1 << forwardChannel; |
| 36 | m_reverseMask = 1 << reverseChannel; |
| 37 | m_mask = m_forwardMask | m_reverseMask; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 38 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 39 | int allocMask = m_module->CheckAndReserveSolenoids(m_mask); |
| 40 | if (allocMask != 0) { |
| 41 | if (allocMask == m_mask) { |
| 42 | throw FRC_MakeError(err::ResourceAlreadyAllocated, "Channels {} and {}", |
| 43 | m_forwardChannel, m_reverseChannel); |
| 44 | } else if (allocMask == m_forwardMask) { |
| 45 | throw FRC_MakeError(err::ResourceAlreadyAllocated, "Channel {}", |
| 46 | m_forwardChannel); |
| 47 | } else { |
| 48 | throw FRC_MakeError(err::ResourceAlreadyAllocated, "Channel {}", |
| 49 | m_reverseChannel); |
| 50 | } |
| 51 | } |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 52 | |
| 53 | HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel + 1, |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 54 | m_module->GetModuleNumber() + 1); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 55 | HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel + 1, |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 56 | m_module->GetModuleNumber() + 1); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 57 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 58 | wpi::SendableRegistry::AddLW(this, "DoubleSolenoid", |
| 59 | m_module->GetModuleNumber(), m_forwardChannel); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 60 | } |
| 61 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 62 | DoubleSolenoid::DoubleSolenoid(PneumaticsModuleType moduleType, |
| 63 | int forwardChannel, int reverseChannel) |
| 64 | : DoubleSolenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType, |
| 65 | forwardChannel, reverseChannel} {} |
| 66 | |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 67 | DoubleSolenoid::~DoubleSolenoid() { |
James Kuszmaul | cf32412 | 2023-01-14 14:07:17 -0800 | [diff] [blame^] | 68 | if (m_module) { |
| 69 | m_module->UnreserveSolenoids(m_mask); |
| 70 | } |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | void DoubleSolenoid::Set(Value value) { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 74 | int setValue = 0; |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 75 | |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 76 | switch (value) { |
| 77 | case kOff: |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 78 | setValue = 0; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 79 | break; |
| 80 | case kForward: |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 81 | setValue = m_forwardMask; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 82 | break; |
| 83 | case kReverse: |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 84 | setValue = m_reverseMask; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 85 | break; |
| 86 | } |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 87 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 88 | m_module->SetSolenoids(m_mask, setValue); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | DoubleSolenoid::Value DoubleSolenoid::Get() const { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 92 | auto values = m_module->GetSolenoids(); |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 93 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 94 | if ((values & m_forwardMask) != 0) { |
| 95 | return Value::kForward; |
| 96 | } else if ((values & m_reverseMask) != 0) { |
| 97 | return Value::kReverse; |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 98 | } else { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 99 | return Value::kOff; |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 100 | } |
| 101 | } |
| 102 | |
| 103 | void DoubleSolenoid::Toggle() { |
| 104 | Value value = Get(); |
| 105 | |
| 106 | if (value == kForward) { |
| 107 | Set(kReverse); |
| 108 | } else if (value == kReverse) { |
| 109 | Set(kForward); |
| 110 | } |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 111 | } |
| 112 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 113 | int DoubleSolenoid::GetFwdChannel() const { |
| 114 | return m_forwardChannel; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 115 | } |
| 116 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 117 | int DoubleSolenoid::GetRevChannel() const { |
| 118 | return m_reverseChannel; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 119 | } |
| 120 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 121 | bool DoubleSolenoid::IsFwdSolenoidDisabled() const { |
| 122 | return (m_module->GetSolenoidDisabledList() & m_forwardMask) != 0; |
| 123 | } |
| 124 | |
| 125 | bool DoubleSolenoid::IsRevSolenoidDisabled() const { |
| 126 | return (m_module->GetSolenoidDisabledList() & m_reverseMask) != 0; |
| 127 | } |
| 128 | |
| 129 | void DoubleSolenoid::InitSendable(wpi::SendableBuilder& builder) { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 130 | builder.SetSmartDashboardType("Double Solenoid"); |
| 131 | builder.SetActuator(true); |
James Kuszmaul | cf32412 | 2023-01-14 14:07:17 -0800 | [diff] [blame^] | 132 | builder.SetSafeState([=, this] { Set(kOff); }); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 133 | builder.AddSmallStringProperty( |
| 134 | "Value", |
James Kuszmaul | cf32412 | 2023-01-14 14:07:17 -0800 | [diff] [blame^] | 135 | [=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 136 | switch (Get()) { |
| 137 | case kForward: |
| 138 | return "Forward"; |
| 139 | case kReverse: |
| 140 | return "Reverse"; |
| 141 | default: |
| 142 | return "Off"; |
| 143 | } |
| 144 | }, |
James Kuszmaul | cf32412 | 2023-01-14 14:07:17 -0800 | [diff] [blame^] | 145 | [=, this](std::string_view value) { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 146 | Value lvalue = kOff; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 147 | if (value == "Forward") { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 148 | lvalue = kForward; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 149 | } else if (value == "Reverse") { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 150 | lvalue = kReverse; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 151 | } |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 152 | Set(lvalue); |
| 153 | }); |
| 154 | } |