mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
278 lines
8.2 KiB
C++
278 lines
8.2 KiB
C++
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2012-2017 PX4 Development Team. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/**
|
|
* @file Device.hpp
|
|
*
|
|
* Definitions for the generic base classes in the device framework.
|
|
*/
|
|
|
|
#ifndef _DEVICE_DEVICE_HPP
|
|
#define _DEVICE_DEVICE_HPP
|
|
|
|
/*
|
|
* Includes here should only cover the needs of the framework definitions.
|
|
*/
|
|
#include <px4_platform_common/px4_config.h>
|
|
#include <px4_platform_common/posix.h>
|
|
|
|
#include <drivers/drv_sensor.h>
|
|
|
|
#define DEVICE_LOG(FMT, ...) PX4_LOG_NAMED(_name, FMT, ##__VA_ARGS__)
|
|
#define DEVICE_DEBUG(FMT, ...) PX4_LOG_NAMED_COND(_name, _debug_enabled, FMT, ##__VA_ARGS__)
|
|
|
|
/**
|
|
* Namespace encapsulating all device framework classes, functions and data.
|
|
*/
|
|
namespace device
|
|
{
|
|
|
|
/**
|
|
* Fundamental base class for all physical drivers (I2C, SPI).
|
|
*
|
|
* This class provides the basic driver template for I2C and SPI devices
|
|
*/
|
|
class __EXPORT Device
|
|
{
|
|
public:
|
|
|
|
// no copy, assignment, move, move assignment
|
|
Device(const Device &) = delete;
|
|
Device &operator=(const Device &) = delete;
|
|
Device(Device &&) = delete;
|
|
Device &operator=(Device &&) = delete;
|
|
|
|
/**
|
|
* Destructor.
|
|
*
|
|
* Public so that anonymous devices can be destroyed.
|
|
*/
|
|
virtual ~Device() = default;
|
|
|
|
/*
|
|
* Direct access methods.
|
|
*/
|
|
|
|
/**
|
|
* Initialise the driver and make it ready for use.
|
|
*
|
|
* @return OK if the driver initialized OK, negative errno otherwise;
|
|
*/
|
|
virtual int init() { return PX4_OK; }
|
|
|
|
/**
|
|
* Read directly from the device.
|
|
*
|
|
* The actual size of each unit quantity is device-specific.
|
|
*
|
|
* @param offset The device address at which to start reading
|
|
* @param data The buffer into which the read values should be placed.
|
|
* @param count The number of items to read.
|
|
* @return The number of items read on success, negative errno otherwise.
|
|
*/
|
|
virtual int read(unsigned address, void *data, unsigned count) { return -ENODEV; }
|
|
|
|
/**
|
|
* Write directly to the device.
|
|
*
|
|
* The actual size of each unit quantity is device-specific.
|
|
*
|
|
* @param address The device address at which to start writing.
|
|
* @param data The buffer from which values should be read.
|
|
* @param count The number of items to write.
|
|
* @return The number of items written on success, negative errno otherwise.
|
|
*/
|
|
virtual int write(unsigned address, void *data, unsigned count) { return -ENODEV; }
|
|
|
|
/**
|
|
* Read a register from the device.
|
|
*
|
|
* @param The register to read.
|
|
* @return The value that was read.
|
|
*/
|
|
virtual uint8_t read_reg(unsigned reg) { return -ENODEV; }
|
|
|
|
/**
|
|
* Write a register in the device.
|
|
*
|
|
* @param reg The register to write.
|
|
* @param value The new value to write.
|
|
* @return OK on success, negative errno otherwise.
|
|
*/
|
|
virtual int write_reg(unsigned reg, uint8_t value) { return -ENODEV; }
|
|
|
|
/**
|
|
* Perform a device-specific operation.
|
|
*
|
|
* @param operation The operation to perform.
|
|
* @param arg An argument to the operation.
|
|
* @return Negative errno on error, OK or positive value on success.
|
|
*/
|
|
virtual int ioctl(unsigned operation, unsigned &arg) { return -ENODEV; }
|
|
|
|
/** Device bus types for DEVID */
|
|
enum DeviceBusType {
|
|
DeviceBusType_UNKNOWN = 0,
|
|
DeviceBusType_I2C = 1,
|
|
DeviceBusType_SPI = 2,
|
|
DeviceBusType_UAVCAN = 3,
|
|
DeviceBusType_SIMULATION = 4,
|
|
DeviceBusType_SERIAL = 5,
|
|
DeviceBusType_MAVLINK = 6,
|
|
};
|
|
|
|
/*
|
|
broken out device elements. The bitfields are used to keep
|
|
the overall value small enough to fit in a float accurately,
|
|
which makes it possible to transport over the MAVLink
|
|
parameter protocol without loss of information.
|
|
*/
|
|
struct DeviceStructure {
|
|
DeviceBusType bus_type : 3;
|
|
uint8_t bus: 5; // which instance of the bus type
|
|
uint8_t address; // address on the bus (eg. I2C address)
|
|
uint8_t devtype; // device class specific device type
|
|
};
|
|
|
|
union DeviceId {
|
|
struct DeviceStructure devid_s;
|
|
uint32_t devid;
|
|
};
|
|
|
|
uint32_t get_device_id() const { return _device_id.devid; }
|
|
|
|
/**
|
|
* Return the bus type the device is connected to.
|
|
*
|
|
* @return The bus type
|
|
*/
|
|
DeviceBusType get_device_bus_type() const { return _device_id.devid_s.bus_type; }
|
|
void set_device_bus_type(DeviceBusType bus_type) { _device_id.devid_s.bus_type = bus_type; }
|
|
|
|
static const char *get_device_bus_string(DeviceBusType bus)
|
|
{
|
|
switch (bus) {
|
|
case DeviceBusType_I2C:
|
|
return "I2C";
|
|
|
|
case DeviceBusType_SPI:
|
|
return "SPI";
|
|
|
|
case DeviceBusType_UAVCAN:
|
|
return "UAVCAN";
|
|
|
|
case DeviceBusType_SIMULATION:
|
|
return "SIMULATION";
|
|
|
|
case DeviceBusType_SERIAL:
|
|
return "SERIAL";
|
|
|
|
case DeviceBusType_MAVLINK:
|
|
return "MAVLINK";
|
|
|
|
case DeviceBusType_UNKNOWN:
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the bus ID the device is connected to.
|
|
*
|
|
* @return The bus ID
|
|
*/
|
|
uint8_t get_device_bus() const { return _device_id.devid_s.bus; }
|
|
void set_device_bus(uint8_t bus) { _device_id.devid_s.bus = bus; }
|
|
|
|
/**
|
|
* Return the bus address of the device.
|
|
*
|
|
* @return The bus address
|
|
*/
|
|
uint8_t get_device_address() const { return _device_id.devid_s.address; }
|
|
void set_device_address(int address) { _device_id.devid_s.address = address; }
|
|
|
|
/**
|
|
* Return the device type
|
|
*
|
|
* @return The device type
|
|
*/
|
|
uint8_t get_device_type() const { return _device_id.devid_s.devtype; }
|
|
void set_device_type(uint8_t devtype) { _device_id.devid_s.devtype = devtype; }
|
|
|
|
/**
|
|
* Print decoded device id string to a buffer.
|
|
*
|
|
* @param buffer buffer to write to
|
|
* @param length buffer length
|
|
* @param id The device id.
|
|
* @param return number of bytes written
|
|
*/
|
|
static int device_id_print_buffer(char *buffer, int length, uint32_t id)
|
|
{
|
|
DeviceId dev_id{};
|
|
dev_id.devid = id;
|
|
|
|
int num_written = snprintf(buffer, length, "Type: 0x%02X, %s:%d (0x%02X)", dev_id.devid_s.devtype,
|
|
get_device_bus_string(dev_id.devid_s.bus_type), dev_id.devid_s.bus, dev_id.devid_s.address);
|
|
|
|
buffer[length - 1] = 0; // ensure 0-termination
|
|
|
|
return num_written;
|
|
}
|
|
|
|
virtual bool external() const { return false; }
|
|
|
|
protected:
|
|
union DeviceId _device_id {}; /**< device identifier information */
|
|
|
|
const char *_name{nullptr}; /**< driver name */
|
|
bool _debug_enabled{false}; /**< if true, debug messages are printed */
|
|
|
|
Device() = delete;
|
|
explicit Device(const char *name) : _name(name) {}
|
|
|
|
Device(uint8_t devtype, const char *name, DeviceBusType bus_type, uint8_t bus, uint8_t address) : _name(name)
|
|
{
|
|
set_device_type(devtype);
|
|
_device_id.devid_s.bus_type = bus_type;
|
|
_device_id.devid_s.bus = bus;
|
|
set_device_address(address);
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace device
|
|
|
|
#endif /* _DEVICE_DEVICE_HPP */
|