summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-05-23 15:23:29 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-05-23 15:23:29 -0600
commitdfaa61731b87c0685c17f41a95a2e758deca80a7 (patch)
tree7ab7b0f9d3360024b315db67d81ae2feeecce2c3
parentc7bf6bf65a458cb30b892340b69de6c025d1cc22 (diff)
downloadnuttx-dfaa61731b87c0685c17f41a95a2e758deca80a7.tar.gz
nuttx-dfaa61731b87c0685c17f41a95a2e758deca80a7.tar.bz2
nuttx-dfaa61731b87c0685c17f41a95a2e758deca80a7.zip
STM32L-Discovery LCD driver is code compele but untested
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/arch/arm/src/stm32/Kconfig24
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_lcd.h8
-rw-r--r--nuttx/configs/stm32ldiscovery/README.txt211
-rw-r--r--nuttx/configs/stm32ldiscovery/nsh/Make.defs2
-rwxr-xr-xnuttx/configs/stm32ldiscovery/nsh/setenv.sh2
-rw-r--r--nuttx/configs/stm32ldiscovery/src/stm32_lcd.c969
-rw-r--r--nuttx/configs/stm32ldiscovery/src/stm32ldiscovery.h62
-rw-r--r--nuttx/include/nuttx/ascii.h4
-rw-r--r--nuttx/include/nuttx/lcd/slcd_codec.h4
-rw-r--r--nuttx/libc/misc/lib_slcddecode.c25
11 files changed, 1094 insertions, 219 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 93212d83e..e33660231 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -4781,3 +4781,5 @@
should set the POLLNVAL event and return immediately (2013-5-23).
* libc/misc/lib_slcdencode.c and lib_slcddecode.c: Add logic to marshal
and serialized special SLCD intermixed with normal ASCII data (2013-5-23)
+ * configs/stm32ldiscovery/src/stm32_lcd.c: STM32L-Discovery's segment LCD
+ is code complete but completely untested (2013-5-23).
diff --git a/nuttx/arch/arm/src/stm32/Kconfig b/nuttx/arch/arm/src/stm32/Kconfig
index 458e7155a..5420f7138 100644
--- a/nuttx/arch/arm/src/stm32/Kconfig
+++ b/nuttx/arch/arm/src/stm32/Kconfig
@@ -500,7 +500,7 @@ config STM32_CAN1
default n
select CAN
select STM32_CAN
- depends on !STM32_VALUELINE
+ depends on !STM32_VALUELINE && !STM32_STM32L15XX
config STM32_CAN2
bool "CAN2"
@@ -586,11 +586,6 @@ config STM32_I2C3
depends on STM32_STM32F20XX || STM32_STM32F40XX
select STM32_I2C
-config STM32_IWDG
- bool "IWDG"
- default n
- select WATCHDOG
-
config STM32_OTGFS
bool "OTG FS"
default n
@@ -664,6 +659,7 @@ config STM32_SYSCFG
config STM32_TIM1
bool "TIM1"
default n
+ depends on !STM32_STM32L15XX
config STM32_TIM2
bool "TIM2"
@@ -693,7 +689,7 @@ config STM32_TIM7
config STM32_TIM8
bool "TIM8"
default n
- depends on !STM32_VALUELINE
+ depends on !STM32_VALUELINE && !STM32_STM32L15XX
config STM32_TIM9
bool "TIM9"
@@ -767,14 +763,14 @@ config STM32_USART3
config STM32_UART4
bool "UART4"
default n
- depends on !STM32_STM32F30XX
+ depends on !STM32_STM32F30XX &&!STM32_STM32L15XX
select ARCH_HAVE_UART4
select STM32_USART
config STM32_UART5
bool "UART5"
default n
- depends on !STM32_STM32F30XX
+ depends on !STM32_STM32F30XX &&!STM32_STM32L15XX
select ARCH_HAVE_UART5
select STM32_USART
@@ -805,6 +801,16 @@ config STM32_USB
depends on (STM32_STM32F10XX && !STM32_VALUELINE) || STM32_STM32L15XX || STM32_STM32F30XX
select USBDEV
+config STM32_LCD
+ bool "Segment LCD"
+ default n
+ depends on STM32_STM32L15XX
+
+config STM32_IWDG
+ bool "IWDG"
+ default n
+ select WATCHDOG
+
config STM32_WWDG
bool "WWDG"
default n
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_lcd.h b/nuttx/arch/arm/src/stm32/chip/stm32_lcd.h
index d79348bcf..70d6be548 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32_lcd.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_lcd.h
@@ -125,7 +125,7 @@
# define LCD_CR_BIAS_1TO4 (0 << LCD_CR_BIAS_SHIFT) /* 00: Bias 1/4 */
# define LCD_CR_BIAS_1TO2 (1 << LCD_CR_BIAS_SHIFT) /* 01: Bias 1/2 */
# define LCD_CR_BIAS_1TO3 (2 << LCD_CR_BIAS_SHIFT) /* 10: Bias 1/3 */
-#define LCD_CR_MUX_SEG (1 << 7) /* Bit 7: Mux segment enable
+#define LCD_CR_MUX_SEG (1 << 7) /* Bit 7: Mux segment enable */
/* Bits 8-31 Reserved */
/* LCD frame control register */
@@ -181,7 +181,7 @@
# define LCD_FCR_PS_DIV8192 (13 << LCD_FCR_PS_SHIFT) /* 0011: ck_ps = LCDCLK/8192 */
# define LCD_FCR_PS_DIV16384 (14 << LCD_FCR_PS_SHIFT) /* 0011: ck_ps = LCDCLK/16384 */
# define LCD_FCR_PS_DIV32768 (15 << LCD_FCR_PS_SHIFT) /* 0011: ck_ps = LCDCLK/32768 */
- /* Bits 26-31 Reserved
+ /* Bits 26-31 Reserved */
/* LCD status register */
@@ -191,14 +191,14 @@
#define LCD_SR_UDD (1 << 3) /* Bit 3: Update Display Done */
#define LCD_SR_RDY (1 << 4) /* Bit 4: Ready flag */
#define LCD_SR_FCRSF (1 << 5) /* Bit 5: LCD Frame Control Register Synchronization flag */
- /* Bits 6-31 Reserved
+ /* Bits 6-31 Reserved */
/* LCD clear register */
/* Bit 0 Reserved */
#define LCD_CLR_SOFC (1 << 1) /* Bit 1: Start of frame flag clear */
/* Bit 2 Reserved */
-#define LCD_CLR_UDDC (1 << 2) /* Bit 3: Update display done clear
+#define LCD_CLR_UDDC (1 << 2) /* Bit 3: Update display done clear */
/* Bits 31:2-31 Reserved */
/* LCD display memory, COMn, S00-S31 */
diff --git a/nuttx/configs/stm32ldiscovery/README.txt b/nuttx/configs/stm32ldiscovery/README.txt
index 734505f5c..308dec381 100644
--- a/nuttx/configs/stm32ldiscovery/README.txt
+++ b/nuttx/configs/stm32ldiscovery/README.txt
@@ -1,22 +1,22 @@
README
======
-This README discusses issues unique to NuttX configurations for the
-STMicro STM32L-Discovery development board. The STM32L-Discovery board
-is based on the STM32L152RBT6 MCU (128KB FLASH and 16KB of SRAM).
+ This README discusses issues unique to NuttX configurations for the
+ STMicro STM32L-Discovery development board. The STM32L-Discovery board
+ is based on the STM32L152RBT6 MCU (128KB FLASH and 16KB of SRAM).
-The STM32L-Discovery and 32L152CDISCOVERY kits are functionally
-equivalent. The difference is the internal Flash memory size (STM32L152RBT6
-with 128 Kbytes or STM32L152RCT6 with 256 Kbytes).
+ The STM32L-Discovery and 32L152CDISCOVERY kits are functionally
+ equivalent. The difference is the internal Flash memory size (STM32L152RBT6
+ with 128 Kbytes or STM32L152RCT6 with 256 Kbytes).
-Both boards feature:
+ Both boards feature:
- - An ST-LINK/V2 embedded debug tool interface,
- - LCD (24 segments, 4 commons),
- - LEDs,
- - Pushbuttons,
- - A linear touch sensor, and
- - Four touchkeys.
+ - An ST-LINK/V2 embedded debug tool interface,
+ - LCD (24 segments, 4 commons),
+ - LEDs,
+ - Pushbuttons,
+ - A linear touch sensor, and
+ - Four touchkeys.
Contents
========
@@ -395,107 +395,114 @@ NXFLAT Toolchain
LEDs
====
-The STM32L-Discovery board has four LEDs. Two of these are controlled by
-logic on the board and are not available for software control:
-
-LD1 COM: LD2 default status is red. LD2 turns to green to indicate that
- communications are in progress between the PC and the ST-LINK/V2.
-LD2 PWR: Red LED indicates that the board is powered.
-
-And two LEDs can be controlled by software:
-
-User LD3: Green LED is a user LED connected to the I/O PB7 of the STM32L152
- MCU.
-User LD4: Blue LED is a user LED connected to the I/O PB6 of the STM32L152
- MCU.
-
-These LEDs are not used by the board port unless CONFIG_ARCH_LEDS is
-defined. In that case, the usage by the board port is defined in
-include/board.h and src/up_leds.c. The LEDs are used to encode OS-related
-events as follows:
-
- SYMBOL Meaning LED state
- LED3 LED4
- ------------------- ----------------------- -------- --------
- LED_STARTED NuttX has been started OFF OFF
- LED_HEAPALLOCATE Heap has been allocated OFF OFF
- LED_IRQSENABLED Interrupts enabled OFF OFF
- LED_STACKCREATED Idle stack created ON OFF
- LED_INIRQ In an interrupt No change
- LED_SIGNAL In a signal handler No change
- LED_ASSERTION An assertion failed No change
- LED_PANIC The system has crashed OFF Blinking
- LED_IDLE STM32 is is sleep mode Not used
+ The STM32L-Discovery board has four LEDs. Two of these are controlled by
+ logic on the board and are not available for software control:
+
+ LD1 COM: LD2 default status is red. LD2 turns to green to indicate
+ that communications are in progress between the PC and the
+ ST-LINK/V2.
+ LD2 PWR: Red LED indicates that the board is powered.
+
+ And two LEDs can be controlled by software:
+
+ User LD3: Green LED is a user LED connected to the I/O PB7 of the
+ STM32L152 MCU.
+ User LD4: Blue LED is a user LED connected to the I/O PB6 of the
+ STM32L152 MCU.
+
+ These LEDs are not used by the board port unless CONFIG_ARCH_LEDS is
+ defined. In that case, the usage by the board port is defined in
+ include/board.h and src/up_leds.c. The LEDs are used to encode OS-related
+ events as follows:
+
+ SYMBOL Meaning LED state
+ LED3 LED4
+ ------------------- ----------------------- -------- --------
+ LED_STARTED NuttX has been started OFF OFF
+ LED_HEAPALLOCATE Heap has been allocated OFF OFF
+ LED_IRQSENABLED Interrupts enabled OFF OFF
+ LED_STACKCREATED Idle stack created ON OFF
+ LED_INIRQ In an interrupt No change
+ LED_SIGNAL In a signal handler No change
+ LED_ASSERTION An assertion failed No change
+ LED_PANIC The system has crashed OFF Blinking
+ LED_IDLE STM32 is is sleep mode Not used
Serial Console
==============
-The STM32L-Discovery has no on-board RS-232 driver. Further, there are no
-USART pins that do not conflict with the on board resources, in particular,
-the LCD: Most USART pins are available if the LCD is enabled; USART2 may be
-used if either the LCD or the on-board LEDs are disabled.
+ The STM32L-Discovery has no on-board RS-232 driver. Further, there are no
+ USART pins that do not conflict with the on board resources, in particular,
+ the LCD: Most USART pins are available if the LCD is enabled; USART2 may
+ be used if either the LCD or the on-board LEDs are disabled.
- PA9 USART1_TX LCD glass COM1 P2, pin 22
- PA10 USART1_RX LCD glass COM2 P2, pin 21
- PB6 USART1_TX LED Blue P2, pin 8
- PB7 USART1_RX LED Green P2, pin 7
+ PA9 USART1_TX LCD glass COM1 P2, pin 22
+ PA10 USART1_RX LCD glass COM2 P2, pin 21
+ PB6 USART1_TX LED Blue P2, pin 8
+ PB7 USART1_RX LED Green P2, pin 7
- PA2 USART2_TX LCD SEG1 P1, pin 17
- PA3 USART2_RX LCD SEG2 P1, pin 18
+ PA2 USART2_TX LCD SEG1 P1, pin 17
+ PA3 USART2_RX LCD SEG2 P1, pin 18
- PB10 USART3_TX LCD SEG6 P1, pin 22
- PB11 USART3_RX LCD SEG7 P1, pin 23
- PC10 USART3_TX LCD SEG22 P2, pin 15
- PC11 USART3_RX LCD SEG23 P2, pin 14
+ PB10 USART3_TX LCD SEG6 P1, pin 22
+ PB11 USART3_RX LCD SEG7 P1, pin 23
+ PC10 USART3_TX LCD SEG22 P2, pin 15
+ PC11 USART3_RX LCD SEG23 P2, pin 14
-GND and (external) 5V are available on both P1 and P2. Note: These signals
-may be at lower voltage levels and, hence, may not properly drive an external
-RS-232 transceiver.
+ NOTES:
-NOTE: The crystal X3 is not installed on the STM32L3-Discovery. As a
-result, the HSE clock is not availabled and the less acurate HSI must be
-used. This may limit the accuracy of the computed baud, especially at
-higher BAUD. The HSI is supposedly calibrated in the factory to within 1%
-at room temperatures so perhaps this not a issue.
+ - GND and (external) 5V are available on both P1 and P2. Note: These
+ signals may be at lower voltage levels and, hence, may not properly
+ drive an external RS-232 transceiver.
-I have had no problems using the USART1 with PA9 and PA10 with a 3.3-5V
-RS-232 transceiver module at 57600 baud. I have not tried higher baud rates.
+ - The crystal X3 is not installed on the STM32L3-Discovery. As a result,
+ the HSE clock is not availabled and the less acurate HSI must be used.
+ This may limit the accuracy of the computed baud, especially at higher
+ BAUD. The HSI is supposedly calibrated in the factory to within 1% at
+ room temperatures so perhaps this not a issue.
-There is no support for a USB serial connector on the STM32L-Discovery board.
-The STM32L152 does support USB, but the USB pins are "free I/O" on the board
-and no USB connector is provided. So the use of a USB console is not option.
-If you need console output, you will need to disable either LCD (and use any
-USART) or the LEDs (and use USART1)
+ - According to the STM32L-Discovery User Manual, the LCD should be removed
+ from its socket if you use any of the LCD pins for any other purpose.
+
+ I have had no problems using the USART1 with PA9 and PA10 with a 3.3-5V
+ RS-232 transceiver module at 57600 baud. I have not tried higher baud
+ rates.
+
+ - There is no support for a USB serial connector on the STM32L-Discovery
+ board. The STM32L152 does support USB, but the USB pins are "free I/O"
+ on the board and no USB connector is provided. So the use of a USB
+ console is not option. If you need console output, you will need to
+ disable either LCD (and use any USART) or the LEDs (and use USART1)
Debugging
=========
-STM32 ST-LINK Utility
----------------------
-For simply writing to FLASH, I use the STM32 ST-LINK Utility. At least
-version 2.4.0 is required (older versions do not recognize the STM32 F3
-device). This utility is available from free from the STMicro website.
+ STM32 ST-LINK Utility
+ ---------------------
+ For simply writing to FLASH, I use the STM32 ST-LINK Utility. At least
+ version 2.4.0 is required (older versions do not recognize the STM32 F3
+ device). This utility is available from free from the STMicro website.
-Debugging
----------
-If you are going to use a debugger, you should make sure that the following
-settings are selection in your configuration file:
+ Debugging
+ ---------
+ If you are going to use a debugger, you should make sure that the following
+ settings are selection in your configuration file:
- CONFIG_DEBUG_SYMBOLS=y : Enable debug symbols in the build
- CONFIG_ARMV7M_USEBASEPRI=y : Use the BASEPRI register to disable interrupts
+ CONFIG_DEBUG_SYMBOLS=y : Enable debug symbols in the build
+ CONFIG_ARMV7M_USEBASEPRI=y : Use the BASEPRI register to disable interrupts
-OpenOCD
--------
-I am told that OpenOCD will work with the ST-Link, but I have never tried
-it.
+ OpenOCD
+ -------
+ I am told that OpenOCD will work with the ST-Link, but I have never tried
+ it.
-https://github.com/texane/stlink
---------------------------------
-This is an open source server for the ST-Link that I have never used.
+ https://github.com/texane/stlink
+ --------------------------------
+ This is an open source server for the ST-Link that I have never used.
-Atollic GDB Server
-------------------
-You can use the Atollic IDE, but I have never done that either.
+ Atollic GDB Server
+ ------------------
+ You can use the Atollic IDE, but I have never done that either.
STM32L-Discovery-specific Configuration Options
===============================================
@@ -693,20 +700,20 @@ STM32L-Discovery-specific Configuration Options
Configurations
==============
-Each STM32L-Discovery configuration is maintained in a sub-directory and
-can be selected as follow:
+ Each STM32L-Discovery configuration is maintained in a sub-directory and
+ can be selected as follow:
cd tools
./configure.sh STM32L-Discovery/<subdir>
cd -
. ./setenv.sh
-If this is a Windows native build, then configure.bat should be used
-instead of configure.sh:
+ If this is a Windows native build, then configure.bat should be used
+ instead of configure.sh:
configure.bat STM32L-Discovery\<subdir>
-Where <subdir> is one of the following:
+ Where <subdir> is one of the following:
nsh:
---
@@ -739,3 +746,9 @@ Where <subdir> is one of the following:
CONFIG_HOST_WINDOWS=y : Builds under Windows
CONFIG_WINDOWS_CYGWIN=y : Using Cygwin
CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYW=y : CodeSourcery for Windows
+
+ 5. To enable SLCD support:
+
+ CONFIG_ARCH_LEDS=y : Disable LED support
+ CONFIG_LIB_SLCDCODEC=y : Enable the SLCD CODEC
+ CONFIG_STM32_LCD=y : Enable the SLCD
diff --git a/nuttx/configs/stm32ldiscovery/nsh/Make.defs b/nuttx/configs/stm32ldiscovery/nsh/Make.defs
index 2987bb200..a47624868 100644
--- a/nuttx/configs/stm32ldiscovery/nsh/Make.defs
+++ b/nuttx/configs/stm32ldiscovery/nsh/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# configs/stm32f3discovery/nsh/Make.defs
+# configs/stm32l1discovery/nsh/Make.defs
#
# Copyright (C) 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/nuttx/configs/stm32ldiscovery/nsh/setenv.sh b/nuttx/configs/stm32ldiscovery/nsh/setenv.sh
index 0a1e71720..41d0f7606 100755
--- a/nuttx/configs/stm32ldiscovery/nsh/setenv.sh
+++ b/nuttx/configs/stm32ldiscovery/nsh/setenv.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# configs/stm32f3discovery/nsh/setenv.sh
+# configs/stm32l1discovery/nsh/setenv.sh
#
# Copyright (C) 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c b/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c
index 0538429fb..d5676baad 100644
--- a/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c
+++ b/nuttx/configs/stm32ldiscovery/src/stm32_lcd.c
@@ -4,6 +4,14 @@
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
*
+ * References:
+ * - Based on the NuttX LCD1602 driver.
+ * - "STM32L100xx, STM32L151xx, STM32L152xx and STM32L162xx advanced ARM-based
+ * 32-bit MCUs", STMicroelectronics, RM0038
+ * - "STM32L1 discovery kits: STM32L-DISCOVERY and 32L152CDISCOVERY,"
+ * STMicroelectronics, UM1079
+ * - STM32L-Discovery Firmware Pack V1.0.2 (for character encoding)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -42,15 +50,21 @@
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
+#include <string.h>
#include <semaphore.h>
#include <poll.h>
#include <errno.h>
#include <debug.h>
+#include <nuttx/ascii.h>
+#include <nuttx/streams.h>
#include <nuttx/fs/fs.h>
+#include <nuttx/lcd/slcd_codec.h>
#include "up_arch.h"
+#include "stm32_gpio.h"
#include "chip/stm32_lcd.h"
+
#include "stm32ldiscovery.h"
#ifdef CONFIG_STM32_LCD
@@ -60,10 +74,14 @@
****************************************************************************/
/* Configuration ************************************************************/
-/* Define CONFIG_DEBUG_LCD to enable detailed LCD debug output. Verbose debug must
- * also be enabled.
+/* Define CONFIG_DEBUG_LCD to enable detailed LCD debug output. Verbose debug
+ * must also be enabled.
*/
+#ifndef CONFIG_LIB_SLCDCODEC
+# error "This SLCD driver requires CONFIG_LIB_SLCDCODEC"
+#endif
+
#ifndef CONFIG_DEBUG
# undef CONFIG_DEBUG_VERBOSE
# undef CONFIG_DEBUG_GRAPHICS
@@ -74,6 +92,14 @@
# undef CONFIG_DEBUG_LCD
#endif
+#ifndef MIN
+# define MIN(a,b) (a < b ? a : b)
+#endif
+
+#ifndef MAX
+# define MAX(a,b) (a > b ? a : b)
+#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
@@ -84,19 +110,68 @@
* address:
*/
-#define LCD_OFFSET (STM32_LCD_BASE - STM32_PERIPH_BASE)
-#define LCD_BBADDR(o,b) (STM32_PERIPHBB_BASE + ((LCD_OFFSET + (o)) << 5) + ((b) << 2))
+#define SLCD_OFFSET (STM32_LCD_BASE - STM32_PERIPH_BASE)
+#define SLCD_BBADDR(o,b) (STM32_PERIPHBB_BASE + ((SLCD_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)
+#define SLCD_CR_LCDEN_BB SLCD_BBADDR(STM32_LCD_CR_OFFSET,0)
+#define SLCD_SR_UDR_BB SLCD_BBADDR(STM32_LCD_SR_OFFSET,2)
+
+/* LCD characteristics */
+
+#define SLCD_NCHARS 6
+
+/* An ASCII character may need to be decorated with a colon or decimal point */
+
+#define SCLD_DP 0x01
+#define SCLD_COLON 0x02
+
+/* Macros used for set/reset the LCD bar */
+
+#define SCLD_BAR0_ON g_slcdstate.bar[1] |= 8
+#define SCLD_BAR0_OFF g_slcdstate.bar[1] &= ~8
+#define SCLD_BAR1_ON g_slcdstate.bar[0] |= 8
+#define SCLD_BAR1_OFF g_slcdstate.bar[0] &= ~8
+#define SCLD_BAR2_ON g_slcdstate.bar[1] |= 2
+#define SCLD_BAR2_OFF g_slcdstate.bar[1] &= ~2
+#define SCLD_BAR3_ON g_slcdstate.bar[0] |= 2
+#define SCLD_BAR3_OFF g_slcdstate.bar[0] &= ~2
+
+/* These definitions support the logic of slcd_writemem() */
+
+#define SLCD_CHAR1_MASK 0xcffffffc
+#define SLCD_CHAR1_UPDATE(s) (((uint32_t)(s) & 0x0c) << 26) | \
+ ((uint32_t)(s) & 0x03)
+#define SLCD_CHAR2_MASK 0xf3ffff03
+#define SLCD_CHAR2_UPDATE(s) (((uint32_t)(s) & 0x0c) << 24) | \
+ (((uint32_t)(s) & 0x02) << 6) | \
+ (((uint32_t)(s) & 0x01) << 2)
+#define SLCD_CHAR3_MASK 0xfcfffcff
+#define SLCD_CHAR3_UPDATE(s) (((uint32_t)(s) & 0x0c) << 22) | \
+ (((uint32_t)(s) & 0x03) << 8)
+#define SLCD_CHAR4_MASK 0xffcff3ff
+#define SLCD_CHAR4_UPDATE(s) (((uint32_t)(s) & 0x0c) << 18) | \
+ (((uint32_t)(s) & 0x03) << 10)
+#define SLCD_CHAR5_MASKA 0xfff3cfff
+#define SLCD_CHAR5_MASKB 0xfff3efff
+#define SLCD_CHAR5_UPDATEA(s) (((uint32_t)(s) & 0x0c) << 16) | \
+ (((uint32_t)(s) & 0x03) << 12)
+#define SLCD_CHAR5_UPDATEB(s) (((uint32_t)(s) & 0x0c) << 16) | \
+ (((uint32_t)(s) & 0x01) << 12)
+#define SLCD_CHAR6_MASK 0xfffc3fff
+#define SLCD_CHAR6_UPDATEA(s) (((uint32_t)(s) & 0x04) << 15) | \
+ (((uint32_t)(s) & 0x08) << 13) | \
+ (((uint32_t)(s) & 0x03) << 14)
+#define SLCD_CHAR6_UPDATEB(s) (((uint32_t)(s) & 0x04) << 15) | \
+ (((uint32_t)(s) & 0x08) << 13) | \
+ (((uint32_t)(s) & 0x03) << 14)
/* Debug ********************************************************************/
#ifdef CONFIG_DEBUG_LCD
-# define lcddbg dbg
-# define lcdvdbg vdbg
+# define lcddbg dbg
+# define lcdvdbg vdbg
#else
# define lcddbg(x...)
# define lcdvdbg(x...)
@@ -106,23 +181,26 @@
* Private Type Definition
****************************************************************************/
-/* Indices into the g_lcdgpio[] array */
+/* SLCD incoming stream structure */
-enum stm32_gpio_e
+struct slcd_instream_s
{
- 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 lib_instream_s stream;
+ FAR const char *buffer;
+ ssize_t nbytes;
};
-struct stm32_lcd_s
+/* Global SLCD state */
+
+struct stm32_slcdstate_s
{
- bool initialized; /* True: Completed initialization sequence */
+ bool initialized; /* True: Completed initialization sequence */
+ uint8_t curpos; /* The current cursor position */
+ uint8_t buffer[SLCD_NCHARS]; /* SLCD ASCII content */
+ uint8_t options[SLCD_NCHARS]; /* With colon or decimal point decoration */
+#if 0 /* Not used */
+ uint8_t bar[2]; /* Controls the bars on the far right of the SLCD */
+#endif
};
/****************************************************************************
@@ -130,15 +208,25 @@ struct stm32_lcd_s
****************************************************************************/
/* Internal utilities */
-static void lcd_clear(void)
+static void slcd_clear(void);
+static int slcd_getstream(FAR struct lib_instream_s *instream);
+#if 0 /* Not used */
+static uint8_t slcd_getcontrast(void);
+static int slcd_setcontrast(uint8_t contrast);
+static void slcd_writebar(void);
+#endif
+static inline uint16_t slcd_mapch(uint8_t ch);
+static inline void slcd_writemem(uint16_t bitset, int curpos);
+static void slcd_writech(uint8_t ch, uint8_t curpos, uint8_t options);
+static inline void slcd_appendch(uint8_t ch, uint8_t options);
+static inline void slcd_action(enum slcdcode_e code, uint8_t count);
/* 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);
+static ssize_t slcd_read(FAR struct file *, FAR char *, size_t);
+static ssize_t slcd_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);
+static int slcd_poll(FAR struct file *filp, FAR struct pollfd *fds, bool setup);
#endif
/****************************************************************************
@@ -147,31 +235,102 @@ static int lcd_poll(FAR struct file *filp, FAR struct pollfd *fds,
/* This is the driver state structure (there is no retained state information) */
-static const struct file_operations g_lcdops =
+static const struct file_operations g_slcdops =
{
0, /* open */
0, /* close */
- lcd_read, /* read */
- lcd_write, /* write */
+ slcd_read, /* read */
+ slcd_write, /* write */
0, /* seek */
0 /* ioctl */
#ifndef CONFIG_DISABLE_POLL
- , lcd_poll /* poll */
+ , slcd_poll /* poll */
#endif
};
+/* LCD state data */
+
+static struct stm32_slcdstate_s g_slcdstate;
+
+/* LCD Mapping
+ *
+ * A
+ * --------- _
+ * |\ |J /| |_| COL
+ * F| H | K |B
+ * | \ | / | _
+ * --G-- --M-+ |_| COL
+ * | /| \ |
+ * E| Q | N |C
+ * | / |P \| _
+ * --------- |_| DP
+ * D
+ *
+ * LCD character 16-bit-encoding:
+ * { E , D , P , N, M , C , COL , DP, B , A , K , J, G , F , Q , H }
+ */
+
+#warning "Encodings for all punctuation are incomplete"
+
+/* Space and ASCII punctuation: 0x20-0x2f */
+
+static const uint16_t g_slcdpunct1[ASCII_0 - ASCII_SPACE] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* <space> ! " # $ % & ' */
+ 0x0000, 0x0000, 0xa0dd, 0x0000, 0x0000, 0xa000, 0x0000, 0x00c0 /* () * + , - . / */
+};
+
+/* ASCII numerals 0-9: 0x30-0x39 */
+
+static const uint16_t g_slcdnummap[ASCII_COLON - ASCII_0] =
+{
+ 0x5f00, 0x4200, 0xf500, 0x6700, 0xea00, 0xaf00, 0xbf00, 0x4600, /* 0-7 */
+ 0xff00, 0xef00 /* 8-9 */
+};
+
+/* ASCII punctuation: 0x3a-0x40 */
+
+static const uint16_t g_slcdpunct2[ASCII_A - ASCII_COLON] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /* : ; < = > ? @ */
+};
+
+/* Upper case letters A-Z: 0x41-0x5a. Also lower case letters a-z: 0x61-0x7a */
+
+static const uint16_t g_slcdalphamap[ASCII_LBRACKET - ASCII_A] =
+{
+ 0xfe00, 0x6714, 0x1d00, 0x4714, 0x9d00, 0x9c00, 0x3f00, 0xfa00, /* A-H */
+ 0x0014, 0x5300, 0x9841, 0x1900, 0x5a48, 0x5a09, 0x5f00, 0xfc00, /* I-P */
+ 0x5f01, 0xfc01, 0xaf00, 0x0414, 0x5b00, 0x18c0, 0x5a81, 0x00c9, /* Q-X */
+ 0x0058, 0x05c0 /* y-Z */
+};
+
+/* ASCII punctuation: 0x5b-0x60 */
+
+static const uint16_t g_slcdpunct3[ASCII_a - ASCII_LBRACKET] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /* [ \ ] ^ _ <right quote> */
+};
+
+/* ASCII punctuation: 0x7b-0x7e */
+
+static const uint16_t g_slcdpunct4[ASCII_DEL - ASCII_LBRACE]=
+{
+ 0x0000, 0x0000, 0x0000, 0x0000 /* { | } ~ */
+};
+
/* All GPIOs that need to be configured for the STM32L-Discovery LCD */
-static uint32_t g_lcdgpio[BOARD_LCD_NGPIOS] =
+static uint32_t g_slcdgpio[BOARD_SLCD_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
+ BOARD_SLCD_COM0, BOARD_SLCD_COM1, BOARD_SLCD_COM2, BOARD_SLCD_COM3,
+
+ BOARD_SLCD_SEG0, BOARD_SLCD_SEG1, BOARD_SLCD_SEG2, BOARD_SLCD_SEG3,
+ BOARD_SLCD_SEG4, BOARD_SLCD_SEG5, BOARD_SLCD_SEG6, BOARD_SLCD_SEG7,
+ BOARD_SLCD_SEG8, BOARD_SLCD_SEG9, BOARD_SLCD_SEG10, BOARD_SLCD_SEG11,
+ BOARD_SLCD_SEG12, BOARD_SLCD_SEG13, BOARD_SLCD_SEG14, BOARD_SLCD_SEG15,
+ BOARD_SLCD_SEG16, BOARD_SLCD_SEG17, BOARD_SLCD_SEG18, BOARD_SLCD_SEG19,
+ BOARD_SLCD_SEG20, BOARD_SLCD_SEG21, BOARD_SLCD_SEG22, BOARD_SLCD_SEG23
};
/****************************************************************************
@@ -179,17 +338,12 @@ static uint32_t g_lcdgpio[BOARD_LCD_NGPIOS] =
****************************************************************************/
/****************************************************************************
- * Name: lcd_clear
- ****************************************************************************/
-
-/****************************************************************************
- * Name: lcd_clear
+ * Name: slcd_clear
****************************************************************************/
-static void lcd_clear(void)
+static void slcd_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
@@ -200,40 +354,728 @@ static void lcd_clear(void)
/* Write all zerios in to the LCD RAM */
- for (regaddr = STM32_LCD_RAML(0); i <= STM32_LCD_RAMH(7); regaddr++)
+ for (regaddr = STM32_LCD_RAML(0); regaddr <= STM32_LCD_RAMH(7); regaddr++)
{
putreg32(0, regaddr);
}
+ /* Set all buffered data to undecorated spaces and home the cursor */
+
+ memset(g_slcdstate.buffer, ' ', SLCD_NCHARS);
+ memset(g_slcdstate.options, 0, SLCD_NCHARS);
+ g_slcdstate.curpos = 0;
+
+ /* Set the UDR bit to transfer the updated data to the second level
+ * buffer.
+ */
+
+ putreg32(1, SLCD_SR_UDR_BB);
+}
+
+/****************************************************************************
+ * Name: slcd_getstream
+ *
+ * Description:
+ * Get one character from the keyboard.
+ *
+ ****************************************************************************/
+
+static int slcd_getstream(FAR struct lib_instream_s *instream)
+{
+ FAR struct slcd_instream_s *slcdstream = (FAR struct slcd_instream_s *)instream;
+
+ DEBUGASSERT(slcdstream && slcdstream->buffer);
+ if (slcdstream->nbytes > 0)
+ {
+ slcdstream->nbytes--;
+ slcdstream->stream.nget++;
+ return (int)*slcdstream->buffer++;
+ }
+
+ return EOF;
+}
+
+/****************************************************************************
+ * Name: slcd_getcontrast
+ ****************************************************************************/
+
+#if 0 /* Not used */
+static uint8_t slcd_getcontrast(void)
+{
+ return (getreg32(STM32_LCD_FCR) & LCD_FCR_CC_MASK) >> LCD_FCR_CC_SHIFT;
+}
+#endif
+
+/****************************************************************************
+ * Name: slcd_setcontrast
+ ****************************************************************************/
+
+#if 0 /* Not used */
+static int slcd_setcontrast(uint8_t contrast)
+{
+ uint2_t regval;
+ int ret = OK;
+
+ /* Make sure that the contrast setting is within range */
+
+ if (contrast > 7)
+ {
+ contrast = 7;
+ ret = -ERANGE;
+ }
+
+ regval = getreg32(STM32_LCD_FCR);
+ regval &= !LCD_FCR_CC_MASK;
+ regval |= contrast << LCD_FCR_CC_SHIFT;
+ putreg32(regval, STM32_LCD_FCR);
+}
+#endif
+
+/****************************************************************************
+ * Name: slcd_writebar
+ ****************************************************************************/
+
+#if 0 /* Not used */
+static void slcd_writebar(void)
+{
+ uint32_t regval;
+
+ /* 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);
+
+ /* Update the BAR */
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= 0xffff5fff;
+ regval |= (uint32_t)(g_slcdstate.bar[0] << 12);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= 0xffff5fff;
+ regval |= (uint32_t)(g_slcdstate.bar[1] << 12);
+ putreg32(regval, STM32_LCD_RAM3L);
+
+
+ /* Set the UDR bit to transfer the updated data to the second level
+ * buffer.
+ */
+
+ putreg32(1, SLCD_SR_UDR_BB);
+}
+#endif
+
+/****************************************************************************
+ * Name: slcd_mapch
+ ****************************************************************************/
+
+static inline uint16_t slcd_mapch(uint8_t ch)
+{
+ /* ASCII control characters, the forward delete character, period, colon,
+ * and all 8-bit ASCII character have already been handled prior to this
+ * function.
+ */
+
+ /* Return spaces all control characters (this should not happen) */
+
+ if (ch < ASCII_SPACE)
+ {
+ return 0x0000;
+ }
+
+ /* Handle space and the first block of puncutation */
+
+ if (ch < ASCII_0)
+ {
+ return g_slcdpunct1[(int)ch - ASCII_SPACE];
+ }
+
+ /* Handle numbers */
+
+ else if (ch < ASCII_COLON)
+ {
+ return g_slcdnummap[(int)ch - ASCII_0];
+ }
+
+ /* Handle the next block of puncutation */
+
+ else if (ch < ASCII_A)
+ {
+ return g_slcdpunct2[(int)ch - ASCII_COLON];
+ }
+
+ /* Handle upper case letters */
+
+ else if (ch < ASCII_LBRACKET)
+ {
+ return g_slcdnummap[(int)ch - ASCII_A];
+ }
+
+ /* Handle the next block of puncutation */
+
+ else if (ch < ASCII_a)
+ {
+ return g_slcdpunct3[(int)ch - ASCII_LBRACKET];
+ }
+
+ /* Handle lower case letters (by mapping them to upper case */
+
+ else if (ch < ASCII_LBRACE)
+ {
+ return g_slcdnummap[(int)ch - ASCII_a];
+ }
+
+ /* Handle the final block of puncutation */
+
+ else if (ch < ASCII_DEL)
+ {
+ return g_slcdpunct4[(int)ch - ASCII_LBRACE];
+ }
+
+ /* Ignore 8-bit ASCII and DEL (this should not happen) */
+
+ return 0x0000;
+}
+
+/****************************************************************************
+ * Name: slcd_writemem
+ ****************************************************************************/
+
+static inline void slcd_writemem(uint16_t bitset, int curpos)
+{
+ uint32_t regval;
+ uint8_t segments[4];
+ int i;
+ int j;
+
+ /* Isolate the least significant bits */
+
+ for (i = 12, j = 0; j < 4; i -= 4, j++)
+ {
+ segments[j] = (bitset >> i) & 0x0f;
+ }
+
+ /* 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);
+
+ /* Now update the SLCD memory for the character at this cursor position by
+ * decoding the bit-mapped value
+ */
+
+ switch (curpos)
+ {
+ case 0:
+ regval = getreg32(STM32_LCD_RAM0L);
+ regval &= SLCD_CHAR1_MASK;
+ regval |= SLCD_CHAR1_UPDATE(segments[0]);
+ putreg32(regval, STM32_LCD_RAM0L);
+
+ regval = getreg32(STM32_LCD_RAM1L);
+ regval &= SLCD_CHAR1_MASK;
+ regval |= SLCD_CHAR1_UPDATE(segments[1]);
+ putreg32(regval, STM32_LCD_RAM1L);
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= SLCD_CHAR1_MASK;
+ regval |= SLCD_CHAR1_UPDATE(segments[2]);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= SLCD_CHAR1_MASK;
+ regval |= SLCD_CHAR1_UPDATE(segments[3]);
+ putreg32(regval, STM32_LCD_RAM3L);
+ break;
+
+ case 1:
+ regval = getreg32(STM32_LCD_RAM0L);
+ regval &= SLCD_CHAR2_MASK;
+ regval |= SLCD_CHAR2_UPDATE(segments[0]);
+ putreg32(regval, STM32_LCD_RAM0L);
+
+ regval = getreg32(STM32_LCD_RAM1L);
+ regval &= SLCD_CHAR2_MASK;
+ regval |= SLCD_CHAR2_UPDATE(segments[1]);
+ putreg32(regval, STM32_LCD_RAM1L);
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= SLCD_CHAR2_MASK;
+ regval |= SLCD_CHAR2_UPDATE(segments[2]);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= SLCD_CHAR2_MASK;
+ regval |= SLCD_CHAR2_UPDATE(segments[3]);
+ putreg32(regval, STM32_LCD_RAM3L);
+ break;
+
+ case 2:
+ regval = getreg32(STM32_LCD_RAM0L);
+ regval &= SLCD_CHAR3_MASK;
+ regval |= SLCD_CHAR3_UPDATE(segments[0]);
+ putreg32(regval, STM32_LCD_RAM0L);
+
+ regval = getreg32(STM32_LCD_RAM1L);
+ regval &= SLCD_CHAR3_MASK;
+ regval |= SLCD_CHAR3_UPDATE(segments[1]);
+ putreg32(regval, STM32_LCD_RAM1L);
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= SLCD_CHAR3_MASK;
+ regval |= SLCD_CHAR3_UPDATE(segments[2]);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= SLCD_CHAR3_MASK;
+ regval |= SLCD_CHAR3_UPDATE(segments[3]);
+ putreg32(regval, STM32_LCD_RAM3L);
+ break;
+
+ case 3:
+ regval = getreg32(STM32_LCD_RAM0L);
+ regval &= SLCD_CHAR4_MASK;
+ regval |= SLCD_CHAR4_UPDATE(segments[0]);
+ putreg32(regval, STM32_LCD_RAM0L);
+
+ regval = getreg32(STM32_LCD_RAM1L);
+ regval &= SLCD_CHAR4_MASK;
+ regval |= SLCD_CHAR4_UPDATE(segments[1]);
+ putreg32(regval, STM32_LCD_RAM1L);
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= SLCD_CHAR4_MASK;
+ regval |= SLCD_CHAR4_UPDATE(segments[2]);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= SLCD_CHAR4_MASK;
+ regval |= SLCD_CHAR4_UPDATE(segments[3]);
+ putreg32(regval, STM32_LCD_RAM3L);
+ break;
+
+ case 4:
+ regval = getreg32(STM32_LCD_RAM0L);
+ regval &= SLCD_CHAR5_MASKA;
+ regval |= SLCD_CHAR5_UPDATEA(segments[0]);
+ putreg32(regval, STM32_LCD_RAM0L);
+
+ regval = getreg32(STM32_LCD_RAM1L);
+ regval &= SLCD_CHAR5_MASKA;
+ regval |= SLCD_CHAR5_UPDATEA(segments[1]);
+ putreg32(regval, STM32_LCD_RAM1L);
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= SLCD_CHAR5_MASKB;
+ regval |= SLCD_CHAR5_UPDATEB(segments[2]);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= SLCD_CHAR5_MASKB;
+ regval |= SLCD_CHAR5_UPDATEB(segments[3]);
+ putreg32(regval, STM32_LCD_RAM3L);
+ break;
+
+ case 5:
+ regval = getreg32(STM32_LCD_RAM0L);
+ regval &= SLCD_CHAR6_MASK;
+ regval |= SLCD_CHAR6_UPDATEA(segments[0]);
+ putreg32(regval, STM32_LCD_RAM0L);
+
+ regval = getreg32(STM32_LCD_RAM1L);
+ regval &= SLCD_CHAR6_MASK;
+ regval |= SLCD_CHAR6_UPDATEA(segments[1]);
+ putreg32(regval, STM32_LCD_RAM1L);
+
+ regval = getreg32(STM32_LCD_RAM2L);
+ regval &= SLCD_CHAR6_MASK;
+ regval |= SLCD_CHAR6_UPDATEB(segments[2]);
+ putreg32(regval, STM32_LCD_RAM2L);
+
+ regval = getreg32(STM32_LCD_RAM3L);
+ regval &= SLCD_CHAR6_MASK;
+ regval |= SLCD_CHAR6_UPDATEB(segments[3]);
+ putreg32(regval, STM32_LCD_RAM3L);
+ break;
+
+ default:
+ return;
+ }
+
/* Set the UDR bit to transfer the updated data to the second level
* buffer.
*/
- putreg32(1, LCD_SR_UDR_BB);
+ putreg32(1, SLCD_SR_UDR_BB);
}
/****************************************************************************
- * Name: lcd_read
+ * Name: slcd_writech
****************************************************************************/
-static ssize_t lcd_read(FAR struct file *filp, FAR char *buffer, size_t len)
+static void slcd_writech(uint8_t ch, uint8_t curpos, uint8_t options)
{
+ uint16_t bitset;
+
+ /* Map the character code to a 16-bit encoded value */
+
+ bitset = slcd_mapch(ch);
+
+ /* Check if the character should be decorated with a decimal point or colon */
+
+ if ((options & SCLD_DP) != 0)
+ {
+ bitset |= 0x0002;
+ }
+ else if ((options & SCLD_DP) != 0)
+ {
+ bitset |= 0x0020;
+ }
+
+ /* Decode the value and write it to the SLCD segment memory */
+
+ slcd_writemem(bitset, curpos);
+
+ /* Save these values in the state structure */
+
+ g_slcdstate.buffer[curpos] = ch;
+ g_slcdstate.options[curpos] = options;
+}
+
+/****************************************************************************
+ * Name: slcd_appendch
+ ****************************************************************************/
+
+static void slcd_appendch(uint8_t ch, uint8_t options)
+{
+ /* Write the character at the current cursor position */
+
+ slcd_writech(ch, g_slcdstate.curpos, options);
+ if (g_slcdstate.curpos < (SLCD_NCHARS - 1))
+ {
+ g_slcdstate.curpos++;
+ }
}
/****************************************************************************
- * Name: lcd_write
+ * Name: slcd_action
****************************************************************************/
-static ssize_t lcd_write(FAR struct file *filp, FAR const char *buffer, size_t len)
+static void slcd_action(enum slcdcode_e code, uint8_t count)
{
+ switch (code)
+ {
+ /* Erasure */
+
+ case SLCDCODE_BACKDEL: /* Backspace (backward delete) N characters */
+ {
+ /* If we are at the home position, then ignore the action */
+
+ if (g_slcdstate.curpos < 1)
+ {
+ break;
+ }
+
+ /* Otherwise, BACKDEL is like moving the cursor back one then doing a
+ * forward deletion. Decrement the cursor position and fall through.
+ */
+
+ g_slcdstate.curpos--;
+ }
+
+ case SLCDCODE_FWDDEL: /* DELete (forward delete) N characters moving text */
+ {
+ int i;
+
+ /* Move all characters after the current cursor position left by one */
+
+ for (i = g_slcdstate.curpos + 1; i < SLCD_NCHARS - 1; i++)
+ {
+ slcd_writech(g_slcdstate.buffer[i-1], i, g_slcdstate.options[i-1]);
+ }
+
+ /* Erase the last character on the display */
+
+ slcd_writech(' ', SLCD_NCHARS - 1, 0);
+ }
+ break;
+
+ case SLCDCODE_ERASE: /* Erase N characters from the cursor position */
+ {
+ int last;
+ int i;
+
+ /* Get the last position to clear and make sure that the last
+ * position is on the SLCD.
+ */
+
+ last = g_slcdstate.curpos + count - 1;
+ if (last >= SLCD_NCHARS)
+ {
+ last = SLCD_NCHARS - 1;
+ }
+
+ /* Erase N characters after the current cursor position left by one */
+
+ for (i = g_slcdstate.curpos; i < last; i++)
+ {
+ slcd_writech(' ', i, 0);
+ }
+ }
+ break;
+
+ case SLCDCODE_CLEAR: /* Home the cursor and erase the entire display */
+ {
+ /* This is like HOME followed by ERASEEOL. Home the cursor and
+ * fall through.
+ */
+
+ g_slcdstate.curpos = 0;
+ }
+
+ case SLCDCODE_ERASEEOL: /* Erase from the cursor position to the end of line */
+ {
+ int i;
+
+ /* Erasecharacters after the current cursor position to the end of the line */
+
+ for (i = g_slcdstate.curpos; i < SLCD_NCHARS; i++)
+ {
+ slcd_writech(' ', i, 0);
+ }
+ }
+ break;
+
+ /* Cursor movement */
+
+ case SLCDCODE_HOME: /* Cursor home */
+ {
+ g_slcdstate.curpos = 0;
+ }
+ break;
+
+ case SLCDCODE_END: /* Cursor end */
+ {
+ g_slcdstate.curpos = SLCD_NCHARS - 1;
+ }
+ break;
+
+ case SLCDCODE_LEFT: /* Cursor left by N characters */
+ {
+ /* Don't permit movement past the beginning of the SLCD */
+
+ if (g_slcdstate.curpos > 0)
+ {
+ g_slcdstate.curpos--;
+ }
+ }
+ break;
+
+ case SLCDCODE_RIGHT: /* Cursor right by N characters */
+ {
+ /* Don't permit movement past the lcd of the SLCD */
+
+ if (g_slcdstate.curpos < (SLCD_NCHARS - 1))
+ {
+ g_slcdstate.curpos++;
+ }
+ }
+ break;
+
+ case SLCDCODE_UP: /* Cursor up by N lines */
+ case SLCDCODE_DOWN: /* Cursor down by N lines */
+ case SLCDCODE_PAGEUP: /* Cursor up by N pages */
+ case SLCDCODE_PAGEDOWN: /* Cursor down by N pages */
+ break; /* Not supportable on this SLCD */
+
+ /* Blinking */
+
+ case SLCDCODE_BLINKSTART: /* Start blinking with current cursor position */
+ case SLCDCODE_BLINKEND: /* End blinking after the current cursor position */
+ case SLCDCODE_BLINKOFF: /* Turn blinking off */
+ break; /* Not implemented */
+
+ /* These are actually unreportable errors */
+
+ default:
+ case SLCDCODE_NORMAL: /* Not a special keycode */
+ break;
+ }
+}
+
+/****************************************************************************
+ * Name: slcd_read
+ ****************************************************************************/
+
+static ssize_t slcd_read(FAR struct file *filp, FAR char *buffer, size_t len)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < SLCD_NCHARS && ret < len; i++)
+ {
+ /* Return the character */
+
+ *buffer++ = g_slcdstate.buffer[i];
+ ret++;
+
+ /* Check if the character is decorated with a folling period or colon */
+
+ if (ret < len && g_slcdstate.buffer[i] != 0)
+ {
+ if ((g_slcdstate.buffer[i] & SCLD_DP) != 0)
+ {
+ *buffer++ = '.';
+ ret++;
+ }
+ else if ((g_slcdstate.buffer[i] & SCLD_COLON) != 0)
+ {
+ *buffer++ = ':';
+ ret++;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: slcd_write
+ ****************************************************************************/
+
+static ssize_t slcd_write(FAR struct file *filp,
+ FAR const char *buffer, size_t len)
+{
+ struct slcd_instream_s instream;
+ struct slcdstate_s state;
+ enum slcdret_e result;
+ uint8_t ch;
+ uint8_t count;
+ uint8_t prev = ' ';
+ bool valid = false;
+
+ /* Initialize the stream for use with the SLCD CODEC */
+
+ instream.stream.get = slcd_getstream;
+ instream.stream.nget = 0;
+ instream.buffer = buffer;
+ instream.nbytes = len;
+
+ /* Prime the pump */
+
+ memset(&state, 0, sizeof(struct slcdstate_s));
+ result = slcd_decode(&instream.stream, &state, &prev, &count);
+ switch (result)
+ {
+ case SLCDRET_CHAR:
+ valid = true;
+ break;
+
+ case SLCDRET_SPEC:
+ {
+ slcd_action((enum slcdcode_e)prev, count);
+ prev = ' ';
+ }
+ break;
+
+ case SLCDRET_EOF:
+ return 0;
+ }
+
+ /* Now decode and process every byte in the input buffer */
+
+ while ((result = slcd_decode(&instream.stream, &state, &ch, &count)) != SLCDRET_EOF)
+ {
+ if (result == SLCDRET_CHAR) /* A normal character was returned */
+ {
+ /* Check for ASCII control characters */
+
+ if (ch < ASCII_SPACE)
+ {
+ /* All are ignored except for backspace and carriage return */
+
+ if (ch == ASCII_BS)
+ {
+ slcd_action(SLCDCODE_BACKDEL, 1);
+ }
+ else if (ch == ASCII_CR)
+ {
+ slcd_action(SLCDCODE_HOME, 0);
+ }
+ }
+
+ /* Handle characters decoreated with a period or a colon */
+
+ else if (ch == '.')
+ {
+ /* Write the previous character with the decimal point appended */
+
+ slcd_appendch(prev, SCLD_DP);
+ prev = ' ';
+ valid = false;
+ }
+ else if (ch == ':')
+ {
+ /* Write the previous character with the colon appended */
+
+ slcd_appendch(prev, SCLD_COLON);
+ prev = ' ';
+ valid = false;
+ }
+
+ /* Handle ASCII_DEL */
+
+ else if (ch == ASCII_DEL)
+ {
+ slcd_action(SLCDCODE_FWDDEL, 1);
+ }
+
+ /* The rest of the 7-bit ASCII characters are fair game */
+
+ else if (ch < 128)
+ {
+ /* Write the previous character if it valid */
+
+ if (valid)
+ {
+ slcd_appendch(prev, 0);
+ }
+
+ /* There is now a valid output character */
+
+ prev = ch;
+ valid = true;
+ }
+ }
+ else /* (result == SLCDRET_SPEC) */ /* A special SLCD action was returned */
+ {
+ slcd_action((enum slcdcode_e)ch, count);
+ }
+ }
+
+ /* Handle any unfinished output */
+
+ if (valid)
+ {
+ slcd_appendch(prev, 0);
+ }
+
+ /* Assume that the entire input buffer was processed */
+
+ return (ssize_t)len;
}
/****************************************************************************
- * Name: lcd_poll
+ * Name: slcd_poll
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
-static int lcd_poll(FAR struct file *filp, FAR struct pollfd *fds,
+static int slcd_poll(FAR struct file *filp, FAR struct pollfd *fds,
bool setup)
{
if (setup)
@@ -256,14 +1098,15 @@ static int lcd_poll(FAR struct file *filp, FAR struct pollfd *fds,
****************************************************************************/
/****************************************************************************
- * Name: stm32_lcd_initialize
+ * Name: stm32_slcd_initialize
*
* Description:
- * Initialize the LCD1602 hardware and register the character driver.
+ * Initialize the STM32L-Discovery hardware and register the character
+ * driver.
*
****************************************************************************/
-int stm32_lcd_initialize(void)
+int stm32_slcd_initialize(void)
{
uint32_t regval;
int ret = OK;
@@ -271,15 +1114,15 @@ int stm32_lcd_initialize(void)
/* Only initialize the driver once. */
- if (!g_lcdops.initialized)
+ if (!g_slcdstate.initialized)
{
lcdvdbg("Initializing\n");
/* Configure LCD GPIO pins */
- for (i = 0; i < BOARD_LCD_NGPIOS; i++);
+ for (i = 0; i < BOARD_SLCD_NGPIOS; i++)
{
- stm32_configgpio(g_lcdgpio[i]);
+ stm32_configgpio(g_slcdgpio[i]);
}
/* Set the LCD prescaler and divider values */
@@ -329,7 +1172,7 @@ int stm32_lcd_initialize(void)
/* Enable LCD peripheral */
- putreg32(1, LCD_CR_LCDEN_BB);
+ putreg32(1, SLCD_CR_LCDEN_BB);
/* Wait Until the LCD is enabled and the LCD booster is ready */
@@ -344,12 +1187,12 @@ int stm32_lcd_initialize(void)
/* Register the LCD device driver */
- ret = register_driver("/dev/slcd", &g_lcdops, 0644, &g_lcdops);
- g_lcdops.initialized = true;
+ ret = register_driver("/dev/slcd", &g_slcdops, 0644, (FAR struct file_operations *)&g_slcdops);
+ g_slcdstate.initialized = true;
/* Then clear the display */
- lcd_clear();
+ slcd_clear();
}
return ret;
diff --git a/nuttx/configs/stm32ldiscovery/src/stm32ldiscovery.h b/nuttx/configs/stm32ldiscovery/src/stm32ldiscovery.h
index 36a48b998..7d5c10988 100644
--- a/nuttx/configs/stm32ldiscovery/src/stm32ldiscovery.h
+++ b/nuttx/configs/stm32ldiscovery/src/stm32ldiscovery.h
@@ -186,38 +186,38 @@
* 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_SLCD_COM0 GPIO_LCD_COM0 /* PA8 */
+#define BOARD_SLCD_COM1 GPIO_LCD_COM1 /* PA9 */
+#define BOARD_SLCD_COM2 GPIO_LCD_COM2 /* PA10 */
+#define BOARD_SLCD_COM3 GPIO_LCD_COM3 /* PB9 */
+#define BOARD_SLCD_SEG0 GPIO_LCD_SEG0 /* PA1 */
+#define BOARD_SLCD_SEG1 GPIO_LCD_SEG1 /* PA2 */
+#define BOARD_SLCD_SEG2 GPIO_LCD_SEG2 /* PA3 */
+#define BOARD_SLCD_SEG3 GPIO_LCD_SEG7 /* PB3 */
+#define BOARD_SLCD_SEG4 GPIO_LCD_SEG8 /* PB4 */
+#define BOARD_SLCD_SEG5 GPIO_LCD_SEG9 /* PB5 */
+#define BOARD_SLCD_SEG6 GPIO_LCD_SEG10 /* PB10 */
+#define BOARD_SLCD_SEG7 GPIO_LCD_SEG11 /* PB11 */
+#define BOARD_SLCD_SEG8 GPIO_LCD_SEG12 /* PB12 */
+#define BOARD_SLCD_SEG9 GPIO_LCD_SEG13 /* PB13 */
+#define BOARD_SLCD_SEG10 GPIO_LCD_SEG14 /* PB14 */
+#define BOARD_SLCD_SEG11 GPIO_LCD_SEG15 /* PB15 */
+#define BOARD_SLCD_SEG12 GPIO_LCD_SEG17 /* PA15 */
+#define BOARD_SLCD_SEG13 GPIO_LCD_SEG16 /* PB8 */
+#define BOARD_SLCD_SEG14 GPIO_LCD_SEG18 /* PC0 */
+#define BOARD_SLCD_SEG15 GPIO_LCD_SEG19 /* PC1 */
+#define BOARD_SLCD_SEG16 GPIO_LCD_SEG20 /* PC2 */
+#define BOARD_SLCD_SEG17 GPIO_LCD_SEG21 /* PC3 */
+#define BOARD_SLCD_SEG18 GPIO_LCD_SEG24 /* PC6 */
+#define BOARD_SLCD_SEG19 GPIO_LCD_SEG25 /* PC7 */
+#define BOARD_SLCD_SEG20 GPIO_LCD_SEG26 /* PC8 */
+#define BOARD_SLCD_SEG21 GPIO_LCD_SEG27 /* PC9 */
+#define BOARD_SLCD_SEG22 GPIO_LCD_SEG40 /* PC10 */
+#define BOARD_SLCD_SEG23 GPIO_LCD_SEG41 /* PC11 */
-#define BOARD LCD_NCOM 4
-#define BOARD LCD_NSEG 24
-#define BOARD_LCD_NGPIOS 28
+#define BOARD_SLCD_NCOM 4
+#define BOARD_SLCD_NSEG 24
+#define BOARD_SLCD_NGPIOS 28
/****************************************************************************************************
* Public Types
diff --git a/nuttx/include/nuttx/ascii.h b/nuttx/include/nuttx/ascii.h
index bfecff520..090d7a49a 100644
--- a/nuttx/include/nuttx/ascii.h
+++ b/nuttx/include/nuttx/ascii.h
@@ -150,8 +150,8 @@
#define ASCII_LBRACKET 0x5b /* Left bracket ([) */
#define ASCII_BACKSLASH 0x5c /* Back slash (\) */
#define ASCII_RBRACKET 0x5d /* Right bracket (]) */
-#define ASCII_CARET 0x5c /* Caret (^) */
-#define ASCII_CIRCUMFLEX 0x5c /* Circumflex (^) */
+#define ASCII_CARET 0x5e /* Caret (^) */
+#define ASCII_CIRCUMFLEX 0x5e /* Circumflex (^) */
#define ASCII_UNDERSCORE 0x5f /* Underscore (_) */
#define ASCII_RSQUOT 0x60 /* Closing single quote */
diff --git a/nuttx/include/nuttx/lcd/slcd_codec.h b/nuttx/include/nuttx/lcd/slcd_codec.h
index a43796718..4a9ff312d 100644
--- a/nuttx/include/nuttx/lcd/slcd_codec.h
+++ b/nuttx/include/nuttx/lcd/slcd_codec.h
@@ -66,8 +66,8 @@ enum slcdcode_e
* ASCII BKSP and DEL values.
*/
- SLCDCODE_FWDDEL, /* DELete (forward delete) N characters moving cursor */
- SLCDCODE_BACKDEL, /* Backspace (backward delete) N characters */
+ SLCDCODE_FWDDEL, /* DELete (forward delete) N characters moving text */
+ SLCDCODE_BACKDEL, /* Backspace (backward delete) N characters moving cursor */
SLCDCODE_ERASE, /* Erase N characters from the cursor position */
SLCDCODE_ERASEEOL, /* Erase from the cursor position to the end of line */
SLCDCODE_CLEAR, /* Home the cursor and erase the entire display */
diff --git a/nuttx/libc/misc/lib_slcddecode.c b/nuttx/libc/misc/lib_slcddecode.c
index 05e883f88..04e9e569e 100644
--- a/nuttx/libc/misc/lib_slcddecode.c
+++ b/nuttx/libc/misc/lib_slcddecode.c
@@ -330,19 +330,21 @@ enum slcdret_e slcd_decode(FAR struct lib_instream_s *stream,
return slcd_reget(state, pch, parg);
}
+ /* Put the character in the reget buffer because there is on more way
+ * that we can fail.
+ */
+
+ state->buf[NDX_CODE5] = (uint8_t)ch;
+ state->nch = NCH_CODE5;
+
/* Verify the special CLCD action code */
if (ch < (int)FIRST_SLCDCODE || ch > (int)LAST_SLCDCODE)
{
- /* Not a special command code.. put the character in the reget
- * buffer.
+ /* Not a special command code. Return the ESC now and the rest
+ * of the characters later.
*/
- state->buf[NDX_CODE5] = (uint8_t)ch;
- state->nch = NCH_CODE5;
-
- /* Return the ESC now and the next two characters later. */
-
return slcd_reget(state, pch, parg);
}
@@ -351,6 +353,15 @@ enum slcdret_e slcd_decode(FAR struct lib_instream_s *stream,
code = CODE_RETURN(ch);
count = slcd_nibble(state->buf[NDX_COUNTH]) << 4;
slcd_nibble(state->buf[NDX_COUNTL]);
+
+ /* All count values must be greater than 0 or something is wrong */
+
+ if (count < 1)
+ {
+ /* Return the ESC now and the rest of the characters later. */
+
+ return slcd_reget(state, pch, parg);
+ }
}
/* We have successfully parsed the the entire escape sequence. Return the