blob: 212673a988d78b11701686ab75d7dfe095cbd9a5 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// 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 Silverman8fce7482020-01-05 13:18:21 -08004
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 Schuh812d0d12021-11-04 20:16:48 -070012#include <wpi/NullDeleter.h>
13#include <wpi/sendable/SendableBuilder.h>
14#include <wpi/sendable/SendableRegistry.h>
Brian Silverman8fce7482020-01-05 13:18:21 -080015
Austin Schuh812d0d12021-11-04 20:16:48 -070016#include "frc/Errors.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080017#include "frc/SensorUtil.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080018
19using namespace frc;
20
Austin Schuh812d0d12021-11-04 20:16:48 -070021DoubleSolenoid::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 Silverman8fce7482020-01-05 13:18:21 -080029 }
Austin Schuh812d0d12021-11-04 20:16:48 -070030 if (!m_module->CheckSolenoidChannel(m_reverseChannel)) {
31 throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}",
32 m_reverseChannel);
Brian Silverman8fce7482020-01-05 13:18:21 -080033 }
34
Austin Schuh812d0d12021-11-04 20:16:48 -070035 m_forwardMask = 1 << forwardChannel;
36 m_reverseMask = 1 << reverseChannel;
37 m_mask = m_forwardMask | m_reverseMask;
Brian Silverman8fce7482020-01-05 13:18:21 -080038
Austin Schuh812d0d12021-11-04 20:16:48 -070039 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 Silverman8fce7482020-01-05 13:18:21 -080052
53 HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel + 1,
Austin Schuh812d0d12021-11-04 20:16:48 -070054 m_module->GetModuleNumber() + 1);
Brian Silverman8fce7482020-01-05 13:18:21 -080055 HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel + 1,
Austin Schuh812d0d12021-11-04 20:16:48 -070056 m_module->GetModuleNumber() + 1);
Brian Silverman8fce7482020-01-05 13:18:21 -080057
Austin Schuh812d0d12021-11-04 20:16:48 -070058 wpi::SendableRegistry::AddLW(this, "DoubleSolenoid",
59 m_module->GetModuleNumber(), m_forwardChannel);
Brian Silverman8fce7482020-01-05 13:18:21 -080060}
61
Austin Schuh812d0d12021-11-04 20:16:48 -070062DoubleSolenoid::DoubleSolenoid(PneumaticsModuleType moduleType,
63 int forwardChannel, int reverseChannel)
64 : DoubleSolenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
65 forwardChannel, reverseChannel} {}
66
Brian Silverman8fce7482020-01-05 13:18:21 -080067DoubleSolenoid::~DoubleSolenoid() {
Austin Schuh812d0d12021-11-04 20:16:48 -070068 m_module->UnreserveSolenoids(m_mask);
Brian Silverman8fce7482020-01-05 13:18:21 -080069}
70
71void DoubleSolenoid::Set(Value value) {
Austin Schuh812d0d12021-11-04 20:16:48 -070072 int setValue = 0;
Austin Schuh1e69f942020-11-14 15:06:14 -080073
Brian Silverman8fce7482020-01-05 13:18:21 -080074 switch (value) {
75 case kOff:
Austin Schuh812d0d12021-11-04 20:16:48 -070076 setValue = 0;
Brian Silverman8fce7482020-01-05 13:18:21 -080077 break;
78 case kForward:
Austin Schuh812d0d12021-11-04 20:16:48 -070079 setValue = m_forwardMask;
Brian Silverman8fce7482020-01-05 13:18:21 -080080 break;
81 case kReverse:
Austin Schuh812d0d12021-11-04 20:16:48 -070082 setValue = m_reverseMask;
Brian Silverman8fce7482020-01-05 13:18:21 -080083 break;
84 }
Austin Schuh1e69f942020-11-14 15:06:14 -080085
Austin Schuh812d0d12021-11-04 20:16:48 -070086 m_module->SetSolenoids(m_mask, setValue);
Brian Silverman8fce7482020-01-05 13:18:21 -080087}
88
89DoubleSolenoid::Value DoubleSolenoid::Get() const {
Austin Schuh812d0d12021-11-04 20:16:48 -070090 auto values = m_module->GetSolenoids();
Austin Schuh1e69f942020-11-14 15:06:14 -080091
Austin Schuh812d0d12021-11-04 20:16:48 -070092 if ((values & m_forwardMask) != 0) {
93 return Value::kForward;
94 } else if ((values & m_reverseMask) != 0) {
95 return Value::kReverse;
Austin Schuh1e69f942020-11-14 15:06:14 -080096 } else {
Austin Schuh812d0d12021-11-04 20:16:48 -070097 return Value::kOff;
Austin Schuh1e69f942020-11-14 15:06:14 -080098 }
99}
100
101void DoubleSolenoid::Toggle() {
102 Value value = Get();
103
104 if (value == kForward) {
105 Set(kReverse);
106 } else if (value == kReverse) {
107 Set(kForward);
108 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800109}
110
Austin Schuh812d0d12021-11-04 20:16:48 -0700111int DoubleSolenoid::GetFwdChannel() const {
112 return m_forwardChannel;
Brian Silverman8fce7482020-01-05 13:18:21 -0800113}
114
Austin Schuh812d0d12021-11-04 20:16:48 -0700115int DoubleSolenoid::GetRevChannel() const {
116 return m_reverseChannel;
Brian Silverman8fce7482020-01-05 13:18:21 -0800117}
118
Austin Schuh812d0d12021-11-04 20:16:48 -0700119bool DoubleSolenoid::IsFwdSolenoidDisabled() const {
120 return (m_module->GetSolenoidDisabledList() & m_forwardMask) != 0;
121}
122
123bool DoubleSolenoid::IsRevSolenoidDisabled() const {
124 return (m_module->GetSolenoidDisabledList() & m_reverseMask) != 0;
125}
126
127void DoubleSolenoid::InitSendable(wpi::SendableBuilder& builder) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800128 builder.SetSmartDashboardType("Double Solenoid");
129 builder.SetActuator(true);
Austin Schuh812d0d12021-11-04 20:16:48 -0700130 builder.SetSafeState([=] { Set(kOff); });
Brian Silverman8fce7482020-01-05 13:18:21 -0800131 builder.AddSmallStringProperty(
132 "Value",
Austin Schuh812d0d12021-11-04 20:16:48 -0700133 [=](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
Brian Silverman8fce7482020-01-05 13:18:21 -0800134 switch (Get()) {
135 case kForward:
136 return "Forward";
137 case kReverse:
138 return "Reverse";
139 default:
140 return "Off";
141 }
142 },
Austin Schuh812d0d12021-11-04 20:16:48 -0700143 [=](std::string_view value) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800144 Value lvalue = kOff;
Austin Schuh812d0d12021-11-04 20:16:48 -0700145 if (value == "Forward") {
Brian Silverman8fce7482020-01-05 13:18:21 -0800146 lvalue = kForward;
Austin Schuh812d0d12021-11-04 20:16:48 -0700147 } else if (value == "Reverse") {
Brian Silverman8fce7482020-01-05 13:18:21 -0800148 lvalue = kReverse;
Austin Schuh812d0d12021-11-04 20:16:48 -0700149 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800150 Set(lvalue);
151 });
152}