diff --git a/IRremote.h b/IRremote.h index 9321d17..42be5ed 100644 --- a/IRremote.h +++ b/IRremote.h @@ -253,10 +253,11 @@ class IRsend public: IRsend () { } - void enableIROut (int khz) ; - void mark (int usec) ; - void space (int usec) ; - void sendRaw (unsigned int buf[], unsigned char len, unsigned char hz) ; + void custom_delay_ms (unsigned int time); + void enableIROut (int khz) ; + void mark (int usec) ; + void space (int usec) ; + void sendRaw (unsigned int buf[], unsigned char len, unsigned char hz) ; //...................................................................... # if SEND_RC5 diff --git a/irSend.cpp b/irSend.cpp index f136571..e7b9d86 100644 --- a/irSend.cpp +++ b/irSend.cpp @@ -1,66 +1,84 @@ -#include "IRremote.h" -#include "IRremoteInt.h" - -//+============================================================================= -void IRsend::sendRaw (unsigned int buf[], unsigned char len, unsigned char hz) -{ - // Set IR carrier frequency - enableIROut(hz); - - for (unsigned char i = 0; i < len; i++) { - if (i & 1) space(buf[i]) ; - else mark (buf[i]) ; - } - - space(0); // Always end with the LED off -} - -//+============================================================================= -// Sends an IR mark for the specified number of microseconds. -// The mark output is modulated at the PWM frequency. -// -void IRsend::mark (int time) -{ - TIMER_ENABLE_PWM; // Enable pin 3 PWM output - if (time > 0) delayMicroseconds(time); -} - -//+============================================================================= -// 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 (int time) -{ - TIMER_DISABLE_PWM; // Disable pin 3 PWM output - if (time > 0) delayMicroseconds(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) -{ - // Disable the Timer2 Interrupt (which is used for receiving IR) - TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt - - pinMode(TIMER_PWM_PIN, OUTPUT); - digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low - - // 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); -} - +#include "IRremote.h" +#include "IRremoteInt.h" + +//+============================================================================= +void IRsend::sendRaw (unsigned int buf[], unsigned char len, unsigned char hz) +{ + // Set IR carrier frequency + enableIROut(hz); + + for (unsigned char i = 0; i < len; i++) { + if (i & 1) space(buf[i]) ; + else mark (buf[i]) ; + } + + space(0); // Always end with the LED off +} + +//+============================================================================= +// Sends an IR mark for the specified number of microseconds. +// The mark output is modulated at the PWM frequency. +// +void IRsend::mark (int time) +{ + TIMER_ENABLE_PWM; // Enable pin 3 PWM output + if (time > 0) custom_delay_ms(time); +} + +//+============================================================================= +// 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 (int time) +{ + TIMER_DISABLE_PWM; // Disable pin 3 PWM output + if (time > 0) IRsend::custom_delay_ms(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) +{ + // Disable the Timer2 Interrupt (which is used for receiving IR) + TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt + + pinMode(TIMER_PWM_PIN, OUTPUT); + digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low + + // 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_ms(unsigned int time) { + if (time) + { + if (time > 16000) + { + delayMicroseconds(time % 1000); + delay(time / 1000); + } + else delayMicroseconds(time); + } +}