Added decodeDistanceWidthData() and therfore changed ir_DistanceProtocol.hpp to ir_DistanceWidthProtocol.hpp and DECODE_DISTANCE to DECODE_DISTANCE_WIDTH.

This commit is contained in:
Armin 2022-11-08 00:36:44 +01:00
parent d51b540cb2
commit fd7f47745d
21 changed files with 750 additions and 357 deletions

View File

@ -18,7 +18,7 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@master
- name: Set up Python
uses: actions/setup-python@v1
with:

View File

@ -96,6 +96,14 @@ Protocols can be switched off and on by defining macros before the line `#includ
- Actively maintained.
- Allows receiving and sending of **raw timing data**.
## New features with version 4.x
- New universal **Pulse Distance Width decoder** added, which covers some previous unknown protocols.
- Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`.
- Support for more than 64 bit data for universal decoder and sender.
# Converting your 3.x program to the 4.x version
- You must replace `#define DECODE_DISTANCE_WIDTH` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder).
## New features with version 3.x
- **Any pin** can be used for sending / receiving.
- Feedback LED can be activated for sending / receiving.

View File

@ -12,7 +12,9 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Support for ATtiny816 - Thanks to elockman.
- Added Bang&Olufsen protocol. #1030.
- 3. parameter of function "void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)" is not optional anymore
and function is now only available if IR_SEND_PIN is not defined. #1033.
and this function is now only available if IR_SEND_PIN is not defined. #1033.
- Added decodeDistanceWidthData() and therfore changed ir_DistanceProtocol.hpp to ir_DistanceWidthProtocol.hpp and DECODE_DISTANCE to DECODE_DISTANCE_WIDTH.
- Fixed bug in sendSony() for command parameter > 0x7F;
## 3.9.0
- Improved documentation with the help of [ElectronicsArchiver}(https://github.com/ElectronicsArchiver).

View File

@ -51,7 +51,7 @@
*/
//#define DECODE_LG
//#define DECODE_NEC
//#define DECODE_DISTANCE
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
// etc. see IRremote.hpp
//

View File

@ -40,8 +40,10 @@
*/
//#define DECODE_LG
//#define DECODE_NEC
//#define DECODE_DISTANCE
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly.
#endif
#if defined(DECODE_BEO)
#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer
#endif

View File

@ -6,6 +6,8 @@
* it sends multiple Samsung32 frames with appropriate delays in between.
* This serves as a Netflix-key emulation for my old Samsung H5273 TV.
*
* Tested on a digispark ATTiny85 board using AttinyCore https://github.com/SpenceKonde/ATTinyCore
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
@ -42,6 +44,51 @@
// USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED
// GND 4| |5 PB0 (0) IR Input
// +----+
/* SAUMSUMG REMOTE CODES (Model: BN59-01180A)
* Power Button - 0x2
* Power Off - 0x98
* 1 - 0x4
* 2 - 0x5
* 3 - 0x6
* 4 - 0x8
* 5 - 0x9
* 6 - 0xa
* 7 - 0xc
* 8 - 0xd
* 9 - 0xe
* CH List - 0x6b
* Vol + - 0x7
* Vol - - 0xb
* Mute - 0xf
* Source - 0x1
* Ch + - 0x12
* Ch - - 0x10
* Menu - 0x1a
* Home - 0x79
* MagicInfo Player - 0x30
* Tools - 0x4b
* Info - 0x1f
* Up arrow - 0x60
* Left arrow - 0x65
* Right arrow - 0x62
* Down arrow - 0x61
* Return - 0x58
* Exit - 0x2d
* A - 0x6c
* B - 0x14
* C - 0x15
* D - 0x16
* Set - 0xab
* Unset - 0xac
* Lock - 0x77
* Stop (square) - 0x46
* Rewind (arrows) - 0x45
* Play (triangle) - 0x47
* Pause (bars) - 0x4a
* Fast Forward (arrows) - 0x48
*/
#include <Arduino.h>
// select only Samsung protocol for sending and receiving

View File

@ -34,7 +34,7 @@
// select only NEC and the universal decoder for pulse distance protocols
#define DECODE_NEC // Includes Apple and Onkyo
#define DECODE_DISTANCE // in case NEC is not received correctly
#define DECODE_DISTANCE_WIDTH // In case NEC is not received correctly. Universal decoder for pulse distance width protocols
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS

View File

@ -51,13 +51,15 @@
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_DISTANCE // universal decoder for pulse distance protocols
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//#define DECODE_HASH // special decoder for all protocols
//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
//#define RAW_BUFFER_LENGTH 180 // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#include <Arduino.h>
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.

View File

@ -66,7 +66,7 @@
#define DECODE_RC6
#define DECODE_SONY
#define DECODE_DISTANCE // universal decoder for pulse distance protocols
#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
#define DECODE_HASH // special decoder for all protocols
#endif
@ -154,6 +154,42 @@ void setup() {
}
void checkReceivedArray(uint32_t *aRawDataArrayPointer, uint8_t aArraySize) {
// wait until signal has received
delay((RECORD_GAP_MICROS / 1000) + 1);
if (IrReceiver.decode()) {
// Print a short summary of received data
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
#else
IrReceiver.printIRResultMinimal(&Serial);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
// We have an unknown protocol, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#endif
if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_DISTANCE_WIDTH) {
for (uint_fast8_t i = 0; i < aArraySize; ++i) {
if (IrReceiver.decodedIRData.decodedRawDataArray[i] != *aRawDataArrayPointer) {
Serial.print(F("ERROR: Received data=0x"));
Serial.print(IrReceiver.decodedIRData.decodedRawDataArray[i], HEX);
Serial.print(F(" != sent data=0x"));
Serial.println(*aRawDataArrayPointer, HEX);
}
aRawDataArrayPointer++;
}
}
IrReceiver.resume();
} else {
Serial.println(F("No data received"));
}
Serial.println();
}
void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
// wait until signal has received
delay((RECORD_GAP_MICROS / 1000) + 1);
@ -179,28 +215,26 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#endif
if (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) {
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("ERROR: Unknown protocol"));
} else {
/*
* Check address
*/
if (IrReceiver.decodedIRData.address != aSentAddress) {
Serial.print(F("ERROR: Received address=0x"));
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(F(" != sent address=0x"));
Serial.println(aSentAddress, HEX);
}
/*
* Check command
*/
if (IrReceiver.decodedIRData.command != aSentCommand) {
Serial.print(F("ERROR: Received command=0x"));
Serial.print(IrReceiver.decodedIRData.command, HEX);
Serial.print(F(" != sent command=0x"));
Serial.println(aSentCommand, HEX);
}
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("ERROR: Unknown protocol"));
} else {
/*
* Check address
*/
if (IrReceiver.decodedIRData.address != aSentAddress) {
Serial.print(F("ERROR: Received address=0x"));
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(F(" != sent address=0x"));
Serial.println(aSentAddress, HEX);
}
/*
* Check command
*/
if (IrReceiver.decodedIRData.command != aSentCommand) {
Serial.print(F("ERROR: Received command=0x"));
Serial.print(IrReceiver.decodedIRData.command, HEX);
Serial.print(F(" != sent command=0x"));
Serial.println(aSentCommand, HEX);
}
}
}
@ -300,7 +334,7 @@ void loop() {
delay(DELAY_AFTER_SEND);
#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants"));
Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants"));
Serial.flush();
uint32_t tRawData[] = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
@ -328,13 +362,60 @@ void loop() {
delay(DELAY_AFTER_SEND);
#endif
Serial.println(F("Send generic 56 bit PulseDistance 0x43D8613C and 0x3BC3BC LSB first"));
#if defined(DISTANCE_DO_MSB_DECODING)
Serial.println(F("Send generic 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first"));
Serial.flush();
uint32_t tRawData1[] = { 0x43D8613C, 0x3BC3BC }; // LSB of tRawData1[0] is sent first
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData1[0], 56, PROTOCOL_IS_LSB_FIRST,
tRawData[0] = 0x43D8613C; // MSB of tRawData[0] is sent first
tRawData[1] = 0x3BC3B;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
checkReceive(0x0, 0x0); // No real check, only printing of received result
checkReceivedArray(tRawData, 2);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send generic 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
checkReceivedArray(tRawData, 2);
delay(DELAY_AFTER_SEND);
#else
Serial.println(F("Send generic 52 bit PulseDistance 0x43D8613C and 0x3BC3B LSB first"));
Serial.flush();
tRawData[0] = 0x43D8613C; // MSB of tRawData[0] is sent first
tRawData[1] = 0x3BC3B;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
checkReceivedArray(tRawData, 2);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send generic 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B LSB first"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
checkReceivedArray(tRawData, 2);
delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_MAGIQUEST)
Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first"));
Serial.flush();
tRawData[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted six right
tRawData[1] = 0x017619; // 19 is the checksum
IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData[0], 55, PROTOCOL_IS_MSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
checkReceive(0xFF00, 0x176);
if (IrReceiver.decodedIRData.decodedRawData != 0x6BCDFF00) {
Serial.print(F("ERROR: Received address=0x"));
Serial.print(IrReceiver.decodedIRData.decodedRawData, HEX);
Serial.println(F(" != sent address=0x6BCDFF00"));
Serial.println();
}
delay(DELAY_AFTER_SEND);
#endif
}
#endif
@ -387,7 +468,7 @@ void loop() {
#if defined(DECODE_SONY)
Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1F, sCommand & 0x7F, sRepeats);
IrSender.sendSony(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
@ -399,7 +480,7 @@ void loop() {
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1FFF, sCommand & 0x7F, sRepeats, SIRCS_20_PROTOCOL);
IrSender.sendSony(sAddress & 0x1FFF, sCommand, sRepeats, SIRCS_20_PROTOCOL);
checkReceive(sAddress & 0x1FFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
#endif

View File

@ -1,6 +1,6 @@
START ../src/UnitTest.cpp from Aug 30 2022
Using library version 3.9.0
Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Whynter, Lego Power Functions, Bosewave , MagiQuest, Pulse Distance, Hash at pin 2
START ../src/UnitTest.cpp from Nov 7 2022
Using library version 4.0.0
Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, Bosewave , MagiQuest, Pulse Distance Width, Hash at pin 2
Ready to send IR signals at pin 3
Send signal mark duration for 38kHz is 8 us, pulse correction is 3000 ns, total period is 26 us
5000 us is the (minimum) gap, after which the start of a new IR packet is assumed
@ -174,30 +174,70 @@ rawData[100]:
+ 450
Sum: 53150
Send generic 56 bit PulseDistance 0x43D8613C and 0x3BC3BC LSB first
Protocol=PulseDistance Raw-Data=0x3BC3BC 56 bits LSB first
Send with:
uint32_t tRawData[]={0x43D8613C, 0x3BC3BC};
IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4450, 600, 1650, 600, 600, &tRawData[0], 56, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, <millisofRepeatPeriod>, <numberOfRepeats>);
rawData[116]:
-1068600
+8850,-4450
+ 500,- 600 + 550,- 600 + 550,-1650 + 600,-1650
+ 550,-1650 + 600,-1650 + 600,- 550 + 600,- 550
+ 600,-1650 + 550,- 600 + 550,- 600 + 550,- 600
+ 550,- 600 + 550,-1650 + 550,-1700 + 600,- 550
+ 600,- 550 + 600,- 550 + 600,- 550 + 550,-1650
+ 600,-1650 + 600,- 550 + 600,-1650 + 550,-1650
+ 600,-1650 + 600,-1650 + 550,- 600 + 550,- 550
+ 600,- 600 + 550,- 600 + 550,-1650 + 600,- 550
+ 550,- 600 + 600,- 600 + 550,-1650 + 600,-1650
+ 550,-1700 + 600,-1650 + 550,- 600 + 550,-1650
+ 550,-1700 + 600,-1600 + 600,- 550 + 600,- 600
+ 550,- 550 + 600,- 600 + 550,-1650 + 550,-1700
+ 600,-1600 + 600,-1650 + 550,- 600 + 600,-1650
+ 600,-1650 + 600,-1650 + 600,- 550 + 550,- 600
Send generic 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first
Protocol=UNKNOWN Hash=0x51DB63E0 54 bits (incl. gap and start) received
rawData[108]:
-1082850
+8850,-4400
+ 600,- 550 + 600,-1650 + 500,- 650 + 550,- 600
+ 550,- 600 + 550,- 600 + 550,-1650 + 600,-1650
+ 600,-1650 + 600,-1650 + 550,- 600 + 550,-1650
+ 600,-1650 + 550,- 600 + 600,- 600 + 550,- 550
+ 600,- 600 + 550,-1650 + 600,-1650 + 600,- 550
+ 600,- 550 + 550,- 600 + 550,- 600 + 550,-1650
+ 550,- 600 + 600,- 600 + 550,-1650 + 550,-1700
+ 600,-1650 + 550,-1700 + 550,- 600 + 550,- 600
+ 600,- 550 + 550,- 600 + 600,-1600 + 600,-1650
+ 550,-1700 + 600,- 550 + 550,-1700 + 550,-1650
+ 600,-1650 + 600,-1650 + 550,- 600 + 600,- 550
+ 600,- 550 + 550,- 750 + 400,-1650 + 550,-1700
+ 600,-1650 + 550,- 600 + 600,-1600 + 600,-1650
+ 550
Sum: 108550
Sum: 101850
Send generic 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first
Protocol=PulseDistanceWidth Raw-Data=0x3BC3B 52 bits MSB first
Send with:
uint32_t tRawData[]={0x43D8613C, 0x3BC3B};
IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 650, 300, 350, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST, SEND_NO_STOP_BIT, <millisofRepeatPeriod>, <numberOfRepeats>);
rawData[106]:
-1079150
+ 350,- 600
+ 300,- 600 + 600,- 300 + 350,- 550 + 350,- 550
+ 350,- 550 + 300,- 600 + 650,- 250 + 650,- 250
+ 650,- 250 + 650,- 250 + 300,- 600 + 650,- 250
+ 650,- 250 + 300,- 600 + 350,- 550 + 350,- 550
+ 350,- 550 + 650,- 250 + 650,- 250 + 350,- 550
+ 300,- 600 + 350,- 550 + 350,- 550 + 600,- 300
+ 350,- 550 + 350,- 600 + 600,- 300 + 600,- 300
+ 600,- 300 + 600,- 300 + 300,- 600 + 300,- 600
+ 350,- 550 + 350,- 550 + 650,- 300 + 600,- 300
+ 600,- 300 + 300,- 600 + 600,- 300 + 600,- 300
+ 600,- 300 + 600,- 300 + 300,- 600 + 300,- 600
+ 300,- 600 + 350,- 550 + 650,- 250 + 650,- 250
+ 650,- 250 + 300,- 600 + 650,- 250 + 650
Sum: 47600
Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first
Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first
Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, <numberOfRepeats>);
rawData[112]:
-1096650
+ 300,- 850 + 300,- 850 + 300,- 850 + 350,- 800
+ 300,- 900 + 250,- 900 + 250,- 900 + 300,- 850
+ 550,- 600 + 550,- 550 + 350,- 800 + 600,- 600
+ 200,- 950 + 550,- 600 + 550,- 600 + 550,- 600
+ 550,- 600 + 250,- 900 + 300,- 850 + 550,- 600
+ 550,- 600 + 300,- 850 + 550,- 600 + 550,- 600
+ 550,- 600 + 550,- 600 + 550,- 600 + 550,- 600
+ 550,- 600 + 550,- 600 + 550,- 600 + 300,- 800
+ 350,- 850 + 300,- 850 + 300,- 850 + 300,- 850
+ 300,- 850 + 300,- 850 + 300,- 850 + 550,- 600
+ 300,- 850 + 550,- 600 + 550,- 600 + 550,- 600
+ 300,- 850 + 550,- 600 + 550,- 600 + 250,- 900
+ 250,- 900 + 300,- 900 + 250,- 850 + 550,- 600
+ 600,- 550 + 300,- 900 + 250,- 850 + 550
Sum: 63850
Send Onkyo (NEC with 16 bit command)
Protocol=Onkyo Address=0xFFF1 Command=0x7676 Raw-Data=0x7676FFF1 32 bits LSB first

View File

@ -39,10 +39,11 @@
*/
typedef enum {
UNKNOWN = 0,
#if defined(SUPPORT_PULSE_WIDTH_DECODING) // The only known pulse width protocol is Sony
#if defined(SUPPORT_PULSE_WIDTH_DECODING) // The only known pulse width protocol is Sony and this is decoded by the sony decoder
PULSE_WIDTH,
#endif
PULSE_DISTANCE,
PULSE_DISTANCE_WIDTH,
APPLE,
DENON,
JVC,
@ -75,6 +76,7 @@ typedef enum {
const char string_Unknown[] PROGMEM = "UNKNOWN";
const char string_PulseWidth[] PROGMEM = "PulseWidth";
const char string_PulseDistance[] PROGMEM = "PulseDistance";
const char string_PulseDistanceWidth[] PROGMEM = "PulseDistanceWidth";
const char string_Apple[] PROGMEM = "Apple";
const char string_Denon[] PROGMEM = "Denon";
const char string_JVC[] PROGMEM = "JVC";

View File

@ -33,6 +33,12 @@
#ifndef _IR_RECEIVE_HPP
#define _IR_RECEIVE_HPP
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
/** \addtogroup Receiving Receiving IR data for multiple protocols
* @{
*/
@ -216,7 +222,11 @@ void IRrecv::initDecodedIRData() {
irparams.OverflowFlag = false;
irparams.rawlen = 0; // otherwise we have OverflowFlag again at next ISR call
decodedIRData.flags = IRDATA_FLAGS_WAS_OVERFLOW;
IR_DEBUG_PRINTLN(F("Overflow happened"));
#if defined(LOCAL_DEBUG)
Serial.print(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of "));
Serial.print(RAW_BUFFER_LENGTH);
Serial.println(F(" with #define RAW_BUFFER_LENGTH=<biggerValue>"));
#endif
} else {
decodedIRData.flags = IRDATA_FLAGS_EMPTY;
@ -378,8 +388,8 @@ bool IRrecv::decode() {
/*
* Try the universal decoder for pulse distance protocols
*/
#if defined(DECODE_DISTANCE)
IR_TRACE_PRINTLN(F("Attempting universal Distance decode"));
#if defined(DECODE_DISTANCE_WIDTH)
IR_TRACE_PRINTLN(F("Attempting universal Distance Width decode"));
if (decodeDistance()) {
return true;
}
@ -426,79 +436,96 @@ bool IRrecv::decodePulseWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStar
if (aMSBfirst) {
/*
* MSB first is currently optimized out by the compiler, since it is never used.
* MSB first is currently optimized out by the compiler, since it is never used :-).
*/
for (uint_fast8_t i = 0; i < aNumberOfBits; i++) {
unsigned int tMarkTicks = *tRawBufPointer++;
// Check for variable length mark indicating a 0 or 1
if (matchMark(*tRawBufPointer, aOneMarkMicros)) {
if (matchMark(tMarkTicks, aOneMarkMicros)) {
tDecodedData = (tDecodedData << 1) | 1;
IR_TRACE_PRINT('1');
} else if (matchMark(*tRawBufPointer, aZeroMarkMicros)) {
} else if (matchMark(tMarkTicks, aZeroMarkMicros)) {
tDecodedData = (tDecodedData << 1) | 0;
IR_TRACE_PRINT('0');
} else {
IR_DEBUG_PRINT(F("Mark="));
IR_DEBUG_PRINT(*tRawBufPointer * MICROS_PER_TICK);
IR_DEBUG_PRINT(F(" is not "));
IR_DEBUG_PRINT(aOneMarkMicros);
IR_DEBUG_PRINT(F(" or "));
IR_DEBUG_PRINT(aZeroMarkMicros);
IR_DEBUG_PRINT(' ');
#if defined(LOCAL_DEBUG)
Serial.print(F("Mark="));
Serial.print(tMarkTicks * MICROS_PER_TICK);
Serial.print(F(" is not "));
Serial.print(aOneMarkMicros);
Serial.print(F(" or "));
Serial.print(aZeroMarkMicros);
Serial.print(F(". Index="));
Serial.print(i);
Serial.print(' ');
#endif
return false;
}
tRawBufPointer++;
// If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it
if (tRawBufPointer < &decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen]) {
// Check for constant length space
if (!matchSpace(*tRawBufPointer, aBitSpaceMicros)) {
IR_DEBUG_PRINT(F("Space="));
IR_DEBUG_PRINT(*tRawBufPointer * MICROS_PER_TICK);
IR_DEBUG_PRINT(F(" is not "));
IR_DEBUG_PRINT(aBitSpaceMicros);
IR_DEBUG_PRINT(' ');
unsigned int tSpaceTicks = *tRawBufPointer++;
if (!matchSpace(tSpaceTicks, aBitSpaceMicros)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Space="));
Serial.print(tSpaceTicks * MICROS_PER_TICK);
Serial.print(F(" is not "));
Serial.print(aBitSpaceMicros);
Serial.print(F(". Index="));
Serial.print(i);
Serial.print(' ');
#endif
return false;
}
tRawBufPointer++;
}
}
IR_TRACE_PRINTLN(F(""));
} else {
// LSB first
for (uint32_t tMask = 1UL; aNumberOfBits > 0; tMask <<= 1, aNumberOfBits--) {
uint32_t tMask = 1UL;
for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
// Check for variable length mark indicating a 0 or 1
if (matchMark(*tRawBufPointer, aOneMarkMicros)) {
unsigned int tMarkTicks = *tRawBufPointer++;
if (matchMark(tMarkTicks, aOneMarkMicros)) {
tDecodedData |= tMask; // set the bit
IR_TRACE_PRINT('1');
} else if (matchMark(*tRawBufPointer, aZeroMarkMicros)) {
} else if (matchMark(tMarkTicks, aZeroMarkMicros)) {
// do not set the bit
IR_TRACE_PRINT('0');
} else {
IR_DEBUG_PRINT(F("Mark="));
IR_DEBUG_PRINT(*tRawBufPointer * MICROS_PER_TICK);
IR_DEBUG_PRINT(F(" is not "));
IR_DEBUG_PRINT(aOneMarkMicros);
IR_DEBUG_PRINT(F(" or "));
IR_DEBUG_PRINT(aZeroMarkMicros);
IR_DEBUG_PRINT(' ');
#if defined(LOCAL_DEBUG)
Serial.print(F("Mark="));
Serial.print(tMarkTicks * MICROS_PER_TICK);
Serial.print(F(" is not "));
Serial.print(aOneMarkMicros);
Serial.print(F(" or "));
Serial.print(aZeroMarkMicros);
Serial.print(F(". Index="));
Serial.print(aNumberOfBits - i);
Serial.print(' ');
#endif
return false;
}
tRawBufPointer++;
// If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it
if (tRawBufPointer < &decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen]) {
// Check for constant length space here
if (!matchSpace(*tRawBufPointer, aBitSpaceMicros)) {
IR_DEBUG_PRINT(F("Space="));
IR_DEBUG_PRINT(*tRawBufPointer * MICROS_PER_TICK);
IR_DEBUG_PRINT(F(" is not "));
IR_DEBUG_PRINT(aBitSpaceMicros);
IR_DEBUG_PRINT(' ');
unsigned int tSpaceTicks = *tRawBufPointer++;
if (!matchSpace(tSpaceTicks, aBitSpaceMicros)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Space="));
Serial.print(tSpaceTicks * MICROS_PER_TICK);
Serial.print(F(" is not "));
Serial.print(aBitSpaceMicros);
Serial.print(F(". Index="));
Serial.print(aNumberOfBits - i);
Serial.print(' ');
#endif
return false;
}
tRawBufPointer++;
}
tMask <<= 1;
}
IR_TRACE_PRINTLN(F(""));
}
@ -507,15 +534,7 @@ bool IRrecv::decodePulseWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStar
}
/**
* Decode pulse distance protocols.
* The mark (pulse) has constant length, the length of the space determines the bit value.
* Each bit looks like: MARK + SPACE_1 -> 1
* or : MARK + SPACE_0 -> 0
*
* Input is IrReceiver.decodedIRData.rawDataPtr->rawbuf[]
* Output is IrReceiver.decodedIRData.decodedRawData
*
* @param aStartOffset must point to a mark
* Decode pulse distance protocols for PulsePauseWidthProtocolConstants.
* @return true if decoding was successful
*/
bool IRrecv::decodePulseDistanceData(PulsePauseWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
@ -546,21 +565,26 @@ bool IRrecv::decodePulseDistanceData(uint_fast8_t aNumberOfBits, uint_fast8_t aS
uint32_t tMask = 1UL;
for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
// Check for constant length mark
if (!matchMark(*tRawBufPointer, aBitMarkMicros)) {
IR_DEBUG_PRINT(F("Mark="));
IR_DEBUG_PRINT(*tRawBufPointer * MICROS_PER_TICK);
IR_DEBUG_PRINT(F(" is not "));
IR_DEBUG_PRINT(aBitMarkMicros);
IR_DEBUG_PRINT(' ');
unsigned int tMarkTicks = *tRawBufPointer++;
if (!matchMark(tMarkTicks, aBitMarkMicros)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Mark="));
Serial.print(tMarkTicks * MICROS_PER_TICK);
Serial.print(F(" is not "));
Serial.print(aBitMarkMicros);
Serial.print(F(". Index="));
Serial.print(aNumberOfBits - i);
Serial.print(' ');
#endif
return false;
}
tRawBufPointer++;
if (aMSBfirst) {
tDecodedData <<= 1;
}
// Check for variable length space indicating a 0 or 1
if (matchSpace(*tRawBufPointer, aOneSpaceMicros)) {
unsigned int tSpaceTicks = *tRawBufPointer++;
if (matchSpace(tSpaceTicks, aOneSpaceMicros)) {
// set the bit
if (aMSBfirst) {
tDecodedData |= 1;
@ -568,20 +592,23 @@ bool IRrecv::decodePulseDistanceData(uint_fast8_t aNumberOfBits, uint_fast8_t aS
tDecodedData |= tMask;
}
IR_TRACE_PRINT('1');
} else if (matchSpace(*tRawBufPointer, aZeroSpaceMicros)) {
} else if (matchSpace(tSpaceTicks, aZeroSpaceMicros)) {
// do not set the bit
IR_TRACE_PRINT('0');
} else {
IR_DEBUG_PRINT(F("Space="));
IR_DEBUG_PRINT(*tRawBufPointer * MICROS_PER_TICK);
IR_DEBUG_PRINT(F(" is not "));
IR_DEBUG_PRINT(aOneSpaceMicros);
IR_DEBUG_PRINT(F(" or "));
IR_DEBUG_PRINT(aZeroSpaceMicros);
IR_DEBUG_PRINT(' ');
#if defined(LOCAL_DEBUG)
Serial.print(F("Space="));
Serial.print(tSpaceTicks * MICROS_PER_TICK);
Serial.print(F(" is not "));
Serial.print(aOneSpaceMicros);
Serial.print(F(" or "));
Serial.print(aZeroSpaceMicros);
Serial.print(F(". Index="));
Serial.print(aNumberOfBits - i);
Serial.print(' ');
#endif
return false;
}
tRawBufPointer++;
tMask <<= 1;
}
IR_TRACE_PRINTLN(F(""));
@ -590,6 +617,77 @@ bool IRrecv::decodePulseDistanceData(uint_fast8_t aNumberOfBits, uint_fast8_t aS
return true;
}
/**
* Decode pulse distance width protocols like MagiQuest.
* Assume, that the sum of mark (pulse) and space has constant length, the length of the mark (or space) determines the bit value.
* Therefore we only require the timing of the mark for the one.
*
* Input is IrReceiver.decodedIRData.rawDataPtr->rawbuf[]
* Output is IrReceiver.decodedIRData.decodedRawData
*
* @param aStartOffset must point to a mark
* @return true if decoding was successful
*/
bool IRrecv::decodeDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
unsigned int aBitPeriodMicros, bool aMSBfirst) {
unsigned int *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
uint32_t tDecodedData = 0;
IR_TRACE_PRINT(F("DistanceWidt StartOffset="));
IR_TRACE_PRINT(aStartOffset);
IR_TRACE_PRINT(F(" NumberOfBits="));
IR_TRACE_PRINTLN(aNumberOfBits);
uint32_t tMask = 1UL;
for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
// get one mark and space pair
unsigned int tMarkTicks = *tRawBufPointer++;
unsigned int tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
IR_TRACE_PRINT(F("Mark="));
IR_TRACE_PRINT(tMarkTicks * MICROS_PER_TICK);
IR_TRACE_PRINT(F(" space="));
IR_TRACE_PRINTLN(tSpaceTicks * MICROS_PER_TICK);
// Check for constant period but not for last bit
if (i != 1 && !matchMark(tMarkTicks + tSpaceTicks, aBitPeriodMicros)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Mark="));
Serial.print(tMarkTicks * MICROS_PER_TICK);
Serial.print(F(" + space="));
Serial.print(tSpaceTicks * MICROS_PER_TICK);
Serial.print(F(" match not "));
Serial.print(aBitPeriodMicros);
Serial.print(F(". Index="));
Serial.print(aNumberOfBits - i);
Serial.print(' ');
#endif
return false;
}
if (aMSBfirst) {
tDecodedData <<= 1;
}
if (matchMark(tMarkTicks, aOneMarkMicros)) {
// It's a 1 -> set the bit
if (aMSBfirst) {
tDecodedData |= 1;
} else {
tDecodedData |= tMask;
}
IR_TRACE_PRINTLN('1');
} else {
// do not set the bit
IR_TRACE_PRINTLN('0');
}
tMask <<= 1;
}
decodedIRData.decodedRawData = tDecodedData;
return true;
}
/*
* Static variables for the getBiphaselevel function
*/
@ -760,13 +858,17 @@ bool IRrecv::decodeHashOld(decode_results *aResults) {
bool IRrecv::checkHeader(PulsePauseWidthProtocolConstants *aProtocolConstants) {
// Check header "mark" and "space"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], aProtocolConstants->HeaderMarkMicros)) {
IR_DEBUG_PRINT(::getProtocolString(aProtocolConstants->ProtocolIndex));
IR_DEBUG_PRINTLN(F(": Header mark length is wrong"));
#if defined(TRACE)
Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
Serial.println(F(": Header mark length is wrong"));
#endif
return false;
}
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], aProtocolConstants->HeaderSpaceMicros)) {
IR_DEBUG_PRINT(::getProtocolString(aProtocolConstants->ProtocolIndex));
IR_DEBUG_PRINTLN(F(": Header space length is wrong"));
#if defined(TRACE)
Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
Serial.println(F(": Header space length is wrong"));
#endif
return false;
}
return true;
@ -795,9 +897,9 @@ bool matchTicks(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
#if defined(TRACE)
if (passed) {
Serial.println(F("?; passed"));
Serial.println(F(" => passed"));
} else {
Serial.println(F("?; FAILED"));
Serial.println(F(" => FAILED"));
}
#endif
return passed;
@ -823,14 +925,14 @@ bool matchMark(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
Serial.print(F(" <= "));
Serial.print(TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
#endif
// compensate for marks exceeded by demodulator hardware
// compensate for marks exceeded by demodulator hardware
bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS))
&& (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS)));
#if defined(TRACE)
if (passed) {
Serial.println(F("?; passed"));
Serial.println(F(" => passed"));
} else {
Serial.println(F("?; FAILED"));
Serial.println(F(" => FAILED"));
}
#endif
return passed;
@ -856,14 +958,14 @@ bool matchSpace(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
Serial.print(F(" <= "));
Serial.print(TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
#endif
// compensate for spaces shortened by demodulator hardware
// compensate for spaces shortened by demodulator hardware
bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS))
&& (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS)));
#if defined(TRACE)
if (passed) {
Serial.println(F("?; passed"));
Serial.println(F(" => passed"));
} else {
Serial.println(F("?; FAILED"));
Serial.println(F(" => FAILED"));
}
#endif
return passed;
@ -956,11 +1058,11 @@ void printActiveIRProtocols(Print *aSerial) {
#if defined(DECODE_MAGIQUEST)
aSerial->print(F("MagiQuest, "));
#endif
#if defined(DECODE_DISTANCE)
#if defined(DECODE_DISTANCE_WIDTH)
# if defined(SUPPORT_PULSE_WIDTH_DECODING) // The only known pulse width protocol is Sony
aSerial->print(F("Universal Distance, "));
aSerial->print(F("Universal Pulse Distance Width, "));
# else
aSerial->print(F("Pulse Distance, "));
aSerial->print(F("Pulse Distance Width, "));
# endif
#endif
#if defined(DECODE_HASH)
@ -1002,8 +1104,8 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap
aSerial->print((aIRDataPtr->rawDataPtr->rawlen + 1) / 2, DEC);
aSerial->println(F(" bits (incl. gap and start) received"));
} else {
#if defined(DECODE_DISTANCE)
if(aIRDataPtr->protocol != PULSE_DISTANCE) {
#if defined(DECODE_DISTANCE_WIDTH)
if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_DISTANCE_WIDTH) {
#endif
/*
* New decoders have address and command
@ -1030,7 +1132,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap
aSerial->print(F(" Toggle=1"));
}
}
#if defined(DECODE_DISTANCE)
#if defined(DECODE_DISTANCE_WIDTH)
}
#endif
if (aIRDataPtr->flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) {
@ -1087,9 +1189,9 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
void printIRSendUsage(Print *aSerial, IRData *aIRDataPtr) {
if (aIRDataPtr->protocol != UNKNOWN && (aIRDataPtr->flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00) {
#if defined(DECODE_DISTANCE)
#if defined(DECODE_DISTANCE_WIDTH)
aSerial->print(F("Send with:"));
if (aIRDataPtr->protocol == PULSE_DISTANCE) {
if (aIRDataPtr->protocol == PULSE_DISTANCE || aIRDataPtr->protocol == PULSE_DISTANCE_WIDTH) {
aSerial->println();
aSerial->print(F(" uint32_t tRawData[]={0x"));
uint_fast8_t tNumberOf32BitChunks = ((aIRDataPtr->numberOfBits - 1) / 32) + 1;
@ -1107,54 +1209,69 @@ void printIRSendUsage(Print *aSerial, IRData *aIRDataPtr) {
aSerial->print(F("Send with: IrSender.send"));
#endif
#if defined(DECODE_DISTANCE)
if (aIRDataPtr->protocol != PULSE_DISTANCE) {
#if defined(DECODE_DISTANCE_WIDTH)
if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_DISTANCE_WIDTH) {
#endif
aSerial->print(getProtocolString(aIRDataPtr->protocol));
aSerial->print(F("(0x"));
aSerial->print(getProtocolString(aIRDataPtr->protocol));
aSerial->print(F("(0x"));
#if defined(DECODE_MAGIQUEST)
if (aIRDataPtr->protocol == MAGIQUEST) {
aSerial->print(aIRDataPtr->decodedRawData, HEX);
} else {
aSerial->print(aIRDataPtr->address, HEX);
}
#else
/*
* New decoders have address and command
*/
if (aIRDataPtr->protocol == MAGIQUEST) {
aSerial->print(aIRDataPtr->decodedRawData, HEX);
} else {
aSerial->print(aIRDataPtr->address, HEX);
}
#else
/*
* New decoders have address and command
*/
aSerial->print(aIRDataPtr->address, HEX);
#endif
aSerial->print(F(", 0x"));
aSerial->print(aIRDataPtr->command, HEX);
aSerial->print(F(", <numberOfRepeats>"));
aSerial->print(F(", 0x"));
aSerial->print(aIRDataPtr->command, HEX);
aSerial->print(F(", <numberOfRepeats>"));
if (aIRDataPtr->flags & IRDATA_FLAGS_EXTRA_INFO) {
aSerial->print(F(", 0x"));
aSerial->print(aIRDataPtr->extra, HEX);
}
#if defined(DECODE_DISTANCE)
if (aIRDataPtr->flags & IRDATA_FLAGS_EXTRA_INFO) {
aSerial->print(F(", 0x"));
aSerial->print(aIRDataPtr->extra, HEX);
}
#if defined(DECODE_DISTANCE_WIDTH)
} else {
aSerial->print("PulseDistanceWidthFromArray(38, ");
aSerial->print((aIRDataPtr->extra >> 8) * MICROS_PER_TICK); // aHeaderMarkMicros
aSerial->print(F(", "));
aSerial->print((aIRDataPtr->extra & 0xFF) * MICROS_PER_TICK); // aHeaderSpaceMicros
aSerial->print((aIRDataPtr->extra & 0xFF) * MICROS_PER_TICK);// aHeaderSpaceMicros
aSerial->print(F(", "));
aSerial->print((aIRDataPtr->address >> 8) * MICROS_PER_TICK); // aOneMarkMicros
// address = tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << 8) | tSpaceTicksLong
// command = tMarkTicksShort << 8) | tSpaceTicksShort
aSerial->print((aIRDataPtr->address >> 8) * MICROS_PER_TICK);// aOneMarkMicros
aSerial->print(F(", "));
aSerial->print((aIRDataPtr->address & 0xFF) * MICROS_PER_TICK); // aOneSpaceMicros
if (aIRDataPtr->protocol == PULSE_DISTANCE) {
aSerial->print((aIRDataPtr->address & 0xFF) * MICROS_PER_TICK);// aOneSpaceMicros
} else {
aSerial->print((aIRDataPtr->command & 0xFF) * MICROS_PER_TICK);// aOneSpaceMicros
}
aSerial->print(F(", "));
aSerial->print((aIRDataPtr->command >> 8) * MICROS_PER_TICK); // aZeroMarkMicros
aSerial->print((aIRDataPtr->command >> 8) * MICROS_PER_TICK);// aZeroMarkMicros
aSerial->print(F(", "));
aSerial->print((aIRDataPtr->command & 0xFF) * MICROS_PER_TICK); // aZeroSpaceMicros
if (aIRDataPtr->protocol == PULSE_DISTANCE) {
aSerial->print((aIRDataPtr->command & 0xFF) * MICROS_PER_TICK);// aZeroSpaceMicros
}else {
aSerial->print((aIRDataPtr->address & 0xFF) * MICROS_PER_TICK);// aZeroSpaceMicros
}
aSerial->print(F(", &tRawData[0], "));
aSerial->print(aIRDataPtr->numberOfBits); // aNumberOfBits
#if defined(DISTANCE_DO_MSB_DECODING)
aSerial->print(F(", PROTOCOL_IS_MSB_FIRST"));
#else
aSerial->print(F(", PROTOCOL_IS_LSB_FIRST"));
#endif
aSerial->print(F(", SEND_STOP_BIT"));
aSerial->print(aIRDataPtr->numberOfBits);// aNumberOfBits
if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
aSerial->print(F(", PROTOCOL_IS_MSB_FIRST"));
} else {
aSerial->print(F(", PROTOCOL_IS_LSB_FIRST"));
}
if (aIRDataPtr->protocol == PULSE_DISTANCE) {
aSerial->print(F(", SEND_STOP_BIT"));
} else {
aSerial->print(F(", SEND_NO_STOP_BIT")); // assume no stop bit like for Magiquest.
}
aSerial->print(F(", <millisofRepeatPeriod>, <numberOfRepeats>"));
}
#endif
@ -1222,7 +1339,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
unsigned int i;
#endif
// Newline is printed every 8. value, if tCounterForNewline % 8 == 0
@ -1237,7 +1354,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
#if defined(DECODE_MAGIQUEST)
decodedIRData.protocol == MAGIQUEST ||
#endif
false) {
false) {
tCounterForNewline = 0; // no or 8 start bits
}
#endif
@ -1316,7 +1433,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
unsigned int i;
#endif
for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
@ -1367,7 +1484,7 @@ void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) {
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
unsigned int i;
#endif
for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
@ -1416,41 +1533,19 @@ void IRrecv::printIRResultAsCVariables(Print *aSerial) {
/*
* !!Must be the same order as in decode_type_t in IRProtocol.h!!!
*/
const char * const ProtocolNames[] PROGMEM =
{
string_Unknown,
const char *const ProtocolNames[]
PROGMEM = { string_Unknown,
#if defined(SUPPORT_PULSE_WIDTH_DECODING) // The only known pulse width protocol is Sony
string_PulseWidth,
#endif
string_PulseDistance,
string_Apple,
string_Denon,
string_JVC,
string_LG,
string_LG2,
string_NEC,
string_NEC2,
string_Onkyo,
string_Panasonic,
string_Kaseikyo,
string_Kaseikyo_Denon,
string_Kaseikyo_Sharp,
string_Kaseikyo_JVC,
string_Kaseikyo_Mitsubishi,
string_RC5,
string_RC6,
string_Samsung,
string_SamsungLG,
string_Sharp,
string_Sony
string_PulseDistance, string_PulseDistanceWidth, string_Apple, string_Denon, string_JVC, string_LG, string_LG2, string_NEC,
string_NEC2, string_Onkyo, string_Panasonic, string_Kaseikyo, string_Kaseikyo_Denon, string_Kaseikyo_Sharp,
string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_SamsungLG, string_Sharp,
string_Sony
#if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
, string_BangOlufsen,
string_BoseWave,
string_Lego,
string_MagiQuest,
string_Whynter
, string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter
#endif
};
};
#if defined(__AVR__)
const __FlashStringHelper* IRrecv::getProtocolString() {
@ -1459,12 +1554,12 @@ const __FlashStringHelper* IRrecv::getProtocolString() {
}
const __FlashStringHelper* getProtocolString(decode_type_t aProtocol) {
const char* tProtocolStringPtr = (char*) pgm_read_word(&ProtocolNames[aProtocol]);
return((__FlashStringHelper *) (tProtocolStringPtr));
const char *tProtocolStringPtr = (char*) pgm_read_word(&ProtocolNames[aProtocol]);
return ((__FlashStringHelper*) (tProtocolStringPtr));
}
#else
const char* IRrecv::getProtocolString() {
// call no class function with same name
// call no class function with same name
return ::getProtocolString(decodedIRData.protocol);
}
@ -1494,9 +1589,10 @@ const char* getProtocolString(decode_type_t aProtocol) {
//#define _IR_MEASURE_TIMING
//#define _IR_TIMING_TEST_PIN 7 // do not forget to execute: "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" if activated by line above
#if defined(TIMER_INTR_NAME)
ISR (TIMER_INTR_NAME) // for ISR definitions
ISR (TIMER_INTR_NAME) // for ISR definitions
#else
ISR () // for functions definitions which are called by separate (board specific) ISR
ISR()
// for functions definitions which are called by separate (board specific) ISR
#endif
{
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
@ -1608,13 +1704,13 @@ ISR () // for functions definitions which are called by separate (board specific
uint8_t bitreverseOneByte(uint8_t aValue) {
// uint8_t tReversedValue;
// return __builtin_avr_insert_bits(0x01234567, aValue, tReversedValue);
// 76543210
// 76543210
aValue = (aValue >> 4) | (aValue << 4); // Swap in groups of 4
// 32107654
// 32107654
aValue = ((aValue & 0xcc) >> 2) | ((aValue & 0x33) << 2); // Swap in groups of 2
// 10325476
// 10325476
aValue = ((aValue & 0xaa) >> 1) | ((aValue & 0x55) << 1); // Swap bit pairs
// 01234567
// 01234567
return aValue;
}
@ -1666,14 +1762,14 @@ bool IRrecv::decode(decode_results *aResults) {
#if defined(DECODE_NEC)
IR_DEBUG_PRINTLN(F("Attempting old NEC decode"));
if (decodeNECMSB(aResults)) {
return true ;
return true;
}
#endif
#if defined(DECODE_SONY)
IR_DEBUG_PRINTLN(F("Attempting old Sony decode"));
if (decodeSonyMSB(aResults)) {
return true ;
if (decodeSonyMSB(aResults)) {
return true;
}
#endif
@ -1684,17 +1780,17 @@ bool IRrecv::decode(decode_results *aResults) {
aResults->value = decodedIRData.decodedRawData;
aResults->decode_type = RC5;
return true ;
return true;
}
#endif
#if defined(DECODE_RC6)
IR_DEBUG_PRINTLN(F("Attempting RC6 decode"));
if (decodeRC6()) {
if (decodeRC6()) {
aResults->bits = decodedIRData.numberOfBits;
aResults->value = decodedIRData.decodedRawData;
aResults->decode_type = RC6;
return true ;
return true;
}
#endif
@ -1702,27 +1798,27 @@ bool IRrecv::decode(decode_results *aResults) {
#if defined(DECODE_LG)
IR_DEBUG_PRINTLN(F("Attempting old LG decode"));
if (decodeLGMSB(aResults)) { return true ;}
if (decodeLGMSB(aResults)) {return true;}
#endif
#if defined(DECODE_JVC)
IR_DEBUG_PRINTLN(F("Attempting old JVC decode"));
if (decodeJVCMSB(aResults)) {
return true ;
return true;
}
#endif
#if defined(DECODE_SAMSUNG)
IR_DEBUG_PRINTLN(F("Attempting old SAMSUNG decode"));
if (decodeSAMSUNG(aResults)) {
return true ;
return true;
}
#endif
#if defined(DECODE_DENON)
IR_DEBUG_PRINTLN(F("Attempting old Denon decode"));
if (decodeDenonOld(aResults)) {
return true ;
return true;
}
#endif
@ -1738,4 +1834,7 @@ bool IRrecv::decode(decode_results *aResults) {
}
/** @}*/
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _IR_RECEIVE_HPP

View File

@ -32,6 +32,12 @@
#ifndef _IR_SEND_HPP
#define _IR_SEND_HPP
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#else
#define LOCAL_DEBUG // This enables debug output only for this file
#endif
/*
* This improves readability of code by avoiding a lot of #if defined clauses
*/
@ -368,6 +374,19 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigne
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
uint_fast8_t tNumberOf32BitChunks = ((aNumberOfBits - 1) / 32) + 1;
#if defined(LOCAL_DEBUG)
// fist data
Serial.print(F("Data[0]=0x"));
Serial.print(aDecodedRawDataArray[0], HEX);
if (tNumberOf32BitChunks > 1) {
Serial.print(F(" Data[1]=0x"));
Serial.print(aDecodedRawDataArray[1], HEX);
}
Serial.print(F(" #="));
Serial.println(aNumberOfBits);
Serial.flush();
#endif
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
@ -377,25 +396,24 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigne
for (uint_fast8_t i = 0; i < tNumberOf32BitChunks; ++i) {
uint8_t tNumberOfBitsForOneSend;
bool tSendStopBit;
if (aNumberOfBits > 32) {
tNumberOfBitsForOneSend = 32;
} else {
tNumberOfBitsForOneSend = aNumberOfBits;
}
// Manage stop bit
bool tSendStopBit;
if (i == (tNumberOf32BitChunks - 1)) {
// End of data
tNumberOfBitsForOneSend = aNumberOfBits;
tSendStopBit = aSendStopBit;
} else {
// intermediate data
tNumberOfBitsForOneSend = 32;
tSendStopBit = false;
}
sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray[i],
tNumberOfBitsForOneSend, aMSBFirst, tSendStopBit);
aNumberOfBits -= 32;
}
@ -415,7 +433,7 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigne
}
/**
* Sends PulseDistance data from array
* Sends PulseDistance data from array using PulsePauseWidthProtocolConstants
* For LSB First the LSB of array[0] is sent first then all bits until MSB of array[0]. Next is LSB of array[1] and so on.
* The output always ends with a space
* Stop bit is always sent
@ -585,6 +603,13 @@ void IRsend::sendPulseDistanceWidthData(PulsePauseWidthProtocolConstants *aProto
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 defined(LOCAL_DEBUG)
// Even printing this short messages (at 115200) disturbs the send timing :-(
// Serial.print(aData, HEX);
// Serial.print('|');
// Serial.println(aNumberOfBits);
#endif
// if (aMSBFirst) { // Send the MSB first.
// For MSBFirst, send data from MSB to LSB until mask bit is shifted out
uint32_t tMask = 1UL << (aNumberOfBits - 1);
@ -901,4 +926,7 @@ unsigned int IRsend::getPulseCorrectionNanos() {
}
/** @}*/
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _IR_SEND_HPP

View File

@ -98,7 +98,7 @@
# 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_DISTANCE_WIDTH) || defined(DECODE_HASH) || defined(DECODE_BOSEWAVE) \
|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_WHYNTER)))
/*
* If no protocol is explicitly enabled, we enable all protocols
@ -122,7 +122,7 @@
# 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_DISTANCE_WIDTH // universal decoder for pulse distance width 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
@ -324,8 +324,8 @@
#include "ir_Sony.hpp"
#include "ir_Others.hpp"
#include "ir_Pronto.hpp" // pronto is an universal decoder and encoder
# if defined(DECODE_DISTANCE) // universal decoder for pulse distance protocols - requires up to 750 bytes additional program memory
#include "ir_DistanceProtocol.hpp"
# if defined(DECODE_DISTANCE_WIDTH) // universal decoder for pulse distance width protocols - requires up to 750 bytes additional program memory
#include <ir_DistanceWidthProtocol.hpp>
# endif
#endif // #if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)

View File

@ -148,16 +148,16 @@ struct irparams_struct {
*/
struct IRData {
decode_type_t protocol; ///< UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
uint16_t address; ///< Decoded address, Distance protocol (OneMarkTicks << 8) | OneSpaceTicks
uint16_t command; ///< Decoded command, Distance protocol (ZeroMarkTicks << 8) | ZeroSpaceTicks
uint16_t address; ///< Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << 8) | tSpaceTicksLong
uint16_t command; ///< Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort
uint16_t extra; ///< Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMarkTicks << 8) | HeaderSpaceTicks.
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.
#if defined(DECODE_DISTANCE)
#if defined(DECODE_DISTANCE_WIDTH)
uint32_t decodedRawDataArray[RAW_DATA_ARRAY_SIZE]; ///< 32 bit decoded raw data, to be used for send function.
#endif
irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by receiving ISR.
};
/**
@ -254,6 +254,9 @@ public:
bool decodePulseWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
unsigned int aZeroMarkMicros, unsigned int aBitSpaceMicros, bool aMSBfirst);
bool decodeDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
unsigned int aBitPeriodMicros, bool aMSBfirst);
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount,
uint_fast8_t aValueOfSpaceToMarkTransition, unsigned int aBiphaseTimeUnit);

View File

@ -310,10 +310,11 @@ bool isTinyReceiverIdle() {
}
/**
* Sets IR_INPUT_PIN mode to INPUT_PULLUP, if required, sets feedback LED output mode and call enablePCIInterruptForTinyReceiver()
* Sets IR_INPUT_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode.
* Then call enablePCIInterruptForTinyReceiver()
*/
bool initPCIInterruptForTinyReceiver() {
pinModeFast(IR_INPUT_PIN, INPUT_PULLUP);
pinModeFast(IR_INPUT_PIN, INPUT);
#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);

View File

@ -1,28 +1,37 @@
/*
* ir_DistanceProtocol.hpp
* ir_DistanceWidthProtocol.hpp
*
* Contains only the decoder functions!
*
* This decoder tries to decode a pulse width or pulse distance protocol.
* This decoder tries to decode a pulse distance or pulse distance width with constant period (or pulse width - not enabled yet) protocol.
* 1. Analyze all space and mark length
* 2. Decide if we have an pulse width or distance protocol
* 2. Decide which protocol we have
* 3. Try to decode with the mark and space data found in step 1
* 4. Assume one start bit / header and one stop bit, since pulse distance data must have a stop bit!
* No data and address decoding, only raw data as result.
*
* Pulse distance data can be sent with the generic function:
* Pulse distance data can be sent with the generic function as in SendDemo example line 155:
* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/d51b540cb2ddf1424888d2d9e6b62fe1ef46859d/examples/SendDemo/SendDemo.ino#L155
* 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
*
* Or send it by filling a DecodedRawDataArray and with the sendPulseDistanceWidthFromArray() function as in SendDemo example line 175:
* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/d51b540cb2ddf1424888d2d9e6b62fe1ef46859d/examples/SendDemo/SendDemo.ino#L175
* sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros,
* unsigned int aHeaderSpaceMicros, unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
* unsigned int aZeroSpaceMicros, uint32_t *aDecodedRawDataArray, unsigned int aNumberOfBits, bool aMSBFirst,
* bool aSendStopBit, unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 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
@ -42,9 +51,8 @@
*
************************************************************************************
*/
#ifndef _IR_DISTANCE_HPP
#define _IR_DISTANCE_HPP
#ifndef _IR_DISTANCE_WIDTH_HPP
#define _IR_DISTANCE_WIDTH_HPP
// accept durations up to 50 * 50 (MICROS_PER_TICK) 2500 microseconds
#define DURATION_ARRAY_SIZE 50
@ -62,7 +70,6 @@
* @{
*/
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#Codings
#if defined(LOCAL_DEBUG)
void printDurations(uint8_t aArray[], uint8_t aMaxIndex) {
for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
@ -73,10 +80,14 @@ void printDurations(uint8_t aArray[], uint8_t aMaxIndex) {
Serial.println();
}
Serial.print(i);
Serial.print(F(":"));
Serial.print(F(": "));
}
Serial.print(aArray[i]);
if (aArray[i] != 0) {
Serial.print(' ');
Serial.print(i * (uint16_t)MICROS_PER_TICK);
}
Serial.print(F(" | "));
Serial.print(aArray[i]);
}
Serial.println();
}
@ -125,13 +136,13 @@ bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIn
* No data and address decoding, only raw data as result.
*/
bool IRrecv::decodeDistance() {
uint8_t tDurationArray[DURATION_ARRAY_SIZE];
uint8_t tDurationArray[DURATION_ARRAY_SIZE]; // For up to 49 ticks / 2450 us
/*
* 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("PULSE_DISTANCE_WIDTH: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is less than 20"));
@ -145,12 +156,12 @@ bool IRrecv::decodeDistance() {
uint8_t tMaxDurationIndex = 0;
/*
* Count number of mark durations. Skip leading start and trailing stop bit.
* Count number of mark durations up to 49 ticks. 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]++;
tDurationArray[tDurationTicks]++; // count duration if less than DURATION_ARRAY_SIZE (50)
if (tMaxDurationIndex < tDurationTicks) {
tMaxDurationIndex = tDurationTicks;
}
@ -169,8 +180,10 @@ bool IRrecv::decodeDistance() {
#endif
if (!tSuccess) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Mark aggregation failed, more than 2 distinct mark duration values found"));
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.println(F("Mark aggregation failed, more than 2 distinct mark duration values found"));
#endif
}
// Reset duration array
@ -202,19 +215,13 @@ bool IRrecv::decodeDistance() {
#endif
if (!tSuccess) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Space aggregation failed, more than 2 distinct space duration values found"));
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.println(F("Space aggregation failed, more than 2 distinct space duration values found"));
#endif
return false;
}
// skip leading start bit and trailing stop bit for decoding.
uint16_t tNumberOfBits = (decodedIRData.rawDataPtr->rawlen / 2) - 2;
// Store data to reproduce frame for sending
decodedIRData.numberOfBits = tNumberOfBits;
decodedIRData.extra = (decodedIRData.rawDataPtr->rawbuf[1] << 8) | decodedIRData.rawDataPtr->rawbuf[2];
decodedIRData.address = (tMarkTicksShort << 8) | tSpaceTicksLong;
decodedIRData.command = (tMarkTicksShort << 8) | tSpaceTicksShort;
/*
* Print characteristics of this protocol. Durations are in ticks.
* Number of bits, start bit, start pause, short mark, long mark, short space, long space
@ -227,51 +234,79 @@ bool IRrecv::decodeDistance() {
* Sony: 12|15|20, 48, 12, 12, 24, 12, 0 // the only known pulse width protocol
*/
#if defined(LOCAL_DEBUG)
Serial.print(F("Protocol constants for a " STR(MICROS_PER_TICK) " us tick: "));
Serial.print(decodedIRData.numberOfBits);
Serial.print(F(" bits, "));
Serial.print(decodedIRData.rawDataPtr->rawbuf[1]);
Serial.print(F("ProtocolConstants: "));
Serial.print(decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(decodedIRData.rawDataPtr->rawbuf[2]);
Serial.print(decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(tMarkTicksLong);
Serial.print(tMarkTicksShort * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.println(tSpaceTicksLong);
Serial.print(tSpaceTicksLong * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(tMarkTicksShort);
if (tMarkTicksLong == 0) {
Serial.print(tMarkTicksShort * MICROS_PER_TICK);
} else {
Serial.print(tMarkTicksLong * MICROS_PER_TICK);
}
Serial.print(F(", "));
Serial.print(tSpaceTicksShort);
Serial.print(tSpaceTicksShort * MICROS_PER_TICK);
Serial.println();
#endif
uint8_t tStartIndex = 3;
// skip leading start bit for decoding.
uint16_t tNumberOfBits = (decodedIRData.rawDataPtr->rawlen / 2) - 1;
if (tSpaceTicksLong > 0 && tMarkTicksLong == 0) {
// For PULSE DISTANCE a stop bit is mandatory, for PULSE_DISTANCE_WIDTH it is not required!
tNumberOfBits--; // Correct for stop bit
}
decodedIRData.numberOfBits = tNumberOfBits;
uint8_t tNumberOfAdditionalLong = (tNumberOfBits - 1) / 32;
/*
* decide, if we have an pulse width or distance protocol
*/
if (tSpaceTicksLong > 0) {
/*
* For PULSE DISTANCE a stop bit is mandatory!
*/
decodedIRData.protocol = PULSE_DISTANCE;
/*
* Here short and long space duration found. Decode in 32 bit chunks.
* Only the last chunk can contain less than 32 bits
*/
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,
bool tResult;
if (tMarkTicksLong > 0) {
decodedIRData.protocol = PULSE_DISTANCE_WIDTH;
/*
* Here we have 2 space and 2 mark durations like MagiQuest
* The longer mark is mostly the mark of the coded 1
*/
tResult = decodeDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksLong * MICROS_PER_TICK,
(tMarkTicksLong + tSpaceTicksShort) * MICROS_PER_TICK,
#if defined(DISTANCE_DO_MSB_DECODING)
true
true
#else
false
false
#endif
);
} else {
decodedIRData.protocol = PULSE_DISTANCE;
tResult = decodePulseDistanceData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksShort * MICROS_PER_TICK,
tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK,
#if defined(DISTANCE_DO_MSB_DECODING)
true
#else
false
#endif
);
}
if (!tResult) {
#if defined(LOCAL_DEBUG)
Serial.print(decodedIRData.protocol);
Serial.println(F(": Decode failed"));
#endif
)) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
} else {
// fill array with decoded data
@ -281,11 +316,12 @@ bool IRrecv::decodeDistance() {
}
}
} 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"));
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_DISTANCE: "));
Serial.println(F("Only 1 distinct duration value for each space and mark found"));
#endif
return false;
}
@ -304,9 +340,11 @@ bool IRrecv::decodeDistance() {
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"));
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_WIDTH: "));
Serial.println(F("Decode failed"));
#endif
return false;
}
tStartIndex += 64;
@ -320,13 +358,24 @@ bool IRrecv::decodeDistance() {
}
#if defined(DISTANCE_DO_MSB_DECODING)
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO;
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO;
#else
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO;
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO;
#endif
// Store data to reproduce frame for sending
decodedIRData.extra = (decodedIRData.rawDataPtr->rawbuf[1] << 8) | decodedIRData.rawDataPtr->rawbuf[2];
if (tMarkTicksLong == 0) {
decodedIRData.address = (tMarkTicksShort << 8) | tSpaceTicksLong;
} else {
decodedIRData.address = (tMarkTicksLong << 8) | tSpaceTicksLong;
}
decodedIRData.command = (tMarkTicksShort << 8) | tSpaceTicksShort;
return true;
}
/** @}*/
#endif // _IR_DISTANCE_HPP
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _IR_DISTANCE_WIDTH_HPP

View File

@ -32,6 +32,12 @@
#ifndef _IR_KASEIKYO_HPP
#define _IR_KASEIKYO_HPP
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
@ -66,7 +72,7 @@
#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_BITS (KASEIKYO_VENDOR_ID_BITS + KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS) // 48
#define KASEIKYO_UNIT 432 // 16 pulses of 37 kHz (432,432432) - Pronto 0x70 | 0x10
#define KASEIKYO_HEADER_MARK (8 * KASEIKYO_UNIT) // 3456
@ -160,7 +166,7 @@ void IRsend::sendKaseikyo_JVC(uint16_t aAddress, uint8_t aCommand, int_fast8_t a
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
// Check we have enough data (96 + 4) 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="));
@ -175,8 +181,10 @@ bool IRrecv::decodeKaseikyo() {
// decode first 16 Vendor ID bits
if (!decodePulseDistanceData(&KaseikyoProtocolConstants, KASEIKYO_VENDOR_ID_BITS)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINTLN(F("Vendor ID decode failed"));
#if defined(LOCAL_DEBUG)
Serial.print(F("Kaseikyo: "));
Serial.println(F("Vendor ID decode failed"));
#endif
return false;
}
@ -205,8 +213,10 @@ bool IRrecv::decodeKaseikyo() {
if (!decodePulseDistanceData(&KaseikyoProtocolConstants,
KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS,
3 + (2 * KASEIKYO_VENDOR_ID_BITS))) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINTLN(F("VendorID parity, address, command + parity decode failed"));
#if defined(LOCAL_DEBUG)
Serial.print(F("Kaseikyo: "));
Serial.println(F("VendorID parity, address, command + parity decode failed"));
#endif
return false;
}
@ -221,13 +231,15 @@ bool IRrecv::decodeKaseikyo() {
if (tVendorParity != (tValue.UByte.LowByte & 0xF)) {
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
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);
#if defined(LOCAL_DEBUG)
Serial.print(F("Kaseikyo: "));
Serial.print(F("4 bit VendorID parity is not correct. expected=0x"));
Serial.print(tVendorParity, HEX);
Serial.print(F(" received=0x"));
Serial.print(decodedIRData.decodedRawData, HEX);
Serial.print(F(" VendorID=0x"));
Serial.println(tVendorId, HEX);
#endif
}
if (tProtocol == KASEIKYO) {
@ -238,15 +250,17 @@ bool IRrecv::decodeKaseikyo() {
if (tValue.UByte.HighByte != tParity) {
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
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);
#if defined(LOCAL_DEBUG)
Serial.print(F("Kaseikyo: "));
Serial.print(F("8 bit Parity is not correct. expected=0x"));
Serial.print(tParity, HEX);
Serial.print(F(" received=0x"));
Serial.print(decodedIRData.decodedRawData >> KASEIKYO_COMMAND_BITS, HEX);
Serial.print(F(" address=0x"));
Serial.print(decodedIRData.address, HEX);
Serial.print(F(" command=0x"));
Serial.println(decodedIRData.command, HEX);
#endif
}
decodedIRData.numberOfBits = KASEIKYO_BITS;
@ -265,4 +279,7 @@ bool IRrecv::decodeKaseikyo() {
*/
/** @}*/
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _IR_KASEIKYO_HPP

View File

@ -72,7 +72,7 @@
+ 500,- 650 + 500,- 650 + 500,- 650 + 200,- 900 // Checksum (+ sum of the 5 bytes before == 0)
+ 250,- 850 + 500,- 650 + 300,- 800 + 500
*/
// MSB first, 8 start bits (zero), 31 wand id bits, 9 magnitude bits 8 checksum bits and no stop bit
// MSB first, 8 start bits (zero), 31 wand id bits, 9 magnitude bits 8 checksum bits and no stop bit => 56 bits
#if !defined (DOXYGEN)
// MagiQuest packet is both Wand ID and magnitude of swish and flick
union magiquest_t {
@ -118,23 +118,33 @@ MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPA
NULL };
//+=============================================================================
//
/**
* @param aWandId 31 bit ID
* @param aMagnitude 9 bit Magnitude
*/
void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) {
// Set IR carrier frequency
enableIROut(38);
// 8 start bits
sendPulseDistanceWidthData(&MagiQuestProtocolConstants, 0, 8);
aMagnitude &= 0x1FF; // we have 9 bit
LongUnion tWandId;
tWandId.ULong = aWandId << 1;
uint8_t tChecksum = (tWandId.Bytes[0]) + tWandId.Bytes[1] + tWandId.Bytes[2] + tWandId.Bytes[3];
tChecksum += aMagnitude + (aMagnitude >> 8);
tChecksum = ~tChecksum + 1;
// Data
sendPulseDistanceWidthData(&MagiQuestProtocolConstants, aWandId, MAGIQUEST_WAND_ID_BITS);
// 8 start bits
sendPulseDistanceWidthData(&MagiQuestProtocolConstants, 0, 8);
// 48 bit data
sendPulseDistanceWidthData(&MagiQuestProtocolConstants, aWandId, MAGIQUEST_WAND_ID_BITS); // send only 31 bit, do not send MSB here
sendPulseDistanceWidthData(&MagiQuestProtocolConstants, aMagnitude, MAGIQUEST_MAGNITUDE_BITS);
sendPulseDistanceWidthData(&MagiQuestProtocolConstants, tChecksum, MAGIQUEST_CHECKSUM_BITS);
#if defined(LOCAL_DEBUG)
// must be after sending, in order not to destroy the send timing
Serial.print(F("MagiQuest checksum=0x"));
Serial.println(tChecksum, HEX);
#endif
IrReceiver.restartAfterSend();
}
@ -142,17 +152,20 @@ void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) {
//
/*
* decodes a 56 bit result, which is not really compatible with standard decoder layout
* magnitude is stored in Command
* magnitude is stored in command
* 31 bit wand_id is stored in decodedRawData
* lower 16 bit of wand_id is stored in address
*/
bool IRrecv::decodeMagiQuest() {
magiquest_t data; // Somewhere to build our code
unsigned int tMark;
unsigned int tSpace;
unsigned int tMarkTicks;
unsigned int tSpaceTicks;
#if defined(LOCAL_DEBUG)
char bitstring[(MAGIQUEST_BITS + 1)];
bitstring[MAGIQUEST_BITS] = '\0';
char tDebugBitstring[(MAGIQUEST_BITS + 1)];
tDebugBitstring[MAGIQUEST_BITS] = '\0';
char * tDebugBitstringPtr = tDebugBitstring;
#endif
// Check we have the right amount of data, magnitude and ID bits and 8 start bits + 0 stop bit
@ -164,50 +177,49 @@ bool IRrecv::decodeMagiQuest() {
return false;
}
// Decode each bit
// Decode the 56 bits in one loop using uint64
data.llword = 0;
uint_fast8_t tIndex = 1; // Skip the gap between frames
unsigned int *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[1];
for (uint_fast8_t i = 0; i < MAGIQUEST_BITS; i++) {
// get one mark and space pair
tMark = decodedIRData.rawDataPtr->rawbuf[tIndex++];
tSpace = decodedIRData.rawDataPtr->rawbuf[tIndex++]; // buffer overflow for last bit, but we do not evaluate this value :-)
tMarkTicks = *tRawBufPointer++;;
tSpaceTicks = *tRawBufPointer++;; // buffer overflow for last bit, but we do not evaluate this value :-)
IR_TRACE_PRINT(F("MagiQuest: mark="));
IR_TRACE_PRINT(tMark * MICROS_PER_TICK);
IR_TRACE_PRINT(tMarkTicks * MICROS_PER_TICK);
IR_TRACE_PRINT(F(" space="));
IR_TRACE_PRINTLN(tSpace * MICROS_PER_TICK);
IR_TRACE_PRINTLN(tSpaceTicks * MICROS_PER_TICK);
// We have no stop bit, so assume that last space, which is not recorded, is correct, since we can not check it
if (i == (MAGIQUEST_BITS - 1) || matchMark(tMark + tSpace, MAGIQUEST_PERIOD)) {
if (!matchMark(tMark, MAGIQUEST_ONE_MARK)) {
if (i == (MAGIQUEST_BITS - 1) || matchMark(tMarkTicks + tSpaceTicks, MAGIQUEST_PERIOD)) {
if (!matchMark(tMarkTicks, MAGIQUEST_ONE_MARK)) {
// It's a 0
data.llword <<= 1;
#if defined(LOCAL_DEBUG)
bitstring[(tIndex / 2) - 1] = '0';
*tDebugBitstringPtr++ = '0';
#endif
} else {
// It's a 1
data.llword = (data.llword << 1) | 1;
#if defined(LOCAL_DEBUG)
bitstring[(tIndex / 2) - 1] = '1';
*tDebugBitstringPtr++ = '1';
#endif
}
} else {
#if defined(LOCAL_DEBUG)
Serial.print(F("Mark and space does not match the constant MagiQuest period. Index="));
Serial.println(i);
// Serial.println(tIndex - 2);
#endif
return false;
}
}
#if defined(LOCAL_DEBUG)
Serial.println(bitstring);
Serial.println(tDebugBitstring);
#endif
// Success
decodedIRData.protocol = MAGIQUEST;
decodedIRData.numberOfBits = tIndex / 2;
decodedIRData.numberOfBits = MAGIQUEST_BITS;
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
LongUnion tWandId;
@ -217,8 +229,8 @@ bool IRrecv::decodeMagiQuest() {
if (tChecksum != 0) {
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
#if defined(LOCAL_DEBUG)
Serial.print(F("Checksum "));
Serial.print(tChecksum);
Serial.print(F("Checksum 0x"));
Serial.print(tChecksum, HEX);
Serial.println(F(" is not 0"));
#endif
}

View File

@ -73,7 +73,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0
************************************/
/**
* @param aCommand If aCommand is >=64 then we switch automatically to RC5X
* @param aCommand If aCommand is >=0x40 then we switch automatically to RC5X
*/
void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
// Set IR carrier frequency
@ -82,7 +82,7 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe
uint16_t tIRData = ((aAddress & 0x1F) << RC5_COMMAND_BITS);
if (aCommand < 0x40) {
// auto discovery of RC5, set field bit to 1
// Auto discovery of RC5X, set field bit to 1
tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
} else {
// Mask bit 7 of command and let field bit 0

View File

@ -92,7 +92,7 @@ SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_NO_STOP_BIT,
* @param numberOfBits should be one of SIRCS_12_PROTOCOL, SIRCS_15_PROTOCOL, SIRCS_20_PROTOCOL. Not checked! 20 -> send 13 address bits
*/
void IRsend::sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits) {
uint32_t tData = (uint32_t) aAddress << 7 | aCommand;
uint32_t tData = (uint32_t) aAddress << 7 | (aCommand & 0x7F);
// send 5, 8, 13 address bits LSB first
sendPulseDistanceWidth(&SonyProtocolConstants, tData, numberOfBits, aNumberOfRepeats);
}