Files
MySensors/libraries/IRLib/examples/rcmm/rcmm.ino
T

211 lines
7.3 KiB
Arduino
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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();
}
}