blob: 5af6a4f71810a9340956b5c7dc56d4cf640cb048 [file] [log] [blame]
Brian Silverman5f17a972016-02-28 01:49:32 -05001#ifndef FRC971_WPILIB_ADIS16448_H_
2#define FRC971_WPILIB_ADIS16448_H_
3
4#include <stdint.h>
5
Brian Silverman5f17a972016-02-28 01:49:32 -05006#include <atomic>
Parker Schuhd3b7a8872018-02-19 16:42:27 -08007#include <memory>
Brian Silverman5f17a972016-02-28 01:49:32 -05008
Parker Schuhd3b7a8872018-02-19 16:42:27 -08009#include "frc971/wpilib/ahal/DigitalInput.h"
10#include "frc971/wpilib/ahal/DigitalOutput.h"
11#include "frc971/wpilib/ahal/SPI.h"
Brian Silverman5f17a972016-02-28 01:49:32 -050012#undef ERROR
13
Austin Schuhdf6cbb12019-02-02 13:46:52 -080014#include "aos/events/event-loop.h"
John Park33858a32018-09-28 23:05:48 -070015#include "aos/logging/logging.h"
Austin Schuhdf6cbb12019-02-02 13:46:52 -080016#include "aos/robot_state/robot_state.q.h"
Austin Schuh73b6e3b2019-05-27 16:37:15 -070017#include "frc971/wpilib/imu.q.h"
Brian Silverman003a4732018-03-11 14:02:15 -070018#include "frc971/wpilib/spi_rx_clearer.h"
Brian Silverman5f17a972016-02-28 01:49:32 -050019
20namespace frc971 {
21namespace wpilib {
22
23// Handles interfacing with an Analog Devices ADIS16448 Inertial Sensor over
24// SPI and sending values out on a queue.
25//
26// The sensor is configured to generate samples at 204.8 Hz, and the values are
27// sent out as each sample is received.
28//
29// This is designed to be passed into ::std::thread's constructor so it will run
30// as a separate thread.
31class ADIS16448 {
32 public:
33 // port is where to find the sensor over SPI.
34 // dio1 must be connected to DIO1 on the sensor.
Austin Schuhdf6cbb12019-02-02 13:46:52 -080035 ADIS16448(::aos::EventLoop *event_loop, frc::SPI::Port port,
36 frc::DigitalInput *dio1);
Brian Silverman5f17a972016-02-28 01:49:32 -050037
Brian Silvermana70994f2017-03-16 22:32:55 -070038 // Sets the dummy SPI port to send values on to make the roboRIO deassert the
39 // chip select line. This is mainly useful when there are no other devices
40 // sharing the bus.
Parker Schuhd3b7a8872018-02-19 16:42:27 -080041 void SetDummySPI(frc::SPI::Port port);
Brian Silvermana70994f2017-03-16 22:32:55 -070042
43 // Sets the reset line for the IMU to use for error recovery.
Parker Schuhd3b7a8872018-02-19 16:42:27 -080044 void set_reset(frc::DigitalOutput *output) { reset_ = output; }
Brian Silvermana70994f2017-03-16 22:32:55 -070045
Brian Silverman5f17a972016-02-28 01:49:32 -050046 // For ::std::thread to call.
47 //
48 // Initializes the sensor and then loops until Quit() is called taking
49 // readings.
50 void operator()();
51
Brian Silvermancfc8fa42019-03-30 21:07:39 -060052 // Sets a function to be called immediately after each time this class uses
53 // the SPI bus. This is a good place to do other things on the bus.
Brian Silverman56c2bcb2019-02-24 15:10:18 -080054 void set_spi_idle_callback(std::function<void()> spi_idle_callback) {
55 spi_idle_callback_ = std::move(spi_idle_callback);
56 }
57
Brian Silverman5f17a972016-02-28 01:49:32 -050058 void Quit() { run_ = false; }
59
Philipp Schrader29d54f22016-04-02 22:14:48 +000060 double gyro_x_zeroed_offset() const { return gyro_x_zeroed_offset_; }
61 double gyro_y_zeroed_offset() const { return gyro_y_zeroed_offset_; }
62 double gyro_z_zeroed_offset() const { return gyro_z_zeroed_offset_; }
63
Brian Silverman5f17a972016-02-28 01:49:32 -050064 private:
Brian Silvermana70994f2017-03-16 22:32:55 -070065 // Try to initialize repeatedly as long as we're supposed to be running.
66 void InitializeUntilSuccessful();
67
Brian Silverman5f17a972016-02-28 01:49:32 -050068 // Converts a 16-bit value at data to a scaled output value where a value of 1
69 // corresponds to lsb_per_output.
70 float ConvertValue(uint8_t *data, double lsb_per_output, bool sign = true);
71
72 // Performs an SPI transaction.
73 // Returns true if it succeeds.
74 template <uint8_t size>
75 bool DoTransaction(uint8_t to_send[size], uint8_t to_receive[size]);
76
77 // Reads one of the gyro's registers and returns the value in value.
78 // next_address is the address of the *next* register to read.
79 // Not sure what gets stored in value for the first read, but it should be
80 // ignored. Passing nullptr for value is allowed to completely ignore it.
81 // Returns true if it succeeds.
82 bool ReadRegister(uint8_t next_address, uint16_t *value);
83
84 // Writes a value to one of the registers.
85 // Returns true if it succeeds.
86 bool WriteRegister(uint8_t address, uint16_t value);
87
88 // Checks the given value of the DIAG_STAT register and logs any errors.
89 // Returns true if there are no errors we care about.
90 bool CheckDiagStatValue(uint16_t value) const;
91
92 // Starts everything up and runs a self test.
93 // Returns true if it succeeds.
94 bool Initialize();
95
Austin Schuhdf6cbb12019-02-02 13:46:52 -080096 ::aos::EventLoop *event_loop_;
97 ::aos::Fetcher<::aos::JoystickState> joystick_state_fetcher_;
Austin Schuh73b6e3b2019-05-27 16:37:15 -070098 ::aos::Sender<::frc971::IMUValues> imu_values_sender_;
Austin Schuhdf6cbb12019-02-02 13:46:52 -080099
Brian Silvermana70994f2017-03-16 22:32:55 -0700100 // TODO(Brian): This object has no business owning these ones.
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800101 const ::std::unique_ptr<frc::SPI> spi_;
102 ::std::unique_ptr<frc::SPI> dummy_spi_;
103 frc::DigitalInput *const dio1_;
104 frc::DigitalOutput *reset_ = nullptr;
Brian Silverman5f17a972016-02-28 01:49:32 -0500105
Brian Silverman56c2bcb2019-02-24 15:10:18 -0800106 std::function<void()> spi_idle_callback_ = []() {};
Brian Silverman5f17a972016-02-28 01:49:32 -0500107 ::std::atomic<bool> run_{true};
Philipp Schrader29d54f22016-04-02 22:14:48 +0000108
109 // The averaged values of the gyro over 6 seconds after power up.
Austin Schuh943fcbd2016-04-03 21:35:41 -0700110 bool gyros_are_zeroed_ = false;
Philipp Schrader29d54f22016-04-02 22:14:48 +0000111 double gyro_x_zeroed_offset_ = 0.0;
112 double gyro_y_zeroed_offset_ = 0.0;
113 double gyro_z_zeroed_offset_ = 0.0;
Brian Silverman003a4732018-03-11 14:02:15 -0700114
115 SpiRxClearer rx_clearer_;
Brian Silverman5f17a972016-02-28 01:49:32 -0500116};
117
118} // namespace wpilib
119} // namespace frc971
120
121#endif // FRC971_WPILIB_ADIS16448_H_