blob: 25e75926f6f57127840eda6ef82e1ae4dfd6a253 [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
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include "aos/events/event_loop.h"
Austin Schuh217a9782019-12-21 23:02:50 -08008#include "aos/events/shm_event_loop.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -07009#include "aos/robot_state/robot_state_generated.h"
Sabina Davisadc58542019-02-01 22:23:00 -080010#include "aos/stl_mutex/stl_mutex.h"
11#include "aos/time/time.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070012#include "frc971/control_loops/control_loops_generated.h"
Sabina Davisadc58542019-02-01 22:23:00 -080013#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
14#include "frc971/wpilib/ahal/DigitalInput.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080015#include "frc971/wpilib/ahal/DriverStation.h"
Sabina Davis1ffa4172019-02-01 22:38:33 -080016#include "frc971/wpilib/dma.h"
17#include "frc971/wpilib/dma_edge_counting.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080018#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisadc58542019-02-01 22:23:00 -080019
20using ::aos::monotonic_clock;
21namespace chrono = ::std::chrono;
22
23namespace frc971 {
24namespace wpilib {
25
26class SensorReader {
27 public:
Austin Schuh217a9782019-12-21 23:02:50 -080028 SensorReader(::aos::ShmEventLoop *event_loop);
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080029 virtual ~SensorReader() {}
Sabina Davisadc58542019-02-01 22:23:00 -080030
Austin Schuh45a549f2019-02-02 15:43:56 -080031 // Updates the fast and medium encoder filter frequencies.
32 void UpdateFastEncoderFilterHz(int hz);
33 void UpdateMediumEncoderFilterHz(int hz);
34
Sabina Davisb6317b72019-02-01 22:53:23 -080035 // Sets the left drivetrain encoder.
36 void set_drivetrain_left_encoder(::std::unique_ptr<frc::Encoder> encoder);
37
38 // Sets the right drivetrain encoder.
39 void set_drivetrain_right_encoder(::std::unique_ptr<frc::Encoder> encoder);
40
Sabina Davis6292bec2019-02-06 22:53:14 -080041 // Adds a sensor to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080042 void AddToDMA(DMASampleHandlerInterface *handler) {
Sabina Davis6292bec2019-02-06 22:53:14 -080043 if (!dma_synchronizer_) {
44 dma_synchronizer_.reset(
45 new ::frc971::wpilib::DMASynchronizer(std::make_unique<DMA>()));
46 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080047 dma_synchronizer_->Add(handler);
48 }
49
Austin Schuh3b010bc2019-02-24 17:25:37 -080050 // Sets PWM trigger mode. If true, synchronize the control loops with the PWM
51 // pulses. The sensors are sampled 50 uS after the falling edge of the PWM
52 // pulse.
53 void set_pwm_trigger(bool trigger) { pwm_trigger_ = trigger; }
Sabina Davisadc58542019-02-01 22:23:00 -080054
Sabina Davisa42cc352019-02-01 22:55:50 -080055 // Stops the pwm trigger on the next iteration.
56 void Quit() { run_ = false; }
57
Sabina Davis399dbd82019-02-01 23:06:08 -080058 virtual void RunIteration() = 0;
Sabina Davis6292bec2019-02-06 22:53:14 -080059 // Runs the DMA iteration after the synchronizer. This only gets run if a
60 // sensor has been added to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080061 virtual void RunDmaIteration() {}
Sabina Davis399dbd82019-02-01 23:06:08 -080062
Sabina Davisadc58542019-02-01 22:23:00 -080063 protected:
Austin Schuh54667ac2019-02-02 16:44:49 -080064 // Copies a DMAEncoder to a IndexPosition with the correct unit and direction
65 // changes.
66 void CopyPosition(const ::frc971::wpilib::DMAEncoder &encoder,
Alex Perrycb7da4b2019-08-28 19:35:56 -070067 ::frc971::IndexPositionT *position,
Austin Schuh54667ac2019-02-02 16:44:49 -080068 double encoder_counts_per_revolution, double encoder_ratio,
69 bool reverse) {
70 const double multiplier = reverse ? -1.0 : 1.0;
71 position->encoder =
72 multiplier * encoder_translate(encoder.polled_encoder_value(),
73 encoder_counts_per_revolution,
74 encoder_ratio);
75 position->latched_encoder =
76 multiplier * encoder_translate(encoder.last_encoder_value(),
77 encoder_counts_per_revolution,
78 encoder_ratio);
79 position->index_pulses = encoder.index_posedge_count();
80 }
81
82 // Copies a AbsoluteEncoderAndPotentiometer to a PotAndAbsolutePosition with
83 // the correct unit and direction changes.
84 void CopyPosition(
85 const ::frc971::wpilib::AbsoluteEncoderAndPotentiometer &encoder,
Alex Perrycb7da4b2019-08-28 19:35:56 -070086 ::frc971::PotAndAbsolutePositionT *position,
Austin Schuh54667ac2019-02-02 16:44:49 -080087 double encoder_counts_per_revolution, double encoder_ratio,
88 ::std::function<double(double)> potentiometer_translate, bool reverse,
89 double pot_offset) {
90 const double multiplier = reverse ? -1.0 : 1.0;
91 position->pot = multiplier * potentiometer_translate(
92 encoder.ReadPotentiometerVoltage()) +
93 pot_offset;
94 position->encoder =
95 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
96 encoder_counts_per_revolution,
97 encoder_ratio);
98
99 position->absolute_encoder =
100 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
101 : encoder.ReadAbsoluteEncoder()) *
102 encoder_ratio * (2.0 * M_PI);
103 }
104
105 // Copies a DMAEdgeCounter to a HallEffectAndPosition with the correct unit
106 // and direction changes.
107 void CopyPosition(const ::frc971::wpilib::DMAEdgeCounter &counter,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700108 ::frc971::HallEffectAndPositionT *position,
Austin Schuh54667ac2019-02-02 16:44:49 -0800109 double encoder_counts_per_revolution, double encoder_ratio,
110 bool reverse) {
111 const double multiplier = reverse ? -1.0 : 1.0;
112 position->encoder =
113 multiplier * encoder_translate(counter.polled_encoder(),
114 encoder_counts_per_revolution,
115 encoder_ratio);
116 position->current = !counter.polled_value();
117 position->posedge_count = counter.negative_count();
118 position->negedge_count = counter.positive_count();
119 position->posedge_value =
120 multiplier * encoder_translate(counter.last_negative_encoder_value(),
121 encoder_counts_per_revolution,
122 encoder_ratio);
123 position->negedge_value =
124 multiplier * encoder_translate(counter.last_positive_encoder_value(),
125 encoder_counts_per_revolution,
126 encoder_ratio);
127 }
128
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800129 // Copies a Absolute Encoder with the correct unit
130 // and direction changes.
131 void CopyPosition(
132 const ::frc971::wpilib::AbsoluteEncoder &encoder,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700133 ::frc971::AbsolutePositionT *position,
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800134 double encoder_counts_per_revolution, double encoder_ratio,
135 bool reverse) {
136 const double multiplier = reverse ? -1.0 : 1.0;
137 position->encoder =
138 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
139 encoder_counts_per_revolution,
140 encoder_ratio);
141
142 position->absolute_encoder =
143 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
144 : encoder.ReadAbsoluteEncoder()) *
145 encoder_ratio * (2.0 * M_PI);
146 }
147
Sabina Davis2243cab2019-02-05 21:45:08 -0800148 void CopyPosition(
149 const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700150 ::frc971::PotAndIndexPositionT *position,
Sabina Davis2243cab2019-02-05 21:45:08 -0800151 ::std::function<double(int32_t)> encoder_translate,
152 ::std::function<double(double)> potentiometer_translate, bool reverse,
153 double pot_offset) {
154 const double multiplier = reverse ? -1.0 : 1.0;
155 position->encoder =
156 multiplier * encoder_translate(encoder.polled_encoder_value());
157 position->pot = multiplier * potentiometer_translate(
158 encoder.polled_potentiometer_voltage()) +
159 pot_offset;
160 position->latched_encoder =
161 multiplier * encoder_translate(encoder.last_encoder_value());
162 position->latched_pot =
163 multiplier *
164 potentiometer_translate(encoder.last_potentiometer_voltage()) +
165 pot_offset;
166 position->index_pulses = encoder.index_posedge_count();
167 }
168
Alex Perry2712c102020-02-17 19:17:11 -0800169 // Copies a relative encoder.
170 void CopyPosition(const ::frc::Encoder &encoder,
171 ::frc971::RelativePositionT *position,
172 double encoder_counts_per_revolution, double encoder_ratio,
173 bool reverse) {
174 const double multiplier = reverse ? -1.0 : 1.0;
175 position->encoder =
176 multiplier * encoder_translate(encoder.GetRaw(),
177 encoder_counts_per_revolution,
178 encoder_ratio);
179 }
180
Austin Schuh54667ac2019-02-02 16:44:49 -0800181 double encoder_translate(int32_t value, double counts_per_revolution,
182 double ratio) {
183 return static_cast<double>(value) / counts_per_revolution * ratio *
184 (2.0 * M_PI);
185 }
186
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800187 ::aos::EventLoop *event_loop_;
188 ::aos::Sender<::aos::RobotState> robot_state_sender_;
189
Austin Schuh45a549f2019-02-02 15:43:56 -0800190 frc::DigitalGlitchFilter fast_encoder_filter_, medium_encoder_filter_;
191
192 ::std::unique_ptr<frc::Encoder> drivetrain_left_encoder_,
193 drivetrain_right_encoder_;
194
195 private:
Austin Schuh2c2cc2e2019-02-02 20:19:45 -0800196 // Gets called right before the DMA synchronizer is up and running.
197 virtual void Start() {}
198
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700199 // Sets up everything during startup.
200 void DoStart();
201
202 // Runs a single iteration.
203 void Loop(int iterations);
204
Austin Schuh3b010bc2019-02-24 17:25:37 -0800205 // Returns the monotonic time of the start of the first PWM cycle.
206 // Returns min_time if no start time could be calculated.
207 monotonic_clock::time_point GetPWMStartTime();
Sabina Davisadc58542019-02-01 22:23:00 -0800208
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700209 bool pwm_trigger_ = false;
Sabina Davisadc58542019-02-01 22:23:00 -0800210
Sabina Davis1ffa4172019-02-01 22:38:33 -0800211 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
212
Sabina Davisadc58542019-02-01 22:23:00 -0800213 ::std::atomic<bool> run_{true};
Austin Schuh3b010bc2019-02-24 17:25:37 -0800214 ::frc::DriverStation *ds_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700215
216 const int32_t my_pid_;
217
218 // Pointer to the phased loop handler used to modify the wakeup.
219 ::aos::PhasedLoopHandler *phased_loop_handler_;
220
221 // Last time we got called.
222 ::aos::monotonic_clock::time_point last_monotonic_now_ =
223 ::aos::monotonic_clock::min_time;
224 // The current period.
225 chrono::microseconds period_ = chrono::microseconds(5000);
Sabina Davisadc58542019-02-01 22:23:00 -0800226};
227
228} // namespace wpilib
229} // namespace frc971
230
231#endif // FRC971_WPILIB_SENSOR_READER_H_