blob: ec6f62745edc29466b06145316ce736dd8f3a608 [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
Brian Silverman70ec7192015-01-26 17:52:40 -05005#include "aos/common/time.h"
6#include "aos/linux_code/init.h"
7
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#ifdef WPILIB2017
25 ::std::to_string(input_->GetChannel()));
26#else
Brian Silverman70ec7192015-01-26 17:52:40 -050027 ::std::to_string(input_->GetChannelForRouting()));
Brian Silvermane48dbc12017-02-04 20:06:29 -080028#endif
Brian Silverman70ec7192015-01-26 17:52:40 -050029
30 input_->RequestInterrupts();
31 input_->SetUpSourceEdge(true, true);
32
33 {
34 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
35 current_value_ = input_->Get();
36 }
37
38 ::aos::SetCurrentThreadRealtimePriority(priority());
39 InterruptableSensorBase::WaitResult result = InterruptableSensorBase::kBoth;
40 while (should_run()) {
41 result = input_->WaitForInterrupt(
42 0.1, result != InterruptableSensorBase::kTimeout);
43 if (result == InterruptableSensorBase::kTimeout) {
44 continue;
45 }
46 interrupt_received();
47
48 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
49 int32_t encoder_value = encoder_->GetRaw();
50 bool hall_value = input_->Get();
51 if (current_value_ != hall_value) {
52 if (hall_value) {
53 ++shadow_values_.positive_interrupt_count;
54 shadow_values_.last_positive_encoder_value = encoder_value;
55 } else {
56 ++shadow_values_.negative_interrupt_count;
57 shadow_values_.last_negative_encoder_value = encoder_value;
58 }
59 current_value_ = hall_value;
60 } else {
61 LOG(WARNING, "Detected spurious edge on %d. Dropping it.\n",
Brian Silvermane48dbc12017-02-04 20:06:29 -080062#ifdef WPILIB2017
63 input_->GetChannel());
64#else
Brian Silverman70ec7192015-01-26 17:52:40 -050065 input_->GetChannelForRouting());
Brian Silvermane48dbc12017-02-04 20:06:29 -080066#endif
Brian Silverman70ec7192015-01-26 17:52:40 -050067 }
68 }
69}
70
71void InterruptSynchronizer::RunIteration() {
72 while (true) {
73 if (!TryStartIteration()) continue;
74
75 // Wait more than the amount of time it takes for a digital input change
76 // to go from visible to software to having triggered an interrupt.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080077 ::std::this_thread::sleep_for(::std::chrono::microseconds(120));
Brian Silverman70ec7192015-01-26 17:52:40 -050078
79 if (TryFinishingIteration()) return;
80 }
81}
82
83bool InterruptSynchronizer::TryStartIteration() {
84 for (auto &c : handlers_) {
85 c->save_interrupt_count();
86 }
87
88 {
89 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
90 for (auto &c : handlers_) {
91 c->GatherPolledValue();
92 }
93 }
94 return true;
95}
96
97bool InterruptSynchronizer::TryFinishingIteration() {
98 // Make sure no interrupts have occurred while we were waiting. If they
99 // have, we are in an inconsistent state and need to try again.
100 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
101 for (auto &c : handlers_) {
102 if (c->interrupt_count_changed()) {
103 LOG(WARNING, "got an interrupt while sampling. retrying\n");
104 return false;
105 }
106 }
107 for (auto &c : handlers_) {
108 c->CommitValue();
109 }
110 return true;
111}
112
113} // namespace wpilib
114} // namespace frc971