// Set up PWM on the given pin boolean pwmInitDeciHertz(const IOPin* pin, uint32_t deciHertz, PERCENTAGE duty, uint32_t* actualDeciHertz){ boolean rtn = FALSE; const TimerCompare* channel = compareFromIOPin(pin); if(channel==null){ setError(PWM_PIN_NOT_AVAILABLE); }else{ // The pin is valid // The pin is valid and available TIMER_MODE mode; uint16_t icr; uint16_t prescaler; uint32_t actual; const Timer* timer = compareGetTimer(channel); // Find the best PWM setting boolean valid = timerCalcPwm(timer, deciHertz, 100, &mode, &icr, &prescaler, &actual); if(!valid){ // There is no PWM setting that is valid setError( (timerIsInUse(timer)) ? PWM_TIMER_IN_USE : TIMER_HAS_NO_PWM ); }else{ // Lets set up the PWM timerSetMode(timer,mode); if(modeIsICR(mode)){ // Set the ICR PORT icrPort = pgm_read_word(&timer->pgm_icr); _SFR_MEM16(icrPort)=icr; } // Mark the channel as in use // compareAttach(channel,&nullTimerCompareCallback,0,null); // Turn the pin into an output, low pin_make_output(pin, FALSE); // Turn on the PWM pin output compareSetOutputMode(channel, CHANNEL_MODE_NON_INVERTING); // Turn on the timer timerSetPrescaler(timer,prescaler); // Set the initial duty cycle pwmSetDutyCycle(pin,duty); // Set the return value if(actualDeciHertz){ *actualDeciHertz = actual; } rtn = TRUE; } } return rtn; }
// Author: unknown // Modified by : Markus Joos ([email protected]) #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <avr/sleep.h> #include "global.h" #include "timer.h" // Program ROM constants // the pre-scale division values stored in order of timer control register index // STOP, CLK, CLK/8, CLK/64, CLK/256, CLK/1024 unsigned short __attribute__ ((progmem)) const TimerPrescaleFactor[] = {0,1,8,64,256,1024}; typedef void (*voidFuncPtr)(void); volatile static voidFuncPtr TimerIntFunc; // Delay for a minimum of <us> microseconds // The time resolution is dependent on the time the loop takes // e.g. with 4Mhz and 5 cycles per loop, the resolution is 1.25 us //***********************/ void delay_us(u16 time_us) //Called from ipmi_if.c and fru.c //***********************/ { u16 delay_loops; register u16 i; // one loop takes 5 cpu cycles delay_loops = (time_us + 3) / 22 * 3 * CYCLES_PER_US; // +3 for rounding up (dirty) //MJ: "22 * 3" is the result of a manual calibration of the delay for (i=0; i < delay_loops; i++) asm volatile("nop"); //MJ: Without the "nop" there is the risk that the loop gets removed by the optimizer } //*****************/ void timerInit(void) //Called from mmc_main.c //*****************/ { TimerIntFunc = 0; // detach all user functions from interrupts // Initialise timer 0 outb(TCCR0, (inb(TCCR0) | CTC_MODE)); // set set CTC mode timerSetPrescaler(TIMER0PRESCALE); // set pre-scaler outb(TCNT0, 0); // reset TCNT0 outb(OCR0, 0x8C); // set value to output compare register sbi(TIMSK, OCIE0); // enable output compare match interrupt }
static boolean initPWM(const IOPin* pin, uint32_t deciHertz){ const TimerCompare* channel = compareFromIOPin(pin); if(channel==null){ setError(PWM_PIN_NOT_AVAILABLE); return FALSE; } if(compareIsInUse(channel)){ setError(PWM_PIN_IN_USE); return FALSE; } TIMER_MODE mode; uint16_t icr; uint16_t prescaler; const Timer* timer = compareGetTimer(channel); // Find the best PWM setting for 10kHz, with 128 steps boolean valid = timerCalcPwm(timer, deciHertz, 128, &mode, &icr, &prescaler); if(!valid){ // There is no PWM setting that is valid setError( (timerIsInUse(timer)) ? PWM_TIMER_IN_USE : TIMER_HAS_NO_PWM ); }else{ // Lets set up the PWM if(!timerIsInUse(timer)){ timerSetMode(timer,mode); if(modeIsICR(mode)){ // Set the ICR PORT icrPort = pgm_read_word(&timer->pgm_icr); _SFR_MEM16(icrPort)=icr; } } // Make it an output pin and set high for brake pin_make_output(pin,TRUE); // Use inverting PWM compareSetOutputMode(channel,CHANNEL_MODE_INVERTING); // Mark the channels as in use compareAttach(channel,&nullTimerCompareCallback,0,null); // Do this last as it then turns on the timer timerSetPrescaler(timer,prescaler); } return valid; }
/* void delay_ms(unsigned char time_ms) { unsigned short delay_count = F_CPU / 4000; unsigned short cnt; asm volatile ("\n" "L_dl1%=:\n\t" "mov %A0, %A2\n\t" "mov %B0, %B2\n" "L_dl2%=:\n\t" "sbiw %A0, 1\n\t" "brne L_dl2%=\n\t" "dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt) :"r"(time_ms), "r"((unsigned short) (delay_count)) ); } */ void timerInit(void) { // detach all user functions from interrupts TimerIntFunc = 0; // initialize timer 0 outb(TCCR0, (inb(TCCR0) | CTC_MODE)); // set set CTC mode timerSetPrescaler( TIMER0PRESCALE ); // set prescaler // timerSetPrescaler( TIMER_CLK_DIV1024 ); // set prescaler outb(TCNT0, 0); // reset TCNT0 outb(OCR0, 0x8C); // set value to output compare register sbi(TIMSK, OCIE0); // enable output compare match interrupt // enable interrupts //sei(); }