backlight_software.c
1365 bytes
1#include "backlight.h"
2#include "backlight_driver_common.h"
3#include "util.h"
4
5#ifdef BACKLIGHT_BREATHING
6# error "Backlight breathing is not available for software PWM. Please disable."
7#endif
8
9static uint16_t s_duty_pattern = 0;
10
11// clang-format off
12
13/** \brief PWM duty patterns
14 *
15 * We scale the current backlight level to an index within this array. This allows
16 * backlight_task to focus on just switching LEDs on/off, and we can predict the duty pattern
17 */
18static const uint16_t backlight_duty_table[] = {
19 0b0000000000000000,
20 0b1000000000000000,
21 0b1000000010000000,
22 0b1000001000010000,
23 0b1000100010001000,
24 0b1001001001001000,
25 0b1010101010101010,
26 0b1110111011101110,
27 0b1111111111111111,
28};
29#define backlight_duty_table_size ARRAY_SIZE(backlight_duty_table)
30
31// clang-format on
32
33static uint8_t scale_backlight(uint8_t v) {
34 return v * (backlight_duty_table_size - 1) / BACKLIGHT_LEVELS;
35}
36
37void backlight_init_ports(void) {
38 backlight_pins_init();
39}
40
41void backlight_set(uint8_t level) {
42 s_duty_pattern = backlight_duty_table[scale_backlight(level)];
43}
44
45void backlight_task(void) {
46 static uint8_t backlight_tick = 0;
47
48 if (s_duty_pattern & ((uint16_t)1 << backlight_tick)) {
49 backlight_pins_on();
50 } else {
51 backlight_pins_off();
52 }
53 backlight_tick = (backlight_tick + 1) % 16;
54}