resources/libtiny/Servo.cpp
//=============================================================================
// FUNCTION:    void timerCompareMatchISR()
//
// DESCRIPTION: Interrupt service routine for timer0 compare A match.
//              This is where the magic happens.
//
// INPUT:       Nothing
//
// RETURNS:     Nothing
//=============================================================================
void timerCompareMatchISR()
DESCRIPTION: Interrupt service routine for timer0 compare A match.
This is where the magic happens.

Nothing

Nothing
void timerCompareMatchISR () DESCRIPTION : Interrupt service routine for timer0 compare A match . This is where the magic happens . Nothing Nothing
void ServoSequencer::timerCompareMatchISR()
{
    switch (state)
    {
    case WAITING_TO_SET_PIN_HIGH:
        ++servoIndex;
        if(servoIndex == MAX_SERVOS)
        {
            servoIndex = 0;
        }
        else
        {
        }
        if( servoRegistry[servoIndex].enabled == true )
        {
          #if defined(__AVR_ATtinyX5__)
            PORTB |= (1 << servoRegistry[servoIndex].pin);
          #elif defined(__AVR_ATtinyX61__)
            uint8_t bit = digitalPinToBitMask(servoRegistry[servoIndex].pin);
            uint8_t port = digitalPinToPort(servoRegistry[servoIndex].pin);
            volatile uint8_t *out;
            out = portOutputRegister(port);
            *out|=bit;
          #else 
            #error "Unsupported part - how did execution get here?"
          #endif
        }
        else
        {
        }
        TCNTn  = 0;
        OCRnx = 64 - TRIM_DURATION; 
        state = WAITING_FOR_512_MARK;
        break;
    case WAITING_FOR_512_MARK:
        OCRnx = servoRegistry[servoIndex].pulseLengthInTicks;
        state = WAITING_TO_SET_PIN_LOW;
        TCNTn  = 0;
        if(OCRnx == 0)
        {
           TCNTn = 0xFF;
        }
        else
        {
            TIFR = (1 << OCF0A);  
        }
        break;
    case WAITING_TO_SET_PIN_LOW:
        if( servoRegistry[servoIndex].enabled == true )
        {
          #if defined(__AVR_ATtinyX5__)
            PORTB &= ~(1 << servoRegistry[servoIndex].pin);
          #elif defined(__AVR_ATtinyX61__)
            uint8_t bit = digitalPinToBitMask(servoRegistry[servoIndex].pin);
            uint8_t port = digitalPinToPort(servoRegistry[servoIndex].pin);
            volatile uint8_t *out;
            out = portOutputRegister(port);
            *out&=~bit;
          #else 
            #error "Unsupported part - how did execution get here?"
          #endif
        }
        else
        {
        }
        if( (64 + servoRegistry[servoIndex].pulseLengthInTicks) > 255 )
        {
            state = WAITING_TO_SET_PIN_HIGH;
            OCRnx = 512 - (64 + servoRegistry[servoIndex].pulseLengthInTicks);
        }
        else
        {
            state = WAITING_FOR_2048_MARK;
            OCRnx = 255 - (64 + servoRegistry[servoIndex].pulseLengthInTicks);
        }
        TCNTn  = 0;
        break;
    case WAITING_FOR_2048_MARK:
        state = WAITING_TO_SET_PIN_HIGH;
        TCNTn  = 0;
        OCRnx = 255;
        break;
    }
}
void ServoSequencer :: timerCompareMatchISR ( ) { switch ( state ) { case WAITING_TO_SET_PIN_HIGH : ++ servoIndex ; if ( servoIndex == MAX_SERVOS ) { servoIndex = 0 ; } else { } if ( servoRegistry [ servoIndex ] . enabled == true ) { #if defined ( __AVR_ATtinyX5__ ) PORTB |= ( 1 << servoRegistry [ servoIndex ] . pin ) ; #elif defined ( __AVR_ATtinyX61__ ) uint8_t bit = digitalPinToBitMask ( servoRegistry [ servoIndex ] . pin ) ; uint8_t port = digitalPinToPort ( servoRegistry [ servoIndex ] . pin ) ; volatile uint8_t * out ; out = portOutputRegister ( port ) ; * out |= bit ; #else #error  "Unsupported part - how did execution get here?" #endif } else { } TCNTn = 0 ; OCRnx = 64 - TRIM_DURATION ; state = WAITING_FOR_512_MARK ; break ; case WAITING_FOR_512_MARK : OCRnx = servoRegistry [ servoIndex ] . pulseLengthInTicks ; state = WAITING_TO_SET_PIN_LOW ; TCNTn = 0 ; if ( OCRnx == 0 ) { TCNTn = 0xFF ; } else { TIFR = ( 1 << OCF0A ) ; } break ; case WAITING_TO_SET_PIN_LOW : if ( servoRegistry [ servoIndex ] . enabled == true ) { #if defined ( __AVR_ATtinyX5__ ) PORTB &= ~ ( 1 << servoRegistry [ servoIndex ] . pin ) ; #elif defined ( __AVR_ATtinyX61__ ) uint8_t bit = digitalPinToBitMask ( servoRegistry [ servoIndex ] . pin ) ; uint8_t port = digitalPinToPort ( servoRegistry [ servoIndex ] . pin ) ; volatile uint8_t * out ; out = portOutputRegister ( port ) ; * out &= ~ bit ; #else #error  "Unsupported part - how did execution get here?" #endif } else { } if ( ( 64 + servoRegistry [ servoIndex ] . pulseLengthInTicks ) > 255 ) { state = WAITING_TO_SET_PIN_HIGH ; OCRnx = 512 - ( 64 + servoRegistry [ servoIndex ] . pulseLengthInTicks ) ; } else { state = WAITING_FOR_2048_MARK ; OCRnx = 255 - ( 64 + servoRegistry [ servoIndex ] . pulseLengthInTicks ) ; } TCNTn = 0 ; break ; case WAITING_FOR_2048_MARK : state = WAITING_TO_SET_PIN_HIGH ; TCNTn = 0 ; OCRnx = 255 ; break ; } }
FUNCTION:    void timerCompareMatchISR()
DESCRIPTION: Interrupt service routine for timer0 compare A match.
FUNCTION : void timerCompareMatchISR () DESCRIPTION : Interrupt service routine for timer0 compare A match .
//go to the next servo in the registry //if we are the end of the registry, go to the beginning of it //we are not at the end, leave the servo index as is //if this servo is enabled set the pin high //This servo position is not enabled, don't manipulate the pin //reset the counter to 0 //set the compare value to 64 (512 us). This is the constant pulse offset. //trim off 4 ticks (32us), this is about the total combined time we spent inside this ISR; //update our state //set the compare value to the additional amount of timer ticks the pulse should last //update our state //reset the counter to 0 //Did we just set OCRnx to zero? //Since we are setting OCRnx and TCNTn to 0 we are not going to get an interrupt //until the counter overflows and goes back to 0. //set the counter its highest value, to have it overflow right away. //This will cause this interrupt to fire again almost immediately (at the next timer tick) //otherwise we need to clear the OCF0A flag because it is possible that the //counter value incremented and matched the output compare value while this //function was being executed // write logical 1 to the OCF0A flag to clear it // also have to write 0 to all other bits for this to work. //if this servo is enabled set the pin low //This servo position is not enabled, don't manipulate the pin //check if the length of this pulse is 2048 microseconds or longer //This pulse length has passed the 2048 us mark, so we skip state WAITING_FOR_2048_MARK //update state //set the compare value to the amount of time (in timer ticks) we need to wait to reach //4096 microseconds mark //which is 512 minus the total pulse length. (resulting number will be between 0 and 255 inclusive) //This pulse length has not reached the 2048 us mark, therefor we have to get to that mark first //update state //set OCRnx to the amount of time (in timer ticks) we have to wait to reach this mark //which is 255 minus the total pulse length //reset the counter to 0 //update state //reset the counter to 0 //set the compare value to the longest length of time, 255 ticks, or 2040 microseconds //This will take us to the ~4096 microsecond mark, //at which point the cycle starts again with the next servo slot. //end switch