blob: 4fc21724fe8a56342b653823c038deaf7eab1b4b [file] [log] [blame]
Brian Silverman70ec7192015-01-26 17:52:40 -05001#include "frc971/wpilib/interrupt_edge_counting.h"
2
Austin Schuhf2a50ba2016-12-24 16:16:26 -08003#include <chrono>
4
Alex Perrycb7da4b2019-08-28 19:35:56 -07005#include "aos/realtime.h"
John Park33858a32018-09-28 23:05:48 -07006#include "aos/time/time.h"
Brian Silverman70ec7192015-01-26 17:52:40 -05007
Stephan Pleinesf63bde82024-01-13 15:59:33 -08008namespace frc971::wpilib {
Brian Silverman70ec7192015-01-26 17:52:40 -05009
10void EdgeCounter::GatherPolledValue() {
11 shadow_values_.polled_value = input_->Get();
12 bool miss_match = (shadow_values_.polled_value != current_value_);
13 if (miss_match && last_miss_match_) {
14 current_value_ = shadow_values_.polled_value;
15 last_miss_match_ = false;
16 } else {
17 last_miss_match_ = miss_match;
18 }
19}
20
21void EdgeCounter::operator()() {
22 ::aos::SetCurrentThreadName("EdgeCounter_" +
Brian Silvermane48dbc12017-02-04 20:06:29 -080023 ::std::to_string(input_->GetChannel()));
Brian Silverman70ec7192015-01-26 17:52:40 -050024
25 input_->RequestInterrupts();
26 input_->SetUpSourceEdge(true, true);
27
28 {
29 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
30 current_value_ = input_->Get();
31 }
32
33 ::aos::SetCurrentThreadRealtimePriority(priority());
Parker Schuhd3b7a8872018-02-19 16:42:27 -080034 frc::InterruptableSensorBase::WaitResult result =
35 frc::InterruptableSensorBase::kBoth;
Brian Silverman70ec7192015-01-26 17:52:40 -050036 while (should_run()) {
37 result = input_->WaitForInterrupt(
Parker Schuhd3b7a8872018-02-19 16:42:27 -080038 0.1, result != frc::InterruptableSensorBase::kTimeout);
39 if (result == frc::InterruptableSensorBase::kTimeout) {
Brian Silverman70ec7192015-01-26 17:52:40 -050040 continue;
41 }
42 interrupt_received();
43
44 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
45 int32_t encoder_value = encoder_->GetRaw();
46 bool hall_value = input_->Get();
47 if (current_value_ != hall_value) {
48 if (hall_value) {
49 ++shadow_values_.positive_interrupt_count;
50 shadow_values_.last_positive_encoder_value = encoder_value;
51 } else {
52 ++shadow_values_.negative_interrupt_count;
53 shadow_values_.last_negative_encoder_value = encoder_value;
54 }
55 current_value_ = hall_value;
56 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070057 AOS_LOG(WARNING, "Detected spurious edge on %d. Dropping it.\n",
58 input_->GetChannel());
Brian Silverman70ec7192015-01-26 17:52:40 -050059 }
60 }
61}
62
63void InterruptSynchronizer::RunIteration() {
64 while (true) {
65 if (!TryStartIteration()) continue;
66
67 // Wait more than the amount of time it takes for a digital input change
68 // to go from visible to software to having triggered an interrupt.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080069 ::std::this_thread::sleep_for(::std::chrono::microseconds(120));
Brian Silverman70ec7192015-01-26 17:52:40 -050070
71 if (TryFinishingIteration()) return;
72 }
73}
74
75bool InterruptSynchronizer::TryStartIteration() {
76 for (auto &c : handlers_) {
77 c->save_interrupt_count();
78 }
79
80 {
81 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
82 for (auto &c : handlers_) {
83 c->GatherPolledValue();
84 }
85 }
86 return true;
87}
88
89bool InterruptSynchronizer::TryFinishingIteration() {
90 // Make sure no interrupts have occurred while we were waiting. If they
91 // have, we are in an inconsistent state and need to try again.
92 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
93 for (auto &c : handlers_) {
94 if (c->interrupt_count_changed()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070095 AOS_LOG(WARNING, "got an interrupt while sampling. retrying\n");
Brian Silverman70ec7192015-01-26 17:52:40 -050096 return false;
97 }
98 }
99 for (auto &c : handlers_) {
100 c->CommitValue();
101 }
102 return true;
103}
104
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800105} // namespace frc971::wpilib