From bc170f11b4e891a176320a4304a14de3adb18ad5 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 22 May 2013 18:12:54 -0600 Subject: [PATCH] Beginning of a segment LCD driver for the STM32L-Discovery --- configs/stm32ldiscovery/README.txt | 10 +- configs/stm32ldiscovery/src/Makefile | 18 +- configs/stm32ldiscovery/src/stm32_lcd.c | 358 ++++++++++++++++++ configs/stm32ldiscovery/src/stm32ldiscovery.h | 121 ++++++ 4 files changed, 491 insertions(+), 16 deletions(-) create mode 100644 configs/stm32ldiscovery/src/stm32_lcd.c diff --git a/configs/stm32ldiscovery/README.txt b/configs/stm32ldiscovery/README.txt index 20154f6d11..734505f5c6 100644 --- a/configs/stm32ldiscovery/README.txt +++ b/configs/stm32ldiscovery/README.txt @@ -67,12 +67,15 @@ GPIO Pin Usage TIM3_CH2/TIM1_CH1N /LCD_SEG4/TIM11_CH1/ PA8 USART1_CK/MCO/ LCD glass COM0 P2, pin 23 + LCD_COM0 PA9 USART1_TX/LCD_COM1 LCD glass COM1 P2, pin 22 PA10 USART1_RX/LCD_COM2 LCD glass COM2 P2, pin 21 PA11 USART1_CTS/USBDM/ --- P2, pin 20 SPI1_MISO PA12 USART1_RTS/USBDP/ --- P2, pin 19 SPI1_MOSI + JTDI TIM2_CH1_ETR/PA15/ LCD_SEG12 P2, pin 16 + SPI1_NSS/LCD_SEG17 ----- --------------------- -------------------------------- ---------------- PB0 ADC_IN8/TIM3_CH3/ Linear Touch Sensor (PB0) --- LCD_SEG5/COMP1_INP/ @@ -82,6 +85,11 @@ GPIO Pin Usage VREF_OUT PB2/ --- --- P1, pin 21 BOOT1 + JTDO TIM2_CH2/PB3/TRACES LCD_SEG3, SWO P2, pin 11 + WO/SPI1_SCK/COMP2_I + NM/LCD_SEG7 + JNTRST TIM3_CH1/PB4/SPI1_MIS SEG4 P2, pin 10 + O/COMP2_INP/LCD_SEG8 PB5 I2C1_SMBAl/TIM3_CH2/ LCD SEG5 P2, pin 9 SPI1_MOSI/COMP2_INP/ LCD_SEG9 @@ -98,7 +106,7 @@ GPIO Pin Usage PB11 I2C2_SDA/USART3_RX/ LCD SEG7 P1, pin 23 TIM2_CH4/LCD_SEG11 PB12 SPI2_NSS/I2C2_SMBA/ LCD SEG8 P1, pin 24 - USART3_CK/LCD_SEG1 + USART3_CK/LCD_SEG12 2/ADC_IN18/COMP1_INP / TIM10_CH1 PB13 SPI2_SCK/USART3_CTS/ LCD SEG9 P1, pin 25 diff --git a/configs/stm32ldiscovery/src/Makefile b/configs/stm32ldiscovery/src/Makefile index e37f46609c..1e0bd225ce 100644 --- a/configs/stm32ldiscovery/src/Makefile +++ b/configs/stm32ldiscovery/src/Makefile @@ -53,23 +53,11 @@ CSRCS += stm32_userleds.c endif ifeq ($(CONFIG_ARCH_BUTTONS),y) -CSRCS += stm32_buttons.c +CSRCS += stm32_buttons.c endif -ifeq ($(CONFIG_STM32_USB),y) -CSRCS += stm32_usb.c -endif - -ifeq ($(CONFIG_PWM),y) -CSRCS += stm32_pwm.c -endif - -ifeq ($(CONFIG_QENCODER),y) -CSRCS += stm32_qencoder.c -endif - -ifeq ($(CONFIG_WATCHDOG),y) -CSRCS += stm32_watchdog.c +ifeq ($(CONFIG_STM32_LCD),y) +CSRCS += stm32_lcd.c endif ifeq ($(CONFIG_NSH_ARCHINIT),y) diff --git a/configs/stm32ldiscovery/src/stm32_lcd.c b/configs/stm32ldiscovery/src/stm32_lcd.c new file mode 100644 index 0000000000..0538429fba --- /dev/null +++ b/configs/stm32ldiscovery/src/stm32_lcd.c @@ -0,0 +1,358 @@ +/**************************************************************************** + * configs/stm32ldiscovery/src/stm32_lcd.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Authors: 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 "up_arch.h" +#include "chip/stm32_lcd.h" +#include "stm32ldiscovery.h" + +#ifdef CONFIG_STM32_LCD + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +/* Define CONFIG_DEBUG_LCD to enable detailed LCD debug output. Verbose debug must + * also be enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +# undef CONFIG_DEBUG_LCD +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_LCD +#endif + +/* LCD **********************************************************************/ +/* LCD. The STM32L152RBT6 supports either a 4x32 or 8x28. The STM32L- + * Discovery has an LCD 24 segments, 4 commons. See stm32ldiscovery.h for + * the pin mapping. + */ + +/* Macro to convert an LCD register offset and bit number into a bit-band + * address: + */ + +#define LCD_OFFSET (STM32_LCD_BASE - STM32_PERIPH_BASE) +#define LCD_BBADDR(o,b) (STM32_PERIPHBB_BASE + ((LCD_OFFSET + (o)) << 5) + ((b) << 2)) + +/* Some useful bit-band addresses */ + +#define LCD_CR_LCDEN_BB LCD_BBADDR(STM32_LCD_CR_OFFSET,0) +#define LCD_SR_UDR_BB LCD_BBADDR(STM32_LCD_SR_OFFSET,2) + +/* Debug ********************************************************************/ + +#ifdef CONFIG_DEBUG_LCD +# define lcddbg dbg +# define lcdvdbg vdbg +#else +# define lcddbg(x...) +# define lcdvdbg(x...) +#endif + +/**************************************************************************** + * Private Type Definition + ****************************************************************************/ + +/* Indices into the g_lcdgpio[] array */ + +enum stm32_gpio_e +{ + LCD_COM0 = 0, LCD_COM1, LCD_COM2, LCD_COM3, + + LCD_SEG0, LCD_SEG1, LCD_SEG2, LCD_SEG3, LCD_SEG4, LCD_SEG5, LCD_SEG6, + LCD_SEG7, LCD_SEG8, LCD_SEG9, LCD_SEG10, LCD_SEG11, LCD_SEG12, LCD_SEG13, + LCD_SEG14, LCD_SEG15, LCD_SEG16, LCD_SEG17, LCD_SEG18, LCD_SEG19, LCD_SEG20, + LCD_SEG21, LCD_SEG22, LCD_SEG23, + + LCD_NGPIOS +}; + +struct stm32_lcd_s +{ + bool initialized; /* True: Completed initialization sequence */ +}; + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ +/* Internal utilities */ + +static void lcd_clear(void) + +/* Character driver methods */ + +static ssize_t lcd_read(FAR struct file *, FAR char *, size_t); +static ssize_t lcd_write(FAR struct file *, FAR const char *, size_t); +#ifndef CONFIG_DISABLE_POLL +static int lcd_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This is the driver state structure (there is no retained state information) */ + +static const struct file_operations g_lcdops = +{ + 0, /* open */ + 0, /* close */ + lcd_read, /* read */ + lcd_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , lcd_poll /* poll */ +#endif +}; + +/* All GPIOs that need to be configured for the STM32L-Discovery LCD */ + +static uint32_t g_lcdgpio[BOARD_LCD_NGPIOS] = +{ + BOARD_LCD_COM0, BOARD_LCD_COM1, BOARD_LCD_COM2, BOARD_LCD_COM3, + + BOARD_LCD_SEG0, BOARD_LCD_SEG1, BOARD_LCD_SEG2, BOARD_LCD_SEG3, + BOARD_LCD_SEG4, BOARD_LCD_SEG5, BOARD_LCD_SEG6, BOARD_LCD_SEG7, + BOARD_LCD_SEG8, BOARD_LCD_SEG9, BOARD_LCD_SEG10, BOARD_LCD_SEG11, + BOARD_LCD_SEG12, BOARD_LCD_SEG13, BOARD_LCD_SEG14, BOARD_LCD_SEG15, + BOARD_LCD_SEG16, BOARD_LCD_SEG17, BOARD_LCD_SEG18, BOARD_LCD_SEG19, + BOARD_LCD_SEG20, BOARD_LCD_SEG21, BOARD_LCD_SEG22, BOARD_LCD_SEG23 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lcd_clear + ****************************************************************************/ + +/**************************************************************************** + * Name: lcd_clear + ****************************************************************************/ + +static void lcd_clear(void) +{ + uint32_t regaddr; + int i; + + /* Make sure that any previous transfer is complete. The firmware sets + * the UDR each it modifies the LCD_RAM. The UDR bit stays set until the + * end of the update. During this time the LCD_RAM is write protected. + */ + + while ((getreg32(STM32_LCD_SR) & LCD_SR_UDR) != 0); + + /* Write all zerios in to the LCD RAM */ + + for (regaddr = STM32_LCD_RAML(0); i <= STM32_LCD_RAMH(7); regaddr++) + { + putreg32(0, regaddr); + } + + /* Set the UDR bit to transfer the updated data to the second level + * buffer. + */ + + putreg32(1, LCD_SR_UDR_BB); +} + +/**************************************************************************** + * Name: lcd_read + ****************************************************************************/ + +static ssize_t lcd_read(FAR struct file *filp, FAR char *buffer, size_t len) +{ +} + +/**************************************************************************** + * Name: lcd_write + ****************************************************************************/ + +static ssize_t lcd_write(FAR struct file *filp, FAR const char *buffer, size_t len) +{ +} + +/**************************************************************************** + * Name: lcd_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int lcd_poll(FAR struct file *filp, FAR struct pollfd *fds, + bool setup) +{ + if (setup) + { + /* Data is always avaialble to be read */ + + fds->revents |= (fds->events & (POLLIN|POLLOUT)); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_lcd_initialize + * + * Description: + * Initialize the LCD1602 hardware and register the character driver. + * + ****************************************************************************/ + +int stm32_lcd_initialize(void) +{ + uint32_t regval; + int ret = OK; + int i; + + /* Only initialize the driver once. */ + + if (!g_lcdops.initialized) + { + lcdvdbg("Initializing\n"); + + /* Configure LCD GPIO pins */ + + for (i = 0; i < BOARD_LCD_NGPIOS; i++); + { + stm32_configgpio(g_lcdgpio[i]); + } + + /* Set the LCD prescaler and divider values */ + + regval = getreg32(STM32_LCD_FCR); + regval &= ~(LCD_FCR_DIV_MASK | LCD_FCR_PS_MASK); + regval |= ( LCD_FCR_PS_DIV1 | LCD_FCR_DIV(31)); + putreg32(regval, STM32_LCD_FCR); + + /* Wait for the FCRSF flag to be set */ + + while ((getreg32(STM32_LCD_SR) & LCD_SR_FCRSF) == 0); + + /* Set the duty (1/4), bias (1/3), and the internal voltage source (VSEL=0) */ + + regval = getreg32(STM32_LCD_CR); + regval &= ~(LCD_CR_BIAS_MASK | LCD_CR_DUTY_MASK | LCD_CR_VSEL); + regval |= (LCD_CR_DUTY_1TO4 | LCD_CR_BIAS_1TO3); + putreg32(regval, STM32_LCD_CR); + + /* SEG[31:28] are multiplexed with SEG[43:40] */ + + regval |= LCD_CR_MUX_SEG; + putreg32(regval, STM32_LCD_CR); + + /* Set the contrast to the mean value */ + + regval = getreg32(STM32_LCD_FCR); + regval &= ~LCD_FCR_CC_MASK; + regval |= LCD_FCR_CC_VLCD(4); + putreg32(regval, STM32_LCD_FCR); + + /* No dead time */ + + regval &= ~LCD_FCR_DEAD_MASK; + putreg32(regval, STM32_LCD_FCR); + + /* Set the pulse-on duration to 4/ck_ps */ + + regval &= ~LCD_FCR_PON_MASK; + regval |= LCD_FCR_PON(4); + putreg32(regval, STM32_LCD_FCR); + + /* Wait Until the LCD FCR register is synchronized */ + + while ((getreg32(STM32_LCD_SR) & LCD_SR_FCRSF) == 0); + + /* Enable LCD peripheral */ + + putreg32(1, LCD_CR_LCDEN_BB); + + /* Wait Until the LCD is enabled and the LCD booster is ready */ + + while ((getreg32(STM32_LCD_SR) & (LCD_SR_ENS | LCD_SR_RDY)) != (LCD_SR_ENS | LCD_SR_RDY)); + + /* Disable blinking */ + + regval = getreg32(STM32_LCD_FCR); + regval &= ~(LCD_FCR_BLINKF_MASK | LCD_FCR_BLINK_MASK); + regval |= (LCD_FCR_BLINK_DISABLE | LCD_FCR_BLINKF_DIV32); + putreg32(regval, STM32_LCD_FCR); + + /* Register the LCD device driver */ + + ret = register_driver("/dev/slcd", &g_lcdops, 0644, &g_lcdops); + g_lcdops.initialized = true; + + /* Then clear the display */ + + lcd_clear(); + } + + return ret; +} + +#endif /* CONFIG_STM32_LCD */ diff --git a/configs/stm32ldiscovery/src/stm32ldiscovery.h b/configs/stm32ldiscovery/src/stm32ldiscovery.h index c012b9a084..36a48b9982 100644 --- a/configs/stm32ldiscovery/src/stm32ldiscovery.h +++ b/configs/stm32ldiscovery/src/stm32ldiscovery.h @@ -98,6 +98,127 @@ #define GPIO_BTN_USER (GPIO_INPUT | GPIO_FLOAT | GPIO_EXTI | GPIO_PORTA | GPIO_PIN0) +/* LCD definitions **********************************************************************************/ +/* LCD. The STM32L152RBT6 supports either a 4x32 or 8x28. The STM32L-Discovery + * has an LCD 24 segments, 4 commons. On that board, LCD pins are mapped as + * follows: + * + * The 24 segments are represented by the letters A, B, C, D, E, F, G, H, J, + * K, M, N, P, Q, COL (colon), and DP (decimal point) + * + * A + * --------- _ + * |\ |J /| |_| COL + * F| H | K |B + * | \ | / | _ + * --G-- --M-+ |_| COL + * | /| \ | + * E| Q | N |C + * | / |P \| _ + * --------- |_| DP + * D + * + * Plus BAR0-3. The following is of each segment of each of the 6 characters 4 x 24: + * + * ---- ----- ----- ----- ----- --------------- + * GPIO COM3 COM2 COM1 COM0 SIGNAL NAME + * ---- ----- ----- ----- ----- --------------- + * PA1 1N 1P 1D 1E LCD SEG0 + * PA2 1DP 1COL 1C 1M LCD SEG1 + * PA3 2N 2P 2D 2E LCD SEG2 + * PB3 2DP 2COL 2C 2M LCD SEG3 + * PB4 3N 3P 3D 3E LCD SEG4 + * PB5 3DP 3COL 3C 3M LCD SEG5 + * PB10 4N 4P 4D 4E LCD SEG6 + * PB11 4DP 4COL 4C 4M LCD SEG7 + * PB12 5N 5P 5D 5E LCD SEG8 + * PB13 BAR2 BAR3 5C 5M LCD SEG9 + * PB14 6N 6P 6D 6E LCD SEG10 + * PB15 BAR0 BAR1 6C 6M LCD SEG11 + * PB9 COM3 LCD glass COM3 + * PA10 COM2 LCD glass COM2 + * PA9 COM1 LCD glass COM1 + * PA8 COM0 LCD glass COM0 + * PA15 6J 6K 6A 6B LCD SEG12 + * PB8 6H 6Q 6F 6G LCD SEG13 + * PC0 5J 5K 5A 5B LCD SEG14 + * PC1 5H 5Q 5F 5G LCD SEG15 + * PC2 4J 4K 4A 4B LCD SEG16 + * PC3 4H 4Q 4F 4G LCD SEG17 + * PC6 3J 3K 3A 3B LCD SEG18 + * PC7 3H 3Q 3F 3G LCD SEG19 + * PC8 2J 2K 2A 2B LCD SEG20 + * PC9 2H 2Q 2F 2G LCD SEG21 + * PC10 1J 1K 1A 1B LCD SEG22 + * PC11 1H 1Q 1F 1G LCD SEG23 + * ---- ----- ----- ----- ----- --------------- + * + * ----- --------------------- ---------------- + * GPIO ALTERNATE FUNCTION BOARD SIGNAL + * ----- --------------------- ---------------- + * PA8 LCD_COM0 LCD glass COM0 + * PA9 LCD_COM1 LCD glass COM1 + * PA10 LCD_COM2 LCD glass COM2 + * PB9 LCD_COM3 LCD glass COM3 + * PA1 LCD_SEG0 LCD SEG0 + * PA2 LCD_SEG1 LCD SEG1 + * PA3 LCD_SEG2 LCD SEG2 + * PB3 LCD_SEG7 LCD_SEG3 + * PB4 LCD_SEG8 LCD_SEG4 + * PB5 LCD_SEG9 LCD SEG5 + * PB10 LCD_SEG10 LCD SEG6 + * PB11 LCD_SEG11 LCD SEG7 + * PB12 LCD_SEG12 LCD SEG8 + * PB13 LCD_SEG13 LCD SEG9 + * PB14 LCD_SEG14 LCD SEG10 + * PB15 LCD_SEG15 LCD SEG11 + * PA15 LCD_SEG12 LCD SEG12 + * PB8 LCD_SEG16 LCD SEG13 + * PC0 LCD_SEG18 LCD SEG14 + * PC1 LCD_SEG19 LCD SEG15 + * PC2 LCD_SEG20 LCD SEG16 + * PC3 LCD_SEG21 LCD SEG17 + * PC6 LCD_SEG24 LCD SEG18 + * PC7 LCD_SEG25 LCD SEG19 + * PC8 LCD_SEG26 LCD SEG20 + * PC9 LCD_SEG27 LCD SEG21 + * PC10 LCD_SEG40 LCD SEG22 + * PC11 LCD_SEG41 LCD SEG23 + */ + +#define BOARD_LCD_COM0 GPIO_LCD_COM0 /* PA8 */ +#define BOARD_LCD_COM1 GPIO_LCD_COM1 /* PA9 */ +#define BOARD_LCD_COM2 GPIO_LCD_COM2 /* PA10 */ +#define BOARD_LCD_COM3 GPIO_LCD_COM3 /* PB9 */ +#define BOARD_LCD_SEG0 GPIO_LCD_SEG0 /* PA1 */ +#define BOARD_LCD_SEG1 GPIO_LCD_SEG1 /* PA2 */ +#define BOARD_LCD_SEG2 GPIO_LCD_SEG2 /* PA3 */ +#define BOARD_LCD_SEG3 GPIO_LCD_SEG7 /* PB3 */ +#define BOARD_LCD_SEG4 GPIO_LCD_SEG8 /* PB4 */ +#define BOARD_LCD_SEG5 GPIO_LCD_SEG9 /* PB5 */ +#define BOARD_LCD_SEG6 GPIO_LCD_SEG10 /* PB10 */ +#define BOARD_LCD_SEG7 GPIO_LCD_SEG11 /* PB11 */ +#define BOARD_LCD_SEG8 GPIO_LCD_SEG12 /* PB12 */ +#define BOARD_LCD_SEG9 GPIO_LCD_SEG13 /* PB13 */ +#define BOARD_LCD_SEG10 GPIO_LCD_SEG14 /* PB14 */ +#define BOARD_LCD_SEG11 GPIO_LCD_SEG15 /* PB15 */ +#define BOARD_LCD_SEG12 GPIO_LCD_SEG17 /* PA15 */ +#define BOARD_LCD_SEG13 GPIO_LCD_SEG16 /* PB8 */ +#define BOARD_LCD_SEG14 GPIO_LCD_SEG18 /* PC0 */ +#define BOARD_LCD_SEG15 GPIO_LCD_SEG19 /* PC1 */ +#define BOARD_LCD_SEG16 GPIO_LCD_SEG20 /* PC2 */ +#define BOARD_LCD_SEG17 GPIO_LCD_SEG21 /* PC3 */ +#define BOARD_LCD_SEG18 GPIO_LCD_SEG24 /* PC6 */ +#define BOARD_LCD_SEG19 GPIO_LCD_SEG25 /* PC7 */ +#define BOARD_LCD_SEG20 GPIO_LCD_SEG26 /* PC8 */ +#define BOARD_LCD_SEG21 GPIO_LCD_SEG27 /* PC9 */ +#define BOARD_LCD_SEG22 GPIO_LCD_SEG40 /* PC10 */ +#define BOARD_LCD_SEG23 GPIO_LCD_SEG41 /* PC11 */ + +#define BOARD LCD_NCOM 4 +#define BOARD LCD_NSEG 24 +#define BOARD_LCD_NGPIOS 28 + /**************************************************************************************************** * Public Types ****************************************************************************************************/