[update] lcd example uses libstm32l_discovery
authorFabien Le Mentec <texane@gmail.com>
Sun, 16 Oct 2011 16:05:46 +0000 (11:05 -0500)
committerFabien Le Mentec <texane@gmail.com>
Sun, 16 Oct 2011 16:05:46 +0000 (11:05 -0500)
doc/tutorial/tutorial.pdf
doc/tutorial/tutorial.tex
example/lcd/Makefile
example/lcd/discover_board.h [new file with mode: 0644]
example/lcd/main.c
example/lcd/stm32l_discovery_lcd.c [new file with mode: 0644]
example/lcd/stm32l_discovery_lcd.h [new file with mode: 0644]

index f62e4f406d73f29bf597fbfad6ba4806f168e721..b84d061f57921ebc02df6a11261675a97c3d31fa 100644 (file)
Binary files a/doc/tutorial/tutorial.pdf and b/doc/tutorial/tutorial.pdf differ
index 370eb7014f970105d9b1e5562d3ba51dfe2259fa..cef3632ac51a4cfefc36de88965c664dd3d0c78d 100644 (file)
@@ -178,6 +178,15 @@ $> make
 \end{lstlisting}
 \end{small}
 
+\paragraph{}
+An example using the library can be built using:\\
+\begin{small}
+\begin{lstlisting}[frame=tb]
+$> cd stlink.git/example/lcd
+$> make
+\end{lstlisting}
+\end{small}
+
 \newpage
 \section{References}
 \begin{itemize}
index eeb4813c24c8ac6308eeccc42e08ae7db749ea82..0febe491283e4cfb9b6b913f002ba8eb9df1e91a 100644 (file)
@@ -1,28 +1,37 @@
-EXECUTABLE=lcd.elf
-BIN_IMAGE=lcd.bin
+ELF=lcd.elf
 
 CC=arm-none-eabi-gcc
-OBJCOPY=arm-none-eabi-objcopy
 
 CFLAGS=-O2 -mlittle-endian -mthumb
 CFLAGS+=-mcpu=cortex-m3 -ffreestanding -nostdlib -nostdinc
 
+CFLAGS+=-I.
+
+# stm32l_discovery lib
+CFLAGS+=-I../libstm32l_discovery/inc
+CFLAGS+=-I../libstm32l_discovery/inc/base
+CFLAGS+=-I../libstm32l_discovery/inc/core_support
+CFLAGS+=-I../libstm32l_discovery/inc/device_support
+
 # to run from SRAM
 CFLAGS+=-Wl,-T,linker_stm32l.lds
 
-# to write to flash then run
-# CFLAGS+=-Wl,-Ttext,0x08000000 -Wl,-e,0x08000000
+SRCS=\
+main.c\
+stm32l_discovery_lcd.c
+
+OBJS=$(SRCS:.c=.o)
 
-all: $(BIN_IMAGE)
+all: $(ELF)
 
-$(BIN_IMAGE): $(EXECUTABLE)
-       $(OBJCOPY) -O binary $^ $@
+$(ELF): $(OBJS)
+       $(CC) $(CFLAGS) -o $@ $(OBJS) -L../libstm32l_discovery/build -lstm32l_discovery
 
-$(EXECUTABLE): main.c
-       $(CC) $(CFLAGS) $^ -o $@
+%.o: %.c
+       $(CC) $(CFLAGS) -c -o $@ $^
 
 clean:
-       rm -rf $(EXECUTABLE)
-       rm -rf $(BIN_IMAGE)
+       -rm -f $(OBJS)
+       -rm -f $(ELF)
 
 .PHONY: all clean
diff --git a/example/lcd/discover_board.h b/example/lcd/discover_board.h
new file mode 100644 (file)
index 0000000..9161768
--- /dev/null
@@ -0,0 +1,61 @@
+ /**\r
+  ******************************************************************************\r
+  * @file    discover_board.h\r
+  * @author  Microcontroller Division\r
+  * @version V1.0.2\r
+  * @date    September-2011\r
+  * @brief   Input/Output defines\r
+  ******************************************************************************\r
+  * @copy\r
+  *\r
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
+  *\r
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>\r
+  */\r
+\r
+/* Define to prevent recursive inclusion -------------------------------------*/\r
+\r
+#ifndef __DISCOVER_BOARD_H\r
+#define __DISCOVER_BOARD_H\r
+\r
+/* Includes ------------------------------------------------------------------*/\r
+#include "stm32l1xx.h"  \r
+\r
+#define bool _Bool\r
+#define FALSE 0\r
+#define TRUE !FALSE\r
+\r
+/* MACROs for SET, RESET or TOGGLE Output port */\r
+\r
+#define GPIO_HIGH(a,b)                 a->BSRRL = b\r
+#define GPIO_LOW(a,b)          a->BSRRH = b\r
+#define GPIO_TOGGLE(a,b)       a->ODR ^= b \r
+\r
+#define USERBUTTON_GPIO_PORT   GPIOA\r
+#define USERBUTTON_GPIO_PIN     GPIO_Pin_0\r
+#define USERBUTTON_GPIO_CLK     RCC_AHBPeriph_GPIOA\r
+\r
+#define LD_GPIO_PORT           GPIOB\r
+#define LD_GREEN_GPIO_PIN              GPIO_Pin_7\r
+#define LD_BLUE_GPIO_PIN             GPIO_Pin_6\r
+#define LD_GPIO_PORT_CLK             RCC_AHBPeriph_GPIOB\r
+\r
+#define CTN_GPIO_PORT           GPIOC\r
+#define CTN_CNTEN_GPIO_PIN      GPIO_Pin_13\r
+#define CTN_GPIO_CLK            RCC_AHBPeriph_GPIOC\r
+\r
+#define WAKEUP_GPIO_PORT        GPIOA\r
+\r
+#define IDD_MEASURE_PORT       GPIOA\r
+#define IDD_MEASURE             GPIO_Pin_4\r
+\r
+\r
+#endif\r
+\r
+\r
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/\r
index b693084887ad9070bef07e5a957fc2e980cc72ac..3713971a90db6f6bcd5066234974fad3ba9d1c95 100644 (file)
@@ -1,8 +1,23 @@
-/* this example is only for stm32l discover */
-
-typedef unsigned char uint8_t;
-typedef unsigned int uint32_t;
-
+/* this example is only for stm32l discover.
+   adapted from ST firmwares projects.
+ */
+
+/* base headers */
+#include "stdint.h"
+
+/* libstm32l_discovery headers */
+#include "stm32l1xx_gpio.h"
+#include "stm32l1xx_adc.h"
+#include "stm32l1xx_lcd.h"
+#include "stm32l1xx_rcc.h"
+#include "stm32l1xx_rtc.h"
+#include "stm32l1xx_exti.h"
+#include "stm32l1xx_pwr.h"
+#include "stm32l1xx_syscfg.h"
+#include "stm32l1xx_dbgmcu.h"
+
+/* lcd wrapper routines header */
+#include "stm32l_discovery_lcd.h"
 
 /* boot mode */
 
@@ -15,17 +30,14 @@ typedef unsigned int uint32_t;
    refer to CD00240193.pdf, GPIO.
 */
 
-#define GPIOA 0x40020000
-#define GPIOA_MODER (GPIOA + 0x00)
-#define GPIOA_ODR (GPIOA + 0x14)
+#define GPIOA_MODER (GPIOA_BASE + 0x00)
+#define GPIOA_ODR (GPIOA_BASE + 0x14)
 
-#define GPIOB 0x40020400
-#define GPIOB_MODER (GPIOB + 0x00)
-#define GPIOB_ODR (GPIOB + 0x14)
+#define GPIOB_MODER (GPIOB_BASE + 0x00)
+#define GPIOB_ODR (GPIOB_BASE + 0x14)
 
-#define GPIOC 0x40020800
-#define GPIOC_MODER (GPIOC + 0x00)
-#define GPIOC_ODR (GPIOC + 0x14)
+#define GPIOC_MODER (GPIOC_BASE + 0x00)
+#define GPIOC_ODR (GPIOC_BASE + 0x14)
 
 
 /* leds */
@@ -50,43 +62,212 @@ static inline void switch_leds_off(void)
 }
 
 
-/* lcd. refer to DM00027954.pdf. */
+#define delay()                                                \
+do {                                                   \
+  register unsigned int i;                             \
+  for (i = 0; i < 1000000; ++i)                                \
+    __asm__ __volatile__ ("nop\n\t":::"memory");       \
+} while (0)
+
+
+#if CONFIG_BOOT_SRAM
+
+extern uint32_t _fstack;
+
+static inline void setup_stack(void)
+{
+  /* setup the stack to point to _fstack (refer to ld script) */
+
+  static const uint32_t fstack = (uint32_t)&_fstack;
+
+  __asm__ __volatile__
+    (
+     "ldr sp, %0\n\t"
+     : 
+     : "m"(fstack)
+     : "sp"
+    );
+}
+
+#endif /* CONFIG_BOOT_SRAM */
+
+
+/* application related setup */
+
+static void RCC_Configuration(void)
+{  
+  /* Enable HSI Clock */
+  RCC_HSICmd(ENABLE);
+  
+  /*!< Wait till HSI is ready */
+  while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
+
+  /* Set HSI as sys clock*/
+  RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
+  
+  /* Set MSI clock range to ~4.194MHz*/
+  RCC_MSIRangeConfig(RCC_MSIRange_6);
+  
+  /* Enable the GPIOs clocks */
+  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC| RCC_AHBPeriph_GPIOD| RCC_AHBPeriph_GPIOE| RCC_AHBPeriph_GPIOH, ENABLE);     
+
+  /* Enable comparator, LCD and PWR mngt clocks */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_COMP | RCC_APB1Periph_LCD | RCC_APB1Periph_PWR,ENABLE);
+    
+  /* Enable ADC & SYSCFG clocks */
+  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_SYSCFG , ENABLE);
+
+  /* Allow access to the RTC */
+  PWR_RTCAccessCmd(ENABLE);
+
+  /* Reset RTC Backup Domain */
+  RCC_RTCResetCmd(ENABLE);
+  RCC_RTCResetCmd(DISABLE);
+
+  /* LSE Enable */
+  RCC_LSEConfig(RCC_LSE_ON);
+
+  /* Wait until LSE is ready */
+  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
+  
+   /* RTC Clock Source Selection */ 
+  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); 
+  
+  /* Enable the RTC */
+  RCC_RTCCLKCmd(ENABLE);   
+  
+  /*Disable HSE*/
+  RCC_HSEConfig(RCC_HSE_OFF);
+  if(RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET )
+  {
+    /* Stay in infinite loop if HSE is not disabled*/
+    while(1); 
+  }
+}
+
+static void Init_GPIOs(void)
+{
+#if 0 /* fixme: GPIO_Init raises a bug in some gcc toolchains */
+
+  /* GPIO, EXTI and NVIC Init structure declaration */
+  GPIO_InitTypeDef GPIO_InitStructure;
+
+#if 0
+  EXTI_InitTypeDef EXTI_InitStructure;
+  NVIC_InitTypeDef NVIC_InitStructure;
+#endif
 
 #if 0
+  /* Configure User Button pin as input */
+  GPIO_InitStructure.GPIO_Pin = USERBUTTON_GPIO_PIN;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
+  GPIO_Init(USERBUTTON_GPIO_PORT, &GPIO_InitStructure);
+#endif
 
-#define LCD_SEG0 PA1
-#define LCD_SEG1 PA2
-#define LCD_SEG2 PA3
-#define LCD_SEG3 PB3
-#define LCD_SEG4 PB4
-#define LCD_SEG5 PB5
-#define LCD_SEG6 PB10
-#define LCD_SEG7 PB11
-#define LCD_SEG8 PB12
-#define LCD_SEG9 PB13
-#define LCD_SEG10 PB14
-#define LCD_SEG11 PB15
-#define LCD_SEG12 PA15
-#define LCD_SEG13 PB8
-#define LCD_SEG14 PC0
-#define LCD_SEG15 PC1
-#define LCD_SEG16 PC2
-#define LCD_SEG17 PC3
-#define LCD_SEG18 PC6
-#define LCD_SEG19 PC7
-#define LCD_SEG20 PC8
-#define LCD_SEG21 PC9
-#define LCD_SEG22 PC10
-#define LCD_SEG23 PC11
-#define LCD_COM0 PA8
-#define LCD_COM1 PA9
-#define LCD_COM2 PA10
-#define LCD_COM3 PB9
+#if 0
+  /* Select User Button pin as input source for EXTI Line */
+  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
+
+  /* Configure EXT1 Line 0 in interrupt mode trigged on Rising edge */
+  EXTI_InitStructure.EXTI_Line = EXTI_Line0 ;  // PA0 for User button AND IDD_WakeUP
+  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
+  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
+  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
+  EXTI_Init(&EXTI_InitStructure);
+
+  /* Enable and set EXTI0 Interrupt to the lowest priority */
+  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure); 
+#endif
 
+#if 0
+  /* Configure the LED_pin as output push-pull for LD3 & LD4 usage*/
+  GPIO_InitStructure.GPIO_Pin = LD_GREEN_GPIO_PIN | LD_BLUE_GPIO_PIN;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+  GPIO_Init(LD_GPIO_PORT, &GPIO_InitStructure);
+  
+  /* Force a low level on LEDs*/ 
+  GPIO_LOW(LD_GPIO_PORT,LD_GREEN_GPIO_PIN);    
+  GPIO_LOW(LD_GPIO_PORT,LD_BLUE_GPIO_PIN);
+    
+  /* Counter enable: GPIO set in output for enable the counter */
+  GPIO_InitStructure.GPIO_Pin = CTN_CNTEN_GPIO_PIN;
+  GPIO_Init( CTN_GPIO_PORT, &GPIO_InitStructure);
+  
+  /* To prepare to start counter */
+  GPIO_HIGH(CTN_GPIO_PORT,CTN_CNTEN_GPIO_PIN);
+      
+  /* Configure Port A LCD Output pins as alternate function */
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 |GPIO_Pin_10 |GPIO_Pin_15;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_Init( GPIOA, &GPIO_InitStructure);
+  
+  /* Select LCD alternate function for Port A LCD Output pins */
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource8,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource15,GPIO_AF_LCD) ;  
+  
+  /* Configure Port B LCD Output pins as alternate function */ 
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 \
+                                 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;  
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_Init( GPIOB, &GPIO_InitStructure);
+  
+  /* Select LCD alternate function for Port B LCD Output pins */
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource3,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_LCD) ;  
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource12,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,GPIO_AF_LCD) ;   
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,GPIO_AF_LCD) ;   
 #endif
 
-static void setup_lcd(void)
-{
+#if 0  
+  /* Configure Port C LCD Output pins as alternate function */ 
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 \
+                                 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11 ;                               
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_Init( GPIOC, &GPIO_InitStructure);  
+
+  /* Select LCD alternate function for Port B LCD Output pins */
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource0,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1,GPIO_AF_LCD) ; 
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9,GPIO_AF_LCD) ;
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10,GPIO_AF_LCD) ; 
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11,GPIO_AF_LCD) ;  
+#endif
+  
+#if 0
+  /* Configure ADC (IDD_MEASURE) pin as Analogue */
+  GPIO_InitStructure.GPIO_Pin = IDD_MEASURE  ;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+  GPIO_Init( IDD_MEASURE_PORT, &GPIO_InitStructure);
+#endif
+
+#else /* fixme */
+
   /* set every port in digital output mode  */
 
   /* PA[1:3,8:10,15] */
@@ -125,187 +306,12 @@ static void setup_lcd(void)
     (1 << (9 * 2)) |
     (1 << (10 * 2)) |
     (1 << (11 * 2));
-}
-
-static inline void set_lcd_com(unsigned int i, unsigned int val)
-{
-  /* table for LCD_COM<N> */
-  static const uint32_t regs[4] = { GPIOA_ODR, GPIOA_ODR, GPIOA_ODR, GPIOB_ODR };
-  static const uint8_t bits[4] = { 8, 9, 10, 9 };
-
-  uint32_t tmp = *(volatile uint32_t*)regs[i];
-  tmp &= ~(1 << bits[i]);
-  tmp |= val << bits[i];
-  *(volatile uint32_t*)regs[i] = tmp;
-}
-
-static void clear_lcd(void)
-{
-  /* tables for LCD_SEG<N> */
-
-  static const uint32_t regs[24] =
-  {
-    GPIOA_ODR,
-    GPIOA_ODR,
-    GPIOA_ODR,
-
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-    GPIOB_ODR,
-
-    GPIOA_ODR,
-
-    GPIOB_ODR,
-
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR,
-    GPIOC_ODR
-  };
-
-  static const uint8_t bits[24] =
-  {
-    1,
-    2,
-    3,
-
-    3,
-    4,
-    5,
-    10,
-    11,
-    12,
-    13,
-    14,
-    15,
-
-    15,
-
-    8,
-
-    0,
-    1,
-    2,
-    3,
-    6,
-    7,
-    8,
-    9,
-    10,
-    11
-  };
-
-  /* foreach lcd selector, select and zero */
-  unsigned int i;
-  for (i = 0; i < sizeof(regs) / sizeof(regs[0]); ++i)
-  {
-    /* select */
-    *(volatile uint32_t*)regs[i] |= 1 << bits[i];
-
-    /* set segments */
-    set_lcd_com(0, 0);
-    set_lcd_com(1, 0);
-    set_lcd_com(2, 0);
-    set_lcd_com(3, 0);
 
-    /* deselect */
-    *(volatile uint32_t*)regs[i] &= ~(1 << bits[i]);
-  }
+#endif /* fixme */
 }
 
-static void update_lcd(void)
-{
-  static unsigned int state = 0;
-
-  clear_lcd();
-
-/*   if (state == 0) */
-  if (1)
-  {
-    /* left square (segments: 1A, 1B, 1C, 1D, 1E, 1F) */
-
-    /* 1A, 1B: PC10, COM0, COM1 */
-    *(volatile uint32_t*)GPIOC_ODR |= 1 << 10;
-    set_lcd_com(0, 1);
-    set_lcd_com(1, 1);
-    set_lcd_com(2, 0);
-    set_lcd_com(3, 0);
-    *(volatile uint32_t*)GPIOC_ODR &= ~(1 << 10);
-
-    /* 1C: PA2, COM1 */
-    *(volatile uint32_t*)GPIOA_ODR |= 1 << 2;
-    set_lcd_com(0, 0);
-    set_lcd_com(1, 1);
-    set_lcd_com(2, 0);
-    set_lcd_com(3, 0);
-    *(volatile uint32_t*)GPIOA_ODR &= ~(1 << 2);
-
-    /* 1D, 1E: PA1, COM0, COM1 */
-    *(volatile uint32_t*)GPIOA_ODR |= 1 << 1;
-    set_lcd_com(0, 1);
-    set_lcd_com(1, 1);
-    set_lcd_com(2, 0);
-    set_lcd_com(3, 0);
-    *(volatile uint32_t*)GPIOA_ODR &= ~(1 << 1);
-
-    /* 1F: PC11, COM1 */
-    *(volatile uint32_t*)GPIOC_ODR |= 1 << 11;
-    set_lcd_com(0, 0);
-    set_lcd_com(1, 1);
-    set_lcd_com(2, 0);
-    set_lcd_com(3, 0);
-    *(volatile uint32_t*)GPIOC_ODR &= ~(1 << 11);
-  }
-  else
-  {
-    /* right square (segments: 6A, 6B, 6C, 6D, 6E, 6F) */
-  }
-
-/*   state ^= 1; */
-}
-
-
-#define delay()                                                \
-do {                                                   \
-  register unsigned int i;                             \
-  for (i = 0; i < 1000000; ++i)                                \
-    __asm__ __volatile__ ("nop\n\t":::"memory");       \
-} while (0)
-
-
-#if CONFIG_BOOT_SRAM
-
-extern uint32_t _fstack;
-
-static inline void setup_stack(void)
-{
-  /* setup the stack to point to _fstack (refer to ld script) */
-
-  static const uint32_t fstack = (uint32_t)&_fstack;
-
-  __asm__ __volatile__
-    (
-     "ldr sp, %0\n\t"
-     : 
-     : "m"(fstack)
-     : "sp"
-    );
-}
-
-#endif /* CONFIG_BOOT_SRAM */
 
+/* main */
 
 static void __attribute__((naked)) __attribute__((used)) main(void)
 {
@@ -314,23 +320,30 @@ static void __attribute__((naked)) __attribute__((used)) main(void)
   setup_stack();
 #endif /* CONFIG_BOOT_SRAM */
 
-  setup_leds();
+  RCC_Configuration();
 
-  setup_lcd();
-  clear_lcd();
-/*   while (1) ; */
+  Init_GPIOs();
 
-  update_lcd();
+  LCD_GLASS_Init();
+  LCD_BlinkConfig(LCD_BlinkMode_AllSEG_AllCOM,LCD_BlinkFrequency_Div512);
+  LCD_GLASS_DisplayString("FUBAR");
   while (1) ;
 
+  setup_leds();
+
   while (1)
   {
-    /* update_lcd(); */
-    switch_leds_on();
+    /* switch_leds_on(); */
+    GPIO_HIGH(LD_GPIO_PORT, LD_GREEN_GPIO_PIN);        
+    GPIO_HIGH(LD_GPIO_PORT, LD_BLUE_GPIO_PIN); 
     delay();
 
-    /* update_lcd(); */
-    switch_leds_off();
+    /* switch_leds_off(); */
+    GPIO_LOW(LD_GPIO_PORT, LD_GREEN_GPIO_PIN); 
+    GPIO_LOW(LD_GPIO_PORT, LD_BLUE_GPIO_PIN);  
     delay();
+
+    LCD_GLASS_Clear();
+    LCD_GLASS_DisplayString("FUBAR");
   }
 }
diff --git a/example/lcd/stm32l_discovery_lcd.c b/example/lcd/stm32l_discovery_lcd.c
new file mode 100644 (file)
index 0000000..64163de
--- /dev/null
@@ -0,0 +1,614 @@
+/**\r
+  ******************************************************************************\r
+  * @file    stm32l_discovery_lcd.c\r
+  * @author  Microcontroller Division\r
+  * @version V1.0.0\r
+  * @date    Apri-2011\r
+  * @brief   This file includes driver for the glass LCD Module mounted on \r
+  *          STM32l discovery board MB963\r
+  ******************************************************************************\r
+  * @copy\r
+  *\r
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
+  *\r
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>\r
+  */ \r
+\r
+/* Includes ------------------------------------------------------------------*/\r
+#include "stm32l_discovery_lcd.h"\r
+#include "discover_board.h"\r
+#include "stm32l1xx_lcd.h"\r
+#include "stm32l1xx_gpio.h"\r
+#include "stm32l1xx_rcc.h"\r
+/* #include "main.h" */\r
+\r
+/* this variable can be used for accelerate the scrolling exit when push user button */\r
+volatile bool KeyPressed = FALSE; \r
+               \r
+/* LCD BAR status: We don't write directly in LCD RAM for save the bar setting */\r
+uint8_t t_bar[2]={0x0,0X0};\r
+               \r
+/*  =========================================================================\r
+                                 LCD MAPPING\r
+    =========================================================================\r
+           A\r
+     _  ----------\r
+COL |_| |\   |J  /|\r
+       F| H  |  K |B\r
+     _  |  \ | /  |\r
+COL |_| --G-- --M--\r
+        |   /| \  |\r
+       E|  Q |  N |C\r
+     _  | /  |P  \|   \r
+DP  |_| -----------  \r
+           D         \r
+\r
+ An LCD character coding is based on the following matrix:\r
+      { E , D , P , N   }\r
+      { M , C , COL , DP}\r
+      { B , A , K , J   }\r
+      { G , F , Q , H   }\r
+\r
+ The character 'A' for example is:\r
+  -------------------------------\r
+LSB   { 1 , 0 , 0 , 0   }\r
+      { 1 , 1 , 0 , 0   }\r
+      { 1 , 1 , 0 , 0   }\r
+MSB   { 1 , 1 , 0 , 0   }\r
+      -------------------\r
+  'A' =  F    E   0   0 hexa\r
+\r
+*/\r
+\r
+/* Constant table for cap characters 'A' --> 'Z' */\r
+const uint16_t CapLetterMap[26]=\r
+    {\r
+        /* A      B      C      D      E      F      G      H      I  */\r
+        0xFE00,0x6714,0x1d00,0x4714,0x9d00,0x9c00,0x3f00,0xfa00,0x0014,\r
+        /* J      K      L      M      N      O      P      Q      R  */\r
+        0x5300,0x9841,0x1900,0x5a48,0x5a09,0x5f00,0xFC00,0x5F01,0xFC01,\r
+        /* S      T      U      V      W      X      Y      Z  */\r
+        0xAF00,0x0414,0x5b00,0x18c0,0x5a81,0x00c9,0x0058,0x05c0\r
+    };\r
+\r
+/* Constant table for number '0' --> '9' */\r
+const uint16_t NumberMap[10]=\r
+    {\r
+        /* 0      1      2      3      4      5      6      7      8      9  */\r
+        0x5F00,0x4200,0xF500,0x6700,0xEa00,0xAF00,0xBF00,0x04600,0xFF00,0xEF00\r
+    };\r
+\r
+static void LCD_Conv_Char_Seg(uint8_t* c,bool point,bool column,uint8_t* digit);\r
+\r
+/**\r
+  * @brief  Configures the LCD GLASS relative GPIO port IOs and LCD peripheral.\r
+  * @param  None\r
+  * @retval None\r
+  */\r
+void LCD_GLASS_Init(void)\r
+{\r
+  LCD_InitTypeDef LCD_InitStruct;\r
+\r
\r
+  LCD_InitStruct.LCD_Prescaler = LCD_Prescaler_1;\r
+  LCD_InitStruct.LCD_Divider = LCD_Divider_31;\r
+  LCD_InitStruct.LCD_Duty = LCD_Duty_1_4;\r
+  LCD_InitStruct.LCD_Bias = LCD_Bias_1_3;\r
+  LCD_InitStruct.LCD_VoltageSource = LCD_VoltageSource_Internal;\r
+\r
\r
+  /* Initialize the LCD */\r
+  LCD_Init(&LCD_InitStruct);\r
+  \r
+  LCD_MuxSegmentCmd(ENABLE);\r
+  \r
+  /* To set contrast to mean value */\r
+  LCD_ContrastConfig(LCD_Contrast_Level_4);\r
+  \r
+  LCD_DeadTimeConfig(LCD_DeadTime_0);\r
+  LCD_PulseOnDurationConfig(LCD_PulseOnDuration_4);\r
+\r
+  /* Wait Until the LCD FCR register is synchronized */\r
+  LCD_WaitForSynchro();\r
+  \r
+  /* Enable LCD peripheral */\r
+  LCD_Cmd(ENABLE);\r
+  \r
+  /* Wait Until the LCD is enabled */\r
+  while(LCD_GetFlagStatus(LCD_FLAG_ENS) == RESET)\r
+  {\r
+  }\r
+  /*!< Wait Until the LCD Booster is ready */  \r
+  while(LCD_GetFlagStatus(LCD_FLAG_RDY) == RESET)\r
+  {\r
+  } \r
+\r
+  LCD_BlinkConfig(LCD_BlinkMode_Off,LCD_BlinkFrequency_Div32);   \r
+  LCD_GLASS_Clear();\r
+}\r
+\r
+/**\r
+  * @brief  To initialize the LCD pins\r
+  * @caller main\r
+  * @param None\r
+  * @retval None\r
+  */\r
+\r
+void LCD_GLASS_Configure_GPIO(void)\r
+{\r
+  GPIO_InitTypeDef GPIO_InitStructure;\r
+  \r
+/* Enable GPIOs clock */       \r
+  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC |\r
+                        RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE | RCC_AHBPeriph_GPIOH, ENABLE);\r
+\r
+  \r
+/* Configure Output for LCD */\r
+/* Port A */\r
+  GPIO_StructInit(&GPIO_InitStructure);\r
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 |GPIO_Pin_10 |GPIO_Pin_15;\r
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;\r
+  GPIO_Init( GPIOA, &GPIO_InitStructure);\r
+\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource8,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOA, GPIO_PinSource15,GPIO_AF_LCD) ;  \r
+  \r
+/* Configure Output for LCD */\r
+/* Port B */  \r
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 \\r
+                                 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;  \r
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;\r
+  GPIO_Init( GPIOB, &GPIO_InitStructure);\r
+  \r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource3,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_LCD) ;  \r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource12,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,GPIO_AF_LCD) ;   \r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,GPIO_AF_LCD) ;   \r
+  \r
+/* Configure Output for LCD */\r
+/* Port C*/  \r
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 \\r
+                                 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11 ;                               \r
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;\r
+  GPIO_Init( GPIOC, &GPIO_InitStructure);  \r
+  \r
+\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource0,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1,GPIO_AF_LCD) ; \r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9,GPIO_AF_LCD) ;\r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10,GPIO_AF_LCD) ; \r
+  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11,GPIO_AF_LCD) ;  \r
+\r
+/* Disable GPIOs clock */      \r
+  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC |\r
+                        RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE | RCC_AHBPeriph_GPIOH, DISABLE);\r
+  \r
+}\r
+\r
+/**\r
+  * @brief  LCD contrast setting min-->max-->min by pressing user button\r
+  * @param  None\r
+  * @retval None\r
+  */\r
+\r
+static void Delay(uint32_t nTime)\r
+{\r
+  while((nTime--) != 0); \r
+}\r
+\r
+void LCD_contrast()\r
+{\r
+  uint32_t contrast ;\r
+  \r
+  /* To get the actual contrast value in register */\r
+  contrast = LCD->FCR & LCD_Contrast_Level_7;\r
+  \r
+  while ((GPIOC->IDR & USERBUTTON_GPIO_PIN) == 0x0)\r
+  {\r
+    contrast += LCD_Contrast_Level_1;  \r
+    \r
+    if (contrast > LCD_Contrast_Level_7)\r
+     contrast=LCD_Contrast_Level_0;\r
+  \r
+    LCD_ContrastConfig(contrast);\r
+    Delay(100);\r
+  }\r
+}\r
+\r
+/**\r
+  * @brief  Setting bar on LCD, writes bar value in LCD frame buffer \r
+  * @param  None\r
+  * @retval None\r
+  */\r
+void LCD_bar()\r
+{\r
+        \r
+  LCD->RAM[LCD_RAMRegister_4] &= 0xffff5fff;\r
+  LCD->RAM[LCD_RAMRegister_6] &= 0xffff5fff;\r
+/* bar1 bar3 */\r
+  LCD->RAM[LCD_RAMRegister_4] |= (uint32_t)(t_bar[0]<<12);\r
+  \r
+/*bar0 bar2 */\r
+  LCD->RAM[LCD_RAMRegister_6] |= (uint32_t)(t_bar[1]<<12);\r
\r
+}\r
+\r
+/**\r
+  * @brief  Converts an ascii char to the a LCD digit.\r
+  * @param  c: a char to display.\r
+  * @param  point: a point to add in front of char\r
+  *         This parameter can be: POINT_OFF or POINT_ON\r
+  * @param  column : flag indicating if a column has to be add in front\r
+  *         of displayed character.\r
+  *         This parameter can be: COLUMN_OFF or COLUMN_ON.\r
+       * @param        digit array with segment \r
+  * @retval None\r
+  */\r
+static void LCD_Conv_Char_Seg(uint8_t* c,bool point,bool column, uint8_t* digit)\r
+{\r
+  uint16_t ch = 0 ;\r
+  uint8_t i,j;\r
+  \r
+  switch (*c)\r
+    {\r
+    case ' ' : \r
+      ch = 0x00;\r
+      break;\r
+    \r
+    case '*':\r
+      ch = star;\r
+      break;\r
+                  \r
+    case 'µ' :\r
+      ch = C_UMAP;\r
+      break;\r
+    \r
+    case 'm' :\r
+      ch = C_mMap;\r
+      break;\r
+                  \r
+    case 'n' :\r
+      ch = C_nMap;\r
+      break;                                   \r
+                  \r
+    case '-' :\r
+      ch = C_minus;\r
+      break;\r
+      \r
+    case '/' :\r
+      ch = C_slatch;\r
+      break;  \r
+      \r
+    case '°' :\r
+      ch = C_percent_1;\r
+      break;  \r
+    case '%' :\r
+      ch = C_percent_2; \r
+      break;\r
+    case 255 :\r
+      ch = C_full;\r
+      break ;\r
+    \r
+    case '0':\r
+    case '1':\r
+    case '2':\r
+    case '3':\r
+    case '4':\r
+    case '5':\r
+    case '6':\r
+    case '7':\r
+    case '8':\r
+    case '9':                  \r
+      ch = NumberMap[*c-0x30];         \r
+      break;\r
+          \r
+    default:\r
+      /* The character c is one letter in upper case*/\r
+      if ( (*c < 0x5b) && (*c > 0x40) )\r
+      {\r
+        ch = CapLetterMap[*c-'A'];\r
+      }\r
+      /* The character c is one letter in lower case*/\r
+      if ( (*c <0x7b) && ( *c> 0x60) )\r
+      {\r
+        ch = CapLetterMap[*c-'a'];\r
+      }\r
+      break;\r
+  }\r
+       \r
+  /* Set the digital point can be displayed if the point is on */\r
+  if (point)\r
+  {\r
+    ch |= 0x0002;\r
+  }\r
+\r
+  /* Set the "COL" segment in the character that can be displayed if the column is on */\r
+  if (column)\r
+  {\r
+    ch |= 0x0020;\r
+  }            \r
+\r
+  for (i = 12,j=0 ;j<4; i-=4,j++)\r
+  {\r
+    digit[j] = (ch >> i) & 0x0f; //To isolate the less signifiant dibit\r
+  }\r
+}\r
+\r
+/**\r
+  * @brief  This function writes a char in the LCD frame buffer.\r
+  * @param  ch: the character to display.\r
+  * @param  point: a point to add in front of char\r
+  *         This parameter can be: POINT_OFF or POINT_ON\r
+  * @param  column: flag indicating if a column has to be add in front\r
+  *         of displayed character.\r
+  *         This parameter can be: COLUMN_OFF or COLUMN_ON.           \r
+  * @param  position: position in the LCD of the caracter to write [0:7]\r
+  * @retval None\r
+  * @par    Required preconditions: The LCD should be cleared before to start the\r
+  *         write operation.  \r
+  */\r
+void LCD_GLASS_WriteChar(uint8_t* ch, bool point, bool column, uint8_t position)\r
+{\r
+  uint8_t digit[4];     /* Digit frame buffer */\r
+   \r
+/* To convert displayed character in segment in array digit */\r
+  LCD_Conv_Char_Seg(ch,point,column,digit);\r
+\r
+/* TO wait LCD Ready */  \r
+  while( LCD_GetFlagStatus (LCD_FLAG_UDR) != RESET) ;\r
+  \r
+  switch (position)\r
+  {\r
+    /* Position 1 on LCD (Digit1)*/\r
+    case 1:\r
+      LCD->RAM[LCD_RAMRegister_0] &= 0xcffffffc;\r
+      LCD->RAM[LCD_RAMRegister_2] &= 0xcffffffc;\r
+      LCD->RAM[LCD_RAMRegister_4] &= 0xcffffffc;\r
+      LCD->RAM[LCD_RAMRegister_6] &= 0xcffffffc;\r
+\r
+      LCD->RAM[LCD_RAMRegister_0] |= ((digit[0]& 0x0c) << 26 ) | (digit[0]& 0x03) ; // 1G 1B 1M 1E         \r
+      LCD->RAM[LCD_RAMRegister_2] |= ((digit[1]& 0x0c) << 26 ) | (digit[1]& 0x03) ; // 1F 1A 1C 1D \r
+      LCD->RAM[LCD_RAMRegister_4] |= ((digit[2]& 0x0c) << 26 ) | (digit[2]& 0x03) ; // 1Q 1K 1Col 1P                                                                                                                                    \r
+      LCD->RAM[LCD_RAMRegister_6] |= ((digit[3]& 0x0c) << 26 ) | (digit[3]& 0x03) ; // 1H 1J 1DP 1N\r
+\r
+      break;\r
+    \r
+    /* Position 2 on LCD (Digit2)*/\r
+    case 2:\r
+      LCD->RAM[LCD_RAMRegister_0] &= 0xf3ffff03;\r
+      LCD->RAM[LCD_RAMRegister_2] &= 0xf3ffff03;      \r
+      LCD->RAM[LCD_RAMRegister_4] &= 0xf3ffff03;\r
+      LCD->RAM[LCD_RAMRegister_6] &= 0xf3ffff03;\r
+      \r
+      LCD->RAM[LCD_RAMRegister_0] |= ((digit[0]& 0x0c) << 24 )|((digit[0]& 0x02) << 6 )|((digit[0]& 0x01) << 2 ) ; // 2G 2B 2M 2E        \r
+      LCD->RAM[LCD_RAMRegister_2] |= ((digit[1]& 0x0c) << 24 )|((digit[1]& 0x02) << 6 )|((digit[1]& 0x01) << 2 ) ; // 2F 2A 2C 2D\r
+      LCD->RAM[LCD_RAMRegister_4] |= ((digit[2]& 0x0c) << 24 )|((digit[2]& 0x02) << 6 )|((digit[2]& 0x01) << 2 ) ; // 2Q 2K 2Col 2P\r
+      LCD->RAM[LCD_RAMRegister_6] |= ((digit[3]& 0x0c) << 24 )|((digit[3]& 0x02) << 6 )|((digit[3]& 0x01) << 2 ) ; // 2H 2J 2DP 2N\r
+      \r
+      break;\r
+    \r
+    /* Position 3 on LCD (Digit3)*/\r
+    case 3:\r
+      LCD->RAM[LCD_RAMRegister_0] &= 0xfcfffcff;\r
+      LCD->RAM[LCD_RAMRegister_2] &= 0xfcfffcff;\r
+      LCD->RAM[LCD_RAMRegister_4] &= 0xfcfffcff;\r
+      LCD->RAM[LCD_RAMRegister_6] &= 0xfcfffcff;\r
+\r
+      LCD->RAM[LCD_RAMRegister_0] |= ((digit[0]& 0x0c) << 22 ) | ((digit[0]& 0x03) << 8 ) ; // 3G 3B 3M 3E     \r
+      LCD->RAM[LCD_RAMRegister_2] |= ((digit[1]& 0x0c) << 22 ) | ((digit[1]& 0x03) << 8 ) ; // 3F 3A 3C 3D\r
+      LCD->RAM[LCD_RAMRegister_4] |= ((digit[2]& 0x0c) << 22 ) | ((digit[2]& 0x03) << 8 ) ; // 3Q 3K 3Col 3P\r
+      LCD->RAM[LCD_RAMRegister_6] |= ((digit[3]& 0x0c) << 22 ) | ((digit[3]& 0x03) << 8 ) ; // 3H 3J 3DP 3N\r
+      \r
+      break;\r
+    \r
+    /* Position 4 on LCD (Digit4)*/\r
+    case 4:\r
+      LCD->RAM[LCD_RAMRegister_0] &= 0xffcff3ff;\r
+      LCD->RAM[LCD_RAMRegister_2] &= 0xffcff3ff;\r
+      LCD->RAM[LCD_RAMRegister_4] &= 0xffcff3ff;\r
+      LCD->RAM[LCD_RAMRegister_6] &= 0xffcff3ff;\r
+      \r
+      LCD->RAM[LCD_RAMRegister_0] |= ((digit[0]& 0x0c) << 18 ) | ((digit[0]& 0x03) << 10 ) ; // 4G 4B 4M 4E    \r
+      LCD->RAM[LCD_RAMRegister_2] |= ((digit[1]& 0x0c) << 18 ) | ((digit[1]& 0x03) << 10 ) ; // 4F 4A 4C 4D\r
+      LCD->RAM[LCD_RAMRegister_4] |= ((digit[2]& 0x0c) << 18 ) | ((digit[2]& 0x03) << 10 ) ; // 4Q 4K 4Col 4P\r
+      LCD->RAM[LCD_RAMRegister_6] |= ((digit[3]& 0x0c) << 18 ) | ((digit[3]& 0x03) << 10 ) ; // 4H 4J 4DP 4N\r
+      \r
+      break;\r
+    \r
+    /* Position 5 on LCD (Digit5)*/\r
+    case 5:\r
+      LCD->RAM[LCD_RAMRegister_0] &= 0xfff3cfff;\r
+      LCD->RAM[LCD_RAMRegister_2] &= 0xfff3cfff;\r
+      LCD->RAM[LCD_RAMRegister_4] &= 0xfff3efff;\r
+      LCD->RAM[LCD_RAMRegister_6] &= 0xfff3efff;\r
+\r
+      LCD->RAM[LCD_RAMRegister_0] |= ((digit[0]& 0x0c) << 16 ) | ((digit[0]& 0x03) << 12 ) ; // 5G 5B 5M 5E    \r
+      LCD->RAM[LCD_RAMRegister_2] |= ((digit[1]& 0x0c) << 16 ) | ((digit[1]& 0x03) << 12 ) ; // 5F 5A 5C 5D\r
+      LCD->RAM[LCD_RAMRegister_4] |= ((digit[2]& 0x0c) << 16 ) | ((digit[2]& 0x01) << 12 ) ; // 5Q 5K   5P \r
+      LCD->RAM[LCD_RAMRegister_6] |= ((digit[3]& 0x0c) << 16 ) | ((digit[3]& 0x01) << 12 ) ; // 5H 5J   5N\r
+      \r
+      break;\r
+    \r
+    /* Position 6 on LCD (Digit6)*/\r
+    case 6:\r
+      LCD->RAM[LCD_RAMRegister_0] &= 0xfffc3fff;\r
+      LCD->RAM[LCD_RAMRegister_2] &= 0xfffc3fff;\r
+      LCD->RAM[LCD_RAMRegister_4] &= 0xfffc3fff;\r
+      LCD->RAM[LCD_RAMRegister_6] &= 0xfffc3fff;\r
+\r
+      LCD->RAM[LCD_RAMRegister_0] |= ((digit[0]& 0x04) << 15 ) | ((digit[0]& 0x08) << 13 ) | ((digit[0]& 0x03) << 14 ) ; // 6B 6G 6M 6E        \r
+      LCD->RAM[LCD_RAMRegister_2] |= ((digit[1]& 0x04) << 15 ) | ((digit[1]& 0x08) << 13 ) | ((digit[1]& 0x03) << 14 ) ; // 6A 6F 6C 6D\r
+      LCD->RAM[LCD_RAMRegister_4] |= ((digit[2]& 0x04) << 15 ) | ((digit[2]& 0x08) << 13 ) | ((digit[2]& 0x01) << 14 ) ; // 6K 6Q    6P \r
+      LCD->RAM[LCD_RAMRegister_6] |= ((digit[3]& 0x04) << 15 ) | ((digit[3]& 0x08) << 13 ) | ((digit[3]& 0x01) << 14 ) ; // 6J 6H   6N\r
+      \r
+      break;\r
+    \r
+     default:\r
+      break;\r
+  }\r
+\r
+/* Refresh LCD  bar */\r
+  LCD_bar();\r
+\r
+/* Update the LCD display */\r
+  LCD_UpdateDisplayRequest();\r
+  \r
+}\r
+\r
+/**\r
+  * @brief  This function writes a char in the LCD RAM.\r
+  * @param  ptr: Pointer to string to display on the LCD Glass.\r
+  * @retval None\r
+  */\r
+void LCD_GLASS_DisplayString(uint8_t* ptr)\r
+{\r
+  uint8_t i = 0x01;\r
+\r
+  /* Send the string character by character on lCD */\r
+  while ((*ptr != 0) & (i < 8))\r
+  {\r
+    /* Display one character on LCD */\r
+    LCD_GLASS_WriteChar(ptr, FALSE, FALSE, i);\r
+\r
+    /* Point on the next character */\r
+    ptr++;\r
+\r
+    /* Increment the character counter */\r
+    i++;\r
+  }\r
+}\r
+\r
+/**\r
+  * @brief  This function writes a char in the LCD RAM.\r
+  * @param  ptr: Pointer to string to display on the LCD Glass.\r
+  * @retval None\r
+  * @par    Required preconditions: Char is ASCCI value "Ored" with decimal point or Column flag\r
+  */\r
+void LCD_GLASS_DisplayStrDeci(uint16_t* ptr)\r
+{\r
+  uint8_t i = 0x01;\r
+  uint8_t char_tmp;\r
+  \r
+//  LCD_GLASS_Clear();\r
+  /* Send the string character by character on lCD */\r
+  while ((*ptr != 0) & (i < 8))\r
+  {                    \r
+    char_tmp = (*ptr) & 0x00ff;\r
+    \r
+    switch ((*ptr) & 0xf000)\r
+    {\r
+      case DOT:\r
+          /* Display one character on LCD with decimal point */\r
+          LCD_GLASS_WriteChar(&char_tmp, POINT_ON, COLUMN_OFF, i);\r
+          break;\r
+      case DOUBLE_DOT:\r
+          /* Display one character on LCD with decimal point */\r
+          LCD_GLASS_WriteChar(&char_tmp, POINT_OFF, COLUMN_ON, i);\r
+          break;\r
+      default:\r
+          LCD_GLASS_WriteChar(&char_tmp, POINT_OFF, COLUMN_OFF, i);            \r
+          break;\r
+    }/* Point on the next character */\r
+    ptr++;\r
+    \r
+    /* Increment the character counter */\r
+    i++;\r
+  }\r
+}\r
+\r
+/**\r
+  * @brief  This function Clear the whole LCD RAM.\r
+  * @param  None\r
+  * @retval None\r
+  */\r
+void LCD_GLASS_Clear(void)\r
+{\r
+  uint8_t counter = 0;\r
+\r
+  /* TO wait LCD Ready */  \r
+  while( LCD_GetFlagStatus (LCD_FLAG_UDR) != RESET) ;\r
+  \r
+  for (counter = LCD_RAMRegister_0; counter <= LCD_RAMRegister_15; counter++)\r
+  {\r
+    LCD->RAM[counter] = 0;\r
+  }\r
+\r
+  /* Update the LCD display */\r
+  LCD_UpdateDisplayRequest();\r
+  \r
+}\r
+\r
+/**\r
+  * @brief  Display a string in scrolling mode\r
+  * @param  ptr: Pointer to string to display on the LCD Glass.\r
+  * @param  nScroll: Specifies how many time the message will be scrolled\r
+  * @param  ScrollSpeed : Speciifes the speed of the scroll, low value gives\r
+  *         higher speed \r
+  * @retval None\r
+  * @par    Required preconditions: The LCD should be cleared before to start the\r
+  *         write operation.\r
+  */\r
+void LCD_GLASS_ScrollSentence(uint8_t* ptr, uint16_t nScroll, uint16_t ScrollSpeed)\r
+{\r
+  uint8_t Repetition;\r
+  uint8_t Char_Nb;\r
+  uint8_t* ptr1;\r
+  uint8_t str[7]="";\r
+  uint8_t Str_size;\r
+  \r
+  if (ptr == 0) return;\r
+\r
+/* To calculate end of string */\r
+  for (ptr1=ptr,Str_size = 0 ; *ptr1 != 0; Str_size++,ptr1++) ;\r
+  \r
+  ptr1 = ptr;\r
+  \r
+  LCD_GLASS_DisplayString(ptr);\r
+  Delay(ScrollSpeed);\r
+          \r
+/* To shift the string for scrolling display*/\r
+  for (Repetition=0; Repetition<nScroll; Repetition++)\r
+  {\r
+    for (Char_Nb=0; Char_Nb<Str_size; Char_Nb++)\r
+    {\r
+      *(str) =* (ptr1+((Char_Nb+1)%Str_size));\r
+      *(str+1) =* (ptr1+((Char_Nb+2)%Str_size));\r
+      *(str+2) =* (ptr1+((Char_Nb+3)%Str_size));\r
+      *(str+3) =* (ptr1+((Char_Nb+4)%Str_size));\r
+      *(str+4) =* (ptr1+((Char_Nb+5)%Str_size));\r
+      *(str+5) =* (ptr1+((Char_Nb+6)%Str_size));\r
+      LCD_GLASS_Clear();\r
+      LCD_GLASS_DisplayString(str);\r
+  \r
+  /* user button pressed stop the scrolling sentence */\r
+      if (KeyPressed)\r
+              return;                  \r
+      Delay(ScrollSpeed);\r
+    }  \r
+  }\r
+\r
+}\r
+\r
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/\r
diff --git a/example/lcd/stm32l_discovery_lcd.h b/example/lcd/stm32l_discovery_lcd.h
new file mode 100644 (file)
index 0000000..d496b84
--- /dev/null
@@ -0,0 +1,127 @@
+ /**\r
+  ******************************************************************************\r
+  * @file    stm32l_discovery_lcd.h\r
+  * @author  Microcontroller Division\r
+  * @version V1.0.0\r
+  * @date    Apri-2011\r
+  * @brief   This file contains all the functions prototypes for the glass LCD\r
+  *          firmware driver.\r
+  ******************************************************************************\r
+  * @copy\r
+  *\r
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
+  *\r
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>\r
+  */ \r
+\r
+/* Define to prevent recursive inclusion -------------------------------------*/\r
+#ifndef __stm32l_discovery_lcd\r
+#define __stm32l_discovery_lcd\r
+\r
+/* Includes ------------------------------------------------------------------*/\r
+#include "stm32l1xx.h"   \r
+#include "discover_board.h"\r
+\r
+/* Define for scrolling sentences*/\r
+#define SCROLL_SPEED   300\r
+#define SCROLL_SPEED_L  600\r
+#define SCROLL_NUM     1\r
+\r
+/* Define for character '.' */\r
+#define  POINT_OFF FALSE\r
+#define  POINT_ON TRUE\r
+\r
+/* Define for caracter ":" */\r
+#define  COLUMN_OFF FALSE\r
+#define  COLUMN_ON TRUE\r
+\r
+#define DOT 0x8000 /* for add decimal point in string */\r
+#define DOUBLE_DOT 0x4000 /* for add decimal point in string */\r
+\r
+\r
+/*  =========================================================================\r
+                                 LCD MAPPING\r
+    =========================================================================\r
+           A\r
+     _  ----------\r
+COL |_| |\   |J  /|\r
+       F| H  |  K |B\r
+     _  |  \ | /  |\r
+COL |_| --G-- --M--\r
+        |   /| \  |\r
+       E|  Q |  N |C\r
+     _  | /  |P  \|   \r
+DP  |_| -----------  \r
+           D         \r
+\r
+ An LCD character coding is based on the following matrix:\r
+      { E , D , P , N   }\r
+      { M , C , COL , DP}\r
+      { B , A , K , J   }\r
+      { G , F , Q , H   }\r
+\r
+ The character 'A' for example is:\r
+  -------------------------------\r
+LSB   { 1 , 0 , 0 , 0   }\r
+      { 1 , 1 , 0 , 0   }\r
+      { 1 , 1 , 0 , 0   }\r
+MSB   { 1 , 1 , 0 , 0   }\r
+      -------------------\r
+  'A' =  F    E   0   0 hexa\r
+\r
+*/\r
+/* Macros used for set/reset bar LCD bar */\r
+#define BAR0_ON  t_bar[1] |= 8\r
+#define BAR0_OFF t_bar[1] &= ~8\r
+#define BAR1_ON  t_bar[0] |= 8\r
+#define BAR1_OFF t_bar[0] &= ~8\r
+#define BAR2_ON  t_bar[1] |= 2\r
+#define BAR2_OFF t_bar[1] &= ~2\r
+#define BAR3_ON t_bar[0]  |= 2 \r
+#define BAR3_OFF t_bar[0] &= ~2 \r
+\r
+/* code for 'µ' character */\r
+#define C_UMAP 0x6084\r
+\r
+/* code for 'm' character */\r
+#define C_mMap 0xb210\r
+\r
+/* code for 'n' character */\r
+#define C_nMap 0x2210\r
+\r
+/* constant code for '*' character */\r
+#define star 0xA0DD\r
+\r
+/* constant code for '-' character */\r
+#define C_minus 0xA000\r
+\r
+/* constant code for '/' */\r
+#define C_slatch  0x00c0\r
+\r
+/* constant code for ° */\r
+#define C_percent_1 0xec00\r
+\r
+/* constant code  for small o */\r
+#define C_percent_2 0xb300\r
+\r
+#define C_full 0xffdd\r
+\r
+void LCD_bar(void);\r
+void LCD_GLASS_Init(void);\r
+void LCD_GLASS_WriteChar(uint8_t* ch, bool point, bool column,uint8_t position);\r
+void LCD_GLASS_DisplayString(uint8_t* ptr);\r
+void LCD_GLASS_DisplayStrDeci(uint16_t* ptr);\r
+void LCD_GLASS_ClearChar(uint8_t position);\r
+void LCD_GLASS_Clear(void);\r
+void LCD_GLASS_ScrollSentence(uint8_t* ptr, uint16_t nScroll, uint16_t ScrollSpeed);\r
+void LCD_GLASS_WriteTime(char a, uint8_t posi, bool column);\r
+void LCD_GLASS_Configure_GPIO(void);\r
+\r
+#endif /* stm32l_discovery_lcd*/\r
+\r
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/\r