#include #include #include "led.h" #include "softpwm_led.h" #include "debug.h" #define SOFTPWM_LED_FREQ 64 #define SOFTPWM_LED_TIMER_TOP F_CPU / (256 * SOFTPWM_LED_FREQ) static uint8_t softpwm_led_state = 0; static uint8_t softpwm_led_ocr[LED_COUNT] = {0}; static uint8_t softpwm_led_ocr_buff[LED_COUNT] = {0}; void softpwm_init(void) { #ifdef SOFTPWM_LED_TIMER3 /* Timer3 setup */ /* CTC mode */ TCCR3B |= (1<> 8) & 0xff; OCR3AL = SOFTPWM_LED_TIMER_TOP & 0xff; SREG = sreg; #else /* Timer1 setup */ /* CTC mode */ TCCR1B |= (1<> 8) & 0xff; OCR1AL = SOFTPWM_LED_TIMER_TOP & 0xff; SREG = sreg; #endif softpwm_led_init(); } void softpwm_led_enable(void) { /* Enable Compare Match Interrupt */ #ifdef SOFTPWM_LED_TIMER3 TIMSK3 |= (1< 0x7F) { breathing_led_index[index] = 0x7F; if (breathing_led_rebound_high & LED_BIT(index)) { LED_BIT_SET(breathing_led_direction, index); } } else { breathing_led_index[index] += offset; } } void breathing_led_decrease(uint8_t index, uint8_t offset) { if (breathing_led_index[index] < offset) { breathing_led_index[index] = 0; if (breathing_led_rebound_low & LED_BIT(index)) { LED_BIT_CLEAR(breathing_led_direction, index); } } else { breathing_led_index[index] -= offset; } } void breathing_led_set_mode(uint8_t index, uint8_t mode) { switch (mode) { case BREATHING_LED_UP: breathing_led_index[index] = 0; LED_BIT_CLEAR(breathing_led_direction, index); LED_BIT_CLEAR(breathing_led_rebound_low, index); LED_BIT_CLEAR(breathing_led_rebound_high, index); break; case BREATHING_LED_DOWN: breathing_led_index[index] = 0x7F; LED_BIT_SET(breathing_led_direction, index); LED_BIT_CLEAR(breathing_led_rebound_low, index); LED_BIT_CLEAR(breathing_led_rebound_high, index); break; case BREATHING_LED_CYCLE: breathing_led_index[index] = 0; LED_BIT_CLEAR(breathing_led_direction, index); LED_BIT_SET(breathing_led_rebound_low, index); LED_BIT_SET(breathing_led_rebound_high, index); } } void breathing_led_set_duration(uint8_t index, uint8_t dur) { breathing_led_duration[index] = dur; //dprintf("breathing led set duration: %u\n", breathing_led_duration); } void breathing_led_increase_all(uint8_t offset) { for (uint8_t i = 0; i < LED_COUNT; i++) { breathing_led_increase(i, offset); } } void breathing_led_decrease_all(uint8_t offset) { for (uint8_t i = 0; i < LED_COUNT; i++) { breathing_led_decrease(i, offset); } } void breathing_led_set_mode_all(uint8_t mode) { for (uint8_t i = 0; i < LED_COUNT; i++) { breathing_led_set_mode(i, mode); } } void breathing_led_set_duration_all(uint8_t dur) { for (uint8_t i = 0; i < LED_COUNT; i++) { breathing_led_duration[i] = dur; } } #endif #ifdef SOFTPWM_LED_TIMER3 ISR(TIMER3_COMPA_vect) #else ISR(TIMER1_COMPA_vect) #endif { static uint8_t pwm = 0; pwm++; // LED on if (pwm == 0) { for (uint8_t i = 0; i < LED_COUNT; i++) { softpwm_led_on(i); softpwm_led_ocr[i] = softpwm_led_ocr_buff[i]; } } // LED off for (uint8_t i = 0; i < LED_COUNT; i++) { if (pwm == softpwm_led_ocr[i]) { softpwm_led_off(i); } } #ifdef BREATHING_LED_ENABLE static uint8_t count = 0; static uint8_t step[LED_COUNT] = {0}; if (breathing_led_state) { if (++count > SOFTPWM_LED_FREQ) { count = 0; for (uint8_t i = 0; i < LED_COUNT; i++) { if (breathing_led_state & LED_BIT(i)) { if (++step[i] > breathing_led_duration[i]) { step[i] = 0; softpwm_led_ocr_buff[i] = pgm_read_byte(&breathing_table[breathing_led_index[i]]); if (breathing_led_direction & LED_BIT(i)) { breathing_led_decrease(i, 1); } else { breathing_led_increase(i, 1); } } } } } } #endif }