blob: 67eb0b7f8303a8edb9e9ac609d2f8492b3abd824 [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
Austin Schuh1e69f942020-11-14 15:06:14 -08002/* Copyright (c) 2008-2020 FIRST. All Rights Reserved. */
Brian Silverman8fce7482020-01-05 13:18:21 -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/FRCUsageReporting.h>
13#include <hal/HALBase.h>
14#include <hal/Ports.h>
15#include <hal/Solenoid.h>
16
17#include "frc/SensorUtil.h"
18#include "frc/WPIErrors.h"
19#include "frc/smartdashboard/SendableBuilder.h"
20#include "frc/smartdashboard/SendableRegistry.h"
21
22using namespace frc;
23
24DoubleSolenoid::DoubleSolenoid(int forwardChannel, int reverseChannel)
25 : DoubleSolenoid(SensorUtil::GetDefaultSolenoidModule(), forwardChannel,
26 reverseChannel) {}
27
28DoubleSolenoid::DoubleSolenoid(int moduleNumber, int forwardChannel,
29 int reverseChannel)
30 : SolenoidBase(moduleNumber),
31 m_forwardChannel(forwardChannel),
32 m_reverseChannel(reverseChannel) {
33 if (!SensorUtil::CheckSolenoidModule(m_moduleNumber)) {
34 wpi_setWPIErrorWithContext(ModuleIndexOutOfRange,
35 "Solenoid Module " + wpi::Twine(m_moduleNumber));
36 return;
37 }
38 if (!SensorUtil::CheckSolenoidChannel(m_forwardChannel)) {
39 wpi_setWPIErrorWithContext(
40 ChannelIndexOutOfRange,
41 "Solenoid Channel " + wpi::Twine(m_forwardChannel));
42 return;
43 }
44 if (!SensorUtil::CheckSolenoidChannel(m_reverseChannel)) {
45 wpi_setWPIErrorWithContext(
46 ChannelIndexOutOfRange,
47 "Solenoid Channel " + wpi::Twine(m_reverseChannel));
48 return;
49 }
50 int32_t status = 0;
51 m_forwardHandle = HAL_InitializeSolenoidPort(
52 HAL_GetPortWithModule(moduleNumber, m_forwardChannel), &status);
53 if (status != 0) {
54 wpi_setHALErrorWithRange(status, 0, HAL_GetNumSolenoidChannels(),
55 forwardChannel);
56 m_forwardHandle = HAL_kInvalidHandle;
57 m_reverseHandle = HAL_kInvalidHandle;
58 return;
59 }
60
61 m_reverseHandle = HAL_InitializeSolenoidPort(
62 HAL_GetPortWithModule(moduleNumber, m_reverseChannel), &status);
63 if (status != 0) {
64 wpi_setHALErrorWithRange(status, 0, HAL_GetNumSolenoidChannels(),
65 reverseChannel);
66 // free forward solenoid
67 HAL_FreeSolenoidPort(m_forwardHandle);
68 m_forwardHandle = HAL_kInvalidHandle;
69 m_reverseHandle = HAL_kInvalidHandle;
70 return;
71 }
72
73 m_forwardMask = 1 << m_forwardChannel;
74 m_reverseMask = 1 << m_reverseChannel;
75
76 HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_forwardChannel + 1,
77 m_moduleNumber + 1);
78 HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel + 1,
79 m_moduleNumber + 1);
80
81 SendableRegistry::GetInstance().AddLW(this, "DoubleSolenoid", m_moduleNumber,
82 m_forwardChannel);
83}
84
85DoubleSolenoid::~DoubleSolenoid() {
86 HAL_FreeSolenoidPort(m_forwardHandle);
87 HAL_FreeSolenoidPort(m_reverseHandle);
88}
89
90void DoubleSolenoid::Set(Value value) {
91 if (StatusIsFatal()) return;
92
93 bool forward = false;
94 bool reverse = false;
Austin Schuh1e69f942020-11-14 15:06:14 -080095
Brian Silverman8fce7482020-01-05 13:18:21 -080096 switch (value) {
97 case kOff:
98 forward = false;
99 reverse = false;
100 break;
101 case kForward:
102 forward = true;
103 reverse = false;
104 break;
105 case kReverse:
106 forward = false;
107 reverse = true;
108 break;
109 }
Austin Schuh1e69f942020-11-14 15:06:14 -0800110
Brian Silverman8fce7482020-01-05 13:18:21 -0800111 int fstatus = 0;
112 HAL_SetSolenoid(m_forwardHandle, forward, &fstatus);
113 int rstatus = 0;
114 HAL_SetSolenoid(m_reverseHandle, reverse, &rstatus);
115
116 wpi_setHALError(fstatus);
117 wpi_setHALError(rstatus);
118}
119
120DoubleSolenoid::Value DoubleSolenoid::Get() const {
121 if (StatusIsFatal()) return kOff;
Austin Schuh1e69f942020-11-14 15:06:14 -0800122
Brian Silverman8fce7482020-01-05 13:18:21 -0800123 int fstatus = 0;
124 int rstatus = 0;
125 bool valueForward = HAL_GetSolenoid(m_forwardHandle, &fstatus);
126 bool valueReverse = HAL_GetSolenoid(m_reverseHandle, &rstatus);
127
128 wpi_setHALError(fstatus);
129 wpi_setHALError(rstatus);
130
Austin Schuh1e69f942020-11-14 15:06:14 -0800131 if (valueForward) {
132 return kForward;
133 } else if (valueReverse) {
134 return kReverse;
135 } else {
136 return kOff;
137 }
138}
139
140void DoubleSolenoid::Toggle() {
141 Value value = Get();
142
143 if (value == kForward) {
144 Set(kReverse);
145 } else if (value == kReverse) {
146 Set(kForward);
147 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800148}
149
150bool DoubleSolenoid::IsFwdSolenoidBlackListed() const {
151 int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
152 return (blackList & m_forwardMask) != 0;
153}
154
155bool DoubleSolenoid::IsRevSolenoidBlackListed() const {
156 int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
157 return (blackList & m_reverseMask) != 0;
158}
159
160void DoubleSolenoid::InitSendable(SendableBuilder& builder) {
161 builder.SetSmartDashboardType("Double Solenoid");
162 builder.SetActuator(true);
163 builder.SetSafeState([=]() { Set(kOff); });
164 builder.AddSmallStringProperty(
165 "Value",
166 [=](wpi::SmallVectorImpl<char>& buf) -> wpi::StringRef {
167 switch (Get()) {
168 case kForward:
169 return "Forward";
170 case kReverse:
171 return "Reverse";
172 default:
173 return "Off";
174 }
175 },
176 [=](wpi::StringRef value) {
177 Value lvalue = kOff;
178 if (value == "Forward")
179 lvalue = kForward;
180 else if (value == "Reverse")
181 lvalue = kReverse;
182 Set(lvalue);
183 });
184}