/*************************************************************************** * Copyright (C) 11/2014 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 #include #include "event.h" #include "pwm.h" #include "target.h" /* *********************************************************************** */ #if (PWM_TIM_16BIT) #define PWM_TABLE_SIZE 128 #define PWM_TABLE_GET(x) pgm_read_word(&pwmtable16[x]) const uint16_t pwmtable16[PWM_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 PWM_TABLE_SIZE 32 #define PWM_TABLE_GET(x) pgm_read_byte(&pwmtable8[x]) const uint8_t pwmtable8[PWM_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 static uint8_t pwm_index[2]; static uint8_t pwm_setpoint[2]; static uint8_t pwm_setpoint_save[2]; /* *********************************************************************** */ void pwm_event_handler(struct event_entry *event) { uint8_t channel = event->num; if (event->type == EVENT_TYPE_PWM_COMMAND) { switch (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; 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_TIM_ENABLE(); } else if (event->type == EVENT_TYPE_PWM_VALUE) { if (event->value < PWM_TABLE_SIZE) { pwm_setpoint[event->num] = event->value; } else { pwm_setpoint[event->num] = (PWM_TABLE_SIZE -1); } PWM_TIM_ENABLE(); } } /* pwm_event_handler */ static void pwm_update(uint8_t channel) { if ((pwm_setpoint[channel] > pwm_index[channel]) && (pwm_index[channel] < (PWM_TABLE_SIZE -1)) ) { pwm_index[channel]++; /* setpoint reached, notify others */ if (pwm_index[channel] == pwm_setpoint[channel]) { event_queue(EVENT_TYPE_PWM_STATUS, channel, pwm_setpoint[channel]); } } else if ((pwm_setpoint[channel] < pwm_index[channel]) && (pwm_index[channel] > 0) ) { pwm_index[channel]--; /* setpoint reached, notify others */ if (pwm_index[channel] == pwm_setpoint[channel]) { event_queue(EVENT_TYPE_PWM_STATUS, channel, pwm_setpoint[channel]); } } /* if PWM is zero, disable output */ if (pwm_index[channel] == 0) { if (channel == 0) { PWM_CH0_OFF(); } else { PWM_CH1_OFF(); } } /* if PWM is max, enable output */ else if (pwm_index[channel] == (PWM_TABLE_SIZE -1)) { if (channel == 0) { PWM_CH0_ON(); } else { PWM_CH1_ON(); } } /* else load new PWM into timer */ else { if (channel == 0) { PWM_CH0_PWM(PWM_TABLE_GET(pwm_index[0])); } else { PWM_CH1_PWM(PWM_TABLE_GET(pwm_index[1])); } } } /* pwm_set */ ISR(PWM_TIM_VECT) { static uint8_t delay; delay++; if (delay == PWM_DELAY_COUNT) { delay = 0; /* update PWM values */ pwm_update(0); pwm_update(1); /* disable timer if both channels are ON or OFF */ if (PWM_TIM_CHECK()) { PWM_TIM_ENABLE(); } else { PWM_TIM_DISABLE(); } } } /* TIM1_OVF_vect */ uint8_t pwm_get_sleep_mode(void) { if (PWM_TIM_RUNNING()) { return SLEEP_MODE_IDLE; } else { return SLEEP_MODE_PWR_DOWN; } } /* pwm_get_sleep_mode */ void pwm_init(void) { PWM_TIM_INIT(); } /* pwm_init */