diff --git a/main.c b/main.c index fd9ec7a..9e0cc37 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* firmware to control LCD using HD44780 driver over I²C - * Copyright (C) 2019-2020 King Kévin + * Copyright (C) 2019-2022 King Kévin * SPDX-License-Identifier: GPL-3.0-or-later */ #include @@ -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;