blob: 60cd84dcb32b6c7441bc5a6542599a5ea61af80e [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.
4
5#include "frc/PneumaticsControlModule.h"
6
7#include <hal/CTREPCM.h>
8#include <wpi/NullDeleter.h>
9#include <wpi/StackTrace.h>
10
11#include "frc/Compressor.h"
12#include "frc/DoubleSolenoid.h"
13#include "frc/Errors.h"
14#include "frc/SensorUtil.h"
15#include "frc/Solenoid.h"
16
17using namespace frc;
18
19wpi::mutex PneumaticsControlModule::m_handleLock;
20std::unique_ptr<
21 wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>>
22 PneumaticsControlModule::m_handleMap = nullptr;
23
24// Always called under lock, so we can avoid the double lock from the magic
25// static
26std::weak_ptr<PneumaticsControlModule::DataStore>&
27PneumaticsControlModule::GetDataStore(int module) {
28 if (!m_handleMap) {
29 m_handleMap = std::make_unique<wpi::DenseMap<
30 int, std::weak_ptr<PneumaticsControlModule::DataStore>>>();
31 }
32 return (*m_handleMap)[module];
33}
34
35class PneumaticsControlModule::DataStore {
36 public:
37 explicit DataStore(int module, const char* stackTrace) {
38 int32_t status = 0;
39 HAL_CTREPCMHandle handle =
40 HAL_InitializeCTREPCM(module, stackTrace, &status);
41 FRC_CheckErrorStatus(status, "Module {}", module);
42 m_moduleObject = PneumaticsControlModule{handle, module};
43 m_moduleObject.m_dataStore =
44 std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
45 }
46
47 ~DataStore() noexcept { HAL_FreeCTREPCM(m_moduleObject.m_handle); }
48
49 DataStore(DataStore&&) = delete;
50 DataStore& operator=(DataStore&&) = delete;
51
52 private:
53 friend class PneumaticsControlModule;
54 uint32_t m_reservedMask{0};
55 bool m_compressorReserved{false};
56 wpi::mutex m_reservedLock;
57 PneumaticsControlModule m_moduleObject{HAL_kInvalidHandle, 0};
58};
59
60PneumaticsControlModule::PneumaticsControlModule()
61 : PneumaticsControlModule{SensorUtil::GetDefaultCTREPCMModule()} {}
62
63PneumaticsControlModule::PneumaticsControlModule(int module) {
64 std::string stackTrace = wpi::GetStackTrace(1);
65 std::scoped_lock lock(m_handleLock);
66 auto& res = GetDataStore(module);
67 m_dataStore = res.lock();
68 if (!m_dataStore) {
69 m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
70 res = m_dataStore;
71 }
72 m_handle = m_dataStore->m_moduleObject.m_handle;
73 m_module = module;
74}
75
76PneumaticsControlModule::PneumaticsControlModule(HAL_CTREPCMHandle handle,
77 int module)
78 : m_handle{handle}, m_module{module} {}
79
80bool PneumaticsControlModule::GetCompressor() const {
81 int32_t status = 0;
82 auto result = HAL_GetCTREPCMCompressor(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -080083 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -070084 return result;
85}
86
Austin Schuh75263e32022-02-22 18:05:32 -080087void PneumaticsControlModule::DisableCompressor() {
Austin Schuh812d0d12021-11-04 20:16:48 -070088 int32_t status = 0;
Austin Schuh75263e32022-02-22 18:05:32 -080089 HAL_SetCTREPCMClosedLoopControl(m_handle, false, &status);
90 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -070091}
92
Austin Schuh75263e32022-02-22 18:05:32 -080093void PneumaticsControlModule::EnableCompressorDigital() {
94 int32_t status = 0;
95 HAL_SetCTREPCMClosedLoopControl(m_handle, true, &status);
96 FRC_ReportError(status, "Module {}", m_module);
97}
98
99void PneumaticsControlModule::EnableCompressorAnalog(
100 units::pounds_per_square_inch_t minPressure,
101 units::pounds_per_square_inch_t maxPressure) {
102 int32_t status = 0;
103 HAL_SetCTREPCMClosedLoopControl(m_handle, true, &status);
104 FRC_ReportError(status, "Module {}", m_module);
105}
106
107void PneumaticsControlModule::EnableCompressorHybrid(
108 units::pounds_per_square_inch_t minPressure,
109 units::pounds_per_square_inch_t maxPressure) {
110 int32_t status = 0;
111 HAL_SetCTREPCMClosedLoopControl(m_handle, true, &status);
112 FRC_ReportError(status, "Module {}", m_module);
113}
114
115CompressorConfigType PneumaticsControlModule::GetCompressorConfigType() const {
Austin Schuh812d0d12021-11-04 20:16:48 -0700116 int32_t status = 0;
117 auto result = HAL_GetCTREPCMClosedLoopControl(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800118 FRC_ReportError(status, "Module {}", m_module);
119 return result ? CompressorConfigType::Digital
120 : CompressorConfigType::Disabled;
Austin Schuh812d0d12021-11-04 20:16:48 -0700121}
122
123bool PneumaticsControlModule::GetPressureSwitch() const {
124 int32_t status = 0;
125 auto result = HAL_GetCTREPCMPressureSwitch(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800126 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700127 return result;
128}
129
Austin Schuh75263e32022-02-22 18:05:32 -0800130units::ampere_t PneumaticsControlModule::GetCompressorCurrent() const {
Austin Schuh812d0d12021-11-04 20:16:48 -0700131 int32_t status = 0;
132 auto result = HAL_GetCTREPCMCompressorCurrent(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800133 FRC_ReportError(status, "Module {}", m_module);
134 return units::ampere_t{result};
Austin Schuh812d0d12021-11-04 20:16:48 -0700135}
136
137bool PneumaticsControlModule::GetCompressorCurrentTooHighFault() const {
138 int32_t status = 0;
139 auto result = HAL_GetCTREPCMCompressorCurrentTooHighFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800140 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700141 return result;
142}
143bool PneumaticsControlModule::GetCompressorCurrentTooHighStickyFault() const {
144 int32_t status = 0;
145 auto result =
146 HAL_GetCTREPCMCompressorCurrentTooHighStickyFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800147 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700148 return result;
149}
150bool PneumaticsControlModule::GetCompressorShortedFault() const {
151 int32_t status = 0;
152 auto result = HAL_GetCTREPCMCompressorShortedFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800153 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700154 return result;
155}
156bool PneumaticsControlModule::GetCompressorShortedStickyFault() const {
157 int32_t status = 0;
158 auto result = HAL_GetCTREPCMCompressorShortedStickyFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800159 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700160 return result;
161}
162bool PneumaticsControlModule::GetCompressorNotConnectedFault() const {
163 int32_t status = 0;
164 auto result = HAL_GetCTREPCMCompressorNotConnectedFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800165 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700166 return result;
167}
168bool PneumaticsControlModule::GetCompressorNotConnectedStickyFault() const {
169 int32_t status = 0;
170 auto result =
171 HAL_GetCTREPCMCompressorNotConnectedStickyFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800172 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700173 return result;
174}
175
176bool PneumaticsControlModule::GetSolenoidVoltageFault() const {
177 int32_t status = 0;
178 auto result = HAL_GetCTREPCMSolenoidVoltageFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800179 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700180 return result;
181}
182bool PneumaticsControlModule::GetSolenoidVoltageStickyFault() const {
183 int32_t status = 0;
184 auto result = HAL_GetCTREPCMSolenoidVoltageStickyFault(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800185 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700186 return result;
187}
188
189void PneumaticsControlModule::ClearAllStickyFaults() {
190 int32_t status = 0;
191 HAL_ClearAllCTREPCMStickyFaults(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800192 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700193}
194
195void PneumaticsControlModule::SetSolenoids(int mask, int values) {
196 int32_t status = 0;
197 HAL_SetCTREPCMSolenoids(m_handle, mask, values, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800198 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700199}
200
201int PneumaticsControlModule::GetSolenoids() const {
202 int32_t status = 0;
203 auto result = HAL_GetCTREPCMSolenoids(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800204 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700205 return result;
206}
207
208int PneumaticsControlModule::GetModuleNumber() const {
209 return m_module;
210}
211
212int PneumaticsControlModule::GetSolenoidDisabledList() const {
213 int32_t status = 0;
214 auto result = HAL_GetCTREPCMSolenoidDisabledList(m_handle, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800215 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700216 return result;
217}
218
219void PneumaticsControlModule::FireOneShot(int index) {
220 int32_t status = 0;
221 HAL_FireCTREPCMOneShot(m_handle, index, &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800222 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700223}
224
225void PneumaticsControlModule::SetOneShotDuration(int index,
226 units::second_t duration) {
227 int32_t status = 0;
228 units::millisecond_t millis = duration;
229 HAL_SetCTREPCMOneShotDuration(m_handle, index, millis.to<int32_t>(), &status);
Austin Schuh75263e32022-02-22 18:05:32 -0800230 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700231}
232
233bool PneumaticsControlModule::CheckSolenoidChannel(int channel) const {
234 return HAL_CheckCTREPCMSolenoidChannel(channel);
235}
236
237int PneumaticsControlModule::CheckAndReserveSolenoids(int mask) {
238 std::scoped_lock lock{m_dataStore->m_reservedLock};
239 uint32_t uMask = static_cast<uint32_t>(mask);
240 if ((m_dataStore->m_reservedMask & uMask) != 0) {
241 return m_dataStore->m_reservedMask & uMask;
242 }
243 m_dataStore->m_reservedMask |= uMask;
244 return 0;
245}
246
247void PneumaticsControlModule::UnreserveSolenoids(int mask) {
248 std::scoped_lock lock{m_dataStore->m_reservedLock};
249 m_dataStore->m_reservedMask &= ~(static_cast<uint32_t>(mask));
250}
251
252bool PneumaticsControlModule::ReserveCompressor() {
253 std::scoped_lock lock{m_dataStore->m_reservedLock};
254 if (m_dataStore->m_compressorReserved) {
255 return false;
256 }
257 m_dataStore->m_compressorReserved = true;
258 return true;
259}
260
261void PneumaticsControlModule::UnreserveCompressor() {
262 std::scoped_lock lock{m_dataStore->m_reservedLock};
263 m_dataStore->m_compressorReserved = false;
264}
265
Austin Schuh75263e32022-02-22 18:05:32 -0800266units::volt_t PneumaticsControlModule::GetAnalogVoltage(int channel) const {
267 return units::volt_t{0};
268}
269
270units::pounds_per_square_inch_t PneumaticsControlModule::GetPressure(
271 int channel) const {
272 return 0_psi;
273}
274
Austin Schuh812d0d12021-11-04 20:16:48 -0700275Solenoid PneumaticsControlModule::MakeSolenoid(int channel) {
276 return Solenoid{m_module, PneumaticsModuleType::CTREPCM, channel};
277}
278
279DoubleSolenoid PneumaticsControlModule::MakeDoubleSolenoid(int forwardChannel,
280 int reverseChannel) {
281 return DoubleSolenoid{m_module, PneumaticsModuleType::CTREPCM, forwardChannel,
282 reverseChannel};
283}
284
285Compressor PneumaticsControlModule::MakeCompressor() {
286 return Compressor{m_module, PneumaticsModuleType::CTREPCM};
287}
288
289std::shared_ptr<PneumaticsBase> PneumaticsControlModule::GetForModule(
290 int module) {
291 std::string stackTrace = wpi::GetStackTrace(1);
292 std::scoped_lock lock(m_handleLock);
293 auto& res = GetDataStore(module);
294 std::shared_ptr<DataStore> dataStore = res.lock();
295 if (!dataStore) {
296 dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
297 res = dataStore;
298 }
299
300 return std::shared_ptr<PneumaticsBase>{dataStore, &dataStore->m_moduleObject};
301}