feat: 全量同步 254 个常用的 Arduino 扩展库文件
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @file IRFeedbackLED.hpp
|
||||
*
|
||||
* @brief All Feedback LED specific functions are contained in this file.
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
*************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2021-2022 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_FEEDBACK_LED_HPP
|
||||
#define _IR_FEEDBACK_LED_HPP
|
||||
|
||||
/** \addtogroup FeedbackLEDFunctions Feedback LED functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "digitalWriteFast.h"
|
||||
|
||||
/**
|
||||
* Contains pin number and enable status of the feedback LED
|
||||
*/
|
||||
struct FeedbackLEDControlStruct {
|
||||
uint8_t FeedbackLEDPin; ///< if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
|
||||
uint8_t LedFeedbackEnabled; ///< LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of pin on IR processing
|
||||
};
|
||||
|
||||
struct FeedbackLEDControlStruct FeedbackLEDControl; ///< The feedback LED control instance
|
||||
|
||||
/**
|
||||
* Enable blinking of feedback LED (LED_BUILTIN is taken as default) on IR sending and receiving
|
||||
* Cannot disable it here!!! Use disableLEDFeedbackForReceive() or disableLEDFeedbackForSend()
|
||||
* @param aFeedbackLEDPin If aFeedbackLEDPin == 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
|
||||
* If FeedbackLEDPin == 0 and no LED_BUILTIN defined, disable LED feedback
|
||||
* @param aEnableLEDFeedback If LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of Feedback LED
|
||||
*/
|
||||
void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback) {
|
||||
|
||||
FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin; // default is 0 -> use LED_BUILTIN if available, else disable feedback
|
||||
|
||||
if (aEnableLEDFeedback != DO_NOT_ENABLE_LED_FEEDBACK) {
|
||||
FeedbackLEDControl.LedFeedbackEnabled |= aEnableLEDFeedback;
|
||||
if (aFeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
|
||||
pinMode(aFeedbackLEDPin, OUTPUT);
|
||||
#if defined(LED_BUILTIN)
|
||||
} else {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
#else
|
||||
FeedbackLEDControl.LedFeedbackEnabled = LED_FEEDBACK_DISABLED_COMPLETELY; // we have no LED_BUILTIN available
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Direct replacement for blink13()
|
||||
*/
|
||||
void setLEDFeedback(bool aEnableLEDFeedback) {
|
||||
bool tEnableLEDFeedback = LED_FEEDBACK_DISABLED_COMPLETELY;
|
||||
if (aEnableLEDFeedback) {
|
||||
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND | LED_FEEDBACK_ENABLED_FOR_RECEIVE;
|
||||
}
|
||||
setLEDFeedback(FeedbackLEDControl.FeedbackLEDPin, tEnableLEDFeedback);
|
||||
}
|
||||
|
||||
void enableLEDFeedback() {
|
||||
FeedbackLEDControl.LedFeedbackEnabled |= LED_FEEDBACK_ENABLED_FOR_RECEIVE;
|
||||
}
|
||||
|
||||
void disableLEDFeedback() {
|
||||
FeedbackLEDControl.LedFeedbackEnabled &= ~(LED_FEEDBACK_ENABLED_FOR_RECEIVE);
|
||||
}
|
||||
|
||||
void enableLEDFeedbackForSend() {
|
||||
FeedbackLEDControl.LedFeedbackEnabled |= LED_FEEDBACK_ENABLED_FOR_SEND;
|
||||
}
|
||||
|
||||
void disableLEDFeedbackForSend() {
|
||||
FeedbackLEDControl.LedFeedbackEnabled &= ~(LED_FEEDBACK_ENABLED_FOR_SEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flash LED while receiving or sending IR data. Does not check if enabled, this must be done by the caller.
|
||||
* Handles the 0 value of FeedbackLEDPin and the macro FEEDBACK_LED_IS_ACTIVE_LOW.
|
||||
*/
|
||||
#if defined(ESP32) || defined(ESP8266)
|
||||
IRAM_ATTR
|
||||
#endif
|
||||
void setFeedbackLED(bool aSwitchLedOn) {
|
||||
if (aSwitchLedOn) {
|
||||
if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
|
||||
#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
|
||||
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED on
|
||||
#else
|
||||
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED on
|
||||
#endif
|
||||
#if defined(LED_BUILTIN) // use fast macros here
|
||||
} else {
|
||||
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
|
||||
digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
|
||||
# else
|
||||
digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
|
||||
#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
|
||||
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED off
|
||||
#else
|
||||
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED off
|
||||
#endif
|
||||
#if defined(LED_BUILTIN) // use fast macros here
|
||||
} else {
|
||||
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
|
||||
digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
|
||||
# else
|
||||
digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Old deprecated function name for setLEDFeedback() or enableLEDFeedback() / disableLEDFeedback()
|
||||
*/
|
||||
void IRrecv::blink13(uint8_t aEnableLEDFeedback) {
|
||||
setLEDFeedback(FeedbackLEDControl.FeedbackLEDPin, aEnableLEDFeedback);
|
||||
}
|
||||
/**
|
||||
* Old deprecated function name for setLEDFeedback()
|
||||
*/
|
||||
void setBlinkPin(uint8_t aBlinkPin) {
|
||||
setLEDFeedback(aBlinkPin, FeedbackLEDControl.LedFeedbackEnabled);
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
|
||||
#endif // _IR_FEEDBACK_LED_HPP
|
||||
103
arduino-libs/arduino-cli/libraries/IRremote/src/IRProtocol.h
Normal file
103
arduino-libs/arduino-cli/libraries/IRremote/src/IRProtocol.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file IRProtocol.h
|
||||
* @brief Common declarations for receiving and sending.
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-2021 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_PROTOCOL_H
|
||||
#define _IR_PROTOCOL_H
|
||||
|
||||
/**
|
||||
* An enum consisting of all supported formats.
|
||||
* You do NOT need to remove entries from this list when disabling protocols!
|
||||
*/
|
||||
typedef enum {
|
||||
UNKNOWN = 0,
|
||||
PULSE_DISTANCE,
|
||||
PULSE_WIDTH,
|
||||
DENON,
|
||||
DISH,
|
||||
JVC,
|
||||
LG,
|
||||
LG2,
|
||||
NEC,
|
||||
PANASONIC,
|
||||
KASEIKYO,
|
||||
KASEIKYO_JVC,
|
||||
KASEIKYO_DENON,
|
||||
KASEIKYO_SHARP,
|
||||
KASEIKYO_MITSUBISHI,
|
||||
RC5,
|
||||
RC6,
|
||||
SAMSUNG,
|
||||
SHARP,
|
||||
SONY,
|
||||
ONKYO,
|
||||
APPLE,
|
||||
BOSEWAVE,
|
||||
LEGO_PF,
|
||||
MAGIQUEST,
|
||||
WHYNTER,
|
||||
} decode_type_t;
|
||||
|
||||
const __FlashStringHelper* getProtocolString(decode_type_t aProtocol);
|
||||
|
||||
#define PROTOCOL_IS_LSB_FIRST false
|
||||
#define PROTOCOL_IS_MSB_FIRST true
|
||||
|
||||
/*
|
||||
* Carrier frequencies for various protocols
|
||||
*/
|
||||
#define SONY_KHZ 40
|
||||
#define BOSEWAVE_KHZ 38
|
||||
#define DENON_KHZ 38
|
||||
#define JVC_KHZ 38
|
||||
#define LG_KHZ 38
|
||||
#define NEC_KHZ 38
|
||||
#define SAMSUNG_KHZ 38
|
||||
#define KASEIKYO_KHZ 37
|
||||
#define RC5_RC6_KHZ 36
|
||||
|
||||
/*
|
||||
* Constants for some protocols
|
||||
*/
|
||||
#define PANASONIC_VENDOR_ID_CODE 0x2002
|
||||
#define DENON_VENDOR_ID_CODE 0x3254
|
||||
#define MITSUBISHI_VENDOR_ID_CODE 0xCB23
|
||||
#define SHARP_VENDOR_ID_CODE 0x5AAA
|
||||
#define JVC_VENDOR_ID_CODE 0x0103
|
||||
|
||||
#define SIRCS_12_PROTOCOL 12
|
||||
#define SIRCS_15_PROTOCOL 15
|
||||
#define SIRCS_20_PROTOCOL 20
|
||||
|
||||
#define LEGO_MODE_EXTENDED 0
|
||||
#define LEGO_MODE_COMBO 1
|
||||
#define LEGO_MODE_SINGLE 0x4 // here the 2 LSB have meanings like Output A / Output B
|
||||
|
||||
#endif // _IR_PROTOCOL_H
|
||||
1588
arduino-libs/arduino-cli/libraries/IRremote/src/IRReceive.hpp
Normal file
1588
arduino-libs/arduino-cli/libraries/IRremote/src/IRReceive.hpp
Normal file
File diff suppressed because it is too large
Load Diff
645
arduino-libs/arduino-cli/libraries/IRremote/src/IRSend.hpp
Normal file
645
arduino-libs/arduino-cli/libraries/IRremote/src/IRSend.hpp
Normal file
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* IRSend.hpp
|
||||
*
|
||||
* Contains common functions for sending
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2009-2022 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_SEND_HPP
|
||||
#define _IR_SEND_HPP
|
||||
|
||||
/*
|
||||
* This improves readability of code by avoiding a lot of #if defined clauses
|
||||
*/
|
||||
#if defined(IR_SEND_PIN)
|
||||
#define sendPin IR_SEND_PIN
|
||||
#endif
|
||||
|
||||
#include "digitalWriteFast.h"
|
||||
|
||||
/** \addtogroup Sending Sending IR data for multiple protocols
|
||||
* @{
|
||||
*/
|
||||
|
||||
// The sender instance
|
||||
IRsend IrSender;
|
||||
|
||||
IRsend::IRsend() { // @suppress("Class members should be properly initialized")
|
||||
#if !defined(IR_SEND_PIN)
|
||||
sendPin = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(NO_LED_FEEDBACK_CODE)
|
||||
setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(IR_SEND_PIN)
|
||||
/**
|
||||
* Simple start with defaults - LED feedback enabled! Used if IR_SEND_PIN is defined. Saves program memory.
|
||||
*/
|
||||
void IRsend::begin(){
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aFeedbackLEDPin if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
|
||||
*/
|
||||
void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
|
||||
#if !defined(NO_LED_FEEDBACK_CODE)
|
||||
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
|
||||
if(aEnableLEDFeedback) {
|
||||
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
|
||||
}
|
||||
setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
|
||||
#else
|
||||
(void) aEnableLEDFeedback;
|
||||
(void) aFeedbackLEDPin;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // defined(IR_SEND_PIN)
|
||||
IRsend::IRsend(uint_fast8_t aSendPin) { // @suppress("Class members should be properly initialized")
|
||||
sendPin = aSendPin;
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the send pin and enable LED feedback with board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
|
||||
* @param aSendPin The Arduino pin number, where a IR sender diode is connected.
|
||||
*/
|
||||
void IRsend::begin(uint_fast8_t aSendPin) {
|
||||
sendPin = aSendPin;
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
|
||||
# endif
|
||||
}
|
||||
|
||||
void IRsend::setSendPin(uint_fast8_t aSendPin) {
|
||||
sendPin = aSendPin;
|
||||
}
|
||||
#endif // defined(IR_SEND_PIN)
|
||||
|
||||
/**
|
||||
* Initializes the send and feedback pin
|
||||
* @param aSendPin The Arduino pin number, where a IR sender diode is connected.
|
||||
* @param aFeedbackLEDPin if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
|
||||
*/
|
||||
void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
|
||||
#if defined(IR_SEND_PIN)
|
||||
(void) aSendPin; // for backwards compatibility
|
||||
#else
|
||||
sendPin = aSendPin;
|
||||
#endif
|
||||
|
||||
#if !defined(NO_LED_FEEDBACK_CODE)
|
||||
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
|
||||
if (aEnableLEDFeedback) {
|
||||
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
|
||||
}
|
||||
setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
|
||||
#else
|
||||
(void) aEnableLEDFeedback;
|
||||
(void) aFeedbackLEDPin;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aIRSendData The values of protocol, address, command and repeat flag are taken for sending.
|
||||
* @param aNumberOfRepeats Number of repeats to send after the initial data.
|
||||
*/
|
||||
size_t IRsend::write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats) {
|
||||
|
||||
auto tProtocol = aIRSendData->protocol;
|
||||
auto tAddress = aIRSendData->address;
|
||||
auto tCommand = aIRSendData->command;
|
||||
bool tSendRepeat = (aIRSendData->flags & IRDATA_FLAGS_IS_REPEAT);
|
||||
// switch (tProtocol) { // 26 bytes bigger than if, else if, else
|
||||
// case NEC:
|
||||
// sendNEC(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
|
||||
// break;
|
||||
// case SAMSUNG:
|
||||
// sendSamsung(tAddress, tCommand, aNumberOfRepeats);
|
||||
// break;
|
||||
// case SONY:
|
||||
// sendSony(tAddress, tCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
|
||||
// break;
|
||||
// case PANASONIC:
|
||||
// sendPanasonic(tAddress, tCommand, aNumberOfRepeats);
|
||||
// break;
|
||||
// case DENON:
|
||||
// sendDenon(tAddress, tCommand, aNumberOfRepeats);
|
||||
// break;
|
||||
// case SHARP:
|
||||
// sendSharp(tAddress, tCommand, aNumberOfRepeats);
|
||||
// break;
|
||||
// case JVC:
|
||||
// sendJVC((uint8_t) tAddress, (uint8_t) tCommand, aNumberOfRepeats); // casts are required to specify the right function
|
||||
// break;
|
||||
// case RC5:
|
||||
// sendRC5(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
|
||||
// break;
|
||||
// case RC6:
|
||||
// // No toggle for repeats// sendRC6(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
/*
|
||||
* Order of protocols is in guessed relevance :-)
|
||||
*/
|
||||
if (tProtocol == NEC) {
|
||||
sendNEC(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
|
||||
|
||||
} else if (tProtocol == SAMSUNG) {
|
||||
sendSamsung(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == SONY) {
|
||||
sendSony(tAddress, tCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
|
||||
|
||||
} else if (tProtocol == PANASONIC) {
|
||||
sendPanasonic(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == DENON) {
|
||||
sendDenon(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == SHARP) {
|
||||
sendSharp(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == LG) {
|
||||
sendLG(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
|
||||
|
||||
} else if (tProtocol == JVC) {
|
||||
sendJVC((uint8_t) tAddress, (uint8_t) tCommand, aNumberOfRepeats); // casts are required to specify the right function
|
||||
|
||||
} else if (tProtocol == RC5) {
|
||||
sendRC5(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
|
||||
|
||||
} else if (tProtocol == RC6) {
|
||||
sendRC6(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
|
||||
|
||||
} else if (tProtocol == KASEIKYO_JVC) {
|
||||
sendKaseikyo_JVC(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == KASEIKYO_DENON) {
|
||||
sendKaseikyo_Denon(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == KASEIKYO_SHARP) {
|
||||
sendKaseikyo_Sharp(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == KASEIKYO_MITSUBISHI) {
|
||||
sendKaseikyo_Mitsubishi(tAddress, tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == ONKYO) {
|
||||
sendOnkyo(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
|
||||
|
||||
} else if (tProtocol == APPLE) {
|
||||
sendApple(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
|
||||
|
||||
#if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
|
||||
} else if (tProtocol == BOSEWAVE) {
|
||||
sendBoseWave(tCommand, aNumberOfRepeats);
|
||||
|
||||
} else if (tProtocol == LEGO_PF) {
|
||||
sendLegoPowerFunctions(tAddress, tCommand, tCommand >> 4, tSendRepeat); // send 5 autorepeats
|
||||
#endif
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function using an 16 byte microsecond timing array for every purpose.
|
||||
* Raw data starts with a Mark. No leading space as in received timing data!
|
||||
*/
|
||||
void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(aIRFrequencyKilohertz);
|
||||
|
||||
/*
|
||||
* Raw data starts with a mark.
|
||||
*/
|
||||
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
|
||||
if (i & 1) {
|
||||
// Odd
|
||||
space(aBufferWithMicroseconds[i]);
|
||||
} else {
|
||||
mark(aBufferWithMicroseconds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* New function using an 8 byte tick timing array to save program memory
|
||||
* Raw data starts with a Mark. No leading space as in received timing data!
|
||||
*/
|
||||
void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(aIRFrequencyKilohertz);
|
||||
|
||||
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
|
||||
if (i & 1) {
|
||||
// Odd
|
||||
space(aBufferWithTicks[i] * MICROS_PER_TICK);
|
||||
} else {
|
||||
mark(aBufferWithTicks[i] * MICROS_PER_TICK);
|
||||
}
|
||||
}
|
||||
IRLedOff(); // Always end with the LED off
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function using an 16 byte microsecond timing array in FLASH for every purpose.
|
||||
* Raw data starts with a Mark. No leading space as in received timing data!
|
||||
*/
|
||||
void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
|
||||
#if !defined(__AVR__)
|
||||
sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
|
||||
#else
|
||||
// Set IR carrier frequency
|
||||
enableIROut(aIRFrequencyKilohertz);
|
||||
/*
|
||||
* Raw data starts with a mark
|
||||
*/
|
||||
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
|
||||
unsigned int duration = pgm_read_word(&aBufferWithMicroseconds[i]);
|
||||
if (i & 1) {
|
||||
// Odd
|
||||
space(duration);
|
||||
} else {
|
||||
mark(duration);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* New function using an 8 byte tick timing array in FLASH to save program memory
|
||||
* Raw data starts with a Mark. No leading space as in received timing data!
|
||||
*/
|
||||
void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
|
||||
#if !defined(__AVR__)
|
||||
sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
|
||||
#else
|
||||
// Set IR carrier frequency
|
||||
enableIROut(aIRFrequencyKilohertz);
|
||||
|
||||
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
|
||||
unsigned int duration = pgm_read_byte(&aBufferWithTicks[i]) * (unsigned int) MICROS_PER_TICK;
|
||||
if (i & 1) {
|
||||
// Odd
|
||||
space(duration);
|
||||
} else {
|
||||
mark(duration);
|
||||
}
|
||||
}
|
||||
IRLedOff(); // Always end with the LED off
|
||||
IrReceiver.restartAfterSend();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends PulseDistance data
|
||||
* The output always ends with a space
|
||||
*/
|
||||
void IRsend::sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
|
||||
unsigned int aZeroSpaceMicros, uint32_t aData, uint_fast8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit) {
|
||||
|
||||
if (aMSBfirst) { // Send the MSB first.
|
||||
// send data from MSB to LSB until mask bit is shifted out
|
||||
for (uint32_t tMask = 1UL << (aNumberOfBits - 1); tMask; tMask >>= 1) {
|
||||
if (aData & tMask) {
|
||||
IR_TRACE_PRINT('1');
|
||||
mark(aOneMarkMicros);
|
||||
space(aOneSpaceMicros);
|
||||
} else {
|
||||
IR_TRACE_PRINT('0');
|
||||
mark(aZeroMarkMicros);
|
||||
space(aZeroSpaceMicros);
|
||||
}
|
||||
}
|
||||
} else { // Send the Least Significant Bit (LSB) first / MSB last.
|
||||
for (uint_fast8_t bit = 0; bit < aNumberOfBits; bit++, aData >>= 1)
|
||||
if (aData & 1) { // Send a 1
|
||||
IR_TRACE_PRINT('1');
|
||||
mark(aOneMarkMicros);
|
||||
space(aOneSpaceMicros);
|
||||
} else { // Send a 0
|
||||
IR_TRACE_PRINT('0');
|
||||
mark(aZeroMarkMicros);
|
||||
space(aZeroSpaceMicros);
|
||||
}
|
||||
}
|
||||
if (aSendStopBit) {
|
||||
IR_TRACE_PRINT('S');
|
||||
mark(aZeroMarkMicros); // seems like this is used for stop bits
|
||||
}
|
||||
IR_TRACE_PRINTLN(F(""));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends Biphase data MSB first
|
||||
* Always send start bit, do not send the trailing space of the start bit
|
||||
* 0 -> mark+space
|
||||
* 1 -> space+mark
|
||||
* The output always ends with a space
|
||||
*/
|
||||
void IRsend::sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
|
||||
|
||||
// do not send the trailing space of the start bit
|
||||
mark(aBiphaseTimeUnit);
|
||||
|
||||
IR_TRACE_PRINT('S');
|
||||
uint_fast8_t tLastBitValue = 1; // Start bit is a 1
|
||||
|
||||
// Data - Biphase code MSB first
|
||||
for (uint32_t tMask = 1UL << (aNumberOfBits - 1); tMask; tMask >>= 1) {
|
||||
if (aData & tMask) {
|
||||
IR_TRACE_PRINT('1');
|
||||
space(aBiphaseTimeUnit);
|
||||
mark(aBiphaseTimeUnit);
|
||||
tLastBitValue = 1;
|
||||
|
||||
} else {
|
||||
IR_TRACE_PRINT('0');
|
||||
#if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
|
||||
if (tLastBitValue) {
|
||||
// Extend the current mark in order to generate a continuous signal without short breaks
|
||||
delayMicroseconds(aBiphaseTimeUnit);
|
||||
} else {
|
||||
mark(aBiphaseTimeUnit);
|
||||
}
|
||||
#else
|
||||
(void) tLastBitValue; // to avoid compiler warnings
|
||||
mark(aBiphaseTimeUnit); // can not eventually delay here, we must call mark to generate the signal
|
||||
#endif
|
||||
space(aBiphaseTimeUnit);
|
||||
tLastBitValue = 0;
|
||||
}
|
||||
}
|
||||
IR_TRACE_PRINTLN(F(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an IR mark for the specified number of microseconds.
|
||||
* The mark output is modulated at the PWM frequency if USE_NO_SEND_PWM is not defined.
|
||||
* The output is guaranteed to be OFF / inactive after after the call of the function.
|
||||
* This function may affect the state of feedback LED.
|
||||
*/
|
||||
void IRsend::mark(unsigned int aMarkMicros) {
|
||||
|
||||
#if defined(SEND_PWM_BY_TIMER)
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(true);
|
||||
}
|
||||
# endif
|
||||
ENABLE_SEND_PWM_BY_TIMER; // Enable timer or ledcWrite() generated PWM output
|
||||
customDelayMicroseconds(aMarkMicros);
|
||||
IRLedOff(); // manages also feedback LED
|
||||
|
||||
#elif defined(USE_NO_SEND_PWM)
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(true);
|
||||
}
|
||||
# endif
|
||||
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
|
||||
pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
|
||||
# else
|
||||
digitalWriteFast(sendPin, LOW); // Set output to active low.
|
||||
# endif
|
||||
|
||||
customDelayMicroseconds(aMarkMicros);
|
||||
IRLedOff();
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(false);
|
||||
}
|
||||
# endif
|
||||
|
||||
#else
|
||||
unsigned long startMicros = micros();
|
||||
unsigned long nextPeriodEnding = startMicros;
|
||||
unsigned long tMicros;
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
bool FeedbackLedIsActive = false;
|
||||
# endif
|
||||
|
||||
do {
|
||||
// digitalToggleFast(_IR_TIMING_TEST_PIN);
|
||||
// Output the PWM pulse
|
||||
noInterrupts(); // do not let interrupts extend the short on period
|
||||
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
|
||||
# if defined(OUTPUT_OPEN_DRAIN)
|
||||
digitalWriteFast(sendPin, LOW); // active state for open drain
|
||||
# else
|
||||
pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
|
||||
# endif
|
||||
# else
|
||||
// 3.5 us from FeedbackLed on to pin setting. 5.7 us from call of mark() to pin setting incl. setting of feedback pin.
|
||||
// 4.3 us from do{ to pin setting if sendPin is no constant
|
||||
digitalWriteFast(sendPin, HIGH);
|
||||
# endif
|
||||
delayMicroseconds (periodOnTimeMicros); // this is normally implemented by a blocking wait
|
||||
|
||||
// Output the PWM pause
|
||||
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
|
||||
# if defined(OUTPUT_OPEN_DRAIN)
|
||||
digitalWriteFast(sendPin, HIGH); // Set output with pin mode OUTPUT_OPEN_DRAIN to inactive high.
|
||||
# else
|
||||
pinModeFast(sendPin, INPUT); // to mimic the open drain inactive state
|
||||
# endif
|
||||
|
||||
# else
|
||||
digitalWriteFast(sendPin, LOW);
|
||||
# endif
|
||||
interrupts(); // Enable interrupts -to keep micros correct- for the longer off period 3.4 us until receive ISR is active (for 7 us + pop's)
|
||||
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
/*
|
||||
* Delayed call of setFeedbackLED() to get better timing
|
||||
*/
|
||||
if (!FeedbackLedIsActive) {
|
||||
FeedbackLedIsActive = true;
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(true);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
/*
|
||||
* Pause timing
|
||||
*/
|
||||
nextPeriodEnding += periodTimeMicros;
|
||||
do {
|
||||
tMicros = micros(); // we have only 4 us resolution for AVR @16MHz
|
||||
// check for aMarkMicros to be gone
|
||||
unsigned int tDeltaMicros = tMicros - startMicros;
|
||||
#if defined(__AVR__)
|
||||
// tDeltaMicros += (160 / CLOCKS_PER_MICRO); // adding this once increases program size !
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) { // 30 to be constant. Using periodTimeMicros increases program size too much.
|
||||
// reset feedback led in the last pause before end
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(false);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) { // To compensate for call duration - 112 is an empirical value
|
||||
#else
|
||||
if (tDeltaMicros >= aMarkMicros) {
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(false);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// digitalToggleFast(_IR_TIMING_TEST_PIN); // 3.0 us per call @16MHz
|
||||
} while (tMicros < nextPeriodEnding); // 3.4 us @16MHz
|
||||
} while (true);
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Just switch the IR sending LED off to send an IR space
|
||||
* A space is "no output", so the PWM output is disabled.
|
||||
* This function may affect the state of feedback LED.
|
||||
*/
|
||||
void IRsend::IRLedOff() {
|
||||
#if defined(SEND_PWM_BY_TIMER)
|
||||
DISABLE_SEND_PWM_BY_TIMER; // Disable PWM output
|
||||
#elif defined(USE_NO_SEND_PWM)
|
||||
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
|
||||
digitalWriteFast(sendPin, LOW); // prepare for all next active states.
|
||||
pinModeFast(sendPin, INPUT); // inactive state for open drain
|
||||
# else
|
||||
digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
|
||||
# endif
|
||||
#else
|
||||
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
|
||||
# if defined(OUTPUT_OPEN_DRAIN)
|
||||
digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
|
||||
# else
|
||||
pinModeFast(sendPin, INPUT); // inactive state to mimic open drain
|
||||
# endif
|
||||
# else
|
||||
digitalWriteFast(sendPin, LOW);
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(NO_LED_FEEDBACK_CODE)
|
||||
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
|
||||
setFeedbackLED(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an IR space for the specified number of microseconds.
|
||||
* A space is "no output", so just wait.
|
||||
*/
|
||||
void IRsend::space(unsigned int aSpaceMicros) {
|
||||
customDelayMicroseconds(aSpaceMicros);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom delay function that circumvents Arduino's delayMicroseconds 16 bit limit
|
||||
* and is (mostly) not extended by the duration of interrupt codes like the millis() interrupt
|
||||
*/
|
||||
void IRsend::customDelayMicroseconds(unsigned long aMicroseconds) {
|
||||
#if defined(__AVR__)
|
||||
unsigned long start = micros() - (64 / clockCyclesPerMicrosecond()); // - (64 / clockCyclesPerMicrosecond()) for reduced resolution and additional overhead
|
||||
#else
|
||||
unsigned long start = micros();
|
||||
#endif
|
||||
// overflow invariant comparison :-)
|
||||
while (micros() - start < aMicroseconds) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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-40 kHz and for software generation gives 26 us for 38.46 kHz, 27 us for 37.04 kHz and 25 us for 40 kHz.
|
||||
* 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 16 MHz / (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://www.righto.com/2009/07/secrets-of-arduino-pwm.html for details.
|
||||
*/
|
||||
void IRsend::enableIROut(uint_fast8_t aFrequencyKHz) {
|
||||
#if defined(SEND_PWM_BY_TIMER)
|
||||
timerConfigForSend(aFrequencyKHz); // must set output pin mode and disable receive interrupt if required, e.g. uses the same resource
|
||||
|
||||
#elif defined(USE_NO_SEND_PWM)
|
||||
(void) aFrequencyKHz;
|
||||
|
||||
#else
|
||||
periodTimeMicros = (1000U + (aFrequencyKHz / 2)) / aFrequencyKHz; // rounded value -> 26 for 38.46 kHz, 27 for 37.04 kHz, 25 for 40 kHz.
|
||||
# if defined(IR_SEND_PIN)
|
||||
periodOnTimeMicros = (((periodTimeMicros * IR_SEND_DUTY_CYCLE_PERCENT) + 50) / 100U); // +50 for rounding -> 830/100 for 30% and 16 MHz
|
||||
# else
|
||||
// Heuristics! We require a nanosecond correction for "slow" digitalWrite() functions
|
||||
periodOnTimeMicros = (((periodTimeMicros * IR_SEND_DUTY_CYCLE_PERCENT) + 50 - (PULSE_CORRECTION_NANOS / 10)) / 100U); // +50 for rounding -> 530/100 for 30% and 16 MHz
|
||||
# endif
|
||||
#endif // defined(SEND_PWM_BY_TIMER)
|
||||
|
||||
#if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && defined(OUTPUT_OPEN_DRAIN) // the mode INPUT for mimicking open drain is set at IRLedOff()
|
||||
# if defined(IR_SEND_PIN)
|
||||
pinModeFast(IR_SEND_PIN, OUTPUT_OPEN_DRAIN);
|
||||
# else
|
||||
pinModeFast(sendPin, OUTPUT_OPEN_DRAIN);
|
||||
# endif
|
||||
#else
|
||||
# if !(defined(SEND_PWM_BY_TIMER) && defined(ESP32)) // ledcWrite since ESP 2.0.2 does not work if pin mode is set
|
||||
# if defined(IR_SEND_PIN)
|
||||
pinModeFast(IR_SEND_PIN, OUTPUT);
|
||||
# else
|
||||
pinModeFast(sendPin, OUTPUT);
|
||||
# endif
|
||||
# endif
|
||||
#endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
|
||||
}
|
||||
|
||||
unsigned int IRsend::getPulseCorrectionNanos() {
|
||||
return PULSE_CORRECTION_NANOS;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_SEND_HPP
|
||||
14
arduino-libs/arduino-cli/libraries/IRremote/src/IRremote.h
Normal file
14
arduino-libs/arduino-cli/libraries/IRremote/src/IRremote.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @file IRremote.h
|
||||
*
|
||||
* @brief Stub for backward compatibility
|
||||
*/
|
||||
|
||||
#ifndef IRremote_h
|
||||
#define IRremote_h
|
||||
|
||||
#include "IRremote.hpp"
|
||||
|
||||
#endif // IRremote_h
|
||||
#pragma once
|
||||
|
||||
357
arduino-libs/arduino-cli/libraries/IRremote/src/IRremote.hpp
Normal file
357
arduino-libs/arduino-cli/libraries/IRremote/src/IRremote.hpp
Normal file
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* @file IRremote.hpp
|
||||
*
|
||||
* @brief Public API to the library.
|
||||
*
|
||||
* @code
|
||||
* !!! All the macro values defined here can be overwritten with values, !!!
|
||||
* !!! the user defines in its source code BEFORE the #include <IRremote.hpp> !!!
|
||||
* @endcode
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2015-2022 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*
|
||||
* For Ken Shiriffs original blog entry, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
|
||||
* Initially influenced by:
|
||||
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
|
||||
* and http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
|
||||
*/
|
||||
|
||||
/*
|
||||
* This library can be configured at compile time by the following options / macros:
|
||||
* For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
|
||||
*
|
||||
* - RAW_BUFFER_LENGTH Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits.
|
||||
* - IR_SEND_PIN If specified (as constant), reduces program size and improves send timing for AVR.
|
||||
* - SEND_PWM_BY_TIMER Disable carrier PWM generation in software and use (restricted) hardware PWM.
|
||||
* - USE_NO_SEND_PWM Use no carrier PWM, just simulate an **active low** receiver signal. Overrides SEND_PWM_BY_TIMER definition.
|
||||
* - USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
|
||||
* - EXCLUDE_EXOTIC_PROTOCOLS If activated, BOSEWAVE, WHYNTER and LEGO_PF are excluded in decode() and in sending with IrSender.write().
|
||||
* - EXCLUDE_UNIVERSAL_PROTOCOLS If activated, the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) are excluded in decode().
|
||||
* - DECODE_* Selection of individual protocols to be decoded. See below.
|
||||
* - MARK_EXCESS_MICROS Value is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules.
|
||||
* - RECORD_GAP_MICROS Minimum gap between IR transmissions, to detect the end of a protocol.
|
||||
* - FEEDBACK_LED_IS_ACTIVE_LOW Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low.
|
||||
* - NO_LED_FEEDBACK_CODE This completely disables the LED feedback code for send and receive.
|
||||
* - IR_INPUT_IS_ACTIVE_HIGH Enable it if you use a RF receiver, which has an active HIGH output signal.
|
||||
* - IR_SEND_DUTY_CYCLE_PERCENT Duty cycle of IR send signal.
|
||||
* - MICROS_PER_TICK Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 us at 38 kHz.
|
||||
* - IR_USE_AVR_TIMER* Selection of timer to be used for generating IR receiving sample interval.
|
||||
*/
|
||||
|
||||
#ifndef _IR_REMOTE_HPP
|
||||
#define _IR_REMOTE_HPP
|
||||
|
||||
#define VERSION_IRREMOTE "3.7.1"
|
||||
#define VERSION_IRREMOTE_MAJOR 3
|
||||
#define VERSION_IRREMOTE_MINOR 7
|
||||
#define VERSION_IRREMOTE_PATCH 1
|
||||
|
||||
/*
|
||||
* Macro to convert 3 version parts into an integer
|
||||
* To be used in preprocessor comparisons, such as #if VERSION_IRREMOTE_HEX >= VERSION_HEX_VALUE(3, 7, 0)
|
||||
*/
|
||||
#define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
|
||||
#define VERSION_IRREMOTE_HEX VERSION_HEX_VALUE(VERSION_IRREMOTE_MAJOR, VERSION_IRREMOTE_MINOR, VERSION_IRREMOTE_PATCH)
|
||||
|
||||
// activate it for all cores that does not use the -flto flag, if you get false error messages regarding begin() during compilation.
|
||||
//#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN
|
||||
|
||||
/*
|
||||
* If activated, BOSEWAVE, MAGIQUEST,WHYNTER and LEGO_PF are excluded in decoding and in sending with IrSender.write
|
||||
*/
|
||||
//#define EXCLUDE_EXOTIC_PROTOCOLS
|
||||
/****************************************************
|
||||
* PROTOCOLS
|
||||
****************************************************/
|
||||
/*
|
||||
* Supported IR protocols
|
||||
* Each protocol you include costs memory and, during decode, costs time
|
||||
* Copy the lines with the protocols you need in your program before the #include <IRremote.hpp> line
|
||||
* See also SimpleReceiver example
|
||||
*/
|
||||
|
||||
#if !defined(NO_DECODER) // for sending raw only
|
||||
# if (!(defined(DECODE_DENON) || defined(DECODE_JVC) || defined(DECODE_KASEIKYO) \
|
||||
|| defined(DECODE_PANASONIC) || defined(DECODE_LG) || defined(DECODE_NEC) || defined(DECODE_SAMSUNG) \
|
||||
|| defined(DECODE_SONY) || defined(DECODE_RC5) || defined(DECODE_RC6) \
|
||||
|| defined(DECODE_DISTANCE) || defined(DECODE_HASH) || defined(DECODE_BOSEWAVE) \
|
||||
|| defined(DECODE_LEGO_PF) || defined(DECODE_WHYNTER)))
|
||||
/*
|
||||
* If no protocol is explicitly enabled, we enable all protocols
|
||||
*/
|
||||
#define DECODE_DENON // Includes Sharp
|
||||
#define DECODE_JVC
|
||||
#define DECODE_KASEIKYO
|
||||
#define DECODE_PANASONIC // the same as DECODE_KASEIKYO
|
||||
#define DECODE_LG
|
||||
#define DECODE_NEC // Includes Apple and Onkyo
|
||||
#define DECODE_SAMSUNG
|
||||
#define DECODE_SONY
|
||||
#define DECODE_RC5
|
||||
#define DECODE_RC6
|
||||
|
||||
# if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory
|
||||
#define DECODE_BOSEWAVE
|
||||
#define DECODE_LEGO_PF
|
||||
#define DECODE_WHYNTER
|
||||
#define DECODE_MAGIQUEST // It modifies the RAW_BUFFER_LENGTH from 100 to 112
|
||||
# endif
|
||||
|
||||
# if !defined(EXCLUDE_UNIVERSAL_PROTOCOLS)
|
||||
#define DECODE_DISTANCE // universal decoder for pulse distance protocols - requires up to 750 bytes additional program memory
|
||||
#define DECODE_HASH // special decoder for all protocols - requires up to 250 bytes additional program memory
|
||||
# endif
|
||||
# endif
|
||||
#endif // !defined(NO_DECODER)
|
||||
|
||||
#if defined(DECODE_NEC) && !(~(~DECODE_NEC + 0) == 0 && ~(~DECODE_NEC + 1) == 1)
|
||||
#warning "The macros DECODE_XXX no longer require a value. Decoding is now switched by defining / non defining the macro."
|
||||
#endif
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core.
|
||||
|
||||
/****************************************************
|
||||
* RECEIVING
|
||||
****************************************************/
|
||||
|
||||
/**
|
||||
* The length of the buffer where the IR timing data is stored before decoding
|
||||
* 100 is sufficient for most standard protocols, but air conditioners often send a longer protocol data stream
|
||||
*/
|
||||
#if !defined(RAW_BUFFER_LENGTH)
|
||||
# if defined(DECODE_MAGIQUEST)
|
||||
#define RAW_BUFFER_LENGTH 112 // MagiQuest requires 112 bytes.
|
||||
# else
|
||||
#define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit.
|
||||
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
|
||||
# endif
|
||||
#endif
|
||||
#if RAW_BUFFER_LENGTH % 2 == 1
|
||||
#error RAW_BUFFER_LENGTH must be even, since the array consists of space / mark pairs.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
|
||||
* to compensate for the signal forming of different IR receiver modules
|
||||
* For Vishay TSOP*, marks tend to be too long and spaces tend to be too short.
|
||||
* If you set MARK_EXCESS_MICROS to approx. 50us then the TSOP4838 works best.
|
||||
* At 100us it also worked, but not as well.
|
||||
* Set MARK_EXCESS to 100us and the VS1838 doesn't work at all.
|
||||
*
|
||||
* The right value is critical for IR codes using short pulses like Denon / Sharp / Lego
|
||||
*
|
||||
* Observed values:
|
||||
* Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level.
|
||||
* VS1838 Mark Excess -50 to +50 us
|
||||
* TSOP31238 Mark Excess 0 to +50
|
||||
*/
|
||||
#if !defined(MARK_EXCESS_MICROS)
|
||||
// To change this value, you simply can add a line #define "MARK_EXCESS_MICROS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
|
||||
#define MARK_EXCESS_MICROS 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Minimum gap between IR transmissions, to detect the end of a protocol.
|
||||
* Must be greater than any space of a protocol e.g. the NEC header space of 4500 us.
|
||||
* Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
|
||||
* Keep in mind, that this is the delay between the end of the received command and the start of decoding.
|
||||
*/
|
||||
#if !defined(RECORD_GAP_MICROS)
|
||||
// To change this value, you simply can add a line #define "RECORD_GAP_MICROS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
|
||||
#define RECORD_GAP_MICROS 5000 // FREDRICH28AC / LG2 header space is 9700, NEC header space is 4500
|
||||
#endif
|
||||
/**
|
||||
* Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value.
|
||||
*/
|
||||
#if !defined(RECORD_GAP_MICROS_WARNING_THRESHOLD)
|
||||
// To change this value, you simply can add a line #define "RECORD_GAP_MICROS_WARNING_THRESHOLD <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
|
||||
#define RECORD_GAP_MICROS_WARNING_THRESHOLD 20000
|
||||
#endif
|
||||
|
||||
/** Minimum gap between IR transmissions, in MICROS_PER_TICK */
|
||||
#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) // 221 for 1100
|
||||
|
||||
/*
|
||||
* Activate this line if your receiver has an external output driver transistor / "inverted" output
|
||||
*/
|
||||
//#define IR_INPUT_IS_ACTIVE_HIGH
|
||||
#if defined(IR_INPUT_IS_ACTIVE_HIGH)
|
||||
// IR detector output is active high
|
||||
#define INPUT_MARK 1 ///< Sensor output for a mark ("flash")
|
||||
#else
|
||||
// IR detector output is active low
|
||||
#define INPUT_MARK 0 ///< Sensor output for a mark ("flash")
|
||||
#endif
|
||||
/****************************************************
|
||||
* SENDING
|
||||
****************************************************/
|
||||
/**
|
||||
* Define to disable carrier PWM generation in software and use (restricted) hardware PWM.
|
||||
*/
|
||||
//#define SEND_PWM_BY_TIMER // restricts send pin on many platforms to fixed pin numbers
|
||||
|
||||
#if (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED)
|
||||
# if !defined(SEND_PWM_BY_TIMER)
|
||||
#define SEND_PWM_BY_TIMER // the best and default method for ESP32
|
||||
#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default. If this is not intended, deactivate the line over this warning message in file IRremote.hpp.
|
||||
# endif
|
||||
#else
|
||||
# if defined(SEND_PWM_BY_TIMER)
|
||||
# if defined(IR_SEND_PIN)
|
||||
#undef IR_SEND_PIN // to avoid warning 3 lines later
|
||||
#warning Since SEND_PWM_BY_TIMER is defined, the existing value of IR_SEND_PIN is discarded and replaced by the value determined by timer used for PWM generation
|
||||
# endif
|
||||
#define IR_SEND_PIN DeterminedByTimer // must be set here, since it is evaluated at IRremoteInt.h, before the include of private/IRTimer.hpp
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define to use no carrier PWM, just simulate an active low receiver signal.
|
||||
*/
|
||||
//#define USE_NO_SEND_PWM
|
||||
#if defined(SEND_PWM_BY_TIMER) && defined(USE_NO_SEND_PWM)
|
||||
#warning "SEND_PWM_BY_TIMER and USE_NO_SEND_PWM are both defined -> undefine SEND_PWM_BY_TIMER now!"
|
||||
#undef SEND_PWM_BY_TIMER // USE_NO_SEND_PWM overrides SEND_PWM_BY_TIMER
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define to use or simulate open drain output mode at send pin.
|
||||
* Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
|
||||
*/
|
||||
//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
|
||||
#if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
|
||||
#warning Pin mode OUTPUT_OPEN_DRAIN is not supported on this platform -> fall back to mode OUTPUT.
|
||||
#endif
|
||||
/**
|
||||
* This amount is subtracted from the on-time of the pulses generated for software PWM generation.
|
||||
* It should be the time used for digitalWrite(sendPin, LOW) and the call to delayMicros()
|
||||
* Measured value for Nano @16MHz is around 3000, for Bluepill @72MHz is around 700, for Zero 3600
|
||||
*/
|
||||
#if !defined(PULSE_CORRECTION_NANOS)
|
||||
# if defined(F_CPU)
|
||||
// To change this value, you simply can add a line #define "PULSE_CORRECTION_NANOS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
|
||||
#define PULSE_CORRECTION_NANOS (48000L / (F_CPU/MICROS_IN_ONE_SECOND)) // 3000 @16MHz, 666 @72MHz
|
||||
# else
|
||||
#define PULSE_CORRECTION_NANOS 600
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Duty cycle in percent for sent signals.
|
||||
*/
|
||||
#if ! defined(IR_SEND_DUTY_CYCLE_PERCENT)
|
||||
#define IR_SEND_DUTY_CYCLE_PERCENT 30 // 30 saves power and is compatible to the old existing code
|
||||
#endif
|
||||
|
||||
/**
|
||||
* microseconds per clock interrupt tick
|
||||
*/
|
||||
#if ! defined(MICROS_PER_TICK)
|
||||
#define MICROS_PER_TICK 50
|
||||
#endif
|
||||
|
||||
#define MILLIS_IN_ONE_SECOND 1000L
|
||||
#define MICROS_IN_ONE_SECOND 1000000L
|
||||
#define MICROS_IN_ONE_MILLI 1000L
|
||||
|
||||
#include "IRremoteInt.h"
|
||||
|
||||
#if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)
|
||||
#include "private/IRTimer.hpp" // defines IR_SEND_PIN for AVR and SEND_PWM_BY_TIMER
|
||||
|
||||
# if !defined(NO_LED_FEEDBACK_CODE)
|
||||
# if !defined(LED_BUILTIN)
|
||||
/*
|
||||
* print a warning
|
||||
*/
|
||||
#warning INFO: No definition for LED_BUILTIN found -> default LED feedback is disabled.
|
||||
# endif
|
||||
#include "IRFeedbackLED.hpp"
|
||||
# endif
|
||||
/*
|
||||
* Include the sources here to enable compilation with macro values set by user program.
|
||||
*/
|
||||
#include "IRReceive.hpp"
|
||||
#include "IRSend.hpp"
|
||||
|
||||
/*
|
||||
* Include the sources of all decoders here to enable compilation with macro values set by user program.
|
||||
*/
|
||||
# if defined(DECODE_BOSEWAVE)
|
||||
#include "ir_BoseWave.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_DENON ) // Includes Sharp
|
||||
#include "ir_Denon.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_DISTANCE) // universal decoder for pulse distance protocols - requires up to 750 bytes additional program memory
|
||||
#include "ir_DistanceProtocol.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_JVC)
|
||||
#include "ir_JVC.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_KASEIKYO) || defined(DECODE_PANASONIC)
|
||||
#include "ir_Kaseikyo.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_LEGO_PF)
|
||||
#include "ir_Lego.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_LG)
|
||||
#include "ir_LG.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_MAGIQUEST)
|
||||
#include "ir_MagiQuest.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_NEC) // Includes Apple and Onkyo
|
||||
#include "ir_NEC.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_RC5) || defined(DECODE_RC6)
|
||||
#include "ir_RC5_RC6.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_SAMSUNG)
|
||||
#include "ir_Samsung.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_SONY)
|
||||
#include "ir_Sony.hpp"
|
||||
# endif
|
||||
# if defined(DECODE_WHYNTER)
|
||||
#include "ir_Whynter.hpp"
|
||||
# endif
|
||||
|
||||
#include "ir_Pronto.hpp" // pronto is an universal decoder and encoder
|
||||
|
||||
#include "ir_Dish.hpp" // contains only sendDISH(unsigned long data, int nbits)
|
||||
#endif // #if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)
|
||||
|
||||
/**
|
||||
* Macros for legacy compatibility
|
||||
*/
|
||||
#define RAWBUF 101 // Maximum length of raw duration buffer
|
||||
#define REPEAT 0xFFFFFFFF
|
||||
#define USECPERTICK MICROS_PER_TICK
|
||||
#define MARK_EXCESS MARK_EXCESS_MICROS
|
||||
|
||||
#endif // _IR_REMOTE_HPP
|
||||
532
arduino-libs/arduino-cli/libraries/IRremote/src/IRremoteInt.h
Normal file
532
arduino-libs/arduino-cli/libraries/IRremote/src/IRremoteInt.h
Normal file
@@ -0,0 +1,532 @@
|
||||
/**
|
||||
* @file IRremoteInt.h
|
||||
* @brief Contains all declarations required for the interface to IRremote.
|
||||
* Could not be named IRremote.h, since this has another semantic (it must include all *.hpp files) for old example code found in the wild.
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2015-2022 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_REMOTE_INT_H
|
||||
#define _IR_REMOTE_INT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define MARK 1
|
||||
#define SPACE 0
|
||||
|
||||
#if defined(PARTICLE)
|
||||
#define F_CPU 16000000 // definition for a board for which F_CPU is not defined
|
||||
#endif
|
||||
#if defined(F_CPU) // F_CPU is used to generate the receive send timings in some CPU's
|
||||
#define CLOCKS_PER_MICRO (F_CPU / MICROS_IN_ONE_SECOND)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For backwards compatibility
|
||||
*/
|
||||
#if defined(SYSCLOCK) // allow for processor specific code to define F_CPU
|
||||
#undef F_CPU
|
||||
#define F_CPU SYSCLOCK // Clock frequency to be used for timing.
|
||||
#endif
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
|
||||
//#define TRACE // Activate this for more debug output.
|
||||
|
||||
/**
|
||||
* For better readability of code
|
||||
*/
|
||||
#define DISABLE_LED_FEEDBACK false
|
||||
#define ENABLE_LED_FEEDBACK true
|
||||
#define USE_DEFAULT_FEEDBACK_LED_PIN 0
|
||||
|
||||
#include "IRProtocol.h"
|
||||
|
||||
/****************************************************
|
||||
* Declarations for the receiver Interrupt Service Routine
|
||||
****************************************************/
|
||||
// ISR State-Machine : Receiver States
|
||||
#define IR_REC_STATE_IDLE 0
|
||||
#define IR_REC_STATE_MARK 1
|
||||
#define IR_REC_STATE_SPACE 2
|
||||
#define IR_REC_STATE_STOP 3 // set to IR_REC_STATE_IDLE only by resume()
|
||||
|
||||
/**
|
||||
* This struct contains the data and control used for receiver static functions and the ISR (interrupt service routine)
|
||||
* Only StateForISR needs to be volatile. All the other fields are not written by ISR after data available and before start/resume.
|
||||
*/
|
||||
struct irparams_struct {
|
||||
// The fields are ordered to reduce memory over caused by struct-padding
|
||||
volatile uint8_t StateForISR; ///< State Machine state
|
||||
uint_fast8_t IRReceivePin; ///< Pin connected to IR data from detector
|
||||
#if defined(__AVR__)
|
||||
volatile uint8_t *IRReceivePinPortInputRegister;
|
||||
uint8_t IRReceivePinMask;
|
||||
#endif
|
||||
uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition.
|
||||
|
||||
bool OverflowFlag; ///< Raw buffer OverflowFlag occurred
|
||||
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
|
||||
uint_fast8_t rawlen; ///< counter of entries in rawbuf
|
||||
#else
|
||||
uint_fast16_t rawlen; ///< counter of entries in rawbuf
|
||||
#endif
|
||||
unsigned int rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command
|
||||
};
|
||||
|
||||
/*
|
||||
* Debug directives
|
||||
*/
|
||||
#if defined(DEBUG)
|
||||
# define IR_DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
|
||||
# define IR_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
|
||||
#else
|
||||
/**
|
||||
* If DEBUG, print the arguments, otherwise do nothing.
|
||||
*/
|
||||
# define IR_DEBUG_PRINT(...) void()
|
||||
/**
|
||||
* If DEBUG, print the arguments as a line, otherwise do nothing.
|
||||
*/
|
||||
# define IR_DEBUG_PRINTLN(...) void()
|
||||
#endif
|
||||
|
||||
#if defined(TRACE)
|
||||
# define IR_TRACE_PRINT(...) Serial.print(__VA_ARGS__)
|
||||
# define IR_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__)
|
||||
#else
|
||||
# define IR_TRACE_PRINT(...) void()
|
||||
# define IR_TRACE_PRINTLN(...) void()
|
||||
#endif
|
||||
|
||||
/****************************************************
|
||||
* RECEIVING
|
||||
****************************************************/
|
||||
/*
|
||||
* Definitions for member IRData.flags
|
||||
*/
|
||||
#define IRDATA_FLAGS_EMPTY 0x00
|
||||
#define IRDATA_FLAGS_IS_REPEAT 0x01
|
||||
#define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02
|
||||
#define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check
|
||||
#define IRDATA_TOGGLE_BIT_MASK 0x08 ///< is set if RC5 or RC6 toggle bit is set
|
||||
#define IRDATA_FLAGS_EXTRA_INFO 0x10 ///< there is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID)
|
||||
#define IRDATA_FLAGS_WAS_OVERFLOW 0x40 ///< irparams.rawlen is 0 in this case to avoid endless OverflowFlag
|
||||
#define IRDATA_FLAGS_IS_LSB_FIRST 0x00
|
||||
#define IRDATA_FLAGS_IS_MSB_FIRST 0x80 ///< Just for info. Value is mainly determined by the protocol
|
||||
|
||||
/**
|
||||
* Data structure for the user application, available as decodedIRData.
|
||||
* Filled by decoders and read by print functions or user application.
|
||||
*/
|
||||
struct IRData {
|
||||
decode_type_t protocol; ///< UNKNOWN, NEC, SONY, RC5, ...
|
||||
uint16_t address; ///< Decoded address
|
||||
uint16_t command; ///< Decoded command
|
||||
uint16_t extra; ///< Contains MagiQuest magnitude, Kaseikyo unknown vendor ID and Distance protocol (SpaceTicksShort << 8) | SpaceTicksLong.
|
||||
uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
|
||||
uint8_t flags; ///< See IRDATA_FLAGS_* definitions above
|
||||
uint32_t decodedRawData; ///< Up to 32 bit decoded raw data, to be used for send functions.
|
||||
irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
|
||||
};
|
||||
|
||||
/**
|
||||
* Results returned from old decoders !!!deprecated!!!
|
||||
*/
|
||||
struct decode_results {
|
||||
decode_type_t decode_type; // deprecated, moved to decodedIRData.protocol ///< UNKNOWN, NEC, SONY, RC5, ...
|
||||
uint16_t address; ///< Used by Panasonic & Sharp [16-bits]
|
||||
uint32_t value; // deprecated, moved to decodedIRData.decodedRawData ///< Decoded value / command [max 32-bits]
|
||||
uint8_t bits; // deprecated, moved to decodedIRData.numberOfBits ///< Number of bits in decoded value
|
||||
uint16_t magnitude; // deprecated, moved to decodedIRData.extra ///< Used by MagiQuest [16-bits]
|
||||
bool isRepeat; // deprecated, moved to decodedIRData.flags ///< True if repeat of value is detected
|
||||
|
||||
// next 3 values are copies of irparams values - see IRremoteint.h
|
||||
unsigned int *rawbuf; // deprecated, moved to decodedIRData.rawDataPtr->rawbuf ///< Raw intervals in 50uS ticks
|
||||
uint_fast8_t rawlen; // deprecated, moved to decodedIRData.rawDataPtr->rawlen ///< Number of records in rawbuf
|
||||
bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long
|
||||
};
|
||||
|
||||
/**
|
||||
* Main class for receiving IR signals
|
||||
*/
|
||||
class IRrecv {
|
||||
public:
|
||||
|
||||
IRrecv();
|
||||
IRrecv(uint_fast8_t aReceivePin);
|
||||
IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin);
|
||||
void setReceivePin(uint_fast8_t aReceivePinNumber);
|
||||
|
||||
/*
|
||||
* Stream like API
|
||||
*/
|
||||
void begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback = false, uint_fast8_t aFeedbackLEDPin =
|
||||
USE_DEFAULT_FEEDBACK_LED_PIN);
|
||||
void start();
|
||||
void enableIRIn(); // alias for start
|
||||
void start(uint32_t aMicrosecondsToAddToGapCounter);
|
||||
void restartAfterSend();
|
||||
|
||||
bool available();
|
||||
IRData* read(); // returns decoded data
|
||||
// write is a method of class IRsend below
|
||||
// size_t write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
void stop();
|
||||
void disableIRIn(); // alias for stop
|
||||
void end(); // alias for stop
|
||||
|
||||
bool isIdle();
|
||||
|
||||
/*
|
||||
* The main functions
|
||||
*/
|
||||
bool decode(); // Check if available and try to decode
|
||||
void resume(); // Enable receiving of the next value
|
||||
|
||||
/*
|
||||
* Useful info and print functions
|
||||
*/
|
||||
void printIRResultShort(Print *aSerial);
|
||||
void printIRResultMinimal(Print *aSerial);
|
||||
void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
|
||||
void printIRResultAsCVariables(Print *aSerial);
|
||||
|
||||
void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
|
||||
void compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int frequency = 38000U);
|
||||
|
||||
/*
|
||||
* Store the data for further processing
|
||||
*/
|
||||
void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr);
|
||||
size_t compensateAndStorePronto(String *aString, unsigned int frequency = 38000U);
|
||||
|
||||
/*
|
||||
* The main decoding functions used by the individual decoders
|
||||
*/
|
||||
bool decodePulseDistanceData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aBitMarkMicros,
|
||||
unsigned int aOneSpaceMicros, unsigned int aZeroSpaceMicros, bool aMSBfirst);
|
||||
|
||||
bool decodePulseWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
|
||||
unsigned int aZeroMarkMicros, unsigned int aBitSpaceMicros, bool aMSBfirst);
|
||||
|
||||
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount,
|
||||
uint_fast8_t aValueOfSpaceToMarkTransition, unsigned int aBiphaseTimeUnit);
|
||||
|
||||
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, unsigned int aBiphaseTimeUnit);
|
||||
uint_fast8_t getBiphaselevel();
|
||||
|
||||
/*
|
||||
* All standard (decode address + command) protocol decoders
|
||||
*/
|
||||
bool decodeBoseWave();
|
||||
bool decodeDenon();
|
||||
bool decodeJVC();
|
||||
bool decodeKaseikyo();
|
||||
bool decodeLegoPowerFunctions();
|
||||
bool decodeLG();
|
||||
bool decodeMagiQuest(); // not completely standard
|
||||
bool decodeNEC();
|
||||
bool decodeRC5();
|
||||
bool decodeRC6();
|
||||
bool decodeSamsung();
|
||||
bool decodeSharp(); // redirected to decodeDenon()
|
||||
bool decodeSony();
|
||||
bool decodeWhynter();
|
||||
|
||||
bool decodeDistance();
|
||||
|
||||
bool decodeHash();
|
||||
|
||||
// Template function :-)
|
||||
bool decodeShuzu();
|
||||
|
||||
/*
|
||||
* Old functions
|
||||
*/
|
||||
bool decodeDenonOld(decode_results *aResults);
|
||||
bool decodeJVCMSB(decode_results *aResults);
|
||||
bool decodeLGMSB(decode_results *aResults);
|
||||
bool decodeNECMSB(decode_results *aResults);
|
||||
bool decodePanasonicMSB(decode_results *aResults);
|
||||
bool decodeSonyMSB(decode_results *aResults);
|
||||
bool decodeSAMSUNG(decode_results *aResults);
|
||||
bool decodeHashOld(decode_results *aResults);
|
||||
|
||||
bool decode(
|
||||
decode_results *aResults)
|
||||
__attribute__ ((deprecated ("Please use IrReceiver.decode() without a parameter and IrReceiver.decodedIRData.<fieldname> ."))); // deprecated
|
||||
|
||||
// for backward compatibility. Now in IRFeedbackLED.hpp
|
||||
void blink13(uint8_t aEnableLEDFeedback)
|
||||
__attribute__ ((deprecated ("Please use setLEDFeedback() or enableLEDFeedback() / disableLEDFeedback()."))); // deprecated
|
||||
|
||||
/*
|
||||
* Internal functions
|
||||
*/
|
||||
void initDecodedIRData();
|
||||
uint_fast8_t compare(unsigned int oldval, unsigned int newval);
|
||||
|
||||
IRData decodedIRData; // New: decoded IR data for the application
|
||||
|
||||
// Last decoded IR data for repeat detection
|
||||
decode_type_t lastDecodedProtocol;
|
||||
uint32_t lastDecodedAddress;
|
||||
uint32_t lastDecodedCommand;
|
||||
|
||||
uint8_t repeatCount; // Used e.g. for Denon decode for autorepeat decoding.
|
||||
};
|
||||
|
||||
extern uint_fast8_t sBiphaseDecodeRawbuffOffset; //
|
||||
|
||||
/*
|
||||
* Mark & Space matching functions
|
||||
*/
|
||||
bool matchTicks(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros);
|
||||
bool matchMark(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros);
|
||||
bool matchSpace(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros);
|
||||
|
||||
/*
|
||||
* Old function names
|
||||
*/
|
||||
bool MATCH(unsigned int measured, unsigned int desired);
|
||||
bool MATCH_MARK(unsigned int measured_ticks, unsigned int desired_us);
|
||||
bool MATCH_SPACE(unsigned int measured_ticks, unsigned int desired_us);
|
||||
|
||||
int getMarkExcessMicros();
|
||||
void printActiveIRProtocols(Print *aSerial);
|
||||
void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintGap);
|
||||
|
||||
/****************************************************
|
||||
* Feedback LED related functions
|
||||
****************************************************/
|
||||
#define DO_NOT_ENABLE_LED_FEEDBACK 0x00
|
||||
#define LED_FEEDBACK_DISABLED_COMPLETELY 0x00
|
||||
#define LED_FEEDBACK_ENABLED_FOR_RECEIVE 0x01
|
||||
#define LED_FEEDBACK_ENABLED_FOR_SEND 0x02
|
||||
void setFeedbackLED(bool aSwitchLedOn);
|
||||
void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback); // if aFeedbackLEDPin == 0, then take board BLINKLED_ON() and BLINKLED_OFF() functions
|
||||
void setLEDFeedback(bool aEnableLEDFeedback); // Direct replacement for blink13()
|
||||
void enableLEDFeedback();
|
||||
constexpr auto enableLEDFeedbackForReceive = enableLEDFeedback; // alias for enableLEDFeedback
|
||||
void disableLEDFeedback();
|
||||
constexpr auto disableLEDFeedbackForReceive = disableLEDFeedback; // alias for enableLEDFeedback
|
||||
void enableLEDFeedbackForSend();
|
||||
void disableLEDFeedbackForSend();
|
||||
|
||||
void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please use setLEDFeedback()."))); // deprecated
|
||||
|
||||
/*
|
||||
* Pulse parms are ((X*50)-MARK_EXCESS_MICROS) for the Mark and ((X*50)+MARK_EXCESS_MICROS) for the Space.
|
||||
* First MARK is the one after the long gap
|
||||
* Pulse parameters in microseconds
|
||||
*/
|
||||
#if !defined(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING)
|
||||
#define TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING 25 // Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding.
|
||||
#endif
|
||||
|
||||
/** Lower tolerance for comparison of measured data */
|
||||
//#define LTOL (1.0 - (TOLERANCE/100.))
|
||||
#define LTOL (100 - TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING)
|
||||
/** Upper tolerance for comparison of measured data */
|
||||
//#define UTOL (1.0 + (TOLERANCE/100.))
|
||||
#define UTOL (100 + TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING)
|
||||
|
||||
//#define TICKS_LOW(us) ((int)(((us)*LTOL/MICROS_PER_TICK)))
|
||||
//#define TICKS_HIGH(us) ((int)(((us)*UTOL/MICROS_PER_TICK + 1)))
|
||||
#if MICROS_PER_TICK == 50 && TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING == 25 // Defaults
|
||||
#define TICKS_LOW(us) ((us)/67 ) // (us) / ((MICROS_PER_TICK:50 / LTOL:75 ) * 100)
|
||||
#define TICKS_HIGH(us) (((us)/40) + 1) // (us) / ((MICROS_PER_TICK:50 / UTOL:125) * 100) + 1
|
||||
#else
|
||||
#define TICKS_LOW(us) ((unsigned int ) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) ))
|
||||
#define TICKS_HIGH(us) ((unsigned int ) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The receiver instance
|
||||
*/
|
||||
extern IRrecv IrReceiver;
|
||||
|
||||
/****************************************************
|
||||
* SENDING
|
||||
****************************************************/
|
||||
|
||||
/**
|
||||
* Just for better readability of code
|
||||
*/
|
||||
#define NO_REPEATS 0
|
||||
#define SEND_STOP_BIT true
|
||||
#define SEND_REPEAT_COMMAND true ///< used for e.g. NEC, where a repeat is different from just repeating the data.
|
||||
|
||||
/**
|
||||
* Main class for sending IR signals
|
||||
*/
|
||||
class IRsend {
|
||||
public:
|
||||
IRsend();
|
||||
|
||||
/*
|
||||
* IR_SEND_PIN is defined
|
||||
*/
|
||||
#if defined(IR_SEND_PIN)
|
||||
void begin();
|
||||
void begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
|
||||
#else
|
||||
IRsend(uint_fast8_t aSendPin);
|
||||
void begin(uint_fast8_t aSendPin);
|
||||
void setSendPin(uint_fast8_t aSendPin); // required if we use IRsend() as constructor
|
||||
#endif
|
||||
|
||||
// Not guarded for backward compatibility
|
||||
void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
|
||||
|
||||
size_t write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
|
||||
void enableIROut(uint_fast8_t aFrequencyKHz);
|
||||
|
||||
void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
|
||||
unsigned int aZeroSpaceMicros, uint32_t aData, uint_fast8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit = false);
|
||||
void sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);
|
||||
|
||||
void mark(unsigned int aMarkMicros);
|
||||
void space(unsigned int aSpaceMicros);
|
||||
void IRLedOff();
|
||||
|
||||
// 8 Bit array
|
||||
void sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
|
||||
void sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
|
||||
|
||||
// 16 Bit array
|
||||
void sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
|
||||
void sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
|
||||
|
||||
/*
|
||||
* New send functions
|
||||
*/
|
||||
void sendBoseWave(uint8_t aCommand, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
void sendDenon(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendSharp = false);
|
||||
void sendDenonRaw(uint16_t aRawData, uint_fast8_t aNumberOfRepeats = 0)
|
||||
#if !defined (DOXYGEN)
|
||||
__attribute__ ((deprecated ("Please use sendDenon(aAddress, aCommand, aNumberOfRepeats).")));
|
||||
#endif
|
||||
void sendJVC(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);
|
||||
|
||||
void sendLGRepeat(bool aUseLG2Protocol = false);
|
||||
void sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false, bool aUseLG2Protocol =
|
||||
false);
|
||||
void sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false, bool aUseLG2Protocol = false);
|
||||
|
||||
void sendNECRepeat();
|
||||
void sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
|
||||
void sendNECRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false);
|
||||
// NEC variants
|
||||
void sendOnkyo(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
|
||||
void sendApple(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
|
||||
|
||||
void sendKaseikyo(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats, uint16_t aVendorCode); // LSB first
|
||||
void sendPanasonic(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
|
||||
void sendKaseikyo_Denon(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
|
||||
void sendKaseikyo_Mitsubishi(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
|
||||
void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
|
||||
void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
|
||||
|
||||
void sendRC5(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
|
||||
void sendRC6(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
|
||||
void sendSamsungRepeat();
|
||||
void sendSamsung(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats);
|
||||
void sendSharp(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats); // redirected to sendDenon
|
||||
void sendSony(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint8_t numberOfBits = SIRCS_12_PROTOCOL);
|
||||
|
||||
void sendLegoPowerFunctions(uint8_t aChannel, uint8_t tCommand, uint8_t aMode, bool aDoSend5Times = true);
|
||||
void sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times = true);
|
||||
void sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times = true);
|
||||
|
||||
void sendMagiQuest(uint32_t wand_id, uint16_t magnitude);
|
||||
|
||||
void sendPronto(const __FlashStringHelper *str, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
void sendPronto(const char *prontoHexString, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
void sendPronto(const uint16_t *data, unsigned int length, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
#if defined(__AVR__)
|
||||
void sendPronto_PF(uint_farptr_t str, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
|
||||
void sendPronto_P(const char *str, uint_fast8_t aNumberOfRepeats);
|
||||
#endif
|
||||
|
||||
// Template protocol :-)
|
||||
void sendShuzu(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);
|
||||
|
||||
/*
|
||||
* OLD send functions
|
||||
*/
|
||||
void sendDenon(unsigned long data, int nbits);
|
||||
void sendDISH(unsigned long data, int nbits);
|
||||
void sendJVC(unsigned long data, int nbits,
|
||||
bool repeat)
|
||||
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendJVC(aAddress, aCommand, aNumberOfRepeats)."))) {
|
||||
sendJVCMSB(data, nbits, repeat);
|
||||
}
|
||||
void sendJVCMSB(unsigned long data, int nbits, bool repeat = false);
|
||||
|
||||
void sendLG(unsigned long data, int nbits);
|
||||
|
||||
void sendNEC(uint32_t aRawData,
|
||||
uint8_t nbits)
|
||||
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendNEC(aAddress, aCommand, aNumberOfRepeats)."))) {
|
||||
sendNECMSB(aRawData, nbits);
|
||||
}
|
||||
void sendNECMSB(uint32_t data, uint8_t nbits, bool repeat = false);
|
||||
void sendPanasonic(uint16_t aAddress,
|
||||
uint32_t aData)
|
||||
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendPanasonic(aAddress, aCommand, aNumberOfRepeats).")));
|
||||
void sendRC5(uint32_t data, uint8_t nbits);
|
||||
void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle);
|
||||
void sendRC6(uint32_t data, uint8_t nbits);
|
||||
void sendRC6(uint64_t data, uint8_t nbits);
|
||||
void sendSharpRaw(unsigned long data, int nbits);
|
||||
void sendSharp(unsigned int address, unsigned int command);
|
||||
void sendSAMSUNG(unsigned long data, int nbits);
|
||||
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSamsung().")));
|
||||
void sendSony(unsigned long data,
|
||||
int nbits)
|
||||
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats).")));
|
||||
;
|
||||
void sendWhynter(unsigned long data, int nbits);
|
||||
|
||||
#if !defined(IR_SEND_PIN)
|
||||
uint8_t sendPin;
|
||||
#endif
|
||||
unsigned int periodTimeMicros;
|
||||
unsigned int periodOnTimeMicros; // compensated with PULSE_CORRECTION_NANOS for duration of digitalWrite.
|
||||
unsigned int getPulseCorrectionNanos();
|
||||
|
||||
void customDelayMicroseconds(unsigned long aMicroseconds);
|
||||
};
|
||||
|
||||
/*
|
||||
* The sender instance
|
||||
*/
|
||||
extern IRsend IrSender;
|
||||
|
||||
#endif // _IR_REMOTE_INT_H
|
||||
96
arduino-libs/arduino-cli/libraries/IRremote/src/LongUnion.h
Normal file
96
arduino-libs/arduino-cli/libraries/IRremote/src/LongUnion.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* LongUnion.h
|
||||
*
|
||||
* Copyright (C) 2020 Armin Joachimsmeyer
|
||||
* Email: armin.joachimsmeyer@gmail.com
|
||||
*
|
||||
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
|
||||
*
|
||||
* Arduino-Utils is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _WORD_UNION_H
|
||||
#define _WORD_UNION_H
|
||||
/**
|
||||
* Union to specify parts / manifestations of a 16 bit Word without casts and shifts.
|
||||
* It also supports the compiler generating small code.
|
||||
*/
|
||||
union WordUnion {
|
||||
struct {
|
||||
uint8_t LowByte;
|
||||
uint8_t HighByte;
|
||||
} UByte;
|
||||
struct {
|
||||
int8_t LowByte;
|
||||
int8_t HighByte;
|
||||
} Byte;
|
||||
uint8_t UBytes[2];
|
||||
int8_t Bytes[2];
|
||||
uint16_t UWord;
|
||||
int16_t Word;
|
||||
uint8_t *BytePointer;
|
||||
};
|
||||
#endif // _WORD_UNION_H
|
||||
|
||||
#ifndef _LONG_UNION_H
|
||||
#define _LONG_UNION_H
|
||||
/**
|
||||
* Union to specify parts / manifestations of a 32 bit Long without casts and shifts.
|
||||
* It also supports the compiler generating small code.
|
||||
*/
|
||||
union LongUnion {
|
||||
struct {
|
||||
uint8_t LowByte;
|
||||
uint8_t MidLowByte;
|
||||
uint8_t MidHighByte;
|
||||
uint8_t HighByte;
|
||||
} UByte;
|
||||
struct {
|
||||
int8_t LowByte;
|
||||
int8_t MidLowByte;
|
||||
int8_t MidHighByte;
|
||||
int8_t HighByte;
|
||||
} Byte;
|
||||
struct {
|
||||
uint8_t LowByte;
|
||||
WordUnion MidWord;
|
||||
uint8_t HighByte;
|
||||
} ByteWord;
|
||||
struct {
|
||||
int16_t LowWord;
|
||||
int16_t HighWord;
|
||||
} Word;
|
||||
struct {
|
||||
WordUnion LowWord;
|
||||
WordUnion HighWord;
|
||||
} WordUnion;
|
||||
struct {
|
||||
uint16_t LowWord;
|
||||
uint16_t HighWord;
|
||||
} UWord;
|
||||
uint8_t UBytes[4]; // seems to have the same code size as using struct UByte
|
||||
int8_t Bytes[4];
|
||||
uint16_t UWords[2];
|
||||
int16_t Words[2];
|
||||
uint32_t ULong;
|
||||
int32_t Long;
|
||||
};
|
||||
#endif // _LONG_UNION_H
|
||||
|
||||
#endif // !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H)
|
||||
114
arduino-libs/arduino-cli/libraries/IRremote/src/TinyIRReceiver.h
Normal file
114
arduino-libs/arduino-cli/libraries/IRremote/src/TinyIRReceiver.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* TinyIRReceiver.h
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2021 Armin Joachimsmeyer
|
||||
* armin.joachimsmeyer@gmail.com
|
||||
*
|
||||
* This file is part of IRMP https://github.com/ukw100/IRMP.
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
* TinyIRReceiver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TINY_IR_RECEIVER_H
|
||||
#define _TINY_IR_RECEIVER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup TinyReceiver Minimal receiver for NEC protocol
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function is called if a complete command was received and must be implemented by the including file (user code)
|
||||
*/
|
||||
void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat);
|
||||
|
||||
// LSB first, 1 start bit + 16 bit address + 8 bit data + 8 bit inverted data + 1 stop bit.
|
||||
// see: https://www.sbprojects.net/knowledge/ir/nec.php
|
||||
|
||||
#define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
|
||||
#define NEC_COMMAND_BITS 16 // Command and inverted command
|
||||
|
||||
#define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
|
||||
#define NEC_UNIT 560
|
||||
|
||||
#define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000
|
||||
#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500
|
||||
|
||||
#define NEC_BIT_MARK NEC_UNIT
|
||||
#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690
|
||||
#define NEC_ZERO_SPACE NEC_UNIT
|
||||
|
||||
#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250
|
||||
#define NEC_REPEAT_PERIOD 110000 // Not used yet - Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
|
||||
|
||||
/*
|
||||
* Macros for comparing timing values
|
||||
*/
|
||||
#define lowerValue25Percent(aDuration) (aDuration - (aDuration / 4))
|
||||
#define upperValue25Percent(aDuration) (aDuration + (aDuration / 4))
|
||||
#define lowerValue50Percent(aDuration) (aDuration / 2) // (aDuration - (aDuration / 2))
|
||||
#define upperValue50Percent(aDuration) (aDuration + (aDuration / 2))
|
||||
|
||||
/*
|
||||
* The states for the state machine
|
||||
*/
|
||||
#define IR_RECEIVER_STATE_WAITING_FOR_START_MARK 0
|
||||
#define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE 1
|
||||
#define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK 2
|
||||
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE 3
|
||||
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4
|
||||
#define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5
|
||||
/**
|
||||
* Control and data variables of the state machine for TinyReceiver
|
||||
*/
|
||||
struct TinyIRReceiverStruct {
|
||||
/*
|
||||
* State machine
|
||||
*/
|
||||
uint32_t LastChangeMicros; ///< microseconds of last Pin Change Interrupt.
|
||||
uint8_t IRReceiverState; ///< the state of the state machine.
|
||||
uint8_t IRRawDataBitCounter;
|
||||
/*
|
||||
* Data
|
||||
*/
|
||||
uint32_t IRRawDataMask;
|
||||
LongUnion IRRawData;
|
||||
bool IRRepeatDetected;
|
||||
};
|
||||
|
||||
/*
|
||||
* Can be used by the callback to transfer received data to main loop for further processing
|
||||
* E.g. with volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;
|
||||
*/
|
||||
struct TinyIRReceiverCallbackDataStruct {
|
||||
uint16_t Address;
|
||||
uint8_t Command;
|
||||
bool isRepeat;
|
||||
bool justWritten;
|
||||
};
|
||||
|
||||
void initPCIInterruptForTinyReceiver();
|
||||
void enablePCIInterruptForTinyReceiver();
|
||||
void disablePCIInterruptForTinyReceiver();
|
||||
bool isTinyReceiverIdle();
|
||||
|
||||
/** @}*/
|
||||
|
||||
#endif // _TINY_IR_RECEIVER_H
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* TinyIRReceiver.hpp
|
||||
*
|
||||
* Receives IR protocol data of NEC protocol using pin change interrupts.
|
||||
* NEC is the protocol of most cheap remote controls for Arduino.
|
||||
*
|
||||
* No parity check is done!
|
||||
* On a completely received IR command, the user function handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition)
|
||||
* is called in interrupt context but with interrupts being enabled to enable use of delay() etc.
|
||||
* !!!!!!!!!!!!!!!!!!!!!!
|
||||
* Functions called in interrupt context should be running as short as possible,
|
||||
* so if you require longer action, save the data (address + command) and handle them in the main loop.
|
||||
* !!!!!!!!!!!!!!!!!!!!!
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2021-2022 Armin Joachimsmeyer
|
||||
* armin.joachimsmeyer@gmail.com
|
||||
*
|
||||
* This file is part of IRMP https://github.com/ukw100/IRMP.
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
* TinyIRReceiver is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This library can be configured at compile time by the following options / macros:
|
||||
* For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library (scroll down)
|
||||
*
|
||||
* - IR_INPUT_PIN The pin number for TinyIRReceiver IR input.
|
||||
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED.
|
||||
* - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TINY_IR_RECEIVER_HPP
|
||||
#define _TINY_IR_RECEIVER_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "TinyIRReceiver.h" // If not defined, it defines IR_INPUT_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT
|
||||
|
||||
#include "digitalWriteFast.h"
|
||||
/** \addtogroup TinyReceiver Minimal receiver for NEC protocol
|
||||
* @{
|
||||
*/
|
||||
|
||||
//#define DEBUG // to see if attachInterrupt used
|
||||
//#define TRACE // to see the state of the ISR state machine
|
||||
//#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement.
|
||||
//#define _IR_TIMING_TEST_PIN 7
|
||||
TinyIRReceiverStruct TinyIRReceiverControl;
|
||||
|
||||
/*
|
||||
* Set input pin and output pin definitions etc.
|
||||
*/
|
||||
#if !defined(IR_INPUT_PIN)
|
||||
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
|
||||
#warning "IR_INPUT_PIN is not defined, so it is set to 10"
|
||||
#define IR_INPUT_PIN 10
|
||||
#else
|
||||
#warning "IR_INPUT_PIN is not defined, so it is set to 2"
|
||||
#define IR_INPUT_PIN 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
|
||||
#define IR_FEEDBACK_LED_PIN LED_BUILTIN
|
||||
#endif
|
||||
|
||||
#if !( \
|
||||
(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \
|
||||
|| defined(__AVR_ATtiny88__) /* MH-ET LIVE Tiny88 */ \
|
||||
|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
|
||||
|| defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
|
||||
|| defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
|
||||
|| defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
|
||||
/* ATmegas with ports 0,1,2 above and ATtiny167 only 2 pins below */ \
|
||||
|| ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_INPUT_PIN == 3) || (IR_INPUT_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\
|
||||
|| (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_INPUT_PIN == 3) || (IR_INPUT_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \
|
||||
)
|
||||
#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Declaration of the callback function provided by the user application.
|
||||
* It is called every time a complete IR command or repeat was received.
|
||||
*/
|
||||
#if defined(ESP32) || defined(ESP8266)
|
||||
void IRAM_ATTR handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition);
|
||||
#else
|
||||
void handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The ISR of TinyIRRreceiver.
|
||||
* It handles the NEC protocol decoding and calls the user callback function on complete.
|
||||
* 5 us + 3 us for push + pop for a 16MHz ATmega
|
||||
*/
|
||||
#if defined(ESP32) || defined(ESP8266)
|
||||
void IRAM_ATTR IRPinChangeInterruptHandler(void)
|
||||
#else
|
||||
void IRPinChangeInterruptHandler(void)
|
||||
#endif
|
||||
{
|
||||
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
|
||||
digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
|
||||
#endif
|
||||
/*
|
||||
* Save IR input level
|
||||
* Negative logic, true / HIGH means inactive / IR space, LOW / false means IR mark.
|
||||
*/
|
||||
uint_fast8_t tIRLevel = digitalReadFast(IR_INPUT_PIN);
|
||||
|
||||
#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
|
||||
digitalWriteFast(IR_FEEDBACK_LED_PIN, !tIRLevel);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 1. compute microseconds after last change
|
||||
*/
|
||||
uint32_t tCurrentMicros = micros();
|
||||
uint16_t tMicrosOfMarkOrSpace = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros;
|
||||
TinyIRReceiverControl.LastChangeMicros = tCurrentMicros;
|
||||
|
||||
uint8_t tState = TinyIRReceiverControl.IRReceiverState;
|
||||
|
||||
#if defined(TRACE)
|
||||
Serial.print(tState);
|
||||
Serial.print(' ');
|
||||
// Serial.print(F(" I="));
|
||||
// Serial.print(tIRLevel);
|
||||
// Serial.print(F(" D="));
|
||||
// Serial.print(tDeltaMicros);
|
||||
// Serial.println();
|
||||
#endif
|
||||
|
||||
if (tIRLevel == LOW) {
|
||||
/*
|
||||
* We have a mark here
|
||||
*/
|
||||
if (tMicrosOfMarkOrSpace > 2 * NEC_HEADER_MARK) {
|
||||
// timeout -> must reset state machine
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK) {
|
||||
// We are at the beginning of the header mark, check timing at the next transition
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE;
|
||||
}
|
||||
|
||||
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) {
|
||||
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_SPACE)
|
||||
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_SPACE)) {
|
||||
/*
|
||||
* We have a valid data header space here -> initialize data
|
||||
*/
|
||||
TinyIRReceiverControl.IRRawDataBitCounter = 0;
|
||||
TinyIRReceiverControl.IRRawData.ULong = 0;
|
||||
TinyIRReceiverControl.IRRawDataMask = 1;
|
||||
TinyIRReceiverControl.IRRepeatDetected = false;
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
|
||||
} else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE)
|
||||
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE)
|
||||
&& TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS) {
|
||||
/*
|
||||
* We have a repeat header here and no broken receive before -> set repeat flag
|
||||
*/
|
||||
TinyIRReceiverControl.IRRepeatDetected = true;
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
|
||||
} else {
|
||||
// This parts are optimized by the compiler into jumps to one code :-)
|
||||
// Wrong length -> reset state
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) {
|
||||
// Check data space length
|
||||
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(NEC_ZERO_SPACE)
|
||||
&& tMicrosOfMarkOrSpace <= upperValue50Percent(NEC_ONE_SPACE)) {
|
||||
// We have a valid bit here
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
|
||||
if (tMicrosOfMarkOrSpace >= 2 * NEC_UNIT) {
|
||||
// we received a 1
|
||||
TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask;
|
||||
} else {
|
||||
// we received a 0 - empty code for documentation
|
||||
}
|
||||
// prepare for next bit
|
||||
TinyIRReceiverControl.IRRawDataMask = TinyIRReceiverControl.IRRawDataMask << 1;
|
||||
TinyIRReceiverControl.IRRawDataBitCounter++;
|
||||
} else {
|
||||
// Wrong length -> reset state
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
} else {
|
||||
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/*
|
||||
* We have a space here
|
||||
*/
|
||||
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) {
|
||||
/*
|
||||
* Check length of header mark here
|
||||
*/
|
||||
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_MARK)
|
||||
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_MARK)) {
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK;
|
||||
} else {
|
||||
// Wrong length of header mark -> reset state
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) {
|
||||
// Check data mark length
|
||||
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(NEC_BIT_MARK)
|
||||
&& tMicrosOfMarkOrSpace <= upperValue50Percent(NEC_BIT_MARK)) {
|
||||
/*
|
||||
* We have a valid mark here, check for transmission complete
|
||||
*/
|
||||
if (TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS || TinyIRReceiverControl.IRRepeatDetected) {
|
||||
/*
|
||||
* Code complete -> call callback, no parity check!
|
||||
*/
|
||||
// Reset state for new start
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
|
||||
interrupts(); // enable interrupts, so delay() etc. works in callback
|
||||
#endif
|
||||
/*
|
||||
* Address reduction to 8 bit
|
||||
*/
|
||||
if (TinyIRReceiverControl.IRRawData.UByte.LowByte
|
||||
== (uint8_t) (~TinyIRReceiverControl.IRRawData.UByte.MidLowByte)) {
|
||||
// standard 8 bit address NEC protocol
|
||||
TinyIRReceiverControl.IRRawData.UByte.MidLowByte = 0; // Address is the first 8 bit
|
||||
}
|
||||
|
||||
/*
|
||||
* Call user provided callback here
|
||||
*/
|
||||
handleReceivedTinyIRData(TinyIRReceiverControl.IRRawData.UWord.LowWord,
|
||||
TinyIRReceiverControl.IRRawData.UByte.MidHighByte, TinyIRReceiverControl.IRRepeatDetected);
|
||||
|
||||
} else {
|
||||
// not finished yet
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK;
|
||||
}
|
||||
} else {
|
||||
// Wrong length -> reset state
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
} else {
|
||||
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
|
||||
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
TinyIRReceiverControl.IRReceiverState = tState;
|
||||
#ifdef _IR_MEASURE_TIMING
|
||||
digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isTinyReceiverIdle() {
|
||||
return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets IR_INPUT_PIN mode to INPUT_PULLUP, if required, sets feedback LED output mode and call enablePCIInterruptForTinyReceiver()
|
||||
*/
|
||||
void initPCIInterruptForTinyReceiver() {
|
||||
pinModeFast(IR_INPUT_PIN, INPUT_PULLUP);
|
||||
|
||||
#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
|
||||
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
|
||||
#endif
|
||||
enablePCIInterruptForTinyReceiver();
|
||||
}
|
||||
|
||||
#if defined (DEBUG) && !defined(STR)
|
||||
// Helper macro for getting a macro definition as string
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
#endif
|
||||
/**
|
||||
* Initializes hardware interrupt generation according to IR_INPUT_PIN or use attachInterrupt() function.
|
||||
*/
|
||||
void enablePCIInterruptForTinyReceiver() {
|
||||
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
|
||||
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
|
||||
attachInterrupt(IR_INPUT_PIN, IRPinChangeInterruptHandler, CHANGE); // 2.2 us more than version configured with macros and not compatible
|
||||
|
||||
#elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
|
||||
// costs 112 bytes program memory + 4 bytes RAM
|
||||
attachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN), IRPinChangeInterruptHandler, CHANGE);
|
||||
# if defined(DEBUG)
|
||||
Serial.println(F("Use attachInterrupt for pin=" STR(IR_INPUT_PIN)));
|
||||
# endif
|
||||
#else
|
||||
# if defined(DEBUG)
|
||||
Serial.println(F("Use static interrupt for pin=" STR(IR_INPUT_PIN)));
|
||||
# endif
|
||||
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
// use PinChangeInterrupt no INT0 for pin PB2
|
||||
PCMSK = _BV(IR_INPUT_PIN);
|
||||
// clear interrupt bit
|
||||
GIFR |= 1 << PCIF;
|
||||
// enable interrupt on next change
|
||||
GIMSK |= 1 << PCIE;
|
||||
|
||||
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
|
||||
# if defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
# if (IR_INPUT_PIN == 3)
|
||||
// interrupt on any logical change
|
||||
EICRA |= _BV(ISC00);
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF0;
|
||||
// enable interrupt on next change
|
||||
EIMSK |= 1 << INT0;
|
||||
# elif (IR_INPUT_PIN == 9)
|
||||
EICRA |= _BV(ISC10);
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF1;
|
||||
// enable interrupt on next change
|
||||
EIMSK |= 1 << INT1;
|
||||
# else
|
||||
# error "IR_INPUT_PIN must be 9 or 3."
|
||||
# endif // if (IR_INPUT_PIN == 9)
|
||||
|
||||
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
# if (IR_INPUT_PIN == 14)
|
||||
// interrupt on any logical change
|
||||
EICRA |= _BV(ISC00);
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF0;
|
||||
// enable interrupt on next change
|
||||
EIMSK |= 1 << INT0;
|
||||
# elif (IR_INPUT_PIN == 3)
|
||||
EICRA |= _BV(ISC10);
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF1;
|
||||
// enable interrupt on next change
|
||||
EIMSK |= 1 << INT1;
|
||||
# else
|
||||
# error "IR_INPUT_PIN must be 14 or 3."
|
||||
# endif // if (IR_INPUT_PIN == 14)
|
||||
# endif
|
||||
|
||||
# else // defined(__AVR_ATtiny25__)
|
||||
/*
|
||||
* ATmegas + ATtiny88 here
|
||||
*/
|
||||
# if (IR_INPUT_PIN == 2)
|
||||
// interrupt on any logical change
|
||||
EICRA |= _BV(ISC00);
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF0;
|
||||
// enable interrupt on next change
|
||||
EIMSK |= 1 << INT0;
|
||||
# elif (IR_INPUT_PIN == 3)
|
||||
EICRA |= _BV(ISC10);
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF1;
|
||||
// enable interrupt on next change
|
||||
EIMSK |= 1 << INT1;
|
||||
# elif IR_INPUT_PIN == 4 || IR_INPUT_PIN == 5 || IR_INPUT_PIN == 6 || IR_INPUT_PIN == 7
|
||||
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7)
|
||||
PCICR |= _BV(PCIE2);
|
||||
PCMSK2 = digitalPinToBitMask(IR_INPUT_PIN);
|
||||
# elif IR_INPUT_PIN == 8 || IR_INPUT_PIN == 9 || IR_INPUT_PIN == 10 || IR_INPUT_PIN == 11 || IR_INPUT_PIN == 12 || IR_INPUT_PIN == 13
|
||||
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
|
||||
PCICR |= _BV(PCIE0);
|
||||
PCMSK0 = digitalPinToBitMask(IR_INPUT_PIN);
|
||||
# elif IR_INPUT_PIN == A0 || IR_INPUT_PIN == A1 || IR_INPUT_PIN == A2 || IR_INPUT_PIN == A3 || IR_INPUT_PIN == A4 || IR_INPUT_PIN == A5
|
||||
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
|
||||
PCICR |= _BV(PCIE1);
|
||||
PCMSK1 = digitalPinToBitMask(IR_INPUT_PIN);
|
||||
# else
|
||||
# error "IR_INPUT_PIN not allowed."
|
||||
# endif // if (IR_INPUT_PIN == 2)
|
||||
# endif // defined(__AVR_ATtiny25__)
|
||||
#endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
|
||||
}
|
||||
|
||||
void disablePCIInterruptForTinyReceiver() {
|
||||
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
|
||||
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
|
||||
detachInterrupt(IR_INPUT_PIN);
|
||||
|
||||
#elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
|
||||
// costs 112 bytes program memory + 4 bytes RAM
|
||||
detachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN));
|
||||
#else
|
||||
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
// clear interrupt bit
|
||||
GIFR |= 1 << PCIF;
|
||||
// disable interrupt on next change
|
||||
GIMSK &= ~(1 << PCIE);
|
||||
|
||||
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
|
||||
# if defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
# if (IR_INPUT_PIN == 3)
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF0;
|
||||
// disable interrupt on next change
|
||||
EIMSK &= ~( 1 << INT0);
|
||||
# elif (IR_INPUT_PIN == 9)
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF1;
|
||||
// disable interrupt on next change
|
||||
EIMSK &= ~(1 << INT1);
|
||||
# else
|
||||
# error "IR_INPUT_PIN must be 9 or 3."
|
||||
# endif // if (IR_INPUT_PIN == 9)
|
||||
|
||||
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
# if (IR_INPUT_PIN == 14)
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF0;
|
||||
// disable interrupt on next change
|
||||
EIMSK &= ~(1 << INT0);
|
||||
# elif (IR_INPUT_PIN == 3)
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF1;
|
||||
// disable interrupt on next change
|
||||
EIMSK &= ~(1 << INT1);
|
||||
# else
|
||||
# error "IR_INPUT_PIN must be 14 or 3."
|
||||
# endif // if (IR_INPUT_PIN == 14)
|
||||
# endif
|
||||
|
||||
# else // defined(__AVR_ATtiny25__)
|
||||
/*
|
||||
* ATmegas + ATtiny88 here
|
||||
*/
|
||||
# if (IR_INPUT_PIN == 2)
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF0;
|
||||
// disable interrupt on next change
|
||||
EIMSK &= ~(1 << INT0);
|
||||
# elif (IR_INPUT_PIN == 3)
|
||||
// clear interrupt bit
|
||||
EIFR |= 1 << INTF1;
|
||||
// disable interrupt on next change
|
||||
EIMSK &= ~(1 << INT1);
|
||||
# elif IR_INPUT_PIN == 4 || IR_INPUT_PIN == 5 || IR_INPUT_PIN == 6 || IR_INPUT_PIN == 7
|
||||
//ATmega328 (Uno, Nano ) etc. disable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7)
|
||||
PCICR &= ~(_BV(PCIE2));
|
||||
# elif IR_INPUT_PIN == 8 || IR_INPUT_PIN == 9 || IR_INPUT_PIN == 10 || IR_INPUT_PIN == 11 || IR_INPUT_PIN == 12 || IR_INPUT_PIN == 13
|
||||
//ATmega328 (Uno, Nano ) etc. disable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
|
||||
PCICR &= ~(_BV(PCIE0));
|
||||
# elif IR_INPUT_PIN == A0 || IR_INPUT_PIN == A1 || IR_INPUT_PIN == A2 || IR_INPUT_PIN == A3 || IR_INPUT_PIN == A4 || IR_INPUT_PIN == A5
|
||||
//ATmega328 (Uno, Nano ) etc. disable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
|
||||
PCICR &= ~(_BV(PCIE1));
|
||||
# else
|
||||
# error "IR_INPUT_PIN not allowed."
|
||||
# endif // if (IR_INPUT_PIN == 2)
|
||||
# endif // defined(__AVR_ATtiny25__)
|
||||
#endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
|
||||
}
|
||||
|
||||
/*
|
||||
* Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores.
|
||||
* The default value of TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT is set in TinyIRReceiver.h
|
||||
*/
|
||||
#if defined(__AVR__) && !defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
|
||||
# if (IR_INPUT_PIN == 2)
|
||||
ISR(INT0_vect) // Pin 2 global assignment
|
||||
|
||||
# elif (IR_INPUT_PIN == 3)
|
||||
# if defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
ISR(INT0_vect) // Pin 3 / PB6 / INT0 is connected to USB+ on DigisparkPro boards
|
||||
# else
|
||||
ISR(INT1_vect) // Pin 3 global assignment
|
||||
# endif
|
||||
|
||||
# elif (IR_INPUT_PIN == 9) && defined(ARDUINO_AVR_DIGISPARKPRO) // Digispark pro
|
||||
ISR(INT1_vect)
|
||||
|
||||
# elif (IR_INPUT_PIN == 14) && (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))// For AVR_ATtiny167 INT0 is on pin 14 / PB6
|
||||
ISR(INT0_vect)
|
||||
|
||||
# elif (! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3)
|
||||
// on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect
|
||||
ISR(PCINT0_vect)
|
||||
|
||||
# elif IR_INPUT_PIN == 4 || IR_INPUT_PIN == 5 || IR_INPUT_PIN == 6 || IR_INPUT_PIN == 7
|
||||
// PCINT for ATmega328 Arduino pins 4 (PD4) to 7 (PD7) - (PCINT 20 to 23)
|
||||
ISR(PCINT2_vect)
|
||||
|
||||
# elif IR_INPUT_PIN == 8 || IR_INPUT_PIN == 9 || IR_INPUT_PIN == 10 || IR_INPUT_PIN == 11 || IR_INPUT_PIN == 12 || IR_INPUT_PIN == 13
|
||||
// PCINT for ATmega328 Arduino pins 8 (PB0) to 13 (PB5) - (PCINT 0 to 5)
|
||||
ISR(PCINT0_vect)
|
||||
|
||||
# elif IR_INPUT_PIN == A0 || IR_INPUT_PIN == A1 || IR_INPUT_PIN == A2 || IR_INPUT_PIN == A3 || IR_INPUT_PIN == A4 || IR_INPUT_PIN == A5
|
||||
// PCINT for ATmega328 Arduino pins A1 (PC0) to A5 (PC5) - (PCINT 8 to 13)
|
||||
ISR(PCINT1_vect)
|
||||
|
||||
# endif
|
||||
{
|
||||
IRPinChangeInterruptHandler();
|
||||
}
|
||||
#endif // defined(__AVR__) && ! defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
|
||||
|
||||
/** @}*/
|
||||
|
||||
#endif // _TINY_IR_RECEIVER_HPP
|
||||
138
arduino-libs/arduino-cli/libraries/IRremote/src/ac_LG.h
Normal file
138
arduino-libs/arduino-cli/libraries/IRremote/src/ac_LG.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* ac_LG.h
|
||||
*
|
||||
* Contains definitions for receiving and sending LG air conditioner IR Protocol
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2021 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
// see also: https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h
|
||||
#ifndef _AC_LG_H
|
||||
#define _AC_LG_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/** \addtogroup Airconditoners Air conditioner special code
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LG_ADDRESS 0x88
|
||||
|
||||
/*
|
||||
* The basic IR command codes
|
||||
* Parts of the codes (especially the lower nibbles) may be modified to contain
|
||||
* additional information like temperature, fan speed and minutes.
|
||||
*/
|
||||
#define LG_SWITCH_ON_MASK 0x0800 // This bit is masked if we switch Power on
|
||||
#define LG_MODE_COOLING 0x0800 // Temperature and fan speed in lower nibbles
|
||||
#define LG_MODE_DEHUMIDIFIYING 0x0990 // sets also temperature to 24 and fan speed to 0
|
||||
#define LG_MODE_FAN 0x0A30 // sets also temperature to 18
|
||||
#define LG_MODE_AUTO 0x0B00 // The remote initially sets also temperature to 22 and fan speed to 4
|
||||
#define LG_MODE_HEATING 0x0C00 // Temperature and fan speed in lower nibbles
|
||||
#define LG_ENERGY_SAVING_ON 0x1004
|
||||
#define LG_ENERGY_SAVING_OFF 0x1005
|
||||
#define LG_JET_ON 0x1008
|
||||
#define LG_WALL_SWING_ON 0x1314
|
||||
#define LG_WALL_SWING_OFF 0x1315
|
||||
#define LG_SWING_ON 0x1316 // not verified, for AKB73757604
|
||||
#define LG_SWING_OFF 0x1317 // not verified, for AKB73757604
|
||||
#define LG_TIMER_ON 0x8000 // relative minutes in lower nibbles
|
||||
#define LG_TIMER_OFF 0x9000 // relative minutes in lower nibbles
|
||||
#define LG_SLEEP 0xA000 // relative minutes in lower nibbles
|
||||
#define LG_CLEAR_ALL 0xB000 // Timers and sleep
|
||||
#define LG_POWER_DOWN 0xC005
|
||||
#define LG_LIGHT 0xC00A
|
||||
#define LG_AUTO_CLEAN_ON 0xC00B
|
||||
#define LG_AUTO_CLEAN_OFF 0xC00C
|
||||
|
||||
/*
|
||||
* Commands as printed in menu and uses as first parameter for sendCommandAndParameter
|
||||
*/
|
||||
#define LG_COMMAND_OFF '0'
|
||||
#define LG_COMMAND_ON '1'
|
||||
#define LG_COMMAND_SWING 's'
|
||||
#define LG_COMMAND_AUTO_CLEAN 'a'
|
||||
#define LG_COMMAND_JET 'j'
|
||||
#define LG_COMMAND_ENERGY 'e'
|
||||
#define LG_COMMAND_LIGHT 'l'
|
||||
#define LG_COMMAND_FAN_SPEED 'f'
|
||||
#define LG_COMMAND_TEMPERATURE 't'
|
||||
#define LG_COMMAND_TEMPERATURE_PLUS '+'
|
||||
#define LG_COMMAND_TEMPERATURE_MINUS '-'
|
||||
#define LG_COMMAND_MODE 'm'
|
||||
#define LG_COMMAND_SLEEP 'S'
|
||||
#define LG_COMMAND_TIMER_ON 'T'
|
||||
#define LG_COMMAND_TIMER_OFF 'O'
|
||||
#define LG_COMMAND_CLEAR_ALL 'C'
|
||||
|
||||
/*
|
||||
* The modes are encoded as character values for easy printing :-)
|
||||
*/
|
||||
#define AC_MODE_COOLING 'c'
|
||||
#define AC_MODE_DEHUMIDIFIYING 'd'
|
||||
#define AC_MODE_FAN 'f'
|
||||
#define AC_MODE_AUTO 'a'
|
||||
#define AC_MODE_HEATING 'h'
|
||||
|
||||
// see https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h
|
||||
union LGProtocol {
|
||||
uint32_t raw; ///< The state of the IR remote in IR code form.
|
||||
struct {
|
||||
uint32_t Checksum :4;
|
||||
uint32_t Fan :3;
|
||||
uint32_t FanExt :1;
|
||||
uint32_t Temp :4;
|
||||
uint32_t Mode :4; // highest bit 1 => Set temperature and ventilation by mode
|
||||
uint32_t Function :3;
|
||||
uint32_t SwitchOnMask :1; /* Content is 0 when switching from off to on */
|
||||
uint32_t Signature :8; /* Content is 0x88, LG_ADDRESS */
|
||||
};
|
||||
};
|
||||
|
||||
class Aircondition_LG {
|
||||
public:
|
||||
bool sendCommandAndParameter(char aCommand, int aParameter);
|
||||
void setType(bool aIsWallType);
|
||||
void printMenu(Print *aSerial);
|
||||
void sendIRCommand(uint16_t aCommand);
|
||||
void sendTemperatureFanSpeedAndMode();
|
||||
/*
|
||||
* Internal state of the air condition
|
||||
*/
|
||||
#define LG_IS_WALL_TYPE true
|
||||
#define LG_IS_TOWER_TYPE false
|
||||
bool ACIsWallType; // false : TOWER, true : WALL
|
||||
bool PowerIsOn;
|
||||
|
||||
// These value are encoded and sent by AC_LG_SendCommandAndParameter()
|
||||
uint8_t FanIntensity = 1; // 0 -> low, 4 high, 5 -> cycle
|
||||
uint8_t Temperature = 22; // temperature : 18 ~ 30
|
||||
uint8_t Mode = AC_MODE_COOLING;
|
||||
bool useLG2Protocol = false;
|
||||
};
|
||||
|
||||
/** @}*/
|
||||
#endif // _AC_LG_H
|
||||
322
arduino-libs/arduino-cli/libraries/IRremote/src/ac_LG.hpp
Normal file
322
arduino-libs/arduino-cli/libraries/IRremote/src/ac_LG.hpp
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* ac_LG.hpp
|
||||
*
|
||||
* Contains functions for sending LG air conditioner IR Protocol
|
||||
* There is no state plausibility check, e.g. you can send fan speed in Mode D and change temperature in mode F
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2021-2022 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _AC_LG_HPP
|
||||
#define _AC_LG_HPP
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(INFO) && !defined(LOCAL_INFO)
|
||||
#define LOCAL_INFO
|
||||
#else
|
||||
//#define LOCAL_INFO // This enables info output only for this file
|
||||
#endif
|
||||
//#define DEBUG // for more output from the LG-AC driver.
|
||||
#include "IRremoteInt.h"
|
||||
#include "ac_LG.h" // useful constants
|
||||
#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup Airconditoners Air conditioner special code
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* LG remote measurements: Type AKB73315611, Ver1.1 from 2011.03.01
|
||||
* Internal crystal: 4 MHz
|
||||
* Header: 8.9 ms mark 4.15 ms space
|
||||
* Data: 500 / 540 and 500 / 1580;
|
||||
* Clock is nor synchronized with gate so you have 19 and sometimes 19 and a spike pulses for mark
|
||||
* Duty: 9 us on 17 us off => around 33 % duty
|
||||
* NO REPEAT: If value like temperature has changed during long press, the last value is send at button release
|
||||
* If you do a double press -tested with the fan button-, the next value can be sent after 118 ms
|
||||
*/
|
||||
#define SIZE_OF_FAN_SPEED_MAPPING_TABLE 4
|
||||
const int AC_FAN_TOWER[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 4, 6, 6 }; // last dummy entry to avoid out of bounds access
|
||||
const int AC_FAN_WALL[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 2, 4, 5 }; // 0 -> low, 4 high, 5 -> cycle
|
||||
|
||||
void Aircondition_LG::setType(bool aIsWallType) {
|
||||
ACIsWallType = aIsWallType;
|
||||
#if defined(LOCAL_INFO)
|
||||
Serial.print(F("Set wall type to "));
|
||||
Serial.println(aIsWallType);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Aircondition_LG::printMenu(Print *aSerial) {
|
||||
aSerial->println();
|
||||
aSerial->println();
|
||||
aSerial->println(F("Type command and optional parameter without a separator"));
|
||||
aSerial->println(F("0 Off"));
|
||||
aSerial->println(F("1 On"));
|
||||
aSerial->println(F("s Swing <0 or 1>"));
|
||||
aSerial->println(F("a Auto clean <0 or 1>"));
|
||||
aSerial->println(F("j Jet on"));
|
||||
aSerial->println(F("e Energy saving <0 or 1>"));
|
||||
aSerial->println(F("l Lights toggle"));
|
||||
aSerial->println(F("f Fan speed <0 to 2 or 3 for cycle>"));
|
||||
aSerial->println(F("t Temperature <18 to 30> degree"));
|
||||
aSerial->println(F("+ Temperature + 1"));
|
||||
aSerial->println(F("- Temperature - 1"));
|
||||
aSerial->println(F("m <c(ool) or a(uto) or d(ehumidifying) or h(eating) or f(an) mode>"));
|
||||
aSerial->println(F("S Sleep after <0 to 420> minutes"));
|
||||
aSerial->println(F("T Timer on after <0 to 1439> minutes"));
|
||||
aSerial->println(F("O Timer off after <0 to 1439> minutes"));
|
||||
aSerial->println(F("C Clear all timer and sleep"));
|
||||
aSerial->println(F("e.g. \"s1\" or \"t23\" or \"mc\" or \"O60\" or \"+\""));
|
||||
aSerial->println(F("No plausibility check is made!"));
|
||||
aSerial->println();
|
||||
}
|
||||
|
||||
/*
|
||||
* Send repeat
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
* @param aCommand one of LG_COMMAND_OFF, LG_COMMAND_ON etc.
|
||||
*/
|
||||
bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) {
|
||||
// Commands without parameter
|
||||
switch (aCommand) {
|
||||
case LG_COMMAND_OFF: // off
|
||||
sendIRCommand(LG_POWER_DOWN);
|
||||
PowerIsOn = false;
|
||||
return true;
|
||||
|
||||
case LG_COMMAND_ON: // on
|
||||
PowerIsOn = false; // set to false in order to suppress on bit
|
||||
sendTemperatureFanSpeedAndMode();
|
||||
return true;
|
||||
|
||||
case LG_COMMAND_JET:
|
||||
IR_DEBUG_PRINTLN(F("Send jet on"));
|
||||
sendIRCommand(LG_JET_ON);
|
||||
return true;
|
||||
|
||||
case LG_COMMAND_LIGHT:
|
||||
sendIRCommand(LG_LIGHT);
|
||||
return true;
|
||||
|
||||
case LG_COMMAND_CLEAR_ALL:
|
||||
sendIRCommand(LG_CLEAR_ALL);
|
||||
return true;
|
||||
|
||||
case LG_COMMAND_TEMPERATURE_PLUS:
|
||||
if (18 <= Temperature && Temperature <= 29) {
|
||||
Temperature++;
|
||||
sendTemperatureFanSpeedAndMode();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case LG_COMMAND_TEMPERATURE_MINUS:
|
||||
if (19 <= Temperature && Temperature <= 30) {
|
||||
Temperature--;
|
||||
sendTemperatureFanSpeedAndMode();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
PowerIsOn = true;
|
||||
|
||||
/*
|
||||
* Now the commands which require a parameter
|
||||
*/
|
||||
if (aParameter < 0) {
|
||||
IR_DEBUG_PRINT(F("Error: Parameter is less than 0"));
|
||||
return false;
|
||||
}
|
||||
switch (aCommand) {
|
||||
|
||||
case LG_COMMAND_MODE:
|
||||
Mode = aParameter + '0';
|
||||
sendTemperatureFanSpeedAndMode();
|
||||
break;
|
||||
|
||||
case LG_COMMAND_SWING:
|
||||
IR_DEBUG_PRINT(F("Send air swing="));
|
||||
IR_DEBUG_PRINTLN(aParameter);
|
||||
if (ACIsWallType) {
|
||||
if (aParameter) {
|
||||
sendIRCommand(LG_WALL_SWING_ON);
|
||||
} else {
|
||||
sendIRCommand(LG_WALL_SWING_OFF);
|
||||
}
|
||||
} else {
|
||||
if (aParameter) {
|
||||
sendIRCommand(LG_SWING_ON);
|
||||
} else {
|
||||
sendIRCommand(LG_SWING_OFF);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_AUTO_CLEAN:
|
||||
IR_DEBUG_PRINT(F("Send auto clean="));
|
||||
IR_DEBUG_PRINTLN(aParameter);
|
||||
if (aParameter) {
|
||||
sendIRCommand(LG_AUTO_CLEAN_ON);
|
||||
} else {
|
||||
sendIRCommand(LG_AUTO_CLEAN_OFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_ENERGY:
|
||||
IR_DEBUG_PRINT(F("Send energy saving on="));
|
||||
IR_DEBUG_PRINTLN(aParameter);
|
||||
if (aParameter) {
|
||||
sendIRCommand(LG_ENERGY_SAVING_ON);
|
||||
} else {
|
||||
sendIRCommand(LG_ENERGY_SAVING_OFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_FAN_SPEED:
|
||||
if (aParameter < SIZE_OF_FAN_SPEED_MAPPING_TABLE) {
|
||||
FanIntensity = aParameter;
|
||||
sendTemperatureFanSpeedAndMode();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_TEMPERATURE:
|
||||
if (18 <= aParameter && aParameter <= 30) {
|
||||
Temperature = aParameter;
|
||||
sendTemperatureFanSpeedAndMode();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_SLEEP:
|
||||
// 420 = maximum I have recorded
|
||||
if (aParameter <= 420) {
|
||||
sendIRCommand(LG_SLEEP + aParameter);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_TIMER_ON:
|
||||
// 1440 = minutes of a day
|
||||
if (aParameter <= 1439) {
|
||||
sendIRCommand(LG_TIMER_ON + aParameter);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LG_COMMAND_TIMER_OFF:
|
||||
if (aParameter <= 1439) {
|
||||
sendIRCommand(LG_TIMER_OFF + aParameter);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Aircondition_LG::sendIRCommand(uint16_t aCommand) {
|
||||
|
||||
#if defined(LOCAL_INFO)
|
||||
Serial.print(F("Send code=0x"));
|
||||
Serial.print(aCommand, HEX);
|
||||
Serial.print(F(" | 0b"));
|
||||
Serial.println(aCommand, BIN);
|
||||
#endif
|
||||
|
||||
IrSender.sendLG((uint8_t) LG_ADDRESS, aCommand, 0, false, useLG2Protocol);
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes values from static variables
|
||||
*/
|
||||
void Aircondition_LG::sendTemperatureFanSpeedAndMode() {
|
||||
|
||||
uint8_t tTemperature = Temperature;
|
||||
#if defined(LOCAL_INFO)
|
||||
Serial.print(F("Send temperature="));
|
||||
Serial.print(tTemperature);
|
||||
Serial.print(F(" fan intensity="));
|
||||
Serial.print(FanIntensity);
|
||||
Serial.print(F(" mode="));
|
||||
Serial.println((char )Mode);
|
||||
#endif
|
||||
|
||||
WordUnion tIRCommand;
|
||||
tIRCommand.UWord = 0;
|
||||
|
||||
// Temperature is coded in the upper nibble of the LowByte
|
||||
tIRCommand.UByte.LowByte = ((tTemperature - 15) << 4); // 16 -> 0x00, 18 -> 0x30, 30 -> 0xF0
|
||||
|
||||
// Fan intensity is coded in the lower nibble of the LowByte
|
||||
if (ACIsWallType) {
|
||||
tIRCommand.UByte.LowByte |= AC_FAN_WALL[FanIntensity];
|
||||
} else {
|
||||
tIRCommand.UByte.LowByte |= AC_FAN_TOWER[FanIntensity];
|
||||
}
|
||||
|
||||
switch (Mode) {
|
||||
case AC_MODE_COOLING:
|
||||
tIRCommand.UByte.HighByte = LG_MODE_COOLING >> 8;
|
||||
break;
|
||||
case AC_MODE_HEATING:
|
||||
tIRCommand.UByte.HighByte = LG_MODE_HEATING >> 8;
|
||||
break;
|
||||
case AC_MODE_AUTO:
|
||||
tIRCommand.UByte.HighByte = LG_MODE_AUTO >> 8;
|
||||
break;
|
||||
case AC_MODE_FAN:
|
||||
tTemperature = 18;
|
||||
tIRCommand.UByte.HighByte = LG_MODE_FAN >> 8;
|
||||
break;
|
||||
case AC_MODE_DEHUMIDIFIYING:
|
||||
tIRCommand.UWord = LG_MODE_DEHUMIDIFIYING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!PowerIsOn) {
|
||||
// switch on requires masked bit
|
||||
tIRCommand.UByte.HighByte &= ~(LG_SWITCH_ON_MASK >> 8);
|
||||
}
|
||||
PowerIsOn = true;
|
||||
|
||||
sendIRCommand(tIRCommand.UWord);
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _AC_LG_HPP
|
||||
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
Optimized digital functions for AVR microcontrollers
|
||||
by Watterott electronic (www.watterott.com)
|
||||
based on http://code.google.com/p/digitalwritefast
|
||||
*/
|
||||
|
||||
#ifndef __digitalWriteFast_h_
|
||||
#define __digitalWriteFast_h_ 1
|
||||
|
||||
//#define SANGUINO_PINOUT //define for Sanguino pinout
|
||||
|
||||
// general macros/defines
|
||||
#if !defined(BIT_READ)
|
||||
# define BIT_READ(value, bit) ((value) & (1UL << (bit)))
|
||||
#endif
|
||||
#if !defined(BIT_SET)
|
||||
# define BIT_SET(value, bit) ((value) |= (1UL << (bit)))
|
||||
#endif
|
||||
#if !defined(BIT_CLEAR)
|
||||
# define BIT_CLEAR(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#endif
|
||||
#if !defined(BIT_WRITE)
|
||||
# define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit))
|
||||
#endif
|
||||
|
||||
#if !defined(SWAP)
|
||||
# define SWAP(x,y) do{ (x)=(x)^(y); (y)=(x)^(y); (x)=(x)^(y); }while(0)
|
||||
#endif
|
||||
|
||||
#if !defined(DEC)
|
||||
# define DEC (10)
|
||||
#endif
|
||||
#if !defined(HEX)
|
||||
# define HEX (16)
|
||||
#endif
|
||||
#if !defined(OCT)
|
||||
# define OCT (8)
|
||||
#endif
|
||||
#if !defined(BIN)
|
||||
# define BIN (2)
|
||||
#endif
|
||||
|
||||
// workarounds for ARM microcontrollers
|
||||
#if (!defined(__AVR__) || \
|
||||
defined(ARDUINO_ARCH_SAM) || \
|
||||
defined(ARDUINO_ARCH_SAMD))
|
||||
|
||||
#if !defined(PROGMEM)
|
||||
# define PROGMEM
|
||||
#endif
|
||||
#if !defined(PGM_P)
|
||||
# define PGM_P const char *
|
||||
#endif
|
||||
#if !defined(PSTR)
|
||||
# define PSTR(str) (str)
|
||||
#endif
|
||||
|
||||
#if !defined(memcpy_P)
|
||||
# define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||
#endif
|
||||
#if !defined(strcpy_P)
|
||||
# define strcpy_P(dst, src) strcpy((dst), (src))
|
||||
#endif
|
||||
#if !defined(strcat_P)
|
||||
# define strcat_P(dst, src) strcat((dst), (src))
|
||||
#endif
|
||||
#if !defined(strcmp_P)
|
||||
# define strcmp_P(a, b) strcmp((a), (b))
|
||||
#endif
|
||||
#if !defined(strcasecmp_P)
|
||||
# define strcasecmp_P(a, b) strcasecmp((a), (b))
|
||||
#endif
|
||||
#if !defined(strncmp_P)
|
||||
# define strncmp_P(a, b, n) strncmp((a), (b), (n))
|
||||
#endif
|
||||
#if !defined(strncasecmp_P)
|
||||
# define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n))
|
||||
#endif
|
||||
#if !defined(strstr_P)
|
||||
# define strstr_P(a, b) strstr((a), (b))
|
||||
#endif
|
||||
#if !defined(strlen_P)
|
||||
# define strlen_P(a) strlen((a))
|
||||
#endif
|
||||
#if !defined(sprintf_P)
|
||||
# define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if !defined(pgm_read_byte)
|
||||
# define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
#if !defined(pgm_read_word)
|
||||
# define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
#if !defined(pgm_read_dword)
|
||||
# define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// digital functions
|
||||
//#if !defined(digitalPinToPortReg)
|
||||
#define SPI_SW_SS_PIN (10) //SS on Uno (for software SPI)
|
||||
#define SPI_SW_MOSI_PIN (11) //MOSI on Uno (for software SPI)
|
||||
#define SPI_SW_MISO_PIN (12) //MISO on Uno (for software SPI)
|
||||
#define SPI_SW_SCK_PIN (13) //SCK on Uno (for software SPI)
|
||||
|
||||
// --- Arduino Due and SAM3X8E based boards ---
|
||||
#if (defined(ARDUINO_SAM_DUE) || \
|
||||
defined(__SAM3X8E__))
|
||||
|
||||
#define UART_RX_PIN (0)
|
||||
#define UART_TX_PIN (1)
|
||||
|
||||
#define I2C_SDA_PIN (20)
|
||||
#define I2C_SCL_PIN (21)
|
||||
|
||||
#define SPI_HW_SS_PIN (78) //SS0:77, SS1:87, SS2:86, SS3:78
|
||||
#define SPI_HW_MOSI_PIN (75) //75
|
||||
#define SPI_HW_MISO_PIN (74) //74
|
||||
#define SPI_HW_SCK_PIN (76) //76
|
||||
|
||||
|
||||
// --- Arduino Zero and SAMD21G18 based boards ---
|
||||
#elif (defined(ARDUINO_SAMD_ZERO) || \
|
||||
defined(__SAMD21G18A__))
|
||||
|
||||
#define UART_RX_PIN (0)
|
||||
#define UART_TX_PIN (1)
|
||||
|
||||
#define I2C_SDA_PIN (16)
|
||||
#define I2C_SCL_PIN (17)
|
||||
|
||||
#define SPI_HW_SS_PIN (14) //14
|
||||
#define SPI_HW_MOSI_PIN (21) //21
|
||||
#define SPI_HW_MISO_PIN (18) //18
|
||||
#define SPI_HW_SCK_PIN (20) //20
|
||||
|
||||
|
||||
// --- Arduino Mega and ATmega128x/256x based boards ---
|
||||
#elif (defined(ARDUINO_AVR_MEGA) || \
|
||||
defined(ARDUINO_AVR_MEGA1280) || \
|
||||
defined(ARDUINO_AVR_MEGA2560) || \
|
||||
defined(__AVR_ATmega1280__) || \
|
||||
defined(__AVR_ATmega1281__) || \
|
||||
defined(__AVR_ATmega2560__) || \
|
||||
defined(__AVR_ATmega2561__))
|
||||
|
||||
#define UART_RX_PIN (0) //PE0
|
||||
#define UART_TX_PIN (1) //PE1
|
||||
|
||||
#define I2C_SDA_PIN (20)
|
||||
#define I2C_SCL_PIN (21)
|
||||
|
||||
#define SPI_HW_SS_PIN (53) //PB0
|
||||
#define SPI_HW_MOSI_PIN (51) //PB2
|
||||
#define SPI_HW_MISO_PIN (50) //PB3
|
||||
#define SPI_HW_SCK_PIN (52) //PB1
|
||||
|
||||
#define __digitalPinToPortReg(P) \
|
||||
(((P) >= 22 && (P) <= 29) ? &PORTA : \
|
||||
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : \
|
||||
(((P) >= 30 && (P) <= 37) ? &PORTC : \
|
||||
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : \
|
||||
((((P) <= 3) || (P) == 5) ? &PORTE : \
|
||||
(((P) >= 54 && (P) <= 61) ? &PORTF : \
|
||||
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : \
|
||||
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : \
|
||||
(((P) == 14 || (P) == 15) ? &PORTJ : \
|
||||
(((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL))))))))))
|
||||
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
(((P) >= 22 && (P) <= 29) ? &DDRA : \
|
||||
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : \
|
||||
(((P) >= 30 && (P) <= 37) ? &DDRC : \
|
||||
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : \
|
||||
((((P) <= 3) || (P) == 5) ? &DDRE : \
|
||||
(((P) >= 54 && (P) <= 61) ? &DDRF : \
|
||||
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : \
|
||||
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : \
|
||||
(((P) == 14 || (P) == 15) ? &DDRJ : \
|
||||
(((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL))))))))))
|
||||
|
||||
#define __digitalPinToPINReg(P) \
|
||||
(((P) >= 22 && (P) <= 29) ? &PINA : \
|
||||
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \
|
||||
(((P) >= 30 && (P) <= 37) ? &PINC : \
|
||||
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \
|
||||
((((P) <= 3) || (P) == 5) ? &PINE : \
|
||||
(((P) >= 54 && (P) <= 61) ? &PINF : \
|
||||
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \
|
||||
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \
|
||||
(((P) == 14 || (P) == 15) ? &PINJ : \
|
||||
(((P) >= 62 && (P) <= 69) ? &PINK : &PINL))))))))))
|
||||
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) >= 7 && (P) <= 9) ? (P) - 3 : \
|
||||
(((P) >= 10 && (P) <= 13) ? (P) - 6 : \
|
||||
(((P) >= 22 && (P) <= 29) ? (P) - 22 : \
|
||||
(((P) >= 30 && (P) <= 37) ? 37 - (P) : \
|
||||
(((P) >= 39 && (P) <= 41) ? 41 - (P) : \
|
||||
(((P) >= 42 && (P) <= 49) ? 49 - (P) : \
|
||||
(((P) >= 50 && (P) <= 53) ? 53 - (P) : \
|
||||
(((P) >= 54 && (P) <= 61) ? (P) - 54 : \
|
||||
(((P) >= 62 && (P) <= 69) ? (P) - 62 : \
|
||||
(((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : \
|
||||
(((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : \
|
||||
(((P) == 19) ? 2 : \
|
||||
(((P) == 5 || (P) == 6 || (P) == 18) ? 3 : \
|
||||
(((P) == 2) ? 4 : \
|
||||
(((P) == 3 || (P) == 4) ? 5 : 7)))))))))))))))
|
||||
|
||||
|
||||
// --- Arduino MightyCore standard pinout ---
|
||||
#elif (defined(__AVR_ATmega1284P__) || \
|
||||
defined(__AVR_ATmega1284__) || \
|
||||
defined(__AVR_ATmega644P__) || \
|
||||
defined(__AVR_ATmega644A__) || \
|
||||
defined(__AVR_ATmega644__) || \
|
||||
defined(__AVR_ATmega324PB__) || \
|
||||
defined(__AVR_ATmega324PA__) || \
|
||||
defined(__AVR_ATmega324P__) || \
|
||||
defined(__AVR_ATmega324A__) || \
|
||||
defined(__AVR_ATmega164P__) || \
|
||||
defined(__AVR_ATmega164A__) || \
|
||||
defined(__AVR_ATmega32__) || \
|
||||
defined(__AVR_ATmega16__) || \
|
||||
defined(__AVR_ATmega8535__)) && \
|
||||
!defined(BOBUINO_PINOUT)
|
||||
|
||||
#define UART_RX_PIN (8) //PD0
|
||||
#define UART_TX_PIN (9) //PD1
|
||||
|
||||
#define I2C_SDA_PIN (17) //PC1
|
||||
#define I2C_SCL_PIN (16) //PC0
|
||||
|
||||
#define SPI_HW_SS_PIN (4) //PB4
|
||||
#define SPI_HW_MOSI_PIN (5) //PB5
|
||||
#define SPI_HW_MISO_PIN (6) //PB6
|
||||
#define SPI_HW_SCK_PIN (7) //PB7
|
||||
|
||||
#if defined(__AVR_ATmega324PB__)
|
||||
#define __digitalPinToPortReg(P) \
|
||||
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : (((P) >= 24 && (P) <= 31) ? &PORTA : &PORTE))))
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : (((P) >= 24 && (P) <= 31) ? &DDRA : &DDRE))))
|
||||
#define __digitalPinToPINReg(P) \
|
||||
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : (((P) >= 24 && (P) <= 31) ? &PINA : &PINE))))
|
||||
# if defined(SANGUINO_PINOUT)
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (7 - ((P) - 24)) : (P) - 32))))
|
||||
# else //MightyCore Pinout
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (P) - 24 : (P) - 32))))
|
||||
# endif
|
||||
#else
|
||||
#define __digitalPinToPortReg(P) \
|
||||
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA)))
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : &DDRA)))
|
||||
#define __digitalPinToPINReg(P) \
|
||||
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : &PINA)))
|
||||
# if defined(SANGUINO_PINOUT)
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (7 - ((P) - 24)))))
|
||||
# else //MightyCore Pinout
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24)))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// --- Arduino Leonardo and ATmega16U4/32U4 based boards ---
|
||||
#elif (defined(ARDUINO_AVR_LEONARDO) || \
|
||||
defined(__AVR_ATmega16U4__) || \
|
||||
defined(__AVR_ATmega32U4__))
|
||||
|
||||
#define UART_RX_PIN (0) //PD2
|
||||
#define UART_TX_PIN (1) //PD3
|
||||
|
||||
#define I2C_SDA_PIN (2) //PD1
|
||||
#define I2C_SCL_PIN (3) //PD0
|
||||
|
||||
#define SPI_HW_SS_PIN (17) //PB0
|
||||
#define SPI_HW_MOSI_PIN (16) //PB2
|
||||
#define SPI_HW_MISO_PIN (14) //PB3
|
||||
#define SPI_HW_SCK_PIN (15) //PB1
|
||||
|
||||
#define __digitalPinToPortReg(P) \
|
||||
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PORTD : (((P) == 5 || (P) == 13) ? &PORTC : (((P) >= 18 && (P) <= 23)) ? &PORTF : (((P) == 7) ? &PORTE : &PORTB)))
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &DDRD : (((P) == 5 || (P) == 13) ? &DDRC : (((P) >= 18 && (P) <= 23)) ? &DDRF : (((P) == 7) ? &DDRE : &DDRB)))
|
||||
#define __digitalPinToPINReg(P) \
|
||||
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PIND : (((P) == 5 || (P) == 13) ? &PINC : (((P) >= 18 && (P) <= 23)) ? &PINF : (((P) == 7) ? &PINE : &PINB)))
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) >= 8 && (P) <= 11) ? (P) - 4 : (((P) >= 18 && (P) <= 21) ? 25 - (P) : (((P) == 0) ? 2 : (((P) == 1) ? 3 : (((P) == 2) ? 1 : (((P) == 3) ? 0 : (((P) == 4) ? 4 : (((P) == 6) ? 7 : (((P) == 13) ? 7 : (((P) == 14) ? 3 : (((P) == 15) ? 1 : (((P) == 16) ? 2 : (((P) == 17) ? 0 : (((P) == 22) ? 1 : (((P) == 23) ? 0 : (((P) == 24) ? 4 : (((P) == 25) ? 7 : (((P) == 26) ? 4 : (((P) == 27) ? 5 : 6 )))))))))))))))))))
|
||||
|
||||
|
||||
// --- Arduino Uno and ATmega168/328 based boards ---
|
||||
#elif (defined(ARDUINO_AVR_UNO) || \
|
||||
defined(ARDUINO_AVR_DUEMILANOVE) || \
|
||||
defined(__AVR_ATmega8__) || \
|
||||
defined(__AVR_ATmega48__) || \
|
||||
defined(__AVR_ATmega48P__) || \
|
||||
defined(__AVR_ATmega48PB__) || \
|
||||
defined(__AVR_ATmega88P__) || \
|
||||
defined(__AVR_ATmega88PB__) || \
|
||||
defined(__AVR_ATmega168__) || \
|
||||
defined(__AVR_ATmega168PA__) || \
|
||||
defined(__AVR_ATmega168PB__) || \
|
||||
defined(__AVR_ATmega328__) || \
|
||||
defined(__AVR_ATmega328P__) || \
|
||||
defined(__AVR_ATmega328PB__))
|
||||
|
||||
#define UART_RX_PIN (0) //PD0
|
||||
#define UART_TX_PIN (1) //PD1
|
||||
|
||||
#define I2C_SDA_PIN (18) //A4
|
||||
#define I2C_SCL_PIN (19) //A5
|
||||
|
||||
#define SPI_HW_SS_PIN (10) //PB0
|
||||
#define SPI_HW_MOSI_PIN (11) //PB2
|
||||
#define SPI_HW_MISO_PIN (12) //PB3
|
||||
#define SPI_HW_SCK_PIN (13) //PB1
|
||||
|
||||
#if defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328PB__)
|
||||
#define __digitalPinToPortReg(P) \
|
||||
(((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : (((P) >= 14 && (P) <= 19) ? &PORTC : &PORTE)))
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
(((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : (((P) >= 14 && (P) <= 19) ? &DDRC : &DDRE)))
|
||||
#define __digitalPinToPINReg(P) \
|
||||
(((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : (((P) >= 14 && (P) <= 19) ? &PINC : &PINE)))
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (((P) >= 14 && (P) <= 19) ? (P) - 14 : (((P) >= 20 && (P) <= 21) ? (P) - 18 : (P) - 22))))
|
||||
#else
|
||||
#define __digitalPinToPortReg(P) \
|
||||
(((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC))
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
(((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC))
|
||||
#define __digitalPinToPINReg(P) \
|
||||
(((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC))
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
|
||||
#endif
|
||||
|
||||
// --- Arduino Uno WiFi Rev 2, Nano Every ---
|
||||
#elif defined(__AVR_ATmega4809__)
|
||||
|
||||
#define UART_RX_PIN (0) //PB0
|
||||
#define UART_TX_PIN (1) //PB1
|
||||
|
||||
#define I2C_SDA_PIN (22) //PA2
|
||||
#define I2C_SCL_PIN (23) //PA3
|
||||
|
||||
#define SPI_HW_SS_PIN (8) //PE3
|
||||
#define SPI_HW_MOSI_PIN (11) //PE0
|
||||
#define SPI_HW_MISO_PIN (12) //PE1
|
||||
#define SPI_HW_SCK_PIN (13) //PE2
|
||||
|
||||
#define __digitalPinToPortReg(P) \
|
||||
(((P) == 2 || (P) == 7 ) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT : ((P) == 4) ? &VPORTC.OUT : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT : &VPORTF.OUT)
|
||||
#define __digitalPinToDDRReg(P) \
|
||||
(((P) == 2 || (P) == 7 ) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR : ((P) == 4) ? &VPORTC.DIR : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR : &VPORTF.DIR)
|
||||
#define __digitalPinToPINReg(P) \
|
||||
(((P) == 2 || (P) == 7 ) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN : ((P) == 4) ? &VPORTC.IN : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN : &VPORTF.IN)
|
||||
#define __digitalPinToBit(P) \
|
||||
(((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 : ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 : ((P) == 6 || (P) == 20) ? 4 : ((P) == 3 || (P) == 21) ? 5 : 6 )
|
||||
|
||||
|
||||
// TinyCore
|
||||
// https://raw.githubusercontent.com/xukangmin/TinyCore/master/avr/package/package_tinycore_index.json
|
||||
// https://docs.tinycore.dev/en/latest/
|
||||
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
|
||||
#define __digitalPinToPortReg(P) ((P) <= 5 ? &VPORTB.OUT : ((P) <= 9 ? &VPORTC.OUT : ((P) <= 16 ? &VPORTA.OUT : ((P) <= 18 ? &VPORTB.OUT : &VPORTC.OUT))))
|
||||
#define __digitalPinToDDRReg(P) ((P) <= 5 ? &VPORTB.DIR : ((P) <= 9 ? &VPORTC.DIR : ((P) <= 16 ? &VPORTA.DIR : ((P) <= 18 ? &VPORTB.DIR : &VPORTC.DIR))))
|
||||
#define __digitalPinToPINReg(P) ((P) <= 5 ? &VPORTB.IN : ((P) <= 9 ? &VPORTC.IN : ((P) <= 16 ? &VPORTA.IN : ((P) <= 18 ? &VPORTB.IN : &VPORTC.IN))))
|
||||
#define __digitalPinToBit(P) ( (P) <= 3 ? (3 - P) : ((P) <= 5 ? (P) : ((P) <= 9 ? (P - 6) : ((P) <= 16 ? ((P) - 9) : ((P) <= 18 ? ((P) - 11) : ((P) - 15))))) )
|
||||
|
||||
|
||||
// --- ATtinyX5 ---
|
||||
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
// we have only PORTB
|
||||
#define __digitalPinToPortReg(P) (&PORTB)
|
||||
#define __digitalPinToDDRReg(P) (&DDRB)
|
||||
#define __digitalPinToPINReg(P) (&PINB)
|
||||
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
|
||||
|
||||
|
||||
// --- ATtiny88 ---
|
||||
#elif defined(__AVR_ATtiny88__)
|
||||
# if defined(ARDUINO_AVR_DIGISPARKPRO)
|
||||
#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 14 ? &PORTB : ((P) <= 18 ? &PORTA : &PORTC)))
|
||||
#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 14 ? &DDRB : ((P) <= 18 ? &DDRA : &DDRC)))
|
||||
#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 14 ? &PINB : ((P) <= 18 ? &PINA : &PINC)))
|
||||
#define __digitalPinToBit(P) ( (P) <= 7 ? (P) : ((P) <= 13 ? ((P) - 8) : ((P) == 14 ? 7 : ((P) <= 16 ? ((P) - 14) : ((P) <= 18 ? ((P) - 17) : ((P) == 25 ? 7 : ((P) - 19)))))) )
|
||||
# else
|
||||
#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 15 ? &PORTB : ((P) <= 22 ? &PORTC : ((P) <= 26 ? &PORTA : &PORTC))))
|
||||
#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 15 ? &DDRB : ((P) <= 22 ? &DDRC : ((P) <= 26 ? &DDRA : &DDRC))))
|
||||
#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 15 ? &PINB : ((P) <= 22 ? &PINC : ((P) <= 26 ? &PINA : &PINC))))
|
||||
#define __digitalPinToBit(P) ((P) <= 15 ? ((P) & 0x7) : ((P) == 16 ? (7) : ((P) <= 22 ? ((P) - 17) : ((P) == 27 ? (6) : ((P) - 23)))))
|
||||
# endif
|
||||
|
||||
|
||||
// --- ATtinyX4 + ATtinyX7 ---
|
||||
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
|
||||
# if defined(ARDUINO_AVR_DIGISPARKPRO) || PIN_PA7 == 5
|
||||
// Strange enumeration of pins on Digispark board and core library
|
||||
#define __digitalPinToPortReg(P) (((P) <= 4) ? &PORTB : &PORTA)
|
||||
#define __digitalPinToDDRReg(P) (((P) <= 4) ? &DDRB : &DDRA)
|
||||
#define __digitalPinToPINReg(P) (((P) <= 4) ? &PINB : &PINA)
|
||||
#define __digitalPinToBit(P) (((P) <= 2) ? (P) : (((P) == 3) ? 6 : (((P) == 4) ? 3 : (((P) == 5) ? 7 : (P) - 6 ))))
|
||||
# else
|
||||
// ATtinyX4: PORTA for 0 to 7, PORTB for 8 to 11
|
||||
// ATtinyX7: PORTA for 0 to 7, PORTB for 8 to 15
|
||||
#define __digitalPinToPortReg(P) (((P) <= 7) ? &PORTA : &PORTB)
|
||||
#define __digitalPinToDDRReg(P) (((P) <= 7) ? &DDRA : &DDRB)
|
||||
#define __digitalPinToPINReg(P) (((P) <= 7) ? &PINA : &PINB)
|
||||
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (P) - 8 )
|
||||
# endif
|
||||
|
||||
// --- Other ---
|
||||
#else
|
||||
|
||||
#define I2C_SDA_PIN SDA
|
||||
#define I2C_SCL_PIN SCL
|
||||
|
||||
#define SPI_HW_SS_PIN SS
|
||||
#define SPI_HW_MOSI_PIN MOSI
|
||||
#define SPI_HW_MISO_PIN MISO
|
||||
#define SPI_HW_SCK_PIN SCK
|
||||
|
||||
|
||||
#endif
|
||||
//#endif //#if !defined(digitalPinToPortReg)
|
||||
|
||||
#if !defined(digitalWriteFast)
|
||||
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
|
||||
#define digitalWriteFast(P, V) \
|
||||
if (__builtin_constant_p(P)) { \
|
||||
BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
|
||||
} else { \
|
||||
digitalWrite((P), (V)); \
|
||||
}
|
||||
#else
|
||||
#define digitalWriteFast digitalWrite
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(pinModeFast)
|
||||
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
|
||||
#define pinModeFast(P, V) \
|
||||
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
|
||||
if (V == INPUT_PULLUP) {\
|
||||
BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
|
||||
BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
|
||||
} else { \
|
||||
BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
|
||||
} \
|
||||
} else { \
|
||||
pinMode((P), (V)); \
|
||||
}
|
||||
#else
|
||||
#define pinModeFast pinMode
|
||||
#endif
|
||||
#endif // !defined(pinModeFast)
|
||||
|
||||
#if !defined(digitalReadFast)
|
||||
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
|
||||
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
|
||||
#define __digitalReadFast(P ) \
|
||||
(__builtin_constant_p(P) ) ? \
|
||||
(( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : \
|
||||
digitalRead((P))
|
||||
#else
|
||||
#define digitalReadFast digitalRead
|
||||
#endif
|
||||
#endif // !defined(digitalReadFast)
|
||||
|
||||
#if !defined(digitalToggleFast)
|
||||
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
|
||||
#define digitalToggleFast(P) \
|
||||
if (__builtin_constant_p(P)) { \
|
||||
BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
|
||||
} else { \
|
||||
digitalWrite(P, ! digitalRead(P)); \
|
||||
}
|
||||
#else
|
||||
#define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P))
|
||||
#endif
|
||||
#endif // !defined(digitalToggleFast)
|
||||
|
||||
#endif //__digitalWriteFast_h_
|
||||
137
arduino-libs/arduino-cli/libraries/IRremote/src/ir_BoseWave.hpp
Normal file
137
arduino-libs/arduino-cli/libraries/IRremote/src/ir_BoseWave.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* ir_BoseWave.cpp
|
||||
*
|
||||
* Contains functions for receiving and sending Bose IR Protocol
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
*/
|
||||
#ifndef _IR_BOSEWAVE_HPP
|
||||
#define _IR_BOSEWAVE_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// BBBB OOO SSSS EEEEE
|
||||
// B B O O S E
|
||||
// BB B O O SSS EEEE
|
||||
// B B O O S E
|
||||
// BBBB OOO SSSS EEEEE
|
||||
//==============================================================================
|
||||
// see http://lirc.sourceforge.net/remotes/bose/WAVERADIO
|
||||
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#BOSE
|
||||
//
|
||||
// Support for Bose Wave Radio CD initially provided by https://github.com/uvotguy.
|
||||
//
|
||||
// As seen on my trusty oscilloscope, there is no repeat code. Instead, when I
|
||||
// press and hold a button on my remote, it sends a command, makes a 51.2ms space,
|
||||
// and resends the command, etc, etc.
|
||||
// LSB first, 1 start bit + 8 bit data + 8 bit inverted data + 1 stop bit.
|
||||
#define BOSEWAVE_BITS 16 // Command and inverted command
|
||||
|
||||
#define BOSEWAVE_HEADER_MARK 1014 // 1014 are 39 clock periods (I counted 3 times!)
|
||||
#define BOSEWAVE_HEADER_SPACE 1468 // 1468(measured), 1456 are 56 clock periods
|
||||
#define BOSEWAVE_BIT_MARK 520 // 520 are 20 clock periods
|
||||
#define BOSEWAVE_ZERO_SPACE 468 // 468 are 18 clock periods
|
||||
#define BOSEWAVE_ONE_SPACE 1468 // 1468(measured), 1456 are 56 clock periods
|
||||
|
||||
#define BOSEWAVE_REPEAT_SPACE 50000
|
||||
|
||||
//+=============================================================================
|
||||
|
||||
void IRsend::sendBoseWave(uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(BOSEWAVE_KHZ); // 38 kHz
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Header
|
||||
mark(BOSEWAVE_HEADER_MARK);
|
||||
space(BOSEWAVE_HEADER_SPACE);
|
||||
// send 8 command bits and then 8 inverted command bits LSB first
|
||||
uint16_t tData = ((~aCommand) << 8) | aCommand;
|
||||
|
||||
sendPulseDistanceWidthData(BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ZERO_SPACE, tData,
|
||||
BOSEWAVE_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command with a fixed space gap
|
||||
delay( BOSEWAVE_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
bool IRrecv::decodeBoseWave() {
|
||||
|
||||
// Check header "mark"
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], BOSEWAVE_HEADER_MARK)) {
|
||||
// no debug output, since this check is mainly to determine the received protocol
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check we have enough data +4 for initial gap, start bit mark and space + stop bit mark
|
||||
if (decodedIRData.rawDataPtr->rawlen != (2 * BOSEWAVE_BITS) + 4) {
|
||||
IR_DEBUG_PRINT(F("Bose: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 36"));
|
||||
return false;
|
||||
}
|
||||
// Check header "space"
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], BOSEWAVE_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("Bose: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(BOSEWAVE_BITS, 3, BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_ZERO_SPACE,
|
||||
PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Bose: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * BOSEWAVE_BITS)], BOSEWAVE_BIT_MARK)) {
|
||||
IR_DEBUG_PRINT(F("Bose: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
uint16_t tDecodedValue = decodedIRData.decodedRawData;
|
||||
uint8_t tCommandNotInverted = tDecodedValue & 0xFF; // comes first and is in the lower bits (LSB first :-))
|
||||
uint8_t tCommandInverted = tDecodedValue >> 8;
|
||||
// parity check for command. Use this variant to avoid compiler warning "comparison of promoted ~unsigned with unsigned [-Wsign-compare]"
|
||||
if ((tCommandNotInverted ^ tCommandInverted) != 0xFF) {
|
||||
IR_DEBUG_PRINT(F("Bose: "));
|
||||
IR_DEBUG_PRINT(F("Command and inverted command check failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for repeat
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < ((BOSEWAVE_REPEAT_SPACE + (BOSEWAVE_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
}
|
||||
|
||||
decodedIRData.command = tCommandNotInverted;
|
||||
decodedIRData.protocol = BOSEWAVE;
|
||||
decodedIRData.numberOfBits = BOSEWAVE_BITS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_BOSEWAVE_HPP
|
||||
253
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Denon.hpp
Normal file
253
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Denon.hpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* ir_Denon.cpp
|
||||
*
|
||||
* Contains functions for receiving and sending Denon/Sharp IR Protocol
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-2021 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_DENON_HPP
|
||||
#define _IR_DENON_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// DDDD EEEEE N N OOO N N
|
||||
// D D E NN N O O NN N
|
||||
// D D EEE N N N O O N N N
|
||||
// D D E N NN O O N NN
|
||||
// DDDD EEEEE N N OOO N N
|
||||
//==============================================================================
|
||||
// SSSS H H AAA RRRR PPPP
|
||||
// S H H A A R R P P
|
||||
// SSS HHHHH AAAAA RRRR PPPP
|
||||
// S H H A A R R P
|
||||
// SSSS H H A A R R P
|
||||
//==============================================================================
|
||||
// Denon publish all their IR codes:
|
||||
// https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet
|
||||
// -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls
|
||||
// Having looked at the official Denon Pronto sheet and reverse engineered
|
||||
// the timing values from it, it is obvious that Denon have a range of
|
||||
// different timings and protocols ...the values here work for my AVR-3801 Amp!
|
||||
// MSB first, no start bit, 5 address + 8 command + 2 frame + 1 stop bit - each frame 2 times
|
||||
//
|
||||
#define DENON_ADDRESS_BITS 5
|
||||
#define DENON_COMMAND_BITS 8
|
||||
#define DENON_FRAME_BITS 2 // 00/10 for 1. frame Denon/Sharp, inverted for autorepeat frame
|
||||
|
||||
#define DENON_BITS (DENON_ADDRESS_BITS + DENON_COMMAND_BITS + DENON_FRAME_BITS) // 15 - The number of bits in the command
|
||||
#define DENON_UNIT 260
|
||||
|
||||
#define DENON_BIT_MARK DENON_UNIT // The length of a Bit:Mark
|
||||
#define DENON_ONE_SPACE (7 * DENON_UNIT) // 1820 // The length of a Bit:Space for 1's
|
||||
#define DENON_ZERO_SPACE (3 * DENON_UNIT) // 780 // The length of a Bit:Space for 0's
|
||||
|
||||
#define DENON_AUTO_REPEAT_SPACE 45000 // Every frame is auto repeated with a space period of 45 ms and the command inverted.
|
||||
#define DENON_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
|
||||
|
||||
// for old decoder
|
||||
#define DENON_HEADER_MARK DENON_UNIT // The length of the Header:Mark
|
||||
#define DENON_HEADER_SPACE (3 * DENON_UNIT) // 780 // The length of the Header:Space
|
||||
|
||||
//+=============================================================================
|
||||
void IRsend::sendSharp(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
sendDenon(aAddress, aCommand, aNumberOfRepeats, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only for backwards compatibility
|
||||
*/
|
||||
void IRsend::sendDenonRaw(uint16_t aRawData, uint_fast8_t aNumberOfRepeats) {
|
||||
sendDenon(aRawData >> (DENON_COMMAND_BITS + DENON_FRAME_BITS), aRawData & 0xFF, aNumberOfRepeats);
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendSharp) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(DENON_KHZ); // 38 kHz
|
||||
|
||||
// Shift command and add frame marker
|
||||
uint16_t tCommand = aCommand << DENON_FRAME_BITS; // the lowest bits are 00 for Denon and 10 for Sharp
|
||||
if (aSendSharp) {
|
||||
tCommand |= 0x02;
|
||||
}
|
||||
uint16_t tData = tCommand | ((uint16_t) aAddress << (DENON_COMMAND_BITS + DENON_FRAME_BITS));
|
||||
uint16_t tInvertedData = ((~tCommand) & 0x3FF) | (uint16_t) aAddress << (DENON_COMMAND_BITS + DENON_FRAME_BITS);
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Data
|
||||
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, tData, DENON_BITS,
|
||||
PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
|
||||
// Inverted autorepeat frame
|
||||
delay(DENON_AUTO_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, tInvertedData, DENON_BITS,
|
||||
PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command with a fixed space gap
|
||||
delay( DENON_AUTO_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
bool IRrecv::decodeSharp() {
|
||||
return decodeDenon();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
bool IRrecv::decodeDenon() {
|
||||
|
||||
// we have no start bit, so check for the exact amount of data bits
|
||||
// Check we have the right amount of data (32). The + 2 is for initial gap + stop bit mark
|
||||
if (decodedIRData.rawDataPtr->rawlen != (2 * DENON_BITS) + 2) {
|
||||
IR_DEBUG_PRINT(F("Denon: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 32"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the bits in
|
||||
if (!decodePulseDistanceData(DENON_BITS, 1, DENON_BIT_MARK, DENON_ONE_SPACE, DENON_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Denon: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for stop mark
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[(2 * DENON_BITS) + 1], DENON_HEADER_MARK)) {
|
||||
IR_DEBUG_PRINT(F("Denon: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
uint8_t tFrameBits = decodedIRData.decodedRawData & 0x03;
|
||||
decodedIRData.command = decodedIRData.decodedRawData >> DENON_FRAME_BITS;
|
||||
decodedIRData.address = decodedIRData.command >> DENON_COMMAND_BITS;
|
||||
uint8_t tCommand = decodedIRData.command & 0xFF;
|
||||
decodedIRData.command = tCommand;
|
||||
|
||||
// check for autorepeated inverted command
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < ((DENON_AUTO_REPEAT_SPACE + (DENON_AUTO_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
|
||||
repeatCount++;
|
||||
if (tFrameBits == 0x3 || tFrameBits == 0x1) {
|
||||
// We are in the auto repeated frame with the inverted command
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
// Check parity of consecutive received commands. There is no parity in one data set.
|
||||
uint8_t tLastCommand = lastDecodedCommand;
|
||||
if (tLastCommand != (uint8_t) (~tCommand)) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
|
||||
}
|
||||
// always take non inverted command
|
||||
decodedIRData.command = tLastCommand;
|
||||
}
|
||||
if (repeatCount > 1) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
|
||||
}
|
||||
} else {
|
||||
repeatCount = 0;
|
||||
}
|
||||
|
||||
decodedIRData.numberOfBits = DENON_BITS;
|
||||
if (tFrameBits == 1 || tFrameBits == 2) {
|
||||
decodedIRData.protocol = SHARP;
|
||||
} else {
|
||||
decodedIRData.protocol = DENON;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRrecv::decodeDenonOld(decode_results *aResults) {
|
||||
|
||||
// Check we have the right amount of data
|
||||
if (decodedIRData.rawDataPtr->rawlen != 1 + 2 + (2 * DENON_BITS) + 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check initial Mark+Space match
|
||||
if (!matchMark(aResults->rawbuf[1], DENON_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!matchSpace(aResults->rawbuf[2], DENON_HEADER_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the bits in
|
||||
if (!decodePulseDistanceData(DENON_BITS, 3, DENON_BIT_MARK, DENON_ONE_SPACE, DENON_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
aResults->value = decodedIRData.decodedRawData;
|
||||
aResults->bits = DENON_BITS;
|
||||
aResults->decode_type = DENON;
|
||||
decodedIRData.protocol = DENON;
|
||||
return true;
|
||||
}
|
||||
|
||||
void IRsend::sendDenon(unsigned long data, int nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(DENON_KHZ);
|
||||
#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))
|
||||
Serial.println(
|
||||
"The function sendDenon(data, nbits) is deprecated and may not work as expected! Use sendDenonRaw(data, NumberOfRepeats) or better sendDenon(Address, Command, NumberOfRepeats).");
|
||||
#endif
|
||||
|
||||
// Header
|
||||
mark(DENON_HEADER_MARK);
|
||||
space(DENON_HEADER_SPACE);
|
||||
|
||||
// Data
|
||||
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, data, nbits,
|
||||
PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
void IRsend::sendSharp(unsigned int aAddress, unsigned int aCommand) {
|
||||
sendDenon(aAddress, aCommand, true, 0);
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_DENON_HPP
|
||||
46
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Dish.hpp
Normal file
46
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Dish.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "IRremoteInt.h"
|
||||
|
||||
//==============================================================================
|
||||
// DDDD IIIII SSSS H H
|
||||
// D D I S H H
|
||||
// D D I SSS HHHHH
|
||||
// D D I S H H
|
||||
// DDDD IIIII SSSS H H
|
||||
//==============================================================================
|
||||
|
||||
// Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand )
|
||||
//
|
||||
// The send function needs to be repeated 4 times
|
||||
//
|
||||
// Only send the last for characters of the hex.
|
||||
// I.E. Use 0x1C10 instead of 0x0000000000001C10 as listed in the LIRC file.
|
||||
//
|
||||
// Here is the LIRC file I found that seems to match the remote codes from the
|
||||
// oscilloscope:
|
||||
// DISH NETWORK (echostar 301):
|
||||
// http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx
|
||||
#ifndef _IR_DISH_HPP
|
||||
#define _IR_DISH_HPP
|
||||
|
||||
#define DISH_BITS 16
|
||||
#define DISH_HEADER_MARK 400
|
||||
#define DISH_HEADER_SPACE 6100
|
||||
#define DISH_BIT_MARK 400
|
||||
#define DISH_ONE_SPACE 1700
|
||||
#define DISH_ZERO_SPACE 2800
|
||||
#define DISH_REPEAT_SPACE 6200
|
||||
|
||||
//+=============================================================================
|
||||
void IRsend::sendDISH(unsigned long data, int nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(56);
|
||||
|
||||
mark(DISH_HEADER_MARK);
|
||||
space(DISH_HEADER_SPACE);
|
||||
|
||||
sendPulseDistanceWidthData(DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
|
||||
mark(DISH_HEADER_MARK); //added 26th March 2016, by AnalysIR ( https://www.AnalysIR.com )
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
#endif // _IR_DISH_HPP
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* ir_DistanceProtocol.hpp
|
||||
*
|
||||
* This decoder tries to decode a pulse width or pulse distance protocol.
|
||||
* 1. Analyze all space and mark length
|
||||
* 2. Decide if we have an pulse width or distance protocol
|
||||
* 3. Try to decode with the mark and space data found in step 1
|
||||
* No data and address decoding, only raw data as result.
|
||||
*
|
||||
* Pulse distance data can be sent with the generic function:
|
||||
* void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
|
||||
* unsigned int aZeroSpaceMicros, uint32_t aData, uint8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit = false)
|
||||
* The header must be sent manually with:
|
||||
* IrSender.mark(MarkMicros)
|
||||
* IrSender.space(SpaceMicros);
|
||||
* see also: SendDemo example line 150
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_DISTANCE_HPP
|
||||
#define _IR_DISTANCE_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// accept durations up to 50 * 50 (MICROS_PER_TICK) 2500 microseconds
|
||||
#define DURATION_ARRAY_SIZE 50
|
||||
|
||||
// Switch the decoding according to your needs
|
||||
#define DISTANCE_DO_MSB_DECODING PROTOCOL_IS_LSB_FIRST // this results in the same decodedRawData as e.g. the NEC and Kaseikyo/Panasonic decoder
|
||||
//#define DISTANCE_DO_MSB_DECODING PROTOCOL_IS_MSB_FIRST // this resembles the JVC, Denon
|
||||
|
||||
#if defined(INFO) && !defined(LOCAL_INFO)
|
||||
#define LOCAL_INFO
|
||||
#else
|
||||
#define LOCAL_INFO // This enables info output only for this file
|
||||
#endif
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
//#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#Codings
|
||||
#if defined(DEBUG)
|
||||
void printDurations(uint8_t aArray[], uint8_t aMaxIndex) {
|
||||
for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
|
||||
if (i % 10 == 0) {
|
||||
if (i == 0) {
|
||||
Serial.print(' '); // indentation for the 0
|
||||
} else {
|
||||
Serial.println();
|
||||
}
|
||||
Serial.print(i);
|
||||
Serial.print(F(":"));
|
||||
}
|
||||
Serial.print(F(" | "));
|
||||
Serial.print(aArray[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @return false if more than 2 distinct duration values found
|
||||
*/
|
||||
bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIndex, uint8_t *aLongIndex) {
|
||||
uint8_t tSum = 0;
|
||||
uint16_t tWeightedSum = 0;
|
||||
for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
|
||||
uint8_t tCurrentDurations = aArray[i];
|
||||
if (tCurrentDurations != 0) {
|
||||
// Add it to sum and remove array content
|
||||
tSum += tCurrentDurations;
|
||||
tWeightedSum += (tCurrentDurations * i);
|
||||
aArray[i] = 0;
|
||||
}
|
||||
if ((tCurrentDurations == 0 || i == aMaxIndex) && tSum != 0) {
|
||||
// here we have a sum and a gap after the values
|
||||
uint8_t tAggregateIndex = (tWeightedSum + (tSum / 2)) / tSum; // with rounding
|
||||
aArray[tAggregateIndex] = tSum; // disabling this line increases code size by 2 - unbelievable!
|
||||
// store aggregate for later decoding
|
||||
if (*aShortIndex == 0) {
|
||||
*aShortIndex = tAggregateIndex;
|
||||
} else if (*aLongIndex == 0) {
|
||||
*aLongIndex = tAggregateIndex;
|
||||
} else {
|
||||
// we have 3 bins => this is likely no pulse width or distance protocol. e.g. it can be RC5.
|
||||
return false;
|
||||
}
|
||||
// initialize for next aggregation
|
||||
tSum = 0;
|
||||
tWeightedSum = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to decode a pulse width or pulse distance protocol.
|
||||
* 1. Analyze all space and mark length
|
||||
* 2. Decide if we have an pulse width or distance protocol
|
||||
* 3. Try to decode with the mark and space data found in step 1
|
||||
* No data and address decoding, only raw data as result.
|
||||
*/
|
||||
bool IRrecv::decodeDistance() {
|
||||
uint8_t tDurationArray[DURATION_ARRAY_SIZE];
|
||||
|
||||
/*
|
||||
* Accept only protocols with at least 8 bits
|
||||
*/
|
||||
if (decodedIRData.rawDataPtr->rawlen < (2 * 8) + 4) {
|
||||
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is less than 20"));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint_fast8_t i;
|
||||
|
||||
// Reset duration array
|
||||
memset(tDurationArray, 0, sizeof(tDurationArray));
|
||||
|
||||
uint8_t tMaxDurationIndex = 0;
|
||||
/*
|
||||
* Count number of mark durations. Skip leading start and trailing stop bit.
|
||||
*/
|
||||
for (i = 3; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) {
|
||||
uint8_t tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
|
||||
if (tDurationTicks < sizeof(tDurationArray)) {
|
||||
tDurationArray[tDurationTicks]++;
|
||||
if (tMaxDurationIndex < tDurationTicks) {
|
||||
tMaxDurationIndex = tDurationTicks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Aggregate mark counts to one duration bin
|
||||
*/
|
||||
uint8_t tMarkTicksShort = 0;
|
||||
uint8_t tMarkTicksLong = 0;
|
||||
bool tSuccess = aggregateArrayCounts(tDurationArray, tMaxDurationIndex, &tMarkTicksShort, &tMarkTicksLong);
|
||||
#if defined(DEBUG)
|
||||
Serial.println(F("Mark:"));
|
||||
printDurations(tDurationArray, tMaxDurationIndex);
|
||||
#endif
|
||||
|
||||
if (!tSuccess) {
|
||||
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
IR_DEBUG_PRINTLN(F("Mark aggregation failed, more than 2 distinct mark duration values found"));
|
||||
}
|
||||
|
||||
// Reset duration array
|
||||
memset(tDurationArray, 0, sizeof(tDurationArray));
|
||||
|
||||
/*
|
||||
* Count number of space durations. Skip leading start and trailing stop bit.
|
||||
*/
|
||||
tMaxDurationIndex = 0;
|
||||
for (i = 4; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) {
|
||||
uint8_t tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
|
||||
if (tDurationTicks < sizeof(tDurationArray)) {
|
||||
tDurationArray[tDurationTicks]++;
|
||||
if (tMaxDurationIndex < tDurationTicks) {
|
||||
tMaxDurationIndex = tDurationTicks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Aggregate space counts to one duration bin
|
||||
*/
|
||||
uint8_t tSpaceTicksShort = 0;
|
||||
uint8_t tSpaceTicksLong = 0;
|
||||
tSuccess = aggregateArrayCounts(tDurationArray, tMaxDurationIndex, &tSpaceTicksShort, &tSpaceTicksLong);
|
||||
#if defined(DEBUG)
|
||||
Serial.println(F("Space:"));
|
||||
printDurations(tDurationArray, tMaxDurationIndex);
|
||||
#endif
|
||||
|
||||
if (!tSuccess) {
|
||||
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
IR_DEBUG_PRINTLN(F("Space aggregation failed, more than 2 distinct space duration values found"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip leading start and trailing stop bit.
|
||||
uint16_t tNumberOfBits = (decodedIRData.rawDataPtr->rawlen / 2) - 2;
|
||||
decodedIRData.numberOfBits = tNumberOfBits;
|
||||
|
||||
/*
|
||||
* Print characteristics of this protocol. Durations are in ticks.
|
||||
* Number of bits, start bit, start pause, short mark, long mark, short space, long space
|
||||
*
|
||||
* NEC: 32, 180, 90, 11, 0, 11, 34
|
||||
* Samsung32: 32, 90, 90, 11, 0, 11, 34
|
||||
* LG: 28, 180, 84, 10, 0, 11, 32
|
||||
* JVC: 16, 168, 84, 10, 0, 10, 32
|
||||
* Kaseikyo: 48. 69, 35, 9, 0, 9, 26
|
||||
* Sony: 12|15|20, 48, 12, 12, 24, 12, 0 // the only known pulse width protocol
|
||||
*/
|
||||
IR_DEBUG_PRINT(F("Protocol characteristics for a " STR(MICROS_PER_TICK) " us tick: "));
|
||||
IR_DEBUG_PRINT(decodedIRData.numberOfBits);
|
||||
IR_DEBUG_PRINT(F(", "));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawbuf[1]);
|
||||
IR_DEBUG_PRINT(F(", "));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawbuf[2]);
|
||||
IR_DEBUG_PRINT(F(", "));
|
||||
IR_DEBUG_PRINT(tMarkTicksShort);
|
||||
IR_DEBUG_PRINT(F(", "));
|
||||
IR_DEBUG_PRINT(tMarkTicksLong);
|
||||
IR_DEBUG_PRINT(F(", "));
|
||||
IR_DEBUG_PRINT(tSpaceTicksShort);
|
||||
IR_DEBUG_PRINT(F(", "));
|
||||
IR_DEBUG_PRINTLN(tSpaceTicksLong);
|
||||
|
||||
uint8_t tStartIndex = 3;
|
||||
uint8_t tNumberOfAdditionalLong = (tNumberOfBits - 1) / 32;
|
||||
|
||||
/*
|
||||
* decide, if we have an pulse width or distance protocol
|
||||
*/
|
||||
if (tSpaceTicksLong > 0) {
|
||||
// // check if last bit can be decoded as data or not, in this case take it as a stop bit
|
||||
// if (decodePulseDistanceData(1, decodedIRData.rawDataPtr->rawlen - 3, tMarkTicksShort * MICROS_PER_TICK,
|
||||
// tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
// Serial.print(F("tNumberOfBits++ "));
|
||||
// tNumberOfBits++;
|
||||
// }
|
||||
|
||||
/*
|
||||
* Here short and long space duration found. Decode in 32 bit chunks.
|
||||
*/
|
||||
for (uint_fast8_t i = 0; i <= tNumberOfAdditionalLong; ++i) {
|
||||
uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;
|
||||
if (tNumberOfBitsForOneDecode > 32) {
|
||||
tNumberOfBitsForOneDecode = 32;
|
||||
}
|
||||
if (!decodePulseDistanceData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksShort * MICROS_PER_TICK,
|
||||
tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
} else {
|
||||
|
||||
#if defined(LOCAL_INFO)
|
||||
/*
|
||||
* Print usage :-)
|
||||
*/
|
||||
if (i == 0) {
|
||||
// Print this only once
|
||||
Serial.println();
|
||||
Serial.println(F("PULSE_DISTANCE: Send with:"));
|
||||
Serial.println(F(" IrSender.enableIROut(38);"));
|
||||
Serial.print(F(" IrSender.mark("));
|
||||
Serial.print(decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
|
||||
Serial.println(F(");"));
|
||||
Serial.print(F(" IrSender.space("));
|
||||
Serial.print(decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
|
||||
Serial.println(F(");"));
|
||||
}
|
||||
|
||||
Serial.print(F(" IrSender.sendPulseDistanceWidthData("));
|
||||
Serial.print(tMarkTicksShort * MICROS_PER_TICK); // aOneMarkMicros
|
||||
Serial.print(F(", "));
|
||||
Serial.print(tSpaceTicksLong * MICROS_PER_TICK); // aOneSpaceMicros
|
||||
Serial.print(F(", "));
|
||||
Serial.print(tMarkTicksShort * MICROS_PER_TICK); // aZeroMarkMicros
|
||||
Serial.print(F(", "));
|
||||
Serial.print(tSpaceTicksShort * MICROS_PER_TICK); // aZeroSpaceMicros
|
||||
Serial.print(F(", 0x"));
|
||||
Serial.print(decodedIRData.decodedRawData, HEX); // aData
|
||||
if (tNumberOfBits < 32) {
|
||||
Serial.print(F(", "));
|
||||
Serial.print(tNumberOfBits); // aNumberOfBits
|
||||
} else {
|
||||
Serial.print(F(", 32"));
|
||||
}
|
||||
if (DISTANCE_DO_MSB_DECODING) {
|
||||
Serial.print(F(", true, ")); // aMSBfirst
|
||||
} else {
|
||||
Serial.print(F(", false, ")); // aMSBfirst
|
||||
}
|
||||
if (i == tNumberOfAdditionalLong) {
|
||||
Serial.println(F("true);")); // aSendStopBit - true for last data set
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.println(F("false);"));// aSendStopBit
|
||||
}
|
||||
#endif
|
||||
|
||||
tStartIndex += 64;
|
||||
tNumberOfBits -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
// Store ticks used for decoding in extra
|
||||
decodedIRData.extra = (tSpaceTicksShort << 8) | tSpaceTicksLong;
|
||||
decodedIRData.protocol = PULSE_DISTANCE;
|
||||
} else {
|
||||
if (tMarkTicksLong == 0) {
|
||||
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
IR_DEBUG_PRINTLN(F("Only 1 distinct duration value for each space and mark found"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//#define SUPPORT_PULSE_WIDTH_DECODING
|
||||
#if defined(SUPPORT_PULSE_WIDTH_DECODING) // The only known pulse width protocol is Sony
|
||||
|
||||
// // check if last bit can be decoded as data or not, in this case take it as a stop bit
|
||||
// if (decodePulseWidthData(1, decodedIRData.rawDataPtr->rawlen - 3, tMarkTicksLong * MICROS_PER_TICK,
|
||||
// tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
// tNumberOfBits++;
|
||||
// }
|
||||
// decode without leading start bit. Currently only seen for sony protocol
|
||||
for (uint_fast8_t i = 0; i <= tNumberOfAdditionalLong; ++i) {
|
||||
uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;
|
||||
if (tNumberOfBitsForOneDecode > 32) {
|
||||
tNumberOfBitsForOneDecode = 32;
|
||||
}
|
||||
if (!decodePulseWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksLong * MICROS_PER_TICK,
|
||||
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
IR_DEBUG_PRINT(F("PULSE_WIDTH: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
tStartIndex += 64;
|
||||
tNumberOfBits -= 32;
|
||||
}
|
||||
|
||||
// Store ticks used for decoding in extra
|
||||
decodedIRData.extra = (tMarkTicksShort << 8) | tMarkTicksLong;
|
||||
decodedIRData.protocol = PULSE_WIDTH;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (DISTANCE_DO_MSB_DECODING) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO;
|
||||
} else {
|
||||
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_DISTANCE_HPP
|
||||
242
arduino-libs/arduino-cli/libraries/IRremote/src/ir_JVC.hpp
Normal file
242
arduino-libs/arduino-cli/libraries/IRremote/src/ir_JVC.hpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* ir_JVC.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending JVC IR Protocol in "raw" and standard format with 8 bit address and 8 bit command
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017-2021 Kristian Lauszus, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_JVC_HPP
|
||||
#define _IR_JVC_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// JJJJJ V V CCCC
|
||||
// J V V C
|
||||
// J V V C
|
||||
// J J V V C
|
||||
// J V CCCC
|
||||
//==============================================================================
|
||||
// https://www.sbprojects.net/knowledge/ir/jvc.php
|
||||
// http://www.hifi-remote.com/johnsfine/DecodeIR.html#JVC
|
||||
// IRP: {38k,525}<1,-1|1,-3>(16,-8,(D:8,F:8,1,-45)+)
|
||||
// LSB first, 1 start bit + 8 bit address + 8 bit command + 1 stop bit.
|
||||
// The JVC protocol repeats by skipping the header mark and space -> this leads to a poor repeat detection for JVC protocol.
|
||||
#define JVC_ADDRESS_BITS 8 // 8 bit address
|
||||
#define JVC_COMMAND_BITS 8 // Command
|
||||
|
||||
#define JVC_BITS (JVC_ADDRESS_BITS + JVC_COMMAND_BITS) // 16 - The number of bits in the protocol
|
||||
#define JVC_UNIT 526 // 20 periods of 38 kHz (526.315789)
|
||||
|
||||
#define JVC_HEADER_MARK (16 * JVC_UNIT) // 8400
|
||||
#define JVC_HEADER_SPACE (8 * JVC_UNIT) // 4200
|
||||
|
||||
#define JVC_BIT_MARK JVC_UNIT // The length of a Bit:Mark
|
||||
#define JVC_ONE_SPACE (3 * JVC_UNIT) // 1578 - The length of a Bit:Space for 1's
|
||||
#define JVC_ZERO_SPACE JVC_UNIT // The length of a Bit:Space for 0's
|
||||
|
||||
#define JVC_REPEAT_SPACE (uint16_t)(45 * JVC_UNIT) // 23625 - Commands are repeated with a distance of 23 ms for as long as the key on the remote control is held down.
|
||||
|
||||
//+=============================================================================
|
||||
// JVC does NOT repeat by sending a separate code (like NEC does).
|
||||
// The JVC protocol repeats by skipping the header.
|
||||
//
|
||||
|
||||
void IRsend::sendJVC(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(JVC_KHZ); // 38 kHz
|
||||
|
||||
// Header
|
||||
mark(JVC_HEADER_MARK);
|
||||
space(JVC_HEADER_SPACE);
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Address + command
|
||||
sendPulseDistanceWidthData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE,
|
||||
aAddress | (aCommand << JVC_ADDRESS_BITS), JVC_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command in a fixed raster
|
||||
delay(JVC_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/*
|
||||
* First check for right data length
|
||||
* Next check start bit
|
||||
* Next try the decode
|
||||
*/
|
||||
bool IRrecv::decodeJVC() {
|
||||
|
||||
// Check we have the right amount of data (36 or 34). The +4 is for initial gap, start bit mark and space + stop bit mark. +2 is for repeats
|
||||
if (decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 4) && decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 2)) {
|
||||
IR_DEBUG_PRINT(F("JVC: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 34 or 36"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decodedIRData.rawDataPtr->rawlen == ((2 * JVC_BITS) + 2)) {
|
||||
/*
|
||||
* Check for repeat
|
||||
* Check leading space and first and last mark length
|
||||
*/
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < ((JVC_REPEAT_SPACE + (JVC_REPEAT_SPACE / 4) / MICROS_PER_TICK))
|
||||
&& matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_BIT_MARK)
|
||||
&& matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen - 1], JVC_BIT_MARK)) {
|
||||
/*
|
||||
* We have a repeat here, so do not check for start bit
|
||||
*/
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
decodedIRData.address = lastDecodedAddress;
|
||||
decodedIRData.command = lastDecodedCommand;
|
||||
decodedIRData.protocol = JVC;
|
||||
}
|
||||
} else {
|
||||
|
||||
// Check header "mark" and "space"
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_HEADER_MARK)
|
||||
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], JVC_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("JVC: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(JVC_BITS, 3, JVC_BIT_MARK, JVC_ONE_SPACE, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("JVC: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
uint8_t tCommand = decodedIRData.decodedRawData >> JVC_ADDRESS_BITS; // upper 8 bits of LSB first value
|
||||
uint8_t tAddress = decodedIRData.decodedRawData & 0xFF; // lowest 8 bit of LSB first value
|
||||
|
||||
decodedIRData.command = tCommand;
|
||||
decodedIRData.address = tAddress;
|
||||
decodedIRData.numberOfBits = JVC_BITS;
|
||||
decodedIRData.protocol = JVC;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRrecv::decodeJVCMSB(decode_results *aResults) {
|
||||
unsigned int offset = 1; // Skip first space
|
||||
|
||||
// Check for repeat
|
||||
if ((aResults->rawlen - 1 == 33) && matchMark(aResults->rawbuf[offset], JVC_BIT_MARK)
|
||||
&& matchMark(aResults->rawbuf[aResults->rawlen - 1], JVC_BIT_MARK)) {
|
||||
aResults->bits = 0;
|
||||
aResults->value = 0xFFFFFFFF;
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
|
||||
decodedIRData.protocol = JVC;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initial mark
|
||||
if (!matchMark(aResults->rawbuf[offset], JVC_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// Check we have enough data - +3 for start bit mark and space + stop bit mark
|
||||
if (aResults->rawlen <= (2 * JVC_BITS) + 3) {
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(aResults->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is too small. >= 36 is required."));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initial space
|
||||
if (!matchSpace(aResults->rawbuf[offset], JVC_HEADER_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
if (!decodePulseDistanceData(JVC_BITS, offset, JVC_BIT_MARK, JVC_ONE_SPACE, JVC_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(aResults->rawbuf[offset + (2 * JVC_BITS)], JVC_BIT_MARK)) {
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
aResults->value = decodedIRData.decodedRawData;
|
||||
aResults->bits = JVC_BITS;
|
||||
aResults->decode_type = JVC;
|
||||
decodedIRData.protocol = JVC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* With Send sendJVCMSB() you can send your old 32 bit codes.
|
||||
* To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte.
|
||||
* Or write it as one binary string and reverse/mirror it.
|
||||
* Example:
|
||||
* 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.
|
||||
* 0xCB340102 is binary 11001011001101000000000100000010.
|
||||
* 0x40802CD3 is binary 01000000100000000010110011010011.
|
||||
* If you read the first binary sequence backwards (right to left), you get the second sequence.
|
||||
*/
|
||||
void IRsend::sendJVCMSB(unsigned long data, int nbits, bool repeat) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(JVC_KHZ);
|
||||
|
||||
// Only send the Header if this is NOT a repeat command
|
||||
if (!repeat) {
|
||||
mark(JVC_HEADER_MARK);
|
||||
space(JVC_HEADER_SPACE);
|
||||
}
|
||||
|
||||
// Old version with MSB first Data
|
||||
sendPulseDistanceWidthData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_JVC_HPP
|
||||
336
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Kaseikyo.hpp
Normal file
336
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Kaseikyo.hpp
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* ir_Kaseikyo.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending Kaseikyo/Panasonic IR Protocol in "raw" and standard format with 16 bit address + 8 bit command
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-2021 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_KASEIKYO_HPP
|
||||
#define _IR_KASEIKYO_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC
|
||||
// P P A A NN N A A S O O NN N I C
|
||||
// PPPP AAAAA N N N AAAAA SSS O O N N N I C
|
||||
// P A A N NN A A S O O N NN I C
|
||||
// P A A N N A A SSSS OOO N N IIIII CCCC
|
||||
//==============================================================================
|
||||
// see: http://www.hifi-remote.com/johnsfine/DecodeIR.html#Panasonic and http://www.hifi-remote.com/johnsfine/DecodeIR.html#Kaseikyo
|
||||
// see: http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152
|
||||
// The first two (8-bit) bytes contains the vendor code.
|
||||
// There are multiple interpretations of the next fields:
|
||||
// 1. IRP notation: {37k,432}<1,-1|1,-3>(8,-4,M:8,N:8,X:4,D:4,S:8,F:8,G:8,1,-173)+ {X=M:4:0^M:4:4^N:4:0^N:4:4}
|
||||
// 2. The next two bytes are 4 independent 4-bit fields or Device and Subdevice
|
||||
// The second to last byte is the function and the last byte is xor of the three bytes before it.
|
||||
// 0_______ 1_______ 2______ 3_______ 4_______ 5
|
||||
// 76543210 76543210 76543210 76543210 76543210 76543210
|
||||
// 00000010 00100000 Dev____ Sub Dev Fun____ XOR( B2, B3, B4)
|
||||
// 3. LSB first, start bit + 16 Vendor + 4 Parity(of vendor) + 4 Genre1 + 4 Genre2 + 10 Command + 2 ID + 8 Parity + stop bit
|
||||
//
|
||||
// We reduce it to: start bit + 16 Vendor + 16 Address + 8 Command + 8 Parity + stop bit
|
||||
//
|
||||
#define KASEIKYO_VENDOR_ID_BITS 16
|
||||
#define KASEIKYO_VENDOR_ID_PARITY_BITS 4
|
||||
#define KASEIKYO_ADDRESS_BITS 12
|
||||
#define KASEIKYO_COMMAND_BITS 8
|
||||
#define KASEIKYO_PARITY_BITS 8
|
||||
#define KASEIKYO_BITS (KASEIKYO_VENDOR_ID_BITS + KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS)
|
||||
#define KASEIKYO_UNIT 432 // 16 pulses of 37 kHz (432,432432) - Pronto 0x70 / 0x10
|
||||
|
||||
#define KASEIKYO_HEADER_MARK (8 * KASEIKYO_UNIT) // 3456
|
||||
#define KASEIKYO_HEADER_SPACE (4 * KASEIKYO_UNIT) // 1728
|
||||
|
||||
#define KASEIKYO_BIT_MARK KASEIKYO_UNIT
|
||||
#define KASEIKYO_ONE_SPACE (3 * KASEIKYO_UNIT) // 1296
|
||||
#define KASEIKYO_ZERO_SPACE KASEIKYO_UNIT
|
||||
|
||||
#define KASEIKYO_AVERAGE_DURATION 56000
|
||||
#define KASEIKYO_REPEAT_PERIOD 130000
|
||||
#define KASEIKYO_REPEAT_SPACE (KASEIKYO_REPEAT_PERIOD - KASEIKYO_AVERAGE_DURATION) // 74 ms
|
||||
|
||||
// for old decoder
|
||||
#define KASEIKYO_DATA_BITS 32
|
||||
|
||||
//+=============================================================================
|
||||
/*
|
||||
* Send with LSB first
|
||||
* Address is sub-device << 8 + device
|
||||
*/
|
||||
void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint16_t aVendorCode) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(KASEIKYO_KHZ); // 37 kHz
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Header
|
||||
mark(KASEIKYO_HEADER_MARK);
|
||||
space(KASEIKYO_HEADER_SPACE);
|
||||
|
||||
// Vendor ID
|
||||
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, aVendorCode,
|
||||
KASEIKYO_VENDOR_ID_BITS, PROTOCOL_IS_LSB_FIRST);
|
||||
|
||||
// Vendor Parity
|
||||
uint8_t tVendorParity = aVendorCode ^ (aVendorCode >> 8);
|
||||
tVendorParity = (tVendorParity ^ (tVendorParity >> 4)) & 0xF;
|
||||
|
||||
LongUnion tSendValue;
|
||||
tSendValue.UWord.LowWord = aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS;
|
||||
tSendValue.UByte.LowByte |= tVendorParity; // set low nibble to parity
|
||||
tSendValue.UByte.MidHighByte = aCommand;
|
||||
tSendValue.UByte.HighByte = aCommand ^ tSendValue.UByte.LowByte ^ tSendValue.UByte.MidLowByte; // Parity
|
||||
|
||||
// Send address (device and subdevice) + command + parity + Stop bit
|
||||
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, tSendValue.ULong,
|
||||
KASEIKYO_ADDRESS_BITS + KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS,
|
||||
PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command in a fixed raster
|
||||
delay(KASEIKYO_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub using Kaseikyo with PANASONIC_VENDOR_ID_CODE
|
||||
*/
|
||||
void IRsend::sendPanasonic(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, PANASONIC_VENDOR_ID_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub using Kaseikyo with DENON_VENDOR_ID_CODE
|
||||
*/
|
||||
void IRsend::sendKaseikyo_Denon(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, DENON_VENDOR_ID_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub using Kaseikyo with MITSUBISHI_VENDOR_ID_CODE
|
||||
*/
|
||||
void IRsend::sendKaseikyo_Mitsubishi(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, MITSUBISHI_VENDOR_ID_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub using Kaseikyo with SHARP_VENDOR_ID_CODE
|
||||
*/
|
||||
void IRsend::sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, SHARP_VENDOR_ID_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub using Kaseikyo with JVC_VENDOR_ID_CODE
|
||||
*/
|
||||
void IRsend::sendKaseikyo_JVC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, JVC_VENDOR_ID_CODE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tested with my Panasonic DVD/TV remote
|
||||
*/
|
||||
bool IRrecv::decodeKaseikyo() {
|
||||
|
||||
decode_type_t tProtocol;
|
||||
// Check we have enough data (100)- +4 for initial gap, start bit mark and space + stop bit mark
|
||||
if (decodedIRData.rawDataPtr->rawlen != ((2 * KASEIKYO_BITS) + 4)) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 100"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], KASEIKYO_HEADER_MARK)) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[2], KASEIKYO_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// decode Vendor ID
|
||||
if (!decodePulseDistanceData(KASEIKYO_VENDOR_ID_BITS, 3, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_ZERO_SPACE,
|
||||
PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINTLN(F("Vendor ID decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t tVendorId = decodedIRData.decodedRawData;
|
||||
if (tVendorId == PANASONIC_VENDOR_ID_CODE) {
|
||||
tProtocol = PANASONIC;
|
||||
} else if (tVendorId == SHARP_VENDOR_ID_CODE) {
|
||||
tProtocol = KASEIKYO_SHARP;
|
||||
} else if (tVendorId == DENON_VENDOR_ID_CODE) {
|
||||
tProtocol = KASEIKYO_DENON;
|
||||
} else if (tVendorId == JVC_VENDOR_ID_CODE) {
|
||||
tProtocol = KASEIKYO_JVC;
|
||||
} else if (tVendorId == MITSUBISHI_VENDOR_ID_CODE) {
|
||||
tProtocol = KASEIKYO_MITSUBISHI;
|
||||
} else {
|
||||
tProtocol = KASEIKYO;
|
||||
}
|
||||
|
||||
// Vendor Parity
|
||||
uint8_t tVendorParity = tVendorId ^ (tVendorId >> 8);
|
||||
tVendorParity = (tVendorParity ^ (tVendorParity >> 4)) & 0xF;
|
||||
|
||||
// decode address (device and subdevice) + command + parity
|
||||
if (!decodePulseDistanceData(
|
||||
KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS,
|
||||
3 + (2 * KASEIKYO_VENDOR_ID_BITS), KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE,
|
||||
KASEIKYO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINTLN(F("Address, command + parity decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
LongUnion tValue;
|
||||
tValue.ULong = decodedIRData.decodedRawData;
|
||||
decodedIRData.address = (tValue.UWord.LowWord >> KASEIKYO_VENDOR_ID_PARITY_BITS); // remove vendor parity
|
||||
decodedIRData.command = tValue.UByte.MidHighByte;
|
||||
uint8_t tParity = tValue.UByte.LowByte ^ tValue.UByte.MidLowByte ^ tValue.UByte.MidHighByte;
|
||||
|
||||
if (tVendorParity != (tValue.UByte.LowByte & 0xF)) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINT(F("4 bit VendorID Parity is not correct. expected=0x"));
|
||||
IR_DEBUG_PRINT(tVendorParity, HEX);
|
||||
IR_DEBUG_PRINT(F(" received=0x"));
|
||||
IR_DEBUG_PRINT(decodedIRData.decodedRawData, HEX);
|
||||
IR_DEBUG_PRINT(F(" VendorID=0x"));
|
||||
IR_DEBUG_PRINTLN(tVendorId, HEX);
|
||||
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
}
|
||||
|
||||
if (tProtocol != KASEIKYO) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_EXTRA_INFO;
|
||||
decodedIRData.extra = tVendorId; // Store vendor ID
|
||||
}
|
||||
|
||||
if (tValue.UByte.HighByte != tParity) {
|
||||
IR_DEBUG_PRINT(F("Kaseikyo: "));
|
||||
IR_DEBUG_PRINT(F("8 bit Parity is not correct. expected=0x"));
|
||||
IR_DEBUG_PRINT(tParity, HEX);
|
||||
IR_DEBUG_PRINT(F(" received=0x"));
|
||||
IR_DEBUG_PRINT(decodedIRData.decodedRawData >> KASEIKYO_COMMAND_BITS, HEX);
|
||||
IR_DEBUG_PRINT(F(" address=0x"));
|
||||
IR_DEBUG_PRINT(decodedIRData.address, HEX);
|
||||
IR_DEBUG_PRINT(F(" command=0x"));
|
||||
IR_DEBUG_PRINTLN(decodedIRData.command, HEX);
|
||||
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
|
||||
}
|
||||
|
||||
// check for repeat
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < (KASEIKYO_REPEAT_PERIOD / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
|
||||
}
|
||||
|
||||
decodedIRData.protocol = tProtocol;
|
||||
|
||||
decodedIRData.numberOfBits = KASEIKYO_BITS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Old MSB first decoder
|
||||
*/
|
||||
bool IRrecv::decodePanasonicMSB(decode_results *aResults) {
|
||||
unsigned int offset = 1;
|
||||
|
||||
if (aResults->rawlen < (2 * KASEIKYO_BITS) + 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!matchMark(aResults->rawbuf[offset], KASEIKYO_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
if (!matchMark(aResults->rawbuf[offset], KASEIKYO_HEADER_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// decode address
|
||||
if (!decodePulseDistanceData(KASEIKYO_ADDRESS_BITS + KASEIKYO_DATA_BITS, offset, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE,
|
||||
KASEIKYO_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResults->bits = KASEIKYO_BITS;
|
||||
aResults->value = decodedIRData.decodedRawData;
|
||||
aResults->address = PANASONIC_VENDOR_ID_CODE;
|
||||
aResults->decode_type = PANASONIC;
|
||||
decodedIRData.protocol = PANASONIC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Old version with MSB first data
|
||||
*/
|
||||
void IRsend::sendPanasonic(uint16_t aAddress, uint32_t aData) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(KASEIKYO_KHZ); // 36.7kHz is the correct frequency
|
||||
|
||||
// Header
|
||||
mark(KASEIKYO_HEADER_MARK);
|
||||
space(KASEIKYO_HEADER_SPACE);
|
||||
|
||||
// Old version with MSB first Data Address
|
||||
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, aAddress,
|
||||
KASEIKYO_ADDRESS_BITS, PROTOCOL_IS_MSB_FIRST);
|
||||
|
||||
// Old version with MSB first Data Data + stop bit
|
||||
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, aData,
|
||||
KASEIKYO_DATA_BITS, PROTOCOL_IS_MSB_FIRST);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_KASEIKYO_HPP
|
||||
325
arduino-libs/arduino-cli/libraries/IRremote/src/ir_LG.hpp
Normal file
325
arduino-libs/arduino-cli/libraries/IRremote/src/ir_LG.hpp
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* ir_LG.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending LG IR Protocol in "raw" and standard format with 16 or 8 bit address and 8 bit command
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017-2021 Darryl Smith, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_LG_HPP
|
||||
#define _IR_LG_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// L GGGG
|
||||
// L G
|
||||
// L G GG
|
||||
// L G G
|
||||
// LLLLL GGG
|
||||
//==============================================================================
|
||||
// LG originally added by Darryl Smith (based on the JVC protocol)
|
||||
// see: https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/LGAirConditionerSendDemo
|
||||
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#LGAIR
|
||||
// MSB first, 1 start bit + 8 bit address + 16 bit command + 4 bit checksum + 1 stop bit (28 data bits).
|
||||
// Bit and repeat timing is like NEC
|
||||
// LG2 has different header timing and a shorter bit time
|
||||
/*
|
||||
* LG remote measurements: Type AKB73315611, Ver1.1 from 2011.03.01
|
||||
* Internal crystal: 4 MHz
|
||||
* Header: 8.9 ms mark 4.15 ms space
|
||||
* Data: 500 / 540 and 500 / 1580;
|
||||
* Clock is nor synchronized with gate so you have 19 and sometimes 19 and a spike pulses for mark
|
||||
* Duty: 9 us on 17 us off => around 33 % duty
|
||||
* NO REPEAT: If value like temperature has changed during long press, the last value is send at button release.
|
||||
* If you do a double press, the next value can be sent after around 118 ms. Tested with the fan button.
|
||||
*
|
||||
* The codes of the LG air conditioner are documented in https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/ac_LG.cpp
|
||||
*/
|
||||
#define LG_ADDRESS_BITS 8
|
||||
#define LG_COMMAND_BITS 16
|
||||
#define LG_CHECKSUM_BITS 4
|
||||
#define LG_BITS (LG_ADDRESS_BITS + LG_COMMAND_BITS + LG_CHECKSUM_BITS) // 28
|
||||
|
||||
#define LG_UNIT 500 // 19 periods of 38 kHz
|
||||
|
||||
#define LG_HEADER_MARK (18 * LG_UNIT) // 9000
|
||||
#define LG_HEADER_SPACE 4200 // 84
|
||||
|
||||
#define LG2_HEADER_MARK (6 * LG_UNIT) // 3000
|
||||
#define LG2_HEADER_SPACE (19 * LG_UNIT) // 9500
|
||||
|
||||
#define LG_BIT_MARK LG_UNIT
|
||||
#define LG_ONE_SPACE 1580 // 60 periods of 38 kHz
|
||||
#define LG_ZERO_SPACE 550
|
||||
|
||||
#define LG_REPEAT_HEADER_SPACE (4 * LG_UNIT) // 2250
|
||||
#define LG_AVERAGE_DURATION 58000 // LG_HEADER_MARK + LG_HEADER_SPACE + 32 * 2,5 * LG_UNIT) + LG_UNIT // 2.5 because we assume more zeros than ones
|
||||
#define LG_REPEAT_DURATION (LG_HEADER_MARK + LG_REPEAT_HEADER_SPACE + LG_BIT_MARK)
|
||||
#define LG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
|
||||
#define LG_REPEAT_SPACE (LG_REPEAT_PERIOD - LG_AVERAGE_DURATION) // 52 ms
|
||||
|
||||
//+=============================================================================
|
||||
/*
|
||||
* Send repeat
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
*/
|
||||
void IRsend::sendLGRepeat(bool aUseLG2Protocol) {
|
||||
enableIROut(LG_KHZ); // 38 kHz
|
||||
if (aUseLG2Protocol) {
|
||||
mark(LG2_HEADER_MARK);
|
||||
} else {
|
||||
mark(LG_HEADER_MARK);
|
||||
}
|
||||
space(LG_REPEAT_HEADER_SPACE);
|
||||
mark(LG_BIT_MARK);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
* There is NO delay after the last sent repeat!
|
||||
* @param aUseLG2Protocol if true use LG2 protocol, which has a different header
|
||||
*/
|
||||
void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat, bool aUseLG2Protocol) {
|
||||
uint32_t tRawData = ((uint32_t) aAddress << (LG_COMMAND_BITS + LG_CHECKSUM_BITS)) | ((uint32_t) aCommand << LG_CHECKSUM_BITS);
|
||||
/*
|
||||
* My guess of the 4 bit checksum
|
||||
* Addition of all 4 nibbles of the 16 bit command
|
||||
*/
|
||||
uint8_t tChecksum = 0;
|
||||
uint16_t tTempForChecksum = aCommand;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
tChecksum += tTempForChecksum & 0xF; // add low nibble
|
||||
tTempForChecksum >>= 4; // shift by a nibble
|
||||
}
|
||||
tRawData |= (tChecksum & 0xF);
|
||||
sendLGRaw(tRawData, aNumberOfRepeats, aIsRepeat, aUseLG2Protocol);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here you can put your raw data, even one with "wrong" checksum
|
||||
*/
|
||||
void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aIsRepeat, bool aUseLG2Protocol) {
|
||||
if (aIsRepeat) {
|
||||
sendLGRepeat();
|
||||
return;
|
||||
}
|
||||
// Set IR carrier frequency
|
||||
enableIROut(LG_KHZ);
|
||||
|
||||
// Header
|
||||
if (aUseLG2Protocol) {
|
||||
mark(LG2_HEADER_MARK);
|
||||
space(LG2_HEADER_SPACE);
|
||||
// MSB first
|
||||
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, aRawData, LG_BITS, PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
} else {
|
||||
mark(LG_HEADER_MARK);
|
||||
space(LG_HEADER_SPACE);
|
||||
// MSB first
|
||||
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, aRawData, LG_BITS, PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
}
|
||||
|
||||
for (uint_fast8_t i = 0; i < aNumberOfRepeats; ++i) {
|
||||
// send repeat in a 110 ms raster
|
||||
if (i == 0) {
|
||||
delay(LG_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
} else {
|
||||
delay((LG_REPEAT_PERIOD - LG_REPEAT_DURATION) / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
// send repeat
|
||||
sendLGRepeat(aUseLG2Protocol);
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
// LGs has a repeat like NEC
|
||||
//
|
||||
/*
|
||||
* First check for right data length
|
||||
* Next check start bit
|
||||
* Next try the decode
|
||||
* Last check stop bit
|
||||
*/
|
||||
bool IRrecv::decodeLG() {
|
||||
decode_type_t tProtocol = LG;
|
||||
uint16_t tHeaderSpace = LG_HEADER_SPACE;
|
||||
|
||||
// Check we have the right amount of data (60). The +4 is for initial gap, start bit mark and space + stop bit mark.
|
||||
if (decodedIRData.rawDataPtr->rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 60 or 4"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "mark" this must be done for repeat and data
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG_HEADER_MARK)) {
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) {
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark is wrong"));
|
||||
return false;
|
||||
} else {
|
||||
tProtocol = LG2;
|
||||
tHeaderSpace = LG2_HEADER_SPACE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for repeat - here we have another header space length
|
||||
if (decodedIRData.rawDataPtr->rawlen == 4) {
|
||||
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_REPEAT_HEADER_SPACE)
|
||||
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], LG_BIT_MARK)) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
decodedIRData.address = lastDecodedAddress;
|
||||
decodedIRData.command = lastDecodedCommand;
|
||||
decodedIRData.protocol = lastDecodedProtocol;
|
||||
return true;
|
||||
}
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINT(F("Repeat header space is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check command header space
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], tHeaderSpace)) {
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(LG_BITS, 3, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LG_BITS)], LG_BIT_MARK)) {
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
decodedIRData.command = (decodedIRData.decodedRawData >> LG_CHECKSUM_BITS) & 0xFFFF;
|
||||
decodedIRData.address = decodedIRData.decodedRawData >> (LG_COMMAND_BITS + LG_CHECKSUM_BITS); // first 8 bit
|
||||
|
||||
/*
|
||||
* My guess of the checksum
|
||||
*/
|
||||
uint8_t tChecksum = 0;
|
||||
uint16_t tTempForChecksum = decodedIRData.command;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
tChecksum += tTempForChecksum & 0xF; // add low nibble
|
||||
tTempForChecksum >>= 4; // shift by a nibble
|
||||
}
|
||||
// Checksum check
|
||||
if ((tChecksum & 0xF) != (decodedIRData.decodedRawData & 0xF)) {
|
||||
IR_DEBUG_PRINT(F("LG: "));
|
||||
IR_DEBUG_PRINT(F("4 bit checksum is not correct. expected=0x"));
|
||||
IR_DEBUG_PRINT(tChecksum, HEX);
|
||||
IR_DEBUG_PRINT(F(" received=0x"));
|
||||
IR_DEBUG_PRINT((decodedIRData.decodedRawData & 0xF), HEX);
|
||||
IR_DEBUG_PRINT(F(" data=0x"));
|
||||
IR_DEBUG_PRINTLN(decodedIRData.command, HEX);
|
||||
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
|
||||
}
|
||||
|
||||
decodedIRData.protocol = tProtocol; // LG or LG2
|
||||
decodedIRData.numberOfBits = LG_BITS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRrecv::decodeLGMSB(decode_results *aResults) {
|
||||
unsigned int offset = 1; // Skip first space
|
||||
|
||||
// Check we have enough data (60) - +4 for initial gap, start bit mark and space + stop bit mark
|
||||
if (aResults->rawlen != (2 * LG_BITS) + 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initial mark/space
|
||||
if (!matchMark(aResults->rawbuf[offset], LG_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
if (!matchSpace(aResults->rawbuf[offset], LG_HEADER_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
if (!decodePulseDistanceData(LG_BITS, offset, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
return false;
|
||||
}
|
||||
// Stop bit
|
||||
if (!matchMark(aResults->rawbuf[offset + (2 * LG_BITS)], LG_BIT_MARK)) {
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
aResults->value = decodedIRData.decodedRawData;
|
||||
aResults->bits = LG_BITS;
|
||||
aResults->decode_type = LG;
|
||||
decodedIRData.protocol = LG;
|
||||
return true;
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
void IRsend::sendLG(unsigned long data, int nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(LG_KHZ);
|
||||
#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))
|
||||
Serial.println(
|
||||
"The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).");
|
||||
#endif
|
||||
// Header
|
||||
mark(LG_HEADER_MARK);
|
||||
space(LG_HEADER_SPACE);
|
||||
// mark(LG_BIT_MARK);
|
||||
|
||||
// Data + stop bit
|
||||
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_LG_HPP
|
||||
227
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Lego.hpp
Normal file
227
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Lego.hpp
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* ir_Lego.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending Lego Power Functions IR Protocol
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-2021 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_LEGO_HPP
|
||||
#define _IR_LEGO_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// L EEEEEE EEEE OOOO
|
||||
// L E E O O
|
||||
// L EEEE E EEE O O
|
||||
// L E E E O O
|
||||
// LLLLLL EEEEEE EEEE OOOO
|
||||
//==============================================================================
|
||||
// from LEGO Power Functions RC Manual 26.02.2010 Version 1.20
|
||||
// https://github.com/jurriaan/Arduino-PowerFunctions/raw/master/LEGO_Power_Functions_RC_v120.pdf
|
||||
// https://oberguru.net/elektronik/ir/codes/lego_power_functions_train.lircd.conf
|
||||
//
|
||||
// To ensure correct detection of IR messages six 38 kHz cycles are transmitted as mark.
|
||||
// Low bit consists of 6 cycles of IR and 10 “cycles” of pause,
|
||||
// high bit of 6 cycles IR and 21 “cycles” of pause and start bit of 6 cycles IR and 39 “cycles” of pause.
|
||||
// Low bit range 316 - 526 us
|
||||
// High bit range 526 – 947 us
|
||||
// Start/stop bit range 947 – 1579 us
|
||||
// If tm is the maximum message length (16ms) and Ch is the channel number, then
|
||||
// The delay before transmitting the first message is: (4 – Ch)*tm
|
||||
// The time from start to start for the next 2 messages is: 5*tm
|
||||
// The time from start to start for the following messages is: (6 + 2*Ch)*tm
|
||||
// Supported Devices
|
||||
// LEGO Power Functions IR Receiver 8884
|
||||
// MSB first, 1 start bit + 4 bit channel, 4 bit mode + 4 bit command + 4 bit parity + 1 stop bit.
|
||||
#define LEGO_CHANNEL_BITS 4
|
||||
#define LEGO_MODE_BITS 4
|
||||
#define LEGO_COMMAND_BITS 4
|
||||
#define LEGO_PARITY_BITS 4
|
||||
|
||||
#define LEGO_BITS (LEGO_CHANNEL_BITS + LEGO_MODE_BITS + LEGO_COMMAND_BITS + LEGO_PARITY_BITS)
|
||||
|
||||
#define LEGO_HEADER_MARK 158 // 6 cycles
|
||||
#define LEGO_HEADER_SPACE 1026 // 39 cycles
|
||||
|
||||
#define LEGO_BIT_MARK 158 // 6 cycles
|
||||
#define LEGO_ONE_SPACE 553 // 21 cycles
|
||||
#define LEGO_ZERO_SPACE 263 // 10 cycles
|
||||
|
||||
#define LEGO_AVERAGE_DURATION 11000 // LEGO_HEADER_MARK + LEGO_HEADER_SPACE + 16 * 600 + 158
|
||||
|
||||
#define LEGO_AUTO_REPEAT_PERIOD_MIN 110000 // Every frame is auto repeated 5 times.
|
||||
#define LEGO_AUTO_REPEAT_PERIOD_MAX 230000 // space for channel 3
|
||||
|
||||
/*
|
||||
* Compatibility function for legacy code, this calls the send raw data function
|
||||
*/
|
||||
void IRsend::sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times) {
|
||||
sendLegoPowerFunctions(aRawData, (aRawData >> (LEGO_MODE_BITS + LEGO_COMMAND_BITS + LEGO_PARITY_BITS)) & 0x3, aDoSend5Times);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we process the structured data, and call the send raw data function
|
||||
*/
|
||||
void IRsend::sendLegoPowerFunctions(uint8_t aChannel, uint8_t aCommand, uint8_t aMode, bool aDoSend5Times) {
|
||||
aChannel &= 0x0F; // allow toggle and escape bits too
|
||||
aCommand &= 0x0F;
|
||||
aMode &= 0x0F;
|
||||
uint8_t tParity = 0xF ^ aChannel ^ aMode ^ aCommand;
|
||||
// send 4 bit channel, 4 bit mode, 4 bit command, 4 bit parity
|
||||
uint16_t tRawData = (((aChannel << LEGO_MODE_BITS) | aMode) << (LEGO_COMMAND_BITS + LEGO_PARITY_BITS))
|
||||
| (aCommand << LEGO_PARITY_BITS) | tParity;
|
||||
sendLegoPowerFunctions(tRawData, aChannel, aDoSend5Times);
|
||||
}
|
||||
|
||||
void IRsend::sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times) {
|
||||
enableIROut(38);
|
||||
|
||||
IR_DEBUG_PRINT(F("sendLego aRawData=0x"));
|
||||
IR_DEBUG_PRINTLN(aRawData, HEX);
|
||||
|
||||
aChannel &= 0x03; // we have 4 channels
|
||||
|
||||
uint_fast8_t tNumberOfCommands = 1;
|
||||
if (aDoSend5Times) {
|
||||
tNumberOfCommands = 5;
|
||||
}
|
||||
// required for repeat timing, see http://www.hackvandedam.nl/blog/?page_id=559
|
||||
uint8_t tRepeatPeriod = (110 - (LEGO_AVERAGE_DURATION / MICROS_IN_ONE_MILLI)) + (aChannel * 40); // from 100 to 220
|
||||
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Header
|
||||
mark(LEGO_HEADER_MARK);
|
||||
space(LEGO_HEADER_SPACE);
|
||||
|
||||
sendPulseDistanceWidthData(LEGO_BIT_MARK, LEGO_ONE_SPACE, LEGO_BIT_MARK, LEGO_ZERO_SPACE, aRawData, LEGO_BITS,
|
||||
PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command with a fixed space gap
|
||||
delay(tRepeatPeriod);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/*
|
||||
* Mode is stored in the upper nibble of command
|
||||
*/
|
||||
bool IRrecv::decodeLegoPowerFunctions() {
|
||||
|
||||
// Check header "mark"
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LEGO_HEADER_MARK)) {
|
||||
// no debug output, since this check is mainly to determine the received protocol
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check we have enough data - +4 for initial gap, start bit mark and space + stop bit mark
|
||||
if (decodedIRData.rawDataPtr->rawlen != (2 * LEGO_BITS) + 4) {
|
||||
IR_DEBUG_PRINT(F("LEGO: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 36"));
|
||||
return false;
|
||||
}
|
||||
// Check header "space"
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LEGO_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("LEGO: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(LEGO_BITS, 3, LEGO_BIT_MARK, LEGO_ONE_SPACE, LEGO_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("LEGO: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LEGO_BITS)], LEGO_BIT_MARK)) {
|
||||
IR_DEBUG_PRINT(F("LEGO: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
uint16_t tDecodedValue = decodedIRData.decodedRawData;
|
||||
uint8_t tToggleEscapeChannel = tDecodedValue >> (LEGO_MODE_BITS + LEGO_COMMAND_BITS + LEGO_PARITY_BITS);
|
||||
uint8_t tMode = (tDecodedValue >> (LEGO_COMMAND_BITS + LEGO_PARITY_BITS)) & 0xF;
|
||||
uint8_t tData = (tDecodedValue >> LEGO_PARITY_BITS) & 0xF; // lego calls this field "data"
|
||||
uint8_t tParityReceived = tDecodedValue & 0xF;
|
||||
|
||||
// This is parity as defined in the specifications
|
||||
// But in some scans I saw 0x9 ^ .. as parity formula
|
||||
uint8_t tParityComputed = 0xF ^ tToggleEscapeChannel ^ tMode ^ tData;
|
||||
|
||||
// parity check
|
||||
if (tParityReceived != tParityComputed) {
|
||||
IR_DEBUG_PRINT(F("LEGO: "));
|
||||
IR_DEBUG_PRINT(F("Parity is not correct. expected=0x"));
|
||||
IR_DEBUG_PRINT(tParityComputed, HEX);
|
||||
IR_DEBUG_PRINT(F(" received=0x"));
|
||||
IR_DEBUG_PRINT(tParityReceived, HEX);
|
||||
IR_DEBUG_PRINT(F(", raw=0x"));
|
||||
IR_DEBUG_PRINT(tDecodedValue, HEX);
|
||||
IR_DEBUG_PRINT(F(", 3 nibbles are 0x"));
|
||||
IR_DEBUG_PRINT(tToggleEscapeChannel, HEX);
|
||||
IR_DEBUG_PRINT(F(", 0x"));
|
||||
IR_DEBUG_PRINT(tMode, HEX);
|
||||
IR_DEBUG_PRINT(F(", 0x"));
|
||||
IR_DEBUG_PRINTLN(tData, HEX);
|
||||
// might not be an error, so just continue
|
||||
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for autorepeat (should happen 4 times for one press)
|
||||
*/
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT;
|
||||
}
|
||||
decodedIRData.address = tToggleEscapeChannel;
|
||||
decodedIRData.command = tData | tMode << LEGO_COMMAND_BITS;
|
||||
decodedIRData.protocol = LEGO_PF;
|
||||
decodedIRData.numberOfBits = LEGO_BITS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_LEGO_HPP
|
||||
179
arduino-libs/arduino-cli/libraries/IRremote/src/ir_MagiQuest.hpp
Normal file
179
arduino-libs/arduino-cli/libraries/IRremote/src/ir_MagiQuest.hpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* ir_MagiQuest.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending MagiQuest Protocol
|
||||
* Based off the Magiquest fork of Arduino-IRremote by mpflaga https://github.com/mpflaga/Arduino-IRremote/
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017-2022 E. Stuart Hicks <ehicks@binarymagi.com>, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_MAGIQUEST_HPP
|
||||
#define _IR_MAGIQUEST_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
//
|
||||
//==============================================================================
|
||||
//
|
||||
// M A G I Q U E S T
|
||||
//
|
||||
//==============================================================================
|
||||
// MSB first, 8 Start bits (zero), 32 wand id bits, 16 magnitude bits, one stop bit
|
||||
// Not all start bits must be received, since protocol is MSB first and so the LSB ends up always at the right position.
|
||||
|
||||
#if !defined (DOXYGEN)
|
||||
// MagiQuest packet is both Wand ID and magnitude of swish and flick
|
||||
union magiquest_t {
|
||||
uint64_t llword;
|
||||
struct {
|
||||
uint16_t magnitude;
|
||||
uint32_t wand_id;
|
||||
uint8_t StartBits; // first 8 MSB start bits are zero.
|
||||
uint8_t HighByte; // just to pad the struct out to 64 bits so we can union with llword
|
||||
} cmd;
|
||||
};
|
||||
#endif // !defined (DOXYGEN)
|
||||
|
||||
#define MAGIQUEST_MAGNITUDE_BITS 16 // magiquest_t.cmd.magnitude
|
||||
#define MAGIQUEST_WAND_ID_BITS 32 // magiquest_t.cmd.wand_id
|
||||
#define MAGIQUEST_START_BITS 8 // magiquest_t.cmd.StartBits
|
||||
|
||||
#define MAGIQUEST_PERIOD 1150 // Time for a full MagiQuest "bit" (1100 - 1200 usec)
|
||||
|
||||
#define MAGIQUEST_BITS (MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_WAND_ID_BITS) // 48 Size of the command without the start bits
|
||||
// The maximum size of a packet is the sum of all 3 expected fields * 2
|
||||
#define MAGIQUEST_PACKET_SIZE (MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_WAND_ID_BITS + MAGIQUEST_START_BITS) // 56
|
||||
|
||||
/*
|
||||
* 0 = 25% mark & 75% space across 1 period
|
||||
* 1150 * 0.25 = 288 usec mark
|
||||
* 1150 - 288 = 862 usec space
|
||||
* 1 = 50% mark & 50% space across 1 period
|
||||
* 1150 * 0.5 = 575 usec mark
|
||||
* 1150 - 575 = 575 usec space
|
||||
*/
|
||||
#define MAGIQUEST_UNIT (MAGIQUEST_PERIOD / 4)
|
||||
|
||||
#define MAGIQUEST_ONE_MARK (2 * MAGIQUEST_UNIT) // 576
|
||||
#define MAGIQUEST_ONE_SPACE (2 * MAGIQUEST_UNIT) // 576
|
||||
#define MAGIQUEST_ZERO_MARK MAGIQUEST_UNIT
|
||||
#define MAGIQUEST_ZERO_SPACE (3 * MAGIQUEST_UNIT) // 864
|
||||
|
||||
//+=============================================================================
|
||||
//
|
||||
void IRsend::sendMagiQuest(uint32_t wand_id, uint16_t magnitude) {
|
||||
|
||||
// Set IR carrier frequency
|
||||
enableIROut(38);
|
||||
|
||||
// 8 start bits
|
||||
sendPulseDistanceWidthData(
|
||||
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, 0, 8, PROTOCOL_IS_MSB_FIRST);
|
||||
|
||||
// Data
|
||||
sendPulseDistanceWidthData(
|
||||
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, wand_id, MAGIQUEST_WAND_ID_BITS,
|
||||
PROTOCOL_IS_MSB_FIRST);
|
||||
sendPulseDistanceWidthData(
|
||||
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, magnitude, MAGIQUEST_MAGNITUDE_BITS,
|
||||
PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
//
|
||||
/*
|
||||
* decodes a 56 bit result, which is not really compatible with standard decoder layout
|
||||
*/
|
||||
bool IRrecv::decodeMagiQuest() {
|
||||
magiquest_t data; // Somewhere to build our code
|
||||
unsigned int tOffset = 1; // Skip the gap between packets
|
||||
|
||||
unsigned int tMark;
|
||||
unsigned int tSpace;
|
||||
|
||||
#if defined(DEBUG)
|
||||
char bitstring[(MAGIQUEST_PACKET_SIZE + 1)];
|
||||
bitstring[MAGIQUEST_PACKET_SIZE] = '\0';
|
||||
#endif
|
||||
|
||||
// Check we have the right amount of data, magnitude and ID bits and at least 2 start bits + 1 stop bit
|
||||
if (decodedIRData.rawDataPtr->rawlen < (2 * (MAGIQUEST_BITS + 3))
|
||||
|| decodedIRData.rawDataPtr->rawlen > (2 * (MAGIQUEST_PACKET_SIZE + 1))) {
|
||||
IR_DEBUG_PRINT(F("MagiQuest: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not between 102 and 114"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the bits in
|
||||
data.llword = 0;
|
||||
while (tOffset < (unsigned int) (decodedIRData.rawDataPtr->rawlen - 1)) {
|
||||
// get one mark and space pair
|
||||
tMark = decodedIRData.rawDataPtr->rawbuf[tOffset++];
|
||||
tSpace = decodedIRData.rawDataPtr->rawbuf[tOffset++];
|
||||
|
||||
IR_TRACE_PRINT(F("MagiQuest: mark="));
|
||||
IR_TRACE_PRINT(tMark * MICROS_PER_TICK);
|
||||
IR_TRACE_PRINT(F(" space="));
|
||||
IR_TRACE_PRINTLN(tSpace * MICROS_PER_TICK);
|
||||
|
||||
if (matchMark(tSpace + tMark, MAGIQUEST_PERIOD)) {
|
||||
if (tSpace > tMark) {
|
||||
// It's a 0
|
||||
data.llword <<= 1;
|
||||
#if defined(DEBUG)
|
||||
bitstring[(tOffset / 2) - 1] = '0';
|
||||
#endif
|
||||
} else {
|
||||
// It's a 1
|
||||
data.llword = (data.llword << 1) | 1;
|
||||
#if defined(DEBUG)
|
||||
bitstring[(tOffset / 2) - 1] = '1';
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
IR_DEBUG_PRINTLN(F("Mark and space does not match the constant MagiQuest period"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IR_DEBUG_PRINTLN(bitstring);
|
||||
|
||||
// Success
|
||||
decodedIRData.protocol = MAGIQUEST;
|
||||
decodedIRData.numberOfBits = tOffset / 2;
|
||||
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
decodedIRData.extra = data.cmd.magnitude;
|
||||
decodedIRData.decodedRawData = data.cmd.wand_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // _IR_MAGIQUEST_HPP
|
||||
380
arduino-libs/arduino-cli/libraries/IRremote/src/ir_NEC.hpp
Normal file
380
arduino-libs/arduino-cli/libraries/IRremote/src/ir_NEC.hpp
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* ir_NEC.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending NEC IR Protocol in "raw" and standard format with 16 or 8 bit address and 8 bit command
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-2021 Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_NEC_HPP
|
||||
#define _IR_NEC_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// N N EEEEE CCCC
|
||||
// NN N E C
|
||||
// N N N EEE C
|
||||
// N NN E C
|
||||
// N N EEEEE CCCC
|
||||
//==============================================================================
|
||||
// see: https://www.sbprojects.net/knowledge/ir/nec.php
|
||||
// for Apple see https://en.wikipedia.org/wiki/Apple_Remote
|
||||
// ONKYO like NEC but 16 independent command bits
|
||||
// LSB first, 1 start bit + 16 bit address (or 8 bit address and 8 bit inverted address) + 8 bit command + 8 bit inverted command + 1 stop bit.
|
||||
//
|
||||
#define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
|
||||
#define NEC_COMMAND_BITS 16 // Command and inverted command
|
||||
|
||||
#define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
|
||||
#define NEC_UNIT 560 // 21.28 periods of 38 kHz, 11.2 ticks TICKS_LOW = 8.358 TICKS_HIGH = 15.0
|
||||
|
||||
#define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000 / 180
|
||||
#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500 / 90
|
||||
|
||||
#define NEC_BIT_MARK NEC_UNIT
|
||||
#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690 / 33.8 TICKS_LOW = 25.07 TICKS_HIGH = 45.0
|
||||
#define NEC_ZERO_SPACE NEC_UNIT
|
||||
|
||||
#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250
|
||||
|
||||
#define NEC_AVERAGE_DURATION 62000 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2,5 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
|
||||
#define NEC_REPEAT_DURATION (NEC_HEADER_MARK + NEC_REPEAT_HEADER_SPACE + NEC_BIT_MARK) // 12 ms
|
||||
#define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
|
||||
#define NEC_REPEAT_SPACE (NEC_REPEAT_PERIOD - NEC_AVERAGE_DURATION) // 48 ms
|
||||
|
||||
#define APPLE_ADDRESS 0x87EE
|
||||
//+=============================================================================
|
||||
/*
|
||||
* Send repeat
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
*/
|
||||
void IRsend::sendNECRepeat() {
|
||||
enableIROut(NEC_KHZ); // 38 kHz
|
||||
mark(NEC_HEADER_MARK);
|
||||
space(NEC_REPEAT_HEADER_SPACE);
|
||||
mark(NEC_BIT_MARK);
|
||||
IrReceiver.restartAfterSend();
|
||||
// ledOff(); // Always end with the LED off
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
* There is NO delay after the last sent repeat!
|
||||
* https://www.sbprojects.net/knowledge/ir/nec.php
|
||||
* @param aIsRepeat if true, send only one repeat frame without leading and trailing space
|
||||
*/
|
||||
void IRsend::sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
|
||||
|
||||
LongUnion tRawData;
|
||||
|
||||
// Address 16 bit LSB first
|
||||
if ((aAddress & 0xFF00) == 0) {
|
||||
// assume 8 bit address -> send 8 address bits and then 8 inverted address bits LSB first
|
||||
tRawData.UByte.LowByte = aAddress;
|
||||
tRawData.UByte.MidLowByte = ~tRawData.UByte.LowByte;
|
||||
} else {
|
||||
tRawData.UWord.LowWord = aAddress;
|
||||
}
|
||||
|
||||
// send 8 command bits and then 8 inverted command bits LSB first
|
||||
tRawData.UByte.MidHighByte = aCommand;
|
||||
tRawData.UByte.HighByte = ~aCommand;
|
||||
|
||||
sendNECRaw(tRawData.ULong, aNumberOfRepeats, aIsRepeat);
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
* There is NO delay after the last sent repeat!
|
||||
* @param aIsRepeat if true, send only one repeat frame without leading and trailing space
|
||||
*/
|
||||
void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
|
||||
|
||||
LongUnion tRawData;
|
||||
|
||||
// Address 16 bit LSB first
|
||||
tRawData.UWord.LowWord = aAddress;
|
||||
// Command 16 bit LSB first
|
||||
tRawData.UWord.HighWord = aCommand;
|
||||
|
||||
sendNECRaw(tRawData.ULong, aNumberOfRepeats, aIsRepeat);
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
* There is NO delay after the last sent repeat!
|
||||
* https://en.wikipedia.org/wiki/Apple_Remote
|
||||
* https://gist.github.com/darconeous/4437f79a34e3b6441628
|
||||
* @param aAddress is the DeviceId*
|
||||
* @param aIsRepeat if true, send only one repeat frame without leading and trailing space
|
||||
*/
|
||||
void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
|
||||
|
||||
LongUnion tRawData;
|
||||
|
||||
// Address 16 bit LSB first
|
||||
tRawData.UWord.LowWord = APPLE_ADDRESS;
|
||||
|
||||
// send Apple code and then 8 command bits LSB first
|
||||
tRawData.UByte.MidHighByte = aCommand;
|
||||
tRawData.UByte.HighByte = aDeviceId; // e.g. 0xD7
|
||||
|
||||
sendNECRaw(tRawData.ULong, aNumberOfRepeats, aIsRepeat);
|
||||
}
|
||||
|
||||
void IRsend::sendNECRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
|
||||
if (aIsRepeat) {
|
||||
sendNECRepeat();
|
||||
return;
|
||||
}
|
||||
// Set IR carrier frequency
|
||||
enableIROut(NEC_KHZ);
|
||||
|
||||
// Header
|
||||
mark(NEC_HEADER_MARK);
|
||||
space(NEC_HEADER_SPACE);
|
||||
|
||||
// LSB first + stop bit
|
||||
sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, aRawData, NEC_BITS, PROTOCOL_IS_LSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
|
||||
for (uint_fast8_t i = 0; i < aNumberOfRepeats; ++i) {
|
||||
// send repeat in a 110 ms raster
|
||||
if (i == 0) {
|
||||
delay(NEC_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
} else {
|
||||
delay((NEC_REPEAT_PERIOD - NEC_REPEAT_DURATION) / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
// send repeat
|
||||
sendNECRepeat();
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
// NECs have a repeat only 4 items long
|
||||
//
|
||||
/*
|
||||
* First check for right data length
|
||||
* Next check start bit
|
||||
* Next try the decode
|
||||
* Last check stop bit
|
||||
*
|
||||
* Decodes also Apple
|
||||
*/
|
||||
bool IRrecv::decodeNEC() {
|
||||
|
||||
// Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark.
|
||||
if (decodedIRData.rawDataPtr->rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
|
||||
IR_DEBUG_PRINT(F("NEC: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 68 or 4"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "mark" this must be done for repeat and data
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], NEC_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for repeat - here we have another header space length
|
||||
if (decodedIRData.rawDataPtr->rawlen == 4) {
|
||||
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_REPEAT_HEADER_SPACE)
|
||||
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], NEC_BIT_MARK)) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
decodedIRData.address = lastDecodedAddress;
|
||||
decodedIRData.command = lastDecodedCommand;
|
||||
decodedIRData.protocol = lastDecodedProtocol;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check command header space
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("NEC: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(NEC_BITS, 3, NEC_BIT_MARK, NEC_ONE_SPACE, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("NEC: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * NEC_BITS)], NEC_BIT_MARK)) {
|
||||
IR_DEBUG_PRINT(F("NEC: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
LongUnion tValue;
|
||||
tValue.ULong = decodedIRData.decodedRawData;
|
||||
decodedIRData.command = tValue.UByte.MidHighByte; // 8 bit
|
||||
// Address
|
||||
if (tValue.UWord.LowWord == APPLE_ADDRESS) {
|
||||
/*
|
||||
* Apple
|
||||
*/
|
||||
decodedIRData.protocol = APPLE;
|
||||
decodedIRData.address = tValue.UByte.HighByte;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* NEC LSB first, so first sent bit is also LSB of decodedIRData.decodedRawData
|
||||
*/
|
||||
if (tValue.UByte.LowByte == (uint8_t) (~tValue.UByte.MidLowByte)) {
|
||||
// standard 8 bit address NEC protocol
|
||||
decodedIRData.address = tValue.UByte.LowByte; // first 8 bit
|
||||
} else {
|
||||
// extended NEC protocol
|
||||
decodedIRData.address = tValue.UWord.LowWord; // first 16 bit
|
||||
}
|
||||
// Check for command if it is 8 bit NEC or 16 bit ONKYO
|
||||
if (tValue.UByte.MidHighByte == (uint8_t) (~tValue.UByte.HighByte)) {
|
||||
decodedIRData.protocol = NEC;
|
||||
} else {
|
||||
decodedIRData.protocol = ONKYO;
|
||||
decodedIRData.command = tValue.UWord.HighWord; // 16 bit command
|
||||
|
||||
/*
|
||||
* Old NEC plausibility check below, now it is just ONKYO :-)
|
||||
*/
|
||||
// IR_DEBUG_PRINT(F("NEC: "));
|
||||
// IR_DEBUG_PRINT(F("Command=0x"));
|
||||
// IR_DEBUG_PRINT(tValue.UByte.MidHighByte, HEX);
|
||||
// IR_DEBUG_PRINT(F(" is not inverted value of 0x"));
|
||||
// IR_DEBUG_PRINTLN(tValue.UByte.HighByte, HEX);
|
||||
// decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
}
|
||||
}
|
||||
decodedIRData.numberOfBits = NEC_BITS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRrecv::decodeNECMSB(decode_results *aResults) {
|
||||
unsigned int offset = 1; // Index in to results; Skip first space.
|
||||
|
||||
// Check header "mark"
|
||||
if (!matchMark(aResults->rawbuf[offset], NEC_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// Check for repeat
|
||||
if ((aResults->rawlen == 4) && matchSpace(aResults->rawbuf[offset], NEC_REPEAT_HEADER_SPACE)
|
||||
&& matchMark(aResults->rawbuf[offset + 1], NEC_BIT_MARK)) {
|
||||
aResults->bits = 0;
|
||||
aResults->value = 0xFFFFFFFF;
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
|
||||
decodedIRData.protocol = NEC;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check we have the right amount of data (32). +4 for initial gap, start bit mark and space + stop bit mark
|
||||
if (aResults->rawlen != (2 * NEC_BITS) + 4) {
|
||||
IR_DEBUG_PRINT(F("NEC MSB: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(aResults->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 68"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "space"
|
||||
if (!matchSpace(aResults->rawbuf[offset], NEC_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("NEC MSB: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
if (!decodePulseDistanceData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, NEC_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("NEC MSB: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(aResults->rawbuf[offset + (2 * NEC_BITS)], NEC_BIT_MARK)) {
|
||||
IR_DEBUG_PRINT(F("NEC MSB: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
aResults->value = decodedIRData.decodedRawData;
|
||||
aResults->bits = NEC_BITS;
|
||||
aResults->decode_type = NEC;
|
||||
decodedIRData.protocol = NEC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* With Send sendNECMSB() you can send your old 32 bit codes.
|
||||
* To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte.
|
||||
* Or write it as one binary string and reverse/mirror it.
|
||||
* Example:
|
||||
* 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.
|
||||
* 0xCB340102 is binary 11001011001101000000000100000010.
|
||||
* 0x40802CD3 is binary 01000000100000000010110011010011.
|
||||
* If you read the first binary sequence backwards (right to left), you get the second sequence.
|
||||
*/
|
||||
void IRsend::sendNECMSB(uint32_t data, uint8_t nbits, bool repeat) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(NEC_KHZ);
|
||||
|
||||
if (data == 0xFFFFFFFF || repeat) {
|
||||
sendNECRepeat();
|
||||
return;
|
||||
}
|
||||
|
||||
// Header
|
||||
mark(NEC_HEADER_MARK);
|
||||
space(NEC_HEADER_SPACE);
|
||||
|
||||
// Old version with MSB first Data + stop bit
|
||||
sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_NEC_HPP
|
||||
335
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Pronto.hpp
Normal file
335
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Pronto.hpp
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* @file ir_Pronto.hpp
|
||||
* @brief In this file, the functions IRrecv::compensateAndPrintPronto and IRsend::sendPronto are defined.
|
||||
*
|
||||
* See http://www.harctoolbox.org/Glossary.html#ProntoSemantics
|
||||
* Pronto database http://www.remotecentral.com/search.htm
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Bengt Martensson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_PRONTO_HPP
|
||||
#define _IR_PRONTO_HPP
|
||||
|
||||
// The first number, here 0000, denotes the type of the signal. 0000 denotes a raw IR signal with modulation,
|
||||
// The second number, here 006C, denotes a frequency code
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT"
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! @cond
|
||||
// DO NOT EXPORT from this file
|
||||
static const uint16_t learnedToken = 0x0000U;
|
||||
static const uint16_t learnedNonModulatedToken = 0x0100U;
|
||||
static const unsigned int bitsInHexadecimal = 4U;
|
||||
static const unsigned int digitsInProntoNumber = 4U;
|
||||
static const unsigned int numbersInPreamble = 4U;
|
||||
static const unsigned int hexMask = 0xFU;
|
||||
static const uint32_t referenceFrequency = 4145146UL;
|
||||
static const uint16_t fallbackFrequency = 64767U; // To use with frequency = 0;
|
||||
static const uint32_t microsecondsInSeconds = 1000000UL;
|
||||
static const uint16_t PRONTO_DEFAULT_GAP = 45000;
|
||||
//! @endcond
|
||||
|
||||
static unsigned int toFrequencyKHz(uint16_t code) {
|
||||
return ((referenceFrequency / code) + 500) / 1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the string given as Pronto Hex, and send it a number of times given as argument.
|
||||
*/
|
||||
void IRsend::sendPronto(const uint16_t *data, unsigned int length, uint_fast8_t aNumberOfRepeats) {
|
||||
unsigned int timebase = (microsecondsInSeconds * data[1] + referenceFrequency / 2) / referenceFrequency;
|
||||
unsigned int khz;
|
||||
switch (data[0]) {
|
||||
case learnedToken: // normal, "learned"
|
||||
khz = toFrequencyKHz(data[1]);
|
||||
break;
|
||||
case learnedNonModulatedToken: // non-demodulated, "learned"
|
||||
khz = 0U;
|
||||
break;
|
||||
default:
|
||||
return; // There are other types, but they are not handled yet.
|
||||
}
|
||||
unsigned int intros = 2 * data[2];
|
||||
unsigned int repeats = 2 * data[3];
|
||||
IR_DEBUG_PRINT(F("sendPronto intros="));
|
||||
IR_DEBUG_PRINT(intros);
|
||||
IR_DEBUG_PRINT(F(" repeats="));
|
||||
IR_DEBUG_PRINTLN(repeats);
|
||||
if (numbersInPreamble + intros + repeats != length) { // inconsistent sizes
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a new microseconds timing array for sendRaw.
|
||||
* If recorded by IRremote, intro contains the whole IR data and repeat is empty
|
||||
*/
|
||||
uint16_t durations[intros + repeats];
|
||||
for (unsigned int i = 0; i < intros + repeats; i++) {
|
||||
uint32_t duration = ((uint32_t) data[i + numbersInPreamble]) * timebase;
|
||||
durations[i] = (unsigned int) ((duration <= UINT16_MAX) ? duration : UINT16_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the intro. intros is even.
|
||||
* Do not send the trailing space here, send it if repeats are requested
|
||||
*/
|
||||
if (intros >= 2) {
|
||||
sendRaw(durations, intros - 1, khz);
|
||||
}
|
||||
|
||||
if (repeats == 0 || aNumberOfRepeats == 0) {
|
||||
// only send intro once
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now send the trailing space/gap of the intro and all the repeats
|
||||
*/
|
||||
if (intros >= 2) {
|
||||
delay(durations[intros - 1] / MICROS_IN_ONE_MILLI); // equivalent to space(durations[intros - 1]); but allow bigger values for the gap
|
||||
}
|
||||
for (unsigned int i = 0; i < aNumberOfRepeats; i++) {
|
||||
sendRaw(durations + intros, repeats - 1, khz);
|
||||
if ((i + 1) < aNumberOfRepeats) { // skip last trailing space/gap, see above
|
||||
delay(durations[intros + repeats - 1] / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the string given as Pronto Hex, and send it a number of times given
|
||||
* as the second argument. Thereby the division of the Pronto Hex into
|
||||
* an intro-sequence and a repeat sequence is taken into account:
|
||||
* First the intro sequence is sent, then the repeat sequence is sent times-1 times.
|
||||
* However, if the intro sequence is empty, the repeat sequence is sent times times.
|
||||
* <a href="http://www.harctoolbox.org/Glossary.html#ProntoSemantics">Reference</a>.
|
||||
*
|
||||
* Note: Using this function is very wasteful for the memory consumption on
|
||||
* a small board.
|
||||
* Normally it is a much better idea to use a tool like e.g. IrScrutinizer
|
||||
* to transform Pronto type signals offline
|
||||
* to a more memory efficient format.
|
||||
*
|
||||
* @param str C type string (null terminated) containing a Pronto Hex representation.
|
||||
* @param aNumberOfRepeats Number of times to send the signal.
|
||||
*/
|
||||
void IRsend::sendPronto(const char *str, uint_fast8_t aNumberOfRepeats) {
|
||||
size_t len = strlen(str) / (digitsInProntoNumber + 1) + 1;
|
||||
uint16_t data[len];
|
||||
const char *p = str;
|
||||
char *endptr[1];
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
long x = strtol(p, endptr, 16);
|
||||
if (x == 0 && i >= numbersInPreamble) {
|
||||
// Alignment error?, bail immediately (often right result).
|
||||
len = i;
|
||||
break;
|
||||
}
|
||||
data[i] = static_cast<uint16_t>(x); // If input is conforming, there can be no overflow!
|
||||
p = *endptr;
|
||||
}
|
||||
sendPronto(data, len, aNumberOfRepeats);
|
||||
}
|
||||
|
||||
#if defined(__AVR__)
|
||||
/**
|
||||
* Version of sendPronto that reads from PROGMEM, saving RAM memory.
|
||||
* @param str pronto C type string (null terminated) containing a Pronto Hex representation.
|
||||
* @param aNumberOfRepeats Number of times to send the signal.
|
||||
*/
|
||||
//far pointer (? for ATMega2560 etc.)
|
||||
void IRsend::sendPronto_PF(uint_farptr_t str, uint_fast8_t aNumberOfRepeats) {
|
||||
size_t len = strlen_PF(str);
|
||||
char work[len + 1];
|
||||
strncpy_PF(work, str, len);
|
||||
sendPronto(work, aNumberOfRepeats);
|
||||
}
|
||||
|
||||
//standard pointer
|
||||
void IRsend::sendPronto_P(const char *str, uint_fast8_t aNumberOfRepeats) {
|
||||
size_t len = strlen_P(str);
|
||||
char work[len + 1];
|
||||
strncpy_P(work, str, len);
|
||||
sendPronto(work, aNumberOfRepeats);
|
||||
}
|
||||
#endif
|
||||
|
||||
void IRsend::sendPronto(const __FlashStringHelper *str, uint_fast8_t aNumberOfRepeats) {
|
||||
size_t len = strlen_P(reinterpret_cast<const char*>(str));
|
||||
char work[len + 1];
|
||||
strncpy_P(work, reinterpret_cast<const char*>(str), len);
|
||||
return sendPronto(work, aNumberOfRepeats);
|
||||
}
|
||||
|
||||
static uint16_t effectiveFrequency(uint16_t frequency) {
|
||||
return frequency > 0 ? frequency : fallbackFrequency;
|
||||
}
|
||||
|
||||
static uint16_t toTimebase(uint16_t frequency) {
|
||||
return microsecondsInSeconds / effectiveFrequency(frequency);
|
||||
}
|
||||
|
||||
static uint16_t toFrequencyCode(uint16_t frequency) {
|
||||
return referenceFrequency / effectiveFrequency(frequency);
|
||||
}
|
||||
|
||||
static char hexDigit(unsigned int x) {
|
||||
return (char) (x <= 9 ? ('0' + x) : ('A' + (x - 10)));
|
||||
}
|
||||
|
||||
static void dumpDigit(Print *aSerial, unsigned int number) {
|
||||
aSerial->print(hexDigit(number));
|
||||
}
|
||||
|
||||
static void dumpNumber(Print *aSerial, uint16_t number) {
|
||||
for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
|
||||
unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
|
||||
dumpDigit(aSerial, (number >> shifts) & hexMask);
|
||||
}
|
||||
aSerial->print(' ');
|
||||
}
|
||||
|
||||
static void dumpDuration(Print *aSerial, uint32_t duration, uint16_t timebase) {
|
||||
dumpNumber(aSerial, (duration + timebase / 2) / timebase);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding!
|
||||
*/
|
||||
static void compensateAndDumpSequence(Print *aSerial, const volatile unsigned int *data, size_t length, uint16_t timebase) {
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
uint32_t tDuration = data[i] * MICROS_PER_TICK;
|
||||
if (i & 1) {
|
||||
// Mark
|
||||
tDuration -= getMarkExcessMicros();
|
||||
} else {
|
||||
tDuration += getMarkExcessMicros();
|
||||
}
|
||||
dumpDuration(aSerial, tDuration, timebase);
|
||||
}
|
||||
|
||||
// append a gap
|
||||
dumpDuration(aSerial, PRONTO_DEFAULT_GAP, timebase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the result (second argument) as Pronto Hex on the Print supplied as argument.
|
||||
* Used in the ReceiveDump example.
|
||||
* @param aSerial The Print object on which to write, for Arduino you can use &Serial.
|
||||
* @param aFrequencyHertz Modulation frequency in Hz. Often 38000Hz.
|
||||
*/
|
||||
void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int aFrequencyHertz) {
|
||||
aSerial->println(F("Pronto Hex as string"));
|
||||
aSerial->print(F("char prontoData[] = \""));
|
||||
dumpNumber(aSerial, aFrequencyHertz > 0 ? learnedToken : learnedNonModulatedToken);
|
||||
dumpNumber(aSerial, toFrequencyCode(aFrequencyHertz));
|
||||
dumpNumber(aSerial, (decodedIRData.rawDataPtr->rawlen + 1) / 2);
|
||||
dumpNumber(aSerial, 0);
|
||||
unsigned int timebase = toTimebase(aFrequencyHertz);
|
||||
compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1, timebase); // skip leading space
|
||||
aSerial->println("\";");
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for dumping Pronto to a String. This is not very time and space efficient
|
||||
* and can lead to resource problems especially on small processors like AVR's
|
||||
*/
|
||||
|
||||
static bool dumpDigit(String *aString, unsigned int number) {
|
||||
aString->concat(hexDigit(number));
|
||||
return number;
|
||||
}
|
||||
|
||||
static size_t dumpNumber(String *aString, uint16_t number) {
|
||||
|
||||
size_t size = 0;
|
||||
|
||||
for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
|
||||
unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
|
||||
size += dumpDigit(aString, (number >> shifts) & hexMask);
|
||||
}
|
||||
aString->concat(' ');
|
||||
size++;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding!
|
||||
*/
|
||||
static size_t dumpDuration(String *aString, uint32_t duration, uint16_t timebase) {
|
||||
return dumpNumber(aString, (duration + timebase / 2) / timebase);
|
||||
}
|
||||
|
||||
static size_t compensateAndDumpSequence(String *aString, const volatile unsigned int *data, size_t length, uint16_t timebase) {
|
||||
|
||||
size_t size = 0;
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
uint32_t tDuration = data[i] * MICROS_PER_TICK;
|
||||
if (i & 1) {
|
||||
// Mark
|
||||
tDuration -= getMarkExcessMicros();
|
||||
} else {
|
||||
tDuration += getMarkExcessMicros();
|
||||
}
|
||||
size += dumpDuration(aString, tDuration, timebase);
|
||||
}
|
||||
|
||||
// append minimum gap
|
||||
size += dumpDuration(aString, PRONTO_DEFAULT_GAP, timebase);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes Pronto HEX to a String object.
|
||||
* Returns the amount of characters added to the string.(360 characters for a NEC code!)
|
||||
*/
|
||||
size_t IRrecv::compensateAndStorePronto(String *aString, unsigned int frequency) {
|
||||
|
||||
size_t size = 0;
|
||||
unsigned int timebase = toTimebase(frequency);
|
||||
|
||||
size += dumpNumber(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken);
|
||||
size += dumpNumber(aString, toFrequencyCode(frequency));
|
||||
size += dumpNumber(aString, (decodedIRData.rawDataPtr->rawlen + 1) / 2);
|
||||
size += dumpNumber(aString, 0);
|
||||
size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1,
|
||||
timebase); // skip leading space
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_PRONTO_HPP
|
||||
559
arduino-libs/arduino-cli/libraries/IRremote/src/ir_RC5_RC6.hpp
Normal file
559
arduino-libs/arduino-cli/libraries/IRremote/src/ir_RC5_RC6.hpp
Normal file
@@ -0,0 +1,559 @@
|
||||
/*
|
||||
* ir_RC5_RC6.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending RC5, RC5X Protocols
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_RC5_RC6_HPP
|
||||
#define _IR_RC5_RC6_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
//#define TRACE // Activate this for more debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
bool sLastSendToggleValue = false;
|
||||
//uint8_t sLastReceiveToggleValue = 3; // 3 -> start value
|
||||
|
||||
//==============================================================================
|
||||
// RRRR CCCC 55555
|
||||
// R R C 5
|
||||
// RRRR C 5555
|
||||
// R R C 5
|
||||
// R R CCCC 5555
|
||||
//==============================================================================
|
||||
//
|
||||
// see: https://www.sbprojects.net/knowledge/ir/rc5.php
|
||||
// https://en.wikipedia.org/wiki/Manchester_code
|
||||
// mark->space => 0
|
||||
// space->mark => 1
|
||||
// MSB first 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command (6 bit command plus one field bit for RC5X), no stop bit
|
||||
// duty factor is 25%,
|
||||
//
|
||||
#define RC5_ADDRESS_BITS 5
|
||||
#define RC5_COMMAND_BITS 6
|
||||
#define RC5_COMMAND_FIELD_BIT 1
|
||||
#define RC5_TOGGLE_BIT 1
|
||||
|
||||
#define RC5_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS) // 13
|
||||
|
||||
#define RC5_UNIT 889 // 32 periods of 36 kHz (888.8888)
|
||||
|
||||
#define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7
|
||||
|
||||
#define RC5_DURATION (15L * RC5_UNIT) // 13335
|
||||
#define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792
|
||||
#define RC5_REPEAT_SPACE (RC5_REPEAT_PERIOD - RC5_DURATION) // 100 ms
|
||||
|
||||
/**
|
||||
* @param aCommand If aCommand is >=64 then we switch automatically to RC5X
|
||||
*/
|
||||
void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(RC5_RC6_KHZ);
|
||||
|
||||
uint16_t tIRData = ((aAddress & 0x1F) << RC5_COMMAND_BITS);
|
||||
|
||||
if (aCommand < 0x40) {
|
||||
// set field bit to lower field / set inverted upper command bit
|
||||
tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
|
||||
} else {
|
||||
// let field bit zero
|
||||
aCommand &= 0x3F;
|
||||
}
|
||||
|
||||
tIRData |= aCommand;
|
||||
|
||||
if (aEnableAutomaticToggle) {
|
||||
if (sLastSendToggleValue == 0) {
|
||||
sLastSendToggleValue = 1;
|
||||
// set toggled bit
|
||||
tIRData |= 1 << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
|
||||
} else {
|
||||
sLastSendToggleValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// start bit is sent by sendBiphaseData
|
||||
sendBiphaseData(RC5_UNIT, tIRData, RC5_BITS);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command in a fixed raster
|
||||
delay(RC5_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to decode data as RC5 protocol
|
||||
* _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
* Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |
|
||||
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of each data bit period
|
||||
* _ _ - Mark
|
||||
* 2 Start bits for RC5 _____| |_| ... - Data starts with a space->mark bit
|
||||
* - Space
|
||||
* _
|
||||
* 1 Start bit for RC5X _____| ...
|
||||
*
|
||||
*/
|
||||
bool IRrecv::decodeRC5() {
|
||||
uint8_t tBitIndex;
|
||||
uint32_t tDecodedRawData = 0;
|
||||
|
||||
// Set Biphase decoding start values
|
||||
initBiphaselevel(1, RC5_UNIT); // Skip gap space
|
||||
|
||||
// Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark.
|
||||
if (decodedIRData.rawDataPtr->rawlen < MIN_RC5_MARKS + 2 && decodedIRData.rawDataPtr->rawlen > ((2 * RC5_BITS) + 2)) {
|
||||
// no debug output, since this check is mainly to determine the received protocol
|
||||
IR_DEBUG_PRINT(F("RC5: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not between 11 and 26"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check start bit, the first space is included in the gap
|
||||
if (getBiphaselevel() != MARK) {
|
||||
IR_DEBUG_PRINT(F("RC5: "));
|
||||
IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get data bits - MSB first
|
||||
*/
|
||||
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) {
|
||||
uint8_t tStartLevel = getBiphaselevel();
|
||||
uint8_t tEndLevel = getBiphaselevel();
|
||||
|
||||
if ((tStartLevel == SPACE) && (tEndLevel == MARK)) {
|
||||
// we have a space to mark transition here
|
||||
tDecodedRawData = (tDecodedRawData << 1) | 1;
|
||||
} else if ((tStartLevel == MARK) && (tEndLevel == SPACE)) {
|
||||
// we have a mark to space transition here
|
||||
tDecodedRawData = (tDecodedRawData << 1) | 0;
|
||||
} else {
|
||||
// IR_TRACE_PRINT since I saw this too often
|
||||
IR_DEBUG_PRINT(F("RC5: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Success
|
||||
decodedIRData.numberOfBits = tBitIndex; // must be RC5_BITS
|
||||
|
||||
LongUnion tValue;
|
||||
tValue.ULong = tDecodedRawData;
|
||||
decodedIRData.decodedRawData = tDecodedRawData;
|
||||
decodedIRData.command = tValue.UByte.LowByte & 0x3F;
|
||||
decodedIRData.address = (tValue.UWord.LowWord >> RC5_COMMAND_BITS) & 0x1F;
|
||||
|
||||
// Get the inverted 7. command bit for RC5X, the inverted value is always 1 for RC5 and serves as a second start bit.
|
||||
if ((tValue.UWord.LowWord & (1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS))) == 0) {
|
||||
decodedIRData.command += 0x40;
|
||||
}
|
||||
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
if (tValue.UByte.MidLowByte & 0x8) {
|
||||
decodedIRData.flags = IRDATA_TOGGLE_BIT_MASK | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
}
|
||||
|
||||
// check for repeat
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < (RC5_REPEAT_PERIOD / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
|
||||
}
|
||||
|
||||
decodedIRData.protocol = RC5;
|
||||
return true;
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
// RRRR CCCC 6666
|
||||
// R R C 6
|
||||
// RRRR C 6666
|
||||
// R R C 6 6
|
||||
// R R CCCC 666
|
||||
//
|
||||
//
|
||||
// mark->space => 1
|
||||
// space->mark => 0
|
||||
// https://www.sbprojects.net/knowledge/ir/rc6.php
|
||||
// https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A
|
||||
// https://en.wikipedia.org/wiki/Manchester_code
|
||||
|
||||
#define MIN_RC6_SAMPLES 1
|
||||
|
||||
#define RC6_RPT_LENGTH 46000
|
||||
|
||||
#define RC6_LEADING_BIT 1
|
||||
#define RC6_MODE_BITS 3 // never seen others than all 0 for Philips TV
|
||||
#define RC6_TOGGLE_BIT 1 // toggles at every key press. Can be used to distinguish repeats from 2 key presses.
|
||||
#define RC6_ADDRESS_BITS 8
|
||||
#define RC6_COMMAND_BITS 8
|
||||
|
||||
#define RC6_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 13
|
||||
|
||||
#define RC6_UNIT 444 // 16 periods of 36 kHz (444.4444)
|
||||
|
||||
#define RC6_HEADER_MARK (6 * RC6_UNIT) // 2666
|
||||
#define RC6_HEADER_SPACE (2 * RC6_UNIT) // 889
|
||||
|
||||
#define RC6_TRAILING_SPACE (6 * RC6_UNIT) // 2666
|
||||
#define MIN_RC6_MARKS 4 + ((RC6_ADDRESS_BITS + RC6_COMMAND_BITS) / 2) // 12, 4 are for preamble
|
||||
|
||||
#define RC6_REPEAT_SPACE 107000 // just a guess but > 2.666ms
|
||||
|
||||
/**
|
||||
* Main RC6 send function
|
||||
*/
|
||||
void IRsend::sendRC6(uint32_t aRawData, uint8_t aNumberOfBitsToSend) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(RC5_RC6_KHZ);
|
||||
|
||||
// Header
|
||||
mark(RC6_HEADER_MARK);
|
||||
space(RC6_HEADER_SPACE);
|
||||
|
||||
// Start bit
|
||||
mark(RC6_UNIT);
|
||||
space(RC6_UNIT);
|
||||
|
||||
// Data MSB first
|
||||
uint32_t mask = 1UL << (aNumberOfBitsToSend - 1);
|
||||
for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
|
||||
// The fourth bit we send is the "double width toggle bit"
|
||||
unsigned int t = (i == 4) ? (RC6_UNIT * 2) : (RC6_UNIT);
|
||||
if (aRawData & mask) {
|
||||
mark(t);
|
||||
space(t);
|
||||
} else {
|
||||
space(t);
|
||||
mark(t);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send RC6 64 bit raw data
|
||||
* We do not wait for the minimal trailing space of 2666 us
|
||||
*/
|
||||
void IRsend::sendRC6(uint64_t data, uint8_t nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(RC5_RC6_KHZ);
|
||||
|
||||
// Header
|
||||
mark(RC6_HEADER_MARK);
|
||||
space(RC6_HEADER_SPACE);
|
||||
|
||||
// Start bit
|
||||
mark(RC6_UNIT);
|
||||
space(RC6_UNIT);
|
||||
|
||||
// Data MSB first
|
||||
uint64_t mask = 1ULL << (nbits - 1);
|
||||
for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
|
||||
// The fourth bit we send is the "double width toggle bit"
|
||||
unsigned int t = (i == 4) ? (RC6_UNIT * 2) : (RC6_UNIT);
|
||||
if (data & mask) {
|
||||
mark(t);
|
||||
space(t);
|
||||
} else {
|
||||
space(t);
|
||||
mark(t);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble raw data for RC6 from parameters and toggle state and send
|
||||
* We do not wait for the minimal trailing space of 2666 us
|
||||
* @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable.
|
||||
*/
|
||||
void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
|
||||
|
||||
LongUnion tIRRawData;
|
||||
tIRRawData.UByte.LowByte = aCommand;
|
||||
tIRRawData.UByte.MidLowByte = aAddress;
|
||||
|
||||
tIRRawData.UWord.HighWord = 0; // must clear high word
|
||||
if (aEnableAutomaticToggle) {
|
||||
if (sLastSendToggleValue == 0) {
|
||||
sLastSendToggleValue = 1;
|
||||
// set toggled bit
|
||||
IR_DEBUG_PRINT(F("Set Toggle "));
|
||||
tIRRawData.UByte.MidHighByte = 1; // 3 Mode bits are 0
|
||||
} else {
|
||||
sLastSendToggleValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINT(F("sLastSendToggleValue="));
|
||||
IR_DEBUG_PRINT(sLastSendToggleValue);
|
||||
IR_DEBUG_PRINT(F(" RawData="));
|
||||
IR_DEBUG_PRINTLN(tIRRawData.ULong, HEX);
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// start and leading bits are sent by sendRC6
|
||||
sendRC6(tIRRawData.ULong, RC6_BITS - 1); // -1 since the leading bit is additionally sent by sendRC6
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command in a fixed raster
|
||||
delay(RC6_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to decode data as RC6 protocol
|
||||
*/
|
||||
bool IRrecv::decodeRC6() {
|
||||
uint8_t tBitIndex;
|
||||
uint32_t tDecodedRawData = 0;
|
||||
|
||||
// Check we have the right amount of data (). The +3 for initial gap, start bit mark and space
|
||||
if (decodedIRData.rawDataPtr->rawlen < MIN_RC6_MARKS + 3 && decodedIRData.rawDataPtr->rawlen > ((2 * RC6_BITS) + 3)) {
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not between 15 and 45"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "mark" and "space", this must be done for repeat and data
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], RC6_HEADER_MARK)
|
||||
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], RC6_HEADER_SPACE)) {
|
||||
// no debug output, since this check is mainly to determine the received protocol
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set Biphase decoding start values
|
||||
initBiphaselevel(3, RC6_UNIT); // Skip gap-space and start-bit mark + space
|
||||
|
||||
// Process first bit, which is known to be a 1 (mark->space)
|
||||
if (getBiphaselevel() != MARK) {
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK"));
|
||||
return false;
|
||||
}
|
||||
if (getBiphaselevel() != SPACE) {
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINTLN(F("second getBiphaselevel() is not SPACE"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) {
|
||||
uint8_t tStartLevel; // start level of coded bit
|
||||
uint8_t tEndLevel; // end level of coded bit
|
||||
|
||||
tStartLevel = getBiphaselevel();
|
||||
if (tBitIndex == 3) {
|
||||
// Toggle bit is double wide; make sure second half is equal first half
|
||||
if (tStartLevel != getBiphaselevel()) {
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINTLN(F("Toggle mark or space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
tEndLevel = getBiphaselevel();
|
||||
if (tBitIndex == 3) {
|
||||
// Toggle bit is double wide; make sure second half matches
|
||||
if (tEndLevel != getBiphaselevel()) {
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINTLN(F("Toggle mark or space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine tDecodedRawData bit value by checking the transition type
|
||||
*/
|
||||
if ((tStartLevel == MARK) && (tEndLevel == SPACE)) {
|
||||
// we have a mark to space transition here
|
||||
tDecodedRawData = (tDecodedRawData << 1) | 1; // inverted compared to RC5
|
||||
} else if ((tStartLevel == SPACE) && (tEndLevel == MARK)) {
|
||||
// we have a space to mark transition here
|
||||
tDecodedRawData = (tDecodedRawData << 1) | 0;
|
||||
} else {
|
||||
IR_DEBUG_PRINT(F("RC6: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
// we have no transition here or one level is -1 -> error
|
||||
return false; // Error
|
||||
}
|
||||
}
|
||||
|
||||
// Success
|
||||
decodedIRData.numberOfBits = tBitIndex;
|
||||
|
||||
LongUnion tValue;
|
||||
tValue.ULong = tDecodedRawData;
|
||||
decodedIRData.decodedRawData = tDecodedRawData;
|
||||
|
||||
if (tBitIndex < 36) {
|
||||
// RC6
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
decodedIRData.command = tValue.UByte.LowByte;
|
||||
decodedIRData.address = tValue.UByte.MidLowByte;
|
||||
// Check for toggle flag
|
||||
if ((tValue.UByte.MidHighByte & 1) != 0) {
|
||||
decodedIRData.flags = IRDATA_TOGGLE_BIT_MASK | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
}
|
||||
} else {
|
||||
// RC6A
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
if ((tValue.UByte.MidLowByte & 0x80) != 0) {
|
||||
decodedIRData.flags = IRDATA_TOGGLE_BIT_MASK | IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
}
|
||||
tValue.UByte.MidLowByte &= 0x87F; // mask toggle bit
|
||||
decodedIRData.command = tValue.UByte.LowByte;
|
||||
decodedIRData.address = tValue.UByte.MidLowByte;
|
||||
}
|
||||
|
||||
// check for repeat, do not check toggle bit yet
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < ((RC6_REPEAT_SPACE + (RC6_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
|
||||
}
|
||||
|
||||
decodedIRData.protocol = RC6;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Old version with 32 bit data
|
||||
*/
|
||||
void IRsend::sendRC5(uint32_t data, uint8_t nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(RC5_RC6_KHZ);
|
||||
|
||||
// Start
|
||||
mark(RC5_UNIT);
|
||||
space(RC5_UNIT);
|
||||
mark(RC5_UNIT);
|
||||
|
||||
// Data - Biphase code MSB first
|
||||
for (uint32_t mask = 1UL << (nbits - 1); mask; mask >>= 1) {
|
||||
if (data & mask) {
|
||||
space(RC5_UNIT); // 1 is space, then mark
|
||||
mark(RC5_UNIT);
|
||||
} else {
|
||||
mark(RC5_UNIT);
|
||||
space(RC5_UNIT);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/*
|
||||
* Not longer required, use sendRC5 instead
|
||||
*/
|
||||
void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(RC5_RC6_KHZ);
|
||||
|
||||
uint8_t addressBits = 5;
|
||||
uint8_t commandBits = 7;
|
||||
// unsigned long nbits = addressBits + commandBits;
|
||||
|
||||
// Start
|
||||
mark(RC5_UNIT);
|
||||
|
||||
// Bit #6 of the command part, but inverted!
|
||||
uint8_t cmdBit6 = (1UL << (commandBits - 1)) & cmd;
|
||||
if (cmdBit6) {
|
||||
// Inverted (1 -> 0 = mark-to-space)
|
||||
mark(RC5_UNIT);
|
||||
space(RC5_UNIT);
|
||||
} else {
|
||||
space(RC5_UNIT);
|
||||
mark(RC5_UNIT);
|
||||
}
|
||||
commandBits--;
|
||||
|
||||
// Toggle bit
|
||||
static int toggleBit = 1;
|
||||
if (toggle) {
|
||||
if (toggleBit == 0) {
|
||||
toggleBit = 1;
|
||||
} else {
|
||||
toggleBit = 0;
|
||||
}
|
||||
}
|
||||
if (toggleBit) {
|
||||
space(RC5_UNIT);
|
||||
mark(RC5_UNIT);
|
||||
} else {
|
||||
mark(RC5_UNIT);
|
||||
space(RC5_UNIT);
|
||||
}
|
||||
|
||||
// Address
|
||||
for (uint_fast8_t mask = 1UL << (addressBits - 1); mask; mask >>= 1) {
|
||||
if (addr & mask) {
|
||||
space(RC5_UNIT); // 1 is space, then mark
|
||||
mark(RC5_UNIT);
|
||||
} else {
|
||||
mark(RC5_UNIT);
|
||||
space(RC5_UNIT);
|
||||
}
|
||||
}
|
||||
|
||||
// Command
|
||||
for (uint_fast8_t mask = 1UL << (commandBits - 1); mask; mask >>= 1) {
|
||||
if (cmd & mask) {
|
||||
space(RC5_UNIT); // 1 is space, then mark
|
||||
mark(RC5_UNIT);
|
||||
} else {
|
||||
mark(RC5_UNIT);
|
||||
space(RC5_UNIT);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_RC5_RC6_HPP
|
||||
270
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Samsung.hpp
Normal file
270
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Samsung.hpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* ir_Samsung.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending Samsung IR Protocol in "raw" and standard format with 16 bit address and 16 or 32 bit command
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017-2021 Darryl Smith, Armin Joachimsmeyer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONSAMSUNGTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_SAMSUNG_HPP
|
||||
#define _IR_SAMSUNG_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
#include "LongUnion.h"
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// SSSS AAA MMM SSSS U U N N GGGG
|
||||
// S A A M M M S U U NN N G
|
||||
// SSS AAAAA M M M SSS U U N N N G GG
|
||||
// S A A M M S U U N NN G G
|
||||
// SSSS A A M M SSSS UUU N N GGG
|
||||
//==============================================================================
|
||||
// see http://www.hifi-remote.com/wiki/index.php?title=DecodeIR#Samsung
|
||||
// https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG32
|
||||
// LSB first, 1 start bit + 16 bit address + 16,32,20 bit data + 1 stop bit.
|
||||
// On my Samsung remote they are plain repeats of the complete frame.
|
||||
#define SAMSUNG_ADDRESS_BITS 16
|
||||
#define SAMSUNG_COMMAND16_BITS 16
|
||||
#define SAMSUNG_COMMAND32_BITS 32
|
||||
#define SAMSUNG_BITS (SAMSUNG_ADDRESS_BITS + SAMSUNG_COMMAND16_BITS)
|
||||
#define SAMSUNG48_BITS (SAMSUNG_ADDRESS_BITS + SAMSUNG_COMMAND32_BITS)
|
||||
|
||||
#define SAMSUNG_UNIT 553 // 21 periods of 38 kHz (552,631) TICKS_LOW = 8.253 TICKS_HIGH = 14.825
|
||||
#define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4400
|
||||
#define SAMSUNG_HEADER_SPACE (8 * SAMSUNG_UNIT) // 4400
|
||||
#define SAMSUNG_BIT_MARK SAMSUNG_UNIT
|
||||
#define SAMSUNG_ONE_SPACE (3 * SAMSUNG_UNIT) // 1650 TICKS_LOW = 24.62 TICKS_HIGH = 42.25
|
||||
#define SAMSUNG_ZERO_SPACE SAMSUNG_UNIT
|
||||
|
||||
#define SAMSUNG_AVERAGE_DURATION 55000 // SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + 32 * 2,5 * SAMSUNG_UNIT + SAMSUNG_UNIT // 2.5 because we assume more zeros than ones
|
||||
#define SAMSUNG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
|
||||
|
||||
/**
|
||||
* Please note me (armin.arduino@gmail.com) if you ever see this special repeat in the wild
|
||||
* Send repeat
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
*/
|
||||
void IRsend::sendSamsungRepeat() {
|
||||
enableIROut(SAMSUNG_KHZ); // 38 kHz
|
||||
mark(SAMSUNG_HEADER_MARK);
|
||||
space(SAMSUNG_HEADER_SPACE);
|
||||
mark(SAMSUNG_BIT_MARK);
|
||||
space(SAMSUNG_ZERO_SPACE);
|
||||
mark(SAMSUNG_BIT_MARK);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
|
||||
// Set IR carrier frequency
|
||||
enableIROut(SAMSUNG_KHZ);
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
unsigned long tStartOfFrameMillis = millis();
|
||||
|
||||
// Header
|
||||
mark(SAMSUNG_HEADER_MARK);
|
||||
space(SAMSUNG_HEADER_SPACE);
|
||||
|
||||
// Address
|
||||
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, aAddress,
|
||||
SAMSUNG_ADDRESS_BITS, PROTOCOL_IS_LSB_FIRST);
|
||||
|
||||
// Command
|
||||
|
||||
// send 8 command bits and then 8 inverted command bits LSB first
|
||||
aCommand = aCommand & 0xFF;
|
||||
aCommand = ((~aCommand) << 8) | aCommand;
|
||||
|
||||
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, aCommand,
|
||||
SAMSUNG_COMMAND16_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeat in a 110 ms raster
|
||||
while (millis() - tStartOfFrameMillis < (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI)) {
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
bool IRrecv::decodeSamsung() {
|
||||
|
||||
// Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark
|
||||
if (decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG_BITS) + 4)
|
||||
&& decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG48_BITS) + 4)) {
|
||||
IR_DEBUG_PRINT(F("Samsung: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 68 or 100"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "mark" + "space"
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], SAMSUNG_HEADER_MARK)
|
||||
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], SAMSUNG_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("Samsung: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decodedIRData.rawDataPtr->rawlen == (2 * SAMSUNG48_BITS) + 4) {
|
||||
/*
|
||||
* Samsung48
|
||||
*/
|
||||
// decode address
|
||||
if (!decodePulseDistanceData(SAMSUNG_ADDRESS_BITS, 3, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
|
||||
PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Samsung: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
decodedIRData.address = decodedIRData.decodedRawData;
|
||||
|
||||
// decode 32 bit command
|
||||
if (!decodePulseDistanceData(SAMSUNG_COMMAND32_BITS, 3, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
|
||||
PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Samsung: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
LongUnion tValue;
|
||||
tValue.ULong = decodedIRData.decodedRawData;
|
||||
// receive 2 * (8 bits then 8 inverted bits) LSB first
|
||||
if (tValue.UByte.HighByte != (uint8_t) (~tValue.UByte.MidHighByte)
|
||||
&& tValue.UByte.MidLowByte != (uint8_t) (~tValue.UByte.LowByte)) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
}
|
||||
decodedIRData.command = tValue.UByte.HighByte << 8 | tValue.UByte.MidLowByte;
|
||||
decodedIRData.numberOfBits = SAMSUNG48_BITS;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Samsung32
|
||||
*/
|
||||
if (!decodePulseDistanceData(SAMSUNG_BITS, 3, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
|
||||
PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Samsung: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
LongUnion tValue;
|
||||
tValue.ULong = decodedIRData.decodedRawData;
|
||||
decodedIRData.address = tValue.UWord.LowWord;
|
||||
|
||||
if (tValue.UByte.MidHighByte == (uint8_t) (~tValue.UByte.HighByte)) {
|
||||
// 8 bit command protocol
|
||||
decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit
|
||||
} else {
|
||||
// 16 bit command protocol
|
||||
decodedIRData.command = tValue.UWord.HighWord; // first 16 bit
|
||||
}
|
||||
decodedIRData.numberOfBits = SAMSUNG_BITS;
|
||||
}
|
||||
|
||||
// check for repeat
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < (SAMSUNG_REPEAT_PERIOD / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
|
||||
}
|
||||
|
||||
decodedIRData.protocol = SAMSUNG;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRrecv::decodeSAMSUNG(decode_results *aResults) {
|
||||
unsigned int offset = 1; // Skip first space
|
||||
|
||||
// Initial mark
|
||||
if (!matchMark(aResults->rawbuf[offset], SAMSUNG_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// Check for repeat -- like a NEC repeat
|
||||
if ((aResults->rawlen == 4) && matchSpace(aResults->rawbuf[offset], 2250)
|
||||
&& matchMark(aResults->rawbuf[offset + 1], SAMSUNG_BIT_MARK)) {
|
||||
aResults->bits = 0;
|
||||
aResults->value = 0xFFFFFFFF;
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
|
||||
decodedIRData.protocol = SAMSUNG;
|
||||
return true;
|
||||
}
|
||||
if (aResults->rawlen < (2 * SAMSUNG_BITS) + 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initial space
|
||||
if (!matchSpace(aResults->rawbuf[offset], SAMSUNG_HEADER_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
if (!decodePulseDistanceData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
|
||||
PROTOCOL_IS_MSB_FIRST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
aResults->value = decodedIRData.decodedRawData;
|
||||
aResults->bits = SAMSUNG_BITS;
|
||||
aResults->decode_type = SAMSUNG;
|
||||
decodedIRData.protocol = SAMSUNG;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Old version with MSB first
|
||||
void IRsend::sendSAMSUNG(unsigned long data, int nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(SAMSUNG_KHZ);
|
||||
|
||||
// Header
|
||||
mark(SAMSUNG_HEADER_MARK);
|
||||
space(SAMSUNG_HEADER_SPACE);
|
||||
|
||||
// Old version with MSB first Data + stop bit
|
||||
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, data, nbits,
|
||||
PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_SAMSUNG_HPP
|
||||
230
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Sony.hpp
Normal file
230
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Sony.hpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* ir_Sony.hpp
|
||||
*
|
||||
* Contains functions for receiving and sending SIRCS/Sony IR Protocol in "raw" and standard format with 5 bit address 7 bit command
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_SONY_HPP
|
||||
#define _IR_SONY_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// SSSS OOO N N Y Y
|
||||
// S O O NN N Y Y
|
||||
// SSS O O N N N Y
|
||||
// S O O N NN Y
|
||||
// SSSS OOO N N Y
|
||||
//==============================================================================
|
||||
// see https://www.sbprojects.net/knowledge/ir/sirc.php
|
||||
// Here http://picprojects.org.uk/projects/sirc/ it is claimed, that many Sony remotes repeat each frame a minimum of 3 times
|
||||
// LSB first, start bit + 7 command + 5 to 13 address, no stop bit
|
||||
//
|
||||
#define SONY_ADDRESS_BITS 5
|
||||
#define SONY_COMMAND_BITS 7
|
||||
#define SONY_EXTRA_BITS 8
|
||||
#define SONY_BITS_MIN (SONY_COMMAND_BITS + SONY_ADDRESS_BITS) // 12 bits
|
||||
#define SONY_BITS_15 (SONY_COMMAND_BITS + SONY_ADDRESS_BITS + 3) // 15 bits
|
||||
#define SONY_BITS_MAX (SONY_COMMAND_BITS + SONY_ADDRESS_BITS + SONY_EXTRA_BITS) // 20 bits == SIRCS_20_PROTOCOL
|
||||
#define SONY_UNIT 600 // 24 periods of 40kHz
|
||||
|
||||
#define SONY_HEADER_MARK (4 * SONY_UNIT) // 2400
|
||||
#define SONY_ONE_MARK (2 * SONY_UNIT) // 1200
|
||||
#define SONY_ZERO_MARK SONY_UNIT
|
||||
#define SONY_SPACE SONY_UNIT
|
||||
|
||||
#define SONY_AVERAGE_DURATION 21000 // SONY_HEADER_MARK + SONY_SPACE + 12 * 2,5 * SONY_UNIT // 2.5 because we assume more zeros than ones
|
||||
#define SONY_REPEAT_PERIOD 45000 // Commands are repeated every 45 ms (measured from start to start) for as long as the key on the remote control is held down.
|
||||
#define SONY_REPEAT_SPACE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION) // 24 ms
|
||||
|
||||
/*
|
||||
* Repeat commands should be sent in a 45 ms raster.
|
||||
* There is NO delay after the last sent command / repeat!
|
||||
* @param numberOfBits if == 20 send 13 address bits otherwise only 5 address bits
|
||||
*/
|
||||
void IRsend::sendSony(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint8_t numberOfBits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(SONY_KHZ); // 40 kHz
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Header
|
||||
mark(SONY_HEADER_MARK);
|
||||
space(SONY_SPACE);
|
||||
|
||||
// send 7 command bits LSB first
|
||||
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, aCommand, SONY_COMMAND_BITS,
|
||||
PROTOCOL_IS_LSB_FIRST);
|
||||
// send 5, 8, 13 address bits LSB first
|
||||
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, aAddress,
|
||||
(numberOfBits - SONY_COMMAND_BITS), PROTOCOL_IS_LSB_FIRST);
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command in a 45 ms raster
|
||||
delay(SONY_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
|
||||
bool IRrecv::decodeSony() {
|
||||
|
||||
// Check header "mark"
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], SONY_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42
|
||||
if (decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MAX) + 2
|
||||
&& decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_15) + 2) {
|
||||
// ??? IR_TRACE_PRINT since I saw this too often
|
||||
IR_DEBUG_PRINT(F("Sony: "));
|
||||
IR_DEBUG_PRINT(F("Data length="));
|
||||
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
|
||||
IR_DEBUG_PRINTLN(F(" is not 12, 15 or 20"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "space"
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], SONY_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("Sony: "));
|
||||
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseWidthData((decodedIRData.rawDataPtr->rawlen - 1) / 2, 3, SONY_ONE_MARK, SONY_ZERO_MARK, SONY_SPACE,
|
||||
PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Sony: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
uint8_t tCommand = decodedIRData.decodedRawData & 0x7F; // first 7 bits
|
||||
uint16_t tAddress = decodedIRData.decodedRawData >> 7; // next 5 or 8 or 13 bits
|
||||
|
||||
/*
|
||||
* Check for repeat
|
||||
*/
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < (SONY_REPEAT_PERIOD / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
}
|
||||
decodedIRData.command = tCommand;
|
||||
decodedIRData.address = tAddress;
|
||||
decodedIRData.numberOfBits = (decodedIRData.rawDataPtr->rawlen - 1) / 2;
|
||||
decodedIRData.protocol = SONY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define SONY_DOUBLE_SPACE_USECS 500 // usually see 713 - not using ticks as get number wrap around
|
||||
bool IRrecv::decodeSonyMSB(decode_results *aResults) {
|
||||
long data = 0;
|
||||
uint8_t bits = 0;
|
||||
unsigned int offset = 0; // Dont skip first space, check its size
|
||||
|
||||
if (aResults->rawlen < (2 * SONY_BITS_MIN) + 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some Sony's deliver repeats fast after first
|
||||
// unfortunately can't spot difference from of repeat from two fast clicks
|
||||
if (aResults->rawbuf[0] < (SONY_DOUBLE_SPACE_USECS / MICROS_PER_TICK)) {
|
||||
IR_DEBUG_PRINTLN(F("IR Gap found"));
|
||||
aResults->bits = 0;
|
||||
aResults->value = 0xFFFFFFFF;
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
|
||||
decodedIRData.protocol = SONY;
|
||||
return true;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// Check header "mark"
|
||||
if (!matchMark(aResults->rawbuf[offset], SONY_HEADER_MARK)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// MSB first - Not compatible to standard, which says LSB first :-(
|
||||
while (offset + 1 < aResults->rawlen) {
|
||||
|
||||
// First check for the constant space length, we do not have a space at the end of raw data
|
||||
// we are lucky, since the start space is equal the data space.
|
||||
if (!matchSpace(aResults->rawbuf[offset], SONY_SPACE)) {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
|
||||
// bit value is determined by length of the mark
|
||||
if (matchMark(aResults->rawbuf[offset], SONY_ONE_MARK)) {
|
||||
data = (data << 1) | 1;
|
||||
} else if (matchMark(aResults->rawbuf[offset], SONY_ZERO_MARK)) {
|
||||
data = (data << 1) | 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
offset++;
|
||||
bits++;
|
||||
|
||||
}
|
||||
|
||||
aResults->bits = bits;
|
||||
aResults->value = data;
|
||||
aResults->decode_type = SONY;
|
||||
decodedIRData.protocol = SONY;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Old version with MSB first data
|
||||
*/
|
||||
void IRsend::sendSony(unsigned long data, int nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(SONY_KHZ);
|
||||
|
||||
// Header
|
||||
mark(SONY_HEADER_MARK);
|
||||
space(SONY_SPACE);
|
||||
|
||||
// Old version with MSB first Data
|
||||
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_SONY_HPP
|
||||
218
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Template.hpp
Normal file
218
arduino-libs/arduino-cli/libraries/IRremote/src/ir_Template.hpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
Assuming the protocol we are adding is for the (imaginary) manufacturer: Shuzu
|
||||
|
||||
Our fantasy protocol is a standard protocol, so we can use this standard
|
||||
template without too much work. Some protocols are quite unique and will require
|
||||
considerably more work in this file! It is way beyond the scope of this text to
|
||||
explain how to reverse engineer "unusual" IR protocols. But, unless you own an
|
||||
oscilloscope, the starting point is probably to use the ReceiveDump.ino sketch and
|
||||
try to spot the pattern!
|
||||
|
||||
Before you start, make sure the IR library is working OK:
|
||||
# Open up the Arduino IDE
|
||||
# Load up the ReceiveDump.ino example sketch
|
||||
# Run it
|
||||
# Analyze your data to have an idea, what is the header timing, the bit timing, the address, the command and the checksum of your protocol.
|
||||
|
||||
Now we can start to add our new protocol...
|
||||
|
||||
1. Copy this file to : ir_<YourProtocolName>.hpp
|
||||
|
||||
2. Replace all occurrences of "Shuzu" with the name of your protocol.
|
||||
|
||||
3. Tweak the #defines to suit your protocol.
|
||||
|
||||
4. If you're lucky, tweaking the #defines will make the decode and send() function
|
||||
work.
|
||||
|
||||
You have now written the code to support your new protocol!
|
||||
|
||||
To integrate it into the IRremote library, you must search for "BOSEWAVE"
|
||||
and add your protocol in the same way as it is already done for BOSEWAVE.
|
||||
|
||||
You have to change the following files:
|
||||
IRSend.hpp IRsend::write(IRData *aIRSendData + uint_fast8_t aNumberOfRepeats)
|
||||
IRProtocol.h Add it to decode_type_t
|
||||
IRReceive.hpp IRrecv::decode() + printActiveIRProtocols(Print *aSerial) + getProtocolString(decode_type_t aProtocol)
|
||||
IRremote.hpp At 3 occurrences of DECODE_XXX
|
||||
IRremoteInt.h Add the declaration of the decode and send function
|
||||
|
||||
Now open the Arduino IDE, load up the ReceiveDump.ino sketch, and run it.
|
||||
Hopefully it will compile and upload.
|
||||
If it doesn't, you've done something wrong. Check your work and look carefully at the error messages.
|
||||
|
||||
If you get this far, I will assume you have successfully added your new protocol
|
||||
|
||||
At last, delete this giant instructional comment.
|
||||
|
||||
If you want us to include your work in the library so others may benefit
|
||||
from your hard work, you have to extend the examples
|
||||
IRremoteInfo, SmallReceiver, simple Receiver, SendDemo and UnitTest too
|
||||
as well as the Readme.md
|
||||
It is not an act, but required for completeness.
|
||||
|
||||
Thanks
|
||||
The maintainer
|
||||
*/
|
||||
|
||||
/*
|
||||
* ir_Shuzu.cpp
|
||||
*
|
||||
* Contains functions for receiving and sending Shuzu IR Protocol ...
|
||||
*
|
||||
* Copyright (C) 2022 Shuzu Guru
|
||||
* shuzu.guru@gmail.com
|
||||
*
|
||||
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
|
||||
*
|
||||
************************************************************************************
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Unknown Contributor :-)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
************************************************************************************
|
||||
*/
|
||||
#ifndef _IR_SHUZU_HPP
|
||||
#define _IR_SHUZU_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
//#define SEND_SHUZU 1 // for testing
|
||||
//#define DECODE_SHUZU 1 // for testing
|
||||
//==============================================================================
|
||||
//
|
||||
//
|
||||
// S H U Z U
|
||||
//
|
||||
//
|
||||
//==============================================================================
|
||||
// see: https://www....
|
||||
|
||||
// LSB first, 1 start bit + 16 bit address + 8 bit command + 1 stop bit.
|
||||
#define SHUZU_ADDRESS_BITS 16 // 16 bit address
|
||||
#define SHUZU_COMMAND_BITS 8 // Command
|
||||
|
||||
#define SHUZU_BITS (SHUZU_ADDRESS_BITS + SHUZU_COMMAND_BITS) // The number of bits in the protocol
|
||||
#define SHUZU_UNIT 560
|
||||
|
||||
#define SHUZU_HEADER_MARK (16 * SHUZU_UNIT) // The length of the Header:Mark
|
||||
#define SHUZU_HEADER_SPACE (8 * SHUZU_UNIT) // The length of the Header:Space
|
||||
|
||||
#define SHUZU_BIT_MARK SHUZU_UNIT // The length of a Bit:Mark
|
||||
#define SHUZU_ONE_SPACE (3 * SHUZU_UNIT) // The length of a Bit:Space for 1's
|
||||
#define SHUZU_ZERO_SPACE SHUZU_UNIT // The length of a Bit:Space for 0's
|
||||
|
||||
#define SHUZU_REPEAT_HEADER_SPACE (4 * SHUZU_UNIT) // 2250
|
||||
|
||||
#define SHUZU_REPEAT_SPACE 45000
|
||||
|
||||
#define SHUZU_OTHER 1234 // Other things you may need to define
|
||||
|
||||
//+=============================================================================
|
||||
//
|
||||
void IRsend::sendShuzu(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(38);
|
||||
|
||||
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
|
||||
while (tNumberOfCommands > 0) {
|
||||
|
||||
// Header
|
||||
mark(SHUZU_HEADER_MARK);
|
||||
space(SHUZU_HEADER_SPACE);
|
||||
|
||||
// Address (device and subdevice)
|
||||
sendPulseDistanceWidthData(SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, aAddress,
|
||||
SHUZU_ADDRESS_BITS, PROTOCOL_IS_LSB_FIRST); // false -> LSB first
|
||||
|
||||
// Command + stop bit
|
||||
sendPulseDistanceWidthData(SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, aCommand,
|
||||
SHUZU_COMMAND_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT); // false, true -> LSB first, stop bit
|
||||
|
||||
tNumberOfCommands--;
|
||||
// skip last delay!
|
||||
if (tNumberOfCommands > 0) {
|
||||
// send repeated command in a fixed raster
|
||||
delay(SHUZU_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
|
||||
}
|
||||
}
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
//
|
||||
/*
|
||||
* First check for right data length
|
||||
* Next check start bit
|
||||
* Next try the decode
|
||||
* Last check stop bit
|
||||
*/
|
||||
bool IRrecv::decodeShuzu() {
|
||||
|
||||
// Check we have the right amount of data (28). The +4 is for initial gap, start bit mark and space + stop bit mark
|
||||
if (decodedIRData.rawDataPtr->rawlen != (2 * SHUZU_BITS) + 4) {
|
||||
// no debug output, since this check is mainly to determine the received protocol
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check header "space"
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], SHUZU_HEADER_MARK)
|
||||
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], SHUZU_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("Shuzu: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// false -> LSB first
|
||||
if (!decodePulseDistanceData(SHUZU_BITS, 3, SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
|
||||
IR_DEBUG_PRINT(F("Shuzu: "));
|
||||
IR_DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * SHUZU_BITS)], SHUZU_BIT_MARK)) {
|
||||
IR_DEBUG_PRINT(F("Shuzu: "));
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
|
||||
uint8_t tCommand = decodedIRData.decodedRawData >> SHUZU_ADDRESS_BITS; // upper 8 bits of LSB first value
|
||||
uint8_t tAddress = decodedIRData.decodedRawData & 0xFFFF; // lowest 16 bit of LSB first value
|
||||
|
||||
/*
|
||||
* Check for repeat
|
||||
*/
|
||||
if (decodedIRData.rawDataPtr->rawbuf[0] < ((SHUZU_REPEAT_SPACE + (SHUZU_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
|
||||
}
|
||||
decodedIRData.command = tCommand;
|
||||
decodedIRData.address = tAddress;
|
||||
decodedIRData.numberOfBits = SHUZU_BITS;
|
||||
decodedIRData.protocol = BOSEWAVE; // we have no SHUZU code
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // _IR_SHUZU_HPP
|
||||
@@ -0,0 +1,82 @@
|
||||
#ifndef _IR_WHYNTER_HPP
|
||||
#define _IR_WHYNTER_HPP
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
|
||||
|
||||
/** \addtogroup Decoder Decoders and encoders for different protocols
|
||||
* @{
|
||||
*/
|
||||
//==============================================================================
|
||||
// W W H H Y Y N N TTTTT EEEEE RRRRR
|
||||
// W W H H Y Y NN N T E R R
|
||||
// W W W HHHHH Y N N N T EEE RRRR
|
||||
// W W W H H Y N NN T E R R
|
||||
// WWW H H Y N N T EEEEE R R
|
||||
//==============================================================================
|
||||
// Whynter A/C ARC-110WD added by Francesco Meschia
|
||||
// see https://docs.google.com/spreadsheets/d/1dsr4Jh-nzC6xvSKGpLlPBF0NRwvlpyw-ozg8eZU813w/edit#gid=0
|
||||
#define WHYNTER_BITS 32
|
||||
#define WHYNTER_HEADER_MARK 2850
|
||||
#define WHYNTER_HEADER_SPACE 2850
|
||||
#define WHYNTER_BIT_MARK 750
|
||||
#define WHYNTER_ONE_SPACE 2150
|
||||
#define WHYNTER_ZERO_SPACE 750
|
||||
|
||||
//+=============================================================================
|
||||
void IRsend::sendWhynter(unsigned long data, int nbits) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(38);
|
||||
|
||||
// Start
|
||||
mark(WHYNTER_BIT_MARK);
|
||||
space(WHYNTER_ZERO_SPACE);
|
||||
|
||||
// Header
|
||||
mark(WHYNTER_HEADER_MARK);
|
||||
space(WHYNTER_HEADER_SPACE);
|
||||
|
||||
// Data + stop bit
|
||||
sendPulseDistanceWidthData(WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, data, nbits,
|
||||
PROTOCOL_IS_MSB_FIRST,
|
||||
SEND_STOP_BIT);
|
||||
IrReceiver.restartAfterSend();
|
||||
}
|
||||
|
||||
//+=============================================================================
|
||||
bool IRrecv::decodeWhynter() {
|
||||
|
||||
// Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark.
|
||||
if (decodedIRData.rawDataPtr->rawlen != (2 * WHYNTER_BITS) + 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sequence begins with a bit mark and a zero space
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], WHYNTER_BIT_MARK)
|
||||
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], WHYNTER_HEADER_SPACE)) {
|
||||
IR_DEBUG_PRINT(F("Whynter: "));
|
||||
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(WHYNTER_BITS, 3, WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trailing mark / stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * WHYNTER_BITS)], WHYNTER_BIT_MARK)) {
|
||||
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
decodedIRData.numberOfBits = WHYNTER_BITS;
|
||||
decodedIRData.protocol = WHYNTER;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
#endif // _IR_WHYNTER_HPP
|
||||
1566
arduino-libs/arduino-cli/libraries/IRremote/src/private/IRTimer.hpp
Normal file
1566
arduino-libs/arduino-cli/libraries/IRremote/src/private/IRTimer.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user