Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 1 | #include "frc971/wpilib/loop_output_handler.h" |
| 2 | |
| 3 | #include <sys/timerfd.h> |
| 4 | |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 5 | #include <chrono> |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 6 | #include <functional> |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 7 | #include <thread> |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 8 | |
Austin Schuh | df6cbb1 | 2019-02-02 13:46:52 -0800 | [diff] [blame] | 9 | #include "aos/events/event-loop.h" |
John Park | 398c74a | 2018-10-20 21:17:39 -0700 | [diff] [blame] | 10 | #include "aos/init.h" |
John Park | 33858a3 | 2018-09-28 23:05:48 -0700 | [diff] [blame] | 11 | #include "aos/robot_state/robot_state.q.h" |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 12 | |
| 13 | namespace frc971 { |
| 14 | namespace wpilib { |
| 15 | |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 16 | namespace chrono = ::std::chrono; |
| 17 | |
Austin Schuh | df6cbb1 | 2019-02-02 13:46:52 -0800 | [diff] [blame] | 18 | LoopOutputHandler::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 Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 24 | |
| 25 | void LoopOutputHandler::operator()() { |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 26 | ::std::thread watchdog_thread(::std::ref(watchdog_)); |
Brian Silverman | 7778fb0 | 2015-12-27 14:08:13 -0800 | [diff] [blame] | 27 | ::aos::SetCurrentThreadName("OutputHandler"); |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 28 | |
| 29 | ::aos::SetCurrentThreadRealtimePriority(30); |
| 30 | while (run_) { |
Brian Silverman | 699f0cb | 2015-02-05 19:45:01 -0500 | [diff] [blame] | 31 | no_joystick_state_.Print(); |
| 32 | fake_joystick_state_.Print(); |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 33 | Read(); |
Austin Schuh | df6cbb1 | 2019-02-02 13:46:52 -0800 | [diff] [blame] | 34 | joystick_state_fetcher_.Fetch(); |
| 35 | if (!joystick_state_fetcher_.get()) { |
Brian Silverman | 699f0cb | 2015-02-05 19:45:01 -0500 | [diff] [blame] | 36 | LOG_INTERVAL(no_joystick_state_); |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 37 | continue; |
| 38 | } |
Austin Schuh | df6cbb1 | 2019-02-02 13:46:52 -0800 | [diff] [blame] | 39 | if (joystick_state_fetcher_->fake) { |
Brian Silverman | 699f0cb | 2015-02-05 19:45:01 -0500 | [diff] [blame] | 40 | LOG_INTERVAL(fake_joystick_state_); |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 41 | continue; |
| 42 | } |
| 43 | |
| 44 | watchdog_.Reset(); |
| 45 | Write(); |
| 46 | } |
| 47 | |
| 48 | Stop(); |
| 49 | |
| 50 | watchdog_.Quit(); |
| 51 | watchdog_thread.join(); |
| 52 | } |
| 53 | |
Austin Schuh | bb227f8 | 2015-09-06 15:27:52 -0700 | [diff] [blame] | 54 | LoopOutputHandler::Watchdog::Watchdog(LoopOutputHandler *handler, |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 55 | ::std::chrono::nanoseconds timeout) |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 56 | : handler_(handler), |
Austin Schuh | bb227f8 | 2015-09-06 15:27:52 -0700 | [diff] [blame] | 57 | timeout_(timeout), |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 58 | timerfd_(timerfd_create(CLOCK_MONOTONIC, 0)) { |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 59 | if (timerfd_.get() == -1) { |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 60 | PLOG(FATAL, "timerfd_create(CLOCK_MONOTONIC, 0)"); |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 61 | } |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | void LoopOutputHandler::Watchdog::operator()() { |
Brian Silverman | 7778fb0 | 2015-12-27 14:08:13 -0800 | [diff] [blame] | 65 | ::aos::SetCurrentThreadRealtimePriority(35); |
| 66 | ::aos::SetCurrentThreadName("OutputWatchdog"); |
Brian Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 67 | uint8_t buf[8]; |
| 68 | while (run_) { |
| 69 | PCHECK(read(timerfd_.get(), buf, sizeof(buf))); |
| 70 | handler_->Stop(); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | void LoopOutputHandler::Watchdog::Reset() { |
| 75 | itimerspec value = itimerspec(); |
Austin Schuh | f2a50ba | 2016-12-24 16:16:26 -0800 | [diff] [blame] | 76 | 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 Silverman | d8f403a | 2014-12-13 19:12:04 -0500 | [diff] [blame] | 81 | PCHECK(timerfd_settime(timerfd_.get(), 0, &value, nullptr)); |
| 82 | } |
| 83 | |
| 84 | } // namespace wpilib |
| 85 | } // namespace frc971 |