As my first code share, I have created a program that will decode the RC6 IR protocol (mode 6 or 32 bit version). I made it to decode the signal from my Media Center Remote Control but it could be easily adapted to read any RC6 (others are mode 0 or 16bit) remote. I borrowed heavily from the IR analyzer program in the playground but the decoding process was all me. Because Im no pro programmer, the code is very straightforward and should be easy for even a noob to understand.
Unfortunately its not perfect, some buttons stall the program while others give an infinite loop. The ones #defined work perfectly tho. So needles to say, if anyone sees an obvious problem give me a shout.
Reference sites stated in the code header
//RC6 IR decoder
//Written by Miles Moody
//Set up for mode 6 (32bit) can be changed for mode 0(16bit)
//Based on Walter Anderson's IRanalyzer.pde
//For more info on RC6 protocol see:
//http://www.sbprojects.com/knowledge/ir/rc6.htm
//http://www.lompec.nl/avusirx.html
#include <avr/interrupt.h>
#include <avr/io.h>
#define TIMER_RESET TCNT1 = 0
#define SAMPLE_SIZE 68 //#of pin changes up to 255
#define headerlower 2500
#define headerupper 2900
#define singlelower 300
#define singleupper 575
#define doublelower 725
#define doubleupper 1050
#define triplelower 1250
#define tripleupper 1500
#define togglebit 16
#define OK 1058
#define LEFT 1056
#define UP 1054
#define PLAY 1046
#define FF 1044
#define PAUSE 1048
#define MUTE 1038
#define SKIPF 1050
#define CHUP 1042
#define VOLUP 1040
#define EJECT 1060
#define LISTING 1062
#define RECTV 1096
#define CLEAR 1034
int TXpin=7;
int RXpin = 2;
unsigned int TimerValue[SAMPLE_SIZE];
byte pulsecode[SAMPLE_SIZE];
char direction[SAMPLE_SIZE];
boolean bit[32];
boolean lastbit;
int lastcode;
int currentcode;
unsigned int commandcode;//1st 16 data bits
unsigned int buttoncode;//2nd 16 data bits
char button[16]={"None"};
int i;
int n;
byte change_count;
int plen[SAMPLE_SIZE];
long time;
long time2;
void setup() {
Serial.begin(115200);
Serial.println("Analyze RC6 IR Remote");
TCCR1A = 0x00; // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
// ICNC1=0 => Capture Noise Canceler disabled -- ICES1=0 => Input Capture Edge Select (not used) -- CTC1=0 => Clear Timer/Counter 1 on Compare/Match
// CS12=0 CS11=1 CS10=1 => Set prescaler to clock/64
TCCR1B = 0x03; // 16MHz clock with prescaler means TCNT1 increments every 4uS
// ICIE1=0 => Timer/Counter 1, Input Capture Interrupt Enable -- OCIE1A=0 => Output Compare A Match Interrupt Enable -- OCIE1B=0 => Output Compare B Match Interrupt Enable
// TOIE1=0 => Timer 1 Overflow Interrupt Enable
TIMSK1 = 0x00;
pinMode(RXpin, INPUT);
pinMode(TXpin, OUTPUT);
}
void loop()
{
Serial.println("Waiting...");
change_count = 0;
while(digitalRead(IRpin) == HIGH) {}
TIMER_RESET;
TimerValue[change_count] = TCNT1;
direction[change_count++] = '0';
while (change_count < SAMPLE_SIZE) {
if (direction[change_count-1] == '0') {
while(digitalRead(RXpin) == LOW) {}
TimerValue[change_count] = TCNT1;
direction[change_count++] = '1';
} else {
while(digitalRead(RXpin) == HIGH) {}
TimerValue[change_count] = TCNT1;
direction[change_count++] = '0';
}
}//end of recording
change_count=0;
while (change_count<SAMPLE_SIZE){
plen[change_count]=(TimerValue[change_count+1]-TimerValue[change_count])*4;
if(plen[change_count]>headerlower &&plen[change_count]<headerupper) pulsecode[change_count]=0; //header pulse
else if(plen[change_count]>singlelower &&plen[change_count]<singleupper) pulsecode[change_count]=1; //single pulse
else if(plen[change_count]>doublelower &&plen[change_count]<doubleupper) pulsecode[change_count]=2; //double pulse
else if(plen[change_count]>triplelower &&plen[change_count]<tripleupper) pulsecode[change_count]=3; //triple pulse or trailer(2) plus single(1)
else pulsecode[change_count]=9; //ender or error pulse
change_count++;
}//done converting to pulse code
change_count=10;//start at trailer
i=0;//start at first (MSB) bit
if(pulsecode[change_count-2]==0) bit[i]=0; //decode bit directly after trailer
else if(pulsecode[change_count-2]==1) bit[i]=1;
lastbit=bit[i];
change_count+=2;
i++;
while(i<=31 || pulsecode[change_count]==9){ //decode the rest based on whether
lastcode=pulsecode[change_count-1]; //or not they change
currentcode=pulsecode[change_count];
if(lastcode==2){
bit[i]=!lastbit;
}
else if(lastcode==1){
bit[i]=lastbit;
}
lastbit=bit[i];
i++;
if(currentcode==2)change_count++;
else if(currentcode==1)change_count+=2;
}
BtoI(0, 16); //binary to integer for command bits
BtoI(16, 16); //bin to int for data bits
Serial.println("Bit stream detected!");
//remove commenting for LOTS more info than just button pressed
/*change_count = 0;
i=0;
Serial.println("p len\tcode\thi/lo\tch cnt\tbit");
while(change_count<SAMPLE_SIZE){
Serial.print(plen[change_count], DEC);
Serial.print("\t");
Serial.print(pulsecode[change_count],DEC);
Serial.print("\t");
Serial.print(direction[change_count+1]);
Serial.print("\t");
Serial.print(change_count, DEC);
Serial.print("\t");
if(change_count<32) Serial.print(int(bit[change_count]), DEC);
Serial.println();
change_count++;
}*/
//Again, remove commenting for pure codes
/*Serial.print("\nCommand Code\t");
Serial.println(commandcode, DEC);
Serial.print("\nButton code\t");
Serial.println(buttoncode,DEC);*/
Serial.print("Button\t\t");
spitbutton();
Serial.println("\nBit stream end!");
change_count=0;
i=0;
delay(2000);
}
void BtoI(int start, int numofbits){ //binary array to integer conversion
int integer=0;
i=start;
while(i<numofbits+start){
if(i==togglebit){/*ignore toggle bit*/}
else integer+=bit[i]<<(numofbits+start-i-1); //same as pow()
i++;
}
if (start==16)buttoncode=integer;
else if (start==0)commandcode=integer;
}
void spitbutton(){ //just prints out the button pressed
switch (buttoncode){
case UP:
Serial.print("UP");
break;
case OK:
Serial.print("OK");
break;
case LEFT:
Serial.print("LEFT");
break;
case PLAY:
Serial.print("PLAY");
break;
case FF:
Serial.print("FF");
break;
case PAUSE:
Serial.print("PAUSE");
break;
case MUTE:
Serial.print("MUTE");
break;
case SKIPF:
Serial.print("SKIPF");
break;
case CHUP:
Serial.print("CHUP");
break;
case VOLUP:
Serial.print("VOLUP");
break;
case EJECT:
Serial.print("EJECT");
break;
case LISTING:
Serial.print("LISTING");
break;
case RECTV:
Serial.print("RECTV");
break;
case CLEAR:
Serial.print("CLEAR");
break;
}
}