From 4710ae736ca7a5a0c56d55eefe7afc587852be90 Mon Sep 17 00:00:00 2001 From: Augusto Fraga Giachero Date: Wed, 28 Aug 2019 07:01:17 -0600 Subject: [PATCH] drivers/analog/dac7554.c: Add support to the DAC7554 digital-to-analog converter. --- drivers/analog/Kconfig | 7 + drivers/analog/Make.defs | 4 + drivers/analog/dac7554.c | 280 +++++++++++++++++++++++++++++++++++++ drivers/analog/dac7571.c | 8 +- include/nuttx/analog/dac.h | 86 +++++++----- 5 files changed, 344 insertions(+), 41 deletions(-) create mode 100644 drivers/analog/dac7554.c diff --git a/drivers/analog/Kconfig b/drivers/analog/Kconfig index 7273ff9af7..a93f6268dd 100644 --- a/drivers/analog/Kconfig +++ b/drivers/analog/Kconfig @@ -159,6 +159,13 @@ config DAC7571_I2C_FREQUENCY default 400000 depends on DAC7571 +config DAC7554 + bool "DAC7554 support" + default n + select SPI + ---help--- + Enable driver support for the Texas Instruments DAC7554 dac. + endif # DAC config OPAMP diff --git a/drivers/analog/Make.defs b/drivers/analog/Make.defs index 09fb9f64b8..5b9f437c4c 100644 --- a/drivers/analog/Make.defs +++ b/drivers/analog/Make.defs @@ -53,6 +53,10 @@ ifeq ($(CONFIG_DAC7571),y) CSRCS += dac7571.c endif +ifeq ($(CONFIG_DAC7554),y) + CSRCS += dac7554.c +endif + endif # Check for COMP devices diff --git a/drivers/analog/dac7554.c b/drivers/analog/dac7554.c new file mode 100644 index 0000000000..3fdb66a6b8 --- /dev/null +++ b/drivers/analog/dac7554.c @@ -0,0 +1,280 @@ +/**************************************************************************** + * arch/drivers/analog/dac7554.c + * + * Copyright (C) 2010, 2016, 2018 Gregory Nutt. All rights reserved. + * Copyright (C) 2018 Daniel P. Carvalho. All rights reserved. + * Copyright (C) 2019 Augusto Fraga Giachero. All rights reserved. + * Author: Augusto Fraga Giachero + * + * This file is a part of NuttX: + * + * Copyright (C) 2019 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 +#include + +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ + +#if !defined(CONFIG_SPI) +# error SPI Support Required. +#endif + +#if defined(CONFIG_DAC7554) + +#ifndef CONFIG_DAC7554_SPI_FREQUENCY +# define CONFIG_DAC7554_SPI_FREQUENCY 1000000 +#endif + +#define DAC7554_SPI_MODE (SPIDEV_MODE2) /* SPI Mode 2: CPOL=1,CPHA=0 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct dac7554_dev_s +{ + FAR struct spi_dev_s *spi; /* SPI interface */ + int spidev; /* SPI Chip Select number */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* I2C Helpers */ + +/* DAC methods */ + +static void dac7554_reset(FAR struct dac_dev_s *dev); +static int dac7554_setup(FAR struct dac_dev_s *dev); +static void dac7554_shutdown(FAR struct dac_dev_s *dev); +static void dac7554_txint(FAR struct dac_dev_s *dev, bool enable); +static int dac7554_send(FAR struct dac_dev_s *dev, + FAR struct dac_msg_s *msg); +static int dac7554_ioctl(FAR struct dac_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct dac_ops_s g_dacops = +{ + .ao_reset = dac7554_reset, + .ao_setup = dac7554_setup, + .ao_shutdown = dac7554_shutdown, + .ao_txint = dac7554_txint, + .ao_send = dac7554_send, + .ao_ioctl = dac7554_ioctl, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dac7554_configspi + * + * Description: + * Configure the SPI interface + * + ****************************************************************************/ + +static inline void dac7554_configspi(FAR struct spi_dev_s *spi) +{ + SPI_SETMODE(spi, DAC7554_SPI_MODE); + SPI_SETBITS(spi, 8); + SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, CONFIG_DAC7554_SPI_FREQUENCY); +} + +/**************************************************************************** + * Name: dac7554_reset + * + * Description: + * Reset the DAC device. Called early to initialize the hardware. This + * is called, before ao_setup() and on error conditions. + * + ****************************************************************************/ + +static void dac7554_reset(FAR struct dac_dev_s *dev) +{ +} + +/**************************************************************************** + * Name: dac7554_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 dac7554_setup(FAR struct dac_dev_s *dev) +{ + return OK; +} + +/**************************************************************************** + * Name: dac7554_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 dac7554_shutdown(FAR struct dac_dev_s *dev) +{ +} + +/**************************************************************************** + * Name: dac7554_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void dac7554_txint(FAR struct dac_dev_s *dev, bool enable) +{ +} + +/**************************************************************************** + * Name: dac7554_send + ****************************************************************************/ + +static int dac7554_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) +{ + FAR struct dac7554_dev_s *priv = (FAR struct dac7554_dev_s *)dev->ad_priv; + uint16_t data; + + /* Sanity check */ + + DEBUGASSERT(priv->SPI != NULL); + + /* Set up message to send */ + + ainfo("value: %08x\n", msg->am_data); + + SPI_LOCK(priv->spi, true); + + dac7554_configspi(priv->spi); + + data = ((msg->am_data >> 16) & 0x0fff) | ((msg->am_channel & 0x03) << 12) | + (1 << 15); + + SPI_SELECT(priv->spi, priv->spidev, true); + + SPI_SEND(priv->spi, (data >> 8)); + SPI_SEND(priv->spi, (data & 0xff)); + + SPI_SELECT(priv->spi, priv->spidev, false); + + SPI_LOCK(priv->spi, false); + + dac_txdone(dev); + return 0; +} + +/**************************************************************************** + * Name: dac7554_ioctl + ****************************************************************************/ + +static int dac7554_ioctl(FAR struct dac_dev_s *dev, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dac7554_initialize + * + * Description: + * Initialize DAC + * + * Input Parameters: + * Port number (for hardware that has multiple DAC interfaces) + * + * Returned Value: + * Valid DAC7554 device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct dac_dev_s *dac7554_initialize(FAR struct spi_dev_s *spi, + int spidev) +{ + FAR struct dac7554_dev_s *priv; + FAR struct dac_dev_s *g_dacdev; + + /* Sanity check */ + + DEBUGASSERT(i2c != NULL); + + /* Initialize the DAC7554 device structure */ + + priv = (FAR struct dac7554_dev_s *)kmm_malloc(sizeof(struct dac7554_dev_s)); + priv->spi = spi; + priv->spidev = spidev; + + g_dacdev = (FAR struct dac_dev_s *)kmm_malloc(sizeof(struct dac_dev_s)); + g_dacdev->ad_ops = &g_dacops; + g_dacdev->ad_priv = priv; + + return g_dacdev; +} + +#endif /* CONFIG_DAC7554 */ diff --git a/drivers/analog/dac7571.c b/drivers/analog/dac7571.c index d404328a64..f2a7956192 100644 --- a/drivers/analog/dac7571.c +++ b/drivers/analog/dac7571.c @@ -106,8 +106,10 @@ 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); +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 @@ -269,7 +271,7 @@ FAR struct dac_dev_s *dac7571_initialize(FAR struct i2c_master_s *i2c, DEBUGASSERT(i2c != NULL); -/* Initialize the DAC7571 device structure */ + /* Initialize the DAC7571 device structure */ priv = (FAR struct dac7571_dev_s *)g_dacdev.ad_priv; priv->i2c = i2c; diff --git a/include/nuttx/analog/dac.h b/include/nuttx/analog/dac.h index 192cd68bc6..f51057aa18 100644 --- a/include/nuttx/analog/dac.h +++ b/include/nuttx/analog/dac.h @@ -1,4 +1,4 @@ -/************************************************************************************ +/**************************************************************************** * include/nuttx/analog/dac.h * * Copyright (C) 2017, 2018 Gregory Nutt. All rights reserved. @@ -38,14 +38,14 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************************************/ + ****************************************************************************/ #ifndef __INCLUDE_NUTTX_ANALOG_DAC_H #define __INCLUDE_NUTTX_ANALOG_DAC_H -/************************************************************************************ +/**************************************************************************** * Included Files - ************************************************************************************/ + ****************************************************************************/ #include #include @@ -58,12 +58,13 @@ #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. +/* 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. */ #if !defined(CONFIG_DAC_FIFOSIZE) @@ -73,9 +74,9 @@ # define CONFIG_DAC_FIFOSIZE 255 #endif -/************************************************************************************ +/**************************************************************************** * Public Types - ************************************************************************************/ + ****************************************************************************/ begin_packed_struct struct dac_msg_s { @@ -86,15 +87,17 @@ begin_packed_struct struct dac_msg_s struct dac_fifo_s { sem_t af_sem; /* Counting semaphore */ - uint8_t af_head; /* Index to the head [IN] index in the circular buffer */ - uint8_t af_tail; /* Index to the tail [OUT] index in the circular buffer */ + uint8_t af_head; /* Index to the head [IN] index + * in the circular buffer */ + uint8_t af_tail; /* Index to the tail [OUT] index + * in the circular buffer */ /* Circular buffer of DAC messages */ struct dac_msg_s af_buffer[CONFIG_DAC_FIFOSIZE]; }; -/* This structure defines all of the operations providd by the architecture specific - * logic. All fields must be provided with non-NULL function pointers by the - * caller of dac_register(). +/* This structure defines all of the operations providd by the architecture + * specific logic. All fields must be provided with non-NULL function + * pointers by the caller of dac_register(). */ struct dac_dev_s; @@ -108,8 +111,8 @@ struct dac_ops_s /* 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. + * This setup includes configuring and attaching DAC interrupts. + * Interrupts are all disabled upon return. */ CODE int (*ao_setup)(FAR struct dac_dev_s *dev); @@ -130,7 +133,6 @@ struct dac_ops_s /* All ioctl calls will be routed through this method */ CODE int (*ao_ioctl)(FAR struct dac_dev_s *dev, int cmd, unsigned long arg); - }; /* This is the device structure used by the driver. The caller of @@ -144,50 +146,53 @@ struct dac_ops_s struct dac_dev_s { - uint8_t ad_ocount; /* The number of times the device has been opened */ + uint8_t ad_ocount; /* The number of times the device has + * been opened */ uint8_t ad_nchannel; /* Number of dac channel */ - sem_t ad_closesem; /* Locks out new opens while close is in progress */ + sem_t ad_closesem; /* Locks out new opens while close is + * in progress */ struct dac_fifo_s ad_xmit; /* Describes receive FIFO */ const struct dac_ops_s *ad_ops; /* Arch-specific operations */ void *ad_priv; /* Used by the arch-specific logic */ }; -/************************************************************************************ +/**************************************************************************** * Public Data - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Public Functions - ************************************************************************************/ + ****************************************************************************/ #if defined(__cplusplus) extern "C" { #endif -/************************************************************************************ +/**************************************************************************** * Name: dac_register * * Description: * Register a dac driver. * * Input Parameters: - * path - The full path to the DAC device to be registered. This could be, as an - * example, "/dev/dac0" + * path - The full path to the DAC device to be registered. This could + * be, as an example, "/dev/dac0" * dev - An instance of the device-specific DAC interface * * Returned Value: * Zero on success; A negated errno value on failure. * - ************************************************************************************/ + ****************************************************************************/ int dac_register(FAR const char *path, FAR struct dac_dev_s *dev); -/************************************************************************************ +/**************************************************************************** * Name: dac_txdone * * Description: - * Called from the DAC interrupt handler at the completion of a send operation. + * Called from the DAC interrupt handler at the completion of a send + * operation. * * Input Parameters: * dev - An instance of the device-specific DAC interface @@ -195,22 +200,27 @@ int dac_register(FAR const char *path, FAR struct dac_dev_s *dev); * Returned Value: * OK on success; a negated errno on failure. * - ************************************************************************************/ + ****************************************************************************/ int dac_txdone(FAR struct dac_dev_s *dev); -/************************************************************************************ +/**************************************************************************** * DAC Initialization functions * - * Architecture-specific versions will have prototypes in architect-specific header - * files. Common DAC implementations in drivers/analog will have prototypes listed - * below. + * Architecture-specific versions will have prototypes in architect-specific + * header files. Common DAC implementations in drivers/analog will have + * prototypes listed below. * - ************************************************************************************/ + ****************************************************************************/ -FAR struct dac_dev_s *up_ad5410initialize(FAR struct spi_dev_s *spi, unsigned int devno); +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); +FAR struct dac_dev_s *dac7571_initialize(FAR struct i2c_master_s *i2c, + uint8_t addr); + +FAR struct dac_dev_s *dac7554_initialize(FAR struct spi_dev_s *spi, + int spidev); /**************************************************************************** * Name: lmp92001_dac_initialize