Commit 416cc09e authored by Chris Young's avatar Chris Young

Update to version 1.5

Version 1.5 features include: New bit-bang output for PWM frequency no
longer requires hardware timers. New IRfrequency class for detecting
received frequency. Updated documentation. Other changes.
parent e076400e
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.5 June 2014
New bit-bang option for PWM output frequency setting. Now can use any output pin with no hardware timers. Note:bit-bang output not as accurate as timer-based frequency selection.
Major rewrite of IRLibTimer.h to facilitate bit-bang. Separated hardware timer selection and specification into sending and receiving sections in order to implement bit-bang.
New IRfrequency class for detecting input frequencies. Previously was a stand-alone special sketch but now is a class including a DumpResults method.
New IRfreq and IRrecvDumpFreq illustrate simultaneous detection of frequency and pattern with both an IR learner and IR receiver is connected.
New #define USE_IRRECV define can be commented out to completely remove the interrupt driven IRrecv receiver class from the library. This resolves ISR conflicts with other libraries such as Tone() when not using IRrecv class.
New #define USE_DUMP define can be commented out to disable DumpResults methods. Saves code space when these methods are not needed.
Revised user manuals to document new features and correct previous documentation problems.
Version 1.42 May 2014
Added support ATmega256RFR2 based Pinoccio Scout platform with examples
Version 1.41 April 2014
......
/* IRLib.cpp from IRLib - an Arduino library for infrared encoding and decoding
* Version 1.41 April 2014
* Version 1.5 June 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
......@@ -257,6 +257,7 @@ void IRsend::send(IRTYPES Type, unsigned long data, unsigned int data2) {
*/
IRdecodeBase::IRdecodeBase(void) {
rawbuf=(volatile unsigned int*)irparams.rawbuf;
IgnoreHeader=false;
Reset();
};
......@@ -293,15 +294,19 @@ void IRdecodeBase::Reset(void) {
bits=0;
rawlen=0;
};
#ifndef USE_DUMP
void DumpUnavailable(void) {Serial.println(F("DumpResults unavailable"));}
#endif
/*
* This method dumps useful information about the decoded values.
*/
void IRdecodeBase::DumpResults(void) {
#ifdef USE_DUMP
int i;unsigned long Extent;int interval;
if(decode_type<=LAST_PROTOCOL){
Serial.print(F("Decoded ")); Serial.print(Pnames(decode_type));
Serial.print(F(": Value:")); Serial.print(value, HEX);
Serial.print(F("(")); Serial.print(decode_type,DEC);
Serial.print(F("): Value:")); Serial.print(value, HEX);
};
Serial.print(F(" (")); Serial.print(bits, DEC); Serial.println(F(" bits)"));
Serial.print(F("Raw samples(")); Serial.print(rawlen, DEC);
......@@ -333,6 +338,9 @@ void IRdecodeBase::DumpResults(void) {
Serial.print(F("Mark min:")); Serial.print(LowMark,DEC);Serial.print(F("\t max:")); Serial.println(HiMark,DEC);
Serial.print(F("Space min:")); Serial.print(LowSpace,DEC);Serial.print(F("\t max:")); Serial.println(HiSpace,DEC);
Serial.println();
#else
DumpUnavailable();
#endif
}
/*
......@@ -348,7 +356,11 @@ bool IRdecodeBase::decodeGeneric(unsigned char Raw_Count, unsigned int Head_Mark
// Some protocols need to do custom header work.
unsigned long data = 0; unsigned char Max; offset=1;
if (Raw_Count) {if (rawlen != Raw_Count) return RAW_COUNT_ERROR;}
if (Head_Mark) {if (!MATCH(rawbuf[offset],Head_Mark)) return HEADER_MARK_ERROR(Head_Mark);}
if(!IgnoreHeader) {
if (Head_Mark) {
if (!MATCH(rawbuf[offset],Head_Mark)) return HEADER_MARK_ERROR(Head_Mark);
}
}
offset++;
if (Head_Space) {if (!MATCH(rawbuf[offset],Head_Space)) return HEADER_SPACE_ERROR(Head_Space);}
......@@ -474,12 +486,12 @@ bool IRdecodePanasonic_Old::decode(void) {
* Many protocols have such check features in their definition but our code typically doesn't
* perform these checks. For example NEC's least significant 8 bits are the complement of
* of the next more significant 8 bits. While it's probably not necessary to error check this,
* here is some sample code to show you how.
* you can un-comment the next 4 lines of code to do this extra checking.
*/
long S1= (value & 0x0007ff); // 00 0000 0000 0111 1111 1111 //00000 000000 11111 111111
long S2= (value & 0x3ff800)>> 11; // 11 1111 1111 1000 0000 0000 //11111 111111 00000 000000
S2= (~S2) & 0x0007ff;
if (S1!=S2) return IRLIB_REJECTION_MESSAGE(F("inverted bit redundancy"));
// long S1= (value & 0x0007ff); // 00 0000 0000 0111 1111 1111 //00000 000000 11111 111111
// long S2= (value & 0x3ff800)>> 11; // 11 1111 1111 1000 0000 0000 //11111 111111 00000 000000
// S2= (~S2) & 0x0007ff;
// if (S1!=S2) return IRLIB_REJECTION_MESSAGE(F("inverted bit redundancy"));
// Success
decode_type = PANASONIC_OLD;
return true;
......@@ -551,7 +563,10 @@ IRdecodeRC::RCLevel IRdecodeRC::getRClevel(unsigned char *used, const unsigned i
avail = 3;
}
else {
return ERROR;
if((IgnoreHeader) && (offset==1) && (width<t1))
avail =1;
else{
return ERROR;}
}
(*used)++;
if (*used >= avail) {
......@@ -601,7 +616,9 @@ bool IRdecodeRC6::decode(void) {
IRLIB_ATTEMPT_MESSAGE(F("RC6"));
if (rawlen < MIN_RC6_SAMPLES) return RAW_COUNT_ERROR;
// Initial mark
if (!MATCH(rawbuf[1], RC6_HDR_MARK)) return HEADER_MARK_ERROR(RC6_HDR_MARK);
if (!IgnoreHeader) {
if (!MATCH(rawbuf[1], RC6_HDR_MARK)) return HEADER_MARK_ERROR(RC6_HDR_MARK);
}
if (!MATCH(rawbuf[2], RC6_HDR_SPACE)) return HEADER_SPACE_ERROR(RC6_HDR_SPACE);
offset=3;//Skip gap and header
data = 0;
......@@ -760,27 +777,10 @@ bool IRrecvLoop::GetResults(IRdecodeBase *decoder) {
IRrecvPCI::IRrecvPCI(unsigned char inum) {
Init();
switch(intrnum=inum) {
#if defined(__AVR_ATmega32U4__) //Assume Arduino Leonardo
case 0: irparams.recvpin=3; break;
case 1: irparams.recvpin=2; break;
case 2: irparams.recvpin=0; break;
case 3: irparams.recvpin=1; break;
case 4: irparams.recvpin=7; break;
#else //Arduino Uno or Mega
case 0: irparams.recvpin=2; break;
case 1: irparams.recvpin=3; break;
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)//Mega only
case 2: irparams.recvpin=21; break;
case 3: irparams.recvpin=20; break;
case 4: irparams.recvpin=19; break;
case 5: irparams.recvpin=18; break;
#endif
#endif
//Illegal vaalue to flag you that something is wrong
default: irparams.recvpin=255;
intrnum=inum;
irparams.recvpin=Pin_from_Intr(inum);
}
}
void IRrecvPCI_Handler(){
unsigned long volatile ChangeTime=micros();
unsigned long DeltaTime=ChangeTime-irparams.timer;
......@@ -830,8 +830,90 @@ bool IRrecvPCI::GetResults(IRdecodeBase *decoder) {
return true;
};
/* This class facilitates detection of frequency of an IR signal. Requires a TSMP58000
* or equivalent device connected to the hardware interrupt pin.
* Create an instance of the object passing the interrupt number.
*/
volatile unsigned FREQUENCY_BUFFER_TYPE *IRfreqTimes;
volatile unsigned char IRfreqCount;
IRfrequency::IRfrequency(unsigned char inum) { //Note this is interrupt number, not pin number
intrnum=inum;
pin= Pin_from_Intr(inum);
//ISR cannot be passed parameters. If I declare the buffer global it would
//always eat RAN even if this object was not declared. So we make global pointer
//and copy the address to it. ISR still puts data in the object.
IRfreqTimes= & (Time_Stamp[0]);
};
// Note ISR handler cannot be part of a class/object
void IRfreqISR(void) {
IRfreqTimes[IRfreqCount++]=micros();
}
void IRfrequency::enableFreqDetect(void){
attachInterrupt(intrnum,IRfreqISR, FALLING);
for(i=0; i<256; i++) Time_Stamp[i]=0;
IRfreqCount=0;
Results= 0.0;
Samples=0;
};
/* Test to see if we have collected at least one full buffer of data.
* Note values are always zeroed before beginning so any non-zero data
* in the final elements means we have collected at least a buffer full.
* By chance the final might be zero so we test two of them. Would be
* nearly impossible for two consecutive elements to be zero unless
* we had not yet collected data.
*/
bool IRfrequency::HaveData(void) {
return (Time_Stamp[255] || Time_Stamp[254]);
};
void IRfrequency::disableFreqDetect(void){
detachInterrupt(intrnum);
};
void IRfrequency::ComputeFreq(void){
Samples=0; Sum=0;
for(i=1; i<256; i++) {
unsigned char Interval=Time_Stamp[i]-Time_Stamp[i-1];
if(Interval>50 || Interval<10) continue;//ignore extraneous results
Sum+=Interval;//accumulate usable intervals
Samples++; //account usable intervals
};
if(Sum)
Results=(double) Samples/(double)Sum*1000;
else
Results= 0.0;
};
//Didn't need to be a method that we made one following example of IRrecvBase
unsigned char IRfrequency::getPinNum(void) {
return pin;
}
void IRfrequency::DumpResults(bool Detail) {
ComputeFreq();
#ifdef USE_DUMP
Serial.print(F("Number of samples:")); Serial.print(Samples,DEC);
Serial.print(F("\t Total interval (us):")); Serial.println(Sum,DEC);
Serial.print(F("Avg. interval(us):")); Serial.print(1.0*Sum/Samples,2);
Serial.print(F("\t Aprx. Frequency(kHz):")); Serial.print(Results,2);
Serial.print(F(" (")); Serial.print(int(Results+0.5),DEC);
Serial.println(F(")"));
if(Detail) {
for(i=1; i<256; i++) {
unsigned int Interval=Time_Stamp[i]-Time_Stamp[i-1];
Serial.print(Interval,DEC); Serial.print("\t");
if ((i % 4)==0)Serial.print(F("\t "));
if ((i % 8)==0)Serial.println();
if ((i % 32)==0)Serial.println();
}
Serial.println();
}
#else
DumpUnavailable();
#endif
};
/*
......@@ -839,6 +921,30 @@ bool IRrecvPCI::GetResults(IRdecodeBase *decoder) {
* nothing to do with IR protocols. You need not understand this is all you're doing is adding
* new protocols or improving the receiving, decoding and sending of protocols.
*/
//See IRLib.h comment explaining this function
unsigned char Pin_from_Intr(unsigned char inum) {
const unsigned char PROGMEM attach_to_pin[]= {
#if defined(__AVR_ATmega256RFR2__)//Assume Pinoccio Scout
4,5,SCL,SDA,RX1,TX1,7
#elif defined(__AVR_ATmega32U4__) //Assume Arduino Leonardo
3,2,0,1,7
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)//Assume Arduino Mega
2,3, 21, 20, 1, 18
#else //Assume Arduino Uno or other ATmega328
2, 3
#endif
};
#if defined(ARDUINO_SAM_DUE)
return inum;
#endif
if (inum<sizeof attach_to_pin) {//note this works because we know it's one byte per entry
return attach_to_pin[inum];
} else {
return 255;
}
}
// Provides ISR
#include <avr/interrupt.h>
// defines for setting and clearing register bits
......@@ -867,8 +973,10 @@ bool IRrecvPCI::GetResults(IRdecodeBase *decoder) {
* and doesn't turn on your IR LED or any output circuit.
*/
void IRrecvBase::No_Output (void) {
pinMode(TIMER_PWM_PIN, OUTPUT);
digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
#if defined(IR_SEND_PWM_PIN)
pinMode(IR_SEND_PWM_PIN, OUTPUT);
digitalWrite(IR_SEND_PWM_PIN, LOW); // When not sending PWM, we want it low
#endif
}
// enable/disable blinking of pin 13 on IR processing
......@@ -892,7 +1000,7 @@ void do_Blink(void) {
}
}
}
#ifdef USE_IRRECV
/*
* The original IRrecv which uses 50µs timer driven interrupts to sample input pin.
*/
......@@ -906,9 +1014,8 @@ void IRrecv::enableIRIn(void) {
IRrecvBase::enableIRIn();
// setup pulse clock timer interrupt
cli();
TIMER_CONFIG_NORMAL();
TIMER_ENABLE_INTR;
TIMER_RESET;
IR_RECV_CONFIG_TICKS();
IR_RECV_ENABLE_INTR;
sei();
}
......@@ -928,9 +1035,8 @@ bool IRrecv::GetResults(IRdecodeBase *decoder) {
* As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
* As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts.
*/
ISR(TIMER_INTR_NAME)
ISR(IR_RECV_INTR_NAME)
{
TIMER_RESET;
enum irdata_t {IR_MARK=0, IR_SPACE=1};
irdata_t irdata = (irdata_t)digitalRead(irparams.recvpin);
irparams.timer++; // One more 50us tick
......@@ -985,7 +1091,7 @@ ISR(TIMER_INTR_NAME)
}
do_Blink();
}
#endif //end of ifdef USE_IRRECV
/*
* The hardware specific portions of IRsendBase
*/
......@@ -1004,15 +1110,15 @@ void IRsendBase::enableIROut(unsigned char khz) {
// See my Secrets of Arduino PWM at http://www.righto.com/2009/07/secrets-of-arduino-pwm.html for details.
// Disable the Timer2 Interrupt (which is used for receiving IR)
TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(TIMER_PWM_PIN, OUTPUT);
digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
TIMER_CONFIG_KHZ(khz);
IR_RECV_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(IR_SEND_PWM_PIN, OUTPUT);
digitalWrite(IR_SEND_PWM_PIN, LOW); // When not sending PWM, we want it low
IR_SEND_CONFIG_KHZ(khz);
}
IRsendBase::IRsendBase () {
pinMode(TIMER_PWM_PIN, OUTPUT);
digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
pinMode(IR_SEND_PWM_PIN, OUTPUT);
digitalWrite(IR_SEND_PWM_PIN, LOW); // When not sending PWM, we want it low
}
//The Arduino built in function delayMicroseconds has limits we wish to exceed
......@@ -1022,13 +1128,13 @@ void My_delay_uSecs(unsigned int T) {
}
void IRsendBase::mark(unsigned int time) {
TIMER_ENABLE_PWM;
My_delay_uSecs(time);
IR_SEND_PWM_START;
IR_SEND_MARK_TIME(time);
Extent+=time;
}
void IRsendBase::space(unsigned int time) {
TIMER_DISABLE_PWM;
IR_SEND_PWM_STOP;
My_delay_uSecs(time);
Extent+=time;
}
......
/* IRLib.h from IRLib an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Version 1.5 June 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
......@@ -36,9 +36,19 @@
// 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_TRACE
// #define IRLIB_TEST
/* If not using the IRrecv class but only using IRrecvPCI or IRrecvLoop you can eliminate
* some conflicts with the duplicate definition of ISR by turning this feature off.
* Comment out the following define to eliminate the conflicts.
*/
#define USE_IRRECV
/* If not using either DumpResults methods of IRdecode nor IRfrequency you can
* comment out the following define to eliminate considerable program space.
*/
#define USE_DUMP
// Only used for testing; can remove virtual for shorter code
#ifdef IRLIB_TEST
#define VIRTUAL virtual
......@@ -73,6 +83,7 @@ public:
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.
bool IgnoreHeader; // Relaxed header detection allows AGC to settle
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,
......@@ -176,6 +187,7 @@ protected:
VIRTUAL void mark(unsigned int usec);
VIRTUAL void space(unsigned int usec);
unsigned long Extent;
unsigned char OnTime,OffTime,iLength;//used by bit-bang output.
};
class IRsendNEC: public virtual IRsendBase
......@@ -264,6 +276,7 @@ protected:
* when trying to analyze unknown protocols, the 50s granularity may not be sufficient.
* In that case use either the IRrecvLoop or the IRrecvPCI class.
*/
#ifdef USE_IRRECV
class IRrecv: public IRrecvBase
{
public:
......@@ -272,6 +285,7 @@ public:
void enableIRIn(void);
void resume(void);
};
#endif
/* 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
......@@ -309,12 +323,46 @@ private:
unsigned char intrnum;
};
/* This class facilitates detection of frequency of an IR signal. Requires a TSMP58000
* or equivalent device connected to the hardware interrupt pin.
* Create an instance of the object passing the interrupt number.
*/
//Un-comment only one of the following three lines depending on available RAM
//#define FREQUENCY_BUFFER_TYPE unsigned char
#define FREQUENCY_BUFFER_TYPE int
//#define FREQUENCY_BUFFER_TYPE long
class IRfrequency
{
public:
//Note this is interrupt number, not pin number
IRfrequency(unsigned char inum);
void enableFreqDetect(void);
bool HaveData(void); //detective data received
void disableFreqDetect(void);
void ComputeFreq(void); //computes but does not print results
void DumpResults(bool Detail); //computes and prints result
unsigned char getPinNum(void);//get value computed from interrupt number
double Results; //results in kHz
unsigned char Samples; //number of samples used in computation
private:
volatile unsigned FREQUENCY_BUFFER_TYPE Time_Stamp[256];
unsigned char intrnum, pin;
unsigned int i;
unsigned long Sum;
};
//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);
/* This routine maps interrupt numbers used by attachInterrupt() into pin numbers.
* NOTE: these interrupt numbers which are passed to attachInterrupt() are not
* necessarily identical to the interrupt numbers in the datasheet of the processor
* chip you are using. These interrupt numbers are a system unique to the
* attachInterrupt() Arduino function. It is used by both IRrecvPCI and IRfrequency.
*/
unsigned char Pin_from_Intr(unsigned char inum);
// Some useful constants
// Decoded value for NEC when a repeat code is received
#define REPEAT 0xffffffff
......
/* IRLibMatch.h from IRLib an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Version 1.5 June 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
......@@ -51,8 +51,8 @@
#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
* These revised MATCH routines allow you to use either percentage or absolute tolerances.
* Use ABS_MATCH for absolute and PERC_MATCH for percentages. The original MATCH macro
* is controlled by the IRLIB_USE_PERCENT definition a few lines above.
*/
......
/* IRLibRData.h from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.4 March 2014
* Version 1.5 June 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
......
/* IRLibTimer.h from IRLib – an Arduino library for infrared encoding and decoding
* Version 1.42 May 2014
* Version 1.5 June 2014
* Copyright 2014 by Chris Young http://cyborg5.com
*
* This library is a major rewrite of IRemote by Ken Shirriff which was covered by
......@@ -34,6 +34,11 @@
* This information came from an alternative fork of the original Ken Shirriff library found here
* https://github.com/TKJElectronics/Arduino-IRremote
*/
/* This file has been significantly reconfigured for version 1.5 and greater. It now
* allows you use a different timer for input versus output. This also allows you to
* use no timers whatsoever by using the IRrecvPCI or IRrecvLoop for input and
* bit-bang routines for output. Note the various "Teensy" sections have not been tested.
*/
#ifndef IRLibTimer_h
#define IRLibTimer_h
......@@ -42,272 +47,280 @@
#else
#include "WProgram.h"
#endif
// Arduino Mega
/* In this section reattempt to detect your hardware type and give you the choice of
* various hardware timers to change the PWM frequency for output. In each hardware
* section below you should un-comment only one of the choices. The defines also
* specify the output pin number. DO NOT change the pin number unless you're using
* nonstandard hardware that would require you to do so. If you wish to use the
* bit-bang PWM output will specify that AFTER this section as an override.
*/
/* 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
//#define IR_SEND_TIMER1 11
#define IR_SEND_TIMER2 9
//#define IR_SEND_TIMER3 5
//#define IR_SEND_TIMER4 6
//#define IR_SEND_TIMER5 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.
#define IR_SEND_TIMER1 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
#ifdef CORE_TEENSY
// it's Teensy 2.0
//#define IR_SEND_TIMER1 14
//#define IR_SEND_TIMER3 9
#define IR_SEND_TIMER4_HS 10
#else
/* it's probably Leonardo */
#define IR_SEND_TIMER1 9
//#define IR_SEND_TIMER3 5
//#define IR_SEND_TIMER4_HS 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
//#define IR_SEND_TIMER1 25
#define IR_SEND_TIMER2 1
//#define IR_SEND_TIMER3 16
/* Sanguino */
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
//#define IR_USE_TIMER1 // tx = pin 13
#define IR_USE_TIMER2 // tx = pin 14
// Pinoccio Scout
//#define IR_SEND_TIMER1 13
#define IR_SEND_TIMER2 14
/* Pinoccio Scout */
#elif defined(__AVR_ATmega256RFR2__)
#define IS_PINOCCIO
#define IR_USE_TIMER3 // tx = pin D3
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#define IR_SEND_TIMER3 3
/* Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc */
#else
//#define IR_USE_TIMER1 // tx = pin 9
#define IR_USE_TIMER2 // tx = pin 3
#endif
//#define IR_SEND_TIMER1 9
#define IR_SEND_TIMER2 3
#endif //end of setting IR_SEND_TIMER based on hardware detection
/* If you want to use bit-bang PWM output, you should un-comment the line below.
* The definition must include the pin number for bit-bang output. This could be any
* available digital output pin. It need not be a designated PWM pin.
* NOTE: By un-commenting this line, you are forcing the library to ignore
* hardware detection and timer specifications above. The bit-bang frequency
* code is not as accurate as using a hardware timer but it is more flexible and
* less hardware platform dependent.
*/
//#define IR_SEND_BIT_BANG 3 //Be sure to set this pin number if you un-comment
/* This is a fudge factor that adjusts bit-bang timing. Feel free to experiment
* for best results.*/
#define IR_BIT_BANG_OVERHEAD 10
/* We are going to presume that you want to use the same hardware timer to control
* the 50 microsecond interrupt used by the IRrecv receiver class as was specified
* above in the hardware detection section for sending. Even if you specified bit-bang
* for sending, the definitions above have selected a default sending timer for you based
* on hardware detection. if that is correct, then do nothing below. However if you do
* wish to specify an IR_RECV_TIMER different than the IR_SEND_TIMER selected by the code
* above, then you should un-comment the IR_RECV_TIMER_OVERRIDE and also un-comment one
* and only one of the following IR_RECV_TIMERx lines below that.
* NOTE: You are responsible for ensuring that the timer you are specifying is
* available on your hardware. You should only choose timers which are shown as available
* for your hardware platform as shown in the defines in the IR_SEND_TIMER section above.
*/
//#define IR_RECV_TIMER_OVERRIDE
//#define IR_RECV_TIMER1
//#define IR_RECV_TIMER2
//#define IR_RECV_TIMER3
//#define IR_RECV_TIMER4
//#define IR_RECV_TIMER4_HS
//#define IR_RECV_TIMER5
// 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 */
/* Everything below this point is a computation based on user settings above.
* In all likelihood you would never need to modify anything below this point
* unless you are adding some completely new feature or seriously modifying
* the behavior of existing features. In other words don't try this at home.
*/
#if !defined(IR_RECV_TIMER_OVERRIDE)
#if defined(IR_SEND_TIMER1)
#define IR_RECV_TIMER1
#elif defined(IR_SEND_TIMER2)
#define IR_RECV_TIMER2
#elif defined(IR_SEND_TIMER3)
#define IR_RECV_TIMER3
#elif defined(IR_SEND_TIMER4)
#define IR_RECV_TIMER4
#elif defined(IR_SEND_TIMER4_HS)
#define IR_RECV_TIMER4_HS
#elif defined(IR_SEND_TIMER5)
#define IR_RECV_TIMER5
#else
#error "Unable to set IR_RECV_TIMER"
#endif
#endif
#if defined(IR_SEND_BIT_BANG) //defines for bit-bang output
#define IR_SEND_PWM_PIN IR_SEND_BIT_BANG
#define IR_SEND_PWM_START unsigned int jmax=time/iLength;\
for(unsigned int j=0;j<jmax;j++) {\
digitalWrite(IR_SEND_BIT_BANG, HIGH); delayMicroseconds(OnTime);\
digitalWrite(IR_SEND_BIT_BANG, LOW); delayMicroseconds(OffTime);}
#define IR_SEND_MARK_TIME(time)
#define IR_SEND_PWM_STOP
#define IR_SEND_CONFIG_KHZ(val) float Length=1000.0/(float)khz;\
iLength=int(Length+0.5); OnTime=int(Length/3.0); \
OffTime=iLength-OnTime-IR_BIT_BANG_OVERHEAD-(val<40);
// 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
#elif defined(IR_SEND_TIMER1) // defines for timer1 (16 bits)
#define IR_SEND_PWM_START (TCCR1A |= _BV(COM1A1))
#define IR_SEND_MARK_TIME(time) My_delay_uSecs(time)
#define IR_SEND_PWM_STOP (TCCR1A &= ~(_BV(COM1A1)))
#define IR_SEND_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR1A = _BV(WGM11); TCCR1B = _BV(WGM13) | _BV(CS10); \
ICR1 = pwmval; OCR1A = pwmval / 3; })
#if defined(CORE_OC1A_PIN)
#define IR_SEND_PWM_PIN CORE_OC1A_PIN /* Teensy */
#else
#define IR_SEND_PWM_PIN IR_SEND_TIMER1
#endif
#elif defined(IR_SEND_TIMER2) // defines for timer2 (8 bits)
#define IR_SEND_PWM_START (TCCR2A |= _BV(COM2B1))
#define IR_SEND_MARK_TIME(time) My_delay_uSecs(time)
#define IR_SEND_PWM_STOP (TCCR2A &= ~(_BV(COM2B1)))
#define IR_SEND_CONFIG_KHZ(val) ({ \
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR2A = _BV(WGM20); TCCR2B = _BV(WGM22) | _BV(CS20); \