/*--------------------------------------------------------------------------*/ ISR(TIMER0_A1, rtimer_a01_isr) { /* store the IV register as any read/write resets interrupt flags */ uint16_t ivreg = TA0IV; if(ivreg & TA0IV_TACCR1) { /* rtimer interrupt */ TA0CCTL1 &= ~CCIFG; watchdog_start(); /* check for and run any pending rtimers */ rtimer_run_next(); /* also check for any pending events and wake up if needed */ if(process_nevents() > 0) { LPM4_EXIT; } watchdog_stop(); } else if(ivreg & TA0IV_TACCR2) { /* simple pwm interrupt */ TA0CCTL2 &= ~CCIFG; if(spwm.on_time > 0) { if(spwm.on_time == period) { TA0CCTL2 &= ~CCIE; /* no need for interrupt, is at 100% DC */ /* SIMPLE_PWM_PORT(OUT) |= (1 << spwm.pin);*/ pwm_on_cb(); } else { /* normal on-case */ if(period_end) { period_end = 0; TA0CCR2 = TAR + spwm.on_time; /* SIMPLE_PWM_PORT(OUT) |= (1 << spwm.pin);*/ pwm_off_cb(); } else { period_end = 1; TA0CCR2 = TAR + (period - spwm.on_time); /* SIMPLE_PWM_PORT(OUT) &= ~(1 << spwm.pin);*/ pwm_on_cb(); } } } } }
/* * set pwm on at a duty cycle expressed in percent from 0 to 100. If crucial, * calculate your own pulsetime and use that function due to rounding errors in * this function. */ void simple_pwm_on(uint8_t dc) { if(dc > 100) { return; } if(dc == 100) { TA0CCTL2 &= ~CCIE; /* no need for interrupt */ spwm.on_time = period; /* SIMPLE_PWM_PORT(OUT) |= (1 << spwm.pin);*/ pwm_on_cb(); } else if(dc == 0) { TA0CCTL2 &= ~CCIE; /* no need for interrupt */ spwm.on_time = 0; /* SIMPLE_PWM_PORT(OUT) &= ~(1 << spwm.pin);*/ pwm_off_cb(); } else { /* convert duty cycle to PWM clock ticks */ uint8_t finetime = (dc * period) / 100; if(finetime == 0 && dc != 0) { /* rounding errors, go for minimum-like */ finetime = 2; } /* set up a compare match for the next PWM period */ TA0CCR2 = TAR + finetime; TA0CCTL2 = CCIE; spwm.on_time = finetime; } }
/* * set pwm on at a specified pulsetime measured in SIMPLE_PWM_SECOND ticks/s. * * The period is (SIMPLE_PWM_SECOND / SIMPLE_PWM_FREQ) - 1, measured in the * same number of ticks/s. Default is 128 Hz and 32768 ticks/s, leaving us w * 255 ticks/period, so the range becomes 0..255. * Use this for precision work, eg a servo motor. */ void simple_pwm_pulsetime(uint16_t finetime) { if(finetime >= period) { TA0CCTL2 &= ~CCIE; /* no need for interrupt */ spwm.on_time = period; /* SIMPLE_PWM_PORT(OUT) |= (1 << spwm.pin);*/ pwm_on_cb(); } else if(finetime == 0) { TA0CCTL2 &= ~CCIE; /* no need for interrupt */ spwm.on_time = 0; /* SIMPLE_PWM_PORT(OUT) &= ~(1 << spwm.pin);*/ pwm_off_cb(); } else { /* set up a compare match for the next PWM period */ TA0CCR2 = TAR + finetime; TA0CCTL2 = CCIE; spwm.on_time = finetime; } }