blob: 4c9917ffb2a81829ff21bdbc867b6aeaa581a7bf [file] [log] [blame]
Brian Silverman7be68ba2020-01-08 22:08:40 -08001#ifndef FRC971_WPILIB_ADIS16470_H_
2#define FRC971_WPILIB_ADIS16470_H_
3
4#include "absl/types/span.h"
5
6#include "aos/events/event_loop.h"
7#include "frc971/wpilib/ahal/DigitalInput.h"
8#include "frc971/wpilib/ahal/DigitalOutput.h"
9#include "frc971/wpilib/ahal/DigitalSource.h"
10#include "frc971/wpilib/ahal/SPI.h"
11#include "frc971/wpilib/fpga_time_conversion.h"
12#include "frc971/wpilib/imu_generated.h"
13
14namespace frc971 {
15namespace wpilib {
16
17// Handles interfacing with an Analog Devices ADIS16470 over SPI and sending the
18// resulting values out on a channel.
19//
20// This relies on the AutoRead functionality in the FPGA to read values when
21// data is ready. It then allows the FPGA to buffer those until right before the
22// relevant control loops run, at which point they are all sent out on the
23// relevant channel.
24class ADIS16470 {
25 public:
26 // event_loop's thread will be hijacked before processing any events.
27 // spi is how to talk to the sensor over SPI.
28 // data_ready is the Data Ready (DR) pin (J6).
29 // reset is the Reset (RST) pin (F3).
30 ADIS16470(aos::EventLoop *event_loop, frc::SPI *spi,
31 frc::DigitalInput *data_ready, frc::DigitalOutput *reset);
32
33 ADIS16470(const ADIS16470 &) = delete;
34 ADIS16470 &operator=(const ADIS16470 &) = delete;
35
36 // Reads all the queued-up data and sends out any complete readings.
37 void DoReads();
38
39 private:
40 enum class State {
41 kUninitialized,
42 kWaitForReset,
43 kRunning,
44 };
45
46 // Performs one (non-blocking) initialization step.
47 void DoInitializeStep();
48
49 // Processes a complete reading in read_data_.
50 void ProcessReading();
51
52 // Converts a 32-bit value at data to a scaled output value where a value of 1
53 // corresponds to lsb_per_output.
54 static double ConvertValue32(absl::Span<const uint32_t> data,
55 double lsb_per_output);
56 static double ConvertValue16(absl::Span<const uint32_t> data,
57 double lsb_per_output);
58
59 static flatbuffers::Offset<ADIS16470DiagStat> PackDiagStat(
60 flatbuffers::FlatBufferBuilder *fbb, uint16_t value);
61
62 static bool DiagStatHasError(const ADIS16470DiagStat &diag_stat);
63
64 // These may only be called during configuration, when spi_ is not in
65 // automatic mode.
66 uint16_t ReadRegister(uint8_t register_address,
67 uint8_t next_register_address);
68 void WriteRegister(uint8_t register_address, uint16_t value);
69
70 void BeginInitialization() {
71 state_ = State::kUninitialized;
72 initialize_timer_->Setup(event_loop_->monotonic_now() +
73 std::chrono::milliseconds(25));
74 }
75
76 aos::EventLoop *const event_loop_;
77 aos::Sender<::frc971::IMUValues> imu_values_sender_;
78 aos::TimerHandler *const initialize_timer_;
79
80 frc::SPI *const spi_;
81 frc::DigitalInput *const data_ready_;
82 frc::DigitalOutput *const reset_;
83
84 State state_ = State::kUninitialized;
85
86 // Data we've read from the FPGA.
87 std::array<uint32_t, 23> read_data_;
88 // Data that we need to read from the FPGA to get a complete reading.
89 absl::Span<uint32_t> to_read_;
90
91 FpgaTimeConverter time_converter_;
92};
93
94} // namespace wpilib
95} // namespace frc971
96
97#endif // FRC971_WPILIB_ADIS16470_H_