From 1dc7d758f96dd2b9bd7b03f01ca032d68b696cf0 Mon Sep 17 00:00:00 2001 From: root <root@lab2.panaceas.james.local> Date: Sun, 2 Nov 2014 10:14:39 +0000 Subject: fish --- libopencm3/lib/stm32/l1/lcd.c | 154 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 libopencm3/lib/stm32/l1/lcd.c (limited to 'libopencm3/lib/stm32/l1/lcd.c') diff --git a/libopencm3/lib/stm32/l1/lcd.c b/libopencm3/lib/stm32/l1/lcd.c new file mode 100644 index 0000000..68173ab --- /dev/null +++ b/libopencm3/lib/stm32/l1/lcd.c @@ -0,0 +1,154 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Nikolay Merinov <nikolay.merinov@member.fsf.org> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libopencm3/stm32/l1/lcd.h> +#include <libopencm3/stm32/rcc.h> + +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_for_step_up_ready(void) +{ + while ((LCD_SR & LCD_SR_RDY) == 0); +} + +void lcd_wait_for_update_ready(void) +{ + while ((LCD_SR & LCD_SR_UDR) != 0); +} + +int lcd_is_enabled(void) +{ + 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); +} -- cgit v1.2.3