blob: 02dea2cd01bb69a004bef1d0542cb7f707b6c757 [file] [log] [blame]
Sabina Davisadc58542019-02-01 22:23:00 -08001#ifndef FRC971_WPILIB_SENSOR_READER_H_
2#define FRC971_WPILIB_SENSOR_READER_H_
3
4#include <atomic>
5#include <chrono>
6
7#include "aos/stl_mutex/stl_mutex.h"
8#include "aos/time/time.h"
Austin Schuh54667ac2019-02-02 16:44:49 -08009#include "frc971/control_loops/control_loops.q.h"
Sabina Davisadc58542019-02-01 22:23:00 -080010#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
11#include "frc971/wpilib/ahal/DigitalInput.h"
Sabina Davis1ffa4172019-02-01 22:38:33 -080012#include "frc971/wpilib/dma.h"
13#include "frc971/wpilib/dma_edge_counting.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080014#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisadc58542019-02-01 22:23:00 -080015
16using ::aos::monotonic_clock;
17namespace chrono = ::std::chrono;
18
19namespace frc971 {
20namespace wpilib {
21
22class SensorReader {
23 public:
24 SensorReader();
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080025 virtual ~SensorReader() {}
Sabina Davisadc58542019-02-01 22:23:00 -080026
Austin Schuh45a549f2019-02-02 15:43:56 -080027 // Updates the fast and medium encoder filter frequencies.
28 void UpdateFastEncoderFilterHz(int hz);
29 void UpdateMediumEncoderFilterHz(int hz);
30
Sabina Davisb6317b72019-02-01 22:53:23 -080031 // Sets the left drivetrain encoder.
32 void set_drivetrain_left_encoder(::std::unique_ptr<frc::Encoder> encoder);
33
34 // Sets the right drivetrain encoder.
35 void set_drivetrain_right_encoder(::std::unique_ptr<frc::Encoder> encoder);
36
37 // Sets the dma.
Sabina Davis1ffa4172019-02-01 22:38:33 -080038 void set_dma(::std::unique_ptr<DMA> dma);
39
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080040 void AddToDMA(DMASampleHandlerInterface *handler) {
41 dma_synchronizer_->Add(handler);
42 }
43
Sabina Davisb6317b72019-02-01 22:53:23 -080044 // Sets the pwm trigger.
Sabina Davisadc58542019-02-01 22:23:00 -080045 void set_pwm_trigger(::std::unique_ptr<frc::DigitalInput> pwm_trigger);
46
Sabina Davisa42cc352019-02-01 22:55:50 -080047 // Stops the pwm trigger on the next iteration.
48 void Quit() { run_ = false; }
49
Sabina Davis399dbd82019-02-01 23:06:08 -080050 virtual void RunIteration() = 0;
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080051 virtual void RunDmaIteration() {}
Sabina Davis399dbd82019-02-01 23:06:08 -080052
53 void operator()();
54
Sabina Davisadc58542019-02-01 22:23:00 -080055 protected:
Austin Schuh54667ac2019-02-02 16:44:49 -080056 // Copies a DMAEncoder to a IndexPosition with the correct unit and direction
57 // changes.
58 void CopyPosition(const ::frc971::wpilib::DMAEncoder &encoder,
59 ::frc971::IndexPosition *position,
60 double encoder_counts_per_revolution, double encoder_ratio,
61 bool reverse) {
62 const double multiplier = reverse ? -1.0 : 1.0;
63 position->encoder =
64 multiplier * encoder_translate(encoder.polled_encoder_value(),
65 encoder_counts_per_revolution,
66 encoder_ratio);
67 position->latched_encoder =
68 multiplier * encoder_translate(encoder.last_encoder_value(),
69 encoder_counts_per_revolution,
70 encoder_ratio);
71 position->index_pulses = encoder.index_posedge_count();
72 }
73
74 // Copies a AbsoluteEncoderAndPotentiometer to a PotAndAbsolutePosition with
75 // the correct unit and direction changes.
76 void CopyPosition(
77 const ::frc971::wpilib::AbsoluteEncoderAndPotentiometer &encoder,
78 ::frc971::PotAndAbsolutePosition *position,
79 double encoder_counts_per_revolution, double encoder_ratio,
80 ::std::function<double(double)> potentiometer_translate, bool reverse,
81 double pot_offset) {
82 const double multiplier = reverse ? -1.0 : 1.0;
83 position->pot = multiplier * potentiometer_translate(
84 encoder.ReadPotentiometerVoltage()) +
85 pot_offset;
86 position->encoder =
87 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
88 encoder_counts_per_revolution,
89 encoder_ratio);
90
91 position->absolute_encoder =
92 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
93 : encoder.ReadAbsoluteEncoder()) *
94 encoder_ratio * (2.0 * M_PI);
95 }
96
97 // Copies a DMAEdgeCounter to a HallEffectAndPosition with the correct unit
98 // and direction changes.
99 void CopyPosition(const ::frc971::wpilib::DMAEdgeCounter &counter,
100 ::frc971::HallEffectAndPosition *position,
101 double encoder_counts_per_revolution, double encoder_ratio,
102 bool reverse) {
103 const double multiplier = reverse ? -1.0 : 1.0;
104 position->encoder =
105 multiplier * encoder_translate(counter.polled_encoder(),
106 encoder_counts_per_revolution,
107 encoder_ratio);
108 position->current = !counter.polled_value();
109 position->posedge_count = counter.negative_count();
110 position->negedge_count = counter.positive_count();
111 position->posedge_value =
112 multiplier * encoder_translate(counter.last_negative_encoder_value(),
113 encoder_counts_per_revolution,
114 encoder_ratio);
115 position->negedge_value =
116 multiplier * encoder_translate(counter.last_positive_encoder_value(),
117 encoder_counts_per_revolution,
118 encoder_ratio);
119 }
120
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800121 // Copies a Absolute Encoder with the correct unit
122 // and direction changes.
123 void CopyPosition(
124 const ::frc971::wpilib::AbsoluteEncoder &encoder,
125 ::frc971::AbsolutePosition *position,
126 double encoder_counts_per_revolution, double encoder_ratio,
127 bool reverse) {
128 const double multiplier = reverse ? -1.0 : 1.0;
129 position->encoder =
130 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
131 encoder_counts_per_revolution,
132 encoder_ratio);
133
134 position->absolute_encoder =
135 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
136 : encoder.ReadAbsoluteEncoder()) *
137 encoder_ratio * (2.0 * M_PI);
138 }
139
Austin Schuh54667ac2019-02-02 16:44:49 -0800140 double encoder_translate(int32_t value, double counts_per_revolution,
141 double ratio) {
142 return static_cast<double>(value) / counts_per_revolution * ratio *
143 (2.0 * M_PI);
144 }
145
Austin Schuh45a549f2019-02-02 15:43:56 -0800146 frc::DigitalGlitchFilter fast_encoder_filter_, medium_encoder_filter_;
147
148 ::std::unique_ptr<frc::Encoder> drivetrain_left_encoder_,
149 drivetrain_right_encoder_;
150
151 private:
Austin Schuh2c2cc2e2019-02-02 20:19:45 -0800152 // Gets called right before the DMA synchronizer is up and running.
153 virtual void Start() {}
154
Sabina Davisb6317b72019-02-01 22:53:23 -0800155 // Uses the pwm trigger to find the pwm cycle width and offset for that
156 // iteration.
Sabina Davisadc58542019-02-01 22:23:00 -0800157 void RunPWMDetecter();
158
159 ::std::unique_ptr<frc::DigitalInput> pwm_trigger_;
160
Sabina Davisadc58542019-02-01 22:23:00 -0800161 // Mutex to manage access to the period and tick time variables.
162 ::aos::stl_mutex tick_time_mutex_;
163 monotonic_clock::time_point last_tick_time_monotonic_timepoint_ =
164 monotonic_clock::min_time;
Austin Schuh45a549f2019-02-02 15:43:56 -0800165 chrono::nanoseconds last_period_;
Sabina Davisadc58542019-02-01 22:23:00 -0800166
Sabina Davis1ffa4172019-02-01 22:38:33 -0800167 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
168
Sabina Davisadc58542019-02-01 22:23:00 -0800169 ::std::atomic<bool> run_{true};
Sabina Davisadc58542019-02-01 22:23:00 -0800170};
171
172} // namespace wpilib
173} // namespace frc971
174
175#endif // FRC971_WPILIB_SENSOR_READER_H_