From 09f4c911ed99f5d73f4c005d79cc46d901765a88 Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Tue, 28 May 2013 23:07:31 +0200 Subject: [PATCH] pwm.c: disable when not needed Timer/Counter 1 eats much power, especially with PLL clock. So let's try to disable it when no PWM channel is active. --- firmware/lights.h | 1 + firmware/pwm.c | 27 +++++++++++++++++++++++++-- firmware/tmr.c | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/firmware/lights.h b/firmware/lights.h index 6851509..0705dd1 100644 --- a/firmware/lights.h +++ b/firmware/lights.h @@ -42,6 +42,7 @@ void susp_pwm(); void pwm_off(unsigned char n); void pwm_set(unsigned char n, uint16_t stride); void pwm_timer(); +void pwm_disable_if_not_needed(); /* tmr.c */ extern volatile uint16_t jiffies; diff --git a/firmware/pwm.c b/firmware/pwm.c index b472273..512268c 100644 --- a/firmware/pwm.c +++ b/firmware/pwm.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -13,6 +14,7 @@ static uint16_t pwm[N_PWMLEDS]; static volatile unsigned char step; +static unsigned char channels_running, pll_enabled; static void enable_pll() { @@ -24,6 +26,8 @@ static void enable_pll() while ((PLLCSR & _BV(PLOCK)) == 0) ; PLLCSR |= _BV(PCKE); + + pll_enabled = 1; } void init_pwm() @@ -31,12 +35,12 @@ void init_pwm() int i; step = 0; + channels_running = 0; + pll_enabled = 0; for (i = 0; i < N_PWMLEDS; i++) pwm[i] = 0; - enable_pll(); - // PWM channel D is inverted, ... TCCR1C = _BV(COM1D1) | _BV(COM1D0) | _BV(PWM1D); // PWM channels A and B are not @@ -76,6 +80,7 @@ void pwm_off(unsigned char n) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { pwm[n] = 0; + channels_running &= ~(1 << n); switch (n) { case 0: DDRB &= ~_BV(PB1); break; @@ -119,6 +124,12 @@ void pwm_set(unsigned char n, uint16_t stride) ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { pwm[n] = stride; + channels_running |= (1 << n); + + if (!pll_enabled) { + power_timer1_enable(); + enable_pll(); + } pwm_update_hw(n); @@ -142,3 +153,15 @@ void pwm_timer() pwm_update_hw(i); } +void pwm_disable_if_not_needed() +{ + if (channels_running) + return; + + pll_enabled = 0; + DDRB &= ~(_BV(PB1) | _BV(PB3) | _BV(PB5)); + PLLCSR &= ~(_BV(PLLE) | _BV(PCKE)); + + power_timer1_disable(); +} + diff --git a/firmware/tmr.c b/firmware/tmr.c index 2e61db8..7a31f19 100644 --- a/firmware/tmr.c +++ b/firmware/tmr.c @@ -22,6 +22,7 @@ ISR(WDT_vect) { timer_check_buttons(); patterns_next_tick(); + pwm_disable_if_not_needed(); timer_start_slow_adcs(); if ((jiffies & 0x7FF) == 0) -- 2.39.3