blob: 903296b8ebfbd462ea22ca33deebf1d0694e0cfa [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"
Brian Silverman70ec7192015-01-26 17:52:40 -05006#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 ::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());
35 InterruptableSensorBase::WaitResult result = InterruptableSensorBase::kBoth;
36 while (should_run()) {
37 result = input_->WaitForInterrupt(
38 0.1, result != InterruptableSensorBase::kTimeout);
39 if (result == InterruptableSensorBase::kTimeout) {
40 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 {
57 LOG(WARNING, "Detected spurious edge on %d. Dropping it.\n",
Brian Silvermane48dbc12017-02-04 20:06:29 -080058 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()) {
95 LOG(WARNING, "got an interrupt while sampling. retrying\n");
96 return false;
97 }
98 }
99 for (auto &c : handlers_) {
100 c->CommitValue();
101 }
102 return true;
103}
104
105} // namespace wpilib
106} // namespace frc971