blob: 967ebb4583e8da0246b6c0898deeaf2b4c9261b0 [file] [log] [blame]
Parker Schuhd3b7a8872018-02-19 16:42:27 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */
3/* 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 "frc971/wpilib/ahal/DriverStation.h"
9
10#include <chrono>
James Kuszmaul9776b392023-01-14 14:08:08 -080011#include <functional>
Vinay Sivae52a6b32021-07-10 15:19:26 -070012#include <memory>
Austin Schuh9950f682021-11-06 15:27:58 -070013#include <string_view>
Parker Schuhd3b7a8872018-02-19 16:42:27 -080014
15#include "FRC_NetworkCommunication/FRCComm.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070016#include "wpi/SmallString.h"
17
Parker Schuhd3b7a8872018-02-19 16:42:27 -080018#include "frc971/wpilib/ahal/AnalogInput.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080019#include "frc971/wpilib/ahal/WPIErrors.h"
Austin Schuhf6b94632019-02-02 22:11:27 -080020#include "hal/HAL.h"
21#include "hal/Power.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080022
23using namespace frc;
24
25#define WPI_LIB_FATAL(error_tag) \
26 do { \
27 } while (false)
28
29const int DriverStation::kJoystickPorts;
30
31DriverStation::~DriverStation() {}
32
33/**
34 * Return a pointer to the singleton DriverStation.
35 *
36 * @return Pointer to the DS instance
37 */
38DriverStation &DriverStation::GetInstance() {
39 static DriverStation instance;
40 return instance;
41}
42
43/**
44 * Report an error to the DriverStation messages window.
45 *
46 * The error is also printed to the program console.
47 */
Austin Schuh9950f682021-11-06 15:27:58 -070048void DriverStation::ReportError(const std::string_view &error) {
49 HAL_SendError(1, 1, 0, std::string(error).c_str(), "", "", 1);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080050}
51
52/**
53 * Report a warning to the DriverStation messages window.
54 *
55 * The warning is also printed to the program console.
56 */
Austin Schuh9950f682021-11-06 15:27:58 -070057void DriverStation::ReportWarning(const std::string_view &error) {
58 HAL_SendError(0, 1, 0, std::string(error).c_str(), "", "", 1);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080059}
60
61/**
62 * Report an error to the DriverStation messages window.
63 *
64 * The error is also printed to the program console.
65 */
66void DriverStation::ReportError(bool is_error, int32_t code,
Austin Schuh9950f682021-11-06 15:27:58 -070067 const std::string_view &error,
68 const std::string_view &location,
69 const std::string_view &stack) {
70 HAL_SendError(is_error, code, 0, std::string(error).c_str(),
71 std::string(location).c_str(), std::string(stack).c_str(), 1);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080072}
73
74/**
75 * Get the value of the axis on a joystick.
76 *
77 * This depends on the mapping of the joystick connected to the specified port.
78 *
79 * @param stick The joystick to read.
80 * @param axis The analog axis value to read from the joystick.
81 * @return The value of the axis on the joystick.
82 */
83double DriverStation::GetStickAxis(int stick, int axis) {
84 if (stick >= kJoystickPorts) {
85 WPI_LIB_FATAL(BadJoystickIndex);
86 return 0;
87 }
88 if (axis >= m_joystickAxes[stick].count) {
89 if (axis >= HAL_kMaxJoystickAxes) WPI_LIB_FATAL(BadJoystickAxis);
90 return 0.0;
91 }
92
93 return m_joystickAxes[stick].axes[axis];
94}
95
96/**
97 * Get the state of a POV on the joystick.
98 *
99 * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
100 */
101int DriverStation::GetStickPOV(int stick, int pov) {
102 if (stick >= kJoystickPorts) {
103 WPI_LIB_FATAL(BadJoystickIndex);
104 return -1;
105 }
106 if (pov >= m_joystickPOVs[stick].count) {
107 if (pov >= HAL_kMaxJoystickPOVs) WPI_LIB_FATAL(BadJoystickAxis);
108 return -1;
109 }
110
111 return m_joystickPOVs[stick].povs[pov];
112}
113
114/**
115 * The state of the buttons on the joystick.
116 *
117 * @param stick The joystick to read.
118 * @return The state of the buttons on the joystick.
119 */
120int DriverStation::GetStickButtons(int stick) const {
121 if (stick >= kJoystickPorts) {
122 WPI_LIB_FATAL(BadJoystickIndex);
123 return 0;
124 }
125 return m_joystickButtons[stick].buttons;
126}
127
128/**
129 * The state of one joystick button. Button indexes begin at 1.
130 *
131 * @param stick The joystick to read.
132 * @param button The button index, beginning at 1.
133 * @return The state of the joystick button.
134 */
135bool DriverStation::GetStickButton(int stick, int button) {
136 if (stick >= kJoystickPorts) {
137 WPI_LIB_FATAL(BadJoystickIndex);
138 return false;
139 }
140 if (button == 0) {
141 return false;
142 }
143 if (button > m_joystickButtons[stick].count) {
144 return false;
145 }
146
147 return ((0x1 << (button - 1)) & m_joystickButtons[stick].buttons) != 0;
148}
149
150/**
151 * Returns the number of axes on a given joystick port.
152 *
153 * @param stick The joystick port number
154 * @return The number of axes on the indicated joystick
155 */
156int DriverStation::GetStickAxisCount(int stick) const {
157 if (stick >= kJoystickPorts) {
158 WPI_LIB_FATAL(BadJoystickIndex);
159 return 0;
160 }
161 return m_joystickAxes[stick].count;
162}
163
164/**
165 * Returns the number of POVs on a given joystick port.
166 *
167 * @param stick The joystick port number
168 * @return The number of POVs on the indicated joystick
169 */
170int DriverStation::GetStickPOVCount(int stick) const {
171 if (stick >= kJoystickPorts) {
172 WPI_LIB_FATAL(BadJoystickIndex);
173 return 0;
174 }
175 return m_joystickPOVs[stick].count;
176}
177
178/**
179 * Returns the number of buttons on a given joystick port.
180 *
181 * @param stick The joystick port number
182 * @return The number of buttons on the indicated joystick
183 */
184int DriverStation::GetStickButtonCount(int stick) const {
185 if (stick >= kJoystickPorts) {
186 WPI_LIB_FATAL(BadJoystickIndex);
187 return 0;
188 }
189 return m_joystickButtons[stick].count;
190}
191
192/**
193 * Returns a boolean indicating if the controller is an xbox controller.
194 *
195 * @param stick The joystick port number
196 * @return A boolean that is true if the controller is an xbox controller.
197 */
198bool DriverStation::GetJoystickIsXbox(int stick) const {
199 if (stick >= kJoystickPorts) {
200 WPI_LIB_FATAL(BadJoystickIndex);
201 return false;
202 }
203 return static_cast<bool>(m_joystickDescriptor[stick].isXbox);
204}
205
206/**
207 * Returns the type of joystick at a given port.
208 *
209 * @param stick The joystick port number
210 * @return The HID type of joystick at the given port
211 */
212int DriverStation::GetJoystickType(int stick) const {
213 if (stick >= kJoystickPorts) {
214 WPI_LIB_FATAL(BadJoystickIndex);
215 return -1;
216 }
217 return static_cast<int>(m_joystickDescriptor[stick].type);
218}
219
220/**
221 * Returns the name of the joystick at the given port.
222 *
223 * @param stick The joystick port number
224 * @return The name of the joystick at the given port
225 */
226std::string DriverStation::GetJoystickName(int stick) const {
227 if (stick >= kJoystickPorts) {
228 WPI_LIB_FATAL(BadJoystickIndex);
229 }
230 std::string retVal(m_joystickDescriptor[stick].name);
231 return retVal;
232}
233
234/**
235 * Returns the types of Axes on a given joystick port.
236 *
237 * @param stick The joystick port number and the target axis
238 * @return What type of axis the axis is reporting to be
239 */
240int DriverStation::GetJoystickAxisType(int stick, int axis) const {
241 if (stick >= kJoystickPorts) {
242 WPI_LIB_FATAL(BadJoystickIndex);
243 return -1;
244 }
245 return m_joystickDescriptor[stick].axisTypes[axis];
246}
247
248/**
249 * Check if the FPGA outputs are enabled.
250 *
251 * The outputs may be disabled if the robot is disabled or e-stopped, the
252 * watchdog has expired, or if the roboRIO browns out.
253 *
254 * @return True if the FPGA outputs are enabled.
255 */
256bool DriverStation::IsSysActive() const {
257 int32_t status = 0;
258 bool retVal = HAL_GetSystemActive(&status);
259 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
260 return retVal;
261}
262
263/**
264 * Check if the system is browned out.
265 *
266 * @return True if the system is browned out
267 */
268bool DriverStation::IsBrownedOut() const {
269 int32_t status = 0;
270 bool retVal = HAL_GetBrownedOut(&status);
271 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
272 return retVal;
273}
274
275/**
James Kuszmaul9776b392023-01-14 14:08:08 -0800276 * Returns the game specific message provided by the FMS.
277 *
278 * @return A string containing the game specific message.
279 */
Lee Mracekdb8bde02022-01-08 02:54:21 -0500280std::string_view DriverStation::GetGameSpecificMessage() const {
281 return std::string_view(
282 reinterpret_cast<const char *>(info_.gameSpecificMessage),
283 info_.gameSpecificMessageSize);
284}
285
286/**
James Kuszmaul9776b392023-01-14 14:08:08 -0800287 * Returns the name of the competition event provided by the FMS.
288 *
289 * @return A string containing the event name
290 */
291std::string_view DriverStation::GetEventName() const { return info_.eventName; }
Lee Mracekdb8bde02022-01-08 02:54:21 -0500292
293/**
James Kuszmaul9776b392023-01-14 14:08:08 -0800294 * Returns the match number provided by the FMS.
295 *
296 * @return The number of the match
297 */
Lee Mracekdb8bde02022-01-08 02:54:21 -0500298DriverStation::MatchType DriverStation::GetMatchType() const {
299 return static_cast<DriverStation::MatchType>(info_.matchType);
300}
301
302/**
James Kuszmaul9776b392023-01-14 14:08:08 -0800303 * Returns the match number provided by the FMS.
304 *
305 * @return The number of the match
306 */
307int DriverStation::GetMatchNumber() const { return info_.matchNumber; }
Lee Mracekdb8bde02022-01-08 02:54:21 -0500308
309/**
James Kuszmaul9776b392023-01-14 14:08:08 -0800310 * Returns the number of times the current match has been replayed from the
311 * FMS.
312 *
313 * @return The number of replays
314 */
315int DriverStation::GetReplayNumber() const { return info_.replayNumber; }
Lee Mracekdb8bde02022-01-08 02:54:21 -0500316
317/**
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800318 * Return the alliance that the driver station says it is on.
319 *
320 * This could return kRed or kBlue.
321 *
322 * @return The Alliance enum (kRed, kBlue or kInvalid)
323 */
324DriverStation::Alliance DriverStation::GetAlliance() const {
325 int32_t status = 0;
326 auto allianceStationID = HAL_GetAllianceStation(&status);
327 switch (allianceStationID) {
328 case HAL_AllianceStationID_kRed1:
329 case HAL_AllianceStationID_kRed2:
330 case HAL_AllianceStationID_kRed3:
331 return kRed;
332 case HAL_AllianceStationID_kBlue1:
333 case HAL_AllianceStationID_kBlue2:
334 case HAL_AllianceStationID_kBlue3:
335 return kBlue;
336 default:
337 return kInvalid;
338 }
339}
340
341/**
342 * Return the driver station location on the field.
343 *
344 * This could return 1, 2, or 3.
345 *
346 * @return The location of the driver station (1-3, 0 for invalid)
347 */
348int DriverStation::GetLocation() const {
349 int32_t status = 0;
350 auto allianceStationID = HAL_GetAllianceStation(&status);
351 switch (allianceStationID) {
352 case HAL_AllianceStationID_kRed1:
353 case HAL_AllianceStationID_kBlue1:
354 return 1;
355 case HAL_AllianceStationID_kRed2:
356 case HAL_AllianceStationID_kBlue2:
357 return 2;
358 case HAL_AllianceStationID_kRed3:
359 case HAL_AllianceStationID_kBlue3:
360 return 3;
361 default:
362 return 0;
363 }
364}
365
366/**
367 * Return the approximate match time.
368 *
369 * The FMS does not send an official match time to the robots, but does send an
370 * approximate match time. The value will count down the time remaining in the
371 * current period (auto or teleop).
372 *
373 * Warning: This is not an official time (so it cannot be used to dispute ref
374 * calls or guarantee that a function will trigger before the match ends).
375 *
376 * The Practice Match function of the DS approximates the behaviour seen on the
377 * field.
378 *
379 * @return Time remaining in current match period (auto or teleop)
380 */
381double DriverStation::GetMatchTime() const {
382 int32_t status;
383 return HAL_GetMatchTime(&status);
384}
385
386/**
387 * Read the battery voltage.
388 *
389 * @return The battery voltage in Volts.
390 */
391double DriverStation::GetBatteryVoltage() const {
392 int32_t status = 0;
393 double voltage = HAL_GetVinVoltage(&status);
394 wpi_setErrorWithContext(status, "getVinVoltage");
395
396 return voltage;
397}
398
399/**
400 * Copy data from the DS task for the user.
401 *
402 * If no new data exists, it will just be returned, otherwise
403 * the data will be copied from the DS polling loop.
404 */
405void DriverStation::GetData() {
James Kuszmaul9776b392023-01-14 14:08:08 -0800406 HAL_RefreshDSData();
407
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800408 // Get the status of all of the joysticks, and save to the cache
409 for (uint8_t stick = 0; stick < kJoystickPorts; stick++) {
410 HAL_GetJoystickAxes(stick, &m_joystickAxesCache[stick]);
411 HAL_GetJoystickPOVs(stick, &m_joystickPOVsCache[stick]);
412 HAL_GetJoystickButtons(stick, &m_joystickButtonsCache[stick]);
413 HAL_GetJoystickDescriptor(stick, &m_joystickDescriptorCache[stick]);
414 }
415 m_joystickAxes.swap(m_joystickAxesCache);
416 m_joystickPOVs.swap(m_joystickPOVsCache);
417 m_joystickButtons.swap(m_joystickButtonsCache);
418 m_joystickDescriptor.swap(m_joystickDescriptorCache);
419
420 HAL_ControlWord control_word;
421 HAL_GetControlWord(&control_word);
Lee Mracekdb8bde02022-01-08 02:54:21 -0500422 is_enabled_ = control_word.enabled && control_word.dsAttached;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800423 is_autonomous_ = control_word.autonomous;
424 is_test_mode_ = control_word.test;
425 is_fms_attached_ = control_word.fmsAttached;
Lee Mracekdb8bde02022-01-08 02:54:21 -0500426 is_ds_attached_ = control_word.dsAttached;
427 is_teleop_ = !(control_word.autonomous || control_word.test);
428
429 HAL_GetMatchInfo(&info_);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800430}
431
432/**
433 * DriverStation constructor.
434 *
435 * This is only called once the first time GetInstance() is called
436 */
437DriverStation::DriverStation() {
438 // The HAL_Observe* functions let the Driver Station know that the
439 // robot code is alive (this influences the Robot Code status light on the
440 // DS, and if the DS thinks you don't have robot code, then you can't enable).
441 HAL_ObserveUserProgramStarting();
442
Vinay Sivae52a6b32021-07-10 15:19:26 -0700443 m_joystickAxes = std::make_unique<HAL_JoystickAxes[]>(kJoystickPorts);
444 m_joystickPOVs = std::make_unique<HAL_JoystickPOVs[]>(kJoystickPorts);
445 m_joystickButtons = std::make_unique<HAL_JoystickButtons[]>(kJoystickPorts);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800446 m_joystickDescriptor =
Vinay Sivae52a6b32021-07-10 15:19:26 -0700447 std::make_unique<HAL_JoystickDescriptor[]>(kJoystickPorts);
448 m_joystickAxesCache = std::make_unique<HAL_JoystickAxes[]>(kJoystickPorts);
449 m_joystickPOVsCache = std::make_unique<HAL_JoystickPOVs[]>(kJoystickPorts);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800450 m_joystickButtonsCache =
Vinay Sivae52a6b32021-07-10 15:19:26 -0700451 std::make_unique<HAL_JoystickButtons[]>(kJoystickPorts);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800452 m_joystickDescriptorCache =
Vinay Sivae52a6b32021-07-10 15:19:26 -0700453 std::make_unique<HAL_JoystickDescriptor[]>(kJoystickPorts);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800454
455 // All joysticks should default to having zero axes, povs and buttons, so
456 // uninitialized memory doesn't get sent to speed controllers.
457 for (unsigned int i = 0; i < kJoystickPorts; i++) {
458 m_joystickAxes[i].count = 0;
459 m_joystickPOVs[i].count = 0;
460 m_joystickButtons[i].count = 0;
461 m_joystickDescriptor[i].isXbox = 0;
462 m_joystickDescriptor[i].type = -1;
463 m_joystickDescriptor[i].name[0] = '\0';
464
465 m_joystickAxesCache[i].count = 0;
466 m_joystickPOVsCache[i].count = 0;
467 m_joystickButtonsCache[i].count = 0;
468 m_joystickDescriptorCache[i].isXbox = 0;
469 m_joystickDescriptorCache[i].type = -1;
470 m_joystickDescriptorCache[i].name[0] = '\0';
471 }
472}
473
474void DriverStation::RunIteration(std::function<void()> on_data) {
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800475 GetData();
476
477 // We have to feed some sort of watchdog so that the driver's station knows
478 // that the robot code is still alive. HAL_ObserveUserProgramStarting must be
479 // called during initialization (currently called in the constructor of this
480 // class).
481 if (!IsEnabled()) {
482 HAL_ObserveUserProgramDisabled();
483 } else if (IsAutonomous()) {
484 HAL_ObserveUserProgramAutonomous();
485 } else if (IsTestMode()) {
486 HAL_ObserveUserProgramTest();
487 } else {
488 HAL_ObserveUserProgramTeleop();
489 }
490
491 on_data();
492}