diff --git a/boards/atlflight/eagle/qurt-default.cmake b/boards/atlflight/eagle/qurt-default.cmake index 49440e4bbf..c9983d7db4 100644 --- a/boards/atlflight/eagle/qurt-default.cmake +++ b/boards/atlflight/eagle/qurt-default.cmake @@ -45,6 +45,7 @@ px4_add_board( LABEL qurt-default DRIVERS + barometer/bmp280 gps imu/mpu9250 spektrum_rc diff --git a/boards/atlflight/excelsior/qurt-default.cmake b/boards/atlflight/excelsior/qurt-default.cmake index 25bc791c79..9f0da0588e 100644 --- a/boards/atlflight/excelsior/qurt-default.cmake +++ b/boards/atlflight/excelsior/qurt-default.cmake @@ -45,6 +45,7 @@ px4_add_board( LABEL qurt-default DRIVERS + barometer/bmp280 gps imu/mpu9250 spektrum_rc diff --git a/boards/beaglebone/blue/cross.cmake b/boards/beaglebone/blue/cross.cmake index 6aa1b5dd90..70b78f2b30 100644 --- a/boards/beaglebone/blue/cross.cmake +++ b/boards/beaglebone/blue/cross.cmake @@ -10,6 +10,7 @@ px4_add_board( DRIVERS #barometer # all available barometer drivers + barometer/bmp280 batt_smbus camera_trigger differential_pressure # all available differential pressure drivers diff --git a/boards/beaglebone/blue/native.cmake b/boards/beaglebone/blue/native.cmake index ec4895ce65..d2f767b8f8 100644 --- a/boards/beaglebone/blue/native.cmake +++ b/boards/beaglebone/blue/native.cmake @@ -8,6 +8,7 @@ px4_add_board( DRIVERS #barometer # all available barometer drivers + barometer/bmp280 batt_smbus camera_trigger differential_pressure # all available differential pressure drivers diff --git a/src/drivers/barometer/bmp280/BMP280.hpp b/src/drivers/barometer/bmp280/BMP280.hpp new file mode 100644 index 0000000000..d7a68c4f35 --- /dev/null +++ b/src/drivers/barometer/bmp280/BMP280.hpp @@ -0,0 +1,95 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2016 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. + * + ****************************************************************************/ + +#pragma once + +#include "bmp280.h" + +/* + * BMP280 internal constants and data structures. + */ + +class BMP280 : public cdev::CDev, public px4::ScheduledWorkItem +{ +public: + BMP280(bmp280::IBMP280 *interface, const char *path); + virtual ~BMP280(); + + virtual int init(); + + virtual ssize_t read(cdev::file_t *filp, char *buffer, size_t buflen); + virtual int ioctl(cdev::file_t *filp, int cmd, unsigned long arg); + + /** + * Diagnostics - print some basic information about the driver. + */ + void print_info(); + +private: + bmp280::IBMP280 *_interface; + + bool _running; + + uint8_t _curr_ctrl; + + unsigned _report_interval; // 0 - no cycling, otherwise period of sending a report + unsigned _max_measure_interval; // interval in microseconds needed to measure + + ringbuffer::RingBuffer *_reports; + + bool _collect_phase; + + orb_advert_t _baro_topic; + int _orb_class_instance; + int _class_instance; + + perf_counter_t _sample_perf; + perf_counter_t _measure_perf; + perf_counter_t _comms_errors; + + struct bmp280::calibration_s *_cal; //stored calibration constants + struct bmp280::fcalibration_s _fcal; //pre processed calibration constants + + float _P; /* in Pa */ + float _T; /* in K */ + + + /* periodic execution helpers */ + void start_cycle(); + void stop_cycle(); + + void Run() override; + + int measure(); //start measure + int collect(); //get results and publish +}; diff --git a/src/drivers/barometer/bmp280/CMakeLists.txt b/src/drivers/barometer/bmp280/CMakeLists.txt index 27ee0e615b..72770b31ef 100644 --- a/src/drivers/barometer/bmp280/CMakeLists.txt +++ b/src/drivers/barometer/bmp280/CMakeLists.txt @@ -37,9 +37,11 @@ px4_add_module( COMPILE_FLAGS -Wno-cast-align # TODO: fix and enable SRCS + BMP280.hpp bmp280_spi.cpp bmp280_i2c.cpp bmp280.cpp + bmp280_main.cpp DEPENDS px4_work_queue ) diff --git a/src/drivers/barometer/bmp280/bmp280.cpp b/src/drivers/barometer/bmp280/bmp280.cpp index 5b7cd12df4..b6279bfbd2 100644 --- a/src/drivers/barometer/bmp280/bmp280.cpp +++ b/src/drivers/barometer/bmp280/bmp280.cpp @@ -31,84 +31,7 @@ * ****************************************************************************/ -/** - * @file bmp280.cpp - * Driver for the BMP280 barometric pressure sensor connected via I2C TODO or SPI. - */ - -#include "bmp280.h" - -enum BMP280_BUS { - BMP280_BUS_ALL = 0, - BMP280_BUS_I2C_INTERNAL, - BMP280_BUS_I2C_EXTERNAL, - BMP280_BUS_SPI_INTERNAL, - BMP280_BUS_SPI_EXTERNAL -}; - -/* - * BMP280 internal constants and data structures. - */ - -class BMP280 : public cdev::CDev, public px4::ScheduledWorkItem -{ -public: - BMP280(bmp280::IBMP280 *interface, const char *path); - virtual ~BMP280(); - - virtual int init(); - - virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); - virtual int ioctl(struct file *filp, int cmd, unsigned long arg); - - /** - * Diagnostics - print some basic information about the driver. - */ - void print_info(); - -private: - bmp280::IBMP280 *_interface; - - bool _running; - - uint8_t _curr_ctrl; - - unsigned _report_interval; // 0 - no cycling, otherwise period of sending a report - unsigned _max_measure_interval; // interval in microseconds needed to measure - - ringbuffer::RingBuffer *_reports; - - bool _collect_phase; - - orb_advert_t _baro_topic; - int _orb_class_instance; - int _class_instance; - - perf_counter_t _sample_perf; - perf_counter_t _measure_perf; - perf_counter_t _comms_errors; - - struct bmp280::calibration_s *_cal; //stored calibration constants - struct bmp280::fcalibration_s _fcal; //pre processed calibration constants - - float _P; /* in Pa */ - float _T; /* in K */ - - - /* periodic execution helpers */ - void start_cycle(); - void stop_cycle(); - - void Run() override; - - int measure(); //start measure - int collect(); //get results and publish -}; - -/* - * Driver 'main' command. - */ -extern "C" __EXPORT int bmp280_main(int argc, char *argv[]); +#include "BMP280.hpp" BMP280::BMP280(bmp280::IBMP280 *interface, const char *path) : CDev(path), @@ -239,7 +162,7 @@ BMP280::init() } ssize_t -BMP280::read(struct file *filp, char *buffer, size_t buflen) +BMP280::read(cdev::file_t *filp, char *buffer, size_t buflen) { unsigned count = buflen / sizeof(sensor_baro_s); sensor_baro_s *brp = reinterpret_cast(buffer); @@ -291,7 +214,7 @@ BMP280::read(struct file *filp, char *buffer, size_t buflen) } int -BMP280::ioctl(struct file *filp, int cmd, unsigned long arg) +BMP280::ioctl(cdev::file_t *filp, int cmd, unsigned long arg) { switch (cmd) { @@ -310,7 +233,7 @@ BMP280::ioctl(struct file *filp, int cmd, unsigned long arg) /* FALLTHROUGH */ default: { if (interval == 0) { - interval = (USEC_PER_SEC / arg); + interval = (1000000 / arg); } /* do we need to start internal polling? */ @@ -478,345 +401,3 @@ BMP280::print_info() _reports->get(&brp); print_message(brp); } - -/** - * Local functions in support of the shell command. - */ -namespace bmp280 -{ - -/* - list of supported bus configurations - */ -struct bmp280_bus_option { - enum BMP280_BUS busid; - const char *devpath; - BMP280_constructor interface_constructor; - uint8_t busnum; - uint32_t device; - bool external; - BMP280 *dev; -} bus_options[] = { -#if defined(PX4_SPIDEV_EXT_BARO) && defined(PX4_SPI_BUS_EXT) - { BMP280_BUS_SPI_EXTERNAL, "/dev/bmp280_spi_ext", &bmp280_spi_interface, PX4_SPI_BUS_EXT, PX4_SPIDEV_EXT_BARO, true, NULL }, -#endif -#if defined(PX4_SPIDEV_BARO) -# if defined(PX4_SPIDEV_BARO_BUS) - { BMP280_BUS_SPI_INTERNAL, "/dev/bmp280_spi_int", &bmp280_spi_interface, PX4_SPIDEV_BARO_BUS, PX4_SPIDEV_BARO, false, NULL }, -# else - { BMP280_BUS_SPI_INTERNAL, "/dev/bmp280_spi_int", &bmp280_spi_interface, PX4_SPI_BUS_SENSORS, PX4_SPIDEV_BARO, false, NULL }, -# endif -#endif -#if defined(PX4_I2C_BUS_ONBOARD) && defined(PX4_I2C_OBDEV_BMP280) - { BMP280_BUS_I2C_INTERNAL, "/dev/bmp280_i2c_int", &bmp280_i2c_interface, PX4_I2C_BUS_ONBOARD, PX4_I2C_OBDEV_BMP280, false, NULL }, -#endif -#if defined(PX4_I2C_BUS_EXPANSION) && defined(PX4_I2C_OBDEV_BMP280) - { BMP280_BUS_I2C_EXTERNAL, "/dev/bmp280_i2c_ext", &bmp280_i2c_interface, PX4_I2C_BUS_EXPANSION, PX4_I2C_OBDEV_BMP280, true, NULL }, -#endif -}; -#define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0])) - -bool start_bus(struct bmp280_bus_option &bus); -struct bmp280_bus_option &find_bus(enum BMP280_BUS busid); -void start(enum BMP280_BUS busid); -void test(enum BMP280_BUS busid); -void reset(enum BMP280_BUS busid); -void info(); -void usage(); - - -/** - * Start the driver. - */ -bool -start_bus(struct bmp280_bus_option &bus) -{ - if (bus.dev != nullptr) { - PX4_ERR("bus option already started"); - exit(1); - } - - bmp280::IBMP280 *interface = bus.interface_constructor(bus.busnum, bus.device, bus.external); - - if (interface->init() != OK) { - delete interface; - PX4_WARN("no device on bus %u", (unsigned)bus.busid); - return false; - } - - bus.dev = new BMP280(interface, bus.devpath); - - if (bus.dev == nullptr) { - return false; - } - - if (OK != bus.dev->init()) { - delete bus.dev; - bus.dev = nullptr; - return false; - } - - int fd = open(bus.devpath, O_RDONLY); - - /* set the poll rate to default, starts automatic data collection */ - if (fd == -1) { - PX4_ERR("can't open baro device"); - exit(1); - } - - if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) { - close(fd); - PX4_ERR("failed setting default poll rate"); - exit(1); - } - - close(fd); - return true; -} - - -/** - * Start the driver. - * - * This function call only returns once the driver - * is either successfully up and running or failed to start. - */ -void -start(enum BMP280_BUS busid) -{ - uint8_t i; - bool started = false; - - for (i = 0; i < NUM_BUS_OPTIONS; i++) { - if (busid == BMP280_BUS_ALL && bus_options[i].dev != NULL) { - // this device is already started - continue; - } - - if (busid != BMP280_BUS_ALL && bus_options[i].busid != busid) { - // not the one that is asked for - continue; - } - - started |= start_bus(bus_options[i]); - } - - if (!started) { - PX4_WARN("bus option number is %d", i); - PX4_ERR("driver start failed"); - exit(1); - } - - // one or more drivers started OK - exit(0); -} - - -/** - * find a bus structure for a busid - */ -struct bmp280_bus_option &find_bus(enum BMP280_BUS busid) -{ - for (uint8_t i = 0; i < NUM_BUS_OPTIONS; i++) { - if ((busid == BMP280_BUS_ALL || - busid == bus_options[i].busid) && bus_options[i].dev != NULL) { - return bus_options[i]; - } - } - - PX4_ERR("bus %u not started", (unsigned)busid); - exit(1); -} - -/** - * Perform some basic functional tests on the driver; - * make sure we can collect data from the sensor in polled - * and automatic modes. - */ -void -test(enum BMP280_BUS busid) -{ - struct bmp280_bus_option &bus = find_bus(busid); - sensor_baro_s report; - ssize_t sz; - int ret; - - int fd; - - fd = open(bus.devpath, O_RDONLY); - - if (fd < 0) { - PX4_ERR("open failed (try 'bmp280 start' if the driver is not running)"); - exit(1); - } - - /* do a simple demand read */ - sz = read(fd, &report, sizeof(report)); - - if (sz != sizeof(report)) { - PX4_ERR("immediate read failed"); - exit(1); - } - - print_message(report); - - /* read the sensor 5x and report each value */ - for (unsigned i = 0; i < 5; i++) { - struct pollfd fds; - - /* wait for data to be ready */ - fds.fd = fd; - fds.events = POLLIN; - ret = poll(&fds, 1, 2000); - - if (ret != 1) { - PX4_ERR("timed out waiting for sensor data"); - exit(1); - } - - /* now go get it */ - sz = read(fd, &report, sizeof(report)); - - if (sz != sizeof(report)) { - PX4_ERR("periodic read failed"); - exit(1); - } - - print_message(report); - } - - close(fd); - PX4_ERR("PASS"); - exit(0); -} - -/** - * Reset the driver. - */ -void -reset(enum BMP280_BUS busid) -{ - struct bmp280_bus_option &bus = find_bus(busid); - int fd; - - fd = open(bus.devpath, O_RDONLY); - - if (fd < 0) { - PX4_ERR("failed "); - exit(1); - } - - if (ioctl(fd, SENSORIOCRESET, 0) < 0) { - PX4_ERR("driver reset failed"); - exit(1); - } - - if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) { - PX4_ERR("driver poll restart failed"); - exit(1); - } - - exit(0); -} - -/** - * Print a little info about the driver. - */ -void -info() -{ - for (uint8_t i = 0; i < NUM_BUS_OPTIONS; i++) { - struct bmp280_bus_option &bus = bus_options[i]; - - if (bus.dev != nullptr) { - PX4_WARN("%s", bus.devpath); - bus.dev->print_info(); - } - } - - exit(0); -} - -void -usage() -{ - PX4_WARN("missing command: try 'start', 'info', 'test', 'test2', 'reset'"); - PX4_WARN("options:"); - PX4_WARN(" -X (external I2C bus TODO)"); - PX4_WARN(" -I (internal I2C bus TODO)"); - PX4_WARN(" -S (external SPI bus)"); - PX4_WARN(" -s (internal SPI bus)"); -} - -} // namespace - -int -bmp280_main(int argc, char *argv[]) -{ - int myoptind = 1; - int ch; - const char *myoptarg = nullptr; - enum BMP280_BUS busid = BMP280_BUS_ALL; - - while ((ch = px4_getopt(argc, argv, "XISs", &myoptind, &myoptarg)) != EOF) { - switch (ch) { - case 'X': - busid = BMP280_BUS_I2C_EXTERNAL; - break; - - case 'I': - busid = BMP280_BUS_I2C_INTERNAL; - break; - - case 'S': - busid = BMP280_BUS_SPI_EXTERNAL; - break; - - case 's': - busid = BMP280_BUS_SPI_INTERNAL; - break; - - default: - bmp280::usage(); - return 0; - } - } - - if (myoptind >= argc) { - bmp280::usage(); - return -1; - } - - const char *verb = argv[myoptind]; - - /* - * Start/load the driver. - */ - if (!strcmp(verb, "start")) { - bmp280::start(busid); - } - - /* - * Test the driver/device. - */ - if (!strcmp(verb, "test")) { - bmp280::test(busid); - } - - /* - * Reset the driver. - */ - if (!strcmp(verb, "reset")) { - bmp280::reset(busid); - } - - /* - * Print driver information. - */ - if (!strcmp(verb, "info")) { - bmp280::info(); - } - - PX4_ERR("unrecognized command, try 'start', 'test', 'reset' or 'info'"); - return -1; -} diff --git a/src/drivers/barometer/bmp280/bmp280_main.cpp b/src/drivers/barometer/bmp280/bmp280_main.cpp new file mode 100644 index 0000000000..ac6395d0dc --- /dev/null +++ b/src/drivers/barometer/bmp280/bmp280_main.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** + * + * Copyright (c) 2012-2016 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 bmp280.cpp + * Driver for the BMP280 barometric pressure sensor connected via I2C TODO or SPI. + */ + +#include "BMP280.hpp" + +enum BMP280_BUS { + BMP280_BUS_ALL = 0, + BMP280_BUS_I2C_INTERNAL, + BMP280_BUS_I2C_EXTERNAL, + BMP280_BUS_SPI_INTERNAL, + BMP280_BUS_SPI_EXTERNAL +}; + +/* + * Driver 'main' command. + */ +extern "C" __EXPORT int bmp280_main(int argc, char *argv[]); + +/** + * Local functions in support of the shell command. + */ +namespace bmp280 +{ + +/* + list of supported bus configurations + */ +struct bmp280_bus_option { + enum BMP280_BUS busid; + const char *devpath; + BMP280_constructor interface_constructor; + uint8_t busnum; + uint32_t device; + bool external; + BMP280 *dev; +} bus_options[] = { +#if defined(PX4_SPIDEV_EXT_BARO) && defined(PX4_SPI_BUS_EXT) + { BMP280_BUS_SPI_EXTERNAL, "/dev/bmp280_spi_ext", &bmp280_spi_interface, PX4_SPI_BUS_EXT, PX4_SPIDEV_EXT_BARO, true, NULL }, +#endif +#if defined(PX4_SPIDEV_BARO) +# if defined(PX4_SPIDEV_BARO_BUS) + { BMP280_BUS_SPI_INTERNAL, "/dev/bmp280_spi_int", &bmp280_spi_interface, PX4_SPIDEV_BARO_BUS, PX4_SPIDEV_BARO, false, NULL }, +# else + { BMP280_BUS_SPI_INTERNAL, "/dev/bmp280_spi_int", &bmp280_spi_interface, PX4_SPI_BUS_SENSORS, PX4_SPIDEV_BARO, false, NULL }, +# endif +#endif +#if defined(PX4_I2C_BUS_ONBOARD) && defined(PX4_I2C_OBDEV_BMP280) + { BMP280_BUS_I2C_INTERNAL, "/dev/bmp280_i2c_int", &bmp280_i2c_interface, PX4_I2C_BUS_ONBOARD, PX4_I2C_OBDEV_BMP280, false, NULL }, +#endif +#if defined(PX4_I2C_BUS_EXPANSION) && defined(PX4_I2C_OBDEV_BMP280) + { BMP280_BUS_I2C_EXTERNAL, "/dev/bmp280_i2c_ext", &bmp280_i2c_interface, PX4_I2C_BUS_EXPANSION, PX4_I2C_OBDEV_BMP280, true, NULL }, +#endif +}; +#define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0])) + +/** + * Start the driver. + */ +static bool +start_bus(struct bmp280_bus_option &bus) +{ + if (bus.dev != nullptr) { + PX4_ERR("bus option already started"); + return false; + } + + bmp280::IBMP280 *interface = bus.interface_constructor(bus.busnum, bus.device, bus.external); + + if (interface->init() != OK) { + delete interface; + PX4_WARN("no device on bus %u", (unsigned)bus.busid); + return false; + } + + bus.dev = new BMP280(interface, bus.devpath); + + if (bus.dev == nullptr) { + return false; + } + + if (OK != bus.dev->init()) { + delete bus.dev; + bus.dev = nullptr; + return false; + } + + int fd = px4_open(bus.devpath, O_RDONLY); + + /* set the poll rate to default, starts automatic data collection */ + if (fd == -1) { + PX4_ERR("can't open baro device"); + return false; + } + + if (px4_ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) { + px4_close(fd); + PX4_ERR("failed setting default poll rate"); + return false; + } + + px4_close(fd); + return true; +} + +/** + * Start the driver. + * + * This function call only returns once the driver + * is either successfully up and running or failed to start. + */ +static int +start(enum BMP280_BUS busid) +{ + uint8_t i; + bool started = false; + + for (i = 0; i < NUM_BUS_OPTIONS; i++) { + if (busid == BMP280_BUS_ALL && bus_options[i].dev != NULL) { + // this device is already started + continue; + } + + if (busid != BMP280_BUS_ALL && bus_options[i].busid != busid) { + // not the one that is asked for + continue; + } + + started |= start_bus(bus_options[i]); + } + + if (!started) { + PX4_WARN("bus option number is %d", i); + PX4_ERR("driver start failed"); + return PX4_ERROR; + } + + // one or more drivers started OK + return PX4_OK; +} + +/** + * Print a little info about the driver. + */ +static int +info() +{ + for (uint8_t i = 0; i < NUM_BUS_OPTIONS; i++) { + struct bmp280_bus_option *bus = &bus_options[i]; + + if (bus != nullptr && bus->dev != nullptr) { + PX4_WARN("%s", bus->devpath); + bus->dev->print_info(); + } + } + + return 0; +} + +static int +usage() +{ + PX4_WARN("missing command: try 'start', 'info'"); + PX4_WARN("options:"); + PX4_WARN(" -X (external I2C bus TODO)"); + PX4_WARN(" -I (internal I2C bus TODO)"); + PX4_WARN(" -S (external SPI bus)"); + PX4_WARN(" -s (internal SPI bus)"); + return 0; +} + +} // namespace + +int +bmp280_main(int argc, char *argv[]) +{ + int myoptind = 1; + int ch; + const char *myoptarg = nullptr; + enum BMP280_BUS busid = BMP280_BUS_ALL; + + while ((ch = px4_getopt(argc, argv, "XISs", &myoptind, &myoptarg)) != EOF) { + switch (ch) { + case 'X': + busid = BMP280_BUS_I2C_EXTERNAL; + break; + + case 'I': + busid = BMP280_BUS_I2C_INTERNAL; + break; + + case 'S': + busid = BMP280_BUS_SPI_EXTERNAL; + break; + + case 's': + busid = BMP280_BUS_SPI_INTERNAL; + break; + + default: + return bmp280::usage(); + } + } + + if (myoptind >= argc) { + return bmp280::usage(); + } + + const char *verb = argv[myoptind]; + + /* + * Start/load the driver. + */ + if (!strcmp(verb, "start")) { + return bmp280::start(busid); + } + + /* + * Print driver information. + */ + if (!strcmp(verb, "info")) { + return bmp280::info(); + } + + return bmp280::usage(); +}