From ec29bd7f48f4adbff8c057baa4c570e4ad67bc89 Mon Sep 17 00:00:00 2001 From: Nikolay Merinov Date: Tue, 4 Mar 2014 01:25:36 +0600 Subject: [PATCH] stm32l1: lcd: Basic LCD configure functions. --- include/libopencm3/stm32/l1/lcd.h | 19 ++++- lib/stm32/l1/lcd.c | 118 +++++++++++++++++++++++++++++- 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/include/libopencm3/stm32/l1/lcd.h b/include/libopencm3/stm32/l1/lcd.h index 693e612c..0a4b02b7 100644 --- a/include/libopencm3/stm32/l1/lcd.h +++ b/include/libopencm3/stm32/l1/lcd.h @@ -206,10 +206,25 @@ BEGIN_DECLS void lcd_enable(void); -void lcd_wait_step_up_ready(void); -void lcd_wait_for_update_ready(void); void lcd_update(void); +void lcd_wait_for_lcd_enabled(void); +void lcd_wait_for_step_up_ready(void); +void lcd_wait_for_update_ready(void); + +int lcd_is_enabled(void); +int lcd_is_step_up_ready(void); +int lcd_is_for_update_ready(void); + +void lcd_set_contrast(uint8_t contrast); +void lcd_set_bias(uint8_t bias); +void lcd_set_duty(uint8_t duty); +void lcd_set_prescaler(uint8_t ps); +void lcd_set_divider(uint8_t div); +void lcd_enable_segment_multiplexing(void); +void lcd_disable_segment_multiplexing(void); +void lcd_set_refresh_frequency(uint32_t frequency); + END_DECLS #endif diff --git a/lib/stm32/l1/lcd.c b/lib/stm32/l1/lcd.c index 97aba301..68173ab8 100644 --- a/lib/stm32/l1/lcd.c +++ b/lib/stm32/l1/lcd.c @@ -18,14 +18,24 @@ */ #include +#include void lcd_enable(void) { LCD_CR |= LCD_CR_LCDEN; +} + +void lcd_update(void) +{ + LCD_SR |= LCD_SR_UDR; +} + +void lcd_wait_for_lcd_enabled(void) +{ while ((LCD_SR & LCD_SR_ENS) == 0); } -void lcd_wait_step_up_ready(void) +void lcd_wait_for_step_up_ready(void) { while ((LCD_SR & LCD_SR_RDY) == 0); } @@ -35,8 +45,110 @@ void lcd_wait_for_update_ready(void) while ((LCD_SR & LCD_SR_UDR) != 0); } -void lcd_update(void) +int lcd_is_enabled(void) { - LCD_SR |= LCD_SR_UDR; + return ((LCD_SR & LCD_SR_ENS) != 0); } +int lcd_is_step_up_ready(void) +{ + return ((LCD_SR & LCD_SR_RDY) != 0); +} + +int lcd_is_for_update_ready(void) +{ + return ((LCD_SR & LCD_SR_UDR) == 0); +} + +void lcd_set_contrast(uint8_t contrast) +{ + LCD_FCR &= ~(LCD_FCR_CC_MASK << LCD_FCR_CC_SHIFT); + LCD_FCR |= contrast << LCD_FCR_CC_SHIFT; +} + +void lcd_set_bias(uint8_t bias) +{ + LCD_CR &= ~(LCD_CR_BIAS_MASK << LCD_CR_BIAS_SHIFT); + LCD_CR |= bias << LCD_CR_BIAS_SHIFT; +} + +void lcd_set_duty(uint8_t duty) +{ + LCD_CR &= ~(LCD_CR_DUTY_MASK << LCD_CR_DUTY_SHIFT); + LCD_CR |= duty << LCD_CR_DUTY_SHIFT; +} + +void lcd_set_prescaler(uint8_t ps) +{ + LCD_FCR &= ~(LCD_FCR_PS_MASK << LCD_FCR_PS_SHIFT); + LCD_FCR |= ps << LCD_FCR_PS_SHIFT; +} + +void lcd_set_divider(uint8_t div) +{ + LCD_FCR &= ~(LCD_FCR_DIV_MASK << LCD_FCR_DIV_SHIFT); + LCD_FCR |= div << LCD_FCR_DIV_SHIFT; +} + +void lcd_enable_segment_multiplexing(void) +{ + LCD_CR |= LCD_CR_MUX_SEG; +} + +void lcd_disable_segment_multiplexing(void) +{ + LCD_CR &= ~LCD_CR_MUX_SEG; +} + +void lcd_set_refresh_frequency(uint32_t frequency) +{ + uint32_t duty, lcd_clock; + switch ((LCD_CR >> LCD_CR_DUTY_SHIFT) & LCD_CR_DUTY_MASK) { + case LCD_CR_DUTY_STATIC: + duty = 1; + break; + case LCD_CR_DUTY_1_2: + duty = 2; + break; + case LCD_CR_DUTY_1_3: + duty = 3; + break; + case LCD_CR_DUTY_1_4: + duty = 4; + break; + case LCD_CR_DUTY_1_8: + duty = 8; + break; + default: + /* Incorrect duty */ + return; + } + + switch ((RCC_CSR >> RCC_CSR_RTCSEL_SHIFT) & RCC_CSR_RTCSEL_MASK) { + case RCC_CSR_RTCSEL_LSE: + lcd_clock = 32786; + break; + case RCC_CSR_RTCSEL_LSI: + lcd_clock = 37000; + break; + case RCC_CSR_RTCSEL_HSI: + lcd_clock = 16000000; + break; + default: + /* RCC Clock not selected */ + return; + } + + /* PS * DIV = lcd_clock/(duty * freq) */ + uint32_t ps_mul_div = lcd_clock / (duty * frequency); + + int div, ps = 0; + while (ps_mul_div > 32) { + ps_mul_div >>= 1; + ps++; + } + div = ps_mul_div - 16; + + lcd_set_prescaler(ps); + lcd_set_divider(div); +}