unsigned long micros() { unsigned long m; // uint8_t oldSREG = SREG, t; uint8_t t = 0; istate_t state = __get_interrupt_state(); __disable_interrupt(); // cli(); m = timer0_overflow_count; // t = TCNT0; #warning what is this tcnt0 doing? #ifdef TIFR0 if ((TIFR0 & _BV(TOV0)) && (t < 255)) m++; #else // if ((TIFR & _BV(TOV0)) && (t < 255)) // m++; #endif // SREG = oldSREG; __set_interrupt_state(state); return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); }
void HotStepper::setup(char timer){ if(firstInstance){ firstInstance->instanceSetup(); } // initialize Timer2 for a 3ms duty cycle cli(); // disable global interrupts if(timer == TIMER1INT){ TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B TCNT1 = 0; // initialize counter value to 0 // set compare match register to desired timer count: OCR1A = 48000 / (16/clockCyclesPerMicrosecond()); // turn on CTC mode: TCCR1B |= (1 << WGM12); // Set CS10 bit for no prescaler: TCCR1B |= (1 << CS10); // enable timer compare interrupt: TIMSK1 |= (1 << OCIE1A); }else{ TCCR2A = 0; // set entire TCCR2A register to 0 TCCR2B = 0; // same for TCCR2B TCNT2 = 0; // initialize counter value to 0 // set compare match register to desired timer count: OCR2A = 187 / (16/clockCyclesPerMicrosecond()); // turn on CTC mode TCCR2A |= (1 << WGM21); // Set CS21 and CS22 bits for 256 prescaler TCCR2B |= (1 << CS21); TCCR2B |= (1 << CS22); // enable timer compare interrupt TIMSK2 |= (1 << OCIE2A); } sei(); // enable global interrupts }
void SoftwareServo::write(int angleArg) { if ( angleArg < 0) angleArg = 0; if ( angleArg > 180) angleArg = 180; angle = angleArg; // bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true // That 64L on the end is the TCNT0 prescaler, it will need to change if the clock's prescaler changes, // but then there will likely be an overflow problem, so it will have to be handled by a human. pulse0 = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/64L; }
void PWMServo::write(int angleArg) { uint16_t p; if (angleArg < 0) angleArg = 0; if (angleArg > 180) angleArg = 180; angle = angleArg; // bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true // That 8L on the end is the TCNT1 prescaler, it will need to change if the clock's prescaler changes, // but then there will likely be an overflow problem, so it will have to be handled by a human. p = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/8L; if (pin == 9) OCR1A = p; if (pin == 10) OCR1B = p; }
unsigned long micros() { unsigned long m; uint8_t oldSREG = SREG, t; cli(); m = timer0_overflow_count; #if defined(TCNT0) t = TCNT0; #elif defined(TCNT0L) t = TCNT0L; #else #error TIMER 0 not defined #endif #ifdef TIFR0 if ((TIFR0 & (1<<TOV0)) && (t < 255)) m++; #else if ((TIFR & (1<<TOV0)) && (t < 255)) m++; #endif SREG = oldSREG; return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); }
// frequency (in hertz) and duration (in milliseconds). void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) { _pin = esp8266_pinToGpio[_pin]; int8_t _index; _index = toneBegin(_pin); if (_index >= 0) { // Set the pinMode as OUTPUT pinMode(_pin, OUTPUT); // Calculate the toggle count if (duration > 0) { toggle_counts[_index] = 2 * frequency * duration / 1000; } else { toggle_counts[_index] = -1; } // set up the interrupt frequency switch (tone_timers[_index]) { case 0: // Not currently supported break; case 1: timer1_disable(); timer1_isr_init(); timer1_attachInterrupt(t1IntHandler); timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP); timer1_write((clockCyclesPerMicrosecond() * 500000) / frequency); break; } } }
unsigned long Cron::micros() { unsigned long m; uint8_t oldSREG = SREG, t; cli(); m = timer0_overflow_count; t = TCNT0; if ((TIFR0 & _BV(TOV0)) && (t < 255)) m++; SREG = oldSREG; return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); }
unsigned long micros(void) { unsigned long m; uint8_t oldSREG = SREG, t; cli(); m = timer0_overflow_count; t = TCNT0; #ifdef TIFR0 if ((TIFR0 & _BV(TOV0)) && (t < 255)) m++; #else if ((TIFR & _BV(TOV0)) && (t < 255)) m++; #endif SREG = oldSREG; return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); }
unsigned long FrequencyTimer2::getPeriod() { #if defined(TCCR2B) uint8_t p = (TCCR2B & 7); unsigned long v = OCR2A; #elif defined(TCCR) uint8_t p = (TCCR2 & 7); unsigned long v = OCR2; #elif defined(TCCR4B) uint8_t p = (TCCR4B & 7); unsigned long v = OCR4C; #endif uint8_t shift; switch(p) { case 0 ... 1: shift = 0; break; case 2: shift = 3; break; case 3: shift = 5; break; case 4: shift = 6; break; case 5: shift = 7; break; case 6: shift = 8; break; case 7: shift = 10; break; } return (((v+1) << (shift+1)) + 1) / clockCyclesPerMicrosecond(); // shift+1 converts from half-period to period }
void PWMServo::seizeTimer1() { uint8_t oldSREG = SREG; cli(); TCCR1A = _BV(WGM11); /* Fast PWM, ICR1 is top */ TCCR1B = _BV(WGM13) | _BV(WGM12) /* Fast PWM, ICR1 is top */ | _BV(CS11) /* div 8 clock prescaler */ ; OCR1A = 3000; OCR1B = 3000; ICR1 = clockCyclesPerMicrosecond()*(20000L/8); // 20000 uS is a bit fast for the refresh, 20ms, but // it keeps us from overflowing ICR1 at 20MHz clocks // That "/8" at the end is the prescaler. #if defined(__AVR_ATmega8__) TIMSK &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) ); #else TIMSK1 &= ~(_BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) ); #endif SREG = oldSREG; // undo cli() }
void FrequencyTimer2::setPeriod(unsigned long period) { uint8_t pre, top; if ( period == 0) period = 1; period *= clockCyclesPerMicrosecond(); period /= 2; // we work with half-cycles before the toggle #if defined(TCCR2A) || defined(TCCR2) if ( period <= 256) { pre = 1; top = period-1; } else if ( period <= 256L*8) { // this for AUDIO_RATE 16384, pre=2 is a bitfield 010 which means prescaler = 8 pre = 2; top = period/8-1; } else if ( period <= 256L*32) { pre = 3; top = period/32-1; } else if ( period <= 256L*64) { pre = 4; top = period/64-1; } else if ( period <= 256L*128) { pre = 5; top = period/128-1; } else if ( period <= 256L*256) { pre = 6; top = period/256-1; } else if ( period <= 256L*1024) { pre = 7; top = period/1024-1; } else { pre = 7; top = 255; } #elif defined(TCCR4A) unsigned long prescaler = 1; for(int i=1; i<=16; i++){ if ( period <= 256*prescaler){ pre = i; top = period/prescaler -1; break; } prescaler *= 2; } //pre = 4; // this for AUDIO_RATE 16384, pre=4 is a bitfield 100 which means prescaler = 8 //top = period/8-1; #endif #if defined(TCCR2A) TCCR2B = 0; TCCR2A = 0; TCNT2 = 0; #if defined(ASSR) && defined(AS2) ASSR &= ~_BV(AS2); // use clock, not T2 pin #endif OCR2A = top; //Clear Timer on Compare Match (CTC) mode TCCR2A = (_BV(WGM21) | ( FrequencyTimer2::enabled ? _BV(COM2A0) : 0)); TCCR2B = pre; #elif defined(TCCR2) TCCR2 = 0; TCNT2 = 0; ASSR &= ~_BV(AS2); // use clock, not T2 pin OCR2 = top; TCCR2 = (_BV(WGM21) | ( FrequencyTimer2::enabled ? _BV(COM20) : 0) | pre); #elif defined(TCCR4A) // TB2013 for 32u4 (leonardo,teensy) TCCR4A = 0; TCCR4B = 0; TCCR4C = 0; TCCR4D = 0; TCCR4E = 0; TCNT4 = 0; OCR4C= top; // Table 15-19 //TCCR4A = _BV(COM4A1); TCCR4B = pre ; TIMSK4 = FrequencyTimer2::enabled ? _BV(OCIE4A) : 0; #endif }
// Helper functions static inline ICACHE_RAM_ATTR uint32_t MicrosecondsToCycles(uint32_t microseconds) { return clockCyclesPerMicrosecond() * microseconds; }
void FrequencyTimer2::setPeriodMicroSeconds(unsigned long period) { period *= clockCyclesPerMicrosecond(); setPeriodCPUCycles(period); }