blob: 546e64be00a970c71b8b48d2d04d68e205d5c18f [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
John Park33858a32018-09-28 23:05:48 -07005#include "aos/time/time.h"
John Park398c74a2018-10-20 21:17:39 -07006#include "aos/init.h"
Brian Silverman70ec7192015-01-26 17:52:40 -05007
8namespace frc971 {
9namespace wpilib {
10
11void EdgeCounter::GatherPolledValue() {
12 shadow_values_.polled_value = input_->Get();
13 bool miss_match = (shadow_values_.polled_value != current_value_);
14 if (miss_match && last_miss_match_) {
15 current_value_ = shadow_values_.polled_value;
16 last_miss_match_ = false;
17 } else {
18 last_miss_match_ = miss_match;
19 }
20}
21
22void EdgeCounter::operator()() {
23 ::aos::SetCurrentThreadName("EdgeCounter_" +
Brian Silvermane48dbc12017-02-04 20:06:29 -080024 ::std::to_string(input_->GetChannel()));
Brian Silverman70ec7192015-01-26 17:52:40 -050025
26 input_->RequestInterrupts();
27 input_->SetUpSourceEdge(true, true);
28
29 {
30 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
31 current_value_ = input_->Get();
32 }
33
34 ::aos::SetCurrentThreadRealtimePriority(priority());
Parker Schuhd3b7a8872018-02-19 16:42:27 -080035 frc::InterruptableSensorBase::WaitResult result =
36 frc::InterruptableSensorBase::kBoth;
Brian Silverman70ec7192015-01-26 17:52:40 -050037 while (should_run()) {
38 result = input_->WaitForInterrupt(
Parker Schuhd3b7a8872018-02-19 16:42:27 -080039 0.1, result != frc::InterruptableSensorBase::kTimeout);
40 if (result == frc::InterruptableSensorBase::kTimeout) {
Brian Silverman70ec7192015-01-26 17:52:40 -050041 continue;
42 }
43 interrupt_received();
44
45 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
46 int32_t encoder_value = encoder_->GetRaw();
47 bool hall_value = input_->Get();
48 if (current_value_ != hall_value) {
49 if (hall_value) {
50 ++shadow_values_.positive_interrupt_count;
51 shadow_values_.last_positive_encoder_value = encoder_value;
52 } else {
53 ++shadow_values_.negative_interrupt_count;
54 shadow_values_.last_negative_encoder_value = encoder_value;
55 }
56 current_value_ = hall_value;
57 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070058 AOS_LOG(WARNING, "Detected spurious edge on %d. Dropping it.\n",
59 input_->GetChannel());
Brian Silverman70ec7192015-01-26 17:52:40 -050060 }
61 }
62}
63
64void InterruptSynchronizer::RunIteration() {
65 while (true) {
66 if (!TryStartIteration()) continue;
67
68 // Wait more than the amount of time it takes for a digital input change
69 // to go from visible to software to having triggered an interrupt.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080070 ::std::this_thread::sleep_for(::std::chrono::microseconds(120));
Brian Silverman70ec7192015-01-26 17:52:40 -050071
72 if (TryFinishingIteration()) return;
73 }
74}
75
76bool InterruptSynchronizer::TryStartIteration() {
77 for (auto &c : handlers_) {
78 c->save_interrupt_count();
79 }
80
81 {
82 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
83 for (auto &c : handlers_) {
84 c->GatherPolledValue();
85 }
86 }
87 return true;
88}
89
90bool InterruptSynchronizer::TryFinishingIteration() {
91 // Make sure no interrupts have occurred while we were waiting. If they
92 // have, we are in an inconsistent state and need to try again.
93 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
94 for (auto &c : handlers_) {
95 if (c->interrupt_count_changed()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070096 AOS_LOG(WARNING, "got an interrupt while sampling. retrying\n");
Brian Silverman70ec7192015-01-26 17:52:40 -050097 return false;
98 }
99 }
100 for (auto &c : handlers_) {
101 c->CommitValue();
102 }
103 return true;
104}
105
106} // namespace wpilib
107} // namespace frc971