/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- #ifndef AP_Compass_AK8963_H #define AP_Compass_AK8963_H #include #include "../AP_Common/AP_Common.h" #include "../AP_Math/AP_Math.h" #include "Compass.h" #include "AP_Compass_Backend.h" class AK8963_Backend { public: virtual ~AK8963_Backend() {} virtual void read(uint8_t address, uint8_t *buf, uint32_t count) = 0; virtual void write(uint8_t address, const uint8_t *buf, uint32_t count) = 0; virtual bool sem_take_nonblocking() = 0; virtual bool sem_take_blocking() = 0; virtual bool sem_give() = 0; virtual bool init() = 0; virtual uint8_t read(uint8_t address) { uint8_t value; read(address, &value, 1); return value; } virtual void write(uint8_t address, uint8_t value) { write(address, &value, 1); } }; class AP_Compass_AK8963 : public AP_Compass_Backend { public: AP_Compass_AK8963(Compass &compass); bool init(void); void read(void); void accumulate(void); protected: AK8963_Backend *_backend; // Not to be confused with Compass (frontend) "_backends" attribute. float magnetometer_ASA[3]; float _mag_x; float _mag_y; float _mag_z; uint8_t _compass_instance; virtual bool read_raw() = 0; private: typedef enum { STATE_CONVERSION, STATE_SAMPLE, STATE_ERROR } state_t; virtual bool _backend_init() = 0; virtual void _register_read(uint8_t address, uint8_t count, uint8_t *value) = 0; virtual void _register_write(uint8_t address, uint8_t value) = 0; virtual void _backend_reset() = 0; virtual uint8_t _read_id() = 0; virtual void _dump_registers() {} bool _register_read(uint8_t address, uint8_t *value); bool _calibrate(); bool _self_test(); void _update(); void _start_conversion(); void _collect_samples(); float _mag_x_accum; float _mag_y_accum; float _mag_z_accum; uint32_t _accum_count; bool _initialised; state_t _state; uint8_t _magnetometer_adc_resolution; uint32_t _last_update_timestamp; uint32_t _last_accum_time; }; class AK8963_MPU9250_SPI_Backend: public AK8963_Backend { public: AK8963_MPU9250_SPI_Backend(); void read(uint8_t address, uint8_t *buf, uint32_t count); void write(uint8_t address, const uint8_t *buf, uint32_t count); bool sem_take_nonblocking(); bool sem_take_blocking(); bool sem_give(); bool init() ; ~AK8963_MPU9250_SPI_Backend() {} private: AP_HAL::SPIDeviceDriver *_spi; AP_HAL::Semaphore *_spi_sem; }; class AP_Compass_AK8963_MPU9250: public AP_Compass_AK8963 { public: AP_Compass_AK8963_MPU9250(Compass &compass); ~AP_Compass_AK8963_MPU9250() {} bool init(); // detect the sensor static AP_Compass_Backend *detect(Compass &compass); private: bool _backend_init(); void _backend_reset(); void _register_read(uint8_t address, uint8_t count, uint8_t *value); void _register_write(uint8_t address, uint8_t value); void _dump_registers(); bool read_raw(); uint8_t _read_id(); }; #endif