Update IR lib/sensor to use the latest IR_Remote fork by Chris Young (IRLib)

https://github.com/cyborg5/IRLib
This commit is contained in:
Henrik Ekblad
2014-04-01 22:16:22 +02:00
parent b27735a94a
commit 3a2cfbcf13
44 changed files with 3607 additions and 2760 deletions
@@ -0,0 +1,201 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009I know prescription and no
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* This example demonstrates how to extend this library to add a new protocol
* without actually modifying or recompiling the library itself. It implements the protocol
* used by DirecTV. This protocol actually comes in six different varieties.
* It uses three different frequencies 38, 40, or 57 kHz. It also uses two different varieties
* lead out times either 9000us or 30000us. The default is 38 kHz and 30000us.
* You can use a different constructor for the other varieties.
* This is a modified version of the IRecord example.
* If you would like to make this a permanent part of your library you could copy the class
* prototypes to IRLib.h and the code itself to IRLib.cpp. Search for the word "ADDITIONAL"
* to see where to add various pieces of code. Also see the Samsung36 example for details.
*/
#include <IRLib.h>
#include <IRLibMatch.h>
class IRdecodeDirecTV: public virtual IRdecodeBase
{
public:
bool decode(void);
bool Repeat;
};
class IRsendDirecTV: public virtual IRsendBase
{
public:
IRsendDirecTV (int khz= 38,bool LongLeadOut=true);
void send(unsigned long data, bool Repeat);
int Freq;
unsigned int LeadOut;
};
#define DIRECTV (LAST_PROTOCOL+1)
/*
* According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#DirecTV
* The IRP notation for this protocol is:
*{38k,600,msb}<1,-1|1,-2|2,-1|2,-2>(5,(5,-2,D:4,F:8,C:4,1,-50)+) {C=7*(F:2:6)+5*(F:2:4)+3*(F:2:2)+(F:2)}
* Unlike most protocols which use a fixed length mark and a variable length or a variable length
* mark a fixed length space, this protocol varies both the mark and the space.
* The stream is still a series of marks and spaces but the length of either of those
* denotes a one or zero. A length of 1200us=logical 1 and length 600us=logical 0
* It also makes changes to the length of the header mark to devote repeat codes.
* The first header mark should be 6000us but repeat codes should only be 3000us.
*/
bool IRdecodeDirecTV::decode(void) {
long data; int offset;
IRLIB_ATTEMPT_MESSAGE(F("DirecTV"));
if (rawlen != 20) return RAW_COUNT_ERROR;
if (MATCH(rawbuf[1],3000))
Repeat=true;
else
if (!MATCH(rawbuf[1],6000)){
return HEADER_MARK_ERROR(6000);
} else {
Repeat=false;
}
if (!MATCH(rawbuf[2],1200)) return HEADER_SPACE_ERROR(1200);
offset=3; data=0;
while (offset < 18) {
if (MATCH(rawbuf[offset],1200)) {
data = (data << 1) | 1;
}
else if (MATCH(rawbuf[offset],600)) {
data <<= 1;
}
else return DATA_MARK_ERROR(1200);
offset++;
if (MATCH(rawbuf[offset],1200)) {
data = (data << 1) | 1;
}
else if (MATCH (rawbuf[offset],600)) {
data <<= 1;
}
else return DATA_SPACE_ERROR(1200);
offset++;
}
if (!MATCH(rawbuf[1],6000)) return DATA_MARK_ERROR(6000);
bits = 16;//set bit length
value = data;//put remaining bits in value
decode_type= static_cast<IRTYPES>DIRECTV;
return true;
};
//See the comment at the top about different frequencies and lead out times
IRsendDirecTV::IRsendDirecTV (int khz, bool LongLeadOut){
Freq=khz;
if (LongLeadOut) LeadOut=50*600; else LeadOut=15*600;
};
void IRsendDirecTV::send(unsigned long data, bool Repeat) {
enableIROut(Freq);
if(Repeat) mark(3000); else mark(6000);
space(1200);//Send header
for (int i = 0; i < 8; i++) {
if (data & 0x8000) mark(1200); else mark(600);
data <<= 1;
if (data & 0x8000) space(1200); else space(600);
data <<= 1;
};
mark(600);
space(LeadOut);
};
//Create a custom class that combines this new protocol with all the others
class MyCustomSend:
public virtual IRsend,
public virtual IRsendDirecTV
{
public:
void send(IRTYPES Type, unsigned long data, int nbits);
};
void MyCustomSend::send(IRTYPES Type, unsigned long data, int nbits) {
if (Type==DIRECTV)
IRsendDirecTV::send(data,false);
else
IRsend::send(Type, data, nbits);
}
class MyCustomDecode:
public virtual IRdecode,
public virtual IRdecodeDirecTV
{
public:
virtual bool decode(void); // Calls each decode routine individually
void DumpResults(void);
};
bool MyCustomDecode::decode(void) {
if (IRdecodeDirecTV::decode()) return true;
return IRdecode::decode ();
}
void MyCustomDecode::DumpResults(void){
if(decode_type==DIRECTV) {
Serial.print(F("Decoded DirecTV: Value:")); Serial.print(value, HEX);
if (Repeat) Serial.print(F(" repeat flag"));
};
IRdecode::DumpResults();
};
MyCustomDecode My_Decoder;
MyCustomSend My_Sender;
int RECV_PIN = 11;
IRrecv My_Receiver(RECV_PIN);
IRTYPES codeType; // The type of code
unsigned long codeValue; // The data bits
int codeBits; // The length of the code in bits
bool GotOne;
void setup()
{
GotOne=false;
codeType=UNKNOWN;
codeValue=0;
codeBits=0;
Serial.begin(9600);
Serial.println(F("Send a code from your remote and we will record it."));
Serial.println(F("Type any character and press enter. We will send the recorded code."));
My_Receiver.enableIRIn(); // Start the receiver
}
void loop() {
if (Serial.available()>0) {
unsigned char c=Serial.read();
if (c=='p') {//Send a test pattern
GotOne= true; codeType=DIRECTV; codeValue=0x1234; codeBits=16;
}
if(GotOne) {
My_Sender.send(codeType,codeValue,codeBits);
Serial.print(F("Sent "));
if (codeType== DIRECTV) Serial.print(F("DirecTV")); else Serial.print(Pnames(codeType));
Serial.print(F(" Value:0x"));
Serial.print(codeValue, HEX);
Serial.print(F(" Bits:"));
Serial.println(codeBits, DEC);
My_Receiver.enableIRIn(); // Re-enable receiver
}
}
else if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
if(My_Decoder.decode_type == UNKNOWN) {
Serial.println(F("Unknown type received. Ignoring."));
} else {
codeType= My_Decoder.decode_type;
codeValue= My_Decoder.value;
codeBits= My_Decoder.bits;
GotOne=true;
}
My_Decoder.DumpResults();
delay(1000);
My_Receiver.resume();
}
}
@@ -0,0 +1,152 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009I know prescription and no
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* This example demonstrates how to extend this library to add a new protocol
* without actually modifying or recompiling the library itself. It implements the protocol
* known as GIcable which is used by some Motorola cable boxes.
* This is a modified version of the IRecord example.
* If you would like to make this a permanent part of your library you could copy the class
* prototypes to IRLib.h and the code itself to IRLib.cpp. Search for the word "ADDITIONAL"
* to see where to add various pieces of code. Also see the Samsung36 example for details.
*/
#include <IRLib.h>
#include <IRLibMatch.h>
class IRdecodeGIcable: public virtual IRdecodeBase
{
public:
bool decode(void);
};
class IRsendGIcable: public virtual IRsendBase
{
public:
void send(unsigned long data, bool Repeat);
};
#define GICABLE (LAST_PROTOCOL+1)
/* The IRP notation for this protocol according to
* http://www.hifi-remote.com/johnsfine/DecodeIR.html#G.I. Cable
* is "{38.7k,490}<1,-4.5|1,-9>(18,-9,F:8,D:4,C:4,1,-84,(18,-4.5,1,-178)*) {C = -(D + F:4 + F:4:4)}"
*/
bool IRdecodeGIcable::decode(void) {
IRLIB_ATTEMPT_MESSAGE(F("GIcable"));
// Check for repeat
if (rawlen == 4 && MATCH(rawbuf[1], 490*18) && MATCH(rawbuf[2],2205)) {
bits = 0;
value = REPEAT;
decode_type= static_cast<IRTYPES>GICABLE;
return true;
}
if(!decodeGeneric(36, 18*490, 9*490, 0, 490, 9*490, 2205/*(4.5*490)*/)) return false;
decode_type= static_cast<IRTYPES>GICABLE;
return true;
};
void IRsendGIcable::send(unsigned long data, bool Repeat) {
if(Repeat) {
enableIROut(39);
mark (490*18); space (2205); mark (490); space(220);delay (87);//actually "space(87200);"
} else {
sendGeneric(data,16, 490*18, 490*9, 490, 490, 490*9, 2205, 39, true);
}
};
//Create a custom class that combines this new protocol with all the others
class MyCustomSend:
public virtual IRsend,
public virtual IRsendGIcable
{
public:
void send(IRTYPES Type, unsigned long data, int nbits);
};
void MyCustomSend::send(IRTYPES Type, unsigned long data, int nbits) {
if (Type==GICABLE){
IRsendGIcable::send(data,false);
//un-comment the line below to text repeats
//delay(3000); IRsendGIcable::send(data,true);
}
else
IRsend::send(Type, data, nbits);
}
class MyCustomDecode:
public virtual IRdecode,
public virtual IRdecodeGIcable
{
public:
virtual bool decode(void); // Calls each decode routine individually
void DumpResults(void);
};
bool MyCustomDecode::decode(void) {
if (IRdecodeGIcable::decode()) return true;
return IRdecode::decode ();
}
void MyCustomDecode::DumpResults(void){
if(decode_type==GICABLE) {
Serial.print(F("Decoded GIcable: Value:")); Serial.print(value, HEX);
};
IRdecode::DumpResults();
};
MyCustomDecode My_Decoder;
MyCustomSend My_Sender;
int RECV_PIN =11;
IRrecv My_Receiver(RECV_PIN);
IRTYPES codeType; // The type of code
unsigned long codeValue; // The data bits
int codeBits; // The length of the code in bits
bool GotOne;
void setup()
{
GotOne=false;
codeType=UNKNOWN;
codeValue=0;
codeBits=0;
Serial.begin(9600);
Serial.println(F("Send a code from your remote and we will record it."));
Serial.println(F("Type any character and press enter. We will send the recorded code."));
My_Receiver.enableIRIn(); // Start the receiver
}
void loop() {
if (Serial.available()>0) {
unsigned char c=Serial.read();
if (c=='p') {//Send a test pattern
GotOne= true; codeType=GICABLE; codeValue=0x1234; codeBits=16;
}
if(GotOne) {
My_Sender.send(codeType,codeValue,codeBits);
Serial.print(F("Sent "));
if (codeType== GICABLE) Serial.print(F("GIcable")); else Serial.print(Pnames(codeType));
Serial.print(F(" Value:0x"));
Serial.print(codeValue, HEX);
Serial.print(F(" Bits:"));
Serial.println(codeBits, DEC);
My_Receiver.enableIRIn(); // Re-enable receiver
}
}
else if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
if(My_Decoder.decode_type == UNKNOWN) {
Serial.println(F("Unknown type received. Ignoring."));
} else {
codeType= My_Decoder.decode_type;
codeValue= My_Decoder.value;
codeBits= My_Decoder.bits;
GotOne=true;
}
My_Decoder.DumpResults();
delay(1000);
My_Receiver.resume();
}
}
@@ -0,0 +1,117 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/* IRanalyze receives repeated values from a remote and averages the results. Should help in
* analyzing unknown protocols. You have to press the same key repeatedly. If you press a
* different key the totals reset and it computes new averages.
*/
#include <IRLib.h>
#include <IRLibRData.h>
int RECV_PIN = 11;
unsigned int Samples,i, LowSpace, LowMark, HighMark, HighSpace, interval,
balm,aalm,bahm,aahm,bals,aals,bahs,aahs;
unsigned char bacm,aacm,bacs,aacs, Mark_Count,Space_Count;
unsigned int Accumulated_Time[RAWBUF];
unsigned long Mark_Avg, Space_Avg,baam,aaam,baas,aaas;
//Try this program with various receivers
IRrecv My_Receiver(RECV_PIN);
//IRrecvLoop My_Receiver(RECV_PIN);
//Use interrupt=0. This is pin 2 on Arduino Uno and Mega, pin 3 on Leonardo
//IRrecvPCI My_Receiver(0);
IRdecode My_Decoder;
IRTYPES Old_Type;
unsigned long Old_Value;
void setup()
{
Serial.begin(9600);
delay(1000);while(!Serial);
My_Receiver.enableIRIn();
// My_Receiver.Mark_Excess=50;//Try different values here
Samples=0;Old_Value=0; Old_Type=UNKNOWN;
Serial.println(F("Send a signal repeatedly. We will report averages and statistics."));
}
void Tab(void) {Serial.print("\t");};
void loop() {
if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
if( (My_Decoder.decode_type != Old_Type) || (My_Decoder.value != Old_Value)) {
Serial.println(F("Resetting counters"));
for(i=0;i<RAWBUF;i++) {
Accumulated_Time[i]=0;
};
Samples=0;Old_Value= My_Decoder.value; Old_Type=My_Decoder.decode_type;
};
Samples++;
Serial.print(F("\nSamples=")); Serial.println(Samples,DEC);
LowSpace = LowMark=65535;
HighSpace = HighMark=0;
Mark_Avg= Space_Avg= Mark_Count= Space_Count=0;
for(i=0;i<My_Decoder.rawlen;i++){
Accumulated_Time[i]+=My_Decoder.rawbuf[i];
My_Decoder.rawbuf[i]= Accumulated_Time[i]/Samples;//Put back average so DumpResults can report
}
My_Decoder.DumpResults();
//Perform additional analysis
for(i=3;i<My_Decoder.rawlen;i++){ //Compute low, high and average mark and space
interval=My_Decoder.rawbuf[i];
if(i % 2) {
Mark_Avg += interval; LowMark=min(LowMark, interval); HighMark=max(HighMark, interval);Mark_Count++;
} else {
Space_Avg += interval; LowSpace=min(LowSpace, interval); HighSpace=max (HighSpace, interval);Space_Count++;
}
My_Decoder.rawbuf[i]= Accumulated_Time[i]/Samples;//Put back average so DumpResults can report
}
Mark_Avg /= Mark_Count; Space_Avg /= Space_Count;
//Now compute below average highs and lows and above average highs and lows
balm=bals=aalm=aals=32766;
bahm=bahs=aahm=aahs=baam=baas=aaam=aaas=0;
bacm=bacs=aacm=aacs=0;
for(i=3;i<My_Decoder.rawlen;i++){
interval=My_Decoder.rawbuf[i];
if(i % 2) {
if (interval>Mark_Avg) {
aalm=min(aalm,interval); aahm=max(aahm,interval);aacm++;aaam+=interval;
} else {
balm=min(balm,interval); bahm=max(bahm,interval);bacm++;baam+=interval;
}
} else {
if (interval>Space_Avg) {
aals=min(aals,interval); aahs=max(aahs,interval);aacs++;aaas+=interval;
} else {
bals=min(bals,interval); bahs=max(bahs,interval);bacs++;baas+=interval;
}
}
}
baam/=bacm;baas/=bacs;aaam/=aacm;aaas/=aacs;
Serial.println(F("\t #\tLow\tHigh\tAvg."));
Serial.print(F("Mark\t"));Serial.print(Mark_Count,DEC);Tab();Serial.print(LowMark,DEC);Tab();Serial.print(HighMark,DEC);Tab();Serial.println(Mark_Avg,DEC);
Serial.print(F("Space\t"));Serial.print(Space_Count,DEC);Tab();Serial.print(LowSpace,DEC);Tab();Serial.print(HighSpace,DEC);Tab();Serial.println(Space_Avg,DEC);
Serial.println(F("\nMarks\t\t #\tLow\tHigh\tAvg."));
Serial.print(F("Above Avg\t"));Serial.print(aacm,DEC);Tab();Serial.print(aalm,DEC);Tab();Serial.print(aahm,DEC);Tab();Serial.println(aaam,DEC);
Serial.print(F("Belows Avg.\t"));Serial.print(bacm,DEC);Tab();Serial.print(balm,DEC);Tab();Serial.print(bahm,DEC);Tab();Serial.println(baam,DEC);
Serial.println(F("\nSpaces\t\t #\tLow\tHigh\tAvg."));
Serial.print(F("Above Avg.\t"));Serial.print(aacs,DEC);Tab();Serial.print(aals,DEC);Tab();Serial.print(aahs,DEC);Tab();Serial.println(aaas,DEC);
Serial.print(F("Below Avg.\t"));Serial.print(bacs,DEC);Tab();Serial.print(bals,DEC);Tab();Serial.print(bahs,DEC);Tab();Serial.println(baas,DEC);
#define RATIO(n,d) Tab(); Serial.print(float(n)/float(d));
Serial.print(F("\nRatios\t\tBelow\tAbove\n"));
Serial.print(F("Head Mark"));RATIO(My_Decoder.rawbuf[1],baam);RATIO(My_Decoder.rawbuf[1],aaam);
Serial.print(F("\nHead Space"));RATIO(My_Decoder.rawbuf[2],baas);RATIO(My_Decoder.rawbuf[2],aaas);
Serial.print(F("\n\nMark Above/Below="));RATIO(aaam,baam);
Serial.print(F("\nSpace Above/Below="));RATIO(aaas,baas);
Serial.println();
delay(500);
My_Receiver.resume();
};
}
@@ -0,0 +1,95 @@
/* IRfreq: estimate modulation frequency of IR transmitter
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://tech.cyborg5.com
* Based on Arduino firmware for use with AnalysIR IR signal analysis
* software for Windows PCs. Many thanks to the people
* at http://analysir.com for their assistance In developing this program.
*/
#define INTERRUPT_USED 1 // Value can be 0-5 depending on board.
// You should attach your TSMP5800 or equivalent
// receiver to appropriate pin as defined below.
// Do not modified this section
#if defined(__AVR_ATmega32U4__) //Assume Arduino Leonardo
#if(INTERRUPT_USED==0)
#define PIN_USED 3
#elif (INTERRUPT_USED==1)
#define PIN_USED 2
#elif (INTERRUPT_USED==2)
#define PIN_USED 0
#elif (INTERRUPT_USED==3)
#define PIN_USED 1
#elif (INTERRUPT_USED==4)
#define PIN_USED 7
#else
#error "Invalid value for INTERRUPT_USED on Leonardo"
#endif
#elif (INTERRUPT_USED==0) //Uno or Mega
#define PIN_USED 2
#elif (INTERRUPT_USED==1) //Uno or Mega
#define PIN_USED 3
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#if (INTERRUPT_USED==2) //Mega only
#define PIN_USED 21
#elif (INTERRUPT_USED==3) //Mega only
#define PIN_USED 20
#elif (INTERRUPT_USED==4) //Mega only
#define PIN_USED 19
#elif (INTERRUPT_USED==5) //Mega only
#define PIN_USED 18
#else
#error "invalid value for INTERRUPT_USED on Arduino press delete this Michael down five mega"
#endif
#else
#error "Invalid value for INTERRUPT_USED on non-Leonardo non-Mega board"
#endif
#define BUF_SIZE 200
// These are "volatile" because they are modified inside the interrupt handler
volatile byte Time_Stamp[BUF_SIZE]; //Punch the time clock using "micros()" each time a pulse causes interrupt
volatile byte Count; //Index into Time_Stamp
void setup() {
Serial.begin(9600);
while(!Serial);//for Leonardo
pinMode(PIN_USED, INPUT);
Serial.print(F("Using interrupt="));Serial.println(INTERRUPT_USED,DEC);
Serial.println(F("You should have Vishay TSMP58000 or equivalent"));
Serial.print(F("connected to pin=")); Serial.println(PIN_USED,DEC);
}
void loop() {
attachInterrupt(INTERRUPT_USED, My_Interrupt_Handler, FALLING);
while(Count < (BUF_SIZE-10)); //do nothing but process interrupts until buffer almost fills
//We took that extra 10 off just in case interrupt came too fast for us to turn them off
detachInterrupt (INTERRUPT_USED);
Report_Freq();//reports modulation frequency to host over serial
}
void Report_Freq(){
byte Count_Usable=0; //Counts the number of usable valid intervals
unsigned long Sum=0; //Accumulate total of usable intervals
byte I;
byte Interval;//Interval between timestamps
Count--;//last one doesn't count
for (I=1;I<Count;I++){
Interval=(Time_Stamp[I]-Time_Stamp[I-1]);
if (Interval>50 || Interval<10) continue;//this is the period range length exclude extraneous ones
Sum +=Interval; // Accumulate usable intervals
Count_Usable++; // Count usable intervals
Time_Stamp[I-1]=0;//finished with it so clear for next time
}
Time_Stamp[I-1]=0;//now clear last one, which was missed in loop
Serial.print(F("Based on ")); Serial.print(Count_Usable,DEC);
Serial.print(F(" intervals totaling ")); Serial.print(Sum,DEC);
double Frequency=(double)Count_Usable/(double)Sum*1000;
Serial.print(F(" microseconds, the frequency is approx. =")); Serial.print(Frequency);
Serial.println(F("kHz"));
delay(1000);
Count=0; //reset value for next time
}
void My_Interrupt_Handler(){
Time_Stamp[Count++]=micros();
}
@@ -0,0 +1,49 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* IRhashdecode - decode an arbitrary IR code.
* Instead of decoding using a standard encoding scheme
* (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
* This should produce a unique 32-bit number however that number cannot be used
* to retransmit the same code. This is just a quick and dirty way to detect a unique code
* for controlling a device when you don't really care what protocol or values
* are being sent.
*/
#include <IRLib.h>
int RECV_PIN = 11;
IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRdecodeHash My_Hash_Decoder;
void setup()
{
My_Receiver.enableIRIn(); // Start the receiver
Serial.begin(9600);
delay(2000);while(!Serial);//delay for Leonardo
}
void loop() {
if (My_Receiver.GetResults(&My_Decoder)) {//Puts results in My_Decoder
My_Hash_Decoder.copyBuf(&My_Decoder);//copy the results to the hash decoder
My_Decoder.decode();
Serial.print("real decode type:");
Serial.print(Pnames(My_Decoder.decode_type));
Serial.print(" value: 0x");
Serial.print(My_Decoder.value, HEX);
My_Hash_Decoder.decode();
Serial.print(", hash decode: 0x");
Serial.println(My_Hash_Decoder.hash, HEX); // Do something interesting with this value
delay(1000);
My_Receiver.resume();
}
}
@@ -0,0 +1,130 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* IRrecord: record and play back IR signals
* An IR detector/demodulator must be connected to the input RECV_PIN.
* An IR LED must be connected to the appropriate pin.(See IRLibTimer.h) for your
* machine's timers and erupts.
* Record a value by pointing your remote at the device then send any character
* from the serial monitor to send the recorded value.
* Also demonstrates how to use toggle bits which must be controlled outside
* the library routines.
* The logic is:
* If an IR code is received, record it.
* If g serial character is received, send the IR code.
*/
#include <IRLib.h>
int RECV_PIN = 11;
IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
IRsend My_Sender;
/*
* Because this version of the library separated the receiver from the decoder,
* technically you would not need to "store" the code outside the decoder object
* for this overly simple example. All of the details would remain in the object.
* However we are going to go ahead and store them just to show you how.
*/
// Storage for the recorded code
IRTYPES codeType; // The type of code
unsigned long codeValue; // The data bits if type is not raw
int codeBits; // The length of the code in bits
// These values are only stored if it's an unknown type and we are going to use
// raw codes to resend the information.
unsigned int rawCodes[RAWBUF]; // The durations if raw
int rawCount; //The number of interval samples
bool GotOne, GotNew;
void setup()
{
GotOne=false; GotNew=false;
codeType=UNKNOWN;
codeValue=0;
Serial.begin(9600);
delay(2000);while(!Serial);//delay for Leonardo
Serial.println(F("Send a code from your remote and we will record it."));
Serial.println(F("Type any character and press enter. We will send the recorded code."));
My_Receiver.enableIRIn(); // Start the receiver
}
// Stores the code for later playback
void storeCode(void) {
GotNew=true;
codeType = My_Decoder.decode_type;
if (codeType == UNKNOWN) {
Serial.println("Received unknown code, saving as raw");
// To store raw codes:
// Drop first value (gap)
// As of v1.3 of IRLib global values are already in microseconds rather than ticks
// They have also been adjusted for overreporting/underreporting of marks and spaces
rawCount = My_Decoder.rawlen-1;
for (int i = 1; i <=rawCount; i++) {
rawCodes[i - 1] = My_Decoder.rawbuf[i];
};
My_Decoder.DumpResults();
codeType=UNKNOWN;
}
else {
Serial.print(F("Received "));
Serial.print(Pnames(codeType));
if (My_Decoder.value == REPEAT) {
// Don't record a NEC repeat value as that's useless.
Serial.println(F("repeat; ignoring."));
}
else {
codeValue = My_Decoder.value;
codeBits = My_Decoder.bits;
}
Serial.print(F(" Value:0x"));
Serial.println(My_Decoder.value, HEX);
}
}
void sendCode(int repeat) {
if(codeType== UNKNOWN) {
// Assume 38 KHz
My_Sender.IRsendRaw::send(rawCodes,rawCount,38);
Serial.println(F("Sent raw"));
return;
}
if( !GotNew ) {//We've already sent this so handle toggle bits
if (codeType == RC5) {
codeValue ^= 0x0800;
}
else if (codeType == RC6) {
codeValue ^= 0x10000;
}
}
GotNew=false;
My_Sender.send(codeType,codeValue,codeBits);
Serial.print(F("Sent "));
Serial.print(Pnames(codeType));
Serial.print(F(" Value:0x"));
Serial.println(codeValue, HEX);
}
void loop() {
if (Serial.read() != -1) {
if(GotOne) {
sendCode(0);
My_Receiver.enableIRIn(); // Re-enable receiver
}
}
else if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
GotOne=true;
storeCode();
delay(1000);
My_Receiver.resume();
}
}
@@ -0,0 +1,40 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* IRLib: IRrecvDump - dump details of IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
*/
#include <IRLib.h>
int RECV_PIN = 11;
IRrecv My_Receiver(RECV_PIN);
IRdecode My_Decoder;
unsigned int Buffer[RAWBUF];
void setup()
{
Serial.begin(9600);
delay(2000);while(!Serial);//delay for Leonardo
My_Receiver.enableIRIn(); // Start the receiver
My_Decoder.UseExtnBuf(Buffer);
}
void loop() {
if (My_Receiver.GetResults(&My_Decoder)) {
//Restart the receiver so it can be capturing another code
//while we are working on decoding this one.
My_Receiver.resume();
My_Decoder.decode();
My_Decoder.DumpResults();
}
}
@@ -0,0 +1,25 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
#include <IRLib.h>
IRsend My_Sender;
void setup()
{
Serial.begin(9600);
}
void loop() {
if (Serial.read() != -1) {
//send a code every time a character is received from the serial port
//Sony DVD power A8BCA
My_Sender.send(SONY,0xa8bca, 20);
}
}
@@ -0,0 +1,37 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* JVC sends repeat codes that are identical to the regular JVC codes
* however they have no header. Therefore there is an additional parameter
* that tells you whether or not to send as an original code or as a repeat.
*
* The only device I had to test this protocol was an old JVC VCR. It would only work if at least
* 2 frames are sent separated by 45us of "space". All JVC is the same bit length so we use
* the third parameter as a flag to tell it whether or not to send the header.
* Send once with the third parameter "1" then delay about 50 microseconds and send again
* with the third parameter "0".
*/
#include <IRLib.h>
IRsend My_Sender;
void setup()
{
Serial.begin(9600);
}
//send a code every time a character is received from the serial port
void loop() {
if (Serial.read() != -1) {
My_Sender.send(JVC,0xc2d0,1); delayMicroseconds (50);
My_Sender.send(JVC,0xc2d0,0); delayMicroseconds (50);
}
}
@@ -0,0 +1,55 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Use serial port to send codes. For details on this project see
http://tech.cyborg5.com/2013/05/30/irlib-tutorial-part-3-overview-sending-ir-codes/
*/
#include <IRLib.h>
IRsend My_Sender;
int protocol;
long code;
int bits;
void setup() {
Serial.begin(9600);
delay(2000);while(!Serial);//delay for Leonardo
}
long parseHex (void) {
long Value=0; char C;delay(100);
while (Serial.available()>0) {
C= tolower(Serial.read());
if ((C>='0')&&(C<='9'))
C=C-'0';
else
if ((C>='a') && (C<='f'))
C=C-'a'+10;
else
return Value;
Value= C+(Value<<4);
};
return Value;
}
void parseDelimiter () {
char C;
while(Serial.available()>0) {
C=tolower(Serial.peek());
if( (C>='0') && (C<='9') )return;
if( (C>='a') && (C<='f') )return;
C=Serial.read();//throwaway delimiters
delay (5);
}
}
void loop() {
if (Serial.available ()>0) {
protocol = Serial.parseInt (); parseDelimiter();
code = parseHex (); parseDelimiter();
bits = Serial.parseInt (); parseDelimiter();
Serial.print("Prot:"); Serial.print(protocol);
Serial.print(" Code:"); Serial.print(code,HEX);
Serial.print(" Bits:"); Serial.println(bits);
My_Sender.send(IRTYPES(protocol), code, bits);
}
}
@@ -0,0 +1,133 @@
# IRLib demo script
# version 1.0 by Chris Young http://tech.cyborg5.com/irlib/
# Displays a "Virtual remote" on your screen. Clicking on the
# buttons sends serial datato the Arduino which in turn
# since IR signals to a cable box in TV.
# Import all of the necessary pieces of code
import serial, sys, pygame, pygame.mixer
from pygame.locals import *
# You will have to edit this to the proper port and speed
ser = serial.Serial('COM4', 9600)
pygame.init()
# Established screen size, size of buttons and position
size = width, height = 400, 768
button_size=54; button_offset=71
button_x1=65;button_y1=39
max_rows=10; max_columns=4
# Specify a font. I'm using Arial narrow bold from my Windows
# font folder. However the default font shown below also works.
myfont =pygame.font.Font ("c:/windows/fonts/ARIALNB.TTF",30)
#myfont=pygame.font.Font(None,36)
# These are the text labels that will appear on each button
label_text=("TVp", "CBp", "P^", "Pv",\
"<<", ">", ">>", "->",\
"Rec", "=", "s", "<-",\
"Gd", "^", "Fav", "Inf",\
"<", "sel", ">", "Lis",\
"ret", "v", "Prv", "Mnu",\
"1", "2", "3", "Ch+",\
"4", "5", "6", "Ch-",\
"7", "8", "9", "Vol+",\
"Pip", "0", "Mut", "Vol-",\
)
# Each of these 40 strings of text correspond to the
# protocol in code which will be sent over the USB serial
# to the Arduino. The first number is the protocol number.
# See the defined protocols in "IRLib.h"for the
# enum IRTYPES at about line 50. This example uses
# protocol 3 which is "RC5" used by my Magnavox TV
# and protocol 5 "PANASONIC_OLD" used by my Scientific
# Atlantic SA 8300 DVR. The protocol number is followed by
# the hex code to be transmitted. That is followed by the
# number of bits. Note that the PANASONIC_OLD protocol
# does not need the number of bits specified so they are omitted.
IR_Codes= ("3,180c,13","5,37c107","5,36d924","5,37d904",\
"5,37291a","5,37990c","5,36293a","5,36b129",\
"5,375914","5,374117","5,365934","5,37c906",\
"5,36c127","5,36812f","5,37f101","5,36213b",\
"5,37810f","5,366133","5,364137","5,36c926",\
"5,366932","5,37a10b","5,36e123","5,373918",\
"5,36113d","5,37111d","5,36912d","5,377111",\
"5,37910d","5,365135","5,375115","5,36f121",\
"5,36d125","5,37d105","5,363139","3,1810,13",\
"5,37b908","5,373119","3,180d,13","3,1811,13",\
)
# This function gets called to shut everything down
def Finished():
pygame.quit()
sys.exit()
# Gets the button index based on mouse position. Returned
# value is from 0 to 39 (number of buttons-1)
# Returns -1 if you are not over a button.
def ComputeButton():
mx,my=pygame.mouse.get_pos()
mx=mx-button_x1
my=my-button_y1
bx=mx/button_offset; by=my/button_offset
if bx<0 or bx>=max_columns:return -1
if by<0 or by> max_rows:return -1
if (mx%button_offset)>button_size:return -1
if (my%button_offset)>button_size:return -1
return bx+by*max_columns
# Blits the button text from button number "i"
# onto the specified layer using the specified color.
def Show_Text(i,Layer,color=(0,0,0)):
t=label_text[i]
label = myfont.render (t,1,color)
labelpos= label.get_rect()
labelpos.centerx=button_x1+button_size/2+i%max_columns*button_offset
labelpos.centery=button_y1+button_size/2+i/max_columns*button_offset
Layer.blit(label,labelpos)
# Create the screen and load the background image.
screen = pygame.display.set_mode(size)
bg = pygame.image.load("remotebg.png")
# Blit black text labels onto the background image
for i in range (max_rows*max_columns):
Show_Text(i, bg)
# Copy the background to the display
screen.blit(bg,(0,0))
pygame.display.flip()
# Load the clicking sound
Click=pygame.mixer.Sound("click.wav")
# Used to detect when the mouse hovers over a different button
previous=-1
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Finished()
elif event.type == KEYDOWN and event.key == K_ESCAPE:
Finished ()
elif event.type == MOUSEBUTTONDOWN:
i=ComputeButton() #which button did we click
if i>=0:
Click.play() #play the sound
ser.write(IR_Codes[i]) #send the codes
elif event.type==MOUSEMOTION:
i=ComputeButton() #which button are we over
if i!=previous: #difference in the last one?
if i>=0: #turn it red
Show_Text(i,screen,(255,0,0))
else: #or put it back the way it was
screen.blit(bg,(0,0))
previous=i
pygame.display.flip() #update the display
# That's all folks
@@ -0,0 +1,62 @@
//POV-Ray source to generate the background image for IRserial_remote
// create rectangular areas with rounded corners for use as
// buttons and background objects.
// Render at 1024x768 then crop 312 pixels from each side
// leaving 400x768 final image.
#declare Area=15; //size of area lights
#declare CR=0.1; //corner radius
#declare ER= 0.5; //edge radius
#declare CX= 3; //width from corner to corner
#declare CY= 7.75; //height from corner to corner
#declare BZ=-ER; //Z offset for buttons
plane {z,0 pigment{rgb<0.8,0.85,1>*0.8}}//background
#macro Thing (ER,CR,CX,CY,T)
#local Corner=
union {
torus {CR,ER rotate x*90}
cylinder {ER*z,-ER*z,CR}
}
union {
object{Corner translate< CX,CY,0>}
object{Corner translate<-CX,CY,0>}
object{Corner translate< CX,-CY,0>}
object{Corner translate<-CX,-CY,0>}
cylinder{CY*y,-CY*y,ER translate<-CX-CR,0,0>}
cylinder{CY*y,-CY*y,ER translate< CX+CR,0,0>}
cylinder{CX*x,-CX*x,ER translate<0,-CY-CR,0>}
cylinder{CX*x,-CX*x,ER translate<0, CY+CR,0>}
box{<-CX,-CY-CR,-ER><CX,CY+CR,ER>}
box{<-CX-CR,-CY,-ER><CX+CR,CY,ER>}
texture {T}
}
#end
#declare BX= 0.4; #declare BY=BX;//size of the buttons
#declare White_Texture=texture{pigment{rgb 1}finish {ambient 0.3}}
#declare Blue_Texture=texture{pigment {rgb<0.85,0.9 ,1>}}
object {Thing(ER,CR,CX,CY, White_Texture)}//main object
//loop through the buttons
#declare R=-4.5;
#while (R<5.5)
#declare C=-1.5;
#while (C<=1.5)
object{Thing(0.1,0.2,(BX*0.8),(BY*0.8), Blue_Texture)
translate <C*BX*4,R*BY*4,BZ>
}
#declare C=C+1;
#end
#declare R=R+1;
#end
light_source{<50,50,-100>*5 color 0.8
#if (Area)area_light x*Area,y*Area,9,9#end
}
light_source{<0,0,-400>*3 rgb 1}
camera{orthographic location <0,0,-120> look_at <0,0,0> angle 11 }
//That's all folks!
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@@ -0,0 +1,75 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.3 January 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* "IRservo" Control a servo using an IR remote
*/
#include <IRLib.h>
#include <Servo.h>
/* Note: Servo library uses TIMER1. The default timer for IRLib on Arduino Uno
* is TIMER2 so there is no conflict. However a default timer on Arduino Leonardo
* is TIMER1 so you will have to modify the timer used to use TIMER3 or TIMER4
* as specified in IRLibTimer.h. Also you will need to modify the input being used.
*/
// You will have to set these values depending on the protocol
// and remote codes that you are using. These are from my Sony DVD/VCR
#define MY_PROTOCOL SONY
#define RIGHT_ARROW 0x86bca //Move several clockwise
#define LEFT_ARROW 0x46bca //Move servo counterclockwise
#define SELECT_BUTTON 0xd0bca //Center the servo
#define UP_ARROW 0x42bca //Increased number of degrees servo moves
#define DOWN_ARROW 0xc2bca //Decrease number of degrees servo moves
#define BUTTON_0 0x90bca //Pushing buttons 0-9 moves to fix positions
#define BUTTON_1 0x00bca // each 20 degrees greater
#define BUTTON_2 0x80bca
#define BUTTON_3 0x40bca
#define BUTTON_4 0xc0bca
#define BUTTON_5 0x20bca
#define BUTTON_6 0xa0bca
#define BUTTON_7 0x60bca
#define BUTTON_8 0xe0bca
#define BUTTON_9 0x10bca
IRrecv My_Receiver(11);//Receive on pin 11
IRdecode My_Decoder;
Servo My_Servo; // create servo object to control a servo
int pos; // variable to store the servo position
int Speed; // Number of degrees to move each time a left/right button is pressed
void setup()
{
My_Receiver.No_Output();//Turn off any unused IR LED output circuit
My_Servo.attach(9); // attaches the servo on pin 9 to the servo object
pos = 90; // start at midpoint 90 degrees
Speed = 3; // servo moves 3 degrees each time left/right is pushed
My_Servo.write(pos); // Set initial position
My_Receiver.enableIRIn(); // Start the receiver
}
void loop()
{
if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
if(My_Decoder.decode_type==MY_PROTOCOL) {
switch(My_Decoder.value) {
case LEFT_ARROW: pos=min(180,pos+Speed); break;
case RIGHT_ARROW: pos=max(0,pos-Speed); break;
case SELECT_BUTTON: pos=90; break;
case UP_ARROW: Speed=min(10, Speed+1); break;
case DOWN_ARROW: Speed=max(1, Speed-1); break;
case BUTTON_0: pos=0*20; break;
case BUTTON_1: pos=1*20; break;
case BUTTON_2: pos=2*20; break;
case BUTTON_3: pos=3*20; break;
case BUTTON_4: pos=4*20; break;
case BUTTON_5: pos=5*20; break;
case BUTTON_6: pos=6*20; break;
case BUTTON_7: pos=7*20; break;
case BUTTON_8: pos=8*20; break;
case BUTTON_9: pos=9*20; break;
}
My_Servo.write(pos); // tell servo to go to position in variable 'pos'
}
My_Receiver.resume();
}
}
@@ -0,0 +1,258 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009I know prescription and no
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* This example demonstrates how to extend this library to add a new protocol
* without actually modifying or recompiling the library itself. It implements a 36 bit
* Samsung protocol that is used on a Blu-ray player that I own.
* Because a 36 bit value will not fit in the value field (only 32 bits) we have to create
* a second value field. This is a modified version of the IRecord example.
*/
#include <IRLib.h>
#include <IRLibMatch.h>
/* Although it is not necessary for this example to run, everything in this section
* this section of the code could be moved to the actual IRLib.h file
*/
class IRdecodeSamsung36: public virtual IRdecodeBase
{
public:
bool decode(void);
unsigned int value2;
void Reset(void);
private:
bool GetBit(void);
int offset;
unsigned long data;
};
class IRsendSamsung36: public virtual IRsendBase
{
public:
void send(unsigned long data, unsigned long data2);
private:
void PutBits (unsigned long data, int nbits);
};
/* If moving this code to IRLib.h instead of the line below at about
line 60 you should search for the line that says...
#define ADDITIONAL (number)
and change the code to read as follows‘
#define NECX 7
#define SAMSUNG36 8
#define HASH_CODE 9
#define LAST_PROTOCOL HASH_CODE
Also at approximately line 160 look for the line that says...
, public virtual IRdecodeADDITIONAL
and change it to read...
public virtual IRdecodeNECx, //Be sure to add the comma
public virtual IRdecodeSamsung36 //No comma here
And at about line 238 change to read...
public virtual IRsendNECx, //Be sure to add the comma
public virtual IRsendSamsung36 //No comma here
Which will add this protocol to the master send and decode classes
*/
#define SAMSUNG36 (LAST_PROTOCOL+1)
/* Although it is not necessary for this example to run, everything in this section
* this section of the code could be moved to the actual IRLib.cpp file
*/
/*
* According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#Samsung36
* The IRP notation for this protocol is:
* {38k,500}<1,-1|1,-3>(9,-9,D:8,S:8,1,-9,E:4,F:8,-68u,~F:8,1,-118)+
* This means it uses 38k frequency. Base timing is multiples of 500.
* A "0" is mark(500) space(500). A "1" is mark (500) space(1500)
* The header is mark(4500) space(4500).
* The header is followed by 16 bits (8 device, 8 sub device)
* This is followed by a mark(500) space(4500).
* This is followed by 12 more bits (4+8)
* This is followed by 68us ofspace. Followed by eight more bits
* and a final stop bit.
*/
/* Because not all of the data bits are contiguous in the stream
* we created this little routine to get one data bit.
* We then call it in a loop as needed.
*/
bool IRdecodeSamsung36::GetBit(void) {
if (!MATCH(rawbuf[offset],500)) return DATA_MARK_ERROR(500);
offset++;
if (MATCH(rawbuf[offset],1500))
data = (data << 1) | 1;
else if (MATCH(rawbuf[offset],500))
data <<= 1;
else return DATA_SPACE_ERROR(1500);
offset++;
return true;
};
bool IRdecodeSamsung36::decode(void) {
IRLIB_ATTEMPT_MESSAGE(F("Samsung36"));
if (rawlen != 78) return RAW_COUNT_ERROR;
if (!MATCH(rawbuf[1],4500)) return HEADER_MARK_ERROR(4500);
if (!MATCH(rawbuf[2],4500)) return HEADER_SPACE_ERROR(4500);
offset=3; data=0;
//Get first 16 bits
while (offset < 16*2+2) if(!GetBit()) return false;
//Skip middle header
if (!MATCH(rawbuf[offset],500)) return DATA_MARK_ERROR(500);
offset++;
if (!MATCH(rawbuf[offset],4500)) return DATA_SPACE_ERROR(4400);
//save first 16 bits in "value2" and reset data
offset++; value2=data; data=0;
//12 bits into this second segment there is a 68us space
//so we find one of the raw values to eliminate that
rawbuf[62]=rawbuf[62]-68;
//this gets remaining 20 bits
while(offset<77)if(!GetBit()) return false;
bits =36;//set bit length
value = data;//put remaining 12 bits in value
decode_type= static_cast<IRTYPES>SAMSUNG36;
return true;
};
//The Reset method clears out the data however we have extra data to clear
void IRdecodeSamsung36::Reset(void) {
IRdecodeBase::Reset();//respect your parents
value2=0;
};
//Similar to GetBits, this routine sends just one bit of data.
//Need this because data bits are not contiguous in the stream
void IRsendSamsung36::PutBits (unsigned long data, int nbits){
for (int i = 0; i < nbits; i++) {
if (data & 0x80000000) {
mark(500); space(1500);
} else {
mark(500); space(500);
};
data <<= 1;
}
}
void IRsendSamsung36::send(unsigned long data, unsigned long data2) {
data <<= 32-20;
data2 <<= 32-16;
enableIROut(38);
mark(4500); space(4500);//Send header
PutBits (data2, 16);//Send data2 16 bits
mark (500); space (4500);//Send break
PutBits (data, 12);//Send 12 bits
space(68);//Send tiny break
data <<= 12;
PutBits (data, 8);mark(500); //Final eight bits and one stop bit
space(118*500);//Lead out is 118 times the base time 500
};
/*
* This concludes the portion that you could move to IRLib.cpp
* Additionally at apprx. line 39 add F("Samsung36"), to the list
* between NECx and hash code.
* Also add "case SAMSUNG36:IRsendSamsung36::send(data,nbits); break;
* at about line 238. Also at about 400 add
* if (IRdecodeSamsung36::decode()) return true;
*/
/*
* The remaining code is unique to the example sketch.
* We will create a custom class which is a combination
* of all other protocols and our new protocol.
*/
class MyCustomSend:
public virtual IRsend,
public virtual IRsendSamsung36
{
public:
//Note: data2 is the number of bits for non-Samsung36 protocols
void send(IRTYPES Type, unsigned long data, int data2);
};
void MyCustomSend::send(IRTYPES Type, unsigned long data, int data2) {
if (Type==SAMSUNG36)
IRsendSamsung36::send(data,data2);
else
IRsend::send(Type, data, data2);
}
class MyCustomDecode:
public virtual IRdecode,
public virtual IRdecodeSamsung36
{
public:
virtual bool decode(void); // Calls each decode routine individually
void DumpResults(void);
};
bool MyCustomDecode::decode(void) {
if (IRdecodeSamsung36::decode()) return true;
return IRdecode::decode ();
}
void MyCustomDecode::DumpResults(void){
if(decode_type==SAMSUNG36) {
Serial.print(F("Decoded Samsung36: Value:")); Serial.print(value, HEX);
Serial.print(F(": Value2:")); Serial.print(value2, HEX);
};
IRdecode::DumpResults();
};
MyCustomDecode My_Decoder;
MyCustomSend My_Sender;
int RECV_PIN = 11;
IRrecv My_Receiver(RECV_PIN);
IRTYPES codeType; // The type of code
unsigned long codeValue; // The data bits
int codeBits; // The length of the code in bits or for Samsung is storage for data2
bool GotOne;
void setup()
{
GotOne=false;
codeType=UNKNOWN;
codeValue=0;
codeBits=0;//Stores data2 on Samsung36. Stores number of bits on another protocols
Serial.begin(9600);
delay(2000); while(!Serial);
Serial.println(F("Send a code from your remote and we will record it."));
Serial.println(F("Type any character and press enter. We will send the recorded code."));
My_Receiver.enableIRIn(); // Start the receiver
}
void loop() {
if (Serial.available()>0) {
unsigned char c=Serial.read();
if (c=='p') {//Send a test pattern
GotOne= true; codeType=SAMSUNG36; codeValue=0x12345; codeBits=0x6789;
}
if(GotOne) {
My_Sender.send(codeType,codeValue,codeBits);
Serial.print(F("Sent "));
if (codeType==SAMSUNG36) {
Serial.print(F("Samsung36 Value:0x"));
Serial.print(codeValue, HEX);
Serial.print(F(" Value2:0x"));
Serial.println(codeBits, HEX);
} else {
Serial.print(Pnames(codeType));
Serial.print(F(" Value:0x"));
Serial.print(codeValue, HEX);
Serial.print(F(" Bits:"));
Serial.println(codeBits, DEC);
};
My_Receiver.enableIRIn(); // Re-enable receiver
}
}
else if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
if(My_Decoder.decode_type == UNKNOWN) {
Serial.println(F("Unknown type received. Ignoring."));
} else {
codeType= My_Decoder.decode_type;
codeValue= My_Decoder.value;
codeBits= My_Decoder.bits;
GotOne=true;
}
My_Decoder.DumpResults();
delay(1000);
My_Receiver.resume();
}
}
+210
View File
@@ -0,0 +1,210 @@
/* Example program for from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
* Based on original example sketch for IRremote library
* Version 0.11 September, 2009I know prescription and no
* Copyright 2009 Ken Shirriff
* http://www.righto.com/
*/
/*
* This example demonstrates how to extend this library to add a new protocol
* without actually modifying or recompiling the libnonstickrary itself. It implements the
* Phillips RC-MM also known as Nokia Protocol. Is used by AT&T U-Verse cable boxes.
* There are three different varieties that are 12, 24, or 32 bits.
* This is a modified version of the IRecord example.
* If you would like to make this a permanent part of your library you could copy the class
* prototypes to IRLib.h and the code itself to IRLib.cpp. Search for the word "ADDITIONAL"
* to see where to add various pieces of code. Also see the Samsung36 example for details.
*/
#include <IRLib.h>
#include <IRLibMatch.h>
class IRdecodeRCMM: public virtual IRdecodeBase
{
public:
bool decode(void);
};
class IRsendRCMM: public virtual IRsendBase
{
public:
void send(unsigned long data, unsigned char nbits);
};
#define RCMM (LAST_PROTOCOL+1)
#define RCMM_HEAD_MARK 417
#define RCMM_DATA_MARK 167
#define RCMM_ZERO 278
#define RCMM_ONE 444
#define RCMM_TWO 611
#define RCMM_THREE 778
/*
* According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#Nokia
* The IRP notation for these protocols are:
* Nokia 12 bit: {36k,msb}<164,-276|164,-445|164,-614|164,-783>(412,-276,D:4,F:8,164,-???)+
* Nokia 24-bit: {36k,msb}<164,-276|164,-445|164,-614|164,-783>(412,-276,D:8,S:8,F:8,164,-???)+
* Nokia 32 bit: {36k,msb}<164,-276|164,-445|164,-614|164,-783>(412,-276,D:8,S:8,X:8,F:8,164,^100m)+
* Slightly different timing values are documented at
* http://www.sbprojects.com/knowledge/ir/rcmm.php
* We will use the timing from the latter reference.
* Unlike most protocols which defined sequences for a logical "0" and "1", this protocol
* encodes 2 bits per pulse. Therefore it encodes a logical "2" and "3" as well.
* The length of the mark is constant but the length of the space denotes the bit values.
* Note the 32-bit version uses a toggle bit of 0x8000 and as usual it is up to the end-user
* to implement it outside the library routines.
*/
/*
* Normally IRLib uses a plus or minus percentage to determine if an interval matches the
* desired value. However this protocol uses extremely long intervals of similar length.
* For example using the default 25% tolerance the RCMM_TWO value 611 would be accepted for
* anything between 458 and 763. The low end is actually closer to RCMM_ONE value of 444
* and the upper range is closer to RCM_THREE value of 778. To implement this protocol
* we created a new match routine ABS_MATCH which allows you to specify an absolute
* number of microseconds of tolerance for comparison.
*/
#define RCMM_TOLERANCE 80
bool IRdecodeRCMM::decode(void) {
long data;
IRLIB_ATTEMPT_MESSAGE(F("RCMM"));
if ( (rawlen!=(12+2)) && (rawlen!=(24+2)) && (rawlen!=(32+4)) ) return RAW_COUNT_ERROR;
if (!MATCH(rawbuf[1],RCMM_HEAD_MARK)) return HEADER_MARK_ERROR(RCMM_HEAD_MARK);
if (!MATCH(rawbuf[2],RCMM_ZERO)) return HEADER_SPACE_ERROR(RCMM_ZERO);
offset=3; data=0;
while (offset < (rawlen-1)) {
if (!ABS_MATCH(rawbuf[offset],RCMM_DATA_MARK, RCMM_TOLERANCE+50)) return DATA_MARK_ERROR(RCMM_DATA_MARK);
offset++;
if (ABS_MATCH(rawbuf[offset],RCMM_ZERO, RCMM_TOLERANCE) ) { //Logical "0"
data <<= 2;
}
else if (ABS_MATCH(rawbuf[offset],RCMM_ONE, RCMM_TOLERANCE) ) { //Logical "1"
data = (data<<2) + 1;
}
else if (ABS_MATCH(rawbuf[offset],RCMM_TWO, RCMM_TOLERANCE) ) { //Logical "2"
data = (data<<2) + 2;
}
else if (ABS_MATCH(rawbuf[offset],RCMM_THREE, RCMM_TOLERANCE) ) { //Logical "3"
data = (data<<2) + 3;
}
else return DATA_SPACE_ERROR(RCMM_ZERO);
offset++;
}
if (!MATCH(rawbuf[offset],RCMM_DATA_MARK)) return DATA_MARK_ERROR(RCMM_DATA_MARK);
bits = rawlen-4;//set bit length
value = data;//put remaining bits in value
decode_type= static_cast<IRTYPES>RCMM;
return true;
};
void IRsendRCMM::send(unsigned long data, unsigned char nbits) {
Extent=0;
data = data << (32 - nbits);
nbits=nbits/2;
enableIROut(36);
mark(RCMM_HEAD_MARK); space(RCMM_ZERO);//Send header
for (int i = 0; i < nbits; i++) {
mark(RCMM_DATA_MARK);
switch (data & 0xC0000000UL) {//use the leftmost two bits
case 0x00000000UL: space(RCMM_ZERO); break;
case 0x40000000UL: space(RCMM_ONE); break;
case 0x80000000UL: space(RCMM_TWO); break;
case 0xC0000000UL: space(RCMM_THREE); break;
default: Serial.println("sending error");
}
data <<= 2;
};
mark(RCMM_DATA_MARK);
space(27778-Extent);
};
//Create a custom class that combines this new protocol with all the others
class MyCustomSend:
public virtual IRsend,
public virtual IRsendRCMM
{
public:
void send(IRTYPES Type, unsigned long data, int nbits);
};
void MyCustomSend::send(IRTYPES Type, unsigned long data, int nbits) {
if (Type==RCMM)
IRsendRCMM::send(data,nbits);
else
IRsend::send(Type, data, nbits);
}
class MyCustomDecode:
public virtual IRdecode,
public virtual IRdecodeRCMM
{
public:
virtual bool decode(void); // Calls each decode routine individually
void DumpResults(void);
};
bool MyCustomDecode::decode(void) {
if (IRdecodeRCMM::decode()) return true;
return IRdecode::decode ();
}
void MyCustomDecode::DumpResults(void){
if(decode_type==RCMM) {
Serial.print(F("Decoded RCMM: Value:")); Serial.print(value, HEX);
};
IRdecode::DumpResults();
};
MyCustomDecode My_Decoder;
MyCustomSend My_Sender;
int RECV_PIN = 11;
IRrecv My_Receiver(RECV_PIN);
IRTYPES codeType; // The type of code
unsigned long codeValue; // The data bits
int codeBits; // The length of the code in bits or for Samsung is storage for data2
bool GotOne;
char c;
void setup()
{
GotOne=false;
codeType=UNKNOWN;
codeValue=0;
codeBits=0;
Serial.begin(9600);while (! Serial) {};
Serial.println(F("Send a code from your remote and we will record it."));
Serial.println(F("Type any character and press enter. We will send the recorded code."));
My_Receiver.enableIRIn(); // Start the receiver
My_Receiver.Mark_Excess=40;
}
void loop() {
if (Serial.available()>0) {
c=Serial.read();
if (c=='p') {//Send a test pattern
GotOne= true; codeType=RCMM; codeValue=0x12345678; codeBits= 32;
}
if(GotOne) {
My_Sender.send(codeType,codeValue,codeBits);
Serial.print(F("Sent "));
if (codeType== RCMM) Serial.print(F("RCMM")); else Serial.print(Pnames(codeType));
Serial.print(F(" Value:0x"));
Serial.print(codeValue, HEX);
Serial.print(F(" Bits:"));
Serial.println(codeBits, DEC);
My_Receiver.enableIRIn(); // Re-enable receiver
}
}
else if (My_Receiver.GetResults(&My_Decoder)) {
My_Decoder.decode();
if(My_Decoder.decode_type == UNKNOWN) {
Serial.println(F("Unknown type received. Ignoring."));
} else {
codeType= My_Decoder.decode_type;
codeValue= My_Decoder.value;
codeBits= My_Decoder.bits;
GotOne=true;
}
My_Decoder.DumpResults();
delay(1000);
My_Receiver.resume();
}
}