From a634ad55286073ebe6214d5ddc8803ec0d2262b5 Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Tue, 11 Aug 2015 10:03:10 -0400 Subject: [PATCH] Added MB7040 sonar. --- drivers/sensors/Kconfig | 7 + drivers/sensors/Make.defs | 4 + drivers/sensors/mb7040.c | 373 +++++++++++++++++++++++++++++++++ include/nuttx/sensors/mb7040.h | 120 +++++++++++ 4 files changed, 504 insertions(+) create mode 100644 drivers/sensors/mb7040.c create mode 100644 include/nuttx/sensors/mb7040.h diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index fbb7118b85..71df93e31d 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -24,6 +24,13 @@ config LIS331DL select I2C select I2C_TRANSFER +config MB7040 + bool "MaxBotix MB7040 Sonar support" + default n + select I2C + ---help--- + Enable driver support for the MaxBotix MB7040 sonar. + config MPL115A bool "Freescale MPL115A Barometer Sensor support" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 0d86e8e9f7..7b1e1952db 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -69,6 +69,10 @@ ifeq ($(CONFIG_LM92),y) CSRCS += lm92.c endif +ifeq ($(CONFIG_MB7040),y) + CSRCS += mb7040.c +endif + endif # CONFIG_I2C # These drivers depend on SPI support diff --git a/drivers/sensors/mb7040.c b/drivers/sensors/mb7040.c new file mode 100644 index 0000000000..16c853421a --- /dev/null +++ b/drivers/sensors/mb7040.c @@ -0,0 +1,373 @@ +/**************************************************************************** + * drivers/sensors/mb7040.c + * Character driver for the MaxBotix MB7040 Sonar + * + * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Author: Paul Alexander Patience + * + * 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 NuttX 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_I2C) && defined(CONFIG_MB7040) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mb7040_dev_s +{ + FAR struct i2c_dev_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* I2C Helpers */ + +static int mb7040_measurerange(FAR struct mb7040_dev_s *priv); +static int mb7040_readrange(FAR struct mb7040_dev_s *priv, + FAR uint16_t *range); +static int mb7040_changeaddr(FAR struct mb7040_dev_s *priv, uint8_t addr); + +/* Character Driver Methods */ + +static int mb7040_open(FAR struct file *filep); +static int mb7040_close(FAR struct file *filep); +static ssize_t mb7040_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t mb7040_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int mb7040_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_fops = +{ + mb7040_open, + mb7040_close, + mb7040_read, + mb7040_write, + NULL, + mb7040_ioctl +#ifndef CONFIG_DISABLE_POLL + , NULL +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mb7040_measurerange + * + * Description: + * Command the device to measure the range. + * + ****************************************************************************/ + +static int mb7040_measurerange(FAR struct mb7040_dev_s *priv) +{ + uint8_t regaddr; + int ret; + + regaddr = MB7040_RANGE_REG; + sndbg("addr: %02x\n", regaddr); + + /* Write the register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_WRITE(priv->i2c, ®addr, sizeof(regaddr)); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + } + + return ret; +} + +/**************************************************************************** + * Name: mb7040_readrange + * + * Description: + * Read the range last measured by the device. The units are centimeters. + * + ****************************************************************************/ + +static int mb7040_readrange(FAR struct mb7040_dev_s *priv, + FAR uint16_t *range) +{ + uint8_t buffer[2]; + int ret; + + /* Read two bytes */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_READ(priv->i2c, buffer, sizeof(buffer)); + if (ret < 0) + { + sndbg("I2C_READ failed: %d\n", ret); + return ret; + } + + *range = (uint16_t)buffer[0] << 8 | (uint16_t)buffer[1]; + sndbg("range: %04x ret: %d\n", *range, ret); + return ret; +} + +/**************************************************************************** + * Name: mb7040_changeaddr + * + * Description: + * Change the device's I2C address. + * + ****************************************************************************/ + +static int mb7040_changeaddr(FAR struct mb7040_dev_s *priv, uint8_t addr) +{ + uint8_t buffer[3]; + int ret; + + sndbg("new addr: %02x\n", addr); + + /* Sanity check */ + + DEBUGASSERT((addr & 1) == 0); + DEBUGASSERT(addr != 0x00 && addr != 0x50 && addr != 0xa4 && addr != 0xaa); + + /* Set up a 3-byte message to send */ + + buffer[0] = MB7040_ADDRUNLOCK1_REG; + buffer[1] = MB7040_ADDRUNLOCK2_REG; + buffer[2] = addr; + + /* Write the register address followed by the data (no RESTART) */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_WRITE(priv->i2c, buffer, sizeof(buffer)); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + priv->addr = addr; + return ret; +} + +/**************************************************************************** + * Name: mb7040_open + * + * Description: + * This method is called when the device is opened. + * + ****************************************************************************/ + +static int mb7040_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: mb7040_close + * + * Description: + * This method is called when the device is closed. + * + ****************************************************************************/ + +static int mb7040_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: mb7040_read + * + * Description: + * A dummy read method. + * + ****************************************************************************/ + +static ssize_t mb7040_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + return 0; +} + +/**************************************************************************** + * Name: mb7040_write + * + * Description: + * A dummy write method. + * + ****************************************************************************/ + +static ssize_t mb7040_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: mb7040_ioctl + * + * Description: + * The standard ioctl method. + * + ****************************************************************************/ + +static int mb7040_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct mb7040_dev_s *priv = inode->i_private; + int ret = OK; + + /* Handle ioctl commands */ + + switch (cmd) + { + /* Command the device to measure the range. Arg: None. */ + + case SNIOC_MEASURE: + DEBUGASSERT(arg == 0); + ret = mb7040_measurerange(priv); + break; + + /* Read the range last measured by the device. Arg: int32_t* pointer. */ + + case SNIOC_RANGE: + { + FAR int32_t *ptr = (FAR int32_t *)((uintptr_t)arg); + uint16_t range = 0; + DEBUGASSERT(ptr != NULL); + ret = mb7040_readrange(priv, &range); + if (ret == OK) + { + *ptr = (int32_t)range; + } + sndbg("range: %04x ret: %d\n", *ptr, ret); + } + break; + + /* Change the device's I2C address. Arg: uint8_t value. */ + + case SNIOC_CHANGEADDR: + ret = mb7040_changeaddr(priv, (uint8_t)arg); + sndbg("new addr: %02x ret: %d\n", *(uint8_t *)arg, ret); + break; + + /* Unrecognized commands */ + + default: + sndbg("Unrecognized cmd: %d arg: %ld\n", cmd, arg); + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mb7040_register + * + * Description: + * Register the MB7040 character device as 'devpath'. + * + * Input Parameters: + * devpath - The full path to the driver to register, e.g., "/dev/sonar0". + * i2c - An I2C driver instance. + * addr - The I2C address of the MB7040. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int mb7040_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr) +{ + FAR struct mb7040_dev_s *priv; + int ret; + + /* Sanity check */ + + DEBUGASSERT(i2c != NULL); + + /* Initialize the device's structure */ + + priv = (FAR struct mb7040_dev_s *)kmm_malloc(sizeof(*priv)); + if (priv == NULL) + { + sndbg("Failed to allocate instance\n"); + return -ENOMEM; + } + + priv->i2c = i2c; + priv->addr = addr; + + /* Register the character driver */ + + ret = register_driver(devpath, &g_fops, 0666, priv); + if (ret < 0) + { + sndbg("Failed to register driver: %d\n", ret); + kmm_free(priv); + } + + return ret; +} + +#endif /* CONFIG_I2C && CONFIG_MB7040 */ diff --git a/include/nuttx/sensors/mb7040.h b/include/nuttx/sensors/mb7040.h new file mode 100644 index 0000000000..f3359ea1f3 --- /dev/null +++ b/include/nuttx/sensors/mb7040.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * include/nuttx/sensors/mb7040.h + * + * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Author: Paul Alexander Patience + * + * 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 NuttX 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SENSORS_MB7040 +#define __INCLUDE_NUTTX_SENSORS_MB7040 + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#if defined(CONFIG_I2C) && defined(CONFIG_MB7040) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************ + * Prerequisites: + * + * CONFIG_I2C + * Enables support for I2C drivers + * CONFIG_MB7040 + * Enables support for the MB7040 driver + */ + +/* IOCTL Commands ***********************************************************/ + +#define SNIOC_MEASURE _SNIOC(0x0001) /* Arg: None */ +#define SNIOC_RANGE _SNIOC(0x0002) /* Arg: int32_t* pointer */ +#define SNIOC_CHANGEADDR _SNIOC(0x0003) /* Arg: uint8_t value */ + +/* I2C Addresses ************************************************************/ + +#define MB7040_DEFAULTADDR 0x70 /* Default I2C Address */ + +/* Register Definitions *****************************************************/ +/* Register Addresses */ + +#define MB7040_RANGE_REG 0x51 +#define MB7040_ADDRUNLOCK1_REG 0xaa +#define MB7040_ADDRUNLOCK2_REG 0xa5 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct i2c_dev_s; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mb7040_register + * + * Description: + * Register the MB7040 character device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register, e.g., "/dev/sonar0". + * i2c - An I2C driver instance. + * addr - The I2C address of the MB7040. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int mb7040_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_I2C && CONFIG_MB7040 */ +#endif /* __INCLUDE_NUTTX_SENSORS_MB7040 */