feat: 全量同步 254 个常用的 Arduino 扩展库文件
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user