/*************************************************************************** * Copyright (C) 09/2007 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 "main.h" #include "blmc.h" #include "eeprom.h" extern struct ee_param params; struct blmc_ blmc; /* Analog Comparator Channel */ static uint8_t next_sense; void trigger_adc(uint8_t channel) { /* Disable Analog Comperator */ ACSR &= ~(1< 50) { next_phase(); uint16_t i; for (i = 0; i < time; i++) _delay_loop_1(tick >> 8); time -= (time / params.spinup_step +1); } /* manual spinup complete, analog comperator takes control */ blmc.flags &= ~(FLAG_RUN_MASK); blmc.flags |= FLAG_PWM_SPINUP | FLAG_COM_NORMAL; next_phase(); for (time = 0; time < params.spinup_wait; time++) _delay_ms(20); /* switch to desired pwm value */ blmc.flags &= ~(FLAG_RUN_MASK); blmc.flags |= FLAG_PWM_NORMAL | FLAG_COM_NORMAL; } /* * sets new pwm value * called from i2c-slave (set new value) and from timer (recalc current limit) */ void setpwm(uint8_t pwm) { /* run motor *only* if there are no hard errors */ if (pwm >= params.pwm_min && !(blmc.flags & FLAG_HARDERR_MASK)) { /* do a spinup */ if (blmc.pwm == 0) { blmc.flags &= ~(FLAG_RUN_MASK); blmc.flags |= FLAG_PWM_SPINUP | FLAG_COM_SPINUP; } } else { blmc.flags &= ~FLAG_RUN_MASK; pwm = 0; } /* save pwm value */ blmc.pwm = pwm; /* do spinup with small pwm */ if (blmc.flags & FLAG_PWM_SPINUP) pwm = params.spinup_pwm; /* raise current-limit, set flag */ if (blmc.current > params.current_limit) { blmc.flags |= FLAG_CURRENT_LIMIT; blmc.pwm_limit++; /* lower current-limit */ } else if (blmc.pwm_limit > 0) { blmc.pwm_limit--; } else if (blmc.pwm_limit == 0) { blmc.flags &= ~FLAG_CURRENT_LIMIT; } /* prevent overflow */ if (blmc.pwm_limit > pwm) blmc.pwm_limit = pwm; /* set new value */ pwm -= blmc.pwm_limit; /* limit pwm */ if (pwm > params.pwm_max) pwm = params.pwm_max; OCR1A = pwm; OCR1B = pwm; OCR2 = pwm; } ISR(ANA_COMP_vect) { next_phase(); } ISR(ADC_vect) { static uint16_t current_tmp, voltage_tmp; static uint8_t current_cnt, voltage_cnt; uint8_t channel = ADMUX & 0x0F; uint16_t value = ADCW; /* restore channel */ ADMUX = next_sense; /* turn off ADC, disable interrupt */ ADCSRA = 0x00; /* enable Analog Comparator with Interrupts */ if (blmc.flags & FLAG_COM_NORMAL) ACSR |= (1< params.current_max) blmc.flags |= FLAG_OVERCURRENT; } else { voltage_tmp += value; voltage_cnt++; if (voltage_cnt == 6) { blmc.voltage = voltage_tmp; voltage_tmp = 0; voltage_cnt = 0; if (blmc.voltage < params.voltage_min) blmc.flags |= FLAG_UNDERVOLTAGE; } } }