blob: 8217e8696425217d19601d64d165edd0686954aa [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/PneumaticHub.h"
6
7#include <hal/REVPH.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 PneumaticHub::m_handleLock;
20std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>
21 PneumaticHub::m_handleMap = nullptr;
22
23// Always called under lock, so we can avoid the double lock from the magic
24// static
25std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int module) {
26 if (!m_handleMap) {
27 m_handleMap = std::make_unique<
28 wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>();
29 }
30 return (*m_handleMap)[module];
31}
32
33class PneumaticHub::DataStore {
34 public:
35 explicit DataStore(int module, const char* stackTrace) {
36 int32_t status = 0;
37 HAL_REVPHHandle handle = HAL_InitializeREVPH(module, stackTrace, &status);
38 FRC_CheckErrorStatus(status, "Module {}", module);
39 m_moduleObject = PneumaticHub{handle, module};
40 m_moduleObject.m_dataStore =
41 std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
42 }
43
44 ~DataStore() noexcept { HAL_FreeREVPH(m_moduleObject.m_handle); }
45
46 DataStore(DataStore&&) = delete;
47 DataStore& operator=(DataStore&&) = delete;
48
49 private:
50 friend class PneumaticHub;
51 uint32_t m_reservedMask{0};
52 bool m_compressorReserved{false};
53 wpi::mutex m_reservedLock;
54 PneumaticHub m_moduleObject{HAL_kInvalidHandle, 0};
55};
56
57PneumaticHub::PneumaticHub()
58 : PneumaticHub{SensorUtil::GetDefaultREVPHModule()} {}
59
60PneumaticHub::PneumaticHub(int module) {
61 std::string stackTrace = wpi::GetStackTrace(1);
62 std::scoped_lock lock(m_handleLock);
63 auto& res = GetDataStore(module);
64 m_dataStore = res.lock();
65 if (!m_dataStore) {
66 m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
67 res = m_dataStore;
68 }
69 m_handle = m_dataStore->m_moduleObject.m_handle;
70 m_module = module;
71}
72
73PneumaticHub::PneumaticHub(HAL_REVPHHandle handle, int module)
74 : m_handle{handle}, m_module{module} {}
75
76bool PneumaticHub::GetCompressor() const {
77 int32_t status = 0;
78 auto result = HAL_GetREVPHCompressor(m_handle, &status);
79 FRC_CheckErrorStatus(status, "Module {}", m_module);
80 return result;
81}
82
83void PneumaticHub::SetClosedLoopControl(bool enabled) {
84 int32_t status = 0;
85 HAL_SetREVPHClosedLoopControl(m_handle, enabled, &status);
86 FRC_CheckErrorStatus(status, "Module {}", m_module);
87}
88
89bool PneumaticHub::GetClosedLoopControl() const {
90 int32_t status = 0;
91 auto result = HAL_GetREVPHClosedLoopControl(m_handle, &status);
92 FRC_CheckErrorStatus(status, "Module {}", m_module);
93 return result;
94}
95
96bool PneumaticHub::GetPressureSwitch() const {
97 int32_t status = 0;
98 auto result = HAL_GetREVPHPressureSwitch(m_handle, &status);
99 FRC_CheckErrorStatus(status, "Module {}", m_module);
100 return result;
101}
102
103double PneumaticHub::GetCompressorCurrent() const {
104 int32_t status = 0;
105 auto result = HAL_GetREVPHCompressorCurrent(m_handle, &status);
106 FRC_CheckErrorStatus(status, "Module {}", m_module);
107 return result;
108}
109
110void PneumaticHub::SetSolenoids(int mask, int values) {
111 int32_t status = 0;
112 HAL_SetREVPHSolenoids(m_handle, mask, values, &status);
113 FRC_CheckErrorStatus(status, "Module {}", m_module);
114}
115
116int PneumaticHub::GetSolenoids() const {
117 int32_t status = 0;
118 auto result = HAL_GetREVPHSolenoids(m_handle, &status);
119 FRC_CheckErrorStatus(status, "Module {}", m_module);
120 return result;
121}
122
123int PneumaticHub::GetModuleNumber() const {
124 return m_module;
125}
126
127int PneumaticHub::GetSolenoidDisabledList() const {
128 return 0;
129 // TODO Fix me
130 // int32_t status = 0;
131 // auto result = HAL_GetREVPHSolenoidDisabledList(m_handle, &status);
132 // FRC_CheckErrorStatus(status, "Module {}", m_module);
133 // return result;
134}
135
136void PneumaticHub::FireOneShot(int index) {
137 // TODO Fix me
138 // int32_t status = 0;
139 // HAL_FireREVPHOneShot(m_handle, index, &status);
140 // FRC_CheckErrorStatus(status, "Module {}", m_module);
141}
142
143void PneumaticHub::SetOneShotDuration(int index, units::second_t duration) {
144 // TODO Fix me
145 // int32_t status = 0;
146 // units::millisecond_t millis = duration;
147 // HAL_SetREVPHOneShotDuration(m_handle, index, millis.to<int32_t>(),
148 // &status); FRC_CheckErrorStatus(status, "Module {}", m_module);
149}
150
151bool PneumaticHub::CheckSolenoidChannel(int channel) const {
152 return HAL_CheckREVPHSolenoidChannel(channel);
153}
154
155int PneumaticHub::CheckAndReserveSolenoids(int mask) {
156 std::scoped_lock lock{m_dataStore->m_reservedLock};
157 uint32_t uMask = static_cast<uint32_t>(mask);
158 if ((m_dataStore->m_reservedMask & uMask) != 0) {
159 return m_dataStore->m_reservedMask & uMask;
160 }
161 m_dataStore->m_reservedMask |= uMask;
162 return 0;
163}
164
165void PneumaticHub::UnreserveSolenoids(int mask) {
166 std::scoped_lock lock{m_dataStore->m_reservedLock};
167 m_dataStore->m_reservedMask &= ~(static_cast<uint32_t>(mask));
168}
169
170bool PneumaticHub::ReserveCompressor() {
171 std::scoped_lock lock{m_dataStore->m_reservedLock};
172 if (m_dataStore->m_compressorReserved) {
173 return false;
174 }
175 m_dataStore->m_compressorReserved = true;
176 return true;
177}
178
179void PneumaticHub::UnreserveCompressor() {
180 std::scoped_lock lock{m_dataStore->m_reservedLock};
181 m_dataStore->m_compressorReserved = false;
182}
183
184Solenoid PneumaticHub::MakeSolenoid(int channel) {
185 return Solenoid{m_module, PneumaticsModuleType::REVPH, channel};
186}
187
188DoubleSolenoid PneumaticHub::MakeDoubleSolenoid(int forwardChannel,
189 int reverseChannel) {
190 return DoubleSolenoid{m_module, PneumaticsModuleType::REVPH, forwardChannel,
191 reverseChannel};
192}
193
194Compressor PneumaticHub::MakeCompressor() {
195 return Compressor{m_module, PneumaticsModuleType::REVPH};
196}
197
198std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int module) {
199 std::string stackTrace = wpi::GetStackTrace(1);
200 std::scoped_lock lock(m_handleLock);
201 auto& res = GetDataStore(module);
202 std::shared_ptr<DataStore> dataStore = res.lock();
203 if (!dataStore) {
204 dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
205 res = dataStore;
206 }
207
208 return std::shared_ptr<PneumaticsBase>{dataStore, &dataStore->m_moduleObject};
209}