blob: 12bcf3731a8cbd487555ef4c9c99250118381f02 [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"
Austin Schuh3b010bc2019-02-24 17:25:37 -080012#include "frc971/wpilib/ahal/DriverStation.h"
Sabina Davis1ffa4172019-02-01 22:38:33 -080013#include "frc971/wpilib/dma.h"
14#include "frc971/wpilib/dma_edge_counting.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080015#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisadc58542019-02-01 22:23:00 -080016
17using ::aos::monotonic_clock;
18namespace chrono = ::std::chrono;
19
20namespace frc971 {
21namespace wpilib {
22
23class SensorReader {
24 public:
25 SensorReader();
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080026 virtual ~SensorReader() {}
Sabina Davisadc58542019-02-01 22:23:00 -080027
Austin Schuh45a549f2019-02-02 15:43:56 -080028 // Updates the fast and medium encoder filter frequencies.
29 void UpdateFastEncoderFilterHz(int hz);
30 void UpdateMediumEncoderFilterHz(int hz);
31
Sabina Davisb6317b72019-02-01 22:53:23 -080032 // Sets the left drivetrain encoder.
33 void set_drivetrain_left_encoder(::std::unique_ptr<frc::Encoder> encoder);
34
35 // Sets the right drivetrain encoder.
36 void set_drivetrain_right_encoder(::std::unique_ptr<frc::Encoder> encoder);
37
Sabina Davis6292bec2019-02-06 22:53:14 -080038 // Adds a sensor to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080039 void AddToDMA(DMASampleHandlerInterface *handler) {
Sabina Davis6292bec2019-02-06 22:53:14 -080040 if (!dma_synchronizer_) {
41 dma_synchronizer_.reset(
42 new ::frc971::wpilib::DMASynchronizer(std::make_unique<DMA>()));
43 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080044 dma_synchronizer_->Add(handler);
45 }
46
Austin Schuh3b010bc2019-02-24 17:25:37 -080047 // Sets PWM trigger mode. If true, synchronize the control loops with the PWM
48 // pulses. The sensors are sampled 50 uS after the falling edge of the PWM
49 // pulse.
50 void set_pwm_trigger(bool trigger) { pwm_trigger_ = trigger; }
Sabina Davisadc58542019-02-01 22:23:00 -080051
Sabina Davisa42cc352019-02-01 22:55:50 -080052 // Stops the pwm trigger on the next iteration.
53 void Quit() { run_ = false; }
54
Sabina Davis399dbd82019-02-01 23:06:08 -080055 virtual void RunIteration() = 0;
Sabina Davis6292bec2019-02-06 22:53:14 -080056 // Runs the DMA iteration after the synchronizer. This only gets run if a
57 // sensor has been added to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080058 virtual void RunDmaIteration() {}
Sabina Davis399dbd82019-02-01 23:06:08 -080059
60 void operator()();
61
Sabina Davisadc58542019-02-01 22:23:00 -080062 protected:
Austin Schuh54667ac2019-02-02 16:44:49 -080063 // Copies a DMAEncoder to a IndexPosition with the correct unit and direction
64 // changes.
65 void CopyPosition(const ::frc971::wpilib::DMAEncoder &encoder,
66 ::frc971::IndexPosition *position,
67 double encoder_counts_per_revolution, double encoder_ratio,
68 bool reverse) {
69 const double multiplier = reverse ? -1.0 : 1.0;
70 position->encoder =
71 multiplier * encoder_translate(encoder.polled_encoder_value(),
72 encoder_counts_per_revolution,
73 encoder_ratio);
74 position->latched_encoder =
75 multiplier * encoder_translate(encoder.last_encoder_value(),
76 encoder_counts_per_revolution,
77 encoder_ratio);
78 position->index_pulses = encoder.index_posedge_count();
79 }
80
81 // Copies a AbsoluteEncoderAndPotentiometer to a PotAndAbsolutePosition with
82 // the correct unit and direction changes.
83 void CopyPosition(
84 const ::frc971::wpilib::AbsoluteEncoderAndPotentiometer &encoder,
85 ::frc971::PotAndAbsolutePosition *position,
86 double encoder_counts_per_revolution, double encoder_ratio,
87 ::std::function<double(double)> potentiometer_translate, bool reverse,
88 double pot_offset) {
89 const double multiplier = reverse ? -1.0 : 1.0;
90 position->pot = multiplier * potentiometer_translate(
91 encoder.ReadPotentiometerVoltage()) +
92 pot_offset;
93 position->encoder =
94 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
95 encoder_counts_per_revolution,
96 encoder_ratio);
97
98 position->absolute_encoder =
99 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
100 : encoder.ReadAbsoluteEncoder()) *
101 encoder_ratio * (2.0 * M_PI);
102 }
103
104 // Copies a DMAEdgeCounter to a HallEffectAndPosition with the correct unit
105 // and direction changes.
106 void CopyPosition(const ::frc971::wpilib::DMAEdgeCounter &counter,
107 ::frc971::HallEffectAndPosition *position,
108 double encoder_counts_per_revolution, double encoder_ratio,
109 bool reverse) {
110 const double multiplier = reverse ? -1.0 : 1.0;
111 position->encoder =
112 multiplier * encoder_translate(counter.polled_encoder(),
113 encoder_counts_per_revolution,
114 encoder_ratio);
115 position->current = !counter.polled_value();
116 position->posedge_count = counter.negative_count();
117 position->negedge_count = counter.positive_count();
118 position->posedge_value =
119 multiplier * encoder_translate(counter.last_negative_encoder_value(),
120 encoder_counts_per_revolution,
121 encoder_ratio);
122 position->negedge_value =
123 multiplier * encoder_translate(counter.last_positive_encoder_value(),
124 encoder_counts_per_revolution,
125 encoder_ratio);
126 }
127
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800128 // Copies a Absolute Encoder with the correct unit
129 // and direction changes.
130 void CopyPosition(
131 const ::frc971::wpilib::AbsoluteEncoder &encoder,
132 ::frc971::AbsolutePosition *position,
133 double encoder_counts_per_revolution, double encoder_ratio,
134 bool reverse) {
135 const double multiplier = reverse ? -1.0 : 1.0;
136 position->encoder =
137 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
138 encoder_counts_per_revolution,
139 encoder_ratio);
140
141 position->absolute_encoder =
142 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
143 : encoder.ReadAbsoluteEncoder()) *
144 encoder_ratio * (2.0 * M_PI);
145 }
146
Sabina Davis2243cab2019-02-05 21:45:08 -0800147 void CopyPosition(
148 const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
149 ::frc971::PotAndIndexPosition *position,
150 ::std::function<double(int32_t)> encoder_translate,
151 ::std::function<double(double)> potentiometer_translate, bool reverse,
152 double pot_offset) {
153 const double multiplier = reverse ? -1.0 : 1.0;
154 position->encoder =
155 multiplier * encoder_translate(encoder.polled_encoder_value());
156 position->pot = multiplier * potentiometer_translate(
157 encoder.polled_potentiometer_voltage()) +
158 pot_offset;
159 position->latched_encoder =
160 multiplier * encoder_translate(encoder.last_encoder_value());
161 position->latched_pot =
162 multiplier *
163 potentiometer_translate(encoder.last_potentiometer_voltage()) +
164 pot_offset;
165 position->index_pulses = encoder.index_posedge_count();
166 }
167
Austin Schuh54667ac2019-02-02 16:44:49 -0800168 double encoder_translate(int32_t value, double counts_per_revolution,
169 double ratio) {
170 return static_cast<double>(value) / counts_per_revolution * ratio *
171 (2.0 * M_PI);
172 }
173
Austin Schuh45a549f2019-02-02 15:43:56 -0800174 frc::DigitalGlitchFilter fast_encoder_filter_, medium_encoder_filter_;
175
176 ::std::unique_ptr<frc::Encoder> drivetrain_left_encoder_,
177 drivetrain_right_encoder_;
178
179 private:
Austin Schuh2c2cc2e2019-02-02 20:19:45 -0800180 // Gets called right before the DMA synchronizer is up and running.
181 virtual void Start() {}
182
Austin Schuh3b010bc2019-02-24 17:25:37 -0800183 // Returns the monotonic time of the start of the first PWM cycle.
184 // Returns min_time if no start time could be calculated.
185 monotonic_clock::time_point GetPWMStartTime();
Sabina Davisadc58542019-02-01 22:23:00 -0800186
Austin Schuh3b010bc2019-02-24 17:25:37 -0800187 bool pwm_trigger_;
Sabina Davisadc58542019-02-01 22:23:00 -0800188
Sabina Davis1ffa4172019-02-01 22:38:33 -0800189 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
190
Sabina Davisadc58542019-02-01 22:23:00 -0800191 ::std::atomic<bool> run_{true};
Austin Schuh3b010bc2019-02-24 17:25:37 -0800192 ::frc::DriverStation *ds_;
Sabina Davisadc58542019-02-01 22:23:00 -0800193};
194
195} // namespace wpilib
196} // namespace frc971
197
198#endif // FRC971_WPILIB_SENSOR_READER_H_