diff --git a/src/drivers/magnetometer/memsic/mmc5983ma/CMakeLists.txt b/src/drivers/magnetometer/memsic/mmc5983ma/CMakeLists.txt index 3bba9619d7..085faacfeb 100644 --- a/src/drivers/magnetometer/memsic/mmc5983ma/CMakeLists.txt +++ b/src/drivers/magnetometer/memsic/mmc5983ma/CMakeLists.txt @@ -36,6 +36,7 @@ px4_add_module( COMPILE_FLAGS SRCS mmc5983ma_i2c.cpp + mmc5983ma_spi.cpp mmc5983ma_main.cpp mmc5983ma.cpp DEPENDS diff --git a/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma.h b/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma.h index afa526dd1a..c29131f125 100644 --- a/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma.h +++ b/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma.h @@ -54,6 +54,7 @@ #define MMC5983MA_CTRL_REG1_SW_RESET (1 << 7) extern device::Device *MMC5983MA_I2C_interface(const I2CSPIDriverConfig &config); +extern device::Device *MMC5983MA_SPI_interface(const I2CSPIDriverConfig &config); class MMC5983MA : public I2CSPIDriver { diff --git a/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_main.cpp b/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_main.cpp index b8d6e81e34..02efb0c039 100644 --- a/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_main.cpp +++ b/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_main.cpp @@ -36,7 +36,14 @@ I2CSPIDriverBase *MMC5983MA::instantiate(const I2CSPIDriverConfig &config, int runtime_instance) { - device::Device *interface = MMC5983MA_I2C_interface(config); + device::Device *interface = nullptr; + + if (config.bus_type == BOARD_I2C_BUS) { + interface = MMC5983MA_I2C_interface(config); + + } else if (config.bus_type == BOARD_SPI_BUS) { + interface = MMC5983MA_SPI_interface(config); + } if (interface == nullptr) { PX4_ERR("alloc failed"); @@ -69,8 +76,9 @@ void MMC5983MA::print_usage() PRINT_MODULE_USAGE_NAME("mmc5983ma", "driver"); PRINT_MODULE_USAGE_SUBCATEGORY("magnetometer"); PRINT_MODULE_USAGE_COMMAND("start"); - PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false); + PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, true); PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x30); + PRINT_MODULE_USAGE_PARAM_INT('R', 0, 0, 35, "Rotation", true); PRINT_MODULE_USAGE_COMMAND("reset"); PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); } @@ -79,9 +87,10 @@ extern "C" int mmc5983ma_main(int argc, char *argv[]) { using ThisDriver = MMC5983MA; int ch; - BusCLIArguments cli{true, false}; + BusCLIArguments cli{true, true}; cli.i2c_address = 0x30; cli.default_i2c_frequency = 400000; + cli.default_spi_frequency = 10 * 1000 * 1000; while ((ch = cli.getOpt(argc, argv, "R:")) != EOF) { switch (ch) { diff --git a/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_spi.cpp b/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_spi.cpp new file mode 100644 index 0000000000..f3587193f5 --- /dev/null +++ b/src/drivers/magnetometer/memsic/mmc5983ma/mmc5983ma_spi.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** + * + * Copyright (c) 2024 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. + * + ****************************************************************************/ + +#include "mmc5983ma.h" +#include + +/* SPI protocol address bits */ +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) +#define ADDR_INCREMENT (1<<6) + + +class MMC5983MA_SPI : public device::SPI +{ +public: + MMC5983MA_SPI(const I2CSPIDriverConfig &config); + virtual ~MMC5983MA_SPI() = default; + + virtual int read(unsigned address, void *data, unsigned count) override; + virtual int write(unsigned address, void *data, unsigned count) override; + +protected: + virtual int probe(); +}; + +MMC5983MA_SPI::MMC5983MA_SPI(const I2CSPIDriverConfig &config) : + SPI(config) +{ +} + +int MMC5983MA_SPI::probe() +{ + uint8_t data = 0; + + if (read(MMC5983MA_ADDR_PRODUCT_ID, &data, 1)) { + DEVICE_DEBUG("read_reg fail"); + return -EIO; + } + + if (data != MMC5983MA_PRODUCT_ID) { + DEVICE_DEBUG("MMC5983MA bad ID: %02x", data); + return -EIO; + } + + return OK; +} + +int MMC5983MA_SPI::read(unsigned address, void *data, unsigned count) +{ + uint8_t buf[32]; + + if (sizeof(buf) < (count + 1)) { + return -EIO; + } + + buf[0] = address | DIR_READ | ADDR_INCREMENT; + int ret = transfer(&buf[0], &buf[0], count + 1); + memcpy(data, &buf[1], count); + return ret; +} + +int MMC5983MA_SPI::write(unsigned address, void *data, unsigned count) +{ + uint8_t buf[32]; + + if (sizeof(buf) < (count + 1)) { + return -EIO; + } + + buf[0] = (uint8_t)(address | DIR_WRITE); + memcpy(&buf[1], data, count); + + return transfer(&buf[0], nullptr, count + 1); +} + +device::Device *MMC5983MA_SPI_interface(const I2CSPIDriverConfig &config) +{ + return new MMC5983MA_SPI(config); +}