Fixed delay method by replacing delayMicroseconds call with a loop if

it is too long.
This commit is contained in:
Rafi Khan
2015-08-13 16:54:59 -06:00
parent c058f3f336
commit 11cb3fe442
2 changed files with 89 additions and 70 deletions

View File

@@ -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

View File

@@ -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);
}
}