Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

C codes for decoding RC5 signals using PIC microcontoller

Status
Not open for further replies.
@btbass

I am using explorer 16 board. #asm doesn't work with compiler. And asm(" "); gives errors "Error: Invalid mnemonic: 'bcf' ". Please help
 

Thank a lot..!!

---------- Post added at 15:22 ---------- Previous post was at 15:15 ----------

Where is htc.h..? sorry I am newbie..
 

The code btbass has provided you is written for the Hi-Tech C Compiler, "htc.h" loads the PIC device specific header files.

BigDog
 
Got it..Included p24FJ128GA010.h....
Still getting errors..see below..

/*--------------------------------------------------------------------

Title : RC5 Interrupt driven Decoder
Filename : rc_decoder.c

Copyright @ BobTheBass 2011

--------------------------------------------------------------------*/

#include "p24FJ128GA010.h"
#include "rc5_decoder.h"

/*--- RC5 Decoder state machine ---*/

enum RC5_STATE{START_S, CALIBRATE_S, DATA_S};

/*--- RC5 code structure ---*/

volatile RC5_CODE RC5_Code;

/*--- RC5 decoder structure ---*/

typedef struct
{
enum RC5_STATE State;
unsigned char bit_time;
unsigned char pulse_t1;
unsigned char pulse_t2;
unsigned char pulse_t3;
unsigned char tolerance;

unsigned char last_bit;
unsigned char bit_counter;
unsigned int rc_data;
}DECODER;

volatile DECODER Decoder;

/*--- Pulse types ---*/

#define PULSE_OK 0
#define PULSE_ERROR 1

/*--- Local function prototypes ---*/

static unsigned char get_pulse_length(void);
static void one_type_pulse(void);
static void two_type_pulse(void);
static void three_type_pulse(void);
static void save_data(unsigned char data);

/*--- Initialise rc5 decoder interrupt ---*/

void int_rc5_decoder(void)
{
RC5_Code.valid = 0;
Decoder.State = START_S;

TRISA = 0x04; /* RA2 as input */

/* Timer should have an overflow period of greater than 5mS and less than 15mS */
/* Overflow period = (1 / (oscfreq / 4)) * 256 * prescaler */

//OPTION = 0x04; /* Pull ups on, Timer 1:32 prescaler for 4MHz oscillator */

T1CON = 0x8010; /* Pull ups on, Timer 1:64 prescaler for 8MHz oscillator */

_INT0IF = 0; /* Clear interrupt flag */
_INT0IE = 1; /* Enable External interrupt pin (RA2 on 690) */

_T1IF = 0; /* Clear interrupt flag */
_T1IE = 0; /* Timer_0 overflow interrupt disable */


_INT0EP = 1;
}

/*--- Rc5 interrupt ---*/

void _ISR _T1Interrupt(void)
{
switch(Decoder.State)
{
case START_S: TMR1 = 0;
_T1IF = 0;
_T1IE = 1;
Decoder.bit_counter = 0;
Decoder.rc_data = 0;
Decoder.State = CALIBRATE_S;
break;

case CALIBRATE_S: Decoder.pulse_t1 = TMR1; /* Calibrate bit time */
TMR1 = 0;
Decoder.pulse_t2 = Decoder.pulse_t1 + (Decoder.pulse_t1 / 2);
Decoder.pulse_t3 = Decoder.pulse_t1 * 2;
Decoder.tolerance = Decoder.pulse_t1 / 8;
Decoder.last_bit = 1;
Decoder.State = DATA_S;
break;

case DATA_S: if(get_pulse_length() == PULSE_OK){
Decoder.State = DATA_S;
}
else{
_T1IF = 1;
}
break;

default: _T1IF = 1;
break;
}

_INT0IF = 0;
}

if(_T1IF)
{
if(Decoder.bit_counter == 0x0b)
{
save_data(0);
}

if(Decoder.bit_counter == 0x0c)
{
RC5_Code.address = (Decoder.rc_data >> 6) & 0x001f;
RC5_Code.command = Decoder.rc_data & 0x003f;
RC5_Code.toggle = (Decoder.rc_data >> 11) & 0x0001;
RC5_Code.valid = 1;
}

_T1IF = 0;
_T1IE = 0;
Decoder.State = START_S;
}
}

/*--- Get pulse length ---*/

static unsigned char get_pulse_length(void)
{
unsigned char max, min;

Decoder.bit_time = TMR1;
TMR1 = 0;

max = Decoder.bit_time + Decoder.tolerance;
min = Decoder.bit_time - Decoder.tolerance;

if((Decoder.pulse_t1 >= min) && (Decoder.pulse_t1 <= max)){
one_type_pulse();
return PULSE_OK;
}
else if((Decoder.pulse_t2 >= min) && (Decoder.pulse_t2 <= max)){
two_type_pulse();
return PULSE_OK;
}
else if((Decoder.pulse_t3 >= min) && (Decoder.pulse_t3 <= max)){
three_type_pulse();
return PULSE_OK;
}
else{
return PULSE_ERROR;
}
}

/*--- A one type pulse ---*/

static void one_type_pulse(void)
{
if(Decoder.last_bit == 1){
save_data(1);
}
else{
save_data(0);
}
}

/*--- A two type pulse ---*/

static void two_type_pulse(void)
{
if(Decoder.last_bit == 1){
save_data(0);
Decoder.last_bit = 0;
}
else{
save_data(0);
save_data(1);
Decoder.last_bit = 1;
}
}

/*--- A three type pulse ---*/

static void three_type_pulse(void)
{
save_data(0);
save_data(1);
Decoder.last_bit = 1;
}

/*--- Save data ---*/

static void save_data(unsigned char data)
{
Decoder.rc_data <<= 1;

if(data == 1){
Decoder.rc_data |= 1;
}
else{
Decoder.rc_data &= 0xffe;
}

Decoder.bit_counter++;
}

/*--- End of File ---*/


c5_decoder.c: In function '_T1Interrupt':
rc5_decoder.c:81: warning: PSV model not specified for '_T1Interrupt';
assuming 'auto_psv' this may affect latency
rc5_decoder.c: At top level:
rc5_decoder.c:116: error: syntax error before 'if'
 

Are you using the Microchip PIC30 Compiler?

If so, you may need to alter the interrupt service routine syntax as well as other compiler dependent directives.

BigDog
 
I m using C30 compiler....!! Thank but couldn't figure out....!! Any idea..!!
 

C30 compiler version.

Code:
#ifndef RC5_DECODER_H
#define RC5_DECODER_H

#include "posix_types.h"
#include "rc5_event.h"

/*--- RC code structure ---*/

typedef struct
  {
  uint8_t toggle;
  uint8_t address;
  uint8_t command;
  Bool valid;
  }RC5_CODE;

extern volatile RC5_CODE RC5_Code;

/*--- Function prototypes ---*/

void init_rc5_decoder(void);

#endif

/*--- End of File --*/

Code:
#include "rc5_decoder.h"
#include <p24HJ64GP206.h>
#include <stdlib.h>

/*--- RC5 Decoder state machine ---*/

enum RC5_STATE{START_S, CALIBRATE_S, DATA_S};

/*--- RC5 code structure ---*/

volatile RC5_CODE RC5_Code;

/*--- RC5 decoder structure ---*/

typedef struct
  {
  enum RC5_STATE State; 
  int16_t bit_time;
  int16_t pulse_t1;
  int16_t pulse_t2;
  int16_t pulse_t3;
  int16_t tolerance;

  uint8_t last_bit;
  uint16_t bit_counter;
  uint16_t rc_data;
  }DECODER;

volatile DECODER Decoder;

/*--- Pulse types ---*/

#define PULSE_OK    0
#define PULSE_ERROR 1

/*--- Local function prototypes ---*/

static void init_timer_6(void);
static uint8_t get_pulse_length(void);
static void one_type_pulse(void);
static void two_type_pulse(void);
static void three_type_pulse(void);
static void save_data(uint8_t data);

/*--- Initialise rc5 decoder interrupt ---*/

void init_rc5_decoder(void)
  {
  IPC5bits.INT1IP = 5;    /* High Priority */ 
  INTCON2bits.INT1EP = 1; /* Negative edge interrupt */

  init_timer_6();
  RC5_Code.valid = False;
  Decoder.State = START_S; 

  IFS1bits.INT1IF = 0;
  IEC1bits.INT1IE = 1;
  TRISDbits.TRISD8 = 1;   /* Input pin 42, RD8 */
  } 

/*--- Rc5 interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _INT1Interrupt(void)
  {
  switch(Decoder.State)
    {
    case START_S:     TMR6 = 0;
                      IFS2bits.T6IF = 0;
                      T6CONbits.TON = 1;
                      Decoder.bit_counter = 0;
                      Decoder.rc_data = 0x00;
                      Decoder.State = CALIBRATE_S;
                      break;

    case CALIBRATE_S: Decoder.pulse_t1 = TMR6;  /* Calibrate bit time */
                      TMR6 = 0; 
                      Decoder.pulse_t2 = Decoder.pulse_t1 + (Decoder.pulse_t1 / 2);
                      Decoder.pulse_t3 = Decoder.pulse_t1 * 2; 
                      Decoder.tolerance = Decoder.pulse_t1 / 10; 
                      Decoder.last_bit = 1;  
                      PR6 = Decoder.pulse_t1 * 3; 
                      IEC2bits.T6IE = 1;       
                      Decoder.State = DATA_S;
                      break;
 
    case DATA_S:      if(get_pulse_length() == PULSE_OK){
                        Decoder.State = DATA_S;
                        }
                      else{
                        IFS2bits.T6IF = 1;
                        }
                      break;
    
    default:          IFS2bits.T6IF = 1;
                      break;
    }
   
  IFS1bits.INT1IF = 0;    
  }

/*--- Get pulse length ---*/

static uint8_t get_pulse_length(void)
  {
  Decoder.bit_time = TMR6;
  TMR6 = 0;

  if(abs(Decoder.bit_time - Decoder.pulse_t1) < Decoder.tolerance){
    one_type_pulse();
    return PULSE_OK;
    }
  else if(abs(Decoder.bit_time - Decoder.pulse_t2) < Decoder.tolerance){
    two_type_pulse();
    return PULSE_OK;
    }
  else if(abs(Decoder.bit_time - Decoder.pulse_t3) < Decoder.tolerance){
    three_type_pulse();
    return PULSE_OK;
    }
  else{
    return PULSE_ERROR;
    }
  }

/*--- A one type pulse ---*/

static void one_type_pulse(void)
  {
  if(Decoder.last_bit == 1){
    save_data(1);
    }
  else{
    save_data(0);
    }
  }

/*--- A two type pulse ---*/

static void two_type_pulse(void)
  {
  if(Decoder.last_bit == 1){
    save_data(0);
    Decoder.last_bit = 0;
    }
  else{
    save_data(0);
    save_data(1);
    Decoder.last_bit = 1;
    }
  }

/*--- A three type pulse ---*/

static void three_type_pulse(void)
  {
  save_data(0);
  save_data(1);
  Decoder.last_bit = 1;
  }

/*--- Save data ---*/

static void save_data(uint8_t data)
  {
  Decoder.rc_data <<= 1;

  if(data == 1){
    Decoder.rc_data |= 1;
    }
  else{
    Decoder.rc_data &= 0xffe;
    }

  Decoder.bit_counter++;
  }

/*--- Timer 6 one shot Interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _T6Interrupt(void)
  {
  if(Decoder.bit_counter == 0x0b){
    save_data(0);
    }

  RC5_Code.command = Decoder.rc_data & 0x003f;	
  RC5_Code.address = (Decoder.rc_data >> 6) & 0x001f;
  RC5_toggle = (Decoder.rc_data >> 11) & 0x0001; 


  IFS2bits.T6IF = 0;
  IEC2bits.T6IE = 0; 
  T6CONbits.TON = 0; 
  PR6 = 0x400;  
  Decoder.State = START_S; 
  }

/*--- Initialise Timer 6 (Used as RC timer) ---*/

static void init_timer_6(void)
  {
	T6CON = 0;  
  IPC11bits.T6IP = 6;   /* High priority */     
  T6CONbits.TCKPS = 3;  /* Prescale 1:256 */ 
  PR6 = 0x400;          /* Time out */      
  IFS2bits.T6IF = 0;
  IEC2bits.T6IE = 0;    /* Interrupt enable bit */
  T6CONbits.TON = 0;
  }

/*--- End of File ---*/

Code:
#ifndef POSIX_TYPES_H
#define POSIX_TYPES_H
            
/*--- Standard type definitions. ---*/

/* Plain char, only to be used for the storage and use of character values. 
Misra Rule 6.1 (Required) */

typedef unsigned char   uint8_t;    /* unsigned 8 bit type definition */
typedef signed char	    int8_t;     /* signed 8 bit type definition */
typedef unsigned int    uint16_t;	  /* unsigned 16 bit type definition */
typedef signed int	    int16_t; 	  /* signed 16 bit type definition */
typedef unsigned long   uint32_t;	  /* unsigned 32 bit type definition */
typedef signed long	    int32_t; 	  /* signed 32 bit type definition */
typedef unsigned int    Bool;       /* Bool type definition */

/*--- Standard constant definition. ---*/

#define False ((Bool)0x0000U)
#define True  ((Bool)0x0001U)

/*--- End of file. ---*/

#endif
 
@btbass....sorry to bother you...rc5_event.h? Is it user's header file?
 

It will compile without it.
The 'rc_Event.h' is just a list of defines for the addresses and commands in the application.
As the decoder runs in the background via interrupt, when a valid code is received, I set an event flag.

Modify the code like so:
Code:
/*--- Timer 6 one shot Interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _T6Interrupt(void)
  {
  if(Decoder.bit_counter == 0x0b){
    save_data(0);
    }

  RC5_Code.command = Decoder.rc_data & 0x003f;	
  RC5_Code.address = (Decoder.rc_data >> 6) & 0x001f;
  RC5_Code.toggle = (Decoder.rc_data >> 11) & 0x0001; /* Fix this line!!!! */ 

  RC5_Code.valid = True;  /* Set event flag, Add this line */


  IFS2bits.T6IF = 0;
  IEC2bits.T6IE = 0; 
  T6CONbits.TON = 0; 
  PR6 = 0x400;  
  Decoder.State = START_S; 
  }

The main application periodically checks the event flag and when it is set, decodes the command then clears the event flag,

if(RC5_Code.valid == True){
do_somthing;
RC5_Code.valid = False;
}


Typical header file
Code:
/*--- RC5 infra red codes ---*/

#define RC5_ADDRESS     20U

#define STOP            54U
#define PLAY            53U
#define PAUSE           48U
#define NEXT_TRACK      32U
#define PREV_TRACK      33U
#define SCAN_FORWARDS   52U
#define SCAN_BACKWARDS  50U


---------- Post added at 11:26 ---------- Previous post was at 10:04 ----------

Here is generic version using timer 4.
You may need to adjust the timer prescale depending on your clock frequency.

Header file rc5_decoder.h
Code:
#ifndef RC5_DECODER_H
#define RC5_DECODER_H

/*--- Processor Include files ---*/

#if defined (__dsPIC30F__)
    #include <p30Fxxxx.h>
#elif defined (__dsPIC33F__)
    #include <p33Fxxxx.h>
#elif defined (__PIC24H__)
    #include <p24Hxxxx.h>
#elif defined (__PIC24F__)
    #include <p24Fxxxx.h>
#else
    #error Selected processor not supported
#endif

/*--- RC code structure ---*/

typedef struct
  {
  unsigned char toggle;
  unsigned char address;
  unsigned char command;
  unsigned char valid;
  }RC5_CODE;

extern volatile RC5_CODE RC5_Code;

/*--- Function prototypes ---*/

void init_rc5_decoder(void);

#endif

/*--- End of File --*/

decoder rc_decoder.c
Code:
#include "rc5_decoder.h"
#include <stdlib.h>

/*--- RC5 Decoder state machine ---*/

enum RC5_STATE{START_S, CALIBRATE_S, DATA_S};

/*--- RC5 code structure ---*/

volatile RC5_CODE RC5_Code;

/*--- RC5 decoder structure ---*/

typedef struct
  {
  enum RC5_STATE State; 
  int bit_time;
  int pulse_t1;
  int pulse_t2;
  int pulse_t3;
  int tolerance;

  unsigned char last_bit;
  unsigned char bit_counter;
  unsigned int rc_data;
  unsigned char error;
  }DECODER;

volatile DECODER Decoder;

/*--- Pulse types ---*/

#define PULSE_OK    0
#define PULSE_ERROR 1

/*--- Local function prototypes ---*/

static void init_timer_4(void);
static unsigned char get_pulse_length(void);
static void one_type_pulse(void);
static void two_type_pulse(void);
static void three_type_pulse(void);
static void save_data(unsigned char data);

/*--- Initialise rc5 decoder interrupt ---*/

void init_rc5_decoder(void)
  {
  IPC5bits.INT1IP = 5;    /* High Priority */ 
  INTCON2bits.INT1EP = 1; /* Negative edge interrupt */

  init_timer_4();
  RC5_Code.valid = 0;
  Decoder.State = START_S; 

  IFS1bits.INT1IF = 0;
  IEC1bits.INT1IE = 1;
  TRISDbits.TRISD8 = 1;   /* Input pin 42, RD8 */
  } 

/*--- Rc5 interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _INT1Interrupt(void)
  {
  switch(Decoder.State)
    {
    case START_S:     TMR4 = 0;
                      IFS1bits.T4IF = 0;
                      T4CONbits.TON = 1;
                      Decoder.bit_counter = 0;
                      Decoder.rc_data = 0x00;
                      Decoder.State = CALIBRATE_S;
                      break;

    case CALIBRATE_S: Decoder.pulse_t1 = TMR4;  /* Calibrate bit time */
                      TMR4 = 0; 
                      Decoder.pulse_t2 = Decoder.pulse_t1 + (Decoder.pulse_t1 / 2);
                      Decoder.pulse_t3 = Decoder.pulse_t1 * 2; 
                      Decoder.tolerance = Decoder.pulse_t1 / 10; 
                      Decoder.last_bit = 1;  
                      PR4 = Decoder.pulse_t1 * 3; 
                      IEC1bits.T4IE = 1;       
                      Decoder.State = DATA_S;
                      Decoder.error = 0;
                      break;
 
    case DATA_S:      if(get_pulse_length() == PULSE_OK){
                        Decoder.State = DATA_S;
                        }
                      else{
                        Decoder.error = 1;
                        IFS1bits.T4IF = 1;
                        }
                      break;
    
    default:          Decoder.error = 1;
                      IFS1bits.T4IF = 1;
                      break;
    }
   
  IFS1bits.INT1IF = 0;    
  }

/*--- Get pulse length ---*/

static unsigned char get_pulse_length(void)
  {
  Decoder.bit_time = TMR4;
  TMR4 = 0;

  if(abs(Decoder.bit_time - Decoder.pulse_t1) < Decoder.tolerance){
    one_type_pulse();
    return PULSE_OK;
    }
  else if(abs(Decoder.bit_time - Decoder.pulse_t2) < Decoder.tolerance){
    two_type_pulse();
    return PULSE_OK;
    }
  else if(abs(Decoder.bit_time - Decoder.pulse_t3) < Decoder.tolerance){
    three_type_pulse();
    return PULSE_OK;
    }
  else{
    return PULSE_ERROR;
    }
  }

/*--- A one type pulse ---*/

static void one_type_pulse(void)
  {
  if(Decoder.last_bit == 1){
    save_data(1);
    }
  else{
    save_data(0);
    }
  }

/*--- A two type pulse ---*/

static void two_type_pulse(void)
  {
  if(Decoder.last_bit == 1){
    save_data(0);
    Decoder.last_bit = 0;
    }
  else{
    save_data(0);
    save_data(1);
    Decoder.last_bit = 1;
    }
  }

/*--- A three type pulse ---*/

static void three_type_pulse(void)
  {
  save_data(0);
  save_data(1);
  Decoder.last_bit = 1;
  }

/*--- Save data ---*/

static void save_data(unsigned char data)
  {
  Decoder.rc_data <<= 1;

  if(data == 1){
    Decoder.rc_data |= 1;
    }
  else{
    Decoder.rc_data &= 0xffe;
    }

  Decoder.bit_counter++;
  }

/*--- Timer 4 one shot Interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _T4Interrupt(void)
  {
  if(!Decoder.error)
    {
    if(Decoder.bit_counter == 0x0b){
      save_data(0);
      }

    RC5_Code.address = (Decoder.rc_data >> 6) & 0x001f;
    RC5_Code.command = Decoder.rc_data & 0x003f;
    RC5_Code.toggle = (Decoder.rc_data >> 11) & 0x0001; 
    RC5_Code.valid = 1;
    }

  IFS1bits.T4IF = 0;
  IEC1bits.T4IE = 0; 
  T4CONbits.TON = 0; 
  PR4 = 0x400;  
  Decoder.State = START_S; 
  }

/*--- Initialise Timer 4 (Used as RC timer) ---*/

static void init_timer_4(void)
  {
  T4CON = 0;  
  IPC6bits.T4IP = 6;   /* High priority */     
  T4CONbits.TCKPS = 3;  /* Prescale 1:256 */ 
  PR4 = 0x400;          /* Time out */      
  IFS1bits.T4IF = 0;
  IEC1bits.T4IE = 0;    /* Interrupt enable bit */
  T4CONbits.TON = 0;
  }

/*--- End of File ---*/
 
Thanks again btbass....
Getting No errors....I tried code to trun on/off LED using IR remote..won't work..Might Problem with the value of PR4.
I dnt know the formula for value of Period register. My IR sensor freq. 30khz... I am using internal Osc 8mz...what would be the value of PR4 register?

Thanks in Advance btbass..SIR...!!
 

PR4 is set by the function based on the measured pulse width.
With an 8MHz pscillator, you could set the timer prescale to 1:8.
Change this line in the init_timer function to

T4CONbits.TCKPS = 1; /* Prescale 1:8 */

If you are using a debugger, put a breakpoint in the timer interrupt function and use the watch window to see what is what.

Code:
*--- Timer 4 one shot Interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _T4Interrupt(void)
  {
  if(!Decoder.error) /* Break point here. */
    {
    if(Decoder.bit_counter == 0x0b){
      save_data(0);
      }

    RC5_Code.address = (Decoder.rc_data >> 6) & 0x001f;
    RC5_Code.command = Decoder.rc_data & 0x003f;
    RC5_Code.toggle = (Decoder.rc_data >> 11) & 0x0001; 
    RC5_Code.valid = 1;
    }

  IFS1bits.T4IF = 0;
  IEC1bits.T4IE = 0; 
  T4CONbits.TON = 0; 
  PR4 = 0x400;  
  Decoder.State = START_S; 
  }
 
This is main.c...config bit set to FRC (8mhz)..,Please correct me..!!

Code:
#include "main.h"

_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2) 
_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_NONE & FNOSC_FRC)


/*--- RC5 infra red codes ---*/

#define RC5_ADDRESS     20U

#define STOP            54U
#define PLAY            53U
#define PAUSE           48U
#define NEXT_TRACK      32U
#define PREV_TRACK      33U
#define SCAN_FORWARDS   52U
#define SCAN_BACKWARDS  50U
#define DELAY		160000

void main()
{
    TRISA = 0;
	AD1PCFG = 0xffff;
	if(RC5_Code.valid == True)
		{
		 while(1) 		 
		 {PORTA = 0x000f;}
		 RC5_Code.valid = False;
         }
	else {
		 while(1)
		 {PORTA = 0x00f0;}
	     }
  }
 

You have to call init_rc5_decoder first to set it up?

init_rc5_decoder();

I assume you are using the same input pin for the ir?

TRISDbits.TRISD8 = 1; /* Input pin 42, RD8 */

You need a pin with interrupt.



Code:
void main()
  {
  
  init_rc5_decoder(); /* Initialise decoder */

  TRISA = 0;
  AD1PCFG = 0xffff;

while(1)
{
  if(RC5_Code.valid == True)
    {
    PORTA = RC5_Code.command;
    RC5_Code.valid = False;
    }
  else {
    PORTA = 0x00f0;
    }
}
  }
 
Last edited:
I am using INT1/RE8 pin as input.

Code:
#include "main.h"
/*--- RC5 Decoder state machine ---*/

enum RC5_STATE{START_S, CALIBRATE_S, DATA_S};

/*--- RC5 code structure ---*/

volatile RC5_CODE RC5_Code;

/*--- RC5 decoder structure ---*/

typedef struct
  {
  enum RC5_STATE State; 
  int bit_time;
  int pulse_t1;
  int pulse_t2;
  int pulse_t3;
  int tolerance;

  unsigned char last_bit;
  unsigned char bit_counter;
  unsigned int rc_data;
  unsigned char error;
  }DECODER;

volatile DECODER Decoder;

/*--- Pulse types ---*/

#define PULSE_OK    0
#define PULSE_ERROR 1

/*--- Local function prototypes ---*/

static void init_timer_4(void);
static unsigned char get_pulse_length(void);
static void one_type_pulse(void);
static void two_type_pulse(void);
static void three_type_pulse(void);
static void save_data(unsigned char data);

/*--- Initialise rc5 decoder interrupt ---*/

void init_rc5_decoder(void)
  {
  IPC5bits.INT1IP = 5;    /* High Priority */ 
  INTCON2bits.INT1EP = 1; /* Negative edge interrupt */

  init_timer_4();
  RC5_Code.valid = 0;
  Decoder.State = START_S; 

  IFS1bits.INT1IF = 0;
  IEC1bits.INT1IE = 1;
  [B]TRISEbits.TRISE8 = 1; /* Input pin , RE8 */[/B]
  } 

/*--- Rc5 interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _INT1Interrupt(void)
  {
  switch(Decoder.State)
    {
    case START_S:     TMR4 = 0;
                      IFS1bits.T4IF = 0;
                      T4CONbits.TON = 1;
                      Decoder.bit_counter = 0;
                      Decoder.rc_data = 0x00;
                      Decoder.State = CALIBRATE_S;
                      break;

    case CALIBRATE_S: Decoder.pulse_t1 = TMR4;  /* Calibrate bit time */
                      TMR4 = 0; 
                      Decoder.pulse_t2 = Decoder.pulse_t1 + (Decoder.pulse_t1 / 2);
                      Decoder.pulse_t3 = Decoder.pulse_t1 * 2; 
                      Decoder.tolerance = Decoder.pulse_t1 / 10; 
                      Decoder.last_bit = 1;  
                      PR4 = Decoder.pulse_t1 * 3; 
                      IEC1bits.T4IE = 1;       
                      Decoder.State = DATA_S;
                      Decoder.error = 0;
                      break;
 
    case DATA_S:      if(get_pulse_length() == PULSE_OK){
                        Decoder.State = DATA_S;
                        }
                      else{
                        Decoder.error = 1;
                        IFS1bits.T4IF = 1;
                        }
                      break;
    
    default:          Decoder.error = 1;
                      IFS1bits.T4IF = 1;
                      break;
    }
   
  IFS1bits.INT1IF = 0;    
  }

/*--- Get pulse length ---*/

static unsigned char get_pulse_length(void)
  {
  Decoder.bit_time = TMR4;
  TMR4 = 0;

  if(abs(Decoder.bit_time - Decoder.pulse_t1) < Decoder.tolerance){
    one_type_pulse();
    return PULSE_OK;
    }
  else if(abs(Decoder.bit_time - Decoder.pulse_t2) < Decoder.tolerance){
    two_type_pulse();
    return PULSE_OK;
    }
  else if(abs(Decoder.bit_time - Decoder.pulse_t3) < Decoder.tolerance){
    three_type_pulse();
    return PULSE_OK;
    }
  else{
    return PULSE_ERROR;
    }
  }

/*--- A one type pulse ---*/

static void one_type_pulse(void)
  {
  if(Decoder.last_bit == 1){
    save_data(1);
    }
  else{
    save_data(0);
    }
  }

/*--- A two type pulse ---*/

static void two_type_pulse(void)
  {
  if(Decoder.last_bit == 1){
    save_data(0);
    Decoder.last_bit = 0;
    }
  else{
    save_data(0);
    save_data(1);
    Decoder.last_bit = 1;
    }
  }

/*--- A three type pulse ---*/

static void three_type_pulse(void)
  {
  save_data(0);
  save_data(1);
  Decoder.last_bit = 1;
  }

/*--- Save data ---*/

static void save_data(unsigned char data)
  {
  Decoder.rc_data <<= 1;

  if(data == 1){
    Decoder.rc_data |= 1;
    }
  else{
    Decoder.rc_data &= 0xffe;
    }

  Decoder.bit_counter++;
  }

/*--- Timer 4 one shot Interrupt ---*/

void __attribute__((__interrupt__, no_auto_psv)) _T4Interrupt(void)
  {
  if(!Decoder.error)
    {
    if(Decoder.bit_counter == 0x0b){
      save_data(0);
      }

    RC5_Code.address = (Decoder.rc_data >> 6) & 0x001f;
    RC5_Code.command = Decoder.rc_data & 0x003f;
    RC5_Code.toggle = (Decoder.rc_data >> 11) & 0x0001; 
    RC5_Code.valid = 1;
    }

  IFS1bits.T4IF = 0;
  IEC1bits.T4IE = 0; 
  T4CONbits.TON = 0; 
  PR4 = 0x400;  
  Decoder.State = START_S; 
  }

/*--- Initialise Timer 4 (Used as RC timer) ---*/

static void init_timer_4(void)
  {
  T4CON = 0;  
  IPC6bits.T4IP = 6;   /* High priority */     
  [B]T4CONbits.TCKPS = 1;  /* Prescale 1:8 */ 
  PR4 = 0x400;          /* Time out */      [/B]
  IFS1bits.T4IF = 0;
  IEC1bits.T4IE = 0;    /* Interrupt enable bit */
  T4CONbits.TON = 0;
  }
 

INT1/RE8 pin as input is ok. That is the int1 interrupt.
So should work ok.
If you have added the init_rc5_decoder(); call, it should work.
 

Sorry, It won't work...I am using intern osc. 8mhz. ..config bit FRC...Also IR sensor detect IR signal and it's output connected with INT1/RE8...Check signal with oscillator @36khz incoming signal... I doubt about frequency setting or osc. selection...Thakns

---------- Post added at 15:08 ---------- Previous post was at 15:06 ----------

Using Explore 16 PIC24FJ128GA010 board...
 

If you have a debugger, try a few break points to see whats going on.

I have the same Explorer board, I will try your code later today when I can and report back.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top