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