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() { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 68 | m_module->UnreserveSolenoids(m_mask); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | void DoubleSolenoid::Set(Value value) { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 72 | int setValue = 0; |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 73 | |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 74 | switch (value) { |
| 75 | case kOff: |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 76 | setValue = 0; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 77 | break; |
| 78 | case kForward: |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 79 | setValue = m_forwardMask; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 80 | break; |
| 81 | case kReverse: |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 82 | setValue = m_reverseMask; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 83 | break; |
| 84 | } |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 85 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 86 | m_module->SetSolenoids(m_mask, setValue); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | DoubleSolenoid::Value DoubleSolenoid::Get() const { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 90 | auto values = m_module->GetSolenoids(); |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 91 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 92 | if ((values & m_forwardMask) != 0) { |
| 93 | return Value::kForward; |
| 94 | } else if ((values & m_reverseMask) != 0) { |
| 95 | return Value::kReverse; |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 96 | } else { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 97 | return Value::kOff; |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 98 | } |
| 99 | } |
| 100 | |
| 101 | void DoubleSolenoid::Toggle() { |
| 102 | Value value = Get(); |
| 103 | |
| 104 | if (value == kForward) { |
| 105 | Set(kReverse); |
| 106 | } else if (value == kReverse) { |
| 107 | Set(kForward); |
| 108 | } |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 109 | } |
| 110 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 111 | int DoubleSolenoid::GetFwdChannel() const { |
| 112 | return m_forwardChannel; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 113 | } |
| 114 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 115 | int DoubleSolenoid::GetRevChannel() const { |
| 116 | return m_reverseChannel; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 117 | } |
| 118 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 119 | bool DoubleSolenoid::IsFwdSolenoidDisabled() const { |
| 120 | return (m_module->GetSolenoidDisabledList() & m_forwardMask) != 0; |
| 121 | } |
| 122 | |
| 123 | bool DoubleSolenoid::IsRevSolenoidDisabled() const { |
| 124 | return (m_module->GetSolenoidDisabledList() & m_reverseMask) != 0; |
| 125 | } |
| 126 | |
| 127 | void DoubleSolenoid::InitSendable(wpi::SendableBuilder& builder) { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 128 | builder.SetSmartDashboardType("Double Solenoid"); |
| 129 | builder.SetActuator(true); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 130 | builder.SetSafeState([=] { Set(kOff); }); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 131 | builder.AddSmallStringProperty( |
| 132 | "Value", |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 133 | [=](wpi::SmallVectorImpl<char>& buf) -> std::string_view { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 134 | switch (Get()) { |
| 135 | case kForward: |
| 136 | return "Forward"; |
| 137 | case kReverse: |
| 138 | return "Reverse"; |
| 139 | default: |
| 140 | return "Off"; |
| 141 | } |
| 142 | }, |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 143 | [=](std::string_view value) { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 144 | Value lvalue = kOff; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 145 | if (value == "Forward") { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 146 | lvalue = kForward; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 147 | } else if (value == "Reverse") { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 148 | lvalue = kReverse; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame] | 149 | } |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 150 | Set(lvalue); |
| 151 | }); |
| 152 | } |