blob: c111622545cd89613f975fa8319956db956baa13 [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() {
James Kuszmaulcf324122023-01-14 14:07:17 -080068 if (m_module) {
69 m_module->UnreserveSolenoids(m_mask);
70 }
Brian Silverman8fce7482020-01-05 13:18:21 -080071}
72
73void DoubleSolenoid::Set(Value value) {
Austin Schuh812d0d12021-11-04 20:16:48 -070074 int setValue = 0;
Austin Schuh1e69f942020-11-14 15:06:14 -080075
Brian Silverman8fce7482020-01-05 13:18:21 -080076 switch (value) {
77 case kOff:
Austin Schuh812d0d12021-11-04 20:16:48 -070078 setValue = 0;
Brian Silverman8fce7482020-01-05 13:18:21 -080079 break;
80 case kForward:
Austin Schuh812d0d12021-11-04 20:16:48 -070081 setValue = m_forwardMask;
Brian Silverman8fce7482020-01-05 13:18:21 -080082 break;
83 case kReverse:
Austin Schuh812d0d12021-11-04 20:16:48 -070084 setValue = m_reverseMask;
Brian Silverman8fce7482020-01-05 13:18:21 -080085 break;
86 }
Austin Schuh1e69f942020-11-14 15:06:14 -080087
Austin Schuh812d0d12021-11-04 20:16:48 -070088 m_module->SetSolenoids(m_mask, setValue);
Brian Silverman8fce7482020-01-05 13:18:21 -080089}
90
91DoubleSolenoid::Value DoubleSolenoid::Get() const {
Austin Schuh812d0d12021-11-04 20:16:48 -070092 auto values = m_module->GetSolenoids();
Austin Schuh1e69f942020-11-14 15:06:14 -080093
Austin Schuh812d0d12021-11-04 20:16:48 -070094 if ((values & m_forwardMask) != 0) {
95 return Value::kForward;
96 } else if ((values & m_reverseMask) != 0) {
97 return Value::kReverse;
Austin Schuh1e69f942020-11-14 15:06:14 -080098 } else {
Austin Schuh812d0d12021-11-04 20:16:48 -070099 return Value::kOff;
Austin Schuh1e69f942020-11-14 15:06:14 -0800100 }
101}
102
103void DoubleSolenoid::Toggle() {
104 Value value = Get();
105
106 if (value == kForward) {
107 Set(kReverse);
108 } else if (value == kReverse) {
109 Set(kForward);
110 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800111}
112
Austin Schuh812d0d12021-11-04 20:16:48 -0700113int DoubleSolenoid::GetFwdChannel() const {
114 return m_forwardChannel;
Brian Silverman8fce7482020-01-05 13:18:21 -0800115}
116
Austin Schuh812d0d12021-11-04 20:16:48 -0700117int DoubleSolenoid::GetRevChannel() const {
118 return m_reverseChannel;
Brian Silverman8fce7482020-01-05 13:18:21 -0800119}
120
Austin Schuh812d0d12021-11-04 20:16:48 -0700121bool DoubleSolenoid::IsFwdSolenoidDisabled() const {
122 return (m_module->GetSolenoidDisabledList() & m_forwardMask) != 0;
123}
124
125bool DoubleSolenoid::IsRevSolenoidDisabled() const {
126 return (m_module->GetSolenoidDisabledList() & m_reverseMask) != 0;
127}
128
129void DoubleSolenoid::InitSendable(wpi::SendableBuilder& builder) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800130 builder.SetSmartDashboardType("Double Solenoid");
131 builder.SetActuator(true);
James Kuszmaulcf324122023-01-14 14:07:17 -0800132 builder.SetSafeState([=, this] { Set(kOff); });
Brian Silverman8fce7482020-01-05 13:18:21 -0800133 builder.AddSmallStringProperty(
134 "Value",
James Kuszmaulcf324122023-01-14 14:07:17 -0800135 [=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
Brian Silverman8fce7482020-01-05 13:18:21 -0800136 switch (Get()) {
137 case kForward:
138 return "Forward";
139 case kReverse:
140 return "Reverse";
141 default:
142 return "Off";
143 }
144 },
James Kuszmaulcf324122023-01-14 14:07:17 -0800145 [=, this](std::string_view value) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800146 Value lvalue = kOff;
Austin Schuh812d0d12021-11-04 20:16:48 -0700147 if (value == "Forward") {
Brian Silverman8fce7482020-01-05 13:18:21 -0800148 lvalue = kForward;
Austin Schuh812d0d12021-11-04 20:16:48 -0700149 } else if (value == "Reverse") {
Brian Silverman8fce7482020-01-05 13:18:21 -0800150 lvalue = kReverse;
Austin Schuh812d0d12021-11-04 20:16:48 -0700151 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800152 Set(lvalue);
153 });
154}