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
+22
View File
@@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
+215
View File
@@ -0,0 +1,215 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
+50
View File
@@ -0,0 +1,50 @@
Change Log for IRLib – an Arduino library for infrared encoding and decoding
Copyright 2013-2014 by Chris Young http://tech.cyborg5.com/irlib/
Version 1.4 – March 2014
Added IRLIB_ prefix to debug macros to avoid name collisions
Debug macros now report more information
Added example new protocol Phillips RCMM used by AT&T U-Verse boxes and Nokia satellite boxes
Added ABS_MATCH macro which allows you to match using absolute number of microseconds versus the old way which used a percentage. Necessary for implementing RCMM protocol.
Added IRLIB_USE_PERCENT definition which when commented out changes the default from percentage match to absolute match. Also added DEFAULT_ABS_TOLERANCE. More details on these changes will be provided in the documentation when the section on adding new protocols is completed.
Version 1.31 – March 2014
Commented out debug code that was accidentally left active in 1.3 release
Version 1.3 – January 2014
NEW FILES
Added new file IRLibRData.h and moved irparams structure and related items to that file. Allows users to create custom IRrecv classes
NEW EXAMPLES
Rewrote Samsung36 example to include both send and receive
Added new examples for new protocols DirecTV and GIcable
Added new example IRanalyze gives more detailed analysis of timing. Useful in analyzing the protocols
Added new example IRfreq reports modulation frequency of a signal. Requires TSMP58000 IR learner chip
Cleanup of other example routines.
NEW CLASSES
Created IRrecvBase class to allow custom receiver classes. IRrecv is now a derived class from it.
Created IRrecvLoop class which receives IR signals without using any hardware interrupts or timers. Also created IRrecvPCI class which uses Pin Change Interrupts to receive IR signals. These new receivers are more accurate than the 50µs timing of the original IRrecv. However they also have other limitations described in comments.
New functions, variables and methods
In IRrecvBase added "unsigned char Mark_Excess" with default value 100. Was a define macro but now is user settable.
In IRrecvBase added method "unsigned char getPinNum(void);" which retrieves the pin number used from irparams.recvpin. This value not normally accessible to end user.
Globally available function "void do_Blink(void);" blinks pin 13 LED. For use by user created extensions of IRrecvBase.
INTERNAL CHANGES
Data collected by IRrecvBase classes in irparams.rawbuf is now converted to actual microseconds rather than clock ticks of 50 µs each. IRrecvBase::GetResults has a new parameter "Time_per_Ticks" that is used to convert ticks into actual microseconds if needed.
Adjustments to mark and space to deal with overreporting and underreporting of intervals is now done once in IRrecvBase::GetResults eliminating the need for MATCH_MARK(d,v) and MATCH_SPACE(d,v). Just use MATCH(d,v) everywhere.
Modified IRLibsendBase::mark() and IRLibsendBase::space() to overcome limitations of "delayMicroseconds()".
Changed many int to char or unsigned char to save memory
Eliminated DEBUG macro in IRLib.h and its use elsewhere. Macro TRACE is more useful.
Changed IRTYPES to unsigned char and a list of #defines rather than an enum (even though I still really like enums, changing it saves memory)
MEMORY EFFICIENCY
Code changes result in memory savings of approximately 54 bytes in code space and 39 bytes of RAM.
--------------------------------
Version 1.2 – July 2013
Internal version. No public release
--------------------------------
Version 1.1 – April 2013
Constructor of IRsendBase now initializes output pin and forces it low immediately.
New IRrecv::No_Output() method initializes output pin and forces it low. Use this in sketches which receive only by the have output hardware connected.
Added examples IRservo and IRserial_remote
--------------------------------
Version 1.0a – February 2013
Removed debugging test switch which was accidentally left on in file "IRLib.h"
--------------------------------
Version 1.0 – January 2013
Initial Release
File diff suppressed because it is too large Load Diff
+323
View File
@@ -0,0 +1,323 @@
/* IRLib.h from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
* That same license applies to this modified version. See his original copyright below.
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
* My purpose was to reorganize the code to make it easier to add or remove protocols.
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
* by making them separate classes. That way the receiving aspect can be more black box and implementers
* of decoders and senders can just deal with the decoding of protocols. It also allows for alternative
* types of receivers independent of the decoding. This makes porting to different hardware platforms easier.
* Also added provisions to make the classes base classes that could be extended with new protocols
* which would not require recompiling of the original library nor understanding of its detailed contents.
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
* Some changes were just my weird programming style. Also extended debugging information added.
*/
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html http://www.righto.com/
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*/
#ifndef IRLib_h
#define IRLib_h
#include <Arduino.h>
// The following are compile-time library options.
// If you change them, recompile the library.
// If IRLIB_TRACE is defined, some debugging information about the decode will be printed
// IRLIB_TEST must be defined for the IRtest unittests to work. It will make some
// methods virtual, which will be slightly slower, which is why it is optional.
// #define IRLIB_TRACE
// #define IRLIB_TEST
// Only used for testing; can remove virtual for shorter code
#ifdef IRLIB_TEST
#define VIRTUAL virtual
#else
#define VIRTUAL
#endif
#define RAWBUF 100 // Length of raw duration buffer (cannot exceed 255)
typedef char IRTYPES; //formerly was an enum
#define UNKNOWN 0
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define PANASONIC_OLD 5
#define JVC 6
#define NECX 7
//#define ADDITIONAL (number) //make additional protocol 8 and change HASH_CODE to 9
#define HASH_CODE 8
#define LAST_PROTOCOL HASH_CODE
const __FlashStringHelper *Pnames(IRTYPES Type); //Returns a character string that is name of protocol.
// Base class for decoding raw results
class IRdecodeBase
{
public:
IRdecodeBase(void);
IRTYPES decode_type; // NEC, SONY, RC5, UNKNOWN etc.
unsigned long value; // Decoded value
unsigned char bits; // Number of bits in decoded value
volatile unsigned int *rawbuf; // Raw intervals in microseconds
unsigned char rawlen; // Number of records in rawbuf.
virtual void Reset(void); // Initializes the decoder
virtual bool decode(void); // This base routine always returns false override with your routine
bool decodeGeneric(unsigned char Raw_Count, unsigned int Head_Mark, unsigned int Head_Space,
unsigned int Mark_One, unsigned int Mark_Zero, unsigned int Space_One, unsigned int Space_Zero);
virtual void DumpResults (void);
void UseExtnBuf(void *P); //Normally uses same rawbuf as IRrecv. Use this to define your own buffer.
void copyBuf (IRdecodeBase *source);//copies rawbuf and rawlen from one decoder to another
protected:
unsigned char offset; // Index into rawbuf used various places
};
class IRdecodeHash: public virtual IRdecodeBase
{
public:
unsigned long hash;
virtual bool decode(void);//made virtual in case you want to substitute your own hash code
protected:
int compare(unsigned int oldval, unsigned int newval);//used by decodeHash
};
class IRdecodeNEC: public virtual IRdecodeBase
{
public:
virtual bool decode(void);
};
class IRdecodeSony: public virtual IRdecodeBase
{
public:
virtual bool decode(void);
};
class IRdecodeRC: public virtual IRdecodeBase
{
public:
enum RCLevel {MARK, SPACE, ERROR};//used by decoders for RC5/RC6
// These are called by decode
RCLevel getRClevel(unsigned char *used, const unsigned int t1);
protected:
unsigned char nbits;
unsigned char used;
long data;
};
class IRdecodeRC5: public virtual IRdecodeRC
{
public:
virtual bool decode(void);
};
class IRdecodeRC6: public virtual IRdecodeRC
{
public:
virtual bool decode(void);
};
class IRdecodePanasonic_Old: public virtual IRdecodeBase
{
public:
virtual bool decode(void);
};
class IRdecodeJVC: public virtual IRdecodeBase
{
public:
virtual bool decode(void);
};
class IRdecodeNECx: public virtual IRdecodeBase
{
public:
virtual bool decode(void);
};
// main class for decoding all supported protocols
class IRdecode:
public virtual IRdecodeNEC,
public virtual IRdecodeSony,
public virtual IRdecodeRC5,
public virtual IRdecodeRC6,
public virtual IRdecodePanasonic_Old,
public virtual IRdecodeJVC,
public virtual IRdecodeNECx
// , public virtual IRdecodeADDITIONAL //add additional protocols here
{
public:
virtual bool decode(void); // Calls each decode routine individually
};
//Base class for sending signals
class IRsendBase
{
public:
IRsendBase();
void sendGeneric(unsigned long data, unsigned char Num_Bits, unsigned int Head_Mark, unsigned int Head_Space,
unsigned int Mark_One, unsigned int Mark_Zero, unsigned int Space_One, unsigned int Space_Zero,
unsigned char kHz, bool Stop_Bits, unsigned long Max_Extent=0);
protected:
void enableIROut(unsigned char khz);
VIRTUAL void mark(unsigned int usec);
VIRTUAL void space(unsigned int usec);
unsigned long Extent;
};
class IRsendNEC: public virtual IRsendBase
{
public:
void send(unsigned long data);
};
class IRsendSony: public virtual IRsendBase
{
public:
void send(unsigned long data, int nbits);
};
class IRsendRaw: public virtual IRsendBase
{
public:
void send(unsigned int buf[], unsigned char len, unsigned char khz);
};
class IRsendRC5: public virtual IRsendBase
{
public:
void send(unsigned long data);
};
class IRsendRC6: public virtual IRsendBase
{
public:
void send(unsigned long data, unsigned char nbits);
};
class IRsendPanasonic_Old: public virtual IRsendBase
{
public:
void send(unsigned long data);
};
class IRsendJVC: public virtual IRsendBase
{
public:
void send(unsigned long data, bool First);
};
class IRsendNECx: public virtual IRsendBase
{
public:
void send(unsigned long data);
};
class IRsend:
public virtual IRsendNEC,
public virtual IRsendSony,
public virtual IRsendRaw,
public virtual IRsendRC5,
public virtual IRsendRC6,
public virtual IRsendPanasonic_Old,
public virtual IRsendJVC,
public virtual IRsendNECx
// , public virtual IRsendADDITIONAL //add additional protocols here
{
public:
void send(IRTYPES Type, unsigned long data, unsigned int data2);
};
// Changed this to a base class so it can be extended
class IRrecvBase
{
public:
IRrecvBase(void) {};
IRrecvBase(unsigned char recvpin);
void No_Output(void);
void blink13(bool blinkflag);
bool GetResults(IRdecodeBase *decoder, const unsigned int Time_per_Ticks=1);
void enableIRIn(void);
virtual void resume(void);
unsigned char getPinNum(void);
unsigned char Mark_Excess;
protected:
void Init(void);
};
/* Original IRrecv class uses 50µs interrupts to sample input. While this is generally
* accurate enough for everyday purposes, it may be difficult to port to other
* hardware unless you know a lot about hardware timers and interrupts. Also
* when trying to analyze unknown protocols, the 50µs granularity may not be sufficient.
* In that case use either the IRrecvLoop or the IRrecvPCI class.
*/
class IRrecv: public IRrecvBase
{
public:
IRrecv(unsigned char recvpin):IRrecvBase(recvpin){};
bool GetResults(IRdecodeBase *decoder);
void enableIRIn(void);
void resume(void);
};
/* This receiver uses no interrupts or timers. Other interrupt driven receivers
* allow you to do other things and call GetResults at your leisure to see if perhaps
* a sequence has been received. Typically you would put GetResults in your loop
* and it would return false until the sequence had been received. However because this
* receiver uses no interrupts, it takes control of your program when you call GetResults
* and doesn't let go until it's got something to show you. The advantage is you don't need
* interrupts which would make it easier to use and nonstandard hardware and will allow you to
* use any digital input pin. Timing of this routine is only as accurate as your "micros();"
*/
class IRrecvLoop: public IRrecvBase
{
public:
IRrecvLoop(unsigned char recvpin):IRrecvBase(recvpin){};
bool GetResults(IRdecodeBase *decoder);
};
/* This receiver uses the pin change hardware interrupt to detect when your input pin
* changes state. It gives more detailed results than the 50µs interrupts of IRrecv
* and theoretically is more accurate than IRrecvLoop. However because it only detects
* pin changes, it doesn't always know when it's finished. GetResults attempts to detect
* a long gap of space but sometimes the next signal gets there before GetResults notices.
* This means the second set of signals can get messed up unless there is a long gap.
* This receiver is based in part 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 section of code.
*/
class IRrecvPCI: public IRrecvBase
{
public:
//Note this is interrupt number not pin number
IRrecvPCI(unsigned char inum);
bool GetResults(IRdecodeBase *decoder);
void resume(void);
private:
unsigned char intrnum;
};
//Do the actual blinking off and on
//This is not part of IRrecvBase because it may need to be inside an ISR
//and we cannot pass parameters to them.
void do_Blink(void);
// Some useful constants
// Decoded value for NEC when a repeat code is received
#define REPEAT 0xffffffff
#endif //IRLib_h
+100
View File
@@ -0,0 +1,100 @@
/* IRLibMatch.h from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
* That same license applies to this modified version. See his original copyright below.
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
* My purpose was to reorganize the code to make it easier to add or remove protocols.
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
* by making them separate classes. That way the receiving aspect can be more black box and implementers
* of decoders and senders can just deal with the decoding of protocols. It also allows for alternative
* types of receivers independent of the decoding. This makes porting to different hardware platforms easier.
* Also added provisions to make the classes base classes that could be extended with new protocols
* which would not require recompiling of the original library nor understanding of its detailed contents.
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
* Some changes were just my weird programming style. Also extended debugging information added.
*/
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html http://www.righto.com/
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*/
#ifndef IRLibMatch_h
#define IRLibMatch_h
/*
* Originally all timing comparisons for decoding were based on a percent of the
* target value. However when target values are relatively large, the percent tolerance
* is too much. In some instances an absolute tolerance is needed. In order to maintain
* backward compatibility, the default will be to continue to use percent. If you wish to default
* to an absolute tolerance, you should comment out the line below.
*/
#define IRLIB_USE_PERCENT
/*
* These are some miscellaneous definitions that are needed by the decoding routines.
* You need not include this file unless you are creating custom decode routines
* which will require these macros and definitions. Even if you include it, you probably
* don't need to be intimately familiar with the internal details.
*/
#define USECPERTICK 50 // microseconds per clock interrupt tick
#define PERCENT_TOLERANCE 25 // percent tolerance in measurements
#define DEFAULT_ABS_TOLERANCE 75 //absolute tolerance in microseconds
/*
* These revised MATCH routines allow you to use either percentage were absolute tolerances.
* Use ABS_MATCH for absolute and PERC_MATCH percentages. The original MATCH macro
* is controlled by the IRLIB_USE_PERCENT definition a few lines above.
*/
#define PERCENT_LOW(us) (unsigned int) (((us)*(1.0 - PERCENT_TOLERANCE/100.)))
#define PERCENT_HIGH(us) (unsigned int) (((us)*(1.0 + PERCENT_TOLERANCE/100.) + 1))
#define ABS_MATCH(v,e,t) ((v) >= ((e)-(t)) && (v) <= ((e)+(t)))
#define PERC_MATCH(v,e) ((v) >= PERCENT_LOW(e) && (v) <= PERCENT_HIGH(e))
#ifdef IRLIB_USE_PERCENT
#define MATCH(v,e) PERC_MATCH(v,e)
#else
#define MATCH(v,e) ABS_MATCH(v,e,DEFAULT_ABS_TOLERANCE)
#endif
//The following two routines are no longer necessary because mark/space adjustments are done elsewhere
//These definitions maintain backward compatibility.
#define MATCH_MARK(t,u) MATCH(t,u)
#define MATCH_SPACE(t,u) MATCH(t,u)
#ifdef IRLIB_TRACE
void IRLIB_ATTEMPT_MESSAGE(const __FlashStringHelper * s);
void IRLIB_TRACE_MESSAGE(const __FlashStringHelper * s);
byte IRLIB_REJECTION_MESSAGE(const __FlashStringHelper * s);
byte IRLIB_DATA_ERROR_MESSAGE(const __FlashStringHelper * s, unsigned char index, unsigned int value, unsigned int expected);
#define RAW_COUNT_ERROR IRLIB_REJECTION_MESSAGE(F("number of raw samples"));
#define HEADER_MARK_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("header mark"),offset,rawbuf[offset],expected);
#define HEADER_SPACE_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("header space"),offset,rawbuf[offset],expected);
#define DATA_MARK_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("data mark"),offset,rawbuf[offset],expected);
#define DATA_SPACE_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("data space"),offset,rawbuf[offset],expected);
#define TRAILER_BIT_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("RC5/RC6 trailer bit length"),offset,rawbuf[offset],expected);
#else
#define IRLIB_ATTEMPT_MESSAGE(s)
#define IRLIB_TRACE_MESSAGE(s)
#define IRLIB_REJECTION_MESSAGE(s) false
#define IRLIB_DATA_ERROR_MESSAGE(s,i,v,e) false
#define RAW_COUNT_ERROR false
#define HEADER_MARK_ERROR(expected) false
#define HEADER_SPACE_ERROR(expected) false
#define DATA_MARK_ERROR(expected) false
#define DATA_SPACE_ERROR(expected) false
#define TRAILER_BIT_ERROR(expected) false
#endif
#endif //IRLibMatch_h
+54
View File
@@ -0,0 +1,54 @@
/* IRLibRData.h from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
* That same license applies to this modified version. See his original copyright below.
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
* My purpose was to reorganize the code to make it easier to add or remove protocols.
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
* by making them separate classes. That way the receiving aspect can be more black box and implementers
* of decoders and senders can just deal with the decoding of protocols. It also allows for alternative
* types of receivers independent of the decoding. This makes porting to different hardware platforms easier.
* Also added provisions to make the classes base classes that could be extended with new protocols
* which would not require recompiling of the original library nor understanding of its detailed contents.
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
* Some changes were just my weird programming style. Also extended debugging information added.
*/
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html http://www.righto.com/
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*/
#ifndef IRLibRData_h
#define IRLibRData_h
/*
* The structure contains a variety of variables needed by the receiver routines.
* Typically this data would be part of the IRrecv class however the interrupt service routine
* must have access to it and you cannot pass a parameter to such a routine. The data must be global.
* You need not include this file unless you are creating a custom receiver class or extending
* the provided IRrecv class.
*/
// receiver states
enum rcvstate_t {STATE_UNKNOWN, STATE_IDLE, STATE_MARK, STATE_SPACE, STATE_STOP, STATE_RUNNING};
// information for the interrupt handler
typedef struct {
unsigned char recvpin; // pin for IR data from detector
rcvstate_t rcvstate; // state machine
bool blinkflag; // TRUE to enable blinking of pin 13 on IR processing
unsigned long timer; // state timer, counts 50uS ticks.(and other uses)
unsigned int rawbuf[RAWBUF]; // raw data
unsigned char rawlen; // counter of entries in rawbuf
}
irparams_t;
extern volatile irparams_t irparams;
#endif
+330
View File
@@ -0,0 +1,330 @@
/* IRLibTimer.h from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
* GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make modified versions.
* That same license applies to this modified version. See his original copyright below.
* The latest Ken Shirriff code can be found at https://github.com/shirriff/Arduino-IRremote
* My purpose was to reorganize the code to make it easier to add or remove protocols.
* As a result I have separated the act of receiving a set of raw timing codes from the act of decoding them
* by making them separate classes. That way the receiving aspect can be more black box and implementers
* of decoders and senders can just deal with the decoding of protocols. It also allows for alternative
* types of receivers independent of the decoding. This makes porting to different hardware platforms easier.
* Also added provisions to make the classes base classes that could be extended with new protocols
* which would not require recompiling of the original library nor understanding of its detailed contents.
* Some of the changes were made to reduce code size such as unnecessary use of long versus bool.
* Some changes were just my weird programming style. Also extended debugging information added.
*/
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html http://www.righto.com/
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*/
/* This file defines which timer you wish to use. Different versions of Arduino and related boards
* have different timers available to them. For various reasons you might want to use something other than
* timer 2. Some boards do not have timer 2. This attempts to detect which type of board you are using.
* You need uncomment wish to use on your board. You probably will not need to include this in your
* program unless you want to see which timer is being used and which board has been detected.
* This information came from an alternative fork of the original Ken Shirriff library found here
* https://github.com/TKJElectronics/Arduino-IRremote
*/
#ifndef IRLibTimer_h
#define IRLibTimer_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//#define IR_USE_TIMER1 // tx = pin 11
#define IR_USE_TIMER2 // tx = pin 9
//#define IR_USE_TIMER3 // tx = pin 5
//#define IR_USE_TIMER4 // tx = pin 6
//#define IR_USE_TIMER5 // tx = pin 46
// Teensy 1.0
#elif defined(__AVR_AT90USB162__)
#define IR_USE_TIMER1 // tx = pin 17
// Teensy 2.0 versus Leonardo
// These boards use the same chip but the pinouts are different.
#elif defined(__AVR_ATmega32U4__)
#ifdef CORE_TEENSY
// it's Teensy 2.0
//#define IR_USE_TIMER1 // tx = pin 14
//#define IR_USE_TIMER3 // tx = pin 9
#define IR_USE_TIMER4_HS // tx = pin 10
#else
// it's probably Leonardo
#define IR_USE_TIMER1 // tx = pin 9
//#define IR_USE_TIMER3 // tx = pin 5
//#define IR_USE_TIMER4_HS // tx = pin 13
#endif
// Teensy++ 1.0 & 2.0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
//#define IR_USE_TIMER1 // tx = pin 25
#define IR_USE_TIMER2 // tx = pin 1
//#define IR_USE_TIMER3 // tx = pin 16
// Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
//#define IR_USE_TIMER1 // tx = pin 13
#define IR_USE_TIMER2 // tx = pin 14
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#else
//#define IR_USE_TIMER1 // tx = pin 9
#define IR_USE_TIMER2 // tx = pin 3
#endif
// defines for timer2 (8 bits)
#if defined(IR_USE_TIMER2)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR2A |= _BV(COM2B1))
#define TIMER_DISABLE_PWM (TCCR2A &= ~(_BV(COM2B1)))
#define TIMER_ENABLE_INTR (TIMSK2 = _BV(OCIE2A))
#define TIMER_DISABLE_INTR (TIMSK2 = 0)
#define TIMER_INTR_NAME TIMER2_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR2A = _BV(WGM20); \
TCCR2B = _BV(WGM22) | _BV(CS20); \
OCR2A = pwmval; \
OCR2B = pwmval / 3; \
})
#define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000)
#if (TIMER_COUNT_TOP < 256)
#define TIMER_CONFIG_NORMAL() ({ \
TCCR2A = _BV(WGM21); \
TCCR2B = _BV(CS20); \
OCR2A = TIMER_COUNT_TOP; \
TCNT2 = 0; \
})
#else
#define TIMER_CONFIG_NORMAL() ({ \
TCCR2A = _BV(WGM21); \
TCCR2B = _BV(CS21); \
OCR2A = TIMER_COUNT_TOP / 8; \
TCNT2 = 0; \
})
#endif
#if defined(CORE_OC2B_PIN)
#define TIMER_PWM_PIN CORE_OC2B_PIN /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 9 /* Arduino Mega */
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TIMER_PWM_PIN 14 /* Sanguino */
#else
#define TIMER_PWM_PIN 3 /* Arduino Duemilanove, Diecimila, LilyPad, etc */
#endif
// defines for timer1 (16 bits)
#elif defined(IR_USE_TIMER1)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR1A |= _BV(COM1A1))
#define TIMER_DISABLE_PWM (TCCR1A &= ~(_BV(COM1A1)))
#define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A))
#define TIMER_DISABLE_INTR (TIMSK1 = 0)
#define TIMER_INTR_NAME TIMER1_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR1A = _BV(WGM11); \
TCCR1B = _BV(WGM13) | _BV(CS10); \
ICR1 = pwmval; \
OCR1A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR1A = 0; \
TCCR1B = _BV(WGM12) | _BV(CS10); \
OCR1A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT1 = 0; \
})
#if defined(CORE_OC1A_PIN)
#define TIMER_PWM_PIN CORE_OC1A_PIN /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 11 /* Arduino Mega */
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TIMER_PWM_PIN 13 /* Sanguino */
#else
#define TIMER_PWM_PIN 9 /* Arduino Duemilanove, Diecimila, LilyPad, etc */
#endif
// defines for timer3 (16 bits)
#elif defined(IR_USE_TIMER3)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR3A |= _BV(COM3A1))
#define TIMER_DISABLE_PWM (TCCR3A &= ~(_BV(COM3A1)))
#define TIMER_ENABLE_INTR (TIMSK3 = _BV(OCIE3A))
#define TIMER_DISABLE_INTR (TIMSK3 = 0)
#define TIMER_INTR_NAME TIMER3_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR3A = _BV(WGM31); \
TCCR3B = _BV(WGM33) | _BV(CS30); \
ICR3 = pwmval; \
OCR3A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR3A = 0; \
TCCR3B = _BV(WGM32) | _BV(CS30); \
OCR3A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT3 = 0; \
})
#if defined(CORE_OC3A_PIN)
#define TIMER_PWM_PIN CORE_OC3A_PIN /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 5 /* Arduino Mega */
#elif defined(__AVR_ATmega32U4__)
#define TIMER_PWM_PIN 5 /* Arduino Leonardo note already checked for Teensy */
#else
#error "Please add OC3A pin number here\n"
#endif
// defines for timer4 (10 bits, high speed option)
#elif defined(IR_USE_TIMER4_HS)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
#define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4))
#define TIMER_DISABLE_INTR (TIMSK4 = 0)
#define TIMER_INTR_NAME TIMER4_OVF_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR4A = (1<<PWM4A); \
TCCR4B = _BV(CS40); \
TCCR4C = 0; \
TCCR4D = (1<<WGM40); \
TCCR4E = 0; \
TC4H = pwmval >> 8; \
OCR4C = pwmval; \
TC4H = (pwmval / 3) >> 8; \
OCR4A = (pwmval / 3) & 255; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR4A = 0; \
TCCR4B = _BV(CS40); \
TCCR4C = 0; \
TCCR4D = 0; \
TCCR4E = 0; \
TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \
OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \
TC4H = 0; \
TCNT4 = 0; \
})
#if defined(CORE_OC4A_PIN)
#define TIMER_PWM_PIN CORE_OC4A_PIN /* Teensy */
#elif defined(__AVR_ATmega32U4__)
#define TIMER_PWM_PIN 13 /*Leonardo*/
#else
#error "Please add OC4A pin number here\n"
#endif
// defines for timer4 (16 bits)
#elif defined(IR_USE_TIMER4)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
#define TIMER_ENABLE_INTR (TIMSK4 = _BV(OCIE4A))
#define TIMER_DISABLE_INTR (TIMSK4 = 0)
#define TIMER_INTR_NAME TIMER4_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR4A = _BV(WGM41); \
TCCR4B = _BV(WGM43) | _BV(CS40); \
ICR4 = pwmval; \
OCR4A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR4A = 0; \
TCCR4B = _BV(WGM42) | _BV(CS40); \
OCR4A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT4 = 0; \
})
#if defined(CORE_OC4A_PIN)
#define TIMER_PWM_PIN CORE_OC4A_PIN
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 6 /* Arduino Mega */
#else
#error "Please add OC4A pin number here\n"
#endif
// defines for timer5 (16 bits)
#elif defined(IR_USE_TIMER5)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR5A |= _BV(COM5A1))
#define TIMER_DISABLE_PWM (TCCR5A &= ~(_BV(COM5A1)))
#define TIMER_ENABLE_INTR (TIMSK5 = _BV(OCIE5A))
#define TIMER_DISABLE_INTR (TIMSK5 = 0)
#define TIMER_INTR_NAME TIMER5_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR5A = _BV(WGM51); \
TCCR5B = _BV(WGM53) | _BV(CS50); \
ICR5 = pwmval; \
OCR5A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR5A = 0; \
TCCR5B = _BV(WGM52) | _BV(CS50); \
OCR5A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT5 = 0; \
})
#if defined(CORE_OC5A_PIN)
#define TIMER_PWM_PIN CORE_OC5A_PIN
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 46 /* Arduino Mega */
#else
#error "Please add OC5A pin number here\n"
#endif
#else // unknown timer
#error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
#endif
// defines for blinking the LED
#if defined(CORE_LED0_PIN)
#define BLINKLED CORE_LED0_PIN
#define BLINKLED_ON() (digitalWrite(CORE_LED0_PIN, HIGH))
#define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW))
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define BLINKLED 13
#define BLINKLED_ON() (PORTB |= B10000000)
#define BLINKLED_OFF() (PORTB &= B01111111)
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define BLINKLED 0
#define BLINKLED_ON() (PORTD |= B00000001)
#define BLINKLED_OFF() (PORTD &= B11111110)
#elif defined(__AVR_ATmega32U4__) && defined(IR_USE_TIMER4_HS)
//Leonardo not teensy. When using Timer4 output is on 13. Therefore disabling blink LED
//You can add an LED elsewhere if you want
#define BLINKLED 1
#define BLINKLED_ON() (digitalWrite(BLINKLED, HIGH))
#define BLINKLED_OFF() (digitalWrite(BLINKLED, LOW))
#else
#define BLINKLED 13
#define BLINKLED_ON() (PORTB |= B00100000)
#define BLINKLED_OFF() (PORTB &= B11011111)
#endif
#endif //IRLibTimer_h
Binary file not shown.
+84
View File
@@ -0,0 +1,84 @@
IRLib – an Arduino library for infrared encoding and decoding
Version 1.32 January 2014
Copyright 2013, 2014 by Chris Young http://cyborg5.com
This library is a major rewrite of IRemote by Ken Shirriff which was covered
by GNU LESSER GENERAL PUBLIC LICENSE which as I read it allows me to make
modified versions. That same license applies to this modified version. See
his original copyright below.
The latest Ken Shirriff code can be found at
https://github.com/shirriff/Arduino-IRremote
My purpose was to reorganize the code to make it easier to add or remove
protocols. As a result I have separated the act of receiving a set of raw timing
codes from the act of decoding them by making them separate classes. That way
the receiving aspect can be more black box and implementers of decoders and
senders can just deal with the decoding of protocols.
Also added provisions to make the classes base classes that could be extended
with new protocols which would not require recompiling of the original library nor
understanding of its detailed contents. Some of the changes were made to reduce
code size such as unnecessary use of long versus bool. Some changes were just my
weird programming style. Also extended debugging information added.
IRremote
Version 0.1 July, 2009
Copyright 2009 Ken Shirriff
For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm
http://arcfn.com
Interrupt code based on NECIRrcv by Joe Knapp
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
****************************************************
The package contains:
IRLib.cpp Code for the library written in object C++
IRLib.h Header file which you will include in your sketch
IRLibMatch.h Match macros used internally. Need not include this unless you implement
your own protocols
iRLibTimer.h Attempts to detect type of Arduino board and allows you to modify which
interrupt timer you will use. Defaults to timer 2 as did the original KS
library. Alternate board and timer information based on a fork of the
original KS library. That for can be found here.
https://github.com/TKJElectronics/Arduino-IRremote
IRLibRData.h Moved irparams structure and related data to this header to facilitate
user created extensions to IRrecvBase.
Note: there is no "IRremoteInt.h" header as in the original library. Those values were
moved elsewhere.
The examples directory contains:
IRanalyze Dumps detailed information about a recent signal. Useful for analyzing
unknown protocols
IRfreq Reports modulation frequency of IR signal. Requires TSMP58000 IR learner
IRhashdecode Demonstrates hash decoder.
IRrecord Recording incoming signal and play it back when a character is sent
through the serial console. By using the console you no longer need
to wire up a pushbutton to run this code.
IRrecvDump Receives a code, attempts to decode it, produces well formatted
output of the results using the new "dump" method.
IRsendDemo Simplistic demo to send a Sony DVD power signal every time a
character is received from the serial monitor.
IRsendJVC Demonstrates sending a code using JVC protocol which is tricky.
IRservo Demonstrates controlling a servo motor using an IR remote
IRserial_remote Demonstrates a Python application that runs on your PC and sends
serial data to Arduino which in turn sends IR remote signals.
Samsung36 Demonstrates how to expand the library without recompiling it.
Also demonstrates how to handle codes that are longer than 32 bits.
DirecTV Demonstrates additional protocol for DirecTV
GIcable Demonstrates additional protocol for GIcable used by Motorola cable boxes
rcmm Additional protocol Phillips RCMM used by AT&T U-Verse boxes
Note: I did not port any of the other demo sketches although I may add IRTest later.
The manuals directory contains:
IRLibReference.docx Reference manual in Microsoft Word format
IRLibReference.pdf Reference manual in Adobe PDF format
Online version of this manual is also available at:
http://tech.cyborg5.com/irlib/docs/
****************************************************
The library handles the following protocols:
NEC, Sony, RC5, RC6, Raw all of which were supported in the KS version.
Additionally added Panasonic_Old, JVC, NECx.
Also added KS hash code routines which he released separately.
Example code included but not in the library: Samsung36, DirecTV, GIcable.
@@ -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();
}
}
Binary file not shown.
Binary file not shown.