mirror of https://github.com/arendst/Tasmota.git
1258 lines
39 KiB
C++
1258 lines
39 KiB
C++
// Copyright 2009 Ken Shirriff
|
|
// Copyright 2015 Mark Szabo
|
|
// Copyright 2017,2019 David Conran
|
|
|
|
#include "IRsend.h"
|
|
#ifndef UNIT_TEST
|
|
#include <Arduino.h>
|
|
#else
|
|
#define __STDC_LIMIT_MACROS
|
|
#include <stdint.h>
|
|
#endif
|
|
#include <algorithm>
|
|
#ifdef UNIT_TEST
|
|
#include <cmath>
|
|
#endif
|
|
#include "IRtimer.h"
|
|
|
|
/// Constructor for an IRsend object.
|
|
/// @param[in] IRsendPin Which GPIO pin to use when sending an IR command.
|
|
/// @param[in] inverted Optional flag to invert the output. (default = false)
|
|
/// e.g. LED is illuminated when GPIO is LOW rather than HIGH.
|
|
/// @warning Setting `inverted` to something other than the default could
|
|
/// easily destroy your IR LED if you are overdriving it.
|
|
/// Unless you *REALLY* know what you are doing, don't change this.
|
|
/// @param[in] use_modulation Do we do frequency modulation during transmission?
|
|
/// i.e. If not, assume a 100% duty cycle. Ignore attempts to change the
|
|
/// duty cycle etc.
|
|
IRsend::IRsend(uint16_t IRsendPin, bool inverted, bool use_modulation)
|
|
: IRpin(IRsendPin), periodOffset(kPeriodOffset) {
|
|
if (inverted) {
|
|
outputOn = LOW;
|
|
outputOff = HIGH;
|
|
} else {
|
|
outputOn = HIGH;
|
|
outputOff = LOW;
|
|
}
|
|
modulation = use_modulation;
|
|
if (modulation)
|
|
_dutycycle = kDutyDefault;
|
|
else
|
|
_dutycycle = kDutyMax;
|
|
}
|
|
|
|
/// Enable the pin for output.
|
|
void IRsend::begin() {
|
|
#ifndef UNIT_TEST
|
|
pinMode(IRpin, OUTPUT);
|
|
#endif
|
|
ledOff(); // Ensure the LED is in a known safe state when we start.
|
|
}
|
|
|
|
/// Turn off the IR LED.
|
|
void IRsend::ledOff() {
|
|
#ifndef UNIT_TEST
|
|
digitalWrite(IRpin, outputOff);
|
|
#endif
|
|
}
|
|
|
|
/// Turn on the IR LED.
|
|
void IRsend::ledOn() {
|
|
#ifndef UNIT_TEST
|
|
digitalWrite(IRpin, outputOn);
|
|
#endif
|
|
}
|
|
|
|
/// Calculate the period for a given frequency.
|
|
/// @param[in] hz Frequency in Hz.
|
|
/// @param[in] use_offset Should we use the calculated offset or not?
|
|
/// @return nr. of uSeconds.
|
|
/// @note (T = 1/f)
|
|
uint32_t IRsend::calcUSecPeriod(uint32_t hz, bool use_offset) {
|
|
if (hz == 0) hz = 1; // Avoid Zero hz. Divide by Zero is nasty.
|
|
uint32_t period =
|
|
(1000000UL + hz / 2) / hz; // The equiv of round(1000000/hz).
|
|
// Apply the offset and ensure we don't result in a <= 0 value.
|
|
if (use_offset)
|
|
return std::max((uint32_t)1, period + periodOffset);
|
|
else
|
|
return std::max((uint32_t)1, period);
|
|
}
|
|
|
|
/// Set the output frequency modulation and duty cycle.
|
|
/// @param[in] freq The freq we want to modulate at.
|
|
/// Assumes < 1000 means kHz else Hz.
|
|
/// @param[in] duty Percentage duty cycle of the LED.
|
|
/// e.g. 25 = 25% = 1/4 on, 3/4 off.
|
|
/// If you are not sure, try 50 percent.
|
|
/// This is ignored if modulation is disabled at object instantiation.
|
|
/// @note Integer timing functions & math mean we can't do fractions of
|
|
/// microseconds timing. Thus minor changes to the freq & duty values may have
|
|
/// limited effect. You've been warned.
|
|
void IRsend::enableIROut(uint32_t freq, uint8_t duty) {
|
|
// Set the duty cycle to use if we want freq. modulation.
|
|
if (modulation) {
|
|
_dutycycle = std::min(duty, kDutyMax);
|
|
} else {
|
|
_dutycycle = kDutyMax;
|
|
}
|
|
if (freq < 1000) // Were we given kHz? Supports the old call usage.
|
|
freq *= 1000;
|
|
#ifdef UNIT_TEST
|
|
_freq_unittest = freq;
|
|
#endif // UNIT_TEST
|
|
uint32_t period = calcUSecPeriod(freq);
|
|
// Nr. of uSeconds the LED will be on per pulse.
|
|
onTimePeriod = (period * _dutycycle) / kDutyMax;
|
|
// Nr. of uSeconds the LED will be off per pulse.
|
|
offTimePeriod = period - onTimePeriod;
|
|
}
|
|
|
|
#if ALLOW_DELAY_CALLS
|
|
/// An ESP8266 RTOS watch-dog timer friendly version of delayMicroseconds().
|
|
/// @param[in] usec Nr. of uSeconds to delay for.
|
|
void IRsend::_delayMicroseconds(uint32_t usec) {
|
|
// delayMicroseconds() is only accurate to 16383us.
|
|
// Ref: https://www.arduino.cc/en/Reference/delayMicroseconds
|
|
if (usec <= kMaxAccurateUsecDelay) {
|
|
#ifndef UNIT_TEST
|
|
delayMicroseconds(usec);
|
|
#endif
|
|
} else {
|
|
#ifndef UNIT_TEST
|
|
// Invoke a delay(), where possible, to avoid triggering the WDT.
|
|
delay(usec / 1000UL); // Delay for as many whole milliseconds as we can.
|
|
// Delay the remaining sub-millisecond.
|
|
delayMicroseconds(static_cast<uint16_t>(usec % 1000UL));
|
|
#endif
|
|
}
|
|
}
|
|
#else // ALLOW_DELAY_CALLS
|
|
/// A version of delayMicroseconds() that handles large values and does NOT use
|
|
/// the watch-dog friendly delay() calls where appropriate.
|
|
/// @note Use this only if you know what you are doing as it may cause the WDT
|
|
/// to reset the ESP8266.
|
|
void IRsend::_delayMicroseconds(uint32_t usec) {
|
|
for (; usec > kMaxAccurateUsecDelay; usec -= kMaxAccurateUsecDelay)
|
|
#ifndef UNIT_TEST
|
|
delayMicroseconds(kMaxAccurateUsecDelay);
|
|
delayMicroseconds(static_cast<uint16_t>(usec));
|
|
#endif // UNIT_TEST
|
|
}
|
|
#endif // ALLOW_DELAY_CALLS
|
|
|
|
/// Modulate the IR LED for the given period (usec) and at the duty cycle set.
|
|
/// @param[in] usec The period of time to modulate the IR LED for, in
|
|
/// microseconds.
|
|
/// @return Nr. of pulses actually sent.
|
|
/// @note
|
|
/// The ESP8266 has no good way to do hardware PWM, so we have to do it all
|
|
/// in software. There is a horrible kludge/brilliant hack to use the second
|
|
/// serial TX line to do fairly accurate hardware PWM, but it is only
|
|
/// available on a single specific GPIO and only available on some modules.
|
|
/// e.g. It's not available on the ESP-01 module.
|
|
/// Hence, for greater compatibility & choice, we don't use that method.
|
|
/// Ref:
|
|
/// https://www.analysir.com/blog/2017/01/29/updated-esp8266-nodemcu-backdoor-upwm-hack-for-ir-signals/
|
|
uint16_t IRsend::mark(uint16_t usec) {
|
|
// Handle the simple case of no required frequency modulation.
|
|
if (!modulation || _dutycycle >= 100) {
|
|
ledOn();
|
|
_delayMicroseconds(usec);
|
|
ledOff();
|
|
return 1;
|
|
}
|
|
|
|
// Not simple, so do it assuming frequency modulation.
|
|
uint16_t counter = 0;
|
|
IRtimer usecTimer = IRtimer();
|
|
// Cache the time taken so far. This saves us calling time, and we can be
|
|
// assured that we can't have odd math problems. i.e. unsigned under/overflow.
|
|
uint32_t elapsed = usecTimer.elapsed();
|
|
|
|
while (elapsed < usec) { // Loop until we've met/exceeded our required time.
|
|
ledOn();
|
|
// Calculate how long we should pulse on for.
|
|
// e.g. Are we to close to the end of our requested mark time (usec)?
|
|
_delayMicroseconds(std::min((uint32_t)onTimePeriod, usec - elapsed));
|
|
ledOff();
|
|
counter++;
|
|
if (elapsed + onTimePeriod >= usec)
|
|
return counter; // LED is now off & we've passed our allotted time.
|
|
// Wait for the lesser of the rest of the duty cycle, or the time remaining.
|
|
_delayMicroseconds(
|
|
std::min(usec - elapsed - onTimePeriod, (uint32_t)offTimePeriod));
|
|
elapsed = usecTimer.elapsed(); // Update & recache the actual elapsed time.
|
|
}
|
|
return counter;
|
|
}
|
|
|
|
/// Turn the pin (LED) off for a given time.
|
|
/// Sends an IR space for the specified number of microseconds.
|
|
/// A space is no output, so the PWM output is disabled.
|
|
/// @param[in] time Time in microseconds (us).
|
|
void IRsend::space(uint32_t time) {
|
|
ledOff();
|
|
if (time == 0) return;
|
|
_delayMicroseconds(time);
|
|
}
|
|
|
|
/// Calculate & set any offsets to account for execution times during sending.
|
|
///
|
|
/// @param[in] hz The frequency to calibrate at >= 1000Hz. Default is 38000Hz.
|
|
/// @return The calculated period offset (in uSeconds) which is now in use.
|
|
/// e.g. -5.
|
|
/// @note This will generate an 65535us mark() IR LED signal.
|
|
/// This only needs to be called once, if at all.
|
|
int8_t IRsend::calibrate(uint16_t hz) {
|
|
if (hz < 1000) // Were we given kHz? Supports the old call usage.
|
|
hz *= 1000;
|
|
periodOffset = 0; // Turn off any existing offset while we calibrate.
|
|
enableIROut(hz);
|
|
IRtimer usecTimer = IRtimer(); // Start a timer *just* before we do the call.
|
|
uint16_t pulses = mark(UINT16_MAX); // Generate a PWM of 65,535 us. (Max.)
|
|
uint32_t timeTaken = usecTimer.elapsed(); // Record the time it took.
|
|
// While it shouldn't be necessary, assume at least 1 pulse, to avoid a
|
|
// divide by 0 situation.
|
|
pulses = std::max(pulses, (uint16_t)1U);
|
|
uint32_t calcPeriod = calcUSecPeriod(hz); // e.g. @38kHz it should be 26us.
|
|
// Assuming 38kHz for the example calculations:
|
|
// In a 65535us pulse, we should have 2520.5769 pulses @ 26us periods.
|
|
// e.g. 65535.0us / 26us = 2520.5769
|
|
// This should have caused approx 2520 loops through the main loop in mark().
|
|
// The average over that many interations should give us a reasonable
|
|
// approximation at what offset we need to use to account for instruction
|
|
// execution times.
|
|
//
|
|
// Calculate the actual period from the actual time & the actual pulses
|
|
// generated.
|
|
double_t actualPeriod = (double_t)timeTaken / (double_t)pulses;
|
|
// Store the difference between the actual time per period vs. calculated.
|
|
periodOffset = (int8_t)((double_t)calcPeriod - actualPeriod);
|
|
return periodOffset;
|
|
}
|
|
|
|
/// Generic method for sending data that is common to most protocols.
|
|
/// Will send leading or trailing 0's if the nbits is larger than the number
|
|
/// of bits in data.
|
|
/// @param[in] onemark Nr. of usecs for the led to be pulsed for a '1' bit.
|
|
/// @param[in] onespace Nr. of usecs for the led to be fully off for a '1' bit.
|
|
/// @param[in] zeromark Nr. of usecs for the led to be pulsed for a '0' bit.
|
|
/// @param[in] zerospace Nr. of usecs for the led to be fully off for a '0' bit.
|
|
/// @param[in] data The data to be transmitted.
|
|
/// @param[in] nbits Nr. of bits of data to be sent.
|
|
/// @param[in] MSBfirst Flag for bit transmission order.
|
|
/// Defaults to MSB->LSB order.
|
|
void IRsend::sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark,
|
|
uint32_t zerospace, uint64_t data, uint16_t nbits,
|
|
bool MSBfirst) {
|
|
if (nbits == 0) // If we are asked to send nothing, just return.
|
|
return;
|
|
if (MSBfirst) { // Send the MSB first.
|
|
// Send 0's until we get down to a bit size we can actually manage.
|
|
while (nbits > sizeof(data) * 8) {
|
|
mark(zeromark);
|
|
space(zerospace);
|
|
nbits--;
|
|
}
|
|
// Send the supplied data.
|
|
for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1)
|
|
if (data & mask) { // Send a 1
|
|
mark(onemark);
|
|
space(onespace);
|
|
} else { // Send a 0
|
|
mark(zeromark);
|
|
space(zerospace);
|
|
}
|
|
} else { // Send the Least Significant Bit (LSB) first / MSB last.
|
|
for (uint16_t bit = 0; bit < nbits; bit++, data >>= 1)
|
|
if (data & 1) { // Send a 1
|
|
mark(onemark);
|
|
space(onespace);
|
|
} else { // Send a 0
|
|
mark(zeromark);
|
|
space(zerospace);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Generic method for sending simple protocol messages.
|
|
/// Will send leading or trailing 0's if the nbits is larger than the number
|
|
/// of bits in data.
|
|
/// @param[in] headermark Nr. of usecs for the led to be pulsed for the header
|
|
/// mark. A value of 0 means no header mark.
|
|
/// @param[in] headerspace Nr. of usecs for the led to be off after the header
|
|
/// mark. A value of 0 means no header space.
|
|
/// @param[in] onemark Nr. of usecs for the led to be pulsed for a '1' bit.
|
|
/// @param[in] onespace Nr. of usecs for the led to be fully off for a '1' bit.
|
|
/// @param[in] zeromark Nr. of usecs for the led to be pulsed for a '0' bit.
|
|
/// @param[in] zerospace Nr. of usecs for the led to be fully off for a '0' bit.
|
|
/// @param[in] footermark Nr. of usecs for the led to be pulsed for the footer
|
|
/// mark. A value of 0 means no footer mark.
|
|
/// @param[in] gap Nr. of usecs for the led to be off after the footer mark.
|
|
/// This is effectively the gap between messages.
|
|
/// A value of 0 means no gap space.
|
|
/// @param[in] data The data to be transmitted.
|
|
/// @param[in] nbits Nr. of bits of data to be sent.
|
|
/// @param[in] frequency The frequency we want to modulate at. (Hz/kHz)
|
|
/// @param[in] MSBfirst Flag for bit transmission order.
|
|
/// Defaults to MSB->LSB order.
|
|
/// @param[in] repeat Nr. of extra times the message will be sent.
|
|
/// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages
|
|
/// @param[in] dutycycle Percentage duty cycle of the LED.
|
|
/// e.g. 25 = 25% = 1/4 on, 3/4 off.
|
|
/// If you are not sure, try 50 percent.
|
|
/// @note Assumes a frequency < 1000 means kHz otherwise it is in Hz.
|
|
/// Most common value is 38000 or 38, for 38kHz.
|
|
void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace,
|
|
const uint16_t onemark, const uint32_t onespace,
|
|
const uint16_t zeromark, const uint32_t zerospace,
|
|
const uint16_t footermark, const uint32_t gap,
|
|
const uint64_t data, const uint16_t nbits,
|
|
const uint16_t frequency, const bool MSBfirst,
|
|
const uint16_t repeat, const uint8_t dutycycle) {
|
|
sendGeneric(headermark, headerspace, onemark, onespace, zeromark, zerospace,
|
|
footermark, gap, 0U, data, nbits, frequency, MSBfirst, repeat,
|
|
dutycycle);
|
|
}
|
|
|
|
/// Generic method for sending simple protocol messages.
|
|
/// Will send leading or trailing 0's if the nbits is larger than the number
|
|
/// of bits in data.
|
|
/// @param[in] headermark Nr. of usecs for the led to be pulsed for the header
|
|
/// mark. A value of 0 means no header mark.
|
|
/// @param[in] headerspace Nr. of usecs for the led to be off after the header
|
|
/// mark. A value of 0 means no header space.
|
|
/// @param[in] onemark Nr. of usecs for the led to be pulsed for a '1' bit.
|
|
/// @param[in] onespace Nr. of usecs for the led to be fully off for a '1' bit.
|
|
/// @param[in] zeromark Nr. of usecs for the led to be pulsed for a '0' bit.
|
|
/// @param[in] zerospace Nr. of usecs for the led to be fully off for a '0' bit.
|
|
/// @param[in] footermark Nr. of usecs for the led to be pulsed for the footer
|
|
/// mark. A value of 0 means no footer mark.
|
|
/// @param[in] gap Nr. of usecs for the led to be off after the footer mark.
|
|
/// This is effectively the gap between messages.
|
|
/// A value of 0 means no gap space.
|
|
/// @param[in] mesgtime Min. nr. of usecs a single message needs to be.
|
|
/// This is effectively the min. total length of a single message.
|
|
/// @param[in] data The data to be transmitted.
|
|
/// @param[in] nbits Nr. of bits of data to be sent.
|
|
/// @param[in] frequency The frequency we want to modulate at. (Hz/kHz)
|
|
/// @param[in] MSBfirst Flag for bit transmission order.
|
|
/// Defaults to MSB->LSB order.
|
|
/// @param[in] repeat Nr. of extra times the message will be sent.
|
|
/// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages
|
|
/// @param[in] dutycycle Percentage duty cycle of the LED.
|
|
/// e.g. 25 = 25% = 1/4 on, 3/4 off.
|
|
/// If you are not sure, try 50 percent.
|
|
/// @note Assumes a frequency < 1000 means kHz otherwise it is in Hz.
|
|
/// Most common value is 38000 or 38, for 38kHz.
|
|
void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace,
|
|
const uint16_t onemark, const uint32_t onespace,
|
|
const uint16_t zeromark, const uint32_t zerospace,
|
|
const uint16_t footermark, const uint32_t gap,
|
|
const uint32_t mesgtime, const uint64_t data,
|
|
const uint16_t nbits, const uint16_t frequency,
|
|
const bool MSBfirst, const uint16_t repeat,
|
|
const uint8_t dutycycle) {
|
|
// Setup
|
|
enableIROut(frequency, dutycycle);
|
|
IRtimer usecs = IRtimer();
|
|
|
|
// We always send a message, even for repeat=0, hence '<= repeat'.
|
|
for (uint16_t r = 0; r <= repeat; r++) {
|
|
usecs.reset();
|
|
|
|
// Header
|
|
if (headermark) mark(headermark);
|
|
if (headerspace) space(headerspace);
|
|
|
|
// Data
|
|
sendData(onemark, onespace, zeromark, zerospace, data, nbits, MSBfirst);
|
|
|
|
// Footer
|
|
if (footermark) mark(footermark);
|
|
uint32_t elapsed = usecs.elapsed();
|
|
// Avoid potential unsigned integer underflow. e.g. when mesgtime is 0.
|
|
if (elapsed >= mesgtime)
|
|
space(gap);
|
|
else
|
|
space(std::max(gap, mesgtime - elapsed));
|
|
}
|
|
}
|
|
|
|
/// Generic method for sending simple protocol messages.
|
|
/// @param[in] headermark Nr. of usecs for the led to be pulsed for the header
|
|
/// mark. A value of 0 means no header mark.
|
|
/// @param[in] headerspace Nr. of usecs for the led to be off after the header
|
|
/// mark. A value of 0 means no header space.
|
|
/// @param[in] onemark Nr. of usecs for the led to be pulsed for a '1' bit.
|
|
/// @param[in] onespace Nr. of usecs for the led to be fully off for a '1' bit.
|
|
/// @param[in] zeromark Nr. of usecs for the led to be pulsed for a '0' bit.
|
|
/// @param[in] zerospace Nr. of usecs for the led to be fully off for a '0' bit.
|
|
/// @param[in] footermark Nr. of usecs for the led to be pulsed for the footer
|
|
/// mark. A value of 0 means no footer mark.
|
|
/// @param[in] gap Nr. of usecs for the led to be off after the footer mark.
|
|
/// This is effectively the gap between messages.
|
|
/// A value of 0 means no gap space.
|
|
/// @param[in] dataptr Pointer to the data to be transmitted.
|
|
/// @param[in] nbytes Nr. of bytes of data to be sent.
|
|
/// @param[in] frequency The frequency we want to modulate at. (Hz/kHz)
|
|
/// @param[in] MSBfirst Flag for bit transmission order.
|
|
/// Defaults to MSB->LSB order.
|
|
/// @param[in] repeat Nr. of extra times the message will be sent.
|
|
/// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages
|
|
/// @param[in] dutycycle Percentage duty cycle of the LED.
|
|
/// e.g. 25 = 25% = 1/4 on, 3/4 off.
|
|
/// If you are not sure, try 50 percent.
|
|
/// @note Assumes a frequency < 1000 means kHz otherwise it is in Hz.
|
|
/// Most common value is 38000 or 38, for 38kHz.
|
|
void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace,
|
|
const uint16_t onemark, const uint32_t onespace,
|
|
const uint16_t zeromark, const uint32_t zerospace,
|
|
const uint16_t footermark, const uint32_t gap,
|
|
const uint8_t *dataptr, const uint16_t nbytes,
|
|
const uint16_t frequency, const bool MSBfirst,
|
|
const uint16_t repeat, const uint8_t dutycycle) {
|
|
// Setup
|
|
enableIROut(frequency, dutycycle);
|
|
// We always send a message, even for repeat=0, hence '<= repeat'.
|
|
for (uint16_t r = 0; r <= repeat; r++) {
|
|
// Header
|
|
if (headermark) mark(headermark);
|
|
if (headerspace) space(headerspace);
|
|
|
|
// Data
|
|
for (uint16_t i = 0; i < nbytes; i++)
|
|
sendData(onemark, onespace, zeromark, zerospace, *(dataptr + i), 8,
|
|
MSBfirst);
|
|
|
|
// Footer
|
|
if (footermark) mark(footermark);
|
|
space(gap);
|
|
}
|
|
}
|
|
|
|
/// Generic method for sending Manchester code data.
|
|
/// Will send leading or trailing 0's if the nbits is larger than the number
|
|
/// of bits in data.
|
|
/// @param[in] half_period Nr. of uSeconds for half the clock's period.
|
|
/// (1/2 wavelength)
|
|
/// @param[in] data The data to be transmitted.
|
|
/// @param[in] nbits Nr. of bits of data to be sent.
|
|
/// @param[in] MSBfirst Flag for bit transmission order.
|
|
/// Defaults to MSB->LSB order.
|
|
/// @param[in] GEThomas Use G.E. Thomas (true/default) or IEEE 802.3 (false).
|
|
void IRsend::sendManchesterData(const uint16_t half_period,
|
|
const uint64_t data,
|
|
const uint16_t nbits, const bool MSBfirst,
|
|
const bool GEThomas) {
|
|
if (nbits == 0) return; // Nothing to send.
|
|
uint16_t bits = nbits;
|
|
uint64_t copy = (GEThomas) ? data : ~data;
|
|
|
|
if (MSBfirst) { // Send the MSB first.
|
|
// Send 0's until we get down to a bit size we can actually manage.
|
|
if (bits > (sizeof(data) * 8)) {
|
|
sendManchesterData(half_period, 0ULL, bits - sizeof(data) * 8, MSBfirst,
|
|
GEThomas);
|
|
bits = sizeof(data) * 8;
|
|
}
|
|
// Send the supplied data.
|
|
for (uint64_t mask = 1ULL << (bits - 1); mask; mask >>= 1)
|
|
if (copy & mask) {
|
|
mark(half_period);
|
|
space(half_period);
|
|
} else {
|
|
space(half_period);
|
|
mark(half_period);
|
|
}
|
|
} else { // Send the Least Significant Bit (LSB) first / MSB last.
|
|
for (bits = 0; bits < nbits; bits++, copy >>= 1)
|
|
if (copy & 1) {
|
|
mark(half_period);
|
|
space(half_period);
|
|
} else {
|
|
space(half_period);
|
|
mark(half_period);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Generic method for sending Manchester code messages.
|
|
/// Will send leading or trailing 0's if the nbits is larger than the number
|
|
/// @param[in] headermark Nr. of usecs for the led to be pulsed for the header
|
|
/// mark. A value of 0 means no header mark.
|
|
/// @param[in] headerspace Nr. of usecs for the led to be off after the header
|
|
/// mark. A value of 0 means no header space.
|
|
/// @param[in] half_period Nr. of uSeconds for half the clock's period.
|
|
/// (1/2 wavelength)
|
|
/// @param[in] footermark Nr. of usecs for the led to be pulsed for the footer
|
|
/// mark. A value of 0 means no footer mark.
|
|
/// @param[in] gap Min. nr. of usecs for the led to be off after the footer
|
|
/// mark. This is effectively the absolute minimum gap between messages.
|
|
/// @param[in] data The data to be transmitted.
|
|
/// @param[in] nbits Nr. of bits of data to be sent.
|
|
/// @param[in] frequency The frequency we want to modulate at. (Hz/kHz)
|
|
/// @param[in] MSBfirst Flag for bit transmission order.
|
|
/// Defaults to MSB->LSB order.
|
|
/// @param[in] repeat Nr. of extra times the message will be sent.
|
|
/// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages
|
|
/// @param[in] dutycycle Percentage duty cycle of the LED.
|
|
/// e.g. 25 = 25% = 1/4 on, 3/4 off.
|
|
/// If you are not sure, try 50 percent.
|
|
/// @param[in] GEThomas Use G.E. Thomas (true/default) or IEEE 802.3 (false).
|
|
/// @note Assumes a frequency < 1000 means kHz otherwise it is in Hz.
|
|
/// Most common value is 38000 or 38, for 38kHz.
|
|
void IRsend::sendManchester(const uint16_t headermark,
|
|
const uint32_t headerspace,
|
|
const uint16_t half_period,
|
|
const uint16_t footermark, const uint32_t gap,
|
|
const uint64_t data, const uint16_t nbits,
|
|
const uint16_t frequency, const bool MSBfirst,
|
|
const uint16_t repeat, const uint8_t dutycycle,
|
|
const bool GEThomas) {
|
|
// Setup
|
|
enableIROut(frequency, dutycycle);
|
|
|
|
// We always send a message, even for repeat=0, hence '<= repeat'.
|
|
for (uint16_t r = 0; r <= repeat; r++) {
|
|
// Header
|
|
if (headermark) mark(headermark);
|
|
if (headerspace) space(headerspace);
|
|
// Data
|
|
sendManchesterData(half_period, data, nbits, MSBfirst, GEThomas);
|
|
// Footer
|
|
if (footermark) mark(footermark);
|
|
if (gap) space(gap);
|
|
}
|
|
}
|
|
|
|
#if SEND_RAW
|
|
/// Send a raw IRremote message.
|
|
///
|
|
/// @param[in] buf An array of uint16_t's that has microseconds elements.
|
|
/// @param[in] len Nr. of elements in the buf[] array.
|
|
/// @param[in] hz Frequency to send the message at. (kHz < 1000; Hz >= 1000)
|
|
/// @note Even elements are Mark times (On), Odd elements are Space times (Off).
|
|
/// Ref:
|
|
/// examples/IRrecvDumpV2/IRrecvDumpV2.ino (or later)
|
|
void IRsend::sendRaw(const uint16_t buf[], const uint16_t len,
|
|
const uint16_t hz) {
|
|
// Set IR carrier frequency
|
|
enableIROut(hz);
|
|
for (uint16_t i = 0; i < len; i++) {
|
|
if (i & 1) { // Odd bit.
|
|
space(buf[i]);
|
|
} else { // Even bit.
|
|
mark(buf[i]);
|
|
}
|
|
}
|
|
ledOff(); // We potentially have ended with a mark(), so turn of the LED.
|
|
}
|
|
#endif // SEND_RAW
|
|
|
|
/// Get the minimum number of repeats for a given protocol.
|
|
/// @param[in] protocol Protocol number/type of the message you want to send.
|
|
/// @return The number of repeats required.
|
|
uint16_t IRsend::minRepeats(const decode_type_t protocol) {
|
|
switch (protocol) {
|
|
// Single repeats
|
|
case AIWA_RC_T501:
|
|
case AMCOR:
|
|
case COOLIX:
|
|
case ELITESCREENS:
|
|
case GICABLE:
|
|
case INAX:
|
|
case MIDEA24:
|
|
case MITSUBISHI:
|
|
case MITSUBISHI2:
|
|
case MITSUBISHI_AC:
|
|
case MULTIBRACKETS:
|
|
case SHERWOOD:
|
|
case TOSHIBA_AC:
|
|
return kSingleRepeat;
|
|
// Special
|
|
case AIRWELL:
|
|
return kAirwellMinRepeats;
|
|
case CARRIER_AC40:
|
|
return kCarrierAc40MinRepeat;
|
|
case DISH:
|
|
return kDishMinRepeat;
|
|
case EPSON:
|
|
return kEpsonMinRepeat;
|
|
case SONY:
|
|
return kSonyMinRepeat;
|
|
case SONY_38K:
|
|
return kSonyMinRepeat + 1;
|
|
case SYMPHONY:
|
|
return kSymphonyDefaultRepeat;
|
|
case ZEPEAL:
|
|
return kZepealMinRepeat;
|
|
default:
|
|
return kNoRepeat;
|
|
}
|
|
}
|
|
|
|
/// Get the default number of bits for a given protocol.
|
|
/// @param[in] protocol Protocol number/type you want the default bit size for.
|
|
/// @return The number of bits.
|
|
uint16_t IRsend::defaultBits(const decode_type_t protocol) {
|
|
switch (protocol) {
|
|
case MULTIBRACKETS:
|
|
return 8;
|
|
case RC5:
|
|
case SYMPHONY:
|
|
return 12;
|
|
case LASERTAG:
|
|
case RC5X:
|
|
return 13;
|
|
case AIWA_RC_T501:
|
|
case DENON:
|
|
case SHARP:
|
|
return 15;
|
|
case DISH:
|
|
case GICABLE:
|
|
case JVC:
|
|
case LEGOPF:
|
|
case MITSUBISHI:
|
|
case MITSUBISHI2:
|
|
case ZEPEAL:
|
|
return 16;
|
|
case METZ:
|
|
return 19;
|
|
case RC6:
|
|
case SONY:
|
|
case SONY_38K:
|
|
return 20;
|
|
case COOLIX:
|
|
case INAX:
|
|
case MIDEA24:
|
|
case NIKAI:
|
|
case RCMM:
|
|
case TRANSCOLD:
|
|
return 24;
|
|
case LG:
|
|
case LG2:
|
|
return 28;
|
|
case CARRIER_AC:
|
|
case ELITESCREENS:
|
|
case EPSON:
|
|
case NEC:
|
|
case NEC_LIKE:
|
|
case PANASONIC_AC32:
|
|
case SAMSUNG:
|
|
case SHERWOOD:
|
|
case WHYNTER:
|
|
return 32;
|
|
case AIRWELL:
|
|
return 34;
|
|
case LUTRON:
|
|
case TECO:
|
|
return 35;
|
|
case SAMSUNG36:
|
|
return 36;
|
|
case CARRIER_AC40:
|
|
return kCarrierAc40Bits; // 40
|
|
case DOSHISHA:
|
|
return kDoshishaBits; // 40
|
|
case SANYO_LC7461:
|
|
return kSanyoLC7461Bits; // 42
|
|
case GOODWEATHER:
|
|
case MIDEA:
|
|
case PANASONIC:
|
|
return 48;
|
|
case ECOCLIM:
|
|
case MAGIQUEST:
|
|
case VESTEL_AC:
|
|
case TECHNIBEL_AC:
|
|
return 56;
|
|
case AMCOR:
|
|
case CARRIER_AC64:
|
|
case DELONGHI_AC:
|
|
case PIONEER:
|
|
return 64;
|
|
case ARGO:
|
|
return kArgoBits;
|
|
case CORONA_AC:
|
|
return kCoronaAcBits;
|
|
case DAIKIN:
|
|
return kDaikinBits;
|
|
case DAIKIN128:
|
|
return kDaikin128Bits;
|
|
case DAIKIN152:
|
|
return kDaikin152Bits;
|
|
case DAIKIN160:
|
|
return kDaikin160Bits;
|
|
case DAIKIN176:
|
|
return kDaikin176Bits;
|
|
case DAIKIN2:
|
|
return kDaikin2Bits;
|
|
case DAIKIN216:
|
|
return kDaikin216Bits;
|
|
case DAIKIN64:
|
|
return kDaikin64Bits;
|
|
case ELECTRA_AC:
|
|
return kElectraAcBits;
|
|
case GREE:
|
|
return kGreeBits;
|
|
case HAIER_AC:
|
|
return kHaierACBits;
|
|
case HAIER_AC_YRW02:
|
|
return kHaierACYRW02Bits;
|
|
case HITACHI_AC:
|
|
return kHitachiAcBits;
|
|
case HITACHI_AC1:
|
|
return kHitachiAc1Bits;
|
|
case HITACHI_AC2:
|
|
return kHitachiAc2Bits;
|
|
case HITACHI_AC3:
|
|
return kHitachiAc3Bits;
|
|
case HITACHI_AC344:
|
|
return kHitachiAc344Bits;
|
|
case HITACHI_AC424:
|
|
return kHitachiAc424Bits;
|
|
case KELVINATOR:
|
|
return kKelvinatorBits;
|
|
case MILESTAG2:
|
|
return kMilesTag2ShotBits;
|
|
case MIRAGE:
|
|
return kMirageBits;
|
|
case MITSUBISHI_AC:
|
|
return kMitsubishiACBits;
|
|
case MITSUBISHI136:
|
|
return kMitsubishi136Bits;
|
|
case MITSUBISHI112:
|
|
return kMitsubishi112Bits;
|
|
case MITSUBISHI_HEAVY_152:
|
|
return kMitsubishiHeavy152Bits;
|
|
case MITSUBISHI_HEAVY_88:
|
|
return kMitsubishiHeavy88Bits;
|
|
case NEOCLIMA:
|
|
return kNeoclimaBits;
|
|
case PANASONIC_AC:
|
|
return kPanasonicAcBits;
|
|
case SAMSUNG_AC:
|
|
return kSamsungAcBits;
|
|
case SANYO_AC:
|
|
return kSanyoAcBits;
|
|
case SHARP_AC:
|
|
return kSharpAcBits;
|
|
case TCL112AC:
|
|
return kTcl112AcBits;
|
|
case TOSHIBA_AC:
|
|
return kToshibaACBits;
|
|
case TROTEC:
|
|
return kTrotecBits;
|
|
case VOLTAS:
|
|
return kVoltasBits;
|
|
case WHIRLPOOL_AC:
|
|
return kWhirlpoolAcBits;
|
|
case XMP:
|
|
return kXmpBits;
|
|
// No default amount of bits.
|
|
case FUJITSU_AC:
|
|
case MWM:
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/// Send a simple (up to 64 bits) IR message of a given type.
|
|
/// An unknown/unsupported type will send nothing.
|
|
/// @param[in] type Protocol number/type of the message you want to send.
|
|
/// @param[in] data The data you want to send (up to 64 bits).
|
|
/// @param[in] nbits How many bits long the message is to be.
|
|
/// @param[in] repeat How many repeats to do?
|
|
/// @return True if it is a type we can attempt to send, false if not.
|
|
bool IRsend::send(const decode_type_t type, const uint64_t data,
|
|
const uint16_t nbits, const uint16_t repeat) {
|
|
uint16_t min_repeat __attribute__((unused)) =
|
|
std::max(IRsend::minRepeats(type), repeat);
|
|
switch (type) {
|
|
#if SEND_AIRWELL
|
|
case AIRWELL:
|
|
sendAirwell(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_AIWA_RC_T501
|
|
case AIWA_RC_T501:
|
|
sendAiwaRCT501(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_CARRIER_AC
|
|
case CARRIER_AC:
|
|
sendCarrierAC(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_CARRIER_AC40
|
|
case CARRIER_AC40:
|
|
sendCarrierAC40(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_CARRIER_AC40
|
|
#if SEND_CARRIER_AC64
|
|
case CARRIER_AC64:
|
|
sendCarrierAC64(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_CARRIER_AC64
|
|
#if SEND_COOLIX
|
|
case COOLIX:
|
|
sendCOOLIX(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_DAIKIN64
|
|
case DAIKIN64:
|
|
sendDaikin64(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_DELONGHI_AC
|
|
case DELONGHI_AC:
|
|
sendDelonghiAc(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_DENON
|
|
case DENON:
|
|
sendDenon(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_DISH
|
|
case DISH:
|
|
sendDISH(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_DOSHISHA
|
|
case DOSHISHA:
|
|
sendDoshisha(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_ECOCLIM
|
|
case ECOCLIM:
|
|
sendEcoclim(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_ECOCLIM
|
|
#if SEND_ELITESCREENS
|
|
case ELITESCREENS:
|
|
sendElitescreens(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_ELITESCREENS
|
|
#if SEND_EPSON
|
|
case EPSON:
|
|
sendEpson(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_GICABLE
|
|
case GICABLE:
|
|
sendGICable(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_GOODWEATHER
|
|
case GOODWEATHER:
|
|
sendGoodweather(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_GREE
|
|
case GREE:
|
|
sendGree(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_INAX
|
|
case INAX:
|
|
sendInax(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_INAX
|
|
#if SEND_JVC
|
|
case JVC:
|
|
sendJVC(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_LASERTAG
|
|
case LASERTAG:
|
|
sendLasertag(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_LEGOPF
|
|
case LEGOPF:
|
|
sendLegoPf(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_LG
|
|
case LG:
|
|
sendLG(data, nbits, min_repeat);
|
|
break;
|
|
case LG2:
|
|
sendLG2(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_LUTRON
|
|
case LUTRON:
|
|
sendLutron(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_MAGIQUEST
|
|
case MAGIQUEST:
|
|
sendMagiQuest(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_MAGIQUEST
|
|
#if SEND_METZ
|
|
case METZ:
|
|
sendMetz(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_METZ
|
|
#if SEND_MIDEA
|
|
case MIDEA:
|
|
sendMidea(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_MIDEA
|
|
#if SEND_MIDEA24
|
|
case MIDEA24:
|
|
sendMidea24(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_MIDEA24
|
|
#if SEND_MILESTAG2
|
|
case MILESTAG2:
|
|
sendMilestag2(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_MILESTAG2
|
|
#if SEND_MITSUBISHI
|
|
case MITSUBISHI:
|
|
sendMitsubishi(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_MITSUBISHI2
|
|
case MITSUBISHI2:
|
|
sendMitsubishi2(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_MULTIBRACKETS
|
|
case MULTIBRACKETS:
|
|
sendMultibrackets(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_NIKAI
|
|
case NIKAI:
|
|
sendNikai(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_NEC
|
|
case NEC:
|
|
case NEC_LIKE:
|
|
sendNEC(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_PANASONIC
|
|
case PANASONIC:
|
|
sendPanasonic64(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_PANASONIC
|
|
#if SEND_PANASONIC_AC32
|
|
case PANASONIC_AC32:
|
|
sendPanasonicAC32(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_PANASONIC_AC32
|
|
#if SEND_PIONEER
|
|
case PIONEER:
|
|
sendPioneer(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_RC5
|
|
case RC5:
|
|
case RC5X:
|
|
sendRC5(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_RC6
|
|
case RC6:
|
|
sendRC6(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_RCMM
|
|
case RCMM:
|
|
sendRCMM(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SAMSUNG
|
|
case SAMSUNG:
|
|
sendSAMSUNG(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SAMSUNG36
|
|
case SAMSUNG36:
|
|
sendSamsung36(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SANYO
|
|
case SANYO_LC7461:
|
|
sendSanyoLC7461(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SHARP
|
|
case SHARP:
|
|
sendSharpRaw(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SHERWOOD
|
|
case SHERWOOD:
|
|
sendSherwood(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SONY
|
|
case SONY:
|
|
sendSony(data, nbits, min_repeat);
|
|
break;
|
|
case SONY_38K:
|
|
sendSony38(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_SYMPHONY
|
|
case SYMPHONY:
|
|
sendSymphony(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_TECHNIBEL_AC
|
|
case TECHNIBEL_AC:
|
|
sendTechnibelAc(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_TECO
|
|
case TECO:
|
|
sendTeco(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_TECO
|
|
#if SEND_TRANSCOLD
|
|
case TRANSCOLD:
|
|
sendTranscold(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_TRANSCOLD
|
|
#if SEND_VESTEL_AC
|
|
case VESTEL_AC:
|
|
sendVestelAc(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_WHYNTER
|
|
case WHYNTER:
|
|
sendWhynter(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_XMP
|
|
case XMP:
|
|
sendXmp(data, nbits, min_repeat);
|
|
break;
|
|
#endif
|
|
#if SEND_ZEPEAL
|
|
case ZEPEAL:
|
|
sendZepeal(data, nbits, min_repeat);
|
|
break;
|
|
#endif // SEND_ZEPEAL
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// Send a complex (>= 64 bits) IR message of a given type.
|
|
/// An unknown/unsupported type will send nothing.
|
|
/// @param[in] type Protocol number/type of the message you want to send.
|
|
/// @param[in] state A pointer to the array of bytes that make up the state[].
|
|
/// @param[in] nbytes How many bytes are in the state.
|
|
/// @return True if it is a type we can attempt to send, false if not.
|
|
bool IRsend::send(const decode_type_t type, const uint8_t *state,
|
|
const uint16_t nbytes) {
|
|
switch (type) {
|
|
#if SEND_VOLTAS
|
|
case VOLTAS:
|
|
sendVoltas(state, nbytes);
|
|
break;
|
|
#endif // SEND_VOLTAS
|
|
#if SEND_AMCOR
|
|
case AMCOR:
|
|
sendAmcor(state, nbytes);
|
|
break;
|
|
#endif
|
|
#if SEND_ARGO
|
|
case ARGO:
|
|
sendArgo(state, nbytes);
|
|
break;
|
|
#endif // SEND_ARGO
|
|
#if SEND_CORONA_AC
|
|
case CORONA_AC:
|
|
sendCoronaAc(state, nbytes);
|
|
break;
|
|
#endif // SEND_ARGO
|
|
#if SEND_DAIKIN
|
|
case DAIKIN:
|
|
sendDaikin(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN
|
|
#if SEND_DAIKIN128
|
|
case DAIKIN128:
|
|
sendDaikin128(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN128
|
|
#if SEND_DAIKIN152
|
|
case DAIKIN152:
|
|
sendDaikin152(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN152
|
|
#if SEND_DAIKIN160
|
|
case DAIKIN160:
|
|
sendDaikin160(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN160
|
|
#if SEND_DAIKIN176
|
|
case DAIKIN176:
|
|
sendDaikin176(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN176
|
|
#if SEND_DAIKIN2
|
|
case DAIKIN2:
|
|
sendDaikin2(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN2
|
|
#if SEND_DAIKIN216
|
|
case DAIKIN216:
|
|
sendDaikin216(state, nbytes);
|
|
break;
|
|
#endif // SEND_DAIKIN216
|
|
#if SEND_ELECTRA_AC
|
|
case ELECTRA_AC:
|
|
sendElectraAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_ELECTRA_AC
|
|
#if SEND_FUJITSU_AC
|
|
case FUJITSU_AC:
|
|
sendFujitsuAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_FUJITSU_AC
|
|
#if SEND_GREE
|
|
case GREE:
|
|
sendGree(state, nbytes);
|
|
break;
|
|
#endif // SEND_GREE
|
|
#if SEND_HAIER_AC
|
|
case HAIER_AC:
|
|
sendHaierAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_HAIER_AC
|
|
#if SEND_HAIER_AC_YRW02
|
|
case HAIER_AC_YRW02:
|
|
sendHaierACYRW02(state, nbytes);
|
|
break;
|
|
#endif // SEND_HAIER_AC_YRW02
|
|
#if SEND_HITACHI_AC
|
|
case HITACHI_AC:
|
|
sendHitachiAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_HITACHI_AC
|
|
#if SEND_HITACHI_AC1
|
|
case HITACHI_AC1:
|
|
sendHitachiAC1(state, nbytes);
|
|
break;
|
|
#endif // SEND_HITACHI_AC1
|
|
#if SEND_HITACHI_AC2
|
|
case HITACHI_AC2:
|
|
sendHitachiAC2(state, nbytes);
|
|
break;
|
|
#endif // SEND_HITACHI_AC2
|
|
#if SEND_HITACHI_AC3
|
|
case HITACHI_AC3:
|
|
sendHitachiAc3(state, nbytes);
|
|
break;
|
|
#endif // SEND_HITACHI_AC3
|
|
#if SEND_HITACHI_AC344
|
|
case HITACHI_AC344:
|
|
sendHitachiAc344(state, nbytes);
|
|
break;
|
|
#endif // SEND_HITACHI_AC344
|
|
#if SEND_HITACHI_AC424
|
|
case HITACHI_AC424:
|
|
sendHitachiAc424(state, nbytes);
|
|
break;
|
|
#endif // SEND_HITACHI_AC424
|
|
#if SEND_KELVINATOR
|
|
case KELVINATOR:
|
|
sendKelvinator(state, nbytes);
|
|
break;
|
|
#endif // SEND_KELVINATOR
|
|
#if SEND_MIRAGE
|
|
case MIRAGE:
|
|
sendMirage(state, nbytes);
|
|
break;
|
|
#endif // SEND_MIRAGE
|
|
#if SEND_MITSUBISHI_AC
|
|
case MITSUBISHI_AC:
|
|
sendMitsubishiAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_MITSUBISHI_AC
|
|
#if SEND_MITSUBISHI136
|
|
case MITSUBISHI136:
|
|
sendMitsubishi136(state, nbytes);
|
|
break;
|
|
#endif // SEND_MITSUBISHI136
|
|
#if SEND_MITSUBISHI112
|
|
case MITSUBISHI112:
|
|
sendMitsubishi112(state, nbytes);
|
|
break;
|
|
#endif // SEND_MITSUBISHI112
|
|
#if SEND_MITSUBISHIHEAVY
|
|
case MITSUBISHI_HEAVY_88:
|
|
sendMitsubishiHeavy88(state, nbytes);
|
|
break;
|
|
case MITSUBISHI_HEAVY_152:
|
|
sendMitsubishiHeavy152(state, nbytes);
|
|
break;
|
|
#endif // SEND_MITSUBISHIHEAVY
|
|
#if SEND_MWM
|
|
case MWM:
|
|
sendMWM(state, nbytes);
|
|
break;
|
|
#endif // SEND_MWM
|
|
#if SEND_NEOCLIMA
|
|
case NEOCLIMA:
|
|
sendNeoclima(state, nbytes);
|
|
break;
|
|
#endif // SEND_NEOCLIMA
|
|
#if SEND_PANASONIC_AC
|
|
case PANASONIC_AC:
|
|
sendPanasonicAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_PANASONIC_AC
|
|
#if SEND_SAMSUNG_AC
|
|
case SAMSUNG_AC:
|
|
sendSamsungAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_SAMSUNG_AC
|
|
#if SEND_SANYO_AC
|
|
case SANYO_AC:
|
|
sendSanyoAc(state, nbytes);
|
|
break;
|
|
#endif // SEND_SANYO_AC
|
|
#if SEND_SHARP_AC
|
|
case SHARP_AC:
|
|
sendSharpAc(state, nbytes);
|
|
break;
|
|
#endif // SEND_SHARP_AC
|
|
#if SEND_TCL112AC
|
|
case TCL112AC:
|
|
sendTcl112Ac(state, nbytes);
|
|
break;
|
|
#endif // SEND_TCL112AC
|
|
#if SEND_TOSHIBA_AC
|
|
case TOSHIBA_AC:
|
|
sendToshibaAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_TOSHIBA_AC
|
|
#if SEND_TROTEC
|
|
case TROTEC:
|
|
sendTrotec(state, nbytes);
|
|
break;
|
|
#endif // SEND_TROTEC
|
|
#if SEND_WHIRLPOOL_AC
|
|
case WHIRLPOOL_AC:
|
|
sendWhirlpoolAC(state, nbytes);
|
|
break;
|
|
#endif // SEND_WHIRLPOOL_AC
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|