blob: 59770be10486a16293cc80df45be4e8957313e53 [file] [log] [blame]
Brian Silvermand8f403a2014-12-13 19:12:04 -05001#include "frc971/wpilib/loop_output_handler.h"
2
3#include <sys/timerfd.h>
4
Austin Schuhf2a50ba2016-12-24 16:16:26 -08005#include <chrono>
Brian Silvermand8f403a2014-12-13 19:12:04 -05006#include <functional>
Austin Schuhf2a50ba2016-12-24 16:16:26 -08007#include <thread>
Brian Silvermand8f403a2014-12-13 19:12:04 -05008
9#include "aos/linux_code/init.h"
10#include "aos/common/messages/robot_state.q.h"
11
12namespace frc971 {
13namespace wpilib {
14
Austin Schuhf2a50ba2016-12-24 16:16:26 -080015namespace chrono = ::std::chrono;
16
17LoopOutputHandler::LoopOutputHandler(::std::chrono::nanoseconds timeout)
Austin Schuhbb227f82015-09-06 15:27:52 -070018 : watchdog_(this, timeout) {}
Brian Silvermand8f403a2014-12-13 19:12:04 -050019
20void LoopOutputHandler::operator()() {
Brian Silvermand8f403a2014-12-13 19:12:04 -050021 ::std::thread watchdog_thread(::std::ref(watchdog_));
Brian Silverman7778fb02015-12-27 14:08:13 -080022 ::aos::SetCurrentThreadName("OutputHandler");
Brian Silvermand8f403a2014-12-13 19:12:04 -050023
24 ::aos::SetCurrentThreadRealtimePriority(30);
25 while (run_) {
Brian Silverman699f0cb2015-02-05 19:45:01 -050026 no_joystick_state_.Print();
27 fake_joystick_state_.Print();
Brian Silvermand8f403a2014-12-13 19:12:04 -050028 Read();
Brian Silverman699f0cb2015-02-05 19:45:01 -050029 ::aos::joystick_state.FetchLatest();
30 if (!::aos::joystick_state.get()) {
31 LOG_INTERVAL(no_joystick_state_);
Brian Silvermand8f403a2014-12-13 19:12:04 -050032 continue;
33 }
Brian Silverman699f0cb2015-02-05 19:45:01 -050034 if (::aos::joystick_state->fake) {
35 LOG_INTERVAL(fake_joystick_state_);
Brian Silvermand8f403a2014-12-13 19:12:04 -050036 continue;
37 }
38
39 watchdog_.Reset();
40 Write();
41 }
42
43 Stop();
44
45 watchdog_.Quit();
46 watchdog_thread.join();
47}
48
Austin Schuhbb227f82015-09-06 15:27:52 -070049LoopOutputHandler::Watchdog::Watchdog(LoopOutputHandler *handler,
Austin Schuhf2a50ba2016-12-24 16:16:26 -080050 ::std::chrono::nanoseconds timeout)
Brian Silvermand8f403a2014-12-13 19:12:04 -050051 : handler_(handler),
Austin Schuhbb227f82015-09-06 15:27:52 -070052 timeout_(timeout),
Austin Schuhf2a50ba2016-12-24 16:16:26 -080053 timerfd_(timerfd_create(CLOCK_MONOTONIC, 0)) {
Brian Silvermand8f403a2014-12-13 19:12:04 -050054 if (timerfd_.get() == -1) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080055 PLOG(FATAL, "timerfd_create(CLOCK_MONOTONIC, 0)");
Brian Silvermand8f403a2014-12-13 19:12:04 -050056 }
Brian Silvermand8f403a2014-12-13 19:12:04 -050057}
58
59void LoopOutputHandler::Watchdog::operator()() {
Brian Silverman7778fb02015-12-27 14:08:13 -080060 ::aos::SetCurrentThreadRealtimePriority(35);
61 ::aos::SetCurrentThreadName("OutputWatchdog");
Brian Silvermand8f403a2014-12-13 19:12:04 -050062 uint8_t buf[8];
63 while (run_) {
64 PCHECK(read(timerfd_.get(), buf, sizeof(buf)));
65 handler_->Stop();
66 }
67}
68
69void LoopOutputHandler::Watchdog::Reset() {
70 itimerspec value = itimerspec();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080071 value.it_value.tv_sec = chrono::duration_cast<chrono::seconds>(timeout_).count();
72 value.it_value.tv_nsec =
73 chrono::duration_cast<chrono::nanoseconds>(
74 timeout_ - chrono::seconds(value.it_value.tv_sec))
75 .count();
Brian Silvermand8f403a2014-12-13 19:12:04 -050076 PCHECK(timerfd_settime(timerfd_.get(), 0, &value, nullptr));
77}
78
79} // namespace wpilib
80} // namespace frc971