blob: c84bc151165f3c88f256d45aac012d4e2b3db395 [file] [log] [blame]
Brian Silvermanff7b3472015-01-26 17:53:04 -05001#include "frc971/wpilib/dma_edge_counting.h"
2
John Park33858a32018-09-28 23:05:48 -07003#include "aos/logging/logging.h"
Brian Silvermanff7b3472015-01-26 17:53:04 -05004
Stephan Pleinesf63bde82024-01-13 15:59:33 -08005namespace frc971::wpilib {
Brian Silvermanff7b3472015-01-26 17:53:04 -05006
Brian Silverman552350b2015-08-02 18:23:34 -07007bool DMAEdgeCounter::ExtractValue(const DMASample &sample) const {
Brian Silverman03a00cf2015-08-29 19:26:54 -07008 return sample.Get(input_);
Brian Silvermanff7b3472015-01-26 17:53:04 -05009}
10
11void DMAEdgeCounter::UpdateFromSample(const DMASample &sample) {
Brian Silverman03a00cf2015-08-29 19:26:54 -070012 const bool previous_value =
Austin Schuhf83da152017-03-05 22:28:45 -080013 have_prev_sample_ ? ExtractValue(prev_sample_) : previous_polled_value_;
Brian Silverman03a00cf2015-08-29 19:26:54 -070014 have_prev_sample_ = true;
Brian Silvermanff7b3472015-01-26 17:53:04 -050015 prev_sample_ = sample;
Brian Silverman03a00cf2015-08-29 19:26:54 -070016
17 if (!previous_value && ExtractValue(sample)) {
18 pos_edge_count_++;
Brian Silverman03a00cf2015-08-29 19:26:54 -070019 pos_last_encoder_ = sample.GetRaw(encoder_);
20 } else if (previous_value && !ExtractValue(sample)) {
21 neg_edge_count_++;
Brian Silverman03a00cf2015-08-29 19:26:54 -070022 neg_last_encoder_ = sample.GetRaw(encoder_);
23 }
Brian Silvermanff7b3472015-01-26 17:53:04 -050024}
25
Austin Schuh8e5950d2018-03-21 20:29:40 -070026void DMAPulseWidthReader::UpdateFromSample(const DMASample &sample) {
milind-u6b672f82023-02-24 17:36:27 -080027 if (have_prev_sample_ && high_time_ != 0 && prev_sample_.Get(input_) &&
28 !sample.Get(input_)) {
milind-ua2e612b2023-02-24 18:00:59 -080029 last_width_ = (sample.GetTime() - high_time_) * 1e-6;
milind-ua2e612b2023-02-24 18:00:59 -080030 poll_count_ = 0;
milind-u6b672f82023-02-24 17:36:27 -080031 } else if (have_prev_sample_ && !prev_sample_.Get(input_) &&
32 sample.Get(input_)) {
milind-u3a7f9212023-02-24 20:46:59 -080033 last_period_ = (sample.GetTime() - high_time_) * 1e-6;
34 high_time_ = sample.GetTime();
milind-ua2e612b2023-02-24 18:00:59 -080035 poll_count_ = 0;
Austin Schuh8e5950d2018-03-21 20:29:40 -070036 }
37 have_prev_sample_ = true;
38 prev_sample_ = sample;
39}
40
milind-ua2e612b2023-02-24 18:00:59 -080041void DMAPulseWidthReader::UpdatePolledValue() {
42 // If we are polled without an update for too long, reset
43 constexpr size_t kMaxPollCount = 4;
44 if (poll_count_ > kMaxPollCount) {
45 high_time_ = 0;
46 have_prev_sample_ = false;
47 last_width_ = ::std::numeric_limits<double>::quiet_NaN();
milind-u3a7f9212023-02-24 20:46:59 -080048 last_period_ = ::std::numeric_limits<double>::quiet_NaN();
milind-ua2e612b2023-02-24 18:00:59 -080049 }
50 poll_count_++;
51}
52
Ravago Jones128a50e2021-09-18 15:19:39 -070053void DMAPulseSeparationReader::UpdateFromSample(const DMASample &sample) {
Austin Schuh6c053ef2021-09-26 14:32:16 -070054 // save the time of the falling edge of the input one
55 if (have_prev_sample_ && !sample.Get(input_one_) &&
56 prev_sample_.Get(input_one_)) {
Ravago Jones128a50e2021-09-18 15:19:39 -070057 input_one_time_ = sample.GetTimestamp();
58 }
59
Austin Schuh6c053ef2021-09-26 14:32:16 -070060 // take the difference in time between the falling edge of the input one and
61 // the falling edge of the input two
62 if (!sample.Get(input_two_) && input_one_time_.has_value()) {
Ravago Jones128a50e2021-09-18 15:19:39 -070063 last_width_ = sample.GetTimestamp() - input_one_time_.value();
64 pulses_detected_++;
65 input_one_time_.reset();
66 }
Austin Schuh6c053ef2021-09-26 14:32:16 -070067
68 have_prev_sample_ = true;
69 prev_sample_ = sample;
Ravago Jones128a50e2021-09-18 15:19:39 -070070}
71
Brian Silvermanff7b3472015-01-26 17:53:04 -050072void DMASynchronizer::CheckDMA() {
73 DMASample current_sample;
74
75 size_t remaining = 0;
76 while (true) {
77 switch (dma_->Read(&current_sample, 0, &remaining)) {
78 case DMA::STATUS_OK:
79 for (auto &c : handlers_) {
80 c->UpdateFromSample(current_sample);
81 }
82
83 if (remaining == 0) {
Austin Schuhf853bde2017-11-23 13:23:27 -080084 if (sample_time_ < static_cast<int64_t>(current_sample.GetTime())) {
Brian Silvermanff7b3472015-01-26 17:53:04 -050085 // If the latest DMA sample happened after we started polling, then
86 // just use the values from it because they're more recent.
87 for (auto &c : handlers_) {
88 c->PollFromSample(current_sample);
89 }
90 }
91 return;
92 }
Austin Schuh8e5950d2018-03-21 20:29:40 -070093 break;
Brian Silvermanff7b3472015-01-26 17:53:04 -050094 case DMA::STATUS_TIMEOUT:
95 return;
96 case DMA::STATUS_ERROR:
Austin Schuhf257f3c2019-10-27 21:00:43 -070097 AOS_LOG(WARNING, "DMA read failed\n");
Brian Silvermanff7b3472015-01-26 17:53:04 -050098 break;
99 }
100 }
101}
102
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800103} // namespace frc971::wpilib