blob: c15ca5be6957b0406c0bcdc48abf5e29fad3836b [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"
Austin Schuhac17fba2020-03-28 15:55:33 -070012#include "frc971/wpilib/imu_batch_generated.h"
Brian Silverman7be68ba2020-01-08 22:08:40 -080013#include "frc971/wpilib/imu_generated.h"
14
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080015namespace frc971::wpilib {
Brian Silverman7be68ba2020-01-08 22:08:40 -080016
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_.
Austin Schuhac17fba2020-03-28 15:55:33 -070050 flatbuffers::Offset<IMUValues> ProcessReading(
51 flatbuffers::FlatBufferBuilder *fbb);
Brian Silverman7be68ba2020-01-08 22:08:40 -080052
53 // Converts a 32-bit value at data to a scaled output value where a value of 1
54 // corresponds to lsb_per_output.
55 static double ConvertValue32(absl::Span<const uint32_t> data,
56 double lsb_per_output);
57 static double ConvertValue16(absl::Span<const uint32_t> data,
58 double lsb_per_output);
59
60 static flatbuffers::Offset<ADIS16470DiagStat> PackDiagStat(
61 flatbuffers::FlatBufferBuilder *fbb, uint16_t value);
62
63 static bool DiagStatHasError(const ADIS16470DiagStat &diag_stat);
64
65 // These may only be called during configuration, when spi_ is not in
66 // automatic mode.
67 uint16_t ReadRegister(uint8_t register_address,
68 uint8_t next_register_address);
69 void WriteRegister(uint8_t register_address, uint16_t value);
70
71 void BeginInitialization() {
72 state_ = State::kUninitialized;
Philipp Schradera6712522023-07-05 20:25:11 -070073 initialize_timer_->Schedule(event_loop_->monotonic_now() +
74 std::chrono::milliseconds(25));
Brian Silverman7be68ba2020-01-08 22:08:40 -080075 }
76
77 aos::EventLoop *const event_loop_;
Austin Schuhac17fba2020-03-28 15:55:33 -070078 aos::Sender<::frc971::IMUValuesBatch> imu_values_sender_;
Brian Silverman7be68ba2020-01-08 22:08:40 -080079 aos::TimerHandler *const initialize_timer_;
80
81 frc::SPI *const spi_;
82 frc::DigitalInput *const data_ready_;
83 frc::DigitalOutput *const reset_;
84
85 State state_ = State::kUninitialized;
86
87 // Data we've read from the FPGA.
88 std::array<uint32_t, 23> read_data_;
89 // Data that we need to read from the FPGA to get a complete reading.
90 absl::Span<uint32_t> to_read_;
91
92 FpgaTimeConverter time_converter_;
93};
94
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080095} // namespace frc971::wpilib
Brian Silverman7be68ba2020-01-08 22:08:40 -080096
97#endif // FRC971_WPILIB_ADIS16470_H_