blob: 0b35ff532262853975e302fc69fdd8ec33392916 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -08002/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
Brian Silverman41cdd3e2019-01-19 19:48:58 -08003/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "frc/DoubleSolenoid.h"
9
10#include <utility>
11
12#include <hal/HAL.h>
13#include <hal/Ports.h>
14#include <hal/Solenoid.h>
15
16#include "frc/SensorUtil.h"
17#include "frc/WPIErrors.h"
18#include "frc/smartdashboard/SendableBuilder.h"
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080019#include "frc/smartdashboard/SendableRegistry.h"
Brian Silverman41cdd3e2019-01-19 19:48:58 -080020
21using namespace frc;
22
23DoubleSolenoid::DoubleSolenoid(int forwardChannel, int reverseChannel)
24 : DoubleSolenoid(SensorUtil::GetDefaultSolenoidModule(), forwardChannel,
25 reverseChannel) {}
26
27DoubleSolenoid::DoubleSolenoid(int moduleNumber, int forwardChannel,
28 int reverseChannel)
29 : SolenoidBase(moduleNumber),
30 m_forwardChannel(forwardChannel),
31 m_reverseChannel(reverseChannel) {
32 if (!SensorUtil::CheckSolenoidModule(m_moduleNumber)) {
33 wpi_setWPIErrorWithContext(ModuleIndexOutOfRange,
34 "Solenoid Module " + wpi::Twine(m_moduleNumber));
35 return;
36 }
37 if (!SensorUtil::CheckSolenoidChannel(m_forwardChannel)) {
38 wpi_setWPIErrorWithContext(
39 ChannelIndexOutOfRange,
40 "Solenoid Channel " + wpi::Twine(m_forwardChannel));
41 return;
42 }
43 if (!SensorUtil::CheckSolenoidChannel(m_reverseChannel)) {
44 wpi_setWPIErrorWithContext(
45 ChannelIndexOutOfRange,
46 "Solenoid Channel " + wpi::Twine(m_reverseChannel));
47 return;
48 }
49 int32_t status = 0;
50 m_forwardHandle = HAL_InitializeSolenoidPort(
51 HAL_GetPortWithModule(moduleNumber, m_forwardChannel), &status);
52 if (status != 0) {
53 wpi_setErrorWithContextRange(status, 0, HAL_GetNumSolenoidChannels(),
54 forwardChannel, HAL_GetErrorMessage(status));
55 m_forwardHandle = HAL_kInvalidHandle;
56 m_reverseHandle = HAL_kInvalidHandle;
57 return;
58 }
59
60 m_reverseHandle = HAL_InitializeSolenoidPort(
61 HAL_GetPortWithModule(moduleNumber, m_reverseChannel), &status);
62 if (status != 0) {
63 wpi_setErrorWithContextRange(status, 0, HAL_GetNumSolenoidChannels(),
64 reverseChannel, HAL_GetErrorMessage(status));
65 // free forward solenoid
66 HAL_FreeSolenoidPort(m_forwardHandle);
67 m_forwardHandle = HAL_kInvalidHandle;
68 m_reverseHandle = HAL_kInvalidHandle;
69 return;
70 }
71
72 m_forwardMask = 1 << m_forwardChannel;
73 m_reverseMask = 1 << m_reverseChannel;
74
75 HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel,
76 m_moduleNumber);
77 HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel,
78 m_moduleNumber);
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080079
80 SendableRegistry::GetInstance().AddLW(this, "DoubleSolenoid", m_moduleNumber,
81 m_forwardChannel);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080082}
83
84DoubleSolenoid::~DoubleSolenoid() {
85 HAL_FreeSolenoidPort(m_forwardHandle);
86 HAL_FreeSolenoidPort(m_reverseHandle);
87}
88
Brian Silverman41cdd3e2019-01-19 19:48:58 -080089void DoubleSolenoid::Set(Value value) {
90 if (StatusIsFatal()) return;
91
92 bool forward = false;
93 bool reverse = false;
94 switch (value) {
95 case kOff:
96 forward = false;
97 reverse = false;
98 break;
99 case kForward:
100 forward = true;
101 reverse = false;
102 break;
103 case kReverse:
104 forward = false;
105 reverse = true;
106 break;
107 }
108 int fstatus = 0;
109 HAL_SetSolenoid(m_forwardHandle, forward, &fstatus);
110 int rstatus = 0;
111 HAL_SetSolenoid(m_reverseHandle, reverse, &rstatus);
112
113 wpi_setErrorWithContext(fstatus, HAL_GetErrorMessage(fstatus));
114 wpi_setErrorWithContext(rstatus, HAL_GetErrorMessage(rstatus));
115}
116
117DoubleSolenoid::Value DoubleSolenoid::Get() const {
118 if (StatusIsFatal()) return kOff;
119 int fstatus = 0;
120 int rstatus = 0;
121 bool valueForward = HAL_GetSolenoid(m_forwardHandle, &fstatus);
122 bool valueReverse = HAL_GetSolenoid(m_reverseHandle, &rstatus);
123
124 wpi_setErrorWithContext(fstatus, HAL_GetErrorMessage(fstatus));
125 wpi_setErrorWithContext(rstatus, HAL_GetErrorMessage(rstatus));
126
127 if (valueForward) return kForward;
128 if (valueReverse) return kReverse;
129 return kOff;
130}
131
132bool DoubleSolenoid::IsFwdSolenoidBlackListed() const {
133 int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
134 return (blackList & m_forwardMask) != 0;
135}
136
137bool DoubleSolenoid::IsRevSolenoidBlackListed() const {
138 int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
139 return (blackList & m_reverseMask) != 0;
140}
141
142void DoubleSolenoid::InitSendable(SendableBuilder& builder) {
143 builder.SetSmartDashboardType("Double Solenoid");
144 builder.SetActuator(true);
145 builder.SetSafeState([=]() { Set(kOff); });
146 builder.AddSmallStringProperty(
147 "Value",
148 [=](wpi::SmallVectorImpl<char>& buf) -> wpi::StringRef {
149 switch (Get()) {
150 case kForward:
151 return "Forward";
152 case kReverse:
153 return "Reverse";
154 default:
155 return "Off";
156 }
157 },
158 [=](wpi::StringRef value) {
159 Value lvalue = kOff;
160 if (value == "Forward")
161 lvalue = kForward;
162 else if (value == "Reverse")
163 lvalue = kReverse;
164 Set(lvalue);
165 });
166}