drive backlight using PWM
This commit is contained in:
parent
1e446cbb0b
commit
d37edd9e9d
41
main.c
41
main.c
|
@ -1,5 +1,5 @@
|
|||
/* firmware to control LCD using HD44780 driver over I²C
|
||||
* Copyright (C) 2019-2020 King Kévin <kingkevin@cuvoodoo.info>
|
||||
* Copyright (C) 2019-2022 King Kévin <kingkevin@cuvoodoo.info>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
@ -7,12 +7,9 @@
|
|||
#include "stm8s.h"
|
||||
#include "main.h"
|
||||
|
||||
// on-board LED pin in on PB5 (use as sink), same as SDA
|
||||
#define LED_PORT GPIO_PA
|
||||
#define LED_PIN PA3
|
||||
#define led_on() {LED_PORT->ODR.reg &= ~LED_PIN;}
|
||||
#define led_off() {LED_PORT->ODR.reg |= LED_PIN;}
|
||||
#define led_toggle() {LED_PORT->ODR.reg ^= LED_PIN;}
|
||||
// nMOS gate to drive backlight LED
|
||||
#define BL_PORT GPIO_PA
|
||||
#define BL_PIN PA3
|
||||
|
||||
/* usual HD44780 pinout:
|
||||
* - 1 GND: ground
|
||||
|
@ -201,14 +198,9 @@ void main(void)
|
|||
while (!(CLK_ICKR & CLK_ICKR_HSIRDY)); // wait for internal oscillator to be ready
|
||||
|
||||
// save power by disabling unused peripheral
|
||||
CLK_PCKENR1 = CLK_PCKENR1_I2C; // only keep I²C
|
||||
CLK_PCKENR1 = CLK_PCKENR1_I2C | CLK_PCKENR1_TIM25; // only keep I²C and timer 2
|
||||
CLK_PCKENR2 = CLK_PCKENR2_AWU; // only keep AWU
|
||||
|
||||
// configure LED
|
||||
LED_PORT->DDR.reg |= LED_PIN; // switch pin to output
|
||||
LED_PORT->CR1.reg &= ~LED_PIN; // use in open-drain mode
|
||||
led_off(); // start with LED off
|
||||
|
||||
// configure independent watchdog (very loose, just it case the firmware hangs)
|
||||
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
|
||||
IWDG_KR = IWDG_KR_KEY_ENABLE; // start watchdog
|
||||
|
@ -270,6 +262,21 @@ void main(void)
|
|||
AWU->APR.fields.APR = 0x3e; // set time to 256 ms
|
||||
AWU_CSR |= AWU_CSR_AWUEN; // enable AWU (start only when entering wait or active halt mode)
|
||||
|
||||
// configure PWM output for backlight
|
||||
BL_PORT->DDR.reg |= BL_PIN; // switch pin to output
|
||||
BL_PORT->CR1.reg |= BL_PIN; // use in push-pull mode
|
||||
TIM2->CCMR3.output_fields.OC3M = 6; // PWM mode 1
|
||||
TIM2->CCMR3.output_fields.CC3S = 0; // configure channel as output
|
||||
TIM2->CCER2.fields.CC3P = 0; // active high
|
||||
TIM2->CCER2.fields.CC3E = 1; // output enable
|
||||
TIM2->ARRH.fields.ARR15_8 = 0; // set reload to 0xff
|
||||
TIM2->ARRL.fields.ARR7_0 = 0xfe; // set reload to 0xff
|
||||
TIM2->PSCR.fields.PSC = 6; // set frequency to 1 kHz
|
||||
TIM2->CCR3H.fields.CCR3 = 0; // start with PWM off
|
||||
TIM2->CCR3L.fields.CCR3 = 0; // start with PWM off
|
||||
TIM2->EGR.fields.UG = 1; // force reload of values
|
||||
TIM2->CR1.fields.CEN = 1; // enable timer
|
||||
|
||||
// configure display (as per datasheet)
|
||||
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
|
||||
HD44780_RS_PORT->ODR.reg &= ~HD44780_RS_PIN; // set low for instruction
|
||||
|
@ -292,10 +299,8 @@ void main(void)
|
|||
|
||||
rim(); // re-enable interrupts
|
||||
|
||||
led_on();
|
||||
while (true) {
|
||||
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
|
||||
//led_toggle(); // indicate we re running
|
||||
while (i2c_input_used) { // I²C data is available
|
||||
sim(); // disable interrupt while reading buffer to not corrupt indexes
|
||||
uint8_t input_data = i2c_input_buffer[i2c_input_i]; // get start buffered data
|
||||
|
@ -356,11 +361,7 @@ void main(void)
|
|||
hd44780_write_instruction(0x80 | (input_data & 0x3f));
|
||||
break;
|
||||
case MODE_BRIGHTNESS:
|
||||
if (input_data) {
|
||||
led_on();
|
||||
} else {
|
||||
led_off();
|
||||
}
|
||||
TIM2->CCR3L.fields.CCR3 = input_data; // set duty cycle
|
||||
break;
|
||||
default: // read values do not make sense
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue