//************************************************************* // BOOST1.c SAAB 9-3 T5 BCV to T7 BCV valve conversion // // (c) 2016 Escherlogic Inc. All right reserved. // // By: Stefan Hax stefan@escherlogic.com // // You are free to use this at your own risk! // //************************************************************* // ATtiny45 code to convert SAAB 93 T5 boost control valve output // from the ECU to use the newer signle coil T7 boost control valve // // for T7 valve PWM freq is 50Hz for engine speeds lower than 2500RPM // and 32Hz for higher engine speeds // // for T5 valve freq is 90Hz for engine speeds lower than 2500RPM // and 70Hz for higher engine speeds // //********************************************************************** #include #include #include #include #include //********************* Memory Config ****************************************** #define EEPROMMEM __attribute__ ((section (".eeprom"))) uint8_t eeprominit[] EEPROMMEM = {0,0,0,255}; // default eeprom memory settings #define HFUSEMEM __attribute__ ((section (".hfuse"))) uint8_t hfuseinit[] HFUSEMEM = {0xd6}; // hfuse settings -- protect flash during erase -- BOD = 1.8v #define LFUSEMEM __attribute__ ((section (".lfuse"))) uint8_t lfuseinit[] LFUSEMEM = {0xe2}; // lfuse settings -- internal RC osc @ 8Mhz #define EFUSEMEM __attribute__ ((section (".efuse"))) uint8_t efuseinit[] EFUSEMEM = {0xff}; // efuse settings //****************************************************************************** //************************************************ // Port B I/O assignment #define T5A_IN 3 // PB3 connected to T5 A coil drive (input) #define T5B_IN 4 // PB4 connected to T5 B coil drive (input) #define T7_VALVE 0 // PB0 connected to T7 valve (output) //*********************************************** #define VALVE_ON PORTB |= _BV(T7_VALVE) #define VALVE_OFF PORTB &= (uint8_t)~_BV(T7_VALVE) //********************************************************************************************************* // timer0 in CTC mode to generate 50Hz x 100 and 32Hz x 100 interrupt rates #define T_SLOW 38 #define T_FAST 24 // with timer1 clock rate @ 15.625KHz(64MHz/4096): Then 90Hz PWM count:173 and 70Hz PWM count:223 #define SLOW_THRESHOLD 200 // pwm_speed states: enum { PWM_FAST=0, PWM_SLOW }; // T5 2-coil input states: enum { DC_OFF=0, DC_ON, DC_REST }; // globals volatile uint8_t pwm_speed, pwm_out, pwm_cnt; volatile uint8_t dc_state, dc_count, dc_on, dc_calc; //********************************************* // valve output ISR ISR(TIM0_COMPA_vect) { pwm_cnt++; if(pwm_cnt >= 100) { pwm_cnt = 0; OCR0A = (pwm_speed == PWM_FAST)? T_FAST : T_SLOW; // set the TOP valve for the correct PWM frequency } if(pwm_cnt >= pwm_out) { VALVE_OFF; } else { VALVE_ON; } } //******************************************* // timer1 overflow -- if this ISR is called then there is a dead input!! -- Reset everything... ISR(TIM1_OVF_vect) { pwm_speed = PWM_FAST; pwm_out = 0; dc_state = DC_OFF; dc_calc = 0; } //******************************************* // Pin Change ISR (T5A / T5B inputs) ISR(PCINT0_vect) { switch(dc_state) { default: case DC_OFF: if(PINB & _BV(T5A_IN)) { // NOT TRUE!! } else { // TRUE!! dc_count = TCNT1; TCNT1 = 0; dc_state = DC_ON; dc_calc = 1; // trigger PWM output calculations } break; case DC_ON: if(PINB & _BV(T5B_IN)) { // NOT TRUE!! } else { // TRUE!! dc_on = TCNT1; dc_state = DC_REST; } break; case DC_REST: if( PINB & (_BV(T5A_IN) | _BV(T5B_IN)) ) { // BOTH NOT TRUE!! dc_state = DC_OFF; } break; } } //*********************************** // initialize... void init(void) { uint16_t n; //****** timer0 setup *************************** // generate interrupts for bit-bang-PWM output // where: 0 -> output OFF // and 100 -> output 100% TCCR0A = _BV(WGM01); // CTC mode TCCR0B = _BV(CS01) | _BV(CS00); // 8MHz dix 64 OCR0A = (pwm_speed == PWM_FAST)? T_FAST : T_SLOW; // set the TOP valve for the correct PWM frequency pwm_out = 5; // default duty cycle TIMSK |= _BV(OCIE0A); // enable interrupt //****** T7 Valve setup ************************ DDRB = _BV(T7_VALVE); // T7 valve output VALVE_OFF; // turn valve OFF //******* PLL *********************************** // setup for 64MHHz PLLCSR = _BV(PLLE); // enable PLL for(n=0; n<1000; n++); // time delay > 100us while(!(PLLCSR & _BV(PLOCK))); // wait for PLL to lock PLLCSR |= _BV(PCKE); // enable Pclk //******* timer1 setup ************************** // divide by 4096 TCCR1 = _BV(CS13) | _BV(CS12) | _BV(CS10); // PCK/4096 TIMSK |= _BV(TOIE1); // just enable overflow interrupt //***** control input *************************** // setup port change int PCMSK = _BV(T5A_IN) | _BV(T5B_IN); // enable only PB3 & PB4 for PC Int GIMSK |= _BV(PCIE); // enable PC Int //***** global int enable ********************* sei(); // enable global interrupt } //************************************* // compute T7 valve PWM signal and set void pwm_go(void) { if(dc_calc) { // signal from PCINT0 ISR dc_calc = 0; // clear the flag if(dc_count) { // if(dc_count > SLOW_THRESHOLD) { // determine engine speed state.. pwm_speed = PWM_SLOW; } else { pwm_speed = PWM_FAST; } pwm_out = (uint8_t)( ((uint16_t)dc_on * 100) / (uint16_t)dc_count); // compute output PWM } else { // avoiding div/0 pwm_speed = PWM_FAST; pwm_out = 2; } } } //************************************ // main int main(void) { init(); while(1) { pwm_go(); } } //***** done *************************