display_led_low_power_pwm.cpp
1 #include "sdk_common.h" 2 3 #if defined(DISPLAY_LED_LOW_POWER_PWM_ENABLED) && DISPLAY_LED_LOW_POWER_PWM_ENABLED == 1 4 5 #include "display_led_low_power_pwm.h" 6 7 #include <stdbool.h> 8 9 #include "app_error.h" 10 #include "boards.h" 11 #include "low_power_pwm.h" 12 13 #include "../display_log_module.ii" 14 15 static bool display_led_low_power_pwm_initialized = false; 16 17 static struct { 18 low_power_pwm_t lp_pwm; 19 } instance_data; 20 21 static void display_led_low_power_pwm_set_duty_cycle(uint8_t dc) 22 { 23 ret_code_t err_code = low_power_pwm_duty_set(&instance_data.lp_pwm, dc); 24 APP_ERROR_CHECK(err_code); 25 26 // check to see if we set the duty cycle to off, 27 // and if so, immediately clear the bit. the reason 28 // for this is, when shutting down, this will 29 // be called to turn the backlight off, but the timers will 30 // not tick again before the device goes into PWROFF state, 31 // and we want to make sure the LED is off before it does so! 32 if (dc == 0) 33 { 34 nrf_gpio_port_out_clear(instance_data.lp_pwm.p_port, instance_data.lp_pwm.bit_mask_toggle); 35 } 36 } 37 38 static void display_led_low_power_pwm_handler(void* context) 39 { 40 // noop is fine for now. 41 } 42 43 static ret_code_t display_led_low_power_pwm_initialize(const display_led_rgb_driver_config_t* config) 44 { 45 if (display_led_low_power_pwm_initialized) 46 { 47 NRF_LOG_WARNING("display_led_low_power_pwm already initialized."); 48 return NRF_ERROR_MODULE_ALREADY_INITIALIZED; 49 } 50 51 if (config->pin_count == 0) 52 { 53 NRF_LOG_WARNING("display_led_low_power_pwm requires at least a single pin definition."); 54 return NRF_ERROR_INVALID_LENGTH; 55 } 56 57 uint32_t pin_mask = 0; 58 59 for (size_t scan = 0; scan < config->pin_count; ++scan) 60 { 61 pin_mask |= PIN_MASK(config->pins[scan].pin); 62 } 63 64 APP_TIMER_DEF(lowPowerPwmTimer); 65 low_power_pwm_config_t lppwm_config; 66 lppwm_config.active_high = true; 67 lppwm_config.period = DISPLAY_LED_LOW_POWER_PWM_BRIGHTNESS_MAX; 68 lppwm_config.bit_mask = pin_mask; 69 lppwm_config.p_timer_id = &lowPowerPwmTimer; 70 lppwm_config.p_port = NRF_GPIO; 71 72 ret_code_t err_code = low_power_pwm_init((&instance_data.lp_pwm), &lppwm_config, display_led_low_power_pwm_handler); 73 APP_ERROR_CHECK(err_code); 74 75 display_led_low_power_pwm_set_duty_cycle(DISPLAY_LED_LOW_POWER_PWM_BRIGHTNESS_DEFAULT); 76 77 // start the pwm timer! 78 err_code = low_power_pwm_start((&instance_data.lp_pwm), instance_data.lp_pwm.bit_mask); 79 APP_ERROR_CHECK(err_code); 80 81 display_led_low_power_pwm_initialized = true; 82 83 return err_code; 84 } 85 86 static void display_led_low_power_pwm_uninitialize() 87 { 88 low_power_pwm_stop(&instance_data.lp_pwm); 89 display_led_low_power_pwm_initialized = false; 90 } 91 92 static void display_led_low_power_pwm_set_leds(const display_led_rgb_color_t* led_colors, size_t led_count, uint8_t brightness) 93 { 94 if (led_count == 0) 95 { 96 return; 97 } 98 99 // we can only handle one color, so we're just going to use the average 100 // of the rgb of the first color to determine our D/C 101 const display_led_rgb_color_t* color = &led_colors[0]; 102 uint8_t dc = (color->red + color->green + color->blue) / 3; 103 display_led_low_power_pwm_set_duty_cycle(dc); 104 } 105 106 const display_led_rgb_driver_t display_led_low_power_pwm = { 107 .initialize = display_led_low_power_pwm_initialize, 108 .uninitialize = display_led_low_power_pwm_uninitialize, 109 .set_leds = display_led_low_power_pwm_set_leds, 110 .default_brightness = DISPLAY_LED_LOW_POWER_PWM_BRIGHTNESS_DEFAULT, 111 .name = "Low Power PWM", 112 .instance_data = &instance_data, 113 }; 114 115 #endif // DISPLAY_LED_LOW_POWER_PWM_ENABLED