blob: 74e658aeac7972ec8bedfa5bab9dd45a519d807c [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
Austin Schuh1e69f942020-11-14 15:06:14 -08002/* Copyright (c) 2017-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/TimedRobot.h"
9
10#include <stdint.h>
11
12#include <utility>
13
14#include <hal/DriverStation.h>
15#include <hal/FRCUsageReporting.h>
16#include <hal/Notifier.h>
17
18#include "frc/Timer.h"
19#include "frc/Utility.h"
20#include "frc/WPIErrors.h"
21
22using namespace frc;
23
24void TimedRobot::StartCompetition() {
25 RobotInit();
26
Austin Schuh1e69f942020-11-14 15:06:14 -080027 if constexpr (IsSimulation()) {
28 SimulationInit();
29 }
30
Brian Silverman8fce7482020-01-05 13:18:21 -080031 // Tell the DS that the robot is ready to be enabled
32 HAL_ObserveUserProgramStarting();
33
Brian Silverman8fce7482020-01-05 13:18:21 -080034 // Loop forever, calling the appropriate mode-dependent function
35 while (true) {
Austin Schuh1e69f942020-11-14 15:06:14 -080036 // We don't have to check there's an element in the queue first because
37 // there's always at least one (the constructor adds one). It's reenqueued
38 // at the end of the loop.
39 auto callback = m_callbacks.pop();
40
Brian Silverman8fce7482020-01-05 13:18:21 -080041 int32_t status = 0;
Austin Schuh1e69f942020-11-14 15:06:14 -080042 HAL_UpdateNotifierAlarm(
43 m_notifier, static_cast<uint64_t>(callback.expirationTime * 1e6),
44 &status);
45 wpi_setHALError(status);
46
Brian Silverman8fce7482020-01-05 13:18:21 -080047 uint64_t curTime = HAL_WaitForNotifierAlarm(m_notifier, &status);
48 if (curTime == 0 || status != 0) break;
49
Austin Schuh1e69f942020-11-14 15:06:14 -080050 callback.func();
Brian Silverman8fce7482020-01-05 13:18:21 -080051
Austin Schuh1e69f942020-11-14 15:06:14 -080052 callback.expirationTime += callback.period;
53 m_callbacks.push(std::move(callback));
Brian Silverman8fce7482020-01-05 13:18:21 -080054
Austin Schuh1e69f942020-11-14 15:06:14 -080055 // Process all other callbacks that are ready to run
56 while (static_cast<uint64_t>(m_callbacks.top().expirationTime * 1e6) <=
57 curTime) {
58 callback = m_callbacks.pop();
59
60 callback.func();
61
62 callback.expirationTime += callback.period;
63 m_callbacks.push(std::move(callback));
64 }
Brian Silverman8fce7482020-01-05 13:18:21 -080065 }
66}
67
68void TimedRobot::EndCompetition() {
69 int32_t status = 0;
70 HAL_StopNotifier(m_notifier, &status);
71}
72
73units::second_t TimedRobot::GetPeriod() const {
74 return units::second_t(m_period);
75}
76
77TimedRobot::TimedRobot(double period) : TimedRobot(units::second_t(period)) {}
78
79TimedRobot::TimedRobot(units::second_t period) : IterativeRobotBase(period) {
Austin Schuh1e69f942020-11-14 15:06:14 -080080 m_startTime = frc2::Timer::GetFPGATimestamp();
81 AddPeriodic([=] { LoopFunc(); }, period);
82
Brian Silverman8fce7482020-01-05 13:18:21 -080083 int32_t status = 0;
84 m_notifier = HAL_InitializeNotifier(&status);
85 wpi_setHALError(status);
86 HAL_SetNotifierName(m_notifier, "TimedRobot", &status);
87
88 HAL_Report(HALUsageReporting::kResourceType_Framework,
89 HALUsageReporting::kFramework_Timed);
90}
91
92TimedRobot::~TimedRobot() {
93 int32_t status = 0;
94
95 HAL_StopNotifier(m_notifier, &status);
96 wpi_setHALError(status);
97
98 HAL_CleanNotifier(m_notifier, &status);
99}
100
Austin Schuh1e69f942020-11-14 15:06:14 -0800101void TimedRobot::AddPeriodic(std::function<void()> callback,
102 units::second_t period, units::second_t offset) {
103 m_callbacks.emplace(callback, m_startTime, period, offset);
Brian Silverman8fce7482020-01-05 13:18:21 -0800104}