blob: c896ea88c8ac4ab23a88ef080be871b66bdefe8e [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
James Kuszmaul4b81d302019-12-14 20:53:14 -080012#include <hal/FRCUsageReporting.h>
13#include <hal/HALBase.h>
Brian Silverman41cdd3e2019-01-19 19:48:58 -080014#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"
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080020#include "frc/smartdashboard/SendableRegistry.h"
Brian Silverman41cdd3e2019-01-19 19:48:58 -080021
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) {
James Kuszmaul4b81d302019-12-14 20:53:14 -080054 wpi_setHALErrorWithRange(status, 0, HAL_GetNumSolenoidChannels(),
55 forwardChannel);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080056 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) {
James Kuszmaul4b81d302019-12-14 20:53:14 -080064 wpi_setHALErrorWithRange(status, 0, HAL_GetNumSolenoidChannels(),
65 reverseChannel);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080066 // 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
James Kuszmaul4b81d302019-12-14 20:53:14 -080076 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);
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080080
81 SendableRegistry::GetInstance().AddLW(this, "DoubleSolenoid", m_moduleNumber,
82 m_forwardChannel);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080083}
84
85DoubleSolenoid::~DoubleSolenoid() {
86 HAL_FreeSolenoidPort(m_forwardHandle);
87 HAL_FreeSolenoidPort(m_reverseHandle);
88}
89
Brian Silverman41cdd3e2019-01-19 19:48:58 -080090void DoubleSolenoid::Set(Value value) {
91 if (StatusIsFatal()) return;
92
93 bool forward = false;
94 bool reverse = false;
95 switch (value) {
96 case kOff:
97 forward = false;
98 reverse = false;
99 break;
100 case kForward:
101 forward = true;
102 reverse = false;
103 break;
104 case kReverse:
105 forward = false;
106 reverse = true;
107 break;
108 }
109 int fstatus = 0;
110 HAL_SetSolenoid(m_forwardHandle, forward, &fstatus);
111 int rstatus = 0;
112 HAL_SetSolenoid(m_reverseHandle, reverse, &rstatus);
113
James Kuszmaul4b81d302019-12-14 20:53:14 -0800114 wpi_setHALError(fstatus);
115 wpi_setHALError(rstatus);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800116}
117
118DoubleSolenoid::Value DoubleSolenoid::Get() const {
119 if (StatusIsFatal()) return kOff;
120 int fstatus = 0;
121 int rstatus = 0;
122 bool valueForward = HAL_GetSolenoid(m_forwardHandle, &fstatus);
123 bool valueReverse = HAL_GetSolenoid(m_reverseHandle, &rstatus);
124
James Kuszmaul4b81d302019-12-14 20:53:14 -0800125 wpi_setHALError(fstatus);
126 wpi_setHALError(rstatus);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800127
128 if (valueForward) return kForward;
129 if (valueReverse) return kReverse;
130 return kOff;
131}
132
133bool DoubleSolenoid::IsFwdSolenoidBlackListed() const {
134 int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
135 return (blackList & m_forwardMask) != 0;
136}
137
138bool DoubleSolenoid::IsRevSolenoidBlackListed() const {
139 int blackList = GetPCMSolenoidBlackList(m_moduleNumber);
140 return (blackList & m_reverseMask) != 0;
141}
142
143void DoubleSolenoid::InitSendable(SendableBuilder& builder) {
144 builder.SetSmartDashboardType("Double Solenoid");
145 builder.SetActuator(true);
146 builder.SetSafeState([=]() { Set(kOff); });
147 builder.AddSmallStringProperty(
148 "Value",
149 [=](wpi::SmallVectorImpl<char>& buf) -> wpi::StringRef {
150 switch (Get()) {
151 case kForward:
152 return "Forward";
153 case kReverse:
154 return "Reverse";
155 default:
156 return "Off";
157 }
158 },
159 [=](wpi::StringRef value) {
160 Value lvalue = kOff;
161 if (value == "Forward")
162 lvalue = kForward;
163 else if (value == "Reverse")
164 lvalue = kReverse;
165 Set(lvalue);
166 });
167}