Skip to content

Commit 88e243f

Browse files
committed
Broken the source in to manageable chunks - 2KLOC files are not fun to debug!
Utterly failed to reduce the MARK_?? functions back down to MACROs - every time I try, the decoders start failing ...However, I have found a considerable number of bugs in the toolchain, so I'm starting to wonder if the fault is not mine.
1 parent 04e2cfb commit 88e243f

19 files changed

+1640
-1588
lines changed

IRremote.cpp

Lines changed: 42 additions & 1586 deletions
Large diffs are not rendered by default.

IRremote.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,49 @@
1+
#define DEBUG
2+
#undef DEBUG
3+
4+
//------------------------------------------------------------------------------
5+
int MATCH_SPACE (int measured_ticks, int desired_us) ;
6+
int MATCH_MARK (int measured_ticks, int desired_us) ;
7+
int MATCH (int measured, int desired) ;
8+
9+
//------------------------------------------------------------------------------
10+
// Debug directives
11+
#ifdef DEBUG
12+
# define DBG_PRINT(...) Serial.print(__VA_ARGS__)
13+
# define DBG_PRINTLN(...) Serial.println(__VA_ARGS__)
14+
#else
15+
# define DBG_PRINT(...)
16+
# define DBG_PRINTLN(...)
17+
#endif
18+
19+
///int MATCH (int measured, int desired);
20+
///int MATCH_MARK (int measured_ticks, int desired_us);
21+
///int MATCH_SPACE (int measured_ticks, int desired_us);
22+
23+
#define SEND_NEC
24+
#define DECODE_NEC
25+
#define SEND_WHYNTER
26+
#define DECODE_WHYNTER
27+
#define SEND_SONY
28+
#define DECODE_SONY
29+
#define DECODE_SANYO
30+
#define SEND_RC5
31+
#define DECODE_RC5
32+
#define SEND_RC6
33+
#define DECODE_RC6
34+
#define SEND_PANASONIC
35+
#define DECODE_PANASONIC
36+
#define SEND_JVC
37+
#define DECODE_JVC
38+
#define SEND_SAMSUNG
39+
#define DECODE_SAMSUNG
40+
#define DECODE_LG
41+
#define DECODE_MITSUBISHI
42+
#define SEND_AIWA_RC_T501
43+
#define DECODE_AIWA_RC_T501
44+
#define SEND_SHARP
45+
#define SEND_DISH
46+
147
/*
248
* IRremote
349
* Version 0.1 July, 2009
@@ -42,7 +88,6 @@ enum decode_type_t {
4288
LG = 12,
4389
WHYNTER = 13,
4490
AIWA_RC_T501 = 14,
45-
4691
};
4792

4893
// Results returned from the decoder

IRremoteInt.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
#ifndef IRremoteint_h
1818
#define IRremoteint_h
1919

20+
#ifdef IR_GLOBAL
21+
# define EXTERN
22+
#else
23+
# define EXTERN extern
24+
#endif
25+
2026
#if defined(ARDUINO) && ARDUINO >= 100
2127
#include <Arduino.h>
2228
#else
@@ -141,7 +147,7 @@ typedef struct {
141147
irparams_t;
142148

143149
// Defined in IRremote.cpp
144-
extern volatile irparams_t irparams;
150+
EXTERN volatile irparams_t irparams;
145151

146152
// IR detector output is active low
147153
#define MARK 0

irISR.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <avr/interrupt.h>
2+
3+
#include "IRremote.h"
4+
#include "IRremoteInt.h"
5+
6+
//+=============================================================================
7+
// TIMER2 interrupt code to collect raw data.
8+
// Widths of alternating SPACE, MARK are recorded in rawbuf.
9+
// Recorded in ticks of 50 microseconds.
10+
// rawlen counts the number of entries recorded so far.
11+
// First entry is the SPACE between transmissions.
12+
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
13+
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
14+
//
15+
ISR (TIMER_INTR_NAME)
16+
{
17+
TIMER_RESET;
18+
19+
uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);
20+
21+
irparams.timer++; // One more 50us tick
22+
if (irparams.rawlen >= RAWBUF) irparams.rcvstate = STATE_STOP ; // Buffer overflow
23+
24+
switch(irparams.rcvstate) {
25+
case STATE_IDLE: // In the middle of a gap
26+
if (irdata == MARK) {
27+
if (irparams.timer < GAP_TICKS) {
28+
// Not big enough to be a gap.
29+
irparams.timer = 0;
30+
}
31+
else {
32+
// gap just ended, record duration and start recording transmission
33+
irparams.rawlen = 0;
34+
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
35+
irparams.timer = 0;
36+
irparams.rcvstate = STATE_MARK;
37+
}
38+
}
39+
break;
40+
41+
case STATE_MARK: // timing MARK
42+
if (irdata == SPACE) { // MARK ended, record time
43+
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
44+
irparams.timer = 0;
45+
irparams.rcvstate = STATE_SPACE;
46+
}
47+
break;
48+
49+
case STATE_SPACE: // timing SPACE
50+
if (irdata == MARK) { // SPACE just ended, record it
51+
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
52+
irparams.timer = 0;
53+
irparams.rcvstate = STATE_MARK;
54+
}
55+
else { // SPACE
56+
if (irparams.timer > GAP_TICKS) {
57+
// big SPACE, indicates gap between codes
58+
// Mark current code as ready for processing
59+
// Switch to STOP
60+
// Don't reset timer; keep counting space width
61+
irparams.rcvstate = STATE_STOP;
62+
}
63+
}
64+
break;
65+
66+
case STATE_STOP: // waiting, measuring gap
67+
if (irdata == MARK) irparams.timer = 0 ; // reset gap timer
68+
break;
69+
}
70+
71+
if (irparams.blinkflag) {
72+
if (irdata == MARK) BLINKLED_ON() ; // turn pin 13 LED on
73+
else BLINKLED_OFF() ; // turn pin 13 LED off
74+
}
75+
}
76+

irRecv.cpp

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#include "IRremote.h"
2+
#include "IRremoteInt.h"
3+
4+
//+=============================================================================
5+
IRrecv::IRrecv (int recvpin)
6+
{
7+
irparams.recvpin = recvpin;
8+
irparams.blinkflag = 0;
9+
}
10+
11+
//+=============================================================================
12+
// initialization
13+
//
14+
void IRrecv::enableIRIn ( )
15+
{
16+
cli();
17+
// setup pulse clock timer interrupt
18+
//Prescale /8 (16M/8 = 0.5 microseconds per tick)
19+
// Therefore, the timer interval can range from 0.5 to 128 microseconds
20+
// depending on the reset value (255 to 0)
21+
TIMER_CONFIG_NORMAL();
22+
23+
//Timer2 Overflow Interrupt Enable
24+
TIMER_ENABLE_INTR;
25+
26+
TIMER_RESET;
27+
28+
sei(); // enable interrupts
29+
30+
// initialize state machine variables
31+
irparams.rcvstate = STATE_IDLE;
32+
irparams.rawlen = 0;
33+
34+
// set pin modes
35+
pinMode(irparams.recvpin, INPUT);
36+
}
37+
38+
//+=============================================================================
39+
// enable/disable blinking of pin 13 on IR processing
40+
//
41+
void IRrecv::blink13 (int blinkflag)
42+
{
43+
irparams.blinkflag = blinkflag;
44+
if (blinkflag) pinMode(BLINKLED, OUTPUT) ;
45+
}
46+
47+
//+=============================================================================
48+
void IRrecv::resume ( )
49+
{
50+
irparams.rcvstate = STATE_IDLE;
51+
irparams.rawlen = 0;
52+
}
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+
63+
64+
65+
66+
//+=============================================================================
67+
// Decodes the received IR message
68+
// Returns 0 if no data ready, 1 if data ready.
69+
// Results of decoding are stored in results
70+
int IRrecv::decode (decode_results *results)
71+
{
72+
results->rawbuf = irparams.rawbuf;
73+
results->rawlen = irparams.rawlen;
74+
75+
if (irparams.rcvstate != STATE_STOP) return false ;
76+
77+
#ifdef DECODE_NEC
78+
DBG_PRINTLN("Attempting NEC decode");
79+
if (decodeNEC(results)) return true ;
80+
#endif
81+
82+
#ifdef DECODE_SONY
83+
DBG_PRINTLN("Attempting Sony decode");
84+
if (decodeSony(results)) return true ;
85+
#endif
86+
87+
#ifdef DECODE_SANYO
88+
DBG_PRINTLN("Attempting Sanyo decode");
89+
if (decodeSanyo(results)) return true ;
90+
#endif
91+
92+
#ifdef DECODE_MITSUBISHI
93+
DBG_PRINTLN("Attempting Mitsubishi decode");
94+
if (decodeMitsubishi(results)) return true ;
95+
#endif
96+
97+
#ifdef DECODE_RC5
98+
DBG_PRINTLN("Attempting RC5 decode");
99+
if (decodeRC5(results)) return true ;
100+
#endif
101+
102+
#ifdef DECODE_RC6
103+
DBG_PRINTLN("Attempting RC6 decode");
104+
if (decodeRC6(results)) return true ;
105+
#endif
106+
107+
#ifdef DECODE_PANASONIC
108+
DBG_PRINTLN("Attempting Panasonic decode");
109+
if (decodePanasonic(results)) return true ;
110+
#endif
111+
112+
#ifdef DECODE_LG
113+
DBG_PRINTLN("Attempting LG decode");
114+
if (decodeLG(results)) return true ;
115+
#endif
116+
117+
#ifdef DECODE_JVC
118+
DBG_PRINTLN("Attempting JVC decode");
119+
if (decodeJVC(results)) return true ;
120+
#endif
121+
122+
#ifdef DECODE_SAMSUNG
123+
DBG_PRINTLN("Attempting SAMSUNG decode");
124+
if (decodeSAMSUNG(results)) return true ;
125+
#endif
126+
127+
#ifdef DECODE_WHYNTER
128+
DBG_PRINTLN("Attempting Whynter decode");
129+
if (decodeWhynter(results)) return true ;
130+
#endif
131+
132+
#ifdef AIWA_RC_T501
133+
DBG_PRINTLN("Attempting Aiwa RC-T501 decode");
134+
if (decodeAiwaRCT501(results)) return true ;
135+
#endif
136+
137+
// decodeHash returns a hash on any input.
138+
// Thus, it needs to be last in the list.
139+
// If you add any decodes, add them before this.
140+
if (decodeHash(results)) return true ;
141+
// Throw away and start over
142+
resume();
143+
return false;
144+
}
145+
146+
//+=============================================================================
147+
// hashdecode - decode an arbitrary IR code.
148+
// Instead of decoding using a standard encoding scheme
149+
// (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
150+
//
151+
// The algorithm: look at the sequence of MARK signals, and see if each one
152+
// is shorter (0), the same length (1), or longer (2) than the previous.
153+
// Do the same with the SPACE signals. Hszh the resulting sequence of 0's,
154+
// 1's, and 2's to a 32-bit value. This will give a unique value for each
155+
// different code (probably), for most code systems.
156+
//
157+
// http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
158+
//
159+
// Compare two tick values, returning 0 if newval is shorter,
160+
// 1 if newval is equal, and 2 if newval is longer
161+
// Use a tolerance of 20%
162+
//
163+
int IRrecv::compare (unsigned int oldval, unsigned int newval)
164+
{
165+
if (newval < oldval * .8) return 0 ;
166+
else if (oldval < newval * .8) return 2 ;
167+
else return 1 ;
168+
}
169+
170+
//+=============================================================================
171+
// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
172+
// Converts the raw code values into a 32-bit hash code.
173+
// Hopefully this code is unique for each button.
174+
// This isn't a "real" decoding, just an arbitrary value.
175+
//
176+
#define FNV_PRIME_32 16777619
177+
#define FNV_BASIS_32 2166136261
178+
179+
long IRrecv::decodeHash (decode_results *results)
180+
{
181+
// Require at least 6 samples to prevent triggering on noise
182+
if (results->rawlen < 6) return false ;
183+
long hash = FNV_BASIS_32;
184+
for (int i = 1; (i + 2) < results->rawlen; i++) {
185+
int value = compare(results->rawbuf[i], results->rawbuf[i+2]);
186+
// Add value into the hash
187+
hash = (hash * FNV_PRIME_32) ^ value;
188+
}
189+
190+
results->value = hash;
191+
results->bits = 32;
192+
results->decode_type = UNKNOWN;
193+
194+
return true;
195+
}

0 commit comments

Comments
 (0)