blob: 6be855ea53468435b914b65131849609b399c3a4 [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
Austin Schuhdf6cbb12019-02-02 13:46:52 -08009#include "aos/events/event-loop.h"
John Park398c74a2018-10-20 21:17:39 -070010#include "aos/init.h"
John Park33858a32018-09-28 23:05:48 -070011#include "aos/robot_state/robot_state.q.h"
Brian Silvermand8f403a2014-12-13 19:12:04 -050012
13namespace frc971 {
14namespace wpilib {
15
Austin Schuhf2a50ba2016-12-24 16:16:26 -080016namespace chrono = ::std::chrono;
17
Austin Schuhdf6cbb12019-02-02 13:46:52 -080018LoopOutputHandler::LoopOutputHandler(::aos::EventLoop *event_loop,
19 ::std::chrono::nanoseconds timeout)
20 : event_loop_(event_loop),
21 joystick_state_fetcher_(event_loop_->MakeFetcher<::aos::JoystickState>(
22 ".aos.joystick_state")),
23 watchdog_(this, timeout) {}
Brian Silvermand8f403a2014-12-13 19:12:04 -050024
25void LoopOutputHandler::operator()() {
Brian Silvermand8f403a2014-12-13 19:12:04 -050026 ::std::thread watchdog_thread(::std::ref(watchdog_));
Brian Silverman7778fb02015-12-27 14:08:13 -080027 ::aos::SetCurrentThreadName("OutputHandler");
Brian Silvermand8f403a2014-12-13 19:12:04 -050028
29 ::aos::SetCurrentThreadRealtimePriority(30);
30 while (run_) {
Brian Silverman699f0cb2015-02-05 19:45:01 -050031 no_joystick_state_.Print();
32 fake_joystick_state_.Print();
Brian Silvermand8f403a2014-12-13 19:12:04 -050033 Read();
Austin Schuhdf6cbb12019-02-02 13:46:52 -080034 joystick_state_fetcher_.Fetch();
35 if (!joystick_state_fetcher_.get()) {
Brian Silverman699f0cb2015-02-05 19:45:01 -050036 LOG_INTERVAL(no_joystick_state_);
Brian Silvermand8f403a2014-12-13 19:12:04 -050037 continue;
38 }
Austin Schuhdf6cbb12019-02-02 13:46:52 -080039 if (joystick_state_fetcher_->fake) {
Brian Silverman699f0cb2015-02-05 19:45:01 -050040 LOG_INTERVAL(fake_joystick_state_);
Brian Silvermand8f403a2014-12-13 19:12:04 -050041 continue;
42 }
43
44 watchdog_.Reset();
45 Write();
46 }
47
48 Stop();
49
50 watchdog_.Quit();
51 watchdog_thread.join();
52}
53
Austin Schuhbb227f82015-09-06 15:27:52 -070054LoopOutputHandler::Watchdog::Watchdog(LoopOutputHandler *handler,
Austin Schuhf2a50ba2016-12-24 16:16:26 -080055 ::std::chrono::nanoseconds timeout)
Brian Silvermand8f403a2014-12-13 19:12:04 -050056 : handler_(handler),
Austin Schuhbb227f82015-09-06 15:27:52 -070057 timeout_(timeout),
Austin Schuhf2a50ba2016-12-24 16:16:26 -080058 timerfd_(timerfd_create(CLOCK_MONOTONIC, 0)) {
Brian Silvermand8f403a2014-12-13 19:12:04 -050059 if (timerfd_.get() == -1) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080060 PLOG(FATAL, "timerfd_create(CLOCK_MONOTONIC, 0)");
Brian Silvermand8f403a2014-12-13 19:12:04 -050061 }
Brian Silvermand8f403a2014-12-13 19:12:04 -050062}
63
64void LoopOutputHandler::Watchdog::operator()() {
Brian Silverman7778fb02015-12-27 14:08:13 -080065 ::aos::SetCurrentThreadRealtimePriority(35);
66 ::aos::SetCurrentThreadName("OutputWatchdog");
Brian Silvermand8f403a2014-12-13 19:12:04 -050067 uint8_t buf[8];
68 while (run_) {
69 PCHECK(read(timerfd_.get(), buf, sizeof(buf)));
70 handler_->Stop();
71 }
72}
73
74void LoopOutputHandler::Watchdog::Reset() {
75 itimerspec value = itimerspec();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080076 value.it_value.tv_sec = chrono::duration_cast<chrono::seconds>(timeout_).count();
77 value.it_value.tv_nsec =
78 chrono::duration_cast<chrono::nanoseconds>(
79 timeout_ - chrono::seconds(value.it_value.tv_sec))
80 .count();
Brian Silvermand8f403a2014-12-13 19:12:04 -050081 PCHECK(timerfd_settime(timerfd_.get(), 0, &value, nullptr));
82}
83
84} // namespace wpilib
85} // namespace frc971