Hallo
This commit is contained in:
		
							
								
								
									
										198
									
								
								IRremote/IRremote.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								IRremote/IRremote.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,198 @@
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
// IRremote
 | 
			
		||||
// Version 2.0.1 June, 2015
 | 
			
		||||
// Copyright 2009 Ken Shirriff
 | 
			
		||||
// For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
 | 
			
		||||
//
 | 
			
		||||
// Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
 | 
			
		||||
// Modified  by Mitra Ardron <mitra@mitra.biz>
 | 
			
		||||
// Added Sanyo and Mitsubishi controllers
 | 
			
		||||
// Modified Sony to spot the repeat codes that some Sony's send
 | 
			
		||||
//
 | 
			
		||||
// 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/
 | 
			
		||||
//
 | 
			
		||||
// JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 | 
			
		||||
// LG added by Darryl Smith (based on the JVC protocol)
 | 
			
		||||
// Whynter A/C ARC-110WD added by Francesco Meschia
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
// Defining IR_GLOBAL here allows us to declare the instantiation of global variables
 | 
			
		||||
#define IR_GLOBAL
 | 
			
		||||
#	include "IRremote.h"
 | 
			
		||||
#	include "IRremoteInt.h"
 | 
			
		||||
#undef IR_GLOBAL
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_AVR_INTERRUPT_H
 | 
			
		||||
#include <avr/interrupt.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// The match functions were (apparently) originally MACROs to improve code speed
 | 
			
		||||
//   (although this would have bloated the code) hence the names being CAPS
 | 
			
		||||
// A later release implemented debug output and so they needed to be converted
 | 
			
		||||
//   to functions.
 | 
			
		||||
// I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some
 | 
			
		||||
//   reason, no matter what I did I could not get them to function as macros again.
 | 
			
		||||
// I have found a *lot* of bugs in the Arduino compiler over the last few weeks,
 | 
			
		||||
//   and I am currently assuming that one of these bugs is my problem.
 | 
			
		||||
// I may revisit this code at a later date and look at the assembler produced
 | 
			
		||||
//   in a hope of finding out what is going on, but for now they will remain as
 | 
			
		||||
//   functions even in non-DEBUG mode
 | 
			
		||||
//
 | 
			
		||||
int  MATCH (int measured,  int desired)
 | 
			
		||||
{
 | 
			
		||||
 	DBG_PRINT(F("Testing: "));
 | 
			
		||||
 	DBG_PRINT(TICKS_LOW(desired), DEC);
 | 
			
		||||
 	DBG_PRINT(F(" <= "));
 | 
			
		||||
 	DBG_PRINT(measured, DEC);
 | 
			
		||||
 	DBG_PRINT(F(" <= "));
 | 
			
		||||
 	DBG_PRINT(TICKS_HIGH(desired), DEC);
 | 
			
		||||
 | 
			
		||||
  bool passed = ((measured >= TICKS_LOW(desired)) && (measured <= TICKS_HIGH(desired)));
 | 
			
		||||
  if (passed)
 | 
			
		||||
    DBG_PRINTLN(F("?; passed"));
 | 
			
		||||
  else
 | 
			
		||||
    DBG_PRINTLN(F("?; FAILED")); 
 | 
			
		||||
 	return passed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+========================================================
 | 
			
		||||
// Due to sensor lag, when received, Marks tend to be 100us too long
 | 
			
		||||
//
 | 
			
		||||
int  MATCH_MARK (int measured_ticks,  int desired_us)
 | 
			
		||||
{
 | 
			
		||||
	DBG_PRINT(F("Testing mark (actual vs desired): "));
 | 
			
		||||
	DBG_PRINT(measured_ticks * USECPERTICK, DEC);
 | 
			
		||||
	DBG_PRINT(F("us vs "));
 | 
			
		||||
	DBG_PRINT(desired_us, DEC);
 | 
			
		||||
	DBG_PRINT("us"); 
 | 
			
		||||
	DBG_PRINT(": ");
 | 
			
		||||
	DBG_PRINT(TICKS_LOW(desired_us + MARK_EXCESS) * USECPERTICK, DEC);
 | 
			
		||||
	DBG_PRINT(F(" <= "));
 | 
			
		||||
	DBG_PRINT(measured_ticks * USECPERTICK, DEC);
 | 
			
		||||
	DBG_PRINT(F(" <= "));
 | 
			
		||||
	DBG_PRINT(TICKS_HIGH(desired_us + MARK_EXCESS) * USECPERTICK, DEC);
 | 
			
		||||
 | 
			
		||||
  bool passed = ((measured_ticks >= TICKS_LOW (desired_us + MARK_EXCESS))
 | 
			
		||||
                && (measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS)));
 | 
			
		||||
  if (passed)
 | 
			
		||||
    DBG_PRINTLN(F("?; passed"));
 | 
			
		||||
  else
 | 
			
		||||
    DBG_PRINTLN(F("?; FAILED")); 
 | 
			
		||||
 	return passed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+========================================================
 | 
			
		||||
// Due to sensor lag, when received, Spaces tend to be 100us too short
 | 
			
		||||
//
 | 
			
		||||
int  MATCH_SPACE (int measured_ticks,  int desired_us)
 | 
			
		||||
{
 | 
			
		||||
	DBG_PRINT(F("Testing space (actual vs desired): "));
 | 
			
		||||
	DBG_PRINT(measured_ticks * USECPERTICK, DEC);
 | 
			
		||||
	DBG_PRINT(F("us vs "));
 | 
			
		||||
	DBG_PRINT(desired_us, DEC);
 | 
			
		||||
	DBG_PRINT("us"); 
 | 
			
		||||
	DBG_PRINT(": ");
 | 
			
		||||
	DBG_PRINT(TICKS_LOW(desired_us - MARK_EXCESS) * USECPERTICK, DEC);
 | 
			
		||||
	DBG_PRINT(F(" <= "));
 | 
			
		||||
	DBG_PRINT(measured_ticks * USECPERTICK, DEC);
 | 
			
		||||
	DBG_PRINT(F(" <= "));
 | 
			
		||||
	DBG_PRINT(TICKS_HIGH(desired_us - MARK_EXCESS) * USECPERTICK, DEC);
 | 
			
		||||
 | 
			
		||||
  bool passed = ((measured_ticks >= TICKS_LOW (desired_us - MARK_EXCESS))
 | 
			
		||||
                && (measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS)));
 | 
			
		||||
  if (passed)
 | 
			
		||||
    DBG_PRINTLN(F("?; passed"));
 | 
			
		||||
  else
 | 
			
		||||
    DBG_PRINTLN(F("?; FAILED")); 
 | 
			
		||||
 	return passed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Interrupt Service Routine - Fires every 50uS
 | 
			
		||||
// TIMER2 interrupt code to collect raw data.
 | 
			
		||||
// Widths of alternating SPACE, MARK are recorded in rawbuf.
 | 
			
		||||
// Recorded in ticks of 50uS [microseconds, 0.000050 seconds]
 | 
			
		||||
// 'rawlen' counts the number of entries recorded so far.
 | 
			
		||||
// First entry is the SPACE between transmissions.
 | 
			
		||||
// As soon as a the first [SPACE] entry 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; New logging starts
 | 
			
		||||
//
 | 
			
		||||
ISR (TIMER_INTR_NAME)
 | 
			
		||||
{
 | 
			
		||||
	TIMER_RESET;
 | 
			
		||||
 | 
			
		||||
	// Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
 | 
			
		||||
	// digitalRead() is very slow. Optimisation is possible, but makes the code unportable
 | 
			
		||||
	uint8_t  irdata = (uint8_t)digitalRead(irparams.recvpin);
 | 
			
		||||
 | 
			
		||||
	irparams.timer++;  // One more 50uS tick
 | 
			
		||||
	if (irparams.rawlen >= RAWBUF)  irparams.rcvstate = STATE_OVERFLOW ;  // Buffer overflow
 | 
			
		||||
 | 
			
		||||
	switch(irparams.rcvstate) {
 | 
			
		||||
		//......................................................................
 | 
			
		||||
		case STATE_IDLE: // In the middle of a gap
 | 
			
		||||
			if (irdata == MARK) {
 | 
			
		||||
				if (irparams.timer < GAP_TICKS)  {  // Not big enough to be a gap.
 | 
			
		||||
					irparams.timer = 0;
 | 
			
		||||
 | 
			
		||||
				} else {
 | 
			
		||||
					// Gap just ended; Record duration; Start recording transmission
 | 
			
		||||
					irparams.overflow                  = false;
 | 
			
		||||
					irparams.rawlen                    = 0;
 | 
			
		||||
					irparams.rawbuf[irparams.rawlen++] = irparams.timer;
 | 
			
		||||
					irparams.timer                     = 0;
 | 
			
		||||
					irparams.rcvstate                  = STATE_MARK;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		//......................................................................
 | 
			
		||||
		case STATE_MARK:  // Timing Mark
 | 
			
		||||
			if (irdata == SPACE) {   // Mark ended; Record time
 | 
			
		||||
				irparams.rawbuf[irparams.rawlen++] = irparams.timer;
 | 
			
		||||
				irparams.timer                     = 0;
 | 
			
		||||
				irparams.rcvstate                  = STATE_SPACE;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		//......................................................................
 | 
			
		||||
		case STATE_SPACE:  // Timing Space
 | 
			
		||||
			if (irdata == MARK) {  // Space just ended; Record time
 | 
			
		||||
				irparams.rawbuf[irparams.rawlen++] = irparams.timer;
 | 
			
		||||
				irparams.timer                     = 0;
 | 
			
		||||
				irparams.rcvstate                  = STATE_MARK;
 | 
			
		||||
 | 
			
		||||
			} else if (irparams.timer > GAP_TICKS) {  // Space
 | 
			
		||||
					// A long Space, indicates gap between codes
 | 
			
		||||
					// Flag the current code as ready for processing
 | 
			
		||||
					// Switch to STOP
 | 
			
		||||
					// Don't reset timer; keep counting Space width
 | 
			
		||||
					irparams.rcvstate = STATE_STOP;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		//......................................................................
 | 
			
		||||
		case STATE_STOP:  // Waiting; Measuring Gap
 | 
			
		||||
		 	if (irdata == MARK)  irparams.timer = 0 ;  // Reset gap timer
 | 
			
		||||
		 	break;
 | 
			
		||||
		//......................................................................
 | 
			
		||||
		case STATE_OVERFLOW:  // Flag up a read overflow; Stop the State Machine
 | 
			
		||||
			irparams.overflow = true;
 | 
			
		||||
			irparams.rcvstate = STATE_STOP;
 | 
			
		||||
		 	break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef BLINKLED
 | 
			
		||||
	// If requested, flash LED while receiving IR data
 | 
			
		||||
	if (irparams.blinkflag) {
 | 
			
		||||
		if (irdata == MARK)
 | 
			
		||||
			if (irparams.blinkpin) digitalWrite(irparams.blinkpin, HIGH); // Turn user defined pin LED on
 | 
			
		||||
				else BLINKLED_ON() ;   // if no user defined LED pin, turn default LED pin for the hardware on
 | 
			
		||||
		else if (irparams.blinkpin) digitalWrite(irparams.blinkpin, LOW); // Turn user defined pin LED on
 | 
			
		||||
				else BLINKLED_OFF() ;   // if no user defined LED pin, turn default LED pin for the hardware on
 | 
			
		||||
	}
 | 
			
		||||
#endif // BLINKLED
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										371
									
								
								IRremote/IRremote.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								IRremote/IRremote.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,371 @@
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
// IRremote
 | 
			
		||||
// Version 2.0.1 June, 2015
 | 
			
		||||
// Copyright 2009 Ken Shirriff
 | 
			
		||||
// For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
 | 
			
		||||
// Edited by Mitra to add new controller SANYO
 | 
			
		||||
//
 | 
			
		||||
// 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/
 | 
			
		||||
//
 | 
			
		||||
// JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 | 
			
		||||
// LG added by Darryl Smith (based on the JVC protocol)
 | 
			
		||||
// Whynter A/C ARC-110WD added by Francesco Meschia
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
#ifndef IRremote_h
 | 
			
		||||
#define IRremote_h
 | 
			
		||||
 | 
			
		||||
#define VERSION_IRREMOTE "2.4.0"
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// The ISR header contains several useful macros the user may wish to use
 | 
			
		||||
//
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Supported IR protocols
 | 
			
		||||
// Each protocol you include costs memory and, during decode, costs time
 | 
			
		||||
// Disable (set to 0) all the protocols you do not need/want!
 | 
			
		||||
//
 | 
			
		||||
#define DECODE_RC5           1
 | 
			
		||||
#define SEND_RC5             1
 | 
			
		||||
 | 
			
		||||
#define DECODE_RC6           1
 | 
			
		||||
#define SEND_RC6             1
 | 
			
		||||
 | 
			
		||||
#define DECODE_NEC           1
 | 
			
		||||
#define SEND_NEC             1
 | 
			
		||||
 | 
			
		||||
#define DECODE_SONY          1
 | 
			
		||||
#define SEND_SONY            1
 | 
			
		||||
 | 
			
		||||
#define DECODE_PANASONIC     1
 | 
			
		||||
#define SEND_PANASONIC       1
 | 
			
		||||
 | 
			
		||||
#define DECODE_JVC           1
 | 
			
		||||
#define SEND_JVC             1
 | 
			
		||||
 | 
			
		||||
#define DECODE_SAMSUNG       1
 | 
			
		||||
#define SEND_SAMSUNG         1
 | 
			
		||||
 | 
			
		||||
#define DECODE_WHYNTER       1
 | 
			
		||||
#define SEND_WHYNTER         1
 | 
			
		||||
 | 
			
		||||
#define DECODE_AIWA_RC_T501  1
 | 
			
		||||
#define SEND_AIWA_RC_T501    1
 | 
			
		||||
 | 
			
		||||
#define DECODE_LG            1
 | 
			
		||||
#define SEND_LG              1
 | 
			
		||||
 | 
			
		||||
#define DECODE_SANYO         1
 | 
			
		||||
#define SEND_SANYO           0 // NOT WRITTEN
 | 
			
		||||
 | 
			
		||||
#define DECODE_MITSUBISHI    1
 | 
			
		||||
#define SEND_MITSUBISHI      0 // NOT WRITTEN
 | 
			
		||||
 | 
			
		||||
#define DECODE_DISH          0 // NOT WRITTEN
 | 
			
		||||
#define SEND_DISH            1
 | 
			
		||||
 | 
			
		||||
#define DECODE_SHARP         0 // NOT WRITTEN
 | 
			
		||||
#define SEND_SHARP           1
 | 
			
		||||
 | 
			
		||||
#define DECODE_DENON         1
 | 
			
		||||
#define SEND_DENON           1
 | 
			
		||||
 | 
			
		||||
#define DECODE_PRONTO        0 // This function doe not logically make sense
 | 
			
		||||
#define SEND_PRONTO          1
 | 
			
		||||
 | 
			
		||||
#define DECODE_LEGO_PF       0 // NOT WRITTEN
 | 
			
		||||
#define SEND_LEGO_PF         1
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// When sending a Pronto code we request to send either the "once" code
 | 
			
		||||
//                                                   or the "repeat" code
 | 
			
		||||
// If the code requested does not exist we can request to fallback on the
 | 
			
		||||
// other code (the one we did not explicitly request)
 | 
			
		||||
//
 | 
			
		||||
// I would suggest that "fallback" will be the standard calling method
 | 
			
		||||
// The last paragraph on this page discusses the rationale of this idea:
 | 
			
		||||
//   http://www.remotecentral.com/features/irdisp2.htm
 | 
			
		||||
//
 | 
			
		||||
#define PRONTO_ONCE        false
 | 
			
		||||
#define PRONTO_REPEAT      true
 | 
			
		||||
#define PRONTO_FALLBACK    true
 | 
			
		||||
#define PRONTO_NOFALLBACK  false
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// An enumerated list of all supported formats
 | 
			
		||||
// You do NOT need to remove entries from this list when disabling protocols!
 | 
			
		||||
//
 | 
			
		||||
typedef
 | 
			
		||||
	enum {
 | 
			
		||||
		UNKNOWN      = -1,
 | 
			
		||||
		UNUSED       =  0,
 | 
			
		||||
		RC5,
 | 
			
		||||
		RC6,
 | 
			
		||||
		NEC,
 | 
			
		||||
		SONY,
 | 
			
		||||
		PANASONIC,
 | 
			
		||||
		JVC,
 | 
			
		||||
		SAMSUNG,
 | 
			
		||||
		WHYNTER,
 | 
			
		||||
		AIWA_RC_T501,
 | 
			
		||||
		LG,
 | 
			
		||||
		SANYO,
 | 
			
		||||
		MITSUBISHI,
 | 
			
		||||
		DISH,
 | 
			
		||||
		SHARP,
 | 
			
		||||
		DENON,
 | 
			
		||||
		PRONTO,
 | 
			
		||||
		LEGO_PF,
 | 
			
		||||
	}
 | 
			
		||||
decode_type_t;
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Set DEBUG to 1 for lots of lovely debug output
 | 
			
		||||
//
 | 
			
		||||
#define DEBUG  0
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Debug directives
 | 
			
		||||
//
 | 
			
		||||
#if DEBUG
 | 
			
		||||
#	define DBG_PRINT(...)    Serial.print(__VA_ARGS__)
 | 
			
		||||
#	define DBG_PRINTLN(...)  Serial.println(__VA_ARGS__)
 | 
			
		||||
#else
 | 
			
		||||
#	define DBG_PRINT(...)
 | 
			
		||||
#	define DBG_PRINTLN(...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Mark & Space matching functions
 | 
			
		||||
//
 | 
			
		||||
int  MATCH       (int measured, int desired) ;
 | 
			
		||||
int  MATCH_MARK  (int measured_ticks, int desired_us) ;
 | 
			
		||||
int  MATCH_SPACE (int measured_ticks, int desired_us) ;
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Results returned from the decoder
 | 
			
		||||
//
 | 
			
		||||
class decode_results
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
		decode_type_t          decode_type;  // UNKNOWN, NEC, SONY, RC5, ...
 | 
			
		||||
		unsigned int           address;      // Used by Panasonic & Sharp [16-bits]
 | 
			
		||||
		unsigned long          value;        // Decoded value [max 32-bits]
 | 
			
		||||
		int                    bits;         // Number of bits in decoded value
 | 
			
		||||
		volatile unsigned int  *rawbuf;      // Raw intervals in 50uS ticks
 | 
			
		||||
		int                    rawlen;       // Number of records in rawbuf
 | 
			
		||||
		int                    overflow;     // true iff IR raw code too long
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Decoded value for NEC when a repeat code is received
 | 
			
		||||
//
 | 
			
		||||
#define REPEAT 0xFFFFFFFF
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Main class for receiving IR
 | 
			
		||||
//
 | 
			
		||||
class IRrecv
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
		IRrecv (int recvpin) ;
 | 
			
		||||
		IRrecv (int recvpin, int blinkpin);
 | 
			
		||||
 | 
			
		||||
		void  blink13    (int blinkflag) ;
 | 
			
		||||
		int   decode     (decode_results *results) ;
 | 
			
		||||
		void  enableIRIn ( ) ;
 | 
			
		||||
		bool  isIdle     ( ) ;
 | 
			
		||||
		void  resume     ( ) ;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		long  decodeHash (decode_results *results) ;
 | 
			
		||||
		int   compare    (unsigned int oldval, unsigned int newval) ;
 | 
			
		||||
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if (DECODE_RC5 || DECODE_RC6)
 | 
			
		||||
			// This helper function is shared by RC5 and RC6
 | 
			
		||||
			int  getRClevel (decode_results *results,  int *offset,  int *used,  int t1) ;
 | 
			
		||||
#		endif
 | 
			
		||||
#		if DECODE_RC5
 | 
			
		||||
			bool  decodeRC5        (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
#		if DECODE_RC6
 | 
			
		||||
			bool  decodeRC6        (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_NEC
 | 
			
		||||
			bool  decodeNEC        (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_SONY
 | 
			
		||||
			bool  decodeSony       (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_PANASONIC
 | 
			
		||||
			bool  decodePanasonic  (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_JVC
 | 
			
		||||
			bool  decodeJVC        (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_SAMSUNG
 | 
			
		||||
			bool  decodeSAMSUNG    (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_WHYNTER
 | 
			
		||||
			bool  decodeWhynter    (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_AIWA_RC_T501
 | 
			
		||||
			bool  decodeAiwaRCT501 (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_LG
 | 
			
		||||
			bool  decodeLG         (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_SANYO
 | 
			
		||||
			bool  decodeSanyo      (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_MITSUBISHI
 | 
			
		||||
			bool  decodeMitsubishi (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_DISH
 | 
			
		||||
			bool  decodeDish (decode_results *results) ; // NOT WRITTEN
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_SHARP
 | 
			
		||||
			bool  decodeSharp (decode_results *results) ; // NOT WRITTEN
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if DECODE_DENON
 | 
			
		||||
			bool  decodeDenon (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
//......................................................................
 | 
			
		||||
#		if DECODE_LEGO_PF
 | 
			
		||||
			bool  decodeLegoPowerFunctions (decode_results *results) ;
 | 
			
		||||
#		endif
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Main class for sending IR
 | 
			
		||||
//
 | 
			
		||||
class IRsend
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
#ifdef USE_SOFT_CARRIER
 | 
			
		||||
 | 
			
		||||
		IRsend(int pin = SEND_PIN)
 | 
			
		||||
		{
 | 
			
		||||
			sendPin = pin;
 | 
			
		||||
		}
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
		IRsend()
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		void  custom_delay_usec (unsigned long uSecs);
 | 
			
		||||
		void  enableIROut 		(int khz) ;
 | 
			
		||||
		void  mark        		(unsigned int usec) ;
 | 
			
		||||
		void  space       		(unsigned int usec) ;
 | 
			
		||||
		void  sendRaw     		(const unsigned int buf[],  unsigned int len,  unsigned int hz) ;
 | 
			
		||||
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_RC5
 | 
			
		||||
			void  sendRC5        (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
#		if SEND_RC6
 | 
			
		||||
			void  sendRC6        (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_NEC
 | 
			
		||||
			void  sendNEC        (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_SONY
 | 
			
		||||
			void  sendSony       (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_PANASONIC
 | 
			
		||||
			void  sendPanasonic  (unsigned int address,  unsigned long data) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_JVC
 | 
			
		||||
			// JVC does NOT repeat by sending a separate code (like NEC does).
 | 
			
		||||
			// The JVC protocol repeats by skipping the header.
 | 
			
		||||
			// To send a JVC repeat signal, send the original code value
 | 
			
		||||
			//   and set 'repeat' to true
 | 
			
		||||
			void  sendJVC        (unsigned long data,  int nbits,  bool repeat) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_SAMSUNG
 | 
			
		||||
			void  sendSAMSUNG    (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_WHYNTER
 | 
			
		||||
			void  sendWhynter    (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_AIWA_RC_T501
 | 
			
		||||
			void  sendAiwaRCT501 (int code) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_LG
 | 
			
		||||
			void  sendLG         (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_SANYO
 | 
			
		||||
			void  sendSanyo      ( ) ; // NOT WRITTEN
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_MISUBISHI
 | 
			
		||||
			void  sendMitsubishi ( ) ; // NOT WRITTEN
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_DISH
 | 
			
		||||
			void  sendDISH       (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_SHARP
 | 
			
		||||
			void  sendSharpRaw   (unsigned long data,  int nbits) ;
 | 
			
		||||
			void  sendSharp      (unsigned int address,  unsigned int command) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_DENON
 | 
			
		||||
			void  sendDenon      (unsigned long data,  int nbits) ;
 | 
			
		||||
#		endif
 | 
			
		||||
		//......................................................................
 | 
			
		||||
#		if SEND_PRONTO
 | 
			
		||||
			void  sendPronto     (char* code,  bool repeat,  bool fallback) ;
 | 
			
		||||
#		endif
 | 
			
		||||
//......................................................................
 | 
			
		||||
#		if SEND_LEGO_PF
 | 
			
		||||
			void  sendLegoPowerFunctions (uint16_t data, bool repeat = true) ;
 | 
			
		||||
#		endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOFT_CARRIER
 | 
			
		||||
	private:
 | 
			
		||||
		int sendPin;
 | 
			
		||||
 | 
			
		||||
		unsigned int periodTime;
 | 
			
		||||
		unsigned int periodOnTime;
 | 
			
		||||
		
 | 
			
		||||
		void sleepMicros(unsigned long us);
 | 
			
		||||
		void sleepUntilMicros(unsigned long targetTime);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
		const int sendPin = SEND_PIN;
 | 
			
		||||
#endif
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										113
									
								
								IRremote/IRremoteInt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								IRremote/IRremoteInt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
// IRremote
 | 
			
		||||
// Version 2.0.1 June, 2015
 | 
			
		||||
// Copyright 2009 Ken Shirriff
 | 
			
		||||
// For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
 | 
			
		||||
//
 | 
			
		||||
// Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
 | 
			
		||||
//
 | 
			
		||||
// 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/
 | 
			
		||||
//
 | 
			
		||||
// JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 | 
			
		||||
// Whynter A/C ARC-110WD added by Francesco Meschia
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
#ifndef IRremoteint_h
 | 
			
		||||
#define IRremoteint_h
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Include the right Arduino header
 | 
			
		||||
//
 | 
			
		||||
#if defined(ARDUINO) && (ARDUINO >= 100)
 | 
			
		||||
#	include <Arduino.h>
 | 
			
		||||
#else
 | 
			
		||||
#	if !defined(IRPRONTO)
 | 
			
		||||
#		include <WProgram.h>
 | 
			
		||||
#	endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// This handles definition and access to global variables
 | 
			
		||||
//
 | 
			
		||||
#ifdef IR_GLOBAL
 | 
			
		||||
#	define EXTERN
 | 
			
		||||
#else
 | 
			
		||||
#	define EXTERN extern
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Information for the Interrupt Service Routine
 | 
			
		||||
//
 | 
			
		||||
#define RAWBUF  101  // Maximum length of raw duration buffer
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
	struct {
 | 
			
		||||
		// The fields are ordered to reduce memory over caused by struct-padding
 | 
			
		||||
		uint8_t       rcvstate;        // State Machine state
 | 
			
		||||
		uint8_t       recvpin;         // Pin connected to IR data from detector
 | 
			
		||||
		uint8_t       blinkpin;
 | 
			
		||||
		uint8_t       blinkflag;       // true -> enable blinking of pin on IR processing
 | 
			
		||||
		uint8_t       rawlen;          // counter of entries in rawbuf
 | 
			
		||||
		unsigned int  timer;           // State timer, counts 50uS ticks.
 | 
			
		||||
		unsigned int  rawbuf[RAWBUF];  // raw data
 | 
			
		||||
		uint8_t       overflow;        // Raw buffer overflow occurred
 | 
			
		||||
	}
 | 
			
		||||
irparams_t;
 | 
			
		||||
 | 
			
		||||
// ISR State-Machine : Receiver States
 | 
			
		||||
#define STATE_IDLE      2
 | 
			
		||||
#define STATE_MARK      3
 | 
			
		||||
#define STATE_SPACE     4
 | 
			
		||||
#define STATE_STOP      5
 | 
			
		||||
#define STATE_OVERFLOW  6
 | 
			
		||||
 | 
			
		||||
// Allow all parts of the code access to the ISR data
 | 
			
		||||
// NB. The data can be changed by the ISR at any time, even mid-function
 | 
			
		||||
// Therefore we declare it as "volatile" to stop the compiler/CPU caching it
 | 
			
		||||
EXTERN  volatile irparams_t  irparams;
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Defines for setting and clearing register bits
 | 
			
		||||
//
 | 
			
		||||
#ifndef cbi
 | 
			
		||||
#	define cbi(sfr, bit)  (_SFR_BYTE(sfr) &= ~_BV(bit))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef sbi
 | 
			
		||||
#	define sbi(sfr, bit)  (_SFR_BYTE(sfr) |= _BV(bit))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Pulse parms are ((X*50)-100) for the Mark and ((X*50)+100) for the Space.
 | 
			
		||||
// First MARK is the one after the long gap
 | 
			
		||||
// Pulse parameters in uSec
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Due to sensor lag, when received, Marks  tend to be 100us too long and
 | 
			
		||||
//                                   Spaces tend to be 100us too short
 | 
			
		||||
#define MARK_EXCESS    100
 | 
			
		||||
 | 
			
		||||
// Upper and Lower percentage tolerances in measurements
 | 
			
		||||
#define TOLERANCE       25
 | 
			
		||||
#define LTOL            (1.0 - (TOLERANCE/100.))
 | 
			
		||||
#define UTOL            (1.0 + (TOLERANCE/100.))
 | 
			
		||||
 | 
			
		||||
// Minimum gap between IR transmissions
 | 
			
		||||
#define _GAP            5000
 | 
			
		||||
#define GAP_TICKS       (_GAP/USECPERTICK)
 | 
			
		||||
 | 
			
		||||
#define TICKS_LOW(us)   ((int)(((us)*LTOL/USECPERTICK)))
 | 
			
		||||
#define TICKS_HIGH(us)  ((int)(((us)*UTOL/USECPERTICK + 1)))
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// IR detector output is active low
 | 
			
		||||
//
 | 
			
		||||
#define MARK   0
 | 
			
		||||
#define SPACE  1
 | 
			
		||||
 | 
			
		||||
// All board specific stuff has been moved to its own file, included here.
 | 
			
		||||
#include "boarddefs.h"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										653
									
								
								IRremote/boarddefs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										653
									
								
								IRremote/boarddefs.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,653 @@
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
// IRremote
 | 
			
		||||
// Version 2.0.1 June, 2015
 | 
			
		||||
// Copyright 2009 Ken Shirriff
 | 
			
		||||
// For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
 | 
			
		||||
 | 
			
		||||
// This file contains all board specific information. It was previously contained within
 | 
			
		||||
// IRremoteInt.h
 | 
			
		||||
 | 
			
		||||
// Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
 | 
			
		||||
//
 | 
			
		||||
// 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/
 | 
			
		||||
//
 | 
			
		||||
// JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 | 
			
		||||
// Whynter A/C ARC-110WD added by Francesco Meschia
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
#ifndef boarddefs_h
 | 
			
		||||
#define boarddefs_h
 | 
			
		||||
 | 
			
		||||
// Define some defaults, that some boards may like to override
 | 
			
		||||
// (This is to avoid negative logic, ! DONT_... is just awkward.)
 | 
			
		||||
 | 
			
		||||
// This board has/needs the avr/interrupt.h
 | 
			
		||||
#define HAS_AVR_INTERRUPT_H
 | 
			
		||||
 | 
			
		||||
// Define if sending is supported
 | 
			
		||||
#define SENDING_SUPPORTED
 | 
			
		||||
 | 
			
		||||
// If defined, a standard enableIRIn function will be define.
 | 
			
		||||
// Undefine for boards supplying their own.
 | 
			
		||||
#define USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
 | 
			
		||||
// Duty cycle in percent for sent signals. Presently takes effect only with USE_SOFT_CARRIER
 | 
			
		||||
#define DUTY_CYCLE 50
 | 
			
		||||
 | 
			
		||||
// If USE_SOFT_CARRIER, this amount (in micro seconds) is subtracted from the
 | 
			
		||||
// on-time of the pulses.
 | 
			
		||||
#define PULSE_CORRECTION 3
 | 
			
		||||
 | 
			
		||||
// digitalWrite is supposed to be slow. If this is an issue, define faster,
 | 
			
		||||
// board-dependent versions of these macros SENDPIN_ON(pin) and SENDPIN_OFF(pin).
 | 
			
		||||
// Portable, possibly slow, default definitions are given at the end of this file.
 | 
			
		||||
// If defining new versions, feel free to ignore the pin argument if it
 | 
			
		||||
// is not configurable on the current board.
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// 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(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
 | 
			
		||||
#	define BLINKLED        LED_BUILTIN
 | 
			
		||||
#	define BLINKLED_ON()   (digitalWrite(LED_BUILTIN, HIGH))
 | 
			
		||||
#	define BLINKLED_OFF()  (digitalWrite(LED_BUILTIN, LOW))
 | 
			
		||||
 | 
			
		||||
#	define USE_SOFT_CARRIER
 | 
			
		||||
	// Define to use spin wait instead of delayMicros()
 | 
			
		||||
//#	define USE_SPIN_WAIT
 | 
			
		||||
#       undef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
 | 
			
		||||
        // The default pin used used for sending.
 | 
			
		||||
#	define SEND_PIN 9
 | 
			
		||||
 | 
			
		||||
#elif defined(ESP32)
 | 
			
		||||
        // No system LED on ESP32, disable blinking by NOT defining BLINKLED
 | 
			
		||||
 | 
			
		||||
        // avr/interrupt.h is not present
 | 
			
		||||
#       undef HAS_AVR_INTERRUPT_H
 | 
			
		||||
 | 
			
		||||
        // Sending not implemented
 | 
			
		||||
#       undef SENDING_SUPPORTED#
 | 
			
		||||
 | 
			
		||||
        // Supply own enbleIRIn
 | 
			
		||||
#       undef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#	define BLINKLED        13
 | 
			
		||||
#	define BLINKLED_ON()  (PORTB |= B00100000)
 | 
			
		||||
#	define BLINKLED_OFF()  (PORTB &= B11011111)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// CPU Frequency
 | 
			
		||||
//
 | 
			
		||||
#ifdef F_CPU
 | 
			
		||||
#	define SYSCLOCK  F_CPU     // main Arduino clock
 | 
			
		||||
#else
 | 
			
		||||
#	define SYSCLOCK  16000000  // main Arduino clock
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// microseconds per clock interrupt tick
 | 
			
		||||
#define USECPERTICK    50
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Define which timer to use
 | 
			
		||||
//
 | 
			
		||||
// Uncomment the timer you wish to use on your board.
 | 
			
		||||
// If you are using another library which uses timer2, you have options to
 | 
			
		||||
//   switch IRremote to use a different timer.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
#elif defined(__AVR_ATmega32U4__)
 | 
			
		||||
	//#define IR_USE_TIMER1   // tx = pin 14
 | 
			
		||||
	//#define IR_USE_TIMER3   // tx = pin 9
 | 
			
		||||
	#define IR_USE_TIMER4_HS  // tx = pin 10
 | 
			
		||||
 | 
			
		||||
// Teensy 3.0 / Teensy 3.1
 | 
			
		||||
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
 | 
			
		||||
	#define IR_USE_TIMER_CMT  // tx = pin 5
 | 
			
		||||
 | 
			
		||||
// Teensy-LC
 | 
			
		||||
#elif defined(__MKL26Z64__)
 | 
			
		||||
  #define IR_USE_TIMER_TPM1 // tx = pin 16
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
// MightyCore - ATmega1284
 | 
			
		||||
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
 | 
			
		||||
	//#define IR_USE_TIMER1   // tx = pin 13
 | 
			
		||||
	#define IR_USE_TIMER2     // tx = pin 14
 | 
			
		||||
	//#define IR_USE_TIMER3   // tx = pin 6
 | 
			
		||||
 | 
			
		||||
// MightyCore - ATmega164, ATmega324, ATmega644
 | 
			
		||||
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
 | 
			
		||||
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
 | 
			
		||||
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
 | 
			
		||||
|| defined(__AVR_ATmega164P__)
 | 
			
		||||
	//#define IR_USE_TIMER1   // tx = pin 13
 | 
			
		||||
	#define IR_USE_TIMER2     // tx = pin 14
 | 
			
		||||
	
 | 
			
		||||
//MegaCore - ATmega64, ATmega128
 | 
			
		||||
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
 | 
			
		||||
 	#define IR_USE_TIMER1     // tx = pin 13
 | 
			
		||||
 | 
			
		||||
// MightyCore - ATmega8535, ATmega16, ATmega32
 | 
			
		||||
#elif defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
 | 
			
		||||
 	#define IR_USE_TIMER1     // tx = pin 13
 | 
			
		||||
 | 
			
		||||
// Atmega8
 | 
			
		||||
#elif defined(__AVR_ATmega8__)
 | 
			
		||||
	#define IR_USE_TIMER1     // tx = pin 9
 | 
			
		||||
 | 
			
		||||
// ATtiny84
 | 
			
		||||
#elif defined(__AVR_ATtiny84__)
 | 
			
		||||
	#define IR_USE_TIMER1     // tx = pin 6
 | 
			
		||||
 | 
			
		||||
//ATtiny85
 | 
			
		||||
#elif defined(__AVR_ATtiny85__)
 | 
			
		||||
	#define IR_USE_TIMER_TINY0   // tx = pin 1
 | 
			
		||||
 | 
			
		||||
#elif defined(ESP32)
 | 
			
		||||
	#define IR_TIMER_USE_ESP32
 | 
			
		||||
 | 
			
		||||
#elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
 | 
			
		||||
	#define TIMER_PRESCALER_DIV 64
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
 | 
			
		||||
// ATmega48, ATmega88, ATmega168, ATmega328
 | 
			
		||||
	//#define IR_USE_TIMER1   // tx = pin 9
 | 
			
		||||
	#define IR_USE_TIMER2     // tx = pin 3
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Defines for Timer
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// 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 SEND_PIN  CORE_OC2B_PIN  // Teensy
 | 
			
		||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
 | 
			
		||||
#	define SEND_PIN  9              // Arduino Mega
 | 
			
		||||
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
 | 
			
		||||
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
 | 
			
		||||
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
 | 
			
		||||
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
 | 
			
		||||
|| defined(__AVR_ATmega164P__)
 | 
			
		||||
#	define SEND_PIN  14             // MightyCore
 | 
			
		||||
#else
 | 
			
		||||
#	define SEND_PIN  3              // Arduino Duemilanove, Diecimila, LilyPad, etc
 | 
			
		||||
#endif					     // ATmega48, ATmega88, ATmega168, ATmega328
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// 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)))
 | 
			
		||||
 | 
			
		||||
//-----------------
 | 
			
		||||
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8535__) \
 | 
			
		||||
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
 | 
			
		||||
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
 | 
			
		||||
#	define TIMER_ENABLE_INTR   (TIMSK |= _BV(OCIE1A))
 | 
			
		||||
#	define TIMER_DISABLE_INTR  (TIMSK &= ~_BV(OCIE1A))
 | 
			
		||||
#else
 | 
			
		||||
#	define TIMER_ENABLE_INTR   (TIMSK1 = _BV(OCIE1A))
 | 
			
		||||
#	define TIMER_DISABLE_INTR  (TIMSK1 = 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//-----------------
 | 
			
		||||
#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 SEND_PIN  CORE_OC1A_PIN  // Teensy
 | 
			
		||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
 | 
			
		||||
#	define SEND_PIN  11             // Arduino Mega
 | 
			
		||||
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
 | 
			
		||||
#	define SEND_PIN  13	     // MegaCore
 | 
			
		||||
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
 | 
			
		||||
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
 | 
			
		||||
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
 | 
			
		||||
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
 | 
			
		||||
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
 | 
			
		||||
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__)
 | 
			
		||||
#	define SEND_PIN  13             // MightyCore
 | 
			
		||||
#elif defined(__AVR_ATtiny84__)
 | 
			
		||||
# 	define SEND_PIN  6
 | 
			
		||||
#else
 | 
			
		||||
#	define SEND_PIN  9              // Arduino Duemilanove, Diecimila, LilyPad, etc
 | 
			
		||||
#endif					     // ATmega48, ATmega88, ATmega168, ATmega328
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// 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 SEND_PIN  CORE_OC3A_PIN  // Teensy
 | 
			
		||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
 | 
			
		||||
#	define SEND_PIN  5              // Arduino Mega
 | 
			
		||||
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
 | 
			
		||||
#	define SEND_PIN  6              // MightyCore
 | 
			
		||||
#else
 | 
			
		||||
#	error "Please add OC3A pin number here\n"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// 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 SEND_PIN  CORE_OC4A_PIN  // Teensy
 | 
			
		||||
#elif defined(__AVR_ATmega32U4__)
 | 
			
		||||
#	define SEND_PIN  13             // Leonardo
 | 
			
		||||
#else
 | 
			
		||||
#	error "Please add OC4A pin number here\n"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// 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 SEND_PIN  CORE_OC4A_PIN
 | 
			
		||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
 | 
			
		||||
#	define SEND_PIN  6  // Arduino Mega
 | 
			
		||||
#else
 | 
			
		||||
#	error "Please add OC4A pin number here\n"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// 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 SEND_PIN  CORE_OC5A_PIN
 | 
			
		||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
 | 
			
		||||
#	define SEND_PIN  46  // Arduino Mega
 | 
			
		||||
#else
 | 
			
		||||
#	error "Please add OC5A pin number here\n"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// Special carrier modulator timer
 | 
			
		||||
//
 | 
			
		||||
#elif defined(IR_USE_TIMER_CMT)
 | 
			
		||||
 | 
			
		||||
#define TIMER_RESET ({     \
 | 
			
		||||
	uint8_t tmp __attribute__((unused)) = CMT_MSC; \
 | 
			
		||||
	CMT_CMD2 = 30;         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define TIMER_ENABLE_PWM  do {                                         \
 | 
			
		||||
	CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE;  \
 | 
			
		||||
} while(0)
 | 
			
		||||
 | 
			
		||||
#define TIMER_DISABLE_PWM  do {                                        \
 | 
			
		||||
	CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;  \
 | 
			
		||||
} while(0)
 | 
			
		||||
 | 
			
		||||
#define TIMER_ENABLE_INTR   NVIC_ENABLE_IRQ(IRQ_CMT)
 | 
			
		||||
#define TIMER_DISABLE_INTR  NVIC_DISABLE_IRQ(IRQ_CMT)
 | 
			
		||||
#define TIMER_INTR_NAME     cmt_isr
 | 
			
		||||
 | 
			
		||||
//-----------------
 | 
			
		||||
#ifdef ISR
 | 
			
		||||
#	undef ISR
 | 
			
		||||
#endif
 | 
			
		||||
#define  ISR(f)  void f(void)
 | 
			
		||||
 | 
			
		||||
//-----------------
 | 
			
		||||
#define CMT_PPS_DIV  ((F_BUS + 7999999) / 8000000)
 | 
			
		||||
#if F_BUS < 8000000
 | 
			
		||||
#error IRremote requires at least 8 MHz on Teensy 3.x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//-----------------
 | 
			
		||||
#define TIMER_CONFIG_KHZ(val) ({ 	 \
 | 
			
		||||
	SIM_SCGC4 |= SIM_SCGC4_CMT;      \
 | 
			
		||||
	SIM_SOPT2 |= SIM_SOPT2_PTD7PAD;  \
 | 
			
		||||
	CMT_PPS    = CMT_PPS_DIV - 1;    \
 | 
			
		||||
	CMT_CGH1   = ((F_BUS / CMT_PPS_DIV / 3000) + ((val)/2)) / (val); \
 | 
			
		||||
	CMT_CGL1   = ((F_BUS / CMT_PPS_DIV / 1500) + ((val)/2)) / (val); \
 | 
			
		||||
	CMT_CMD1   = 0;                  \
 | 
			
		||||
	CMT_CMD2   = 30;                 \
 | 
			
		||||
	CMT_CMD3   = 0;                  \
 | 
			
		||||
	CMT_CMD4   = 0;                  \
 | 
			
		||||
	CMT_OC     = 0x60;               \
 | 
			
		||||
	CMT_MSC    = 0x01;               \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define TIMER_CONFIG_NORMAL() ({  \
 | 
			
		||||
	SIM_SCGC4 |= SIM_SCGC4_CMT;   \
 | 
			
		||||
	CMT_PPS    = CMT_PPS_DIV - 1; \
 | 
			
		||||
	CMT_CGH1   = 1;               \
 | 
			
		||||
	CMT_CGL1   = 1;               \
 | 
			
		||||
	CMT_CMD1   = 0;               \
 | 
			
		||||
	CMT_CMD2   = 30;              \
 | 
			
		||||
	CMT_CMD3   = 0;               \
 | 
			
		||||
	CMT_CMD4   = (F_BUS / 160000 + CMT_PPS_DIV / 2) / CMT_PPS_DIV - 31; \
 | 
			
		||||
	CMT_OC     = 0;               \
 | 
			
		||||
	CMT_MSC    = 0x03;            \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define SEND_PIN  5
 | 
			
		||||
 | 
			
		||||
// defines for TPM1 timer on Teensy-LC
 | 
			
		||||
#elif defined(IR_USE_TIMER_TPM1)
 | 
			
		||||
#define TIMER_RESET          FTM1_SC |= FTM_SC_TOF;
 | 
			
		||||
#define TIMER_ENABLE_PWM     CORE_PIN16_CONFIG = PORT_PCR_MUX(3)|PORT_PCR_DSE|PORT_PCR_SRE
 | 
			
		||||
#define TIMER_DISABLE_PWM    CORE_PIN16_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_SRE
 | 
			
		||||
#define TIMER_ENABLE_INTR    NVIC_ENABLE_IRQ(IRQ_FTM1)
 | 
			
		||||
#define TIMER_DISABLE_INTR   NVIC_DISABLE_IRQ(IRQ_FTM1)
 | 
			
		||||
#define TIMER_INTR_NAME      ftm1_isr
 | 
			
		||||
#ifdef ISR
 | 
			
		||||
#undef ISR
 | 
			
		||||
#endif
 | 
			
		||||
#define ISR(f) void f(void)
 | 
			
		||||
#define TIMER_CONFIG_KHZ(val) ({                     \
 | 
			
		||||
	SIM_SCGC6 |= SIM_SCGC6_TPM1;                 \
 | 
			
		||||
	FTM1_SC = 0;                                 \
 | 
			
		||||
	FTM1_CNT = 0;                                \
 | 
			
		||||
	FTM1_MOD = (F_PLL/2000) / val - 1;           \
 | 
			
		||||
	FTM1_C0V = (F_PLL/6000) / val - 1;           \
 | 
			
		||||
	FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);     \
 | 
			
		||||
})
 | 
			
		||||
#define TIMER_CONFIG_NORMAL() ({                     \
 | 
			
		||||
	SIM_SCGC6 |= SIM_SCGC6_TPM1;                 \
 | 
			
		||||
	FTM1_SC = 0;                                 \
 | 
			
		||||
	FTM1_CNT = 0;                                \
 | 
			
		||||
	FTM1_MOD = (F_PLL/40000) - 1;                \
 | 
			
		||||
	FTM1_C0V = 0;                                \
 | 
			
		||||
	FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE; \
 | 
			
		||||
})
 | 
			
		||||
#define SEND_PIN        16
 | 
			
		||||
 | 
			
		||||
// defines for timer_tiny0 (8 bits)
 | 
			
		||||
#elif defined(IR_USE_TIMER_TINY0)
 | 
			
		||||
#define TIMER_RESET
 | 
			
		||||
#define TIMER_ENABLE_PWM     (TCCR0A |= _BV(COM0B1))
 | 
			
		||||
#define TIMER_DISABLE_PWM    (TCCR0A &= ~(_BV(COM0B1)))
 | 
			
		||||
#define TIMER_ENABLE_INTR    (TIMSK |= _BV(OCIE0A))
 | 
			
		||||
#define TIMER_DISABLE_INTR   (TIMSK &= ~(_BV(OCIE0A)))
 | 
			
		||||
#define TIMER_INTR_NAME      TIMER0_COMPA_vect
 | 
			
		||||
#define TIMER_CONFIG_KHZ(val) ({ \
 | 
			
		||||
  const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
 | 
			
		||||
  TCCR0A = _BV(WGM00); \
 | 
			
		||||
  TCCR0B = _BV(WGM02) | _BV(CS00); \
 | 
			
		||||
  OCR0A = pwmval; \
 | 
			
		||||
  OCR0B = pwmval / 3; \
 | 
			
		||||
})
 | 
			
		||||
#define TIMER_COUNT_TOP      (SYSCLOCK * USECPERTICK / 1000000)
 | 
			
		||||
#if (TIMER_COUNT_TOP < 256)
 | 
			
		||||
#define TIMER_CONFIG_NORMAL() ({ \
 | 
			
		||||
  TCCR0A = _BV(WGM01); \
 | 
			
		||||
  TCCR0B = _BV(CS00); \
 | 
			
		||||
  OCR0A = TIMER_COUNT_TOP; \
 | 
			
		||||
  TCNT0 = 0; \
 | 
			
		||||
})
 | 
			
		||||
#else
 | 
			
		||||
#define TIMER_CONFIG_NORMAL() ({ \
 | 
			
		||||
  TCCR0A = _BV(WGM01); \
 | 
			
		||||
  TCCR0B = _BV(CS01); \
 | 
			
		||||
  OCR0A = TIMER_COUNT_TOP / 8; \
 | 
			
		||||
  TCNT0 = 0; \
 | 
			
		||||
})
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define SEND_PIN        1  /* ATtiny85 */
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// ESP32 (ESP8266 should likely be added here too)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// ESP32 has it own timer API and does not use these macros, but to avoid ifdef'ing
 | 
			
		||||
// them out in the common code, they are defined to no-op. This allows the code to compile
 | 
			
		||||
// (which it wouldn't otherwise) but irsend will not work until ESP32 specific code is written
 | 
			
		||||
// for that -- merlin
 | 
			
		||||
// As a warning, sending timing specific code from an ESP32 can be challenging if you need 100%
 | 
			
		||||
// reliability because the arduino code may be interrupted and cause your sent waveform to be the
 | 
			
		||||
// wrong length. This is specifically an issue for neopixels which require 800Khz resolution.
 | 
			
		||||
// IR may just work as is with the common code since it's lower frequency, but if not, the other
 | 
			
		||||
// way to do this on ESP32 is using the RMT built in driver like in this incomplete library below
 | 
			
		||||
// https://github.com/ExploreEmbedded/ESP32_RMT
 | 
			
		||||
#elif defined(IR_TIMER_USE_ESP32)
 | 
			
		||||
 | 
			
		||||
#define TIMER_RESET
 | 
			
		||||
 | 
			
		||||
#ifdef ISR
 | 
			
		||||
#	undef ISR
 | 
			
		||||
#endif
 | 
			
		||||
#define  ISR(f)  void IRTimer()
 | 
			
		||||
 | 
			
		||||
#elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
 | 
			
		||||
// use timer 3 hardcoded at this time
 | 
			
		||||
 | 
			
		||||
#define TIMER_RESET
 | 
			
		||||
#define TIMER_ENABLE_PWM     // Not presently used
 | 
			
		||||
#define TIMER_DISABLE_PWM
 | 
			
		||||
#define TIMER_ENABLE_INTR    NVIC_EnableIRQ(TC3_IRQn) // Not presently used    
 | 
			
		||||
#define TIMER_DISABLE_INTR   NVIC_DisableIRQ(TC3_IRQn)
 | 
			
		||||
#define TIMER_INTR_NAME      TC3_Handler // Not presently used
 | 
			
		||||
#define TIMER_CONFIG_KHZ(f)
 | 
			
		||||
 | 
			
		||||
#ifdef ISR
 | 
			
		||||
#	undef ISR
 | 
			
		||||
#endif
 | 
			
		||||
#define  ISR(f)  void irs()
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
// Unknown Timer
 | 
			
		||||
//
 | 
			
		||||
#else
 | 
			
		||||
#	error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Provide default definitions, portable but possibly slower than necessary.
 | 
			
		||||
#ifndef SENDPIN_ON
 | 
			
		||||
#define SENDPIN_ON(pin)  digitalWrite(pin, HIGH)
 | 
			
		||||
#endif
 | 
			
		||||
	
 | 
			
		||||
#ifndef SENDPIN_OFF
 | 
			
		||||
#define SENDPIN_OFF(pin) digitalWrite(pin, LOW)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // ! boarddefs_h
 | 
			
		||||
							
								
								
									
										81
									
								
								IRremote/changelog.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								IRremote/changelog.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
## 2.4.0 - 2017/08/10
 | 
			
		||||
 - Cleanup of hardware dependencies. Merge in SAM support [PR #437](https://github.com/z3t0/Arduino-IRremote/pull/437)
 | 
			
		||||
 | 
			
		||||
## 2.3.3 - 2017/03/31
 | 
			
		||||
- Added ESP32 IR receive support [PR #427](https://github.com/z3t0/Arduino-IRremote/pull/425)
 | 
			
		||||
 | 
			
		||||
## 2.2.3 - 2017/03/27
 | 
			
		||||
- Fix calculation of pause length in LEGO PF protocol [PR #427](https://github.com/z3t0/Arduino-IRremote/pull/427)
 | 
			
		||||
 | 
			
		||||
## 2.2.2 - 2017/01/20
 | 
			
		||||
- Fixed naming bug [PR #398](https://github.com/z3t0/Arduino-IRremote/pull/398)
 | 
			
		||||
 | 
			
		||||
## 2.2.1 - 2016/07/27
 | 
			
		||||
- Added tests for Lego Power Functions Protocol [PR #336](https://github.com/z3t0/Arduino-IRremote/pull/336)
 | 
			
		||||
 | 
			
		||||
## 2.2.0 - 2016/06/28
 | 
			
		||||
- Added support for ATmega8535
 | 
			
		||||
- Added support for ATmega16
 | 
			
		||||
- Added support for ATmega32
 | 
			
		||||
- Added support for ATmega164
 | 
			
		||||
- Added support for ATmega324
 | 
			
		||||
- Added support for ATmega644
 | 
			
		||||
- Added support for ATmega1284
 | 
			
		||||
- Added support for ATmega64
 | 
			
		||||
- Added support for ATmega128
 | 
			
		||||
 | 
			
		||||
[PR](https://github.com/z3t0/Arduino-IRremote/pull/324)
 | 
			
		||||
 | 
			
		||||
## 2.1.1 - 2016/05/04
 | 
			
		||||
- Added Lego Power Functions Protocol [PR #309](https://github.com/z3t0/Arduino-IRremote/pull/309)
 | 
			
		||||
 | 
			
		||||
## 2.1.0 - 2016/02/20
 | 
			
		||||
- Improved Debugging [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258)
 | 
			
		||||
- Display TIME instead of TICKS [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258)
 | 
			
		||||
 | 
			
		||||
## 2.0.4 - 2016/02/20
 | 
			
		||||
- Add Panasonic and JVC to IRrecord example [PR](https://github.com/z3t0/Arduino-IRremote/pull/54)
 | 
			
		||||
 | 
			
		||||
## 2.0.3 - 2016/02/20
 | 
			
		||||
- Change IRSend Raw parameter to const [PR](https://github.com/z3t0/Arduino-IRremote/pull/227)
 | 
			
		||||
 | 
			
		||||
## 2.0.2 - 2015/12/02
 | 
			
		||||
- Added IRremoteInfo Sketch - [PR](https://github.com/z3t0/Arduino-IRremote/pull/241)
 | 
			
		||||
- Enforcing changelog.md
 | 
			
		||||
 | 
			
		||||
## 2.0.1 - 2015/07/26 - [Release](https://github.com/shirriff/Arduino-IRremote/releases/tag/BETA)
 | 
			
		||||
### Changes
 | 
			
		||||
- Updated README
 | 
			
		||||
- Updated Contributors
 | 
			
		||||
- Fixed #110 Mess
 | 
			
		||||
- Created Gitter Room
 | 
			
		||||
- Added Gitter Badge
 | 
			
		||||
- Standardised Code Base
 | 
			
		||||
- Clean Debug Output
 | 
			
		||||
- Optimized Send Loops
 | 
			
		||||
- Modularized Design
 | 
			
		||||
- Optimized and Updated Examples
 | 
			
		||||
- Improved Documentation
 | 
			
		||||
- Fixed and Improved many coding errors
 | 
			
		||||
- Fixed Aiwa RC-T501 Decoding
 | 
			
		||||
- Fixed Interrupt on ATmega8
 | 
			
		||||
- Switched to Stable Release of @PlatformIO
 | 
			
		||||
 | 
			
		||||
### Additions
 | 
			
		||||
- Added Aiwa RC-T501 Protocol
 | 
			
		||||
- Added Denon Protocol
 | 
			
		||||
- Added Pronto Support
 | 
			
		||||
- Added Library Properties
 | 
			
		||||
- Added Template For New Protocols
 | 
			
		||||
- Added this changelog
 | 
			
		||||
- Added Teensy LC Support
 | 
			
		||||
- Added ATtiny84 Support
 | 
			
		||||
- Added ATtiny85 Support
 | 
			
		||||
- Added isIdle method
 | 
			
		||||
 | 
			
		||||
### Deletions
 | 
			
		||||
- Removed (Fixed) #110
 | 
			
		||||
- Broke Teensy 3 / 3.1 Support
 | 
			
		||||
 | 
			
		||||
### Not Working
 | 
			
		||||
- Teensy 3 / 3.1 Support is in Development
 | 
			
		||||
							
								
								
									
										39
									
								
								IRremote/esp32.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								IRremote/esp32.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
#ifdef ESP32
 | 
			
		||||
 | 
			
		||||
// This file contains functions specific to the ESP32.
 | 
			
		||||
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
// "Idiot check"
 | 
			
		||||
#ifdef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
#error Must undef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
hw_timer_t *timer;
 | 
			
		||||
void IRTimer(); // defined in IRremote.cpp, masqueraded as ISR(TIMER_INTR_NAME)
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// initialization
 | 
			
		||||
//
 | 
			
		||||
void  IRrecv::enableIRIn ( )
 | 
			
		||||
{
 | 
			
		||||
// Interrupt Service Routine - Fires every 50uS
 | 
			
		||||
	// ESP32 has a proper API to setup timers, no weird chip macros needed
 | 
			
		||||
	// simply call the readable API versions :)
 | 
			
		||||
	// 3 timers, choose #1, 80 divider nanosecond precision, 1 to count up
 | 
			
		||||
	timer = timerBegin(1, 80, 1);
 | 
			
		||||
	timerAttachInterrupt(timer, &IRTimer, 1);
 | 
			
		||||
	// every 50ns, autoreload = true
 | 
			
		||||
	timerAlarmWrite(timer, 50, true);
 | 
			
		||||
	timerAlarmEnable(timer);
 | 
			
		||||
 | 
			
		||||
	// Initialize state machine variables
 | 
			
		||||
	irparams.rcvstate = STATE_IDLE;
 | 
			
		||||
	irparams.rawlen = 0;
 | 
			
		||||
 | 
			
		||||
	// Set pin modes
 | 
			
		||||
	pinMode(irparams.recvpin, INPUT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // ESP32
 | 
			
		||||
							
								
								
									
										513
									
								
								IRremote/irPronto.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										513
									
								
								IRremote/irPronto.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,513 @@
 | 
			
		||||
#define TEST 0
 | 
			
		||||
 | 
			
		||||
#if TEST
 | 
			
		||||
#	define SEND_PRONTO        1
 | 
			
		||||
#	define PRONTO_ONCE        false
 | 
			
		||||
#	define PRONTO_REPEAT      true
 | 
			
		||||
#	define PRONTO_FALLBACK    true
 | 
			
		||||
#	define PRONTO_NOFALLBACK  false
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if SEND_PRONTO
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
#if TEST
 | 
			
		||||
#	include <stdio.h>
 | 
			
		||||
	void  enableIROut (int freq)  { printf("\nFreq = %d KHz\n", freq); }
 | 
			
		||||
	void  mark        (int t)     { printf("+%d," , t); }
 | 
			
		||||
	void  space       (int t)     { printf("-%d, ", t); }
 | 
			
		||||
#else
 | 
			
		||||
#	include "IRremote.h"
 | 
			
		||||
#endif // TEST
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Check for a valid hex digit
 | 
			
		||||
//
 | 
			
		||||
bool  ishex (char ch)
 | 
			
		||||
{
 | 
			
		||||
	return ( ((ch >= '0') && (ch <= '9')) ||
 | 
			
		||||
             ((ch >= 'A') && (ch <= 'F')) ||
 | 
			
		||||
             ((ch >= 'a') && (ch <= 'f'))   ) ? true : false ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Check for a valid "blank" ... '\0' is a valid "blank"
 | 
			
		||||
//
 | 
			
		||||
bool  isblank (char ch)
 | 
			
		||||
{
 | 
			
		||||
	return ((ch == ' ') || (ch == '\t') || (ch == '\0')) ? true : false ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Bypass spaces
 | 
			
		||||
//
 | 
			
		||||
bool  byp (char** pcp)
 | 
			
		||||
{
 | 
			
		||||
	while (isblank(**pcp))  (*pcp)++ ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Hex-to-Byte : Decode a hex digit
 | 
			
		||||
// We assume the character has already been validated
 | 
			
		||||
//
 | 
			
		||||
uint8_t  htob (char ch)
 | 
			
		||||
{
 | 
			
		||||
	if ((ch >= '0') && (ch <= '9'))  return ch - '0' ;
 | 
			
		||||
	if ((ch >= 'A') && (ch <= 'F'))  return ch - 'A' + 10 ;
 | 
			
		||||
	if ((ch >= 'a') && (ch <= 'f'))  return ch - 'a' + 10 ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Hex-to-Word : Decode a block of 4 hex digits
 | 
			
		||||
// We assume the string has already been validated
 | 
			
		||||
//   and the pointer being passed points at the start of a block of 4 hex digits
 | 
			
		||||
//
 | 
			
		||||
uint16_t  htow (char* cp)
 | 
			
		||||
{
 | 
			
		||||
	return ( (htob(cp[0]) << 12) | (htob(cp[1]) <<  8) |
 | 
			
		||||
             (htob(cp[2]) <<  4) | (htob(cp[3])      )  ) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
bool sendPronto (char* s,  bool repeat,  bool fallback)
 | 
			
		||||
{
 | 
			
		||||
	int       i;
 | 
			
		||||
	int       len;
 | 
			
		||||
	int       skip;
 | 
			
		||||
	char*     cp;
 | 
			
		||||
	uint16_t  freq;  // Frequency in KHz
 | 
			
		||||
	uint8_t   usec;  // pronto uSec/tick
 | 
			
		||||
	uint8_t   once;
 | 
			
		||||
	uint8_t   rpt;
 | 
			
		||||
 | 
			
		||||
	// Validate the string
 | 
			
		||||
	for (cp = s;  *cp;  cp += 4) {
 | 
			
		||||
		byp(&cp);
 | 
			
		||||
		if ( !ishex(cp[0]) || !ishex(cp[1]) ||
 | 
			
		||||
		     !ishex(cp[2]) || !ishex(cp[3]) || !isblank(cp[4]) )  return false ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We will use cp to traverse the string
 | 
			
		||||
	cp = s;
 | 
			
		||||
 | 
			
		||||
	// Check mode = Oscillated/Learned
 | 
			
		||||
	byp(&cp);
 | 
			
		||||
	if (htow(cp) != 0000)  return false;
 | 
			
		||||
	cp += 4;
 | 
			
		||||
 | 
			
		||||
	// Extract & set frequency
 | 
			
		||||
	byp(&cp);
 | 
			
		||||
	freq = (int)(1000000 / (htow(cp) * 0.241246));  // Rounding errors will occur, tolerance is +/- 10%
 | 
			
		||||
	usec = (int)(((1.0 / freq) * 1000000) + 0.5);  // Another rounding error, thank Cod for analogue electronics
 | 
			
		||||
	freq /= 1000;  // This will introduce a(nother) rounding error which we do not want in the usec calcualtion
 | 
			
		||||
	cp += 4;
 | 
			
		||||
 | 
			
		||||
	// Get length of "once" code
 | 
			
		||||
	byp(&cp);
 | 
			
		||||
	once = htow(cp);
 | 
			
		||||
	cp += 4;
 | 
			
		||||
 | 
			
		||||
	// Get length of "repeat" code
 | 
			
		||||
	byp(&cp);
 | 
			
		||||
	rpt = htow(cp);
 | 
			
		||||
	cp += 4;
 | 
			
		||||
 | 
			
		||||
	// Which code are we sending?
 | 
			
		||||
	if (fallback) { // fallback on the "other" code if "this" code is not present
 | 
			
		||||
		if (!repeat) { // requested 'once'
 | 
			
		||||
			if (once)  len = once * 2,  skip = 0 ;  // if once exists send it
 | 
			
		||||
			else       len = rpt  * 2,  skip = 0 ;  // else send repeat code
 | 
			
		||||
		} else { // requested 'repeat'
 | 
			
		||||
			if (rpt)   len = rpt  * 2,  skip = 0 ;  // if rpt exists send it
 | 
			
		||||
			else       len = once * 2,  skip = 0 ;  // else send once code
 | 
			
		||||
		}
 | 
			
		||||
	} else {  // Send what we asked for, do not fallback if the code is empty!
 | 
			
		||||
		if (!repeat)  len = once * 2,  skip = 0 ;     // 'once' starts at 0
 | 
			
		||||
		else          len = rpt  * 2,  skip = once ;  // 'repeat' starts where 'once' ends
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	// Skip to start of code
 | 
			
		||||
	for (i = 0;  i < skip;  i++, cp += 4)  byp(&cp) ;
 | 
			
		||||
 | 
			
		||||
	// Send code
 | 
			
		||||
	enableIROut(freq);
 | 
			
		||||
	for (i = 0;  i < len;  i++) {
 | 
			
		||||
		byp(&cp);
 | 
			
		||||
		if (i & 1)  space(htow(cp) * usec);
 | 
			
		||||
		else        mark (htow(cp) * usec);
 | 
			
		||||
		cp += 4;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if TEST
 | 
			
		||||
 | 
			
		||||
int  main ( )
 | 
			
		||||
{
 | 
			
		||||
	char  prontoTest[] =
 | 
			
		||||
		"0000 0070 0000 0032 0080 0040 0010 0010 0010 0030 " //  10
 | 
			
		||||
		"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  20
 | 
			
		||||
		"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  30
 | 
			
		||||
		"0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " //  40
 | 
			
		||||
		"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  50
 | 
			
		||||
		"0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " //  60
 | 
			
		||||
		"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  70
 | 
			
		||||
		"0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 " //  80
 | 
			
		||||
		"0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " //  90
 | 
			
		||||
		"0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " // 100
 | 
			
		||||
		"0010 0030 0010 0aa6";                               // 104
 | 
			
		||||
 | 
			
		||||
	sendPronto(prontoTest, PRONTO_ONCE,   PRONTO_FALLBACK);    // once code
 | 
			
		||||
	sendPronto(prontoTest, PRONTO_REPEAT, PRONTO_FALLBACK);    // repeat code
 | 
			
		||||
	sendPronto(prontoTest, PRONTO_ONCE,   PRONTO_NOFALLBACK);  // once code
 | 
			
		||||
	sendPronto(prontoTest, PRONTO_REPEAT, PRONTO_NOFALLBACK);  // repeat code
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TEST
 | 
			
		||||
 | 
			
		||||
#endif // SEND_PRONTO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
// Sources:
 | 
			
		||||
//   http://www.remotecentral.com/features/irdisp2.htm
 | 
			
		||||
//   http://www.hifi-remote.com/wiki/index.php?title=Working_With_Pronto_Hex
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#define IRPRONTO
 | 
			
		||||
#include "IRremoteInt.h"  // The Arduino IRremote library defines USECPERTICK
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Source: https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet
 | 
			
		||||
//         -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls
 | 
			
		||||
//
 | 
			
		||||
char  prontoTest[] =
 | 
			
		||||
	"0000 0070 0000 0032 0080 0040 0010 0010 0010 0030 " //  10
 | 
			
		||||
	"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  20
 | 
			
		||||
	"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  30
 | 
			
		||||
	"0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " //  40
 | 
			
		||||
	"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  50
 | 
			
		||||
	"0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " //  60
 | 
			
		||||
	"0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " //  70
 | 
			
		||||
	"0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 " //  80
 | 
			
		||||
	"0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " //  90
 | 
			
		||||
	"0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " // 100
 | 
			
		||||
	"0010 0030 0010 0aa6";                               // 104
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// This is the longest code we can support
 | 
			
		||||
#define CODEMAX  200
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// This is the data we pull out of the pronto code
 | 
			
		||||
typedef
 | 
			
		||||
	struct {
 | 
			
		||||
		int        freq;           // Carrier frequency (in Hz)
 | 
			
		||||
		int        usec;           // uSec per tick (based on freq)
 | 
			
		||||
 | 
			
		||||
		int        codeLen;        // Length of code
 | 
			
		||||
		uint16_t   code[CODEMAX];  // Code in hex
 | 
			
		||||
 | 
			
		||||
		int        onceLen;        // Length of "once" transmit
 | 
			
		||||
		uint16_t*  once;           // Pointer to start within 'code'
 | 
			
		||||
 | 
			
		||||
		int        rptLen;         // Length of "repeat" transmit
 | 
			
		||||
		uint16_t*  rpt;            // Pointer to start within 'code'
 | 
			
		||||
	}
 | 
			
		||||
pronto_t;
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// From what I have seen, the only time we go over 8-bits is the 'space'
 | 
			
		||||
// on the end which creates the lead-out/inter-code gap.  Assuming I'm right,
 | 
			
		||||
// we can code this up as a special case and otherwise halve the size of our
 | 
			
		||||
// data!
 | 
			
		||||
// Ignoring the first four values (the config data) and the last value
 | 
			
		||||
// (the lead-out), if you find a protocol that uses values greater than 00fe
 | 
			
		||||
// we are going to have to revisit this code!
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// So, the 0th byte will be the carrier frequency in Khz (NOT Hz)
 | 
			
		||||
//      "  1st  "    "   "   "  length of the "once" code
 | 
			
		||||
//      "  2nd  "    "   "   "  length of the "repeat" code
 | 
			
		||||
//
 | 
			
		||||
// Thereafter, odd  bytes will be Mark  lengths as a multiple of USECPERTICK uS
 | 
			
		||||
//             even   "     "  "  Space    "    "  "    "     "       "      "
 | 
			
		||||
//
 | 
			
		||||
// Any occurence of "FF" in either a Mark or a Space will indicate
 | 
			
		||||
//   "Use the 16-bit FF value" which will also be a multiple of USECPERTICK uS
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// As a point of comparison, the test code (prontoTest[]) is 520 bytes
 | 
			
		||||
// (yes, more than 0.5KB of our Arduino's precious 32KB) ... after conversion
 | 
			
		||||
// to pronto hex that goes down to ((520/5)*2) = 208 bytes ... once converted to
 | 
			
		||||
// our format we are down to ((208/2) -1 -1 +2) = 104 bytes
 | 
			
		||||
//
 | 
			
		||||
// In fariness this is still very memory-hungry
 | 
			
		||||
// ...As a rough guide:
 | 
			
		||||
//   10 codes cost 1K of memory (this will vary depending on the protocol).
 | 
			
		||||
//
 | 
			
		||||
// So if you're building a complex remote control, you will probably need to
 | 
			
		||||
// keep the codes on an external memory device (not in the Arduino sketch) and
 | 
			
		||||
// load them as you need them.  Hmmm.
 | 
			
		||||
//
 | 
			
		||||
// This dictates that "Oscillated Pronto Codes" are probably NOT the way forward
 | 
			
		||||
//
 | 
			
		||||
// For example, prontoTest[] happens to be: A 48-bit IR code in Denon format
 | 
			
		||||
// So we know it starts with 80/40                           (Denon header)
 | 
			
		||||
//             and ends with 10/aa6                          (Denon leadout)
 | 
			
		||||
//             and all (48) bits in between are either 10/10 (Denon 0)
 | 
			
		||||
//                                                  or 10/30 (Denon 1)
 | 
			
		||||
// So we could easily store this data in 1-byte  ("Denon")
 | 
			
		||||
//                                     + 1-byte  (Length=48)
 | 
			
		||||
//                                     + 6-bytes (IR code)
 | 
			
		||||
// At 8-bytes per code, we can store 128 codes in 1KB or memory - that's a lot
 | 
			
		||||
// better than the 2 (two) we started off with!
 | 
			
		||||
//
 | 
			
		||||
// And serendipitously, by reducing the amount of data, our program will run
 | 
			
		||||
// a LOT faster!
 | 
			
		||||
//
 | 
			
		||||
// Again, I repeat, even after you have spent time converting the "Oscillated
 | 
			
		||||
// Pronto Codes" in to IRremote format, it will be a LOT more memory-hungry
 | 
			
		||||
// than using sendDenon() (or whichever) ...BUT these codes are easily
 | 
			
		||||
// available on the internet, so we'll support them!
 | 
			
		||||
//
 | 
			
		||||
typedef
 | 
			
		||||
	struct {
 | 
			
		||||
		uint16_t   FF;
 | 
			
		||||
		uint8_t    code[CODEMAX];
 | 
			
		||||
	}
 | 
			
		||||
irCode_t;
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#define DEBUGF(...)  printf(__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// String must be block of 4 hex digits separated with blanks
 | 
			
		||||
//
 | 
			
		||||
bool  validate (char* cp,  int* len)
 | 
			
		||||
{
 | 
			
		||||
	for (*len = 0;  *cp;  (*len)++, cp += 4) {
 | 
			
		||||
		byp(&cp);
 | 
			
		||||
		if ( !ishex(cp[0]) || !ishex(cp[1]) ||
 | 
			
		||||
		     !ishex(cp[2]) || !ishex(cp[3]) || !isblank(cp[4]) )  return false ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Hex-to-Byte : Decode a hex digit
 | 
			
		||||
// We assume the character has already been validated
 | 
			
		||||
//
 | 
			
		||||
uint8_t  htob (char ch)
 | 
			
		||||
{
 | 
			
		||||
	if ((ch >= '0') && (ch <= '9'))  return ch - '0' ;
 | 
			
		||||
	if ((ch >= 'A') && (ch <= 'F'))  return ch - 'A' + 10 ;
 | 
			
		||||
	if ((ch >= 'a') && (ch <= 'f'))  return ch - 'a' + 10 ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Hex-to-Word : Decode a block of 4 hex digits
 | 
			
		||||
// We assume the string has already been validated
 | 
			
		||||
//   and the pointer being passed points at the start of a block of 4 hex digits
 | 
			
		||||
//
 | 
			
		||||
uint16_t  htow (char* cp)
 | 
			
		||||
{
 | 
			
		||||
	return ( (htob(cp[0]) << 12) | (htob(cp[1]) <<  8) |
 | 
			
		||||
             (htob(cp[2]) <<  4) | (htob(cp[3])      )  ) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Convert the pronto string in to data
 | 
			
		||||
//
 | 
			
		||||
bool  decode (char* s,  pronto_t* p,  irCode_t* ir)
 | 
			
		||||
{
 | 
			
		||||
	int    i, len;
 | 
			
		||||
	char*  cp;
 | 
			
		||||
 | 
			
		||||
	// Validate the Pronto string
 | 
			
		||||
	if (!validate(s, &p->codeLen)) {
 | 
			
		||||
		DEBUGF("Invalid pronto string\n");
 | 
			
		||||
		return false ;
 | 
			
		||||
    }
 | 
			
		||||
	DEBUGF("Found %d hex codes\n", p->codeLen);
 | 
			
		||||
 | 
			
		||||
	// Allocate memory to store the decoded string
 | 
			
		||||
	//if (!(p->code = malloc(p->len))) {
 | 
			
		||||
	//	DEBUGF("Memory allocation failed\n");
 | 
			
		||||
	//	return false ;
 | 
			
		||||
	//}
 | 
			
		||||
 | 
			
		||||
	// Check in case our code is too long
 | 
			
		||||
	if (p->codeLen > CODEMAX) {
 | 
			
		||||
		DEBUGF("Code too long, edit CODEMAX and recompile\n");
 | 
			
		||||
		return false ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode the string
 | 
			
		||||
	cp = s;
 | 
			
		||||
	for (i = 0;  i < p->codeLen;  i++, cp += 4) {
 | 
			
		||||
		byp(&cp);
 | 
			
		||||
		p->code[i] = htow(cp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Announce our findings
 | 
			
		||||
	DEBUGF("Input: |%s|\n", s);
 | 
			
		||||
	DEBUGF("Found: |");
 | 
			
		||||
    for (i = 0;  i < p->codeLen;  i++)  DEBUGF("%04x ", p->code[i]) ;
 | 
			
		||||
	DEBUGF("|\n");
 | 
			
		||||
 | 
			
		||||
	DEBUGF("Form [%04X] : ", p->code[0]);
 | 
			
		||||
	if      (p->code[0] == 0x0000)  DEBUGF("Oscillated (Learned)\n");
 | 
			
		||||
	else if (p->code[0] == 0x0100)  DEBUGF("Unmodulated\n");
 | 
			
		||||
	else                            DEBUGF("Unknown\n");
 | 
			
		||||
    if (p->code[0] != 0x0000)  return false ;  // Can only handle Oscillated
 | 
			
		||||
 | 
			
		||||
	// Calculate the carrier frequency (+/- 10%) & uSecs per pulse
 | 
			
		||||
	// Pronto uses a crystal which generates a timeabse of 0.241246
 | 
			
		||||
	p->freq     = (int)(1000000 / (p->code[1] * 0.241246));
 | 
			
		||||
	p->usec     = (int)(((1.0 / p->freq) * 1000000) + 0.5);
 | 
			
		||||
	ir->code[0] = p->freq / 1000;
 | 
			
		||||
    DEBUGF("Freq [%04X] : %d Hz  (%d uS/pluse) -> %d KHz\n",
 | 
			
		||||
	       p->code[1], p->freq, p->usec, ir->code[0]);
 | 
			
		||||
 | 
			
		||||
	// Set the length & start pointer for the "once" code
 | 
			
		||||
	p->onceLen  = p->code[2];
 | 
			
		||||
	p->once     = &p->code[4];
 | 
			
		||||
	ir->code[1] = p->onceLen;
 | 
			
		||||
	DEBUGF("Once [%04X] : %d\n", p->code[2], p->onceLen);
 | 
			
		||||
 | 
			
		||||
	// Set the length & start pointer for the "repeat" code
 | 
			
		||||
	p->rptLen = p->code[3];
 | 
			
		||||
	p->rpt    = &p->code[4 + p->onceLen];
 | 
			
		||||
	ir->code[2] = p->rptLen;
 | 
			
		||||
	DEBUGF("Rpt  [%04X] : %d\n", p->code[3], p->rptLen);
 | 
			
		||||
 | 
			
		||||
	// Check everything tallies
 | 
			
		||||
	if (1 + 1 + 1 + 1 + (p->onceLen * 2) + (p->rptLen * 2) != p->codeLen) {
 | 
			
		||||
		DEBUGF("Bad code length\n");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Convert the IR data to our new format
 | 
			
		||||
	ir->FF = p->code[p->codeLen - 1];
 | 
			
		||||
 | 
			
		||||
	len = (p->onceLen * 2) + (p->rptLen * 2);
 | 
			
		||||
	DEBUGF("Encoded: |");
 | 
			
		||||
	for (i = 0;  i < len;  i++) {
 | 
			
		||||
		if (p->code[i+4] == ir->FF) {
 | 
			
		||||
			ir->code[i+3] = 0xFF;
 | 
			
		||||
		} else if (p->code[i+4] > 0xFE) {
 | 
			
		||||
			DEBUGF("\n%04X : Mark/Space overflow\n", p->code[i+4]);
 | 
			
		||||
			return false;
 | 
			
		||||
		} else {
 | 
			
		||||
			ir->code[i+3] = (p->code[i+4] * p->usec) / USECPERTICK;
 | 
			
		||||
		}
 | 
			
		||||
		DEBUGF("%s%d", !i ? "" : (i&1 ? "," : ", "), ir->code[i+3]);
 | 
			
		||||
	}
 | 
			
		||||
	DEBUGF("|\n");
 | 
			
		||||
 | 
			
		||||
	ir->FF = (ir->FF * p->usec) / USECPERTICK;
 | 
			
		||||
	DEBUGF("FF -> %d\n", ir->FF);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
void  irDump (irCode_t* ir)
 | 
			
		||||
{
 | 
			
		||||
	int  i, len;
 | 
			
		||||
 | 
			
		||||
	printf("uint8_t  buttonName[%d] = {", len);
 | 
			
		||||
 | 
			
		||||
	printf("%d,%d, ", (ir->FF >> 8), ir->FF & 0xFF);
 | 
			
		||||
	printf("%d,%d,%d, ", ir->code[0], ir->code[1], ir->code[2]);
 | 
			
		||||
 | 
			
		||||
	len = (ir->code[1] * 2) + (ir->code[2] * 2);
 | 
			
		||||
	for (i = 0;  i < len;  i++) {
 | 
			
		||||
		printf("%s%d", !i ? "" : (i&1 ? "," : ", "), ir->code[i+3]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printf("};\n");
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
int  main ( )
 | 
			
		||||
{
 | 
			
		||||
	pronto_t  pCode;
 | 
			
		||||
	irCode_t  irCode;
 | 
			
		||||
 | 
			
		||||
	decode(prontoTest, &pCode, &irCode);
 | 
			
		||||
 | 
			
		||||
	irDump(&irCode);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif //0
 | 
			
		||||
							
								
								
									
										223
									
								
								IRremote/irRecv.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								IRremote/irRecv.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Decodes the received IR message
 | 
			
		||||
// Returns 0 if no data ready, 1 if data ready.
 | 
			
		||||
// Results of decoding are stored in results
 | 
			
		||||
//
 | 
			
		||||
int  IRrecv::decode (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	results->rawbuf   = irparams.rawbuf;
 | 
			
		||||
	results->rawlen   = irparams.rawlen;
 | 
			
		||||
 | 
			
		||||
	results->overflow = irparams.overflow;
 | 
			
		||||
 | 
			
		||||
	if (irparams.rcvstate != STATE_STOP)  return false ;
 | 
			
		||||
 | 
			
		||||
#if DECODE_NEC
 | 
			
		||||
	DBG_PRINTLN("Attempting NEC decode");
 | 
			
		||||
	if (decodeNEC(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_SONY
 | 
			
		||||
	DBG_PRINTLN("Attempting Sony decode");
 | 
			
		||||
	if (decodeSony(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_SANYO
 | 
			
		||||
	DBG_PRINTLN("Attempting Sanyo decode");
 | 
			
		||||
	if (decodeSanyo(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_MITSUBISHI
 | 
			
		||||
	DBG_PRINTLN("Attempting Mitsubishi decode");
 | 
			
		||||
	if (decodeMitsubishi(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_RC5
 | 
			
		||||
	DBG_PRINTLN("Attempting RC5 decode");
 | 
			
		||||
	if (decodeRC5(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_RC6
 | 
			
		||||
	DBG_PRINTLN("Attempting RC6 decode");
 | 
			
		||||
	if (decodeRC6(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_PANASONIC
 | 
			
		||||
	DBG_PRINTLN("Attempting Panasonic decode");
 | 
			
		||||
	if (decodePanasonic(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_LG
 | 
			
		||||
	DBG_PRINTLN("Attempting LG decode");
 | 
			
		||||
	if (decodeLG(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_JVC
 | 
			
		||||
	DBG_PRINTLN("Attempting JVC decode");
 | 
			
		||||
	if (decodeJVC(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_SAMSUNG
 | 
			
		||||
	DBG_PRINTLN("Attempting SAMSUNG decode");
 | 
			
		||||
	if (decodeSAMSUNG(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_WHYNTER
 | 
			
		||||
	DBG_PRINTLN("Attempting Whynter decode");
 | 
			
		||||
	if (decodeWhynter(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_AIWA_RC_T501
 | 
			
		||||
	DBG_PRINTLN("Attempting Aiwa RC-T501 decode");
 | 
			
		||||
	if (decodeAiwaRCT501(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_DENON
 | 
			
		||||
	DBG_PRINTLN("Attempting Denon decode");
 | 
			
		||||
	if (decodeDenon(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DECODE_LEGO_PF
 | 
			
		||||
	DBG_PRINTLN("Attempting Lego Power Functions");
 | 
			
		||||
	if (decodeLegoPowerFunctions(results))  return true ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	// decodeHash returns a hash on any input.
 | 
			
		||||
	// Thus, it needs to be last in the list.
 | 
			
		||||
	// If you add any decodes, add them before this.
 | 
			
		||||
	if (decodeHash(results))  return true ;
 | 
			
		||||
 | 
			
		||||
	// Throw away and start over
 | 
			
		||||
	resume();
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
IRrecv::IRrecv (int recvpin)
 | 
			
		||||
{
 | 
			
		||||
	irparams.recvpin = recvpin;
 | 
			
		||||
	irparams.blinkflag = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IRrecv::IRrecv (int recvpin, int blinkpin)
 | 
			
		||||
{
 | 
			
		||||
	irparams.recvpin = recvpin;
 | 
			
		||||
	irparams.blinkpin = blinkpin;
 | 
			
		||||
	pinMode(blinkpin, OUTPUT);
 | 
			
		||||
	irparams.blinkflag = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// initialization
 | 
			
		||||
//
 | 
			
		||||
#ifdef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
void  IRrecv::enableIRIn ( )
 | 
			
		||||
{
 | 
			
		||||
// Interrupt Service Routine - Fires every 50uS
 | 
			
		||||
	cli();
 | 
			
		||||
	// Setup pulse clock timer interrupt
 | 
			
		||||
	// Prescale /8 (16M/8 = 0.5 microseconds per tick)
 | 
			
		||||
	// Therefore, the timer interval can range from 0.5 to 128 microseconds
 | 
			
		||||
	// Depending on the reset value (255 to 0)
 | 
			
		||||
	TIMER_CONFIG_NORMAL();
 | 
			
		||||
 | 
			
		||||
	// Timer2 Overflow Interrupt Enable
 | 
			
		||||
	TIMER_ENABLE_INTR;
 | 
			
		||||
 | 
			
		||||
	TIMER_RESET;
 | 
			
		||||
 | 
			
		||||
	sei();  // enable interrupts
 | 
			
		||||
 | 
			
		||||
	// Initialize state machine variables
 | 
			
		||||
	irparams.rcvstate = STATE_IDLE;
 | 
			
		||||
	irparams.rawlen = 0;
 | 
			
		||||
 | 
			
		||||
	// Set pin modes
 | 
			
		||||
	pinMode(irparams.recvpin, INPUT);
 | 
			
		||||
}
 | 
			
		||||
#endif // USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Enable/disable blinking of pin 13 on IR processing
 | 
			
		||||
//
 | 
			
		||||
void  IRrecv::blink13 (int blinkflag)
 | 
			
		||||
{
 | 
			
		||||
#ifdef BLINKLED
 | 
			
		||||
	irparams.blinkflag = blinkflag;
 | 
			
		||||
	if (blinkflag)  pinMode(BLINKLED, OUTPUT) ;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Return if receiving new IR signals
 | 
			
		||||
//
 | 
			
		||||
bool  IRrecv::isIdle ( )
 | 
			
		||||
{
 | 
			
		||||
 return (irparams.rcvstate == STATE_IDLE || irparams.rcvstate == STATE_STOP) ? true : false;
 | 
			
		||||
}
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Restart the ISR state machine
 | 
			
		||||
//
 | 
			
		||||
void  IRrecv::resume ( )
 | 
			
		||||
{
 | 
			
		||||
	irparams.rcvstate = STATE_IDLE;
 | 
			
		||||
	irparams.rawlen = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// hashdecode - 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.
 | 
			
		||||
//
 | 
			
		||||
// The algorithm: look at the sequence of MARK signals, and see if each one
 | 
			
		||||
// is shorter (0), the same length (1), or longer (2) than the previous.
 | 
			
		||||
// Do the same with the SPACE signals.  Hash the resulting sequence of 0's,
 | 
			
		||||
// 1's, and 2's to a 32-bit value.  This will give a unique value for each
 | 
			
		||||
// different code (probably), for most code systems.
 | 
			
		||||
//
 | 
			
		||||
// http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
 | 
			
		||||
//
 | 
			
		||||
// Compare two tick values, returning 0 if newval is shorter,
 | 
			
		||||
// 1 if newval is equal, and 2 if newval is longer
 | 
			
		||||
// Use a tolerance of 20%
 | 
			
		||||
//
 | 
			
		||||
int  IRrecv::compare (unsigned int oldval,  unsigned int newval)
 | 
			
		||||
{
 | 
			
		||||
	if      (newval < oldval * .8)  return 0 ;
 | 
			
		||||
	else if (oldval < newval * .8)  return 2 ;
 | 
			
		||||
	else                            return 1 ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
 | 
			
		||||
// Converts the raw code values into a 32-bit hash code.
 | 
			
		||||
// Hopefully this code is unique for each button.
 | 
			
		||||
// This isn't a "real" decoding, just an arbitrary value.
 | 
			
		||||
//
 | 
			
		||||
#define FNV_PRIME_32 16777619
 | 
			
		||||
#define FNV_BASIS_32 2166136261
 | 
			
		||||
 | 
			
		||||
long  IRrecv::decodeHash (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  hash = FNV_BASIS_32;
 | 
			
		||||
 | 
			
		||||
	// Require at least 6 samples to prevent triggering on noise
 | 
			
		||||
	if (results->rawlen < 6)  return false ;
 | 
			
		||||
 | 
			
		||||
	for (int i = 1;  (i + 2) < results->rawlen;  i++) {
 | 
			
		||||
		int value =  compare(results->rawbuf[i], results->rawbuf[i+2]);
 | 
			
		||||
		// Add value into the hash
 | 
			
		||||
		hash = (hash * FNV_PRIME_32) ^ value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	results->value       = hash;
 | 
			
		||||
	results->bits        = 32;
 | 
			
		||||
	results->decode_type = UNKNOWN;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										139
									
								
								IRremote/irSend.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								IRremote/irSend.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
#ifdef SENDING_SUPPORTED
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
void  IRsend::sendRaw (const unsigned int buf[],  unsigned int len,  unsigned int hz)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(hz);
 | 
			
		||||
 | 
			
		||||
	for (unsigned int i = 0;  i < len;  i++) {
 | 
			
		||||
		if (i & 1)  space(buf[i]) ;
 | 
			
		||||
		else        mark (buf[i]) ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SOFT_CARRIER
 | 
			
		||||
void inline IRsend::sleepMicros(unsigned long us)
 | 
			
		||||
{
 | 
			
		||||
#ifdef USE_SPIN_WAIT
 | 
			
		||||
	sleepUntilMicros(micros() + us);
 | 
			
		||||
#else
 | 
			
		||||
	if (us > 0U) // Is this necessary? (Official docu https://www.arduino.cc/en/Reference/DelayMicroseconds does not tell.)
 | 
			
		||||
		delayMicroseconds((unsigned int) us);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void inline IRsend::sleepUntilMicros(unsigned long targetTime)
 | 
			
		||||
{
 | 
			
		||||
#ifdef USE_SPIN_WAIT
 | 
			
		||||
	while (micros() < targetTime)
 | 
			
		||||
		;
 | 
			
		||||
#else
 | 
			
		||||
        unsigned long now = micros();
 | 
			
		||||
        if (now < targetTime)
 | 
			
		||||
                sleepMicros(targetTime - now);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif // USE_SOFT_CARRIER
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Sends an IR mark for the specified number of microseconds.
 | 
			
		||||
// The mark output is modulated at the PWM frequency.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
void IRsend::mark(unsigned int time)
 | 
			
		||||
{
 | 
			
		||||
#ifdef USE_SOFT_CARRIER
 | 
			
		||||
	unsigned long start = micros();
 | 
			
		||||
	unsigned long stop = start + time;
 | 
			
		||||
	if (stop + periodTime < start)
 | 
			
		||||
		// Counter wrap-around, happens very seldomly, but CAN happen.
 | 
			
		||||
		// Just give up instead of possibly damaging the hardware.
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	unsigned long nextPeriodEnding = start;
 | 
			
		||||
	unsigned long now = micros();
 | 
			
		||||
	while (now < stop) {
 | 
			
		||||
		SENDPIN_ON(sendPin);
 | 
			
		||||
		sleepMicros(periodOnTime);
 | 
			
		||||
		SENDPIN_OFF(sendPin);
 | 
			
		||||
		nextPeriodEnding += periodTime;
 | 
			
		||||
		sleepUntilMicros(nextPeriodEnding);
 | 
			
		||||
		now = micros();
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	TIMER_ENABLE_PWM; // Enable pin 3 PWM output
 | 
			
		||||
	if (time > 0) custom_delay_usec(time);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Leave pin off for time (given in microseconds)
 | 
			
		||||
// Sends an IR space for the specified number of microseconds.
 | 
			
		||||
// A space is no output, so the PWM output is disabled.
 | 
			
		||||
//
 | 
			
		||||
void  IRsend::space (unsigned int time)
 | 
			
		||||
{
 | 
			
		||||
	TIMER_DISABLE_PWM; // Disable pin 3 PWM output
 | 
			
		||||
	if (time > 0) IRsend::custom_delay_usec(time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Enables IR output.  The khz value controls the modulation frequency in kilohertz.
 | 
			
		||||
// The IR output will be on pin 3 (OC2B).
 | 
			
		||||
// This routine is designed for 36-40KHz; if you use it for other values, it's up to you
 | 
			
		||||
// to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)
 | 
			
		||||
// TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
 | 
			
		||||
// controlling the duty cycle.
 | 
			
		||||
// There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
 | 
			
		||||
// To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
 | 
			
		||||
// A few hours staring at the ATmega documentation and this will all make sense.
 | 
			
		||||
// See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
 | 
			
		||||
//
 | 
			
		||||
void  IRsend::enableIROut (int khz)
 | 
			
		||||
{
 | 
			
		||||
#ifdef USE_SOFT_CARRIER
 | 
			
		||||
	periodTime = (1000U + khz/2) / khz; // = 1000/khz + 1/2 = round(1000.0/khz)
 | 
			
		||||
	periodOnTime = periodTime * DUTY_CYCLE / 100U - PULSE_CORRECTION;
 | 
			
		||||
#endif
 | 
			
		||||
	
 | 
			
		||||
	// Disable the Timer2 Interrupt (which is used for receiving IR)
 | 
			
		||||
	TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
 | 
			
		||||
 | 
			
		||||
	pinMode(sendPin, OUTPUT);
 | 
			
		||||
	SENDPIN_OFF(sendPin); // When not sending, we want it low
 | 
			
		||||
 | 
			
		||||
	// COM2A = 00: disconnect OC2A
 | 
			
		||||
	// COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted
 | 
			
		||||
	// WGM2 = 101: phase-correct PWM with OCRA as top
 | 
			
		||||
	// CS2  = 000: no prescaling
 | 
			
		||||
	// The top value for the timer.  The modulation frequency will be SYSCLOCK / 2 / OCR2A.
 | 
			
		||||
	TIMER_CONFIG_KHZ(khz);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Custom delay function that circumvents Arduino's delayMicroseconds limit
 | 
			
		||||
 | 
			
		||||
void IRsend::custom_delay_usec(unsigned long uSecs) {
 | 
			
		||||
  if (uSecs > 4) {
 | 
			
		||||
    unsigned long start = micros();
 | 
			
		||||
    unsigned long endMicros = start + uSecs - 4;
 | 
			
		||||
    if (endMicros < start) { // Check if overflow
 | 
			
		||||
      while ( micros() > start ) {} // wait until overflow
 | 
			
		||||
    }
 | 
			
		||||
    while ( micros() < endMicros ) {} // normal wait
 | 
			
		||||
  } 
 | 
			
		||||
  //else {
 | 
			
		||||
  //  __asm__("nop\n\t"); // must have or compiler optimizes out
 | 
			
		||||
  //}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SENDING_SUPPORTED
 | 
			
		||||
							
								
								
									
										105
									
								
								IRremote/ir_Aiwa.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								IRremote/ir_Aiwa.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                         AAA   IIIII  W   W   AAA
 | 
			
		||||
//                        A   A    I    W   W  A   A
 | 
			
		||||
//                        AAAAA    I    W W W  AAAAA
 | 
			
		||||
//                        A   A    I    W W W  A   A
 | 
			
		||||
//                        A   A  IIIII   WWW   A   A
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
// Based off the RC-T501 RCU
 | 
			
		||||
// Lirc file http://lirc.sourceforge.net/remotes/aiwa/RC-T501
 | 
			
		||||
 | 
			
		||||
#define AIWA_RC_T501_HZ            38
 | 
			
		||||
#define AIWA_RC_T501_BITS          15
 | 
			
		||||
#define AIWA_RC_T501_PRE_BITS      26
 | 
			
		||||
#define AIWA_RC_T501_POST_BITS      1
 | 
			
		||||
#define AIWA_RC_T501_SUM_BITS    (AIWA_RC_T501_PRE_BITS + AIWA_RC_T501_BITS + AIWA_RC_T501_POST_BITS)
 | 
			
		||||
#define AIWA_RC_T501_HDR_MARK    8800
 | 
			
		||||
#define AIWA_RC_T501_HDR_SPACE   4500
 | 
			
		||||
#define AIWA_RC_T501_BIT_MARK     500
 | 
			
		||||
#define AIWA_RC_T501_ONE_SPACE    600
 | 
			
		||||
#define AIWA_RC_T501_ZERO_SPACE  1700
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_AIWA_RC_T501
 | 
			
		||||
void  IRsend::sendAiwaRCT501 (int code)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long  pre = 0x0227EEC0;  // 26-bits
 | 
			
		||||
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(AIWA_RC_T501_HZ);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(AIWA_RC_T501_HDR_MARK);
 | 
			
		||||
	space(AIWA_RC_T501_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Send "pre" data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (26 - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		mark(AIWA_RC_T501_BIT_MARK);
 | 
			
		||||
		if (pre & mask)  space(AIWA_RC_T501_ONE_SPACE) ;
 | 
			
		||||
		else             space(AIWA_RC_T501_ZERO_SPACE) ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
//-v- THIS CODE LOOKS LIKE IT MIGHT BE WRONG - CHECK!
 | 
			
		||||
//    it only send 15bits and ignores the top bit
 | 
			
		||||
//    then uses TOPBIT which is 0x80000000 to check the bit code
 | 
			
		||||
//    I suspect TOPBIT should be changed to 0x00008000
 | 
			
		||||
 | 
			
		||||
	// Skip first code bit
 | 
			
		||||
	code <<= 1;
 | 
			
		||||
	// Send code
 | 
			
		||||
	for (int  i = 0;  i < 15;  i++) {
 | 
			
		||||
		mark(AIWA_RC_T501_BIT_MARK);
 | 
			
		||||
		if (code & 0x80000000)  space(AIWA_RC_T501_ONE_SPACE) ;
 | 
			
		||||
		else                    space(AIWA_RC_T501_ZERO_SPACE) ;
 | 
			
		||||
		code <<= 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
//-^- THIS CODE LOOKS LIKE IT MIGHT BE WRONG - CHECK!
 | 
			
		||||
 | 
			
		||||
	// POST-DATA, 1 bit, 0x0
 | 
			
		||||
	mark(AIWA_RC_T501_BIT_MARK);
 | 
			
		||||
	space(AIWA_RC_T501_ZERO_SPACE);
 | 
			
		||||
 | 
			
		||||
	mark(AIWA_RC_T501_BIT_MARK);
 | 
			
		||||
	space(0);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_AIWA_RC_T501
 | 
			
		||||
bool  IRrecv::decodeAiwaRCT501 (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	int  data   = 0;
 | 
			
		||||
	int  offset = 1;
 | 
			
		||||
 | 
			
		||||
	// Check SIZE
 | 
			
		||||
	if (irparams.rawlen < 2 * (AIWA_RC_T501_SUM_BITS) + 4)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Check HDR Mark/Space
 | 
			
		||||
	if (!MATCH_MARK (results->rawbuf[offset++], AIWA_RC_T501_HDR_MARK ))  return false ;
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], AIWA_RC_T501_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	offset += 26;  // skip pre-data - optional
 | 
			
		||||
	while(offset < irparams.rawlen - 4) {
 | 
			
		||||
		if (MATCH_MARK(results->rawbuf[offset], AIWA_RC_T501_BIT_MARK))  offset++ ;
 | 
			
		||||
		else                                                             return false ;
 | 
			
		||||
 | 
			
		||||
		// ONE & ZERO
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], AIWA_RC_T501_ONE_SPACE))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], AIWA_RC_T501_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                                     break ;  // End of one & zero detected
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	results->bits = (offset - 1) / 2;
 | 
			
		||||
	if (results->bits < 42)  return false ;
 | 
			
		||||
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = AIWA_RC_T501;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										94
									
								
								IRremote/ir_Denon.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								IRremote/ir_Denon.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
// Reverse Engineered by looking at RAW dumps generated by IRremote
 | 
			
		||||
 | 
			
		||||
// I have since discovered that Denon publish all their IR codes:
 | 
			
		||||
//  https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet
 | 
			
		||||
//  -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls
 | 
			
		||||
 | 
			
		||||
// Having looked at the official Denon Pronto sheet and reverse engineered
 | 
			
		||||
// the timing values from it, it is obvious that Denon have a range of
 | 
			
		||||
// different timings and protocols ...the values here work for my AVR-3801 Amp!
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                    DDDD   EEEEE  N   N   OOO   N   N
 | 
			
		||||
//                     D  D  E      NN  N  O   O  NN  N
 | 
			
		||||
//                     D  D  EEE    N N N  O   O  N N N
 | 
			
		||||
//                     D  D  E      N  NN  O   O  N  NN
 | 
			
		||||
//                    DDDD   EEEEE  N   N   OOO   N   N
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define BITS          14  // The number of bits in the command
 | 
			
		||||
 | 
			
		||||
#define HDR_MARK     300  // The length of the Header:Mark
 | 
			
		||||
#define HDR_SPACE    750  // The lenght of the Header:Space
 | 
			
		||||
 | 
			
		||||
#define BIT_MARK     300  // The length of a Bit:Mark
 | 
			
		||||
#define ONE_SPACE   1800  // The length of a Bit:Space for 1's
 | 
			
		||||
#define ZERO_SPACE   750  // The length of a Bit:Space for 0's
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
#if SEND_DENON
 | 
			
		||||
void  IRsend::sendDenon (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark (HDR_MARK);
 | 
			
		||||
	space(HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark (BIT_MARK);
 | 
			
		||||
			space(ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark (BIT_MARK);
 | 
			
		||||
			space(ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
	mark(BIT_MARK);
 | 
			
		||||
    space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
#if DECODE_DENON
 | 
			
		||||
bool  IRrecv::decodeDenon (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long  data   = 0;  // Somewhere to build our code
 | 
			
		||||
	int            offset = 1;  // Skip the Gap reading
 | 
			
		||||
 | 
			
		||||
	// Check we have the right amount of data
 | 
			
		||||
	if (irparams.rawlen != 1 + 2 + (2 * BITS) + 1)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Check initial Mark+Space match
 | 
			
		||||
	if (!MATCH_MARK (results->rawbuf[offset++], HDR_MARK ))  return false ;
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	// Read the bits in
 | 
			
		||||
	for (int i = 0;  i < BITS;  i++) {
 | 
			
		||||
		// Each bit looks like: MARK + SPACE_1 -> 1
 | 
			
		||||
		//                 or : MARK + SPACE_0 -> 0
 | 
			
		||||
		if (!MATCH_MARK(results->rawbuf[offset++], BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
		// IR data is big-endian, so we shuffle it in from the right:
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], ONE_SPACE))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                        return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = BITS;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = DENON;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										54
									
								
								IRremote/ir_Dish.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								IRremote/ir_Dish.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                       DDDD   IIIII   SSSS  H   H
 | 
			
		||||
//                        D  D    I    S      H   H
 | 
			
		||||
//                        D  D    I     SSS   HHHHH
 | 
			
		||||
//                        D  D    I        S  H   H
 | 
			
		||||
//                       DDDD   IIIII  SSSS   H   H
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
// Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand )
 | 
			
		||||
//
 | 
			
		||||
// The sned function needs to be repeated 4 times
 | 
			
		||||
//
 | 
			
		||||
// Only send the last for characters of the hex.
 | 
			
		||||
// I.E.  Use 0x1C10 instead of 0x0000000000001C10 as listed in the LIRC file.
 | 
			
		||||
//
 | 
			
		||||
// Here is the LIRC file I found that seems to match the remote codes from the
 | 
			
		||||
// oscilloscope:
 | 
			
		||||
//   DISH NETWORK (echostar 301):
 | 
			
		||||
//   http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx
 | 
			
		||||
 | 
			
		||||
#define DISH_BITS          16
 | 
			
		||||
#define DISH_HDR_MARK     400
 | 
			
		||||
#define DISH_HDR_SPACE   6100
 | 
			
		||||
#define DISH_BIT_MARK     400
 | 
			
		||||
#define DISH_ONE_SPACE   1700
 | 
			
		||||
#define DISH_ZERO_SPACE  2800
 | 
			
		||||
#define DISH_RPT_SPACE   6200
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_DISH
 | 
			
		||||
void  IRsend::sendDISH (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(56);
 | 
			
		||||
 | 
			
		||||
	mark(DISH_HDR_MARK);
 | 
			
		||||
	space(DISH_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(DISH_BIT_MARK);
 | 
			
		||||
			space(DISH_ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(DISH_BIT_MARK);
 | 
			
		||||
			space(DISH_ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	mark(DISH_HDR_MARK); //added 26th March 2016, by AnalysIR ( https://www.AnalysIR.com )
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										101
									
								
								IRremote/ir_JVC.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								IRremote/ir_JVC.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                             JJJJJ  V   V   CCCC
 | 
			
		||||
//                               J    V   V  C
 | 
			
		||||
//                               J     V V   C
 | 
			
		||||
//                             J J     V V   C
 | 
			
		||||
//                              J       V     CCCC
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define JVC_BITS           16
 | 
			
		||||
#define JVC_HDR_MARK     8000
 | 
			
		||||
#define JVC_HDR_SPACE    4000
 | 
			
		||||
#define JVC_BIT_MARK      600
 | 
			
		||||
#define JVC_ONE_SPACE    1600
 | 
			
		||||
#define JVC_ZERO_SPACE    550
 | 
			
		||||
#define JVC_RPT_LENGTH  60000
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// JVC does NOT repeat by sending a separate code (like NEC does).
 | 
			
		||||
// The JVC protocol repeats by skipping the header.
 | 
			
		||||
// To send a JVC repeat signal, send the original code value
 | 
			
		||||
//   and set 'repeat' to true
 | 
			
		||||
//
 | 
			
		||||
#if SEND_JVC
 | 
			
		||||
void  IRsend::sendJVC (unsigned long data,  int nbits,  bool repeat)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Only send the Header if this is NOT a repeat command
 | 
			
		||||
	if (!repeat){
 | 
			
		||||
		mark(JVC_HDR_MARK);
 | 
			
		||||
		space(JVC_HDR_SPACE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(JVC_BIT_MARK);
 | 
			
		||||
			space(JVC_ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(JVC_BIT_MARK);
 | 
			
		||||
			space(JVC_ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
    mark(JVC_BIT_MARK);
 | 
			
		||||
    space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_JVC
 | 
			
		||||
bool  IRrecv::decodeJVC (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   offset = 1; // Skip first space
 | 
			
		||||
 | 
			
		||||
	// Check for repeat
 | 
			
		||||
	if (  (irparams.rawlen - 1 == 33)
 | 
			
		||||
	    && MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)
 | 
			
		||||
	    && MATCH_MARK(results->rawbuf[irparams.rawlen-1], JVC_BIT_MARK)
 | 
			
		||||
	   ) {
 | 
			
		||||
		results->bits        = 0;
 | 
			
		||||
		results->value       = REPEAT;
 | 
			
		||||
		results->decode_type = JVC;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Initial mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset++], JVC_HDR_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
	if (irparams.rawlen < (2 * JVC_BITS) + 1 )  return false ;
 | 
			
		||||
 | 
			
		||||
	// Initial space
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], JVC_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0;  i < JVC_BITS;  i++) {
 | 
			
		||||
		if (!MATCH_MARK(results->rawbuf[offset++], JVC_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], JVC_ONE_SPACE))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], JVC_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                            return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Stop bit
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = JVC_BITS;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = JVC;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										80
									
								
								IRremote/ir_LG.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								IRremote/ir_LG.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                               L       GGGG
 | 
			
		||||
//                               L      G
 | 
			
		||||
//                               L      G  GG
 | 
			
		||||
//                               L      G   G
 | 
			
		||||
//                               LLLLL   GGG
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define LG_BITS 28
 | 
			
		||||
 | 
			
		||||
#define LG_HDR_MARK 8000
 | 
			
		||||
#define LG_HDR_SPACE 4000
 | 
			
		||||
#define LG_BIT_MARK 600
 | 
			
		||||
#define LG_ONE_SPACE 1600
 | 
			
		||||
#define LG_ZERO_SPACE 550
 | 
			
		||||
#define LG_RPT_LENGTH 60000
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_LG
 | 
			
		||||
bool  IRrecv::decodeLG (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
    long  data   = 0;
 | 
			
		||||
    int   offset = 1; // Skip first space
 | 
			
		||||
 | 
			
		||||
	// Check we have the right amount of data
 | 
			
		||||
    if (irparams.rawlen < (2 * LG_BITS) + 1 )  return false ;
 | 
			
		||||
 | 
			
		||||
    // Initial mark/space
 | 
			
		||||
    if (!MATCH_MARK(results->rawbuf[offset++], LG_HDR_MARK))  return false ;
 | 
			
		||||
    if (!MATCH_SPACE(results->rawbuf[offset++], LG_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0;  i < LG_BITS;  i++) {
 | 
			
		||||
        if (!MATCH_MARK(results->rawbuf[offset++], LG_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
        if      (MATCH_SPACE(results->rawbuf[offset], LG_ONE_SPACE))   data = (data << 1) | 1 ;
 | 
			
		||||
        else if (MATCH_SPACE(results->rawbuf[offset], LG_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
        else                                                           return false ;
 | 
			
		||||
        offset++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Stop bit
 | 
			
		||||
    if (!MATCH_MARK(results->rawbuf[offset], LG_BIT_MARK))   return false ;
 | 
			
		||||
 | 
			
		||||
    // Success
 | 
			
		||||
    results->bits        = LG_BITS;
 | 
			
		||||
    results->value       = data;
 | 
			
		||||
    results->decode_type = LG;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_LG
 | 
			
		||||
void  IRsend::sendLG (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
    // Set IR carrier frequency
 | 
			
		||||
    enableIROut(38);
 | 
			
		||||
 | 
			
		||||
    // Header
 | 
			
		||||
    mark(LG_HDR_MARK);
 | 
			
		||||
    space(LG_HDR_SPACE);
 | 
			
		||||
    mark(LG_BIT_MARK);
 | 
			
		||||
 | 
			
		||||
    // Data
 | 
			
		||||
    for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
        if (data & mask) {
 | 
			
		||||
            space(LG_ONE_SPACE);
 | 
			
		||||
            mark(LG_BIT_MARK);
 | 
			
		||||
        } else {
 | 
			
		||||
            space(LG_ZERO_SPACE);
 | 
			
		||||
            mark(LG_BIT_MARK);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								IRremote/ir_Lego_PF.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								IRremote/ir_Lego_PF.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
#include "ir_Lego_PF_BitStreamEncoder.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//    L       EEEEEE   EEEE    OOOO
 | 
			
		||||
//    L       E       E       O    O
 | 
			
		||||
//    L       EEEE    E  EEE  O    O
 | 
			
		||||
//    L       E       E    E  O    O    LEGO Power Functions
 | 
			
		||||
//    LLLLLL  EEEEEE   EEEE    OOOO     Copyright (c) 2016 Philipp Henkel
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
// Supported Devices
 | 
			
		||||
// LEGO® Power Functions IR Receiver 8884
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
#if SEND_LEGO_PF
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
namespace {
 | 
			
		||||
void logFunctionParameters(uint16_t data, bool repeat) {
 | 
			
		||||
  DBG_PRINT("sendLegoPowerFunctions(data=");
 | 
			
		||||
  DBG_PRINT(data);
 | 
			
		||||
  DBG_PRINT(", repeat=");
 | 
			
		||||
  DBG_PRINTLN(repeat?"true)" : "false)");
 | 
			
		||||
}
 | 
			
		||||
} // anonymous namespace
 | 
			
		||||
#endif // DEBUG
 | 
			
		||||
 | 
			
		||||
void IRsend::sendLegoPowerFunctions(uint16_t data, bool repeat)
 | 
			
		||||
{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
  ::logFunctionParameters(data, repeat);
 | 
			
		||||
#endif // DEBUG
 | 
			
		||||
 | 
			
		||||
  enableIROut(38);
 | 
			
		||||
  static LegoPfBitStreamEncoder bitStreamEncoder;
 | 
			
		||||
  bitStreamEncoder.reset(data, repeat);
 | 
			
		||||
  do {
 | 
			
		||||
    mark(bitStreamEncoder.getMarkDuration());
 | 
			
		||||
    space(bitStreamEncoder.getPauseDuration());
 | 
			
		||||
  } while (bitStreamEncoder.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SEND_LEGO_PF
 | 
			
		||||
							
								
								
									
										115
									
								
								IRremote/ir_Lego_PF_BitStreamEncoder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								IRremote/ir_Lego_PF_BitStreamEncoder.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//    L       EEEEEE   EEEE    OOOO
 | 
			
		||||
//    L       E       E       O    O
 | 
			
		||||
//    L       EEEE    E  EEE  O    O
 | 
			
		||||
//    L       E       E    E  O    O    LEGO Power Functions
 | 
			
		||||
//    LLLLLL  EEEEEE   EEEE    OOOO     Copyright (c) 2016, 2017 Philipp Henkel
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
class LegoPfBitStreamEncoder {
 | 
			
		||||
 private:
 | 
			
		||||
  uint16_t data;
 | 
			
		||||
  bool repeatMessage;
 | 
			
		||||
  uint8_t messageBitIdx;
 | 
			
		||||
  uint8_t repeatCount;
 | 
			
		||||
  uint16_t messageLength;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  // HIGH data bit = IR mark + high pause
 | 
			
		||||
  // LOW data bit = IR mark + low pause
 | 
			
		||||
  static const uint16_t LOW_BIT_DURATION = 421;
 | 
			
		||||
  static const uint16_t HIGH_BIT_DURATION = 711;
 | 
			
		||||
  static const uint16_t START_BIT_DURATION = 1184;
 | 
			
		||||
  static const uint16_t STOP_BIT_DURATION = 1184;
 | 
			
		||||
  static const uint8_t IR_MARK_DURATION = 158;
 | 
			
		||||
  static const uint16_t HIGH_PAUSE_DURATION = HIGH_BIT_DURATION - IR_MARK_DURATION;
 | 
			
		||||
  static const uint16_t LOW_PAUSE_DURATION = LOW_BIT_DURATION - IR_MARK_DURATION;
 | 
			
		||||
  static const uint16_t START_PAUSE_DURATION = START_BIT_DURATION - IR_MARK_DURATION;
 | 
			
		||||
  static const uint16_t STOP_PAUSE_DURATION = STOP_BIT_DURATION - IR_MARK_DURATION;
 | 
			
		||||
  static const uint8_t MESSAGE_BITS = 18;
 | 
			
		||||
  static const uint16_t MAX_MESSAGE_LENGTH = 16000;
 | 
			
		||||
 | 
			
		||||
  void reset(uint16_t data, bool repeatMessage) {
 | 
			
		||||
    this->data = data;
 | 
			
		||||
    this->repeatMessage = repeatMessage;
 | 
			
		||||
    messageBitIdx = 0;
 | 
			
		||||
    repeatCount = 0;
 | 
			
		||||
    messageLength = getMessageLength();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int getChannelId() const { return 1 + ((data >> 12) & 0x3); }
 | 
			
		||||
 | 
			
		||||
  uint16_t getMessageLength() const {
 | 
			
		||||
    // Sum up all marks
 | 
			
		||||
    uint16_t length = MESSAGE_BITS * IR_MARK_DURATION;
 | 
			
		||||
 | 
			
		||||
    // Sum up all pauses
 | 
			
		||||
    length += START_PAUSE_DURATION;
 | 
			
		||||
    for (unsigned long mask = 1UL << 15; mask; mask >>= 1) {
 | 
			
		||||
      if (data & mask) {
 | 
			
		||||
        length += HIGH_PAUSE_DURATION;
 | 
			
		||||
      } else {
 | 
			
		||||
        length += LOW_PAUSE_DURATION;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    length += STOP_PAUSE_DURATION;
 | 
			
		||||
    return length;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  boolean next() {
 | 
			
		||||
    messageBitIdx++;
 | 
			
		||||
    if (messageBitIdx >= MESSAGE_BITS) {
 | 
			
		||||
      repeatCount++;
 | 
			
		||||
      messageBitIdx = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (repeatCount >= 1 && !repeatMessage) {
 | 
			
		||||
      return false;
 | 
			
		||||
    } else if (repeatCount >= 5) {
 | 
			
		||||
      return false;
 | 
			
		||||
    } else {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint8_t getMarkDuration() const { return IR_MARK_DURATION; }
 | 
			
		||||
 | 
			
		||||
  uint32_t getPauseDuration() const {
 | 
			
		||||
    if (messageBitIdx == 0)
 | 
			
		||||
      return START_PAUSE_DURATION;
 | 
			
		||||
    else if (messageBitIdx < MESSAGE_BITS - 1) {
 | 
			
		||||
      return getDataBitPause();
 | 
			
		||||
    } else {
 | 
			
		||||
      return getStopPause();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  uint16_t getDataBitPause() const {
 | 
			
		||||
    const int pos = MESSAGE_BITS - 2 - messageBitIdx;
 | 
			
		||||
    const bool isHigh = data & (1 << pos);
 | 
			
		||||
    return isHigh ? HIGH_PAUSE_DURATION : LOW_PAUSE_DURATION;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint32_t getStopPause() const {
 | 
			
		||||
    if (repeatMessage) {
 | 
			
		||||
      return getRepeatStopPause();
 | 
			
		||||
    } else {
 | 
			
		||||
      return STOP_PAUSE_DURATION;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint32_t getRepeatStopPause() const {
 | 
			
		||||
    if (repeatCount == 0 || repeatCount == 1) {
 | 
			
		||||
      return STOP_PAUSE_DURATION + (uint32_t)5 * MAX_MESSAGE_LENGTH - messageLength;
 | 
			
		||||
    } else if (repeatCount == 2 || repeatCount == 3) {
 | 
			
		||||
      return STOP_PAUSE_DURATION
 | 
			
		||||
             + (uint32_t)(6 + 2 * getChannelId()) * MAX_MESSAGE_LENGTH - messageLength;
 | 
			
		||||
    } else {
 | 
			
		||||
      return STOP_PAUSE_DURATION;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										85
									
								
								IRremote/ir_Mitsubishi.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								IRremote/ir_Mitsubishi.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//    MMMMM  IIIII TTTTT   SSSS  U   U  BBBB   IIIII   SSSS  H   H  IIIII
 | 
			
		||||
//    M M M    I     T    S      U   U  B   B    I    S      H   H    I
 | 
			
		||||
//    M M M    I     T     SSS   U   U  BBBB     I     SSS   HHHHH    I
 | 
			
		||||
//    M   M    I     T        S  U   U  B   B    I        S  H   H    I
 | 
			
		||||
//    M   M  IIIII   T    SSSS    UUU   BBBBB  IIIII  SSSS   H   H  IIIII
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
// Looks like Sony except for timings, 48 chars of data and time/space different
 | 
			
		||||
 | 
			
		||||
#define MITSUBISHI_BITS 16
 | 
			
		||||
 | 
			
		||||
// Mitsubishi RM 75501
 | 
			
		||||
// 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7
 | 
			
		||||
// #define MITSUBISHI_HDR_MARK	250  // seen range 3500
 | 
			
		||||
#define MITSUBISHI_HDR_SPACE	350 //  7*50+100
 | 
			
		||||
#define MITSUBISHI_ONE_MARK	1950 // 41*50-100
 | 
			
		||||
#define MITSUBISHI_ZERO_MARK  750 // 17*50-100
 | 
			
		||||
// #define MITSUBISHI_DOUBLE_SPACE_USECS  800  // usually ssee 713 - not using ticks as get number wrapround
 | 
			
		||||
// #define MITSUBISHI_RPT_LENGTH 45000
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_MITSUBISHI
 | 
			
		||||
bool  IRrecv::decodeMitsubishi (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
  // Serial.print("?!? decoding Mitsubishi:");Serial.print(irparams.rawlen); Serial.print(" want "); Serial.println( 2 * MITSUBISHI_BITS + 2);
 | 
			
		||||
  long data = 0;
 | 
			
		||||
  if (irparams.rawlen < 2 * MITSUBISHI_BITS + 2)  return false ;
 | 
			
		||||
  int offset = 0; // Skip first space
 | 
			
		||||
  // Initial space
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  // Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay
 | 
			
		||||
  Serial.print("IR Gap: ");
 | 
			
		||||
  Serial.println( results->rawbuf[offset]);
 | 
			
		||||
  Serial.println( "test against:");
 | 
			
		||||
  Serial.println(results->rawbuf[offset]);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  // Not seeing double keys from Mitsubishi
 | 
			
		||||
  if (results->rawbuf[offset] < MITSUBISHI_DOUBLE_SPACE_USECS) {
 | 
			
		||||
    // Serial.print("IR Gap found: ");
 | 
			
		||||
    results->bits = 0;
 | 
			
		||||
    results->value = REPEAT;
 | 
			
		||||
    results->decode_type = MITSUBISHI;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  offset++;
 | 
			
		||||
 | 
			
		||||
  // Typical
 | 
			
		||||
  // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7
 | 
			
		||||
 | 
			
		||||
  // Initial Space
 | 
			
		||||
  if (!MATCH_MARK(results->rawbuf[offset], MITSUBISHI_HDR_SPACE))  return false ;
 | 
			
		||||
  offset++;
 | 
			
		||||
 | 
			
		||||
  while (offset + 1 < irparams.rawlen) {
 | 
			
		||||
    if      (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ONE_MARK))   data = (data << 1) | 1 ;
 | 
			
		||||
    else if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ZERO_MARK))  data <<= 1 ;
 | 
			
		||||
    else                                                                 return false ;
 | 
			
		||||
    offset++;
 | 
			
		||||
 | 
			
		||||
    if (!MATCH_SPACE(results->rawbuf[offset], MITSUBISHI_HDR_SPACE))  break ;
 | 
			
		||||
    offset++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Success
 | 
			
		||||
  results->bits = (offset - 1) / 2;
 | 
			
		||||
  if (results->bits < MITSUBISHI_BITS) {
 | 
			
		||||
    results->bits = 0;
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  results->value       = data;
 | 
			
		||||
  results->decode_type = MITSUBISHI;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										98
									
								
								IRremote/ir_NEC.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								IRremote/ir_NEC.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                           N   N  EEEEE   CCCC
 | 
			
		||||
//                           NN  N  E      C
 | 
			
		||||
//                           N N N  EEE    C
 | 
			
		||||
//                           N  NN  E      C
 | 
			
		||||
//                           N   N  EEEEE   CCCC
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define NEC_BITS          32
 | 
			
		||||
#define NEC_HDR_MARK    9000
 | 
			
		||||
#define NEC_HDR_SPACE   4500
 | 
			
		||||
#define NEC_BIT_MARK     560
 | 
			
		||||
#define NEC_ONE_SPACE   1690
 | 
			
		||||
#define NEC_ZERO_SPACE   560
 | 
			
		||||
#define NEC_RPT_SPACE   2250
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_NEC
 | 
			
		||||
void  IRsend::sendNEC (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(NEC_HDR_MARK);
 | 
			
		||||
	space(NEC_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(NEC_BIT_MARK);
 | 
			
		||||
			space(NEC_ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(NEC_BIT_MARK);
 | 
			
		||||
			space(NEC_ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
	mark(NEC_BIT_MARK);
 | 
			
		||||
	space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// NECs have a repeat only 4 items long
 | 
			
		||||
//
 | 
			
		||||
#if DECODE_NEC
 | 
			
		||||
bool  IRrecv::decodeNEC (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  data   = 0;  // We decode in to here; Start with nothing
 | 
			
		||||
	int   offset = 1;  // Index in to results; Skip first entry!?
 | 
			
		||||
 | 
			
		||||
	// Check header "mark"
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK))  return false ;
 | 
			
		||||
	offset++;
 | 
			
		||||
 | 
			
		||||
	// Check for repeat
 | 
			
		||||
	if ( (irparams.rawlen == 4)
 | 
			
		||||
	    && MATCH_SPACE(results->rawbuf[offset  ], NEC_RPT_SPACE)
 | 
			
		||||
	    && MATCH_MARK (results->rawbuf[offset+1], NEC_BIT_MARK )
 | 
			
		||||
	   ) {
 | 
			
		||||
		results->bits        = 0;
 | 
			
		||||
		results->value       = REPEAT;
 | 
			
		||||
		results->decode_type = NEC;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check we have enough data
 | 
			
		||||
	if (irparams.rawlen < (2 * NEC_BITS) + 4)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Check header "space"
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE))  return false ;
 | 
			
		||||
	offset++;
 | 
			
		||||
 | 
			
		||||
	// Build the data
 | 
			
		||||
	for (int i = 0;  i < NEC_BITS;  i++) {
 | 
			
		||||
		// Check data "mark"
 | 
			
		||||
		if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK))  return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
        // Suppend this bit
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE ))  data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                            return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = NEC_BITS;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = NEC;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										78
									
								
								IRremote/ir_Panasonic.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								IRremote/ir_Panasonic.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//       PPPP    AAA   N   N   AAA    SSSS   OOO   N   N  IIIII   CCCC
 | 
			
		||||
//       P   P  A   A  NN  N  A   A  S      O   O  NN  N    I    C
 | 
			
		||||
//       PPPP   AAAAA  N N N  AAAAA   SSS   O   O  N N N    I    C
 | 
			
		||||
//       P      A   A  N  NN  A   A      S  O   O  N  NN    I    C
 | 
			
		||||
//       P      A   A  N   N  A   A  SSSS    OOO   N   N  IIIII   CCCC
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define PANASONIC_BITS          48
 | 
			
		||||
#define PANASONIC_HDR_MARK    3502
 | 
			
		||||
#define PANASONIC_HDR_SPACE   1750
 | 
			
		||||
#define PANASONIC_BIT_MARK     502
 | 
			
		||||
#define PANASONIC_ONE_SPACE   1244
 | 
			
		||||
#define PANASONIC_ZERO_SPACE   400
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_PANASONIC
 | 
			
		||||
void  IRsend::sendPanasonic (unsigned int address,  unsigned long data)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(35);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(PANASONIC_HDR_MARK);
 | 
			
		||||
	space(PANASONIC_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Address
 | 
			
		||||
	for (unsigned long  mask = 1UL << (16 - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		mark(PANASONIC_BIT_MARK);
 | 
			
		||||
		if (address & mask)  space(PANASONIC_ONE_SPACE) ;
 | 
			
		||||
		else                 space(PANASONIC_ZERO_SPACE) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (32 - 1);  mask;  mask >>= 1) {
 | 
			
		||||
        mark(PANASONIC_BIT_MARK);
 | 
			
		||||
        if (data & mask)  space(PANASONIC_ONE_SPACE) ;
 | 
			
		||||
        else              space(PANASONIC_ZERO_SPACE) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
    mark(PANASONIC_BIT_MARK);
 | 
			
		||||
    space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_PANASONIC
 | 
			
		||||
bool  IRrecv::decodePanasonic (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
    unsigned long long  data   = 0;
 | 
			
		||||
    int                 offset = 1;
 | 
			
		||||
 | 
			
		||||
    if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_HDR_MARK ))  return false ;
 | 
			
		||||
    if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
    // decode address
 | 
			
		||||
    for (int i = 0;  i < PANASONIC_BITS;  i++) {
 | 
			
		||||
        if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
        if      (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ONE_SPACE ))  data = (data << 1) | 1 ;
 | 
			
		||||
        else if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
        else                                                                 return false ;
 | 
			
		||||
        offset++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    results->value       = (unsigned long)data;
 | 
			
		||||
    results->address     = (unsigned int)(data >> 32);
 | 
			
		||||
    results->decode_type = PANASONIC;
 | 
			
		||||
    results->bits        = PANASONIC_BITS;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										207
									
								
								IRremote/ir_RC5_RC6.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								IRremote/ir_RC5_RC6.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,207 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Gets one undecoded level at a time from the raw buffer.
 | 
			
		||||
// The RC5/6 decoding is easier if the data is broken into time intervals.
 | 
			
		||||
// E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
 | 
			
		||||
// successive calls to getRClevel will return MARK, MARK, SPACE.
 | 
			
		||||
// offset and used are updated to keep track of the current position.
 | 
			
		||||
// t1 is the time interval for a single bit in microseconds.
 | 
			
		||||
// Returns -1 for error (measured time interval is not a multiple of t1).
 | 
			
		||||
//
 | 
			
		||||
#if (DECODE_RC5 || DECODE_RC6)
 | 
			
		||||
int  IRrecv::getRClevel (decode_results *results,  int *offset,  int *used,  int t1)
 | 
			
		||||
{
 | 
			
		||||
	int  width;
 | 
			
		||||
	int  val;
 | 
			
		||||
	int  correction;
 | 
			
		||||
	int  avail;
 | 
			
		||||
 | 
			
		||||
	if (*offset >= results->rawlen)  return SPACE ;  // After end of recorded buffer, assume SPACE.
 | 
			
		||||
	width      = results->rawbuf[*offset];
 | 
			
		||||
	val        = ((*offset) % 2) ? MARK : SPACE;
 | 
			
		||||
	correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
 | 
			
		||||
 | 
			
		||||
	if      (MATCH(width, (  t1) + correction))  avail = 1 ;
 | 
			
		||||
	else if (MATCH(width, (2*t1) + correction))  avail = 2 ;
 | 
			
		||||
	else if (MATCH(width, (3*t1) + correction))  avail = 3 ;
 | 
			
		||||
	else                                         return -1 ;
 | 
			
		||||
 | 
			
		||||
	(*used)++;
 | 
			
		||||
	if (*used >= avail) {
 | 
			
		||||
		*used = 0;
 | 
			
		||||
		(*offset)++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DBG_PRINTLN( (val == MARK) ? "MARK" : "SPACE" );
 | 
			
		||||
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
// RRRR    CCCC  55555
 | 
			
		||||
// R   R  C      5
 | 
			
		||||
// RRRR   C      5555
 | 
			
		||||
// R  R   C          5
 | 
			
		||||
// R   R   CCCC  5555
 | 
			
		||||
//
 | 
			
		||||
// NB: First bit must be a one (start bit)
 | 
			
		||||
//
 | 
			
		||||
#define MIN_RC5_SAMPLES     11
 | 
			
		||||
#define RC5_T1             889
 | 
			
		||||
#define RC5_RPT_LENGTH   46000
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_RC5
 | 
			
		||||
void  IRsend::sendRC5 (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(36);
 | 
			
		||||
 | 
			
		||||
	// Start
 | 
			
		||||
	mark(RC5_T1);
 | 
			
		||||
	space(RC5_T1);
 | 
			
		||||
	mark(RC5_T1);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			space(RC5_T1); // 1 is space, then mark
 | 
			
		||||
			mark(RC5_T1);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(RC5_T1);
 | 
			
		||||
			space(RC5_T1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_RC5
 | 
			
		||||
bool  IRrecv::decodeRC5 (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	int   nbits;
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   used   = 0;
 | 
			
		||||
	int   offset = 1;  // Skip gap space
 | 
			
		||||
 | 
			
		||||
	if (irparams.rawlen < MIN_RC5_SAMPLES + 2)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Get start bits
 | 
			
		||||
	if (getRClevel(results, &offset, &used, RC5_T1) != MARK)   return false ;
 | 
			
		||||
	if (getRClevel(results, &offset, &used, RC5_T1) != SPACE)  return false ;
 | 
			
		||||
	if (getRClevel(results, &offset, &used, RC5_T1) != MARK)   return false ;
 | 
			
		||||
 | 
			
		||||
	for (nbits = 0;  offset < irparams.rawlen;  nbits++) {
 | 
			
		||||
		int  levelA = getRClevel(results, &offset, &used, RC5_T1);
 | 
			
		||||
		int  levelB = getRClevel(results, &offset, &used, RC5_T1);
 | 
			
		||||
 | 
			
		||||
		if      ((levelA == SPACE) && (levelB == MARK ))  data = (data << 1) | 1 ;
 | 
			
		||||
		else if ((levelA == MARK ) && (levelB == SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                              return false ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = nbits;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = RC5;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// RRRR    CCCC   6666
 | 
			
		||||
// R   R  C      6
 | 
			
		||||
// RRRR   C      6666
 | 
			
		||||
// R  R   C      6   6
 | 
			
		||||
// R   R   CCCC   666
 | 
			
		||||
//
 | 
			
		||||
// NB : Caller needs to take care of flipping the toggle bit
 | 
			
		||||
//
 | 
			
		||||
#define MIN_RC6_SAMPLES      1
 | 
			
		||||
#define RC6_HDR_MARK      2666
 | 
			
		||||
#define RC6_HDR_SPACE      889
 | 
			
		||||
#define RC6_T1             444
 | 
			
		||||
#define RC6_RPT_LENGTH   46000
 | 
			
		||||
 | 
			
		||||
#if SEND_RC6
 | 
			
		||||
void  IRsend::sendRC6 (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(36);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(RC6_HDR_MARK);
 | 
			
		||||
	space(RC6_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Start bit
 | 
			
		||||
	mark(RC6_T1);
 | 
			
		||||
	space(RC6_T1);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  i = 1, mask = 1UL << (nbits - 1);  mask;  i++, mask >>= 1) {
 | 
			
		||||
		// The fourth bit we send is a "double width trailer bit"
 | 
			
		||||
		int  t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1) ;
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(t);
 | 
			
		||||
			space(t);
 | 
			
		||||
		} else {
 | 
			
		||||
			space(t);
 | 
			
		||||
			mark(t);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_RC6
 | 
			
		||||
bool  IRrecv::decodeRC6 (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	int   nbits;
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   used   = 0;
 | 
			
		||||
	int   offset = 1;  // Skip first space
 | 
			
		||||
 | 
			
		||||
	if (results->rawlen < MIN_RC6_SAMPLES)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Initial mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset++],  RC6_HDR_MARK))   return false ;
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], RC6_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	// Get start bit (1)
 | 
			
		||||
	if (getRClevel(results, &offset, &used, RC6_T1) != MARK)   return false ;
 | 
			
		||||
	if (getRClevel(results, &offset, &used, RC6_T1) != SPACE)  return false ;
 | 
			
		||||
 | 
			
		||||
	for (nbits = 0;  offset < results->rawlen;  nbits++) {
 | 
			
		||||
		int  levelA, levelB;  // Next two levels
 | 
			
		||||
 | 
			
		||||
		levelA = getRClevel(results, &offset, &used, RC6_T1);
 | 
			
		||||
		if (nbits == 3) {
 | 
			
		||||
			// T bit is double wide; make sure second half matches
 | 
			
		||||
			if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		levelB = getRClevel(results, &offset, &used, RC6_T1);
 | 
			
		||||
		if (nbits == 3) {
 | 
			
		||||
			// T bit is double wide; make sure second half matches
 | 
			
		||||
			if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if      ((levelA == MARK ) && (levelB == SPACE))  data = (data << 1) | 1 ;  // inverted compared to RC5
 | 
			
		||||
		else if ((levelA == SPACE) && (levelB == MARK ))  data = (data << 1) | 0 ;  // ...
 | 
			
		||||
		else                                              return false ;            // Error
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = nbits;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = RC6;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										92
									
								
								IRremote/ir_Samsung.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								IRremote/ir_Samsung.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//              SSSS   AAA    MMM    SSSS  U   U  N   N   GGGG
 | 
			
		||||
//             S      A   A  M M M  S      U   U  NN  N  G
 | 
			
		||||
//              SSS   AAAAA  M M M   SSS   U   U  N N N  G  GG
 | 
			
		||||
//                 S  A   A  M   M      S  U   U  N  NN  G   G
 | 
			
		||||
//             SSSS   A   A  M   M  SSSS    UUU   N   N   GGG
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define SAMSUNG_BITS          32
 | 
			
		||||
#define SAMSUNG_HDR_MARK    5000
 | 
			
		||||
#define SAMSUNG_HDR_SPACE   5000
 | 
			
		||||
#define SAMSUNG_BIT_MARK     560
 | 
			
		||||
#define SAMSUNG_ONE_SPACE   1600
 | 
			
		||||
#define SAMSUNG_ZERO_SPACE   560
 | 
			
		||||
#define SAMSUNG_RPT_SPACE   2250
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_SAMSUNG
 | 
			
		||||
void  IRsend::sendSAMSUNG (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(SAMSUNG_HDR_MARK);
 | 
			
		||||
	space(SAMSUNG_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(SAMSUNG_BIT_MARK);
 | 
			
		||||
			space(SAMSUNG_ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(SAMSUNG_BIT_MARK);
 | 
			
		||||
			space(SAMSUNG_ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
	mark(SAMSUNG_BIT_MARK);
 | 
			
		||||
    space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// SAMSUNGs have a repeat only 4 items long
 | 
			
		||||
//
 | 
			
		||||
#if DECODE_SAMSUNG
 | 
			
		||||
bool  IRrecv::decodeSAMSUNG (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   offset = 1;  // Skip first space
 | 
			
		||||
 | 
			
		||||
	// Initial mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_HDR_MARK))   return false ;
 | 
			
		||||
	offset++;
 | 
			
		||||
 | 
			
		||||
	// Check for repeat
 | 
			
		||||
	if (    (irparams.rawlen == 4)
 | 
			
		||||
	     && MATCH_SPACE(results->rawbuf[offset], SAMSUNG_RPT_SPACE)
 | 
			
		||||
	     && MATCH_MARK(results->rawbuf[offset+1], SAMSUNG_BIT_MARK)
 | 
			
		||||
	   ) {
 | 
			
		||||
		results->bits        = 0;
 | 
			
		||||
		results->value       = REPEAT;
 | 
			
		||||
		results->decode_type = SAMSUNG;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	if (irparams.rawlen < (2 * SAMSUNG_BITS) + 4)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Initial space
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], SAMSUNG_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0;  i < SAMSUNG_BITS;   i++) {
 | 
			
		||||
		if (!MATCH_MARK(results->rawbuf[offset++], SAMSUNG_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ONE_SPACE))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                                return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = SAMSUNG_BITS;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = SAMSUNG;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								IRremote/ir_Sanyo.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								IRremote/ir_Sanyo.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                      SSSS   AAA   N   N  Y   Y   OOO
 | 
			
		||||
//                     S      A   A  NN  N   Y Y   O   O
 | 
			
		||||
//                      SSS   AAAAA  N N N    Y    O   O
 | 
			
		||||
//                         S  A   A  N  NN    Y    O   O
 | 
			
		||||
//                     SSSS   A   A  N   N    Y     OOO
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
// I think this is a Sanyo decoder:  Serial = SA 8650B
 | 
			
		||||
// Looks like Sony except for timings, 48 chars of data and time/space different
 | 
			
		||||
 | 
			
		||||
#define SANYO_BITS                   12
 | 
			
		||||
#define SANYO_HDR_MARK	           3500  // seen range 3500
 | 
			
		||||
#define SANYO_HDR_SPACE	            950  // seen 950
 | 
			
		||||
#define SANYO_ONE_MARK	           2400  // seen 2400
 | 
			
		||||
#define SANYO_ZERO_MARK             700  // seen 700
 | 
			
		||||
#define SANYO_DOUBLE_SPACE_USECS    800  // usually ssee 713 - not using ticks as get number wrapround
 | 
			
		||||
#define SANYO_RPT_LENGTH          45000
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_SANYO
 | 
			
		||||
bool  IRrecv::decodeSanyo (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   offset = 0;  // Skip first space  <-- CHECK THIS!
 | 
			
		||||
 | 
			
		||||
	if (irparams.rawlen < (2 * SANYO_BITS) + 2)  return false ;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	// Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay
 | 
			
		||||
	Serial.print("IR Gap: ");
 | 
			
		||||
	Serial.println( results->rawbuf[offset]);
 | 
			
		||||
	Serial.println( "test against:");
 | 
			
		||||
	Serial.println(results->rawbuf[offset]);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	// Initial space
 | 
			
		||||
	if (results->rawbuf[offset] < SANYO_DOUBLE_SPACE_USECS) {
 | 
			
		||||
		//Serial.print("IR Gap found: ");
 | 
			
		||||
		results->bits        = 0;
 | 
			
		||||
		results->value       = REPEAT;
 | 
			
		||||
		results->decode_type = SANYO;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	offset++;
 | 
			
		||||
 | 
			
		||||
	// Initial mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset++], SANYO_HDR_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
	// Skip Second Mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset++], SANYO_HDR_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
	while (offset + 1 < irparams.rawlen) {
 | 
			
		||||
		if (!MATCH_SPACE(results->rawbuf[offset++], SANYO_HDR_SPACE))  break ;
 | 
			
		||||
 | 
			
		||||
		if      (MATCH_MARK(results->rawbuf[offset], SANYO_ONE_MARK))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_MARK(results->rawbuf[offset], SANYO_ZERO_MARK))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                            return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits = (offset - 1) / 2;
 | 
			
		||||
	if (results->bits < 12) {
 | 
			
		||||
		results->bits = 0;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = SANYO;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										71
									
								
								IRremote/ir_Sharp.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								IRremote/ir_Sharp.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                       SSSS  H   H   AAA   RRRR   PPPP
 | 
			
		||||
//                      S      H   H  A   A  R   R  P   P
 | 
			
		||||
//                       SSS   HHHHH  AAAAA  RRRR   PPPP
 | 
			
		||||
//                          S  H   H  A   A  R  R   P
 | 
			
		||||
//                      SSSS   H   H  A   A  R   R  P
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
// Sharp and DISH support by Todd Treece: http://unionbridge.org/design/ircommand
 | 
			
		||||
//
 | 
			
		||||
// The send function has the necessary repeat built in because of the need to
 | 
			
		||||
// invert the signal.
 | 
			
		||||
//
 | 
			
		||||
// Sharp protocol documentation:
 | 
			
		||||
//   http://www.sbprojects.com/knowledge/ir/sharp.htm
 | 
			
		||||
//
 | 
			
		||||
// Here is the LIRC file I found that seems to match the remote codes from the
 | 
			
		||||
// oscilloscope:
 | 
			
		||||
//   Sharp LCD TV:
 | 
			
		||||
//   http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
 | 
			
		||||
 | 
			
		||||
#define SHARP_BITS             15
 | 
			
		||||
#define SHARP_BIT_MARK        245
 | 
			
		||||
#define SHARP_ONE_SPACE      1805
 | 
			
		||||
#define SHARP_ZERO_SPACE      795
 | 
			
		||||
#define SHARP_GAP          600000
 | 
			
		||||
#define SHARP_RPT_SPACE      3000
 | 
			
		||||
 | 
			
		||||
#define SHARP_TOGGLE_MASK  0x3FF
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_SHARP
 | 
			
		||||
void  IRsend::sendSharpRaw (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Sending codes in bursts of 3 (normal, inverted, normal) makes transmission
 | 
			
		||||
	// much more reliable. That's the exact behaviour of CD-S6470 remote control.
 | 
			
		||||
	for (int n = 0;  n < 3;  n++) {
 | 
			
		||||
		for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
			if (data & mask) {
 | 
			
		||||
				mark(SHARP_BIT_MARK);
 | 
			
		||||
				space(SHARP_ONE_SPACE);
 | 
			
		||||
			} else {
 | 
			
		||||
				mark(SHARP_BIT_MARK);
 | 
			
		||||
				space(SHARP_ZERO_SPACE);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mark(SHARP_BIT_MARK);
 | 
			
		||||
		space(SHARP_ZERO_SPACE);
 | 
			
		||||
		delay(40);
 | 
			
		||||
 | 
			
		||||
		data = data ^ SHARP_TOGGLE_MASK;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// Sharp send compatible with data obtained through decodeSharp()
 | 
			
		||||
//                                                  ^^^^^^^^^^^^^ FUNCTION MISSING!
 | 
			
		||||
//
 | 
			
		||||
#if SEND_SHARP
 | 
			
		||||
void  IRsend::sendSharp (unsigned int address,  unsigned int command)
 | 
			
		||||
{
 | 
			
		||||
	sendSharpRaw((address << 10) | (command << 2) | 2, SHARP_BITS);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										95
									
								
								IRremote/ir_Sony.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								IRremote/ir_Sony.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//                           SSSS   OOO   N   N  Y   Y
 | 
			
		||||
//                          S      O   O  NN  N   Y Y
 | 
			
		||||
//                           SSS   O   O  N N N    Y
 | 
			
		||||
//                              S  O   O  N  NN    Y
 | 
			
		||||
//                          SSSS    OOO   N   N    Y
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define SONY_BITS                   12
 | 
			
		||||
#define SONY_HDR_MARK             2400
 | 
			
		||||
#define SONY_HDR_SPACE             600
 | 
			
		||||
#define SONY_ONE_MARK             1200
 | 
			
		||||
#define SONY_ZERO_MARK             600
 | 
			
		||||
#define SONY_RPT_LENGTH          45000
 | 
			
		||||
#define SONY_DOUBLE_SPACE_USECS    500  // usually ssee 713 - not using ticks as get number wrapround
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_SONY
 | 
			
		||||
void  IRsend::sendSony (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(40);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(SONY_HDR_MARK);
 | 
			
		||||
	space(SONY_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(SONY_ONE_MARK);
 | 
			
		||||
			space(SONY_HDR_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(SONY_ZERO_MARK);
 | 
			
		||||
			space(SONY_HDR_SPACE);
 | 
			
		||||
    	}
 | 
			
		||||
  	}
 | 
			
		||||
 | 
			
		||||
	// We will have ended with LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_SONY
 | 
			
		||||
bool  IRrecv::decodeSony (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   offset = 0;  // Dont skip first space, check its size
 | 
			
		||||
 | 
			
		||||
	if (irparams.rawlen < (2 * SONY_BITS) + 2)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Some Sony's deliver repeats fast after first
 | 
			
		||||
	// unfortunately can't spot difference from of repeat from two fast clicks
 | 
			
		||||
	if (results->rawbuf[offset] < SONY_DOUBLE_SPACE_USECS) {
 | 
			
		||||
		// Serial.print("IR Gap found: ");
 | 
			
		||||
		results->bits = 0;
 | 
			
		||||
		results->value = REPEAT;
 | 
			
		||||
 | 
			
		||||
#	ifdef DECODE_SANYO
 | 
			
		||||
		results->decode_type = SANYO;
 | 
			
		||||
#	else
 | 
			
		||||
		results->decode_type = UNKNOWN;
 | 
			
		||||
#	endif
 | 
			
		||||
 | 
			
		||||
	    return true;
 | 
			
		||||
	}
 | 
			
		||||
	offset++;
 | 
			
		||||
 | 
			
		||||
	// Initial mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset++], SONY_HDR_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
	while (offset + 1 < irparams.rawlen) {
 | 
			
		||||
		if (!MATCH_SPACE(results->rawbuf[offset++], SONY_HDR_SPACE))  break ;
 | 
			
		||||
 | 
			
		||||
		if      (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                           return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits = (offset - 1) / 2;
 | 
			
		||||
	if (results->bits < 12) {
 | 
			
		||||
		results->bits = 0;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = SONY;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										179
									
								
								IRremote/ir_Template.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								IRremote/ir_Template.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
			
		||||
/*
 | 
			
		||||
Assuming the protocol we are adding is for the (imaginary) manufacturer:  Shuzu
 | 
			
		||||
 | 
			
		||||
Our fantasy protocol is a standard protocol, so we can use this standard
 | 
			
		||||
template without too much work. Some protocols are quite unique and will require
 | 
			
		||||
considerably more work in this file! It is way beyond the scope of this text to
 | 
			
		||||
explain how to reverse engineer "unusual" IR protocols. But, unless you own an
 | 
			
		||||
oscilloscope, the starting point is probably to use the rawDump.ino sketch and
 | 
			
		||||
try to spot the pattern!
 | 
			
		||||
 | 
			
		||||
Before you start, make sure the IR library is working OK:
 | 
			
		||||
  # Open up the Arduino IDE
 | 
			
		||||
  # Load up the rawDump.ino example sketch
 | 
			
		||||
  # Run it
 | 
			
		||||
 | 
			
		||||
Now we can start to add our new protocol...
 | 
			
		||||
 | 
			
		||||
1. Copy this file to : ir_Shuzu.cpp
 | 
			
		||||
 | 
			
		||||
2. Replace all occurrences of "Shuzu" with the name of your protocol.
 | 
			
		||||
 | 
			
		||||
3. Tweak the #defines to suit your protocol.
 | 
			
		||||
 | 
			
		||||
4. If you're lucky, tweaking the #defines will make the default send() function
 | 
			
		||||
   work.
 | 
			
		||||
 | 
			
		||||
5. Again, if you're lucky, tweaking the #defines will have made the default
 | 
			
		||||
   decode() function work.
 | 
			
		||||
 | 
			
		||||
You have written the code to support your new protocol!
 | 
			
		||||
 | 
			
		||||
Now you must do a few things to add it to the IRremote system:
 | 
			
		||||
 | 
			
		||||
1. Open IRremote.h and make the following changes:
 | 
			
		||||
   REMEMEBER to change occurences of "SHUZU" with the name of your protocol
 | 
			
		||||
 | 
			
		||||
   A. At the top, in the section "Supported Protocols", add:
 | 
			
		||||
      #define DECODE_SHUZU  1
 | 
			
		||||
      #define SEND_SHUZU    1
 | 
			
		||||
 | 
			
		||||
   B. In the section "enumerated list of all supported formats", add:
 | 
			
		||||
      SHUZU,
 | 
			
		||||
      to the end of the list (notice there is a comma after the protocol name)
 | 
			
		||||
 | 
			
		||||
   C. Further down in "Main class for receiving IR", add:
 | 
			
		||||
      //......................................................................
 | 
			
		||||
      #if DECODE_SHUZU
 | 
			
		||||
          bool  decodeShuzu (decode_results *results) ;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
   D. Further down in "Main class for sending IR", add:
 | 
			
		||||
      //......................................................................
 | 
			
		||||
      #if SEND_SHUZU
 | 
			
		||||
          void  sendShuzu (unsigned long data,  int nbits) ;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
   E. Save your changes and close the file
 | 
			
		||||
 | 
			
		||||
2. Now open irRecv.cpp and make the following change:
 | 
			
		||||
 | 
			
		||||
   A. In the function IRrecv::decode(), add:
 | 
			
		||||
      #ifdef DECODE_NEC
 | 
			
		||||
          DBG_PRINTLN("Attempting Shuzu decode");
 | 
			
		||||
          if (decodeShuzu(results))  return true ;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
   B. Save your changes and close the file
 | 
			
		||||
 | 
			
		||||
You will probably want to add your new protocol to the example sketch
 | 
			
		||||
 | 
			
		||||
3. Open MyDocuments\Arduino\libraries\IRremote\examples\IRrecvDumpV2.ino
 | 
			
		||||
 | 
			
		||||
   A. In the encoding() function, add:
 | 
			
		||||
      case SHUZU:    Serial.print("SHUZU");     break ;
 | 
			
		||||
 | 
			
		||||
Now open the Arduino IDE, load up the rawDump.ino sketch, and run it.
 | 
			
		||||
Hopefully it will compile and upload.
 | 
			
		||||
If it doesn't, you've done something wrong. Check your work.
 | 
			
		||||
If you can't get it to work - seek help from somewhere.
 | 
			
		||||
 | 
			
		||||
If you get this far, I will assume you have successfully added your new protocol
 | 
			
		||||
There is one last thing to do.
 | 
			
		||||
 | 
			
		||||
1. Delete this giant instructional comment.
 | 
			
		||||
 | 
			
		||||
2. Send a copy of your work to us so we can include it in the library and
 | 
			
		||||
   others may benefit from your hard work and maybe even write a song about how
 | 
			
		||||
   great you are for helping them! :)
 | 
			
		||||
 | 
			
		||||
Regards,
 | 
			
		||||
  BlueChip
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//                              S H U Z U
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define BITS          32  // The number of bits in the command
 | 
			
		||||
 | 
			
		||||
#define HDR_MARK    1000  // The length of the Header:Mark
 | 
			
		||||
#define HDR_SPACE   2000  // The lenght of the Header:Space
 | 
			
		||||
 | 
			
		||||
#define BIT_MARK    3000  // The length of a Bit:Mark
 | 
			
		||||
#define ONE_SPACE   4000  // The length of a Bit:Space for 1's
 | 
			
		||||
#define ZERO_SPACE  5000  // The length of a Bit:Space for 0's
 | 
			
		||||
 | 
			
		||||
#define OTHER       1234  // Other things you may need to define
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
#if SEND_SHUZU
 | 
			
		||||
void  IRsend::sendShuzu (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark (HDR_MARK);
 | 
			
		||||
	space(HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark (BIT_MARK);
 | 
			
		||||
			space(ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark (BIT_MARK);
 | 
			
		||||
			space(ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
	mark(BIT_MARK);
 | 
			
		||||
    space(0);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
//
 | 
			
		||||
#if DECODE_SHUZU
 | 
			
		||||
bool  IRrecv::decodeShuzu (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long  data   = 0;  // Somewhere to build our code
 | 
			
		||||
	int            offset = 1;  // Skip the Gap reading
 | 
			
		||||
 | 
			
		||||
	// Check we have the right amount of data
 | 
			
		||||
	if (irparams.rawlen != 1 + 2 + (2 * BITS) + 1)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Check initial Mark+Space match
 | 
			
		||||
	if (!MATCH_MARK (results->rawbuf[offset++], HDR_MARK ))  return false ;
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	// Read the bits in
 | 
			
		||||
	for (int i = 0;  i < SHUZU_BITS;  i++) {
 | 
			
		||||
		// Each bit looks like: MARK + SPACE_1 -> 1
 | 
			
		||||
		//                 or : MARK + SPACE_0 -> 0
 | 
			
		||||
		if (!MATCH_MARK(results->rawbuf[offset++], BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
		// IR data is big-endian, so we shuffle it in from the right:
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], ONE_SPACE))   data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                        return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits        = BITS;
 | 
			
		||||
	results->value       = data;
 | 
			
		||||
	results->decode_type = SHUZU;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										91
									
								
								IRremote/ir_Whynter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								IRremote/ir_Whynter.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//               W   W  H   H  Y   Y N   N TTTTT EEEEE  RRRRR
 | 
			
		||||
//               W   W  H   H   Y Y  NN  N   T   E      R   R
 | 
			
		||||
//               W W W  HHHHH    Y   N N N   T   EEE    RRRR
 | 
			
		||||
//               W W W  H   H    Y   N  NN   T   E      R  R
 | 
			
		||||
//                WWW   H   H    Y   N   N   T   EEEEE  R   R
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#define WHYNTER_BITS          32
 | 
			
		||||
#define WHYNTER_HDR_MARK    2850
 | 
			
		||||
#define WHYNTER_HDR_SPACE   2850
 | 
			
		||||
#define WHYNTER_BIT_MARK     750
 | 
			
		||||
#define WHYNTER_ONE_MARK     750
 | 
			
		||||
#define WHYNTER_ONE_SPACE   2150
 | 
			
		||||
#define WHYNTER_ZERO_MARK    750
 | 
			
		||||
#define WHYNTER_ZERO_SPACE   750
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if SEND_WHYNTER
 | 
			
		||||
void  IRsend::sendWhynter (unsigned long data,  int nbits)
 | 
			
		||||
{
 | 
			
		||||
	// Set IR carrier frequency
 | 
			
		||||
	enableIROut(38);
 | 
			
		||||
 | 
			
		||||
	// Start
 | 
			
		||||
	mark(WHYNTER_ZERO_MARK);
 | 
			
		||||
	space(WHYNTER_ZERO_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Header
 | 
			
		||||
	mark(WHYNTER_HDR_MARK);
 | 
			
		||||
	space(WHYNTER_HDR_SPACE);
 | 
			
		||||
 | 
			
		||||
	// Data
 | 
			
		||||
	for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
 | 
			
		||||
		if (data & mask) {
 | 
			
		||||
			mark(WHYNTER_ONE_MARK);
 | 
			
		||||
			space(WHYNTER_ONE_SPACE);
 | 
			
		||||
		} else {
 | 
			
		||||
			mark(WHYNTER_ZERO_MARK);
 | 
			
		||||
			space(WHYNTER_ZERO_SPACE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Footer
 | 
			
		||||
	mark(WHYNTER_ZERO_MARK);
 | 
			
		||||
	space(WHYNTER_ZERO_SPACE);  // Always end with the LED off
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
#if DECODE_WHYNTER
 | 
			
		||||
bool  IRrecv::decodeWhynter (decode_results *results)
 | 
			
		||||
{
 | 
			
		||||
	long  data   = 0;
 | 
			
		||||
	int   offset = 1;  // skip initial space
 | 
			
		||||
 | 
			
		||||
	// Check we have the right amount of data
 | 
			
		||||
	if (irparams.rawlen < (2 * WHYNTER_BITS) + 6)  return false ;
 | 
			
		||||
 | 
			
		||||
	// Sequence begins with a bit mark and a zero space
 | 
			
		||||
	if (!MATCH_MARK (results->rawbuf[offset++], WHYNTER_BIT_MARK  ))  return false ;
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], WHYNTER_ZERO_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	// header mark and space
 | 
			
		||||
	if (!MATCH_MARK (results->rawbuf[offset++], WHYNTER_HDR_MARK ))  return false ;
 | 
			
		||||
	if (!MATCH_SPACE(results->rawbuf[offset++], WHYNTER_HDR_SPACE))  return false ;
 | 
			
		||||
 | 
			
		||||
	// data bits
 | 
			
		||||
	for (int i = 0;  i < WHYNTER_BITS;  i++) {
 | 
			
		||||
		if (!MATCH_MARK(results->rawbuf[offset++], WHYNTER_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
		if      (MATCH_SPACE(results->rawbuf[offset], WHYNTER_ONE_SPACE ))  data = (data << 1) | 1 ;
 | 
			
		||||
		else if (MATCH_SPACE(results->rawbuf[offset], WHYNTER_ZERO_SPACE))  data = (data << 1) | 0 ;
 | 
			
		||||
		else                                                                return false ;
 | 
			
		||||
		offset++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// trailing mark
 | 
			
		||||
	if (!MATCH_MARK(results->rawbuf[offset], WHYNTER_BIT_MARK))  return false ;
 | 
			
		||||
 | 
			
		||||
	// Success
 | 
			
		||||
	results->bits = WHYNTER_BITS;
 | 
			
		||||
	results->value = data;
 | 
			
		||||
	results->decode_type = WHYNTER;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								IRremote/library.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								IRremote/library.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "IRremote",
 | 
			
		||||
  "keywords": "infrared, ir, remote",
 | 
			
		||||
  "description": "Send and receive infrared signals with multiple protocols",
 | 
			
		||||
  "repository":
 | 
			
		||||
  {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "https://github.com/z3t0/Arduino-IRremote.git"
 | 
			
		||||
  },
 | 
			
		||||
  "version": "2.3.3",
 | 
			
		||||
  "frameworks": "arduino",
 | 
			
		||||
  "platforms": "atmelavr",
 | 
			
		||||
  "authors" :
 | 
			
		||||
  [
 | 
			
		||||
     {
 | 
			
		||||
       "name":"Rafi Khan",
 | 
			
		||||
       "email":"zetoslab@gmail.com"
 | 
			
		||||
     },
 | 
			
		||||
     {
 | 
			
		||||
       "name":"Ken Shirriff",
 | 
			
		||||
       "email":"ken.shirriff@gmail.com"
 | 
			
		||||
     }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								IRremote/library.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								IRremote/library.properties
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
name=IRremote
 | 
			
		||||
version=2.2.3
 | 
			
		||||
author=shirriff
 | 
			
		||||
maintainer=shirriff
 | 
			
		||||
sentence=Send and receive infrared signals with multiple protocols
 | 
			
		||||
paragraph=Send and receive infrared signals with multiple protocols
 | 
			
		||||
category=Signal Input/Output
 | 
			
		||||
url=https://github.com/shirriff/Arduino-IRremote.git
 | 
			
		||||
architectures=*
 | 
			
		||||
							
								
								
									
										102
									
								
								IRremote/sam.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								IRremote/sam.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
// Support routines for SAM processor boards
 | 
			
		||||
 | 
			
		||||
#include "IRremote.h"
 | 
			
		||||
#include "IRremoteInt.h"
 | 
			
		||||
 | 
			
		||||
#if defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
 | 
			
		||||
 | 
			
		||||
// "Idiot check"
 | 
			
		||||
#ifdef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
#error Must undef USE_DEFAULT_ENABLE_IR_IN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// ATSAMD Timer setup & IRQ functions
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// following based on setup from GitHub jdneo/timerInterrupt.ino
 | 
			
		||||
 | 
			
		||||
static void setTimerFrequency(int frequencyHz)
 | 
			
		||||
{
 | 
			
		||||
	int compareValue = (SYSCLOCK / (TIMER_PRESCALER_DIV * frequencyHz)) - 1;
 | 
			
		||||
	//Serial.println(compareValue);
 | 
			
		||||
	TcCount16* TC = (TcCount16*) TC3;
 | 
			
		||||
	// Make sure the count is in a proportional position to where it was
 | 
			
		||||
	// to prevent any jitter or disconnect when changing the compare value.
 | 
			
		||||
	TC->COUNT.reg = map(TC->COUNT.reg, 0, TC->CC[0].reg, 0, compareValue);
 | 
			
		||||
	TC->CC[0].reg = compareValue;
 | 
			
		||||
	//Serial.print("COUNT.reg ");
 | 
			
		||||
	//Serial.println(TC->COUNT.reg);
 | 
			
		||||
	//Serial.print("CC[0].reg ");
 | 
			
		||||
	//Serial.println(TC->CC[0].reg);
 | 
			
		||||
	while (TC->STATUS.bit.SYNCBUSY == 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void startTimer()
 | 
			
		||||
{
 | 
			
		||||
	REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3);
 | 
			
		||||
	while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync
 | 
			
		||||
 | 
			
		||||
	TcCount16* TC = (TcCount16*) TC3;
 | 
			
		||||
 | 
			
		||||
	TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
 | 
			
		||||
	while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
 | 
			
		||||
 | 
			
		||||
	// Use the 16-bit timer
 | 
			
		||||
	TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
 | 
			
		||||
	while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
 | 
			
		||||
 | 
			
		||||
	// Use match mode so that the timer counter resets when the count matches the compare register
 | 
			
		||||
	TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
 | 
			
		||||
	while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
 | 
			
		||||
 | 
			
		||||
	// Set prescaler to 1024
 | 
			
		||||
	//TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024;
 | 
			
		||||
	TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV64;
 | 
			
		||||
	while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
 | 
			
		||||
 | 
			
		||||
	setTimerFrequency(1000000 / USECPERTICK);
 | 
			
		||||
	
 | 
			
		||||
	// Enable the compare interrupt
 | 
			
		||||
	TC->INTENSET.reg = 0;
 | 
			
		||||
	TC->INTENSET.bit.MC0 = 1;
 | 
			
		||||
 | 
			
		||||
	NVIC_EnableIRQ(TC3_IRQn);
 | 
			
		||||
 | 
			
		||||
	TC->CTRLA.reg |= TC_CTRLA_ENABLE;
 | 
			
		||||
	while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//+=============================================================================
 | 
			
		||||
// initialization
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
void IRrecv::enableIRIn()
 | 
			
		||||
{
 | 
			
		||||
	// Interrupt Service Routine - Fires every 50uS
 | 
			
		||||
	//Serial.println("Starting timer");
 | 
			
		||||
	startTimer();
 | 
			
		||||
	//Serial.println("Started timer");
 | 
			
		||||
 | 
			
		||||
	// Initialize state machine variables
 | 
			
		||||
	irparams.rcvstate = STATE_IDLE;
 | 
			
		||||
	irparams.rawlen = 0;
 | 
			
		||||
 | 
			
		||||
	// Set pin modes
 | 
			
		||||
	pinMode(irparams.recvpin, INPUT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void irs(); // Defined in IRRemote as ISR(TIMER_INTR_NAME)
 | 
			
		||||
 | 
			
		||||
void TC3_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
	TcCount16* TC = (TcCount16*) TC3;
 | 
			
		||||
	// If this interrupt is due to the compare register matching the timer count
 | 
			
		||||
	// we toggle the LED.
 | 
			
		||||
	if (TC->INTFLAG.bit.MC0 == 1) {
 | 
			
		||||
		TC->INTFLAG.bit.MC0 = 1;
 | 
			
		||||
		irs();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
 | 
			
		||||
							
								
								
									
										211
									
								
								mecanum.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								mecanum.ino
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,211 @@
 | 
			
		||||
#include <boarddefs.h>
 | 
			
		||||
#include <IRremote.h>
 | 
			
		||||
#include <IRremoteInt.h>
 | 
			
		||||
#include <ir_Lego_PF_BitStreamEncoder.h>
 | 
			
		||||
#define IR 4
 | 
			
		||||
IRrecv irrecv(IR);
 | 
			
		||||
 | 
			
		||||
#define WHEEL_FRONT_LEFT_F A0
 | 
			
		||||
#define WHEEL_REAR_LEFT_R A1
 | 
			
		||||
#define WHEEL_REAR_RIGHT_F A2
 | 
			
		||||
#define WHEEL_FRONT_RIGHT_R A3
 | 
			
		||||
 | 
			
		||||
#define WHEEL_FRONT_LEFT_R 10
 | 
			
		||||
#define WHEEL_REAR_LEFT_F 9
 | 
			
		||||
#define WHEEL_FRONT_RIGHT_F 8
 | 
			
		||||
#define WHEEL_REAR_RIGHT_R 7
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 4060792887 ^
 | 
			
		||||
 * 4060752087 v
 | 
			
		||||
 * 4060768407 <
 | 
			
		||||
 * 4060784727 >
 | 
			
		||||
 * 4060801047 enter
 | 
			
		||||
 * 4060776567 menu
 | 
			
		||||
 * 4060774527 aspect
 | 
			
		||||
 * 4060745967 vol+
 | 
			
		||||
 * 4060794927 vol-
 | 
			
		||||
 * 4060803087 mute
 | 
			
		||||
 * 4060750047 source
 | 
			
		||||
 * 4060790847 video mode
 | 
			
		||||
 * 4060786767 keystone +
 | 
			
		||||
 * 4060778607 keystone -
 | 
			
		||||
 * 4060782687 mouse +
 | 
			
		||||
 * 4060766367 mouse -
 | 
			
		||||
 * 4060748007 auto adj
 | 
			
		||||
 * 4060743927 freeze
 | 
			
		||||
 * 4060754127 blank
 | 
			
		||||
 * 4060762287 zoom +
 | 
			
		||||
 * 4060770447 zoom -
 | 
			
		||||
 * 4060759227 info
 | 
			
		||||
 * 4060780647 vga
 | 
			
		||||
 * 4060742907 video
 | 
			
		||||
 * 4060775547 s-video
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  Serial.begin(115200);
 | 
			
		||||
  irrecv.enableIRIn();
 | 
			
		||||
  pinMode(WHEEL_REAR_RIGHT_R, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_REAR_RIGHT_F, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_REAR_LEFT_R, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_REAR_LEFT_F, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_FRONT_RIGHT_R, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_FRONT_RIGHT_F, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_FRONT_LEFT_R, OUTPUT);
 | 
			
		||||
  pinMode(WHEEL_FRONT_LEFT_F, OUTPUT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void stop(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_R, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_F, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_R, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_F, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_R, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_F, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_R, HIGH);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_F, HIGH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void forward(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_F, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void backward(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_R, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void strafe_l(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_R, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void strafe_r(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_F, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void diag_l_f(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_F, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void diag_r_r(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_R, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void diag_r_f(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_F, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void diag_l_r(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_R, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void turn_l(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_F, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void turn_r(){
 | 
			
		||||
  digitalWrite(WHEEL_REAR_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_REAR_LEFT_R, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_RIGHT_F, LOW);
 | 
			
		||||
  digitalWrite(WHEEL_FRONT_LEFT_R, LOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned long getIRremote(){
 | 
			
		||||
  static unsigned long lastValue = 0;
 | 
			
		||||
  decode_results irResults;
 | 
			
		||||
  if(irrecv.decode(&irResults) == 0){
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  if(!(irResults.decode_type == NEC && irResults.value == REPEAT)){
 | 
			
		||||
    lastValue = irResults.value;
 | 
			
		||||
  }
 | 
			
		||||
  irrecv.resume();
 | 
			
		||||
  return lastValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
  
 | 
			
		||||
  unsigned long remote = getIRremote();
 | 
			
		||||
  static unsigned long modus;
 | 
			
		||||
  if(remote){
 | 
			
		||||
    Serial.println(remote);
 | 
			
		||||
    modus = remote;
 | 
			
		||||
  }
 | 
			
		||||
  if(modus == 4060792887){
 | 
			
		||||
      forward();
 | 
			
		||||
  }else if(modus == 4060801047){
 | 
			
		||||
    stop();
 | 
			
		||||
  }else if(modus == 4060752087){
 | 
			
		||||
    backward();
 | 
			
		||||
  }else if(modus == 4060768407){
 | 
			
		||||
    strafe_l();
 | 
			
		||||
  }else if(modus == 4060784727){
 | 
			
		||||
    strafe_r();
 | 
			
		||||
  }else if(modus == 4060750047){
 | 
			
		||||
    turn_l();
 | 
			
		||||
  }else if(modus == 4060790847){
 | 
			
		||||
    turn_r();
 | 
			
		||||
  }else if(modus == 4060786767){
 | 
			
		||||
    diag_l_f();
 | 
			
		||||
  }else if(modus == 4060778607){
 | 
			
		||||
    diag_r_r();
 | 
			
		||||
  }else if(modus == 4060782687){
 | 
			
		||||
    diag_r_f();
 | 
			
		||||
  }else if(modus == 4060766367){
 | 
			
		||||
    diag_l_r();
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  /*
 | 
			
		||||
  stop();
 | 
			
		||||
  forward();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  backward();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  strafe_l();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  strafe_r();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  diag_l_f();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  diag_l_r();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  diag_r_f();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  diag_r_r();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  turn_l();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  turn_r();
 | 
			
		||||
  delay(1000);
 | 
			
		||||
  stop();
 | 
			
		||||
  */
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user