123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- //timer02.c
- // use atmega timer2 as main system timer instead of timer0
- // timer0 is used for fast pwm (OC0B output)
- // original OVF handler is disabled
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include "Arduino.h"
- #include "io_atmega2560.h"
- #define BEEPER 84
- uint8_t timer02_pwm0 = 0;
- void timer02_set_pwm0(uint8_t pwm0)
- {
- TCCR0A |= (2 << COM0B0); //switch OC0B to OCR mode
- OCR0B = (uint16_t)OCR0A * pwm0 / 255;
- timer02_pwm0 = pwm0;
- }
- void timer02_init(void)
- {
- //save sreg
- uint8_t _sreg = SREG;
- //disable interrupts for sure
- cli();
- //mask timer0 interrupts - disable all
- TIMSK0 &= ~(1<<TOIE0);
- TIMSK0 &= ~(1<<OCIE0A);
- TIMSK0 &= ~(1<<OCIE0B);
- //setup timer0
- TCCR0A = 0x00; //COM_A-B=00, WGM_0-1=00
- OCR0A = 200; //max PWM value (freq = 40kHz)
- OCR0B = 0; //current PWM value
- //switch timer0 to mode 5 (Phase Correct PWM)
- TCCR0A |= (1 << WGM00); //WGM_0-1=01
- TCCR0B = (1 << CS00) | (1 << WGM02); //WGM_2=1, CS_0-2=001 (no prescaling)
- TCCR0A |= (2 << COM0B0); //switch OC0B to OCR mode
- //setup timer2
- TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00
- TCCR2B = (4 << CS20); //WGM_2=0, CS_0-2=011
- //mask timer2 interrupts - enable OVF, disable others
- TIMSK2 |= (1<<TOIE2);
- TIMSK2 &= ~(1<<OCIE2A);
- TIMSK2 &= ~(1<<OCIE2B);
- //set timer2 OCR registers (OCRB interrupt generated 0.5ms after OVF interrupt)
- OCR2A = 0;
- OCR2B = 128;
- //restore sreg (enable interrupts)
- SREG = _sreg;
- }
- //following code is OVF handler for timer 2
- //it is copy-paste from wiring.c and modified for timer2
- //variables timer0_overflow_count and timer0_millis are declared in wiring.c
- // the prescaler is set so that timer0 ticks every 64 clock cycles, and the
- // the overflow handler is called every 256 ticks.
- #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
- // the whole number of milliseconds per timer0 overflow
- #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
- // the fractional number of milliseconds per timer0 overflow. we shift right
- // by three to fit these numbers into a byte. (for the clock speeds we care
- // about - 8 and 16 MHz - this doesn't lose precision.)
- #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
- #define FRACT_MAX (1000 >> 3)
- //extern volatile unsigned long timer0_overflow_count;
- //extern volatile unsigned long timer0_millis;
- //unsigned char timer0_fract = 0;
- volatile unsigned long timer2_overflow_count;
- volatile unsigned long timer2_millis;
- unsigned char timer2_fract = 0;
- ISR(TIMER2_OVF_vect)
- {
- // copy these to local variables so they can be stored in registers
- // (volatile variables must be read from memory on every access)
- unsigned long m = timer2_millis;
- unsigned char f = timer2_fract;
- m += MILLIS_INC;
- f += FRACT_INC;
- if (f >= FRACT_MAX)
- {
- f -= FRACT_MAX;
- m += 1;
- }
- timer2_fract = f;
- timer2_millis = m;
- timer2_overflow_count++;
- }
- unsigned long millis2(void)
- {
- unsigned long m;
- uint8_t oldSREG = SREG;
- // disable interrupts while we read timer0_millis or we might get an
- // inconsistent value (e.g. in the middle of a write to timer0_millis)
- cli();
- m = timer2_millis;
- SREG = oldSREG;
- return m;
- }
- unsigned long micros2(void)
- {
- unsigned long m;
- uint8_t oldSREG = SREG, t;
- cli();
- m = timer2_overflow_count;
- #if defined(TCNT2)
- t = TCNT2;
- #elif defined(TCNT2L)
- t = TCNT2L;
- #else
- #error TIMER 2 not defined
- #endif
- #ifdef TIFR2
- if ((TIFR2 & _BV(TOV2)) && (t < 255))
- m++;
- #else
- if ((TIFR & _BV(TOV2)) && (t < 255))
- m++;
- #endif
- SREG = oldSREG;
- return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
- }
- void delay2(unsigned long ms)
- {
- uint32_t start = micros2();
- while (ms > 0)
- {
- yield();
- while ( ms > 0 && (micros2() - start) >= 1000)
- {
- ms--;
- start += 1000;
- }
- }
- }
- void tone2(__attribute__((unused)) uint8_t _pin, __attribute__((unused)) unsigned int frequency/*, unsigned long duration*/)
- {
- PIN_SET(BEEPER);
- }
- void noTone2(__attribute__((unused)) uint8_t _pin)
- {
- PIN_CLR(BEEPER);
- }
|