diff --git a/configs/nucleo-l432kc/include/board.h b/configs/nucleo-l432kc/include/board.h index 5f5b8fa4fd0..959cfd0c956 100644 --- a/configs/nucleo-l432kc/include/board.h +++ b/configs/nucleo-l432kc/include/board.h @@ -1,7 +1,7 @@ /************************************************************************************ * configs/nucleo-l432kc/include/board.h * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2016, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -104,16 +104,22 @@ /* I2C * * On Arduino the I2C bus is available at positions A4 and A5. On the - * nulceo-1432kc board the I2C bus pins (PB6 and PB7) are connected to - * pins A4 and A5 through the SB16 and SB18 solder bridges. In this case - * the pins PA5 and PA6 must be configured as input floating. + * nucleo-1432kc board the I2C bus pins (PB6 and PB7) are connected to + * pins A4 and A5 through the SB16 and SB18 solder bridges. + * + * If these solder bridges are open, then Arduino D4(PA5) and D5(PA6) + * pins are not supported. PA5 and PA6 must be configured as input + * floating. * * The optional _GPIO configurations allow the I2C driver to manually * reset the bus to clear stuck slaves. They match the pin configuration, * but are normally-high GPIOs. - * */ +#define GPIO_I2C1_D4 \ + (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTA | GPIO_PIN5) +#define GPIO_I2C1_D5 \ + (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTA | GPIO_PIN6) #define GPIO_I2C1_SCL \ (GPIO_I2C1_SCL_1 | GPIO_OPENDRAIN | GPIO_SPEED_50MHz | GPIO_OUTPUT_SET) #define GPIO_I2C1_SDA \ @@ -127,7 +133,7 @@ /* SPI */ -/* SPI1 is available on the arduino protocol at positions D11/12/13 */ +/* SPI1 is available on the Arduino protocol at positions D11/12/13 */ #define GPIO_SPI1_MISO GPIO_SPI1_MISO_1 /*PA6*/ #define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1 /*PA7*/ diff --git a/configs/nucleo-l432kc/src/Makefile b/configs/nucleo-l432kc/src/Makefile index 35d3560ee78..e30917d8503 100644 --- a/configs/nucleo-l432kc/src/Makefile +++ b/configs/nucleo-l432kc/src/Makefile @@ -52,6 +52,10 @@ ifeq ($(CONFIG_ADC),y) CSRCS += stm32_adc.c endif +ifeq ($(CONFIG_DAC7571),y) +CSRCS += stm32_dac7571.c +endif + ifeq ($(CONFIG_SENSORS_QENCODER),y) CSRCS += stm32_qencoder.c endif diff --git a/configs/nucleo-l432kc/src/nucleo-l432kc.h b/configs/nucleo-l432kc/src/nucleo-l432kc.h index 88fa92c7a8e..e77a79c6e35 100644 --- a/configs/nucleo-l432kc/src/nucleo-l432kc.h +++ b/configs/nucleo-l432kc/src/nucleo-l432kc.h @@ -144,6 +144,18 @@ int stm32l4_pwm_setup(void); int stm32l4_adc_setup(void); #endif +/************************************************************************************ + * Name: stm32_dac7571initialize + * + * Description: + * Initialize and register the DAC7571 driver. + * + ************************************************************************************/ + +#ifdef CONFIG_DAC7571 +int stm32_dac7571initialize(FAR const char *devpath); +#endif + /**************************************************************************** * Name: board_timer_driver_initialize * diff --git a/configs/nucleo-l432kc/src/stm32_appinit.c b/configs/nucleo-l432kc/src/stm32_appinit.c index 0532f1fbbe0..fe4e274aab3 100644 --- a/configs/nucleo-l432kc/src/stm32_appinit.c +++ b/configs/nucleo-l432kc/src/stm32_appinit.c @@ -1,7 +1,7 @@ /**************************************************************************** * configs/nucleo-l432kc/src/stm32l4_appinit.c * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2016, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -190,6 +190,16 @@ int board_app_initialize(uintptr_t arg) } #endif +#ifdef CONFIG_DAC7571 + /* Initialize and register DAC7571 */ + + ret = stm32_dac7571initialize("/dev/dac0"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_dac7571initialize() failed: %d\n", ret); + } +#endif + #ifdef CONFIG_TIMER /* Initialize and register the timer driver */ @@ -204,7 +214,6 @@ int board_app_initialize(uintptr_t arg) #endif #ifdef CONFIG_SENSORS_QENCODER - /* Initialize and register the qencoder driver */ index = 0; diff --git a/configs/nucleo-l432kc/src/stm32_dac7571.c b/configs/nucleo-l432kc/src/stm32_dac7571.c new file mode 100644 index 00000000000..2eb48366e88 --- /dev/null +++ b/configs/nucleo-l432kc/src/stm32_dac7571.c @@ -0,0 +1,129 @@ +/************************************************************************************ + * configs/nucleo-l432kc/src/stm32_dac7571.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#if defined(CONFIG_I2C) && defined(CONFIG_STM32L4_I2C1) && defined(CONFIG_DAC7571) + +/************************************************************************************ + * Preprocessor definitions + ************************************************************************************/ + +#if !defined(CONFIG_DAC7571_ADDR) +# define CONFIG_DAC7571_ADDR 0x4C /* A0 tied to ground */ +#endif + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +static struct dac_dev_s *g_dac; + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_dac7571initialize + * + * Description: + * Initialize and register the DAC7571 DAC driver. + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/dac0" + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ************************************************************************************/ + +int stm32_dac7571initialize(FAR const char *devpath) +{ + FAR struct i2c_master_s *i2c; + int ret; + + /* Configure D4(PA5) and D5(PA6) as input floating */ + + stm32l4_configgpio(GPIO_I2C1_D4); + stm32l4_configgpio(GPIO_I2C1_D5); + + /* Get an instance of the I2C1 interface */ + + i2c = stm32l4_i2cbus_initialize(1); + if (!i2c) + { + return -ENODEV; + } + + /* Then initialize and register DAC7571 */ + + g_dac = dac7571_initialize(i2c, CONFIG_DAC7571_ADDR); + if (!g_dac) + { + ret = -ENODEV; + goto error; + } + + ret = dac_register(devpath, g_dac); + if (ret < 0) + { + aerr("ERROR: dac_register failed: %d\n", ret); + goto error; + } + + return OK; + +error: + (void)stm32l4_i2cbus_uninitialize(i2c); + return ret; +} + +#endif /* defined(CONFIG_I2C) && defined(CONFIG_STM32_I2C1) && defined(CONFIG_DAC7571) */ diff --git a/drivers/analog/Kconfig b/drivers/analog/Kconfig index 96530634766..a535c22d757 100644 --- a/drivers/analog/Kconfig +++ b/drivers/analog/Kconfig @@ -147,6 +147,18 @@ config DAC_AD5410 default n select SPI +config DAC7571 + bool "DAC7571 support" + default n + select I2C + ---help--- + Enable driver support for the Texas Instruments DAC7571 dac. + +config DAC7571_I2C_FREQUENCY + int "DAC7571 I2C frequency" + default 400000 + depends on DAC7571 + endif # DAC config OPAMP diff --git a/drivers/analog/Make.defs b/drivers/analog/Make.defs index 69d10a638de..8450fe0faf4 100644 --- a/drivers/analog/Make.defs +++ b/drivers/analog/Make.defs @@ -48,6 +48,10 @@ CSRCS += dac.c ifeq ($(CONFIG_DAC_AD5410),y) CSRCS += ad5410.c endif + +ifeq ($(CONFIG_DAC7571),y) + CSRCS += dac7571.c +endif endif # Check for COMP devices diff --git a/drivers/analog/dac7571.c b/drivers/analog/dac7571.c new file mode 100644 index 00000000000..2288dfc5e3f --- /dev/null +++ b/drivers/analog/dac7571.c @@ -0,0 +1,280 @@ +/**************************************************************************** + * arch/drivers/analog/dac7571.c + * + * Copyright (C) 2010, 2016, 2018 Gregory Nutt. All rights reserved. + * Copyright (C) 2018 Daniel P. Carvalho. All rights reserved. + * Author: Daniel P. Carvalho + * + * This file is a part of NuttX: + * + * Copyright (C) 2010 Gregory Nutt. 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 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 + +#include +#include +#include + +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ + +#if !defined(CONFIG_I2C) +# error I2C Support Required. +#endif + +#if defined(CONFIG_DAC7571) + +/* Operating modes - not controllable by user */ + +#define DAC7571_CONFIG_OPMODE_SHIFT 4 +#define DAC7571_CONFIG_OPMODE_MASK (0x0F << DAC7571_CONFIG_OPMODE_SHIFT) +#define DAC7571_CONFIG_OPMODE_NORMAL (0 << DAC7571_CONFIG_OPMODE_SHIFT) +#define DAC7571_CONFIG_OPMODE_1K_PWD (1 << DAC7571_CONFIG_OPMODE_SHIFT) +#define DAC7571_CONFIG_OPMODE_100K_PWD (2 << DAC7571_CONFIG_OPMODE_SHIFT) +#define DAC7571_CONFIG_OPMODE_HZ_PWD (3 << DAC7571_CONFIG_OPMODE_SHIFT) + +#ifndef CONFIG_DAC7571_I2C_FREQUENCY +# define CONFIG_DAC7571_I2C_FREQUENCY 400000 +#endif + +#define I2C_NOSTARTSTOP_MSGS 2 +#define I2C_NOSTARTSTOP_ADDRESS_MSG_INDEX 0 +#define I2C_NOSTARTSTOP_DATA_MSG_INDEX 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct dac7571_dev_s +{ + FAR struct i2c_master_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + uint16_t state; /* DAC7571 current state */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* I2C Helpers */ + +/* DAC methods */ + +static void dac7571_reset(FAR struct dac_dev_s *dev); +static int dac7571_setup(FAR struct dac_dev_s *dev); +static void dac7571_shutdown(FAR struct dac_dev_s *dev); +static void dac7571_txint(FAR struct dac_dev_s *dev, bool enable); +static int dac7571_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg); +static int dac7571_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct dac7571_dev_s g_dacpriv; + +static const struct dac_ops_s g_dacops = +{ + .ao_reset = dac7571_reset, + .ao_setup = dac7571_setup, + .ao_shutdown = dac7571_shutdown, + .ao_txint = dac7571_txint, + .ao_send = dac7571_send, + .ao_ioctl = dac7571_ioctl, +}; + +static struct dac_dev_s g_dacdev = +{ + .ad_ops = &g_dacops, + .ad_priv = &g_dacpriv, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dac7571_reset + * + * Description: + * Reset the DAC device. Called early to initialize the hardware. This + * is called, before ao_setup() and on error conditions. + * + ****************************************************************************/ + +static void dac7571_reset(FAR struct dac_dev_s *dev) +{ +} + +/**************************************************************************** + * Name: dac7571_setup + * + * Description: + * Configure the DAC. This method is called the first time that the DAC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching DAC interrupts. Interrupts + * are all disabled upon return. + * + ****************************************************************************/ + +static int dac7571_setup(FAR struct dac_dev_s *dev) +{ + return OK; +} + +/**************************************************************************** + * Name: dac7571_shutdown + * + * Description: + * Disable the DAC. This method is called when the DAC device is closed. + * This method reverses the operation the setup method. + * + ****************************************************************************/ + +static void dac7571_shutdown(FAR struct dac_dev_s *dev) +{ +} + +/**************************************************************************** + * Name: dac7571_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void dac7571_txint(FAR struct dac_dev_s *dev, bool enable) +{ +} + +/**************************************************************************** + * Name: dac7571_send + ****************************************************************************/ + +static int dac7571_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) +{ + FAR struct dac7571_dev_s *priv = (FAR struct dac7571_dev_s *)dev->ad_priv; + struct i2c_config_s config; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv->i2c != NULL); + + /* Set up message to send */ + + ainfo("value: %08x\n", msg->am_data); + + uint8_t const BUFFER_SIZE = 2; + uint8_t buffer[BUFFER_SIZE]; + + buffer[0] = (uint8_t)(msg->am_data >> 8); + buffer[0] &= ~(DAC7571_CONFIG_OPMODE_MASK); /* only normal op mode supported */ + buffer[1] = (uint8_t)(msg->am_data); + + /* Set up the I2C configuration */ + + config.frequency = CONFIG_DAC7571_I2C_FREQUENCY; + config.address = priv->addr; + config.addrlen = 7; + + /* Then perform the transfer. */ + + ret = i2c_write(priv->i2c, &config, buffer, BUFFER_SIZE); + if (ret < 0) + { + aerr("ERROR: dac7571_send failed code:%d\n", ret); + } + + dac_txdone(&g_dacdev); + return ret; +} + +/**************************************************************************** + * Name: dac7571_ioctl + ****************************************************************************/ + +static int dac7571_ioctl(FAR struct dac_dev_s *dev, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dac7571_initialize + * + * Description: + * Initialize DAC + * + * Input Parameters: + * Port number (for hardware that has multiple DAC interfaces) + * + * Returned Value: + * Valid DAC7571 device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct dac_dev_s *dac7571_initialize(FAR struct i2c_master_s *i2c, + uint8_t addr) +{ + FAR struct dac7571_dev_s *priv; + + /* Sanity check */ + + DEBUGASSERT(i2c != NULL); + +/* Initialize the DAC7571 device structure */ + + priv = (FAR struct dac7571_dev_s *)g_dacdev.ad_priv; + priv->i2c = i2c; + priv->addr = addr; + return &g_dacdev; +} + +#endif /* CONFIG_DAC7571 */ \ No newline at end of file diff --git a/include/nuttx/analog/dac.h b/include/nuttx/analog/dac.h index 5f9fce131c2..50dfbbd3818 100644 --- a/include/nuttx/analog/dac.h +++ b/include/nuttx/analog/dac.h @@ -1,7 +1,7 @@ /************************************************************************************ * include/nuttx/analog/dac.h * - * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017, 2018 Gregory Nutt. All rights reserved. * Copyright (C) 2011 Li Zhuoyi. All rights reserved. * Author: Li Zhuoyi * History: 0.1 2011-08-04 initial version @@ -55,11 +55,13 @@ #include #include #include +#include #include /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ + /* Default configuration settings that may be overridden in the board configuration. * file. The configured size is limited to 255 to fit into a uint8_t. */ @@ -208,6 +210,8 @@ int dac_txdone(FAR struct dac_dev_s *dev); FAR struct dac_dev_s *up_ad5410initialize(FAR struct spi_dev_s *spi, unsigned int devno); +FAR struct dac_dev_s *dac7571_initialize(FAR struct i2c_master_s *i2c, uint8_t addr); + #if defined(__cplusplus) } #endif