blob: 4bdb2d232f385031fb9b953709483eefe95ab700 [file] [log] [blame]
Brian Silverman70ec7192015-01-26 17:52:40 -05001#include "frc971/wpilib/interrupt_edge_counting.h"
2
3#include "aos/common/time.h"
4#include "aos/linux_code/init.h"
5
6namespace frc971 {
7namespace wpilib {
8
9void EdgeCounter::GatherPolledValue() {
10 shadow_values_.polled_value = input_->Get();
11 bool miss_match = (shadow_values_.polled_value != current_value_);
12 if (miss_match && last_miss_match_) {
13 current_value_ = shadow_values_.polled_value;
14 last_miss_match_ = false;
15 } else {
16 last_miss_match_ = miss_match;
17 }
18}
19
20void EdgeCounter::operator()() {
21 ::aos::SetCurrentThreadName("EdgeCounter_" +
22 ::std::to_string(input_->GetChannelForRouting()));
23
24 input_->RequestInterrupts();
25 input_->SetUpSourceEdge(true, true);
26
27 {
28 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
29 current_value_ = input_->Get();
30 }
31
32 ::aos::SetCurrentThreadRealtimePriority(priority());
33 InterruptableSensorBase::WaitResult result = InterruptableSensorBase::kBoth;
34 while (should_run()) {
35 result = input_->WaitForInterrupt(
36 0.1, result != InterruptableSensorBase::kTimeout);
37 if (result == InterruptableSensorBase::kTimeout) {
38 continue;
39 }
40 interrupt_received();
41
42 ::std::unique_lock<::aos::stl_mutex> mutex_guard(*mutex());
43 int32_t encoder_value = encoder_->GetRaw();
44 bool hall_value = input_->Get();
45 if (current_value_ != hall_value) {
46 if (hall_value) {
47 ++shadow_values_.positive_interrupt_count;
48 shadow_values_.last_positive_encoder_value = encoder_value;
49 } else {
50 ++shadow_values_.negative_interrupt_count;
51 shadow_values_.last_negative_encoder_value = encoder_value;
52 }
53 current_value_ = hall_value;
54 } else {
55 LOG(WARNING, "Detected spurious edge on %d. Dropping it.\n",
56 input_->GetChannelForRouting());
57 }
58 }
59}
60
61void InterruptSynchronizer::RunIteration() {
62 while (true) {
63 if (!TryStartIteration()) continue;
64
65 // Wait more than the amount of time it takes for a digital input change
66 // to go from visible to software to having triggered an interrupt.
67 ::aos::time::SleepFor(::aos::time::Time::InUS(120));
68
69 if (TryFinishingIteration()) return;
70 }
71}
72
73bool InterruptSynchronizer::TryStartIteration() {
74 for (auto &c : handlers_) {
75 c->save_interrupt_count();
76 }
77
78 {
79 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
80 for (auto &c : handlers_) {
81 c->GatherPolledValue();
82 }
83 }
84 return true;
85}
86
87bool InterruptSynchronizer::TryFinishingIteration() {
88 // Make sure no interrupts have occurred while we were waiting. If they
89 // have, we are in an inconsistent state and need to try again.
90 ::std::unique_lock<::aos::stl_mutex> mutex_guard(mutex_);
91 for (auto &c : handlers_) {
92 if (c->interrupt_count_changed()) {
93 LOG(WARNING, "got an interrupt while sampling. retrying\n");
94 return false;
95 }
96 }
97 for (auto &c : handlers_) {
98 c->CommitValue();
99 }
100 return true;
101}
102
103} // namespace wpilib
104} // namespace frc971