/*************************************************************************** * 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" /* *********************************************************************** */ const uint16_t pwmtable[128] 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 }; #define PWMTABLE_SIZE (sizeof(pwmtable) / sizeof(uint16_t)) 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] < (PWMTABLE_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] = (PWMTABLE_SIZE -1); break; // FIXME: move to some other module? case PWM_MODE_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) { pwm_setpoint[event->num] = event->value; PWM_TIM_ENABLE(); } } /* pwm_event_handler */ static void pwm_update(uint8_t channel) { if ((pwm_setpoint[channel] > pwm_index[channel]) && (pwm_index[channel] < (PWMTABLE_SIZE -1)) ) { pwm_index[channel]++; } else if ((pwm_setpoint[channel] < pwm_index[channel]) && (pwm_index[channel] > 0) ) { pwm_index[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] == (PWMTABLE_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(pgm_read_word(&pwmtable[pwm_index[0]])); } else { PWM_CH1_PWM(pgm_read_word(&pwmtable[pwm_index[1]])); } } } /* pwm_set */ ISR(PWM_TIM_VECT) { static uint8_t delay; delay++; if (delay == 4) { 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 */ void pwm_init(void) { PWM_TIM_INIT(); } /* pwm_init */