1
1
/*
2
2
* IRremote
3
- * Version 0.11 August, 2009
4
- * Copyright 2009 Ken Shirriff
3
+ * Copyright 2009-2010 Ken Shirriff
5
4
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
6
5
*
7
6
* Interrupt code based on NECIRrcv by Joe Knapp
11
10
12
11
#include " IRremote.h"
13
12
#include " IRremoteInt.h"
14
-
15
- // Provides ISR
16
- #include < avr/interrupt.h>
13
+ #include " IRremoteHw.h"
17
14
18
15
volatile irparams_t irparams;
19
16
@@ -169,79 +166,37 @@ void IRsend::sendRC6(unsigned long data, int nbits)
169
166
void IRsend::mark (int time) {
170
167
// Sends an IR mark for the specified number of microseconds.
171
168
// The mark output is modulated at the PWM frequency.
172
- TCCR2A |= _BV (COM2B1); // Enable pin 3 PWM output
169
+ IRremoteEnablePwm ();
173
170
delayMicroseconds (time );
174
171
}
175
172
176
173
/* Leave pin off for time (given in microseconds) */
177
174
void IRsend::space (int time) {
178
175
// Sends an IR space for the specified number of microseconds.
179
176
// A space is no output, so the PWM output is disabled.
180
- TCCR2A &= ~( _BV (COM2B1)); // Disable pin 3 PWM output
177
+ IRremoteDisablePwm ();
181
178
delayMicroseconds (time );
182
179
}
183
180
184
181
void IRsend::enableIROut (int khz) {
185
- // Enables IR output. The khz value controls the modulation frequency in kilohertz.
186
- // The IR output will be on pin 3 (OC2B).
187
- // This routine is designed for 36-40KHz; if you use it for other values, it's up to you
188
- // to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.)
189
- // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
190
- // controlling the duty cycle.
191
- // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
192
- // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
193
- // A few hours staring at the ATmega documentation and this will all make sense.
194
- // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
195
-
196
-
197
- // Disable the Timer2 Interrupt (which is used for receiving IR)
198
- TIMSK2 &= ~_BV (TOIE2); // Timer2 Overflow Interrupt
199
-
200
- pinMode (3 , OUTPUT);
201
- digitalWrite (3 , LOW); // When not sending PWM, we want it low
202
-
203
- // COM2A = 00: disconnect OC2A
204
- // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted
205
- // WGM2 = 101: phase-correct PWM with OCRA as top
206
- // CS2 = 000: no prescaling
207
- TCCR2A = _BV (WGM20);
208
- TCCR2B = _BV (WGM22) | _BV (CS20);
209
-
210
- // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A.
211
- OCR2A = SYSCLOCK / 2 / khz / 1000 ;
212
- OCR2B = OCR2A / 3 ; // 33% duty cycle
182
+ IRremoteEnableIRoutput (khz);
213
183
}
214
184
215
185
IRrecv::IRrecv (int recvpin)
216
186
{
217
187
irparams.recvpin = recvpin;
218
188
irparams.blinkflag = 0 ;
189
+ IRremoteRegisterHandler (&interrupt_handler);
219
190
}
220
191
221
192
// initialization
222
193
void IRrecv::enableIRIn () {
223
- // setup pulse clock timer interrupt
224
- TCCR2A = 0 ; // normal mode
225
-
226
- // Prescale /8 (16M/8 = 0.5 microseconds per tick)
227
- // Therefore, the timer interval can range from 0.5 to 128 microseconds
228
- // depending on the reset value (255 to 0)
229
- cbi (TCCR2B,CS22);
230
- sbi (TCCR2B,CS21);
231
- cbi (TCCR2B,CS20);
232
-
233
- // Timer2 Overflow Interrupt Enable
234
- sbi (TIMSK2,TOIE2);
235
-
236
- RESET_TIMER2;
237
-
238
- sei (); // enable interrupts
194
+ IRremoteEnableIRinput ();
239
195
240
196
// initialize state machine variables
241
197
irparams.rcvstate = STATE_IDLE;
242
198
irparams.rawlen = 0 ;
243
199
244
-
245
200
// set pin modes
246
201
pinMode (irparams.recvpin , INPUT);
247
202
}
@@ -254,17 +209,16 @@ void IRrecv::blink13(int blinkflag)
254
209
pinMode (BLINKLED, OUTPUT);
255
210
}
256
211
257
- // TIMER2 interrupt code to collect raw data.
212
+
213
+ // interrupt code to collect raw data.
258
214
// Widths of alternating SPACE, MARK are recorded in rawbuf.
259
215
// Recorded in ticks of 50 microseconds.
260
216
// rawlen counts the number of entries recorded so far.
261
217
// First entry is the SPACE between transmissions.
262
218
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
263
219
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
264
- ISR (TIMER2_OVF_vect)
220
+ static void interrupt_handler () {
265
221
{
266
- RESET_TIMER2;
267
-
268
222
uint8_t irdata = (uint8_t )digitalRead (irparams.recvpin );
269
223
270
224
irparams.timer ++; // One more 50us tick
@@ -317,15 +271,6 @@ ISR(TIMER2_OVF_vect)
317
271
}
318
272
break ;
319
273
}
320
-
321
- if (irparams.blinkflag ) {
322
- if (irdata == MARK) {
323
- PORTB |= B00100000; // turn pin 13 LED on
324
- }
325
- else {
326
- PORTB &= B11011111; // turn pin 13 LED off
327
- }
328
- }
329
274
}
330
275
331
276
void IRrecv::resume () {
0 commit comments