NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » RC5 infra red decoding

October 15, 2012
by ankush_karche
ankush_karche's Avatar

Hello All,

Earlier I had created one thread on infra red programming. For that I received advice to study basics again and I am progressing on that and getting comfortable. Now I am looking in to below code, all credit goes to Peter Fleury for his program.

I have few basic questions.

For any combination of F_CPU and Prescaler how to calculate value of TIMER_0_CNT value. I want to know how 111us with CLK/8 prescale has been calculated ?


Peter Fleury�s Rc5 code http://jump.to/fleury

Code:

include <inttypes.h>

include <avr/io.h>

include <avr/interrupt.h>

include <avr/signal.h>

/ this should be in <avr/io8515.h> !! /

define TMC8_STOP 0

define TMC8_CK8 _BV(CS01)

/ Macros and constants /

define RC5BitHigh() (bit_is_set(PIND,PD3))

define RC5BitLow() (bit_is_clear(PIND,PD3))

define WAITFORTIMER() { while ( timerflag == 0); timerflag = 0; }

define TIMER_0_CNT 0xCA // 111us with CLK/8 prescale

define RC5BITREF1 6

define RC5BITREF2 11

define RC5BITREF3 14

/ function prototypes / unsigned int rc5decode( void );

/ module global variables / static volatile uint8_t timerflag; //must be volatile because modified by interrupt handler

SIGNAL(SIG_OVERFLOW0) / signal handler for timer0 overflow interrupt / { timerflag = 1; // set global variable

TCNT0 = TIMER_0_CNT;         // reset counter to get this interrupt again

}

unsigned int rc5decode( void ) / decoded RC5 data is returned, or 0x0000 if RC5 data not recognized / { unsigned int rc5data; unsigned char timer, i;

// init timer/Counter0    
TCCR0 = TMC8_CK8;                // use CLK/8 prescale 
TCNT0 = TIMER_0_CNT;             // set timer T/16 = 111us 
TIMSK = _BV(TOIE0);              // enable TCNT0 overflow interrupt

// measure startbit 
timerflag = 0; timer = 0; 
while ( RC5BitLow() && (timer < RC5BITREF2) ) { 
    WAITFORTIMER(); 
    timer++; 
} 
if ( (timer > RC5BITREF1) && (timer < RC5BITREF2) ) { 
    // startbit ok, decode

    // wait T/4: synchronize in the middle of first half of second bit 
    while ( timer < RC5BITREF3 ) { 
        WAITFORTIMER(); 
        timer++; 
    }

    // read the remaining bits 
    rc5data = 1; 
    for (i=0; i<13; i++) { 
        rc5data <<= 1;  
        if ( RC5BitHigh() ) { 
            rc5data |= 0x0001; 
            // wait max T/2 for H->L transition (middle of next bit) 
            timer = 0; 
            while ( RC5BitHigh() && (timer < 16) ) { 
                WAITFORTIMER(); 
                timer++; 
            } 
        }else{ 
            rc5data &= ~0x00001; 
            // wait max T/2 for L->H transition (middle of next bit) 
            timer = 0; 
            while ( RC5BitLow() && (timer < 16) ) { 
                WAITFORTIMER(); 
                timer++; 
            } 
        } 
        if ( timer == 16 ) { 
            rc5data = 0x0000;   // error, next bit not found 
            break; 
        }

        // wait 3/4 T: await next bit 
        for ( timer=0; timer < 12 ; timer++) WAITFORTIMER(); 
    }

}else { 
    rc5data = 0x0000;  // error, invalid RC-5 code 
} 
TCCR0 = TMC8_STOP;            // stop timer0

return (rc5data);

}//rc5decode


Your valuable help is appreciated.

Thanks in advance for your time and help.

With kind regards,

Ankush
October 15, 2012
by ankush_karche
ankush_karche's Avatar

Code:

#include <inttypes.h> 
#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <avr/signal.h>

/* this should be in <avr/io8515.h> !! */ 
#define TMC8_STOP   0 
#define TMC8_CK8   _BV(CS01)

/* 
** Macros and constants 
*/ 
#define RC5BitHigh()    (bit_is_set(PIND,PD3)) 
#define RC5BitLow()     (bit_is_clear(PIND,PD3)) 
#define WAITFORTIMER()  { while ( timerflag == 0); timerflag = 0; }

#define TIMER_0_CNT 0xCA     //  111us with CLK/8 prescale 
#define RC5BITREF1  6  
#define RC5BITREF2  11 
#define RC5BITREF3  14

/* 
** function prototypes 
*/ 
unsigned int rc5decode( void );

/* 
** module global variables 
*/ 
static volatile uint8_t timerflag;  //must be volatile because modified by interrupt handler

SIGNAL(SIG_OVERFLOW0) 
/* 
**  signal handler for timer0 overflow interrupt 
*/ 
{ 
    timerflag = 1;               // set global variable

    TCNT0 = TIMER_0_CNT;         // reset counter to get this interrupt again 
}

unsigned int rc5decode( void ) 
/* 
**  decoded RC5 data is returned, or 0x0000 if RC5 data not recognized 
*/ 
{ 
    unsigned int    rc5data; 
    unsigned char   timer, i;

    // init timer/Counter0    
    TCCR0 = TMC8_CK8;                // use CLK/8 prescale 
    TCNT0 = TIMER_0_CNT;             // set timer T/16 = 111us 
    TIMSK = _BV(TOIE0);              // enable TCNT0 overflow interrupt

    // measure startbit 
    timerflag = 0; timer = 0; 
    while ( RC5BitLow() && (timer < RC5BITREF2) ) { 
        WAITFORTIMER(); 
        timer++; 
    } 
    if ( (timer > RC5BITREF1) && (timer < RC5BITREF2) ) { 
        // startbit ok, decode

        // wait T/4: synchronize in the middle of first half of second bit 
        while ( timer < RC5BITREF3 ) { 
            WAITFORTIMER(); 
            timer++; 
        }

        // read the remaining bits 
        rc5data = 1; 
        for (i=0; i<13; i++) { 
            rc5data <<= 1;  
            if ( RC5BitHigh() ) { 
                rc5data |= 0x0001; 
                // wait max T/2 for H->L transition (middle of next bit) 
                timer = 0; 
                while ( RC5BitHigh() && (timer < 16) ) { 
                    WAITFORTIMER(); 
                    timer++; 
                } 
            }else{ 
                rc5data &= ~0x00001; 
                // wait max T/2 for L->H transition (middle of next bit) 
                timer = 0; 
                while ( RC5BitLow() && (timer < 16) ) { 
                    WAITFORTIMER(); 
                    timer++; 
                } 
            } 
            if ( timer == 16 ) { 
                rc5data = 0x0000;   // error, next bit not found 
                break; 
            }

            // wait 3/4 T: await next bit 
            for ( timer=0; timer < 12 ; timer++) WAITFORTIMER(); 
        }

    }else { 
        rc5data = 0x0000;  // error, invalid RC-5 code 
    } 
    TCCR0 = TMC8_STOP;            // stop timer0

    return (rc5data);

}//rc5decode

For any combination of F_CPU and Prescaler how to calculate value of TIMER_0_CNT value. I want to know how 111us with CLK/8 prescale has been calculated ?

October 15, 2012
by Noter
Noter's Avatar

For F_CPU = 14745600hz

scaled 14745600hz / 8 = 1843200hz

timer tick is 1 / 1843200hz = 0.000000543sec or once every 0.543us

counter is 111us / 0.543us = 204.4

I would use a count of 204 to get 111us when F_CPU is 14745600hz and scaler is 8.

October 16, 2012
by ankush_karche
ankush_karche's Avatar

Thanks Noter for the explaination.

Now it makes sense to me and will help at many steps ahead.

Regards, Ankush

Post a Reply

Please log in to post a reply.

Did you know that you need to think about wires differently when you're transmitting signals more than a few inches? Learn more...