/ src / display / led / display_led_low_power_pwm.cpp
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