diff --git a/configs/stm32f4discovery/src/Makefile b/configs/stm32f4discovery/src/Makefile index 091110de47a..db0bbcec59a 100644 --- a/configs/stm32f4discovery/src/Makefile +++ b/configs/stm32f4discovery/src/Makefile @@ -105,6 +105,10 @@ ifeq ($(CONFIG_STM32_ETHMAC),y) CSRCS += stm32_ethernet.c endif +ifeq ($(CONFIG_LEDS_MAX7219),y) + CSRCS += stm32_max7219_leds.c +endif + ifeq ($(CONFIG_RGBLED),y) CSRCS += stm32_rgbled.c endif diff --git a/configs/stm32f4discovery/src/stm32_bringup.c b/configs/stm32f4discovery/src/stm32_bringup.c index c629074373b..9a91bd7b940 100644 --- a/configs/stm32f4discovery/src/stm32_bringup.c +++ b/configs/stm32f4discovery/src/stm32_bringup.c @@ -125,6 +125,14 @@ int stm32_bringup(void) stm32_zerocross_initialize(); #endif +#ifdef CONFIG_LEDS_MAX7219 + ret = stm32_max7219init("/dev/numdisp0"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: max7219_leds_register failed: %d\n", ret); + } +#endif + #ifdef CONFIG_RGBLED /* Configure the RGB LED driver */ diff --git a/configs/stm32f4discovery/src/stm32_max7219_leds.c b/configs/stm32f4discovery/src/stm32_max7219_leds.c new file mode 100644 index 00000000000..cbff14243b1 --- /dev/null +++ b/configs/stm32f4discovery/src/stm32_max7219_leds.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * configs/stm32f4discovery/src/stm32_max7219_leds.c + * + * Copyright (C) 2018 Alan Carvalho de Assis. All rights reserved. + * Author: Alan Carvalho de Assis + * + * 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 "stm32.h" +#include "stm32_spi.h" +#include "stm32f4discovery.h" + +#if defined(CONFIG_SPI) && defined(CONFIG_STM32_SPI1) && \ + defined(CONFIG_LEDS_MAX7219) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX7219_SPI_PORTNO 1 /* On SPI1 */ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_max7219init + * + * Description: + * Initialize the max7219 to control 7-segment numeric display + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/numdisp0" + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ************************************************************************************/ + +int stm32_max7219init(FAR const char *devpath) +{ + FAR struct spi_dev_s *spi; + int ret; + + spi = stm32_spibus_initialize(MAX7219_SPI_PORTNO); + if (spi == NULL) + { + return -ENODEV; + } + + /* Register the MAX7219 Driver at the specified location. */ + + ret = max7219_leds_register(devpath, spi); + if (ret < 0) + { + lederr("ERROR: max7219_leds_register(%s) failed: %d\n", + devpath, ret); + return ret; + } + + return OK; +} + +#endif /* CONFIG_SPI && CONFIG_LEDS_MAX7219 */ diff --git a/configs/stm32f4discovery/src/stm32_spi.c b/configs/stm32f4discovery/src/stm32_spi.c index e36b0391052..a9be4c1d2d1 100644 --- a/configs/stm32f4discovery/src/stm32_spi.c +++ b/configs/stm32f4discovery/src/stm32_spi.c @@ -75,7 +75,7 @@ void weak_function stm32_spidev_initialize(void) #if defined(CONFIG_STM32_SPI2) && defined(CONFIG_SENSORS_MAX31855) (void)stm32_configgpio(GPIO_MAX31855_CS); /* MAX31855 chip select */ #endif -#ifdef CONFIG_LCD_MAX7219 +#if defined(CONFIG_LCD_MAX7219) || defined(CONFIG_LEDS_MAX7219) (void)stm32_configgpio(GPIO_MAX7219_CS); /* MAX7219 chip select */ #endif #if defined(CONFIG_LCD_ST7567) @@ -132,7 +132,7 @@ void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected) stm32_gpiowrite(STM32_LCD_CS, !selected); } #endif -#ifdef CONFIG_LCD_MAX7219 +#if defined(CONFIG_LCD_MAX7219) || defined(CONFIG_LEDS_MAX7219) if (devid == SPIDEV_DISPLAY(0)) { stm32_gpiowrite(GPIO_MAX7219_CS, !selected); diff --git a/configs/stm32f4discovery/src/stm32f4discovery.h b/configs/stm32f4discovery/src/stm32f4discovery.h index 902c51f6c9f..3738ea9ae79 100644 --- a/configs/stm32f4discovery/src/stm32f4discovery.h +++ b/configs/stm32f4discovery/src/stm32f4discovery.h @@ -506,6 +506,18 @@ int stm32_lis3dshinitialize(FAR const char *devpath); int nunchuck_initialize(FAR char *devname); #endif +/**************************************************************************** + * Name: stm32_max7219init + * + * Description: + * Initialize and register the max7219 numeric display controller + * + ****************************************************************************/ + +#ifdef CONFIG_LEDS_MAX7219 +int stm32_max7219init(FAR const char *devpath); +#endif + /**************************************************************************** * Name: stm32_usbinitialize * diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 5cab3cd90b2..040488f0e13 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -48,6 +48,13 @@ config LEDS_APA102 ---help--- Enable support for the APA102 LED Strip driver. +config LEDS_MAX7219 + bool "MAX7219 Numeric Display" + default n + select SPI + ---help--- + Enable support for the MAX7219 to control 7-segment displays. + config RGBLED bool "RGB LED Driver Support" default n diff --git a/drivers/leds/Make.defs b/drivers/leds/Make.defs index 718d1bc648c..70fb5c03699 100644 --- a/drivers/leds/Make.defs +++ b/drivers/leds/Make.defs @@ -56,6 +56,12 @@ ifeq ($(CONFIG_LEDS_APA102),y) LEDVPATH = :leds endif +ifeq ($(CONFIG_LEDS_MAX7219),y) + CSRCS += max7219.c + LEDDEPATH = --dep-path leds + LEDVPATH = :leds +endif + ifeq ($(CONFIG_RGBLED),y) CSRCS += rgbled.c LEDDEPATH = --dep-path leds diff --git a/drivers/leds/max7219.c b/drivers/leds/max7219.c new file mode 100644 index 00000000000..4f396da95fb --- /dev/null +++ b/drivers/leds/max7219.c @@ -0,0 +1,323 @@ +/**************************************************************************** + * drivers/sensors/max7219.c + * Maxim MAX7219 driver used to control 7-segment display. + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Copyright (C) 2018 Alan Carvalho de Assis + * Author: Alan Carvalho de Assis + * + * 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_SPI) && defined(CONFIG_LEDS_MAX7219) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SPI frequency */ + +#ifndef CONFIG_MAX7219_FREQUENCY +# define CONFIG_MAX7219_FREQUENCY 5000000 +#endif + +#ifndef CONFIG_MAX7219_INTENSITY +# define CONFIG_MAX7219_INTENSITY 8 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct max7219_dev_s +{ + FAR struct spi_dev_s *spi; /* SPI interface */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void max7219_configspi(FAR struct spi_dev_s *spi); +static inline void max7219_write16(FAR struct max7219_dev_s *priv, + uint16_t value); + +/* Character driver methods */ + +static int max7219_open(FAR struct file *filep); +static int max7219_close(FAR struct file *filep); +static ssize_t max7219_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t max7219_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_max7219fops = +{ + max7219_open, /* open */ + max7219_close, /* close */ + max7219_read, /* read */ + max7219_write, /* write */ + 0, /* seek */ + 0, /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + 0, /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: max7219_configspi + * + * Description: + * Set the SPI bus configuration + * + ****************************************************************************/ + +static inline void max7219_configspi(FAR struct spi_dev_s *spi) +{ + /* Configure SPI for the MAX7219 */ + + SPI_SETMODE(spi, SPIDEV_MODE0); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, 0); + (void)SPI_SETFREQUENCY(spi, CONFIG_MAX7219_FREQUENCY); +} + +/**************************************************************************** + * Name: max7219_write16 + * + * Description: + * Write 16-bit to MAX7219 + * + ****************************************************************************/ + +static inline void max7219_write16(FAR struct max7219_dev_s *priv, + uint16_t value) +{ + /* If SPI bus is shared then lock and configure it */ + + (void)SPI_LOCK(priv->spi, true); + + /* Configure the SPI */ + + max7219_configspi(priv->spi); + + /* Select */ + + SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true); + + /* Send 16 bits (2 bytes) */ + + (void)SPI_SNDBLOCK(priv->spi, &value, 2); + + /* Deselect */ + + SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false); + + /* Unlock bus */ + + (void)SPI_LOCK(priv->spi, false); +} + +/**************************************************************************** + * Name: max7219_open + * + * Description: + * This function is called whenever the MAX7219 device is opened. + * + ****************************************************************************/ + +static int max7219_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: max7219_close + * + * Description: + * This routine is called when the LM-75 device is closed. + * + ****************************************************************************/ + +static int max7219_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: max7219_read + ****************************************************************************/ + +static ssize_t max7219_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: max7219_write + ****************************************************************************/ + +static ssize_t max7219_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct max7219_dev_s *priv = inode->i_private; + FAR const char *leds = (FAR char *) buffer; + uint16_t data; + uint8_t i; + + if (!leds) + { + snerr("ERROR: Buffer is null\n"); + return -1; + } + + /* At least one display, so 1 byte */ + + if (buflen < 1) + { + snerr("ERROR: You need to control at least 1 digit!\n"); + return -1; + } + + /* It can control up to 8 digits (8 7-segment displays) */ + + if (buflen > 8) + { + snerr("ERROR: The limit is 8 digits!\n"); + return -1; + } + + /* Write each digit */ + + for (i = 0; i < buflen; i++) + { + data = (MAX7219_DIGIT0 + i) | (leds[i] - '0') << 8; + max7219_write16(priv, data); + } + + /* All bytes were written */ + + return buflen; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: max7219_register + * + * Description: + * Register the MAX7219 character device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/temp0" + * i2c - An instance of the I2C interface to use to communicate with + * MAX7219 + * addr - The I2C address of the LM-75. The base I2C address of the + * MAX7219 is 0x48. Bits 0-3 can be controlled to get 8 unique + * addresses from 0x48 through 0x4f. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int max7219_leds_register(FAR const char *devpath, FAR struct spi_dev_s *spi) +{ + FAR struct max7219_dev_s *priv; + uint16_t data; + int ret; + + /* Initialize the MAX7219 device structure */ + + priv = (FAR struct max7219_dev_s *)kmm_malloc(sizeof(struct max7219_dev_s)); + if (!priv) + { + snerr("ERROR: Failed to allocate instance\n"); + return -ENOMEM; + } + + priv->spi = spi; + + /* Leave the shutdown mode */ + + data = (MAX7219_SHUTDOWN) | (MAX7219_POWER_ON << 8); + max7219_write16(priv, data); + + /* Setup defined intensity */ + + data = (MAX7219_INTENSITY) | + (DISPLAY_INTENSITY(CONFIG_MAX7219_INTENSITY) << 8); + max7219_write16(priv, data); + + /* Enable decoding for all digits */ + + data = (MAX7219_DECODE_MODE) | (ENABLE_DECODE << 8); + max7219_write16(priv, data); + + /* Register the character driver */ + + ret = register_driver(devpath, &g_max7219fops, 0666, priv); + if (ret < 0) + { + snerr("ERROR: Failed to register driver: %d\n", ret); + kmm_free(priv); + } + + return ret; +} +#endif /* CONFIG_SPI && CONFIG_MAX7219 */ diff --git a/include/nuttx/leds/max7219.h b/include/nuttx/leds/max7219.h new file mode 100644 index 00000000000..64f0d8b8f5d --- /dev/null +++ b/include/nuttx/leds/max7219.h @@ -0,0 +1,123 @@ +/**************************************************************************** + * include/nuttx/leds/max7219.h + * + * Copyright (C) 2018 Alan Carvalho de Assis. All rights reserved. + * Author: Alan Carvalho de Assis + * + * 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_LEDS_MAX7219_H +#define __INCLUDE_NUTTX_LEDS_MAX7219_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/* Configuration + * CONFIG_SPI - Enables support for SPI drivers + * CONFIG_LEDS_MAX7219 - Enables support for the MAX7219 driver + */ + +#if defined(CONFIG_SPI) && defined(CONFIG_LEDS_MAX7219) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* MAX7219 register addresses */ + +#define MAX7219_NOOP (0x00) /* No Operation */ +#define MAX7219_DIGIT0 (0x01) /* Digit 0 register */ +#define MAX7219_DIGIT1 (0x02) /* Digit 1 register */ +#define MAX7219_DIGIT2 (0x03) /* Digit 2 register */ +#define MAX7219_DIGIT3 (0x04) /* Digit 3 register */ +#define MAX7219_DIGIT4 (0x05) /* Digit 4 register */ +#define MAX7219_DIGIT5 (0x06) /* Digit 5 register */ +#define MAX7219_DIGIT6 (0x07) /* Digit 6 register */ +#define MAX7219_DIGIT7 (0x08) /* Digit 7 register */ +#define MAX7219_DECODE_MODE (0x09) /* Decode Moder register */ +#define MAX7219_INTENSITY (0x0a) /* Intensity register */ +#define MAX7219_SCAN_LIMIT (0x0b) /* Scan Limit register */ +#define MAX7219_SHUTDOWN (0x0c) /* Shutdown register */ +#define MAX7219_DISPLAY_TEST (0x0f) /* Display Test register */ + +/* Default register values */ + +#define ENABLE_DECODE (0xff) /* Enable decoding of all 7-seg */ +#define DISABLE_DECODE (0x00) /* Disable 7-seg decode */ +#define DEFAULT_SCAN_LIMIT (0x07) /* Display all digits */ +#define DISPLAY_INTENSITY(n) (n & 0xf) /* low nimble defines it */ + +/* Only two power settings are supported: */ + +#define MAX7219_POWER_OFF 0 +#define MAX7219_POWER_ON 1 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: max7219_leds_register + * + * Description: + * Initialize the MAX7219 device as a LEDS interface. + * + * Input Parameters: + * spi - An instance of the SPI interface to use to communicate + * with the MAX7219. + * devno - Device number to identify current display. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + + struct spi_dev_s; /* Forward reference */ +int max7219_leds_register(FAR const char *devpath, FAR struct spi_dev_s *spi); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_SPI && CONFIG_MAX7219 */ +#endif /* __INCLUDE_NUTTX_LEDS_MAX7219_H */