diff --git a/event.c b/event.c index 3d30f45..f224084 100644 --- a/event.c +++ b/event.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 01/2019 by Olaf Rempel * + * Copyright (C) 02/2021 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * @@ -23,9 +23,9 @@ /* *********************************************************************** */ -static event_entry_t events[EVENT_COUNT]; -static volatile uint8_t event_in_idx; -static volatile uint8_t event_out_idx; +static event_entry_t m_events[EVENT_COUNT]; +static volatile uint8_t m_event_in_idx; +static volatile uint8_t m_event_out_idx; /* *********************************************************************** */ @@ -38,14 +38,14 @@ void event_queue(uint8_t type, uint8_t num, uint16_t value) sreg_save = SREG; cli(); - idx = event_in_idx; - p_event = &events[idx++]; + idx = m_event_in_idx; + p_event = &m_events[idx]; if (p_event->type == EVENT_TYPE_EMPTY) { p_event->type = type; p_event->num = num; p_event->value = value; - event_in_idx = idx % EVENT_COUNT; + m_event_in_idx = (idx +1) % EVENT_COUNT; } SREG = sreg_save; @@ -54,13 +54,19 @@ void event_queue(uint8_t type, uint8_t num, uint16_t value) event_entry_t * event_get(void) { - return &events[event_out_idx]; + return &m_events[m_event_out_idx]; } /* event_get */ -void event_clear(void) +void event_clear(event_entry_t * p_event) { - uint8_t idx = event_out_idx; - events[idx++].type = EVENT_TYPE_EMPTY; - event_out_idx = idx % EVENT_COUNT; + uint8_t idx = m_event_out_idx; + + if ((p_event == &m_events[idx]) && + (p_event->type != EVENT_TYPE_EMPTY) + ) + { + p_event->type = EVENT_TYPE_EMPTY; + m_event_out_idx = (idx +1) % EVENT_COUNT; + } } /* event_clear */ diff --git a/event.h b/event.h index 079e45f..ff629dc 100644 --- a/event.h +++ b/event.h @@ -1,13 +1,19 @@ -#ifndef __EVENT_H__ -#define __EVENT_H__ +#ifndef EVENT_H_SEEN +#define EVENT_H_SEEN #include /* *********************************************************************** */ -#define EVENT_COUNT 16 +#define EVENT_COUNT 16 -#define EVENT_TYPE_EMPTY 0x00 +#define EVENT_TYPE_EMPTY 0x00 +#define EVENT_TYPE_TIMER_SET 0x01 +#define EVENT_TYPE_TIMER_ELAPSED 0x02 +#define EVENT_TYPE_PWM_VALUE 0x03 +#define EVENT_TYPE_LEDFADE_COMMAND 0x04 +#define EVENT_TYPE_LEDFADE_VALUE 0x05 +#define EVENT_TYPE_LEDFADE_STATUS 0x06 typedef struct event_entry_s { @@ -20,8 +26,8 @@ typedef struct event_entry_s void event_queue (uint8_t type, uint8_t num, uint16_t value); event_entry_t * event_get (void); -void event_clear (void); +void event_clear (event_entry_t * p_event); /* *********************************************************************** */ -#endif /* __EVENT_H__ */ +#endif /* EVENT_H_SEEN */ diff --git a/ledfade.c b/ledfade.c new file mode 100644 index 0000000..dc54973 --- /dev/null +++ b/ledfade.c @@ -0,0 +1,199 @@ +/*************************************************************************** + * Copyright (C) 02/2021 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License, * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "event.h" +#include "ledfade.h" +#include "timer.h" + +/* *********************************************************************** */ + +#define LEDFADE_CHANNEL_COUNT 2 +#define LEDFADE_FULL_FADE_MS 1000 +#define LEDFADE_16BIT 1 + +#if (LEDFADE_16BIT) +#define LEDFADE_TABLE_SIZE 128 +#define LEDFADE_TABLE_GET(x) pgm_read_word(&m_ledfade_table16[x]) +const uint16_t m_ledfade_table16[LEDFADE_TABLE_SIZE] PROGMEM = +{ + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, + 6, 6, 7, 8, 9, 9, 10, 11, 12, 14, 15, 16, 18, 20, 22, 24, 26, + 28, 31, 34, 37, 40, 44, 48, 53, 58, 63, 69, 75, 82, 90, 98, + 107, 116, 127, 139, 151, 165, 180, 196, 214, 234, 255, 278, + 303, 331, 361, 394, 430, 469, 511, 557, 608, 663, 723, 789, + 860, 938, 1023, 1116, 1217, 1327, 1447, 1578, 1721, 1877, + 2047, 2232, 2434, 2655, 2895, 3157, 3443, 3755, 4095, 4466, + 4870, 5311, 5792, 6316, 6888, 7511, 8191, 8932, 9741, 10623, + 11584, 12633, 13776, 15023, 16383, 17866, 19483, 21246, 23169, + 25267, 27553, 30047, 32767, 35733, 38967, 42494, 46340, 50534, + 55108, 60096, 65535 +}; +#else +#define LEDFADE_TABLE_SIZE 32 +#define LEDFADE_TABLE_GET(x) pgm_read_byte(&m_ledfade_table8[x]) +const uint8_t m_ledfade_table8[LEDFADE_TABLE_SIZE] PROGMEM = +{ + 0, 0, 1, 1, 1, 2, 2, 3, + 4, 5, 6, 7, 9, 10, 12, 15, + 18, 22, 26, 31, 37, 44, 53, 63, + 75, 90, 107, 127, 151, 180, 214, 255 +}; +#endif + +#define LEDFADE_FADE_STEP_MS ((LEDFADE_FULL_FADE_MS + LEDFADE_TABLE_SIZE) / LEDFADE_TABLE_SIZE) + +static uint8_t m_ledfade_value[LEDFADE_CHANNEL_COUNT]; +static uint8_t m_ledfade_setpoint[LEDFADE_CHANNEL_COUNT]; +static uint8_t m_ledfade_setpoint_save[LEDFADE_CHANNEL_COUNT]; +static uint8_t m_ledfade_timer_running; + +/* *********************************************************************** */ + +static void ledfade_update(uint8_t channel) +{ + uint8_t update_pwm = 0; + + if (m_ledfade_setpoint[channel] >= LEDFADE_TABLE_SIZE) + { + m_ledfade_setpoint[channel] = (LEDFADE_TABLE_SIZE -1); + } + + if ((m_ledfade_setpoint[channel] > m_ledfade_value[channel]) && + (m_ledfade_value[channel] < (LEDFADE_TABLE_SIZE -1)) + ) + { + m_ledfade_value[channel]++; + update_pwm = 1; + } + else if ((m_ledfade_setpoint[channel] < m_ledfade_value[channel]) && + (m_ledfade_value[channel] > 0) + ) + { + m_ledfade_value[channel]--; + update_pwm = 1; + } + + if (update_pwm) + { + event_queue(EVENT_TYPE_PWM_VALUE, + channel, + LEDFADE_TABLE_GET(m_ledfade_value[channel])); + + if (m_ledfade_value[channel] == m_ledfade_setpoint[channel]) + { + event_queue(EVENT_TYPE_LEDFADE_STATUS, + channel, + m_ledfade_value[channel]); + } + else if (!m_ledfade_timer_running) + { + event_queue(EVENT_TYPE_TIMER_SET, + EVENT_NUM_TIMER_LEDFADE, + LEDFADE_FADE_STEP_MS); + + m_ledfade_timer_running = 1; + } + } +} /* ledfade_update */ + + +void ledfade_event_handler(event_entry_t * p_event) +{ + if (p_event->type == EVENT_TYPE_LEDFADE_COMMAND) + { + uint8_t channel = p_event->num; + + switch (p_event->value) + { + case EVENT_VALUE_LEDFADE_KEEP: + m_ledfade_setpoint[channel] = m_ledfade_value[channel]; + break; + + /* increment */ + case EVENT_VALUE_LEDFADE_INC: + if (m_ledfade_setpoint[channel] < (LEDFADE_TABLE_SIZE -1)) + { + m_ledfade_setpoint[channel]++; + } + break; + + /* decrement */ + case EVENT_VALUE_LEDFADE_DEC: + if (m_ledfade_setpoint[channel] > 0) + { + m_ledfade_setpoint[channel]--; + } + break; + + /* fade to min */ + case EVENT_VALUE_LEDFADE_MIN: + m_ledfade_setpoint[channel] = 0; + break; + + /* fade to max */ + case EVENT_VALUE_LEDFADE_MAX: + m_ledfade_setpoint[channel] = (LEDFADE_TABLE_SIZE -1); + break; + + /* toggle between 0 and stored value */ + case EVENT_VALUE_LEDFADE_TOGGLE: + if (m_ledfade_setpoint[channel] > 5) + { + m_ledfade_setpoint_save[channel] = m_ledfade_setpoint[channel]; + m_ledfade_setpoint[channel] = 0; + } + else + { + m_ledfade_setpoint[channel] = m_ledfade_setpoint_save[channel]; + } + break; + + default: + break; + } + + ledfade_update(channel); + } + else if (p_event->type == EVENT_TYPE_LEDFADE_VALUE) + { + uint8_t channel = p_event->num; + + if (p_event->value < LEDFADE_TABLE_SIZE) + { + m_ledfade_setpoint[channel] = p_event->value; + } + else + { + m_ledfade_setpoint[channel] = (LEDFADE_TABLE_SIZE -1); + } + + ledfade_update(channel); + } + else if ((p_event->type == EVENT_TYPE_TIMER_ELAPSED) && + (p_event->num == EVENT_NUM_TIMER_LEDFADE) + ) + { + m_ledfade_timer_running = 0; + + ledfade_update(0); + ledfade_update(1); + } +} /* ledfade_event_handler */ diff --git a/ledfade.h b/ledfade.h new file mode 100644 index 0000000..361b5fc --- /dev/null +++ b/ledfade.h @@ -0,0 +1,25 @@ +#ifndef LEDFADE_H_SEEN +#define LEDFADE_H_SEEN + +#include +#include "event.h" + +/* *********************************************************************** */ + +#define EVENT_NUM_LED_CH0 0x00 +#define EVENT_NUM_LED_CH1 0x01 + +#define EVENT_VALUE_LEDFADE_KEEP 0x00 +#define EVENT_VALUE_LEDFADE_INC 0x01 +#define EVENT_VALUE_LEDFADE_DEC 0x02 +#define EVENT_VALUE_LEDFADE_MIN 0x03 +#define EVENT_VALUE_LEDFADE_MAX 0x04 +#define EVENT_VALUE_LEDFADE_TOGGLE 0x05 + +/* *********************************************************************** */ + +void ledfade_event_handler (event_entry_t * p_event); + +/* *********************************************************************** */ + +#endif /* LEDFADE_H_SEEN */ diff --git a/main.c b/main.c index 88cca09..82e3251 100644 --- a/main.c +++ b/main.c @@ -6,6 +6,7 @@ #include "Descriptors.h" #include "event.h" +#include "ledfade.h" #include "pwm.h" #include "timer.h" @@ -47,9 +48,9 @@ int main(void) GlobalInterruptEnable(); - event_queue(EVENT_TYPE_PWM_COMMAND, 0, EVENT_VALUE_PWM_FADE_MAX); - event_queue(EVENT_TYPE_PWM_COMMAND, 1, EVENT_VALUE_PWM_FADE_MAX); - event_queue(EVENT_TYPE_PWM_COMMAND, 2, EVENT_VALUE_PWM_FADE_MAX); + event_queue(EVENT_TYPE_LEDFADE_COMMAND, EVENT_NUM_LED_CH0, EVENT_VALUE_LEDFADE_MAX); + event_queue(EVENT_TYPE_LEDFADE_COMMAND, EVENT_NUM_LED_CH1, EVENT_VALUE_LEDFADE_MAX); + event_queue(EVENT_TYPE_PWM_VALUE, EVENT_NUM_PWM_CH2, 0x8000); for (;;) { @@ -59,35 +60,36 @@ int main(void) timer_check(0); event_entry_t* p_event = event_get(); - if (p_event->type != EVENT_TYPE_EMPTY) + switch (p_event->type) { - switch (p_event->type) - { - case EVENT_TYPE_PWM_COMMAND: - case EVENT_TYPE_PWM_VALUE: - pwm_event_handler(p_event); - break; + case EVENT_TYPE_TIMER_SET: + timer_event_handler(p_event); + break; - case EVENT_TYPE_PWM_STATUS: - break; + case EVENT_TYPE_TIMER_ELAPSED: + if (p_event->num == EVENT_NUM_TIMER_LEDFADE) + { + ledfade_event_handler(p_event); + } + break; - case EVENT_TYPE_TIMER_SET: - timer_event_handler(p_event); - break; + case EVENT_TYPE_PWM_VALUE: + pwm_event_handler(p_event); + break; - case EVENT_TYPE_TIMER_ELAPSED: - if (p_event->num == EVENT_NUM_TIMER_PWM) - { - pwm_event_handler(p_event); - } - break; + case EVENT_TYPE_LEDFADE_COMMAND: + case EVENT_TYPE_LEDFADE_VALUE: + ledfade_event_handler(p_event); + break; - default: - break; - } + case EVENT_TYPE_LEDFADE_STATUS: + break; - event_clear(); + default: + break; } + + event_clear(p_event); } } diff --git a/pwm.c b/pwm.c index a624fe7..f187e63 100644 --- a/pwm.c +++ b/pwm.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 01/2019 by Olaf Rempel * + * Copyright (C) 02/2021 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * @@ -17,34 +17,26 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include -#include +#include #include "pwm.h" -#include "timer.h" - /* *********************************************************************** */ -#define PWM_TIM_16BIT 1 +#define PWM_MIN 0x0000 +#define PWM_MAX 0xFFFF #define PWM_TIM_INIT() { \ /* enable output for OC1A, OC1B, OC3A */ \ DDRB |= (1<= PWM_TABLE_SIZE) - { - pwm_setpoint[channel] = (PWM_TABLE_SIZE - 1); - } - - if ((pwm_setpoint[channel] > pwm_index[channel]) && - (pwm_index[channel] < (PWM_TABLE_SIZE - 1)) - ) - { - pwm_index[channel]++; - check_setpoint = 1; - } - else if ((pwm_setpoint[channel] < pwm_index[channel]) && - (pwm_index[channel] > 0) - ) - { - pwm_index[channel]--; - check_setpoint = 1; - } - - /* setpoint reached, notify others */ - if (check_setpoint) - { - if (pwm_index[channel] == pwm_setpoint[channel]) - { - event_queue(EVENT_TYPE_PWM_STATUS, - channel, - pwm_setpoint[channel]); - } - else if (!pwm_fade_timer_running) - { - event_queue(EVENT_TYPE_TIMER_SET, - EVENT_NUM_TIMER_PWM, - PWM_TIMER_FADE_STEP_MS); - - pwm_fade_timer_running = 1; - } - } - /* if PWM is zero, disable output */ - if (pwm_index[channel] == 0) + if (value == PWM_MIN) { switch (channel) { @@ -178,7 +93,7 @@ static void pwm_update(uint8_t channel) } } /* if PWM is max, enable output */ - else if (pwm_index[channel] == (PWM_TABLE_SIZE - 1)) + else if (value == PWM_MAX) { switch (channel) { @@ -204,15 +119,15 @@ static void pwm_update(uint8_t channel) switch (channel) { case 0: - PWM_CH0_PWM(PWM_TABLE_GET(pwm_index[0])); + PWM_CH0_PWM(value); break; case 1: - PWM_CH1_PWM(PWM_TABLE_GET(pwm_index[1])); + PWM_CH1_PWM(value); break; case 2: - PWM_CH2_PWM(PWM_TABLE_GET(pwm_index[2])); + PWM_CH2_PWM(value); break; default: @@ -223,7 +138,7 @@ static void pwm_update(uint8_t channel) switch (channel) { case 0: - case 1: + case 2: /* disable timer if all channels are ON or OFF */ if (PWM_TIM1_CHECK()) { @@ -235,7 +150,7 @@ static void pwm_update(uint8_t channel) } break; - case 2: + case 1: /* disable timer if all channels are ON or OFF */ if (PWM_TIM3_CHECK()) { @@ -252,99 +167,16 @@ static void pwm_update(uint8_t channel) void pwm_event_handler(event_entry_t * p_event) { - if (p_event->type == EVENT_TYPE_PWM_COMMAND) + if (p_event->type == EVENT_TYPE_PWM_VALUE) { - uint8_t channel = p_event->num; - - switch (p_event->value) - { - case EVENT_VALUE_PWM_KEEP: - pwm_setpoint[channel] = pwm_index[channel]; - break; - - /* increment PWM */ - case EVENT_VALUE_PWM_INC: - if (pwm_setpoint[channel] < (PWM_TABLE_SIZE - 1)) - { - pwm_setpoint[channel]++; - } - break; - - /* decrement PWM */ - case EVENT_VALUE_PWM_DEC: - if (pwm_setpoint[channel] > 0) - { - pwm_setpoint[channel]--; - } - break; - - /* fade to min */ - case EVENT_VALUE_PWM_FADE_MIN: - pwm_setpoint[channel] = 0; - break; - - /* fade to max */ - case EVENT_VALUE_PWM_FADE_MAX: - pwm_setpoint[channel] = (PWM_TABLE_SIZE - 1); - break; - - /* toggle between 0 and stored value */ - case EVENT_VALUE_PWM_TOGGLE: - if (pwm_setpoint[channel] > 5) - { - pwm_setpoint_save[channel] = pwm_setpoint[channel]; - pwm_setpoint[channel] = 0; - } - else - { - pwm_setpoint[channel] = pwm_setpoint_save[channel]; - } - break; - - default: - break; - } - - pwm_update(channel); - } - else if (p_event->type == EVENT_TYPE_PWM_VALUE) - { - uint8_t channel = p_event->num; - - if (p_event->value < PWM_TABLE_SIZE) - { - pwm_setpoint[channel] = p_event->value; - } - else - { - pwm_setpoint[channel] = (PWM_TABLE_SIZE - 1); - } - - pwm_update(channel); - } - else if ((p_event->type == EVENT_TYPE_TIMER_ELAPSED) && - (p_event->num == EVENT_NUM_TIMER_PWM) - ) - { - pwm_fade_timer_running = 0; - - pwm_update(0); - pwm_update(1); - pwm_update(2); + pwm_update(p_event->num, p_event->value); } } /* pwm_event_handler */ uint8_t pwm_get_sleep_mode(void) { - if (PWM_TIM1_RUNNING() || PWM_TIM3_RUNNING()) - { - return SLEEP_MODE_IDLE; - } - else - { - return SLEEP_MODE_PWR_DOWN; - } + return !!(PWM_TIM1_RUNNING() || PWM_TIM3_RUNNING()); } /* pwm_get_sleep_mode */ diff --git a/pwm.h b/pwm.h index 94b3171..c75793d 100644 --- a/pwm.h +++ b/pwm.h @@ -1,32 +1,21 @@ -#ifndef __PWM_H__ -#define __PWM_H__ +#ifndef PWM_H_SEEN +#define PWM_H_SEEN #include #include "event.h" /* *********************************************************************** */ -#define EVENT_TYPE_PWM_COMMAND 0x04 -#define EVENT_TYPE_PWM_VALUE 0x05 -#define EVENT_TYPE_PWM_STATUS 0x06 - #define EVENT_NUM_PWM_CH0 0x00 #define EVENT_NUM_PWM_CH1 0x01 #define EVENT_NUM_PWM_CH2 0x02 -#define EVENT_VALUE_PWM_KEEP 0x00 -#define EVENT_VALUE_PWM_INC 0x01 -#define EVENT_VALUE_PWM_DEC 0x02 -#define EVENT_VALUE_PWM_FADE_MIN 0x03 -#define EVENT_VALUE_PWM_FADE_MAX 0x04 -#define EVENT_VALUE_PWM_TOGGLE 0x05 - /* *********************************************************************** */ void pwm_init (void); void pwm_event_handler (event_entry_t * p_event); -uint8_t pwm_get_sleep_mode (void); +uint8_t pwm_need_hw_clock (void); /* *********************************************************************** */ -#endif /* __PWM_H__ */ +#endif /* PWM_H_SEEN */ diff --git a/timer.c b/timer.c index ba27339..14a74fd 100644 --- a/timer.c +++ b/timer.c @@ -18,7 +18,6 @@ ***************************************************************************/ #include #include -#include #include "event.h" #include "timer.h" @@ -43,8 +42,8 @@ #define TIMER_MSEC2TICKS(x) ((x * F_CPU) / (TIMER_DIVISOR * 1000ULL)) #define TIMER_MSEC2IRQCNT(x) (x / TIMER_IRQFREQ_MS) -static uint16_t timers[TIMER_COUNT]; -volatile static uint8_t timer_ticked; +static uint16_t m_timers[TIMER_COUNT]; +volatile static uint8_t m_timer_ticked; /* *********************************************************************** */ @@ -53,24 +52,24 @@ ISR(TIMER_TIM_VECT) /* 1ms interrupt */ TIMER_TIM_RELOAD(TIMER_MSEC2TICKS(TIMER_IRQFREQ_MS)); - timer_ticked = 1; + m_timer_ticked = 1; } /* TIM1_OVF_vect */ uint8_t timer_check(uint8_t timer_needed) { - if (timer_ticked) + if (m_timer_ticked) { uint8_t i; - timer_ticked = 0; + m_timer_ticked = 0; for (i = 0; i < TIMER_COUNT; i++) { - if (timers[i] > 0) + if (m_timers[i] > 0) { - timers[i]--; - if (timers[i] == 0) + m_timers[i]--; + if (m_timers[i] == 0) { event_queue(EVENT_TYPE_TIMER_ELAPSED, i, 0); } @@ -100,7 +99,7 @@ void timer_event_handler(event_entry_t * p_event) (p_event->num < TIMER_COUNT) ) { - timers[p_event->num] = p_event->value; + m_timers[p_event->num] = p_event->value; /* start timer if needed */ if (!TIMER_TIM_RUNNING()) @@ -112,17 +111,10 @@ void timer_event_handler(event_entry_t * p_event) } /* timer_event_handler */ -uint8_t timer_get_sleep_mode(void) +uint8_t timer_need_hw_clock(void) { - if (TIMER_TIM_RUNNING()) - { - return SLEEP_MODE_IDLE; - } - else - { - return SLEEP_MODE_PWR_DOWN; - } - } /* timer_get_sleep_mode */ + return !!TIMER_TIM_RUNNING(); +} /* timer_get_sleep_mode */ void timer_init(void) diff --git a/timer.h b/timer.h index f75271e..82db5a0 100644 --- a/timer.h +++ b/timer.h @@ -1,5 +1,5 @@ -#ifndef __TIMER_H__ -#define __TIMER_H__ +#ifndef TIMER_H_SEEN +#define TIMER_H_SEEN #include #include "event.h" @@ -8,18 +8,15 @@ #define TIMER_COUNT 1 -#define EVENT_TYPE_TIMER_SET 0x01 -#define EVENT_TYPE_TIMER_ELAPSED 0x02 - -#define EVENT_NUM_TIMER_PWM 0 +#define EVENT_NUM_TIMER_LEDFADE 0 /* *********************************************************************** */ void timer_init (void); uint8_t timer_check (uint8_t timer_needed); void timer_event_handler (event_entry_t * p_event); -uint8_t timer_get_sleep_mode (void); +uint8_t timer_need_hw_clock (void); /* *********************************************************************** */ -#endif /* __TIMER_H__ */ +#endif /* TIMER_H_SEEN */