Version 4.1.0

This commit is contained in:
Armin 2023-02-24 02:40:21 +01:00
parent 920fa30303
commit 114cbf335b
77 changed files with 3116 additions and 1839 deletions

View File

@ -73,6 +73,7 @@ body:
- BoseWave
- Denon
- Dish
- FAST
- JVC
- Lego
- LG

View File

@ -262,7 +262,7 @@ jobs:
- arduino-boards-fqbn: Seeeduino:samd:seeed_XIAO_m0:usbstack=arduino,debug=off,sercom4=include
platform-url: https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
sketches-exclude: AllProtocolsOnLCD
sketches-exclude: AllProtocolsOnLCD,UnitTest,ReceiveAndSendDistanceWidth # No print(uint64_t,.) available
build-properties: # the flags were put in compiler.cpp.extra_flags
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700
All: -DRAW_BUFFER_LENGTH=300

View File

@ -42,7 +42,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
* [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote#send-pin)
+ [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases)
- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote#tiny-nec-receiver-and-sender)
* [Tiny FAST receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote#tiny-fast-receiver-and-sender)
- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#the-fast-protocol)
- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote#faq-and-hints)
* [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote#problems-with-neopixels-fastled-etc)
* [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote#does-not-workcompile-with-another-library)
@ -82,7 +82,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
` Universal Pulse Distance `     ` Universal Pulse Width `     ` Hash `     ` Pronto `
` BoseWave `     ` Bang & Olufsen `     ` Lego `     ` Whynter `     ` MagiQuest `
` BoseWave `     ` Bang & Olufsen `     ` Lego `     ` FAST `     ` Whynter `     ` MagiQuest `
Protocols can be switched off and on by defining macros before the line `#include <IRremote.hpp>` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33):
@ -102,10 +102,13 @@ Protocols can be switched off and on by defining macros before the line `#includ
- New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols.
- Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`.
- RawData type is now 64 bit for 32 bit platforms and therefore `decodedIRData.decodedRawData` can contain complete frame information for more protocols than with 32 bit as before.
- Callback after receiving a command - call your own code if a message was received.
- Callback after receiving a command - It calls your code as soon as a message was received.
- Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols.
- New FAST protocol.
# Converting your 3.x program to the 4.x version
- You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder).
- The parameter `bool hasStopBit` is not longer required and removed e.g. for function `sendPulseDistanceWidth()`.
## New features with version 3.x
- **Any pin** can be used for sending -if `SEND_PWM_BY_TIMER` is not defined- and receiving.
@ -391,22 +394,37 @@ void setup() {
void loop() {}
```
## Tiny FAST receiver and sender
The FAST protocol is proprietary and a JVC protocol **without address and with a shorter header**. It is meant to have a quick response to the event which sent the frame on another board. FAST takes **21 ms for sending** and is sent at a **40 ms period**. It still supports full 8 bit parity for error detection!
# The FAST protocol
The FAST protocol is a proprietary modified JVC protocol **without address, with parity and with a shorter header**.
It is meant to have a quick response to the event which sent the protocol frame on another board.
FAST takes **21 ms for sending** and is sent at a **50 ms period**.
It has full 8 bit parity for error detection.
### FAST protocol characteristics:
- Bit timing is like JVC
- The header is shorter, 3156 &micro;s vs. 12500 &micro;s
- No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, leading to a fixed protocol length of (6 + (16 * 2) + 1) * 526 = 39 * 560 = 20514 microseconds or 20.5 ms.
- Repeats are sent as complete frames but in a 40 ms period / with a 19.5 ms distance.
- No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
- Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
### TinyIRSender with FAST protocol
### Sending FAST protocol with IRremote
```c++
#define USE_FAST_PROTOCOL // Use short protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command
#define IR_SEND_PIN 3
#include <IRremote.hpp>
void setup() {
sendFAST(11, 2); // Send command 11 on pin 3 with 2 repeats.
}
void loop() {}
```
### Sending FAST protocol with TinyIRSender
```c++
#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command
#include "TinyIRSender.hpp"
void setup() {
sendFast8BitAndParity(3, 11, 2); // Send command 11 on pin 3 with 2 repeats.
sendFAST(3, 11, 2); // Send command 11 on pin 3 with 2 repeats.
}
void loop() {}
@ -513,13 +531,12 @@ This examples are a good starting point.
A simple example can be tested online with [WOKWI](https://wokwi.com/projects/338611596994544210).
#### TinyReceiver + TinySender
If **code size** matters, look at these examples.<br/>
The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC and FAST codes, but does not require any timer**.<br/>
If **code size** or **timer usage** matters, look at these examples.<br/>
The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.<br/>
TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
Click on the receiver while simulation is running to specify individual IR codes.
The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC and FAST codes**.<br/>
Sending NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example.
The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.<br/>
It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example.
Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible).
#### SmallReceiver
@ -528,11 +545,11 @@ If the protocol is not NEC and code size matters, look at this [example](https:/
#### ReceiveDemo + AllProtocolsOnLCD
[ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino) receives all protocols and **generates a beep with the Arduino tone() function** on each packet received.<br/>
[AllProtocolsOnLCD](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino) additionally **displays the short result on a 1602 LCD**. The LCD can be connected parallel or serial (I2C).<br/>
By connecting pin debug pin to ground, you can see the raw values for each packet. The pin number of the debug pin is printed during setup, because it depends on board and LCD connection type.<br/>
By connecting debug pin to ground, you can force printing of the raw values for each frame. The pin number of the debug pin is printed during setup, because it depends on board and LCD connection type.<br/>
This example also serves as an **example how to use IRremote and tone() together**.
#### ReceiveDump
Receives all protocols and dumps the received signal in different flavors including Pronto format. Since the printing takes so much time, repeat signals may be skipped or interpreted as UNKNOWN.
Receives all protocols and dumps the received signal in different flavors including Pronto format. Since the printing takes much time, repeat signals may be skipped or interpreted as UNKNOWN.
#### SendDemo
Sends all available protocols at least once.
@ -541,7 +558,12 @@ Sends all available protocols at least once.
Demonstrates **receiving while sending**.
#### ReceiveAndSend
Record and **play back last received IR signal** at button press.
Record and **play back last received IR signal** at button press. IR frames of known protocols are sent by the approriate protocol encoder. `UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`.
#### ReceiveAndSendDistanceWidth
Try to decode each IR frame with the *universal* **DistanceWidth decoder**, store the data and send it on button press with `sendPulseDistanceWidthFromArray()`.<br/>
Storing data for distance width protocol requires 17 bytes.
The ReceiveAndSend example requires 16 bytes for known protocol data and 37 bytes for raw data of e.g.NEC protocol.
#### ReceiveOneAndSendMultiple
Serves as a IR **remote macro expander**. Receives Samsung32 protocol and on receiving a specified input frame, it sends multiple Samsung32 frames with appropriate delays in between.
@ -611,7 +633,7 @@ Modify them by enabling / disabling them, or change the values if applicable.
| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates 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! |
| `DISABLE_CODE_FOR_RECEIVER` | disabled | Saves up to 450 bytes program memory and 269 bytes RAM if receiving functionality is not required. |
| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. |
| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. |
| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 &micro;s at 38 kHz. |
@ -842,4 +864,4 @@ From the version 2.8.0, the license is the MIT license.
# Copyright
Initially coded 2009 Ken Shirriff http://www.righto.com<br/>
Copyright (c) 2016-2017 Rafi Khan<br/>
Copyright (c) 2020-2022 [Armin Joachimsmeyer](https://github.com/ArminJo)
Copyright (c) 2020-2023 [Armin Joachimsmeyer](https://github.com/ArminJo)

View File

@ -2,12 +2,19 @@
The latest version may not be released!
See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master
## 4.0.1
## 4.1.0
- Fixed bug in printing durations > 64535 in printIRResultRawFormatted().
- Narrowed constraints for RC5 RC6 number of bits.
- Changed the first parameter of printTinyReceiverResultMinimal() to &Serial.
- Removed 3 Serial prints for deprecation warnings to fix #1094.
- Version 1.2.0 of TinyIR.
- Version 1.2.0 of TinyIR. Now FAST protocol with 40 ms period and shorter header space.
- Removed field "bool hasStopBit" and parameter "bool aSendStopBit" from PulseDistanceWidthProtocolConstants structure and related functions.
- Changed a lot of "unsigned int" types to "uint16_t" types.
- Improved overflow handling.
- Added FAST protocol.
- Improved handling of PULSE_DISTANCE + PULSE_WIDTH protocols.
- New example ReceiveAndSendDistanceWidth.
- Removed the automatic restarting of the receiver timer after sending with SEND_PWM_BY_TIMER enabled.
## 4.0.0
- Added decoding of PulseDistanceWidth protocols and therfore changed function decodeDistance() to decodeDistanceWidth() and filename ir_DistanceProtocol.hpp to ir_DistanceWidthProtocol.hpp.

View File

@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022 Armin Joachimsmeyer
* Copyright (c) 2022-2023 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
@ -116,8 +116,10 @@ LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
#endif
void printIRResultOnLCD();
size_t printHex(uint16_t aHexByteValue);
void printSpaces(uint_fast8_t aNumberOfSpacesToPrint);
size_t printByteHexOnLCD(uint16_t aHexByteValue);
void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint);
uint16_t sVCCMillivolt;
void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
@ -147,7 +149,7 @@ void setup() {
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols (&Serial);
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#if defined(USE_SERIAL_LCD)
@ -193,6 +195,10 @@ void setup() {
myLCD.setCursor(0, 1);
myLCD.print(F(__DATE__));
#endif
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
sVCCMillivolt = getVCCVoltageMillivoltSimple();
#endif
}
void loop() {
@ -206,8 +212,10 @@ void loop() {
*/
if (IrReceiver.decode()) {
Serial.println();
// Print a short summary of received data
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
Serial.println(F("Overflow detected"));
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
#if defined(USE_LCD)
myLCD.setCursor(0, 0);
@ -222,13 +230,14 @@ void loop() {
IrReceiver.stop();
tone(TONE_PIN, 2200);
// Print a short summary of received data
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
// Print more info
if ((IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW)
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
&& sVCCMillivolt > 4222
#endif
) {
// Print more info, but only if we are connected to USB, i.e. VCC is > 4222 mV, because this may take to long to detect some fast repeats
IrReceiver.printIRSendUsage(&Serial);
IrReceiver.printIRResultRawFormatted(&Serial, false);
IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-)
}
// Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
@ -259,9 +268,9 @@ void loop() {
* Periodically print VCC
*/
sMillisOfLastVoltagePrint = millis();
uint16_t tVCC = getVCCVoltageMillivoltSimple();
sVCCMillivolt = getVCCVoltageMillivoltSimple();
char tVoltageString[5];
dtostrf(tVCC / 1000.0, 4, 2, tVoltageString);
dtostrf(sVCCMillivolt / 1000.0, 4, 2, tVoltageString);
myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0);
myLCD.print(' ');
myLCD.print(tVoltageString);
@ -281,7 +290,7 @@ void loop() {
*/
void printIRResultOnLCD() {
#if defined(USE_LCD)
static uint16_t sLastProtocolIndex;
static uint16_t sLastProtocolIndex = 4711;
static uint16_t sLastProtocolAddress = 4711;
static uint16_t sLastCommand = 0;
static uint8_t sLastCommandPrintPosition;
@ -301,88 +310,106 @@ void printIRResultOnLCD() {
// we overwrite the voltage -> clear rest of line and inhibit new printing of voltage
ProtocolStringOverwritesVoltage = true;
if (tProtocolStringLength < LCD_COLUMNS) {
printSpaces(LCD_COLUMNS - tProtocolStringLength);
printSpacesOnLCD(LCD_COLUMNS - tProtocolStringLength);
}
} else {
// Trigger printing of VCC in main loop
sMillisOfLastVoltagePrint = 0;
ProtocolStringOverwritesVoltage = false;
printSpaces(LCD_VOLTAGE_START_INDEX - tProtocolStringLength);
printSpacesOnLCD(LCD_VOLTAGE_START_INDEX - tProtocolStringLength);
}
# else
printSpaces(LCD_COLUMNS - tProtocolStringLength);
printSpacesOnLCD(LCD_COLUMNS - tProtocolStringLength);
# endif
}
/*
* Print only if address has changed
*/
if (sLastProtocolAddress == 4711 || sLastProtocolAddress != IrReceiver.decodedIRData.address) {
sLastProtocolAddress = IrReceiver.decodedIRData.address;
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
/*
* Show address
* Print number of bits received and microseconds of signal
*/
myLCD.setCursor(0, 1);
# if defined(DECODE_DISTANCE_WIDTH)
if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
myLCD.print(F("[0]=0x"));
uint_fast8_t tAddressStringLength = myLCD.print(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
printSpaces(LCD_COLUMNS - tAddressStringLength);
sLastCommand = 0; // to trigger restoration of "C=" string
return; // no command here
} else {
# endif
myLCD.print(F("A="));
uint_fast8_t tAddressStringLength = printHex(IrReceiver.decodedIRData.address);
printSpaces((LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength);
# if defined(DECODE_DISTANCE_WIDTH)
uint8_t tNumberOfBits = (IrReceiver.decodedIRData.rawDataPtr->rawlen + 1) / 2;
if (tNumberOfBits < 10) {
myLCD.print(' '); // padding space
}
# endif
}
myLCD.print(tNumberOfBits);
myLCD.print(F(" bit "));
uint_fast8_t tDurationStringLength = myLCD.print(IrReceiver.getTotalDurationOfRawData());
myLCD.print(F(" \xE4s")); // \xE4 is micro symbol
printSpacesOnLCD(7 - tDurationStringLength);
sLastProtocolAddress = 4711;
sLastCommand = 44711;
/*
* Print command
*/
uint16_t tCommand = IrReceiver.decodedIRData.command;
} else {
/*
* Print only if address has changed
*/
if (sLastProtocolAddress != IrReceiver.decodedIRData.address) {
sLastProtocolAddress = IrReceiver.decodedIRData.address;
myLCD.setCursor(0, 1);
/*
* Show address
*/
# if defined(DECODE_DISTANCE_WIDTH)
if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
myLCD.print(F("[0]=0x"));
uint_fast8_t tAddressStringLength = myLCD.print(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
printSpacesOnLCD(LCD_COLUMNS - tAddressStringLength);
sLastCommand = 0; // to trigger restoration of "C=" string
return; // no command here
} else {
# endif
myLCD.print(F("A="));
uint_fast8_t tAddressStringLength = printByteHexOnLCD(IrReceiver.decodedIRData.address);
printSpacesOnLCD((LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength);
# if defined(DECODE_DISTANCE_WIDTH)
}
# endif
}
/*
* Print command always
*/
uint16_t tCommand = IrReceiver.decodedIRData.command;
// Check if prefix position must change
if (sLastCommand == 0 || (sLastCommand >= 0x100 && tCommand < 0x100) || (sLastCommand < 0x100 && tCommand >= 0x100)) {
sLastCommand = tCommand;
/*
* Print prefix for 8/16 bit commands
*/
if (tCommand >= 0x100) {
// Do not print "C=" here to have 2 additional characters for command
sLastCommandPrintPosition = 9;
} else {
myLCD.setCursor(LCD_IR_COMMAND_START_INDEX, 1);
myLCD.print(F("C="));
sLastCommandPrintPosition = 11;
if (sLastCommand == 0 || (sLastCommand >= 0x100 && tCommand < 0x100) || (sLastCommand < 0x100 && tCommand >= 0x100)) {
sLastCommand = tCommand;
/*
* Print prefix for 8/16 bit commands
*/
if (tCommand >= 0x100) {
// Do not print "C=" here to have 2 additional characters for command
sLastCommandPrintPosition = 9;
} else {
myLCD.setCursor(LCD_IR_COMMAND_START_INDEX, 1);
myLCD.print(F("C="));
sLastCommandPrintPosition = 11;
}
}
}
/*
* Command data
*/
myLCD.setCursor(sLastCommandPrintPosition, 1);
printHex(tCommand);
/*
* Show or clear repetition flag
*/
if (IrReceiver.decodedIRData.flags & (IRDATA_FLAGS_IS_REPEAT)) {
myLCD.print('R');
return; // Since it is a repetition, printed data has not changed
} else {
myLCD.print(' ');
}
/*
* Command data
*/
myLCD.setCursor(sLastCommandPrintPosition, 1);
printByteHexOnLCD(tCommand);
/*
* Show or clear repetition flag
*/
if (IrReceiver.decodedIRData.flags & (IRDATA_FLAGS_IS_REPEAT)) {
myLCD.print('R');
return; // Since it is a repetition, printed data has not changed
} else {
myLCD.print(' ');
}
} // IrReceiver.decodedIRData.protocol == UNKNOWN
#endif // defined(USE_LCD)
}
#if defined(USE_LCD)
size_t printHex(uint16_t aHexByteValue) {
size_t printByteHexOnLCD(uint16_t aHexByteValue) {
myLCD.print(F("0x"));
size_t tPrintSize = 2;
if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) {
@ -392,7 +419,7 @@ size_t printHex(uint16_t aHexByteValue) {
return myLCD.print(aHexByteValue, HEX) + tPrintSize;
}
void printSpaces(uint_fast8_t aNumberOfSpacesToPrint) {
void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint) {
for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) {
myLCD.print(' ');
}

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -317,6 +317,12 @@ void dumpProtocols() {
Serial.println(F("Disabled"));
#endif
Serial.print(F("FAST: "));
#if defined(DECODE_FAST)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
#endif
}

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -5,6 +5,7 @@
* The logic is:
* If the button is pressed, send the IR code.
* If an IR code is received, record it.
* If the protocol is unknown or not enabled, store it as raw data for later sending.
*
* An example for simultaneous receiving and sending is in the UnitTest example.
*
@ -21,7 +22,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2021 Ken Shirriff, Armin Joachimsmeyer
* Copyright (c) 2009-2023 Ken Shirriff, 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
@ -51,10 +52,22 @@
* If no protocol is defined, all protocols (except Bang&Olufsen) are active.
* This must be done before the #include <IRremote.hpp>
*/
//#define DECODE_DENON // Includes Sharp
//#define DECODE_JVC
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
//#define DECODE_LG
//#define DECODE_NEC
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
// etc. see IRremote.hpp
#define DECODE_NEC // Includes Apple and Onkyo
//#define DECODE_SAMSUNG
//#define DECODE_SONY
//#define DECODE_RC5
//#define DECODE_RC6
//#define DECODE_BOSEWAVE
//#define DECODE_LEGO_PF
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_FAST
//
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
@ -66,25 +79,24 @@
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
// 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. See also IRremote.hpp line 142.
#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include <IRremote.hpp>
int SEND_BUTTON_PIN = APPLICATION_PIN;
int STATUS_PIN = LED_BUILTIN;
int DELAY_BETWEEN_REPEAT = 50;
int DEFAULT_NUMBER_OF_REPEATS_TO_SEND = 3;
// Storage for the recorded code
struct storedIRDataStruct {
@ -94,12 +106,14 @@ struct storedIRDataStruct {
uint8_t rawCodeLength; // The length of the code
} sStoredIRData;
int lastButtonState;
bool sSendButtonWasActive;
void storeCode(IRData *aIRReceivedData);
void storeCode();
void sendCode(storedIRDataStruct *aIRDataToSend);
void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
@ -109,84 +123,86 @@ void setup() {
// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin 3 on press of button at pin "));
#endif
Serial.println(SEND_BUTTON_PIN);
pinMode(STATUS_PIN, OUTPUT);
}
void loop() {
// If button pressed, send the code.
int buttonState = digitalRead(SEND_BUTTON_PIN); // Button pin is active LOW
bool tSendButtonIsActive = (digitalRead(SEND_BUTTON_PIN) == LOW); // Button pin is active LOW
/*
* Check for button just released in order to activate receiving
* Check for current button state
*/
if (lastButtonState == LOW && buttonState == HIGH) {
// Re-enable receiver
Serial.println(F("Button released"));
IrReceiver.start();
}
/*
* Check for static button state
*/
if (buttonState == LOW) {
IrReceiver.stop();
/*
* Button pressed send stored data or repeat
*/
Serial.println(F("Button pressed, now sending"));
digitalWrite(STATUS_PIN, HIGH);
if (lastButtonState == buttonState) {
sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
if (tSendButtonIsActive) {
if (!sSendButtonWasActive) {
Serial.println(F("Stop receiving"));
IrReceiver.stop();
}
/*
* Button pressed -> send stored data
*/
Serial.print(F("Button pressed, now sending "));
if (sSendButtonWasActive == tSendButtonIsActive) {
Serial.print(F("repeat "));
sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
} else {
sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_EMPTY;
}
Serial.flush(); // To avoid disturbing the software PWM generation by serial output interrupts
sendCode(&sStoredIRData);
digitalWrite(STATUS_PIN, LOW);
delay(DELAY_BETWEEN_REPEAT); // Wait a bit between retransmissions
} else if (sSendButtonWasActive) {
/*
* Button is not pressed, check for incoming data
* Button is just released -> activate receiving
*/
} else if (IrReceiver.available()) {
storeCode(IrReceiver.read());
// Restart receiver
Serial.println(F("Button released -> start receiving"));
IrReceiver.start();
} else if (IrReceiver.decode()) {
/*
* Button is not pressed and data available -> store received data and resume
*/
storeCode();
IrReceiver.resume(); // resume receiver
}
lastButtonState = buttonState;
sSendButtonWasActive = tSendButtonIsActive;
delay(100);
}
// Stores the code for later playback in sStoredIRData
// Most of this code is just logging
void storeCode(IRData *aIRReceivedData) {
if (aIRReceivedData->flags & IRDATA_FLAGS_IS_REPEAT) {
void storeCode() {
if (IrReceiver.decodedIRData.rawDataPtr->rawlen < 4) {
Serial.print(F("Ignore data with rawlen="));
Serial.println(IrReceiver.decodedIRData.rawDataPtr->rawlen);
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
Serial.println(F("Ignore repeat"));
return;
}
if (aIRReceivedData->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
Serial.println(F("Ignore autorepeat"));
return;
}
if (aIRReceivedData->flags & IRDATA_FLAGS_PARITY_FAILED) {
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_PARITY_FAILED) {
Serial.println(F("Ignore parity error"));
return;
}
/*
* Copy decoded data
*/
sStoredIRData.receivedIRData = *aIRReceivedData;
sStoredIRData.receivedIRData = IrReceiver.decodedIRData;
if (sStoredIRData.receivedIRData.protocol == UNKNOWN) {
Serial.print(F("Received unknown code and store "));
@ -211,7 +227,7 @@ void sendCode(storedIRDataStruct *aIRDataToSend) {
// Assume 38 KHz
IrSender.sendRaw(aIRDataToSend->rawCode, aIRDataToSend->rawCodeLength, 38);
Serial.print(F("Sent raw "));
Serial.print(F("raw "));
Serial.print(aIRDataToSend->rawCodeLength);
Serial.println(F(" marks or spaces"));
} else {
@ -219,9 +235,7 @@ void sendCode(storedIRDataStruct *aIRDataToSend) {
/*
* Use the write function, which does the switch for different protocols
*/
IrSender.write(&aIRDataToSend->receivedIRData, DEFAULT_NUMBER_OF_REPEATS_TO_SEND);
Serial.print(F("Sent: "));
IrSender.write(&aIRDataToSend->receivedIRData);
printIRResultShort(&Serial, &aIRDataToSend->receivedIRData, false);
}
}

View File

@ -0,0 +1,322 @@
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2021-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote 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>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 Arduino
* ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3 // PA3 - on Digispark board labeled as pin 9
#define IR_SEND_PIN 2 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 7 // PA7 - on Digispark board labeled as pin 5
# endif
# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory
// Pin 6 is TX pin 7 is RX
#define IR_RECEIVE_PIN 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN 2 // PA6
# elif defined(__AVR_ATtiny816__) // Tiny Core Micro
#define IR_RECEIVE_PIN 14 // PA1
#define IR_SEND_PIN 16 // PA3
#define TONE_PIN 1 // PA5
#define APPLICATION_PIN 0 // PA4
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN 4 // PB5
# elif defined(__AVR_ATtiny1614__)
#define IR_RECEIVE_PIN 8 // PA1
#define IR_SEND_PIN 10 // PA3
#define TONE_PIN 1 // PA5
#define APPLICATION_PIN 0 // PA4
# elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 5
#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 13
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc.
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit
// We have no built in LED at pin 13 -> reuse RX LED
#undef LED_BUILTIN
#define LED_BUILTIN LED_BUILTIN_RX
# endif
# endif // defined(__AVR_ATtiny25__)...
#elif defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#elif defined(ESP32)
#include <Arduino.h>
// tone() is included in ESP32 core since 2.0.2
#if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
#endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
#define IR_SEND_PIN PA7
#define IR_SEND_PIN_STRING "PA7"
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
#define APPLICATION_PIN_STRING "PA2"
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards
#define IR_RECEIVE_PIN 11
#define IR_SEND_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IR_SEND_PIN 4 // GPIO16
#define TONE_PIN 5
#define APPLICATION_PIN 6
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 8
#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16 // GPIO16
#define TONE_PIN 17
#define APPLICATION_PIN 18
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 20
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(PARTICLE) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
#define LED_BUILTIN D7
/*
* 4 times the same (default) layout for easy adaption in the future
*/
#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#if !defined(ARDUINO_SAMD_ADAFRUIT)
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
#endif
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#elif defined (NRF51) // BBC micro:bit
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define APPLICATION_PIN 1
#define _IR_TIMING_TEST_PIN 4
#define tone(...) void() // no tone() available
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
#if !defined (RAMEND)
#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif

View File

@ -0,0 +1,184 @@
/*
* ReceiveAndSendDistanceWidth.cpp
*
* Record and play back last received distance width IR signal at button press.
* Using DistanceWidthProtocol covers a lot of known and unknown IR protocols,
* and requires less memory than raw protocol.
*
* The logic is:
* If the button is pressed, send the IR code.
* If an IR code is received, record it.
*
* An example for simultaneous receiving and sending is in the UnitTest example.
*
* An IR detector/demodulator must be connected to the input IR_RECEIVE_PIN.
*
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2023 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.
*
************************************************************************************
*/
#include <Arduino.h>
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(IR_SEND_PIN)
#define IR_SEND_PIN 3
#endif
/*
* Specify DistanceWidthProtocol for decoding. This must be done before the #include <IRremote.hpp>
*/
#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 120
# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO
#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
# else
#define RAW_BUFFER_LENGTH 750
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include <IRremote.hpp>
#define SEND_BUTTON_PIN APPLICATION_PIN
#define DELAY_BETWEEN_REPEATS_MILLIS 70
// Storage for the recorded code, pre-filled with NEC data
IRRawDataType sDecodedRawDataArray[RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // address 0x12 command 0x34
DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // NEC timing
uint8_t sNumberOfBits = 32;
bool sSendButtonWasActive;
void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.println(F("Ready to receive pulse distance/width coded IR signals at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
Serial.println(SEND_BUTTON_PIN);
}
void loop() {
// If button pressed, send the code.
bool tSendButtonIsActive = (digitalRead(SEND_BUTTON_PIN) == LOW); // Button pin is active LOW
/*
* Check for current button state
*/
if (tSendButtonIsActive) {
if (!sSendButtonWasActive) {
Serial.println(F("Stop receiving"));
IrReceiver.stop();
}
/*
* Button pressed -> send stored data
*/
Serial.print(F("Button pressed, now sending "));
Serial.print(sNumberOfBits);
Serial.print(F(" bits 0x"));
Serial.print(sDecodedRawDataArray[0], HEX);
Serial.print(F(" with sendPulseDistanceWidthFromArray timing="));
IrReceiver.printDistanceWidthTimingInfo(&Serial, &sDistanceWidthTimingInfo);
Serial.println();
Serial.flush(); // To avoid disturbing the software PWM generation by serial output interrupts
IrSender.sendPulseDistanceWidthFromArray(38, &sDistanceWidthTimingInfo, &sDecodedRawDataArray[0], sNumberOfBits,
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
PROTOCOL_IS_MSB_FIRST
#else
PROTOCOL_IS_LSB_FIRST
#endif
, 100, 0);
delay(DELAY_BETWEEN_REPEATS_MILLIS); // Wait a bit between retransmissions
} else if (sSendButtonWasActive) {
/*
* Button is just released -> activate receiving
*/
// Restart receiver
Serial.println(F("Button released -> start receiving"));
IrReceiver.start();
} else if (IrReceiver.decode()) {
/*
* Button is not pressed and data available -> store received data and resume
* DistanceWidthTimingInfo and sNumberOfBits should be constant for all keys of the same IR remote / protocol
*/
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.protocol != UNKNOWN) {
IrReceiver.printIRSendUsage(&Serial);
if (memcmp(&sDistanceWidthTimingInfo, &IrReceiver.decodedIRData.DistanceWidthTimingInfo,
sizeof(sDistanceWidthTimingInfo)) != 0) {
Serial.print(F("Store new timing info data="));
IrReceiver.printDistanceWidthTimingInfo(&Serial, &IrReceiver.decodedIRData.DistanceWidthTimingInfo);
Serial.println();
sDistanceWidthTimingInfo = IrReceiver.decodedIRData.DistanceWidthTimingInfo; // copy content here
} else {
Serial.print(F("Timing did not change, so we can reuse already stored timing info."));
}
if (sNumberOfBits != IrReceiver.decodedIRData.numberOfBits) {
Serial.print(F("Store new numberOfBits="));
sNumberOfBits = IrReceiver.decodedIRData.numberOfBits;
Serial.println(IrReceiver.decodedIRData.numberOfBits);
}
if (sDecodedRawDataArray[0] != IrReceiver.decodedIRData.decodedRawDataArray[0]) {
*sDecodedRawDataArray = *IrReceiver.decodedIRData.decodedRawDataArray; // copy content here
Serial.print(F("Store new sDecodedRawDataArray[0]=0x"));
Serial.println(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
}
}
IrReceiver.resume(); // resume receiver
}
sSendButtonWasActive = tSendButtonIsActive;
delay(100);
}

View File

@ -1,8 +1,9 @@
START ../src/ReceiveDemo.cpp from Oct 17 2022
Using library version 4.0.0
START ../src/ReceiveDemo.cpp from Feb 24 2023
Using library version 4.1.0
Enabling IRin...
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
Debug button pin is 5
Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, FAST, Whynter, Lego Power Functions, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 2
If you connect debug pin 5 to ground, raw data is always printed
5000 us is the (minimum) gap, after which the start of a new IR packet is assumed
20 us are subtracted from all marks and added to all spaces for decoding
@ -12,9 +13,6 @@ Send with: IrSender.sendNEC(0x2, 0x34, <numberOfRepeats>);
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
Protocol=NEC Address=0x2 Command=0x34 Raw-Data=0xCB34FD02 32 bits LSB first
Send with: IrSender.sendNEC(0x2, 0x34, <numberOfRepeats>);
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
@ -27,9 +25,6 @@ Send with: IrSender.sendNEC(0x4, 0x8, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x304, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x304, <numberOfRepeats>);
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
@ -42,13 +37,21 @@ Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
Protocol=PulseDistance Raw-Data=0x3BC3BC 56 bits LSB first
Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first
Send with:
uint32_t tRawData[]={0x43D8613C, 0x3BC3BC};
IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1700, 550, 600, &tRawData[0], 56, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, <millisofRepeatPeriod>, <numberOfRepeats>);
uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x3434 Raw-Data=0x34340102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x3434, <numberOfRepeats>);
Protocol=PulseWidth Raw-Data=0xDCBA9 52 bits LSB first
Send with:
uint32_t tRawData[]={0x87654321, 0xDCBA9};
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 350, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
Send with: IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 350, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x5634 Raw-Data=0x56340102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x5634, <numberOfRepeats>);
Protocol=Apple Address=0x2 Command=0x34 Raw-Data=0x23487EE 32 bits LSB first
Send with: IrSender.sendApple(0x2, 0x34, <numberOfRepeats>);
@ -62,24 +65,33 @@ Send with: IrSender.sendKaseikyo(0x102, 0x34, <numberOfRepeats>, 0x4711);
Protocol=Kaseikyo_Denon Address=0x102 Command=0x34 Raw-Data=0x4341020 48 bits LSB first
Send with: IrSender.sendKaseikyo_Denon(0x102, 0x34, <numberOfRepeats>);
Protocol=Denon Address=0x2 Command=0x34 Raw-Data=0x8D0 15 bits MSB first
Protocol=Denon Address=0x2 Command=0x34 Raw-Data=0x682 15 bits LSB first
Send with: IrSender.sendDenon(0x2, 0x34, <numberOfRepeats>);
Protocol=Denon Address=0x2 Command=0x34 Auto-Repeat gap=44550us Raw-Data=0xB2F 15 bits MSB first
Protocol=Denon Address=0x2 Command=0x34 Auto-Repeat gap=45650us Raw-Data=0x7962 15 bits LSB first
Protocol=Sharp Address=0x2 Command=0x34 Raw-Data=0x8D2 15 bits MSB first
Protocol=Sharp Address=0x2 Command=0x34 Raw-Data=0x4682 15 bits LSB first
Send with: IrSender.sendSharp(0x2, 0x34, <numberOfRepeats>);
Protocol=Sharp Address=0x2 Command=0x34 Auto-Repeat gap=44550us Raw-Data=0xB2D 15 bits MSB first
Protocol=Sharp Address=0x2 Command=0x34 Auto-Repeat gap=46400us Raw-Data=0x3962 15 bits LSB first
Protocol=Sony Address=0x2 Command=0x34 Raw-Data=0x134 12 bits LSB first
Send with: IrSender.sendSony(0x2, 0x34, <numberOfRepeats>);
Send with: IrSender.sendSony(0x2, 0x34, 2, 12);
Protocol=Sony Address=0x2 Command=0x34 Raw-Data=0x134 15 bits LSB first
Send with: IrSender.sendSony(0x2, 0x34, <numberOfRepeats>);
Send with: IrSender.sendSony(0x2, 0x34, 2, 15);
Protocol=Sony Address=0x102 Command=0x34 Raw-Data=0x8134 20 bits LSB first
Send with: IrSender.sendSony(0x102, 0x34, <numberOfRepeats>);
Send with: IrSender.sendSony(0x102, 0x34, 2, 20);
Protocol=Samsung Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendSamsung(0x102, 0x34, <numberOfRepeats>);
Protocol=Samsung Address=0x102 Command=0x5634 Raw-Data=0x56340102 32 bits LSB first
Send with: IrSender.sendSamsung(0x102, 0x5634, <numberOfRepeats>);
Protocol=Samsung48 Address=0x102 Command=0x5634 Raw-Data=0xA956 48 bits LSB first
Send with: IrSender.sendSamsung48(0x102, 0x5634, <numberOfRepeats>);
Protocol=RC5 Address=0x2 Command=0x34 Raw-Data=0x10B4 13 bits MSB first
Send with: IrSender.sendRC5(0x2, 0x34, <numberOfRepeats>);
@ -96,25 +108,71 @@ Send with: IrSender.sendSamsung(0x102, 0x34, <numberOfRepeats>);
Protocol=JVC Address=0x2 Command=0x34 Raw-Data=0x3402 16 bits LSB first
Send with: IrSender.sendJVC(0x2, 0x34, <numberOfRepeats>);
Protocol=LG Address=0x2 Command=0x3434 Raw-Data=0x23434E 28 bits MSB first
Send with: IrSender.sendLG(0x2, 0x3434, <numberOfRepeats>);
Protocol=Samsung Address=0x102 Command=0x5634 Raw-Data=0x56340102 32 bits LSB first
Send with: IrSender.sendSamsung(0x102, 0x5634, <numberOfRepeats>);
Protocol=LG Address=0x2 Command=0x5634 Raw-Data=0x256342 28 bits MSB first
Send with: IrSender.sendLG(0x2, 0x5634, <numberOfRepeats>);
Protocol=MagiQuest Address=0x102 Command=0x34 Raw-Data=0x6BCD0102 56 bits MSB first
Send with: IrSender.sendMagiQuest(0x6BCD0102, 0x34, <numberOfRepeats>);
Protocol=Bang&Olufsen Address=0x2 Command=0x34 Raw-Data=0x234 16 bits MSB first
Send with: IrSender.sendBang&Olufsen(0x2, 0x34, <numberOfRepeats>);
Protocol=BoseWave Address=0x0 Command=0x34 Raw-Data=0xCB34 16 bits LSB first
Send with: IrSender.sendBoseWave(0x0, 0x34, <numberOfRepeats>);
Protocol=FAST Address=0x0 Command=0x34 Raw-Data=0xCB34 16 bits LSB first
Send with: IrSender.sendFAST(0x0, 0x34, <numberOfRepeats>);
Protocol=Lego Address=0x2 Command=0x14 Raw-Data=0x2148 16 bits MSB first
Send with: IrSender.sendLego(0x2, 0x14, <numberOfRepeats>);
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179100us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=180450us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=178050us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179350us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179050us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179200us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179050us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179150us Raw-Data=0x2148 16 bits MSB first
Overflow detected
Try to increase the "RAW_BUFFER_LENGTH" value of 600 in ../src/ReceiveDemo.cpp
Protocol=NEC Address=0x3 Command=0x45 Raw-Data=0xBA45FC03 32 bits LSB first
Send with: IrSender.sendNEC(0x3, 0x45, <numberOfRepeats>);
Protocol=NEC Address=0x3 Command=0x45 Repeat gap=43250us
Protocol=NEC Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Send with: IrSender.sendNEC(0x203, 0x45, <numberOfRepeats>);
Protocol=NEC Address=0x203 Command=0x45 Repeat gap=47550us
Protocol=NEC Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Send with: IrSender.sendNEC(0x203, 0x45, <numberOfRepeats>);
Protocol=NEC2 Address=0x203 Command=0x45 Repeat gap=46500us Raw-Data=0xBA450203 32 bits LSB first
Protocol=Onkyo Address=0x203 Command=0x6745 Raw-Data=0x67450203 32 bits LSB first
Send with: IrSender.sendOnkyo(0x203, 0x6745, <numberOfRepeats>);
Protocol=Onkyo Address=0x203 Command=0x6745 Repeat gap=46550us
Protocol=Apple Address=0x3 Command=0x45 Raw-Data=0x34587EE 32 bits LSB first
Send with: IrSender.sendApple(0x3, 0x45, <numberOfRepeats>);
Protocol=Apple Address=0x3 Command=0x45 Repeat gap=31550us
Protocol=Panasonic Address=0x203 Command=0x45 Raw-Data=0x55452030 48 bits LSB first
Send with: IrSender.sendPanasonic(0x203, 0x45, <numberOfRepeats>);
Protocol=Panasonic Address=0x203 Command=0x45 Repeat gap=72550us Raw-Data=0x55452030 48 bits LSB first
Protocol=Kaseikyo Address=0x203 Command=0x45 Extra=0x4711 Raw-Data=0x56452033 48 bits LSB first
Send with: IrSender.sendKaseikyo(0x203, 0x45, <numberOfRepeats>, 0x4711);
Protocol=Kaseikyo Address=0x203 Command=0x45 Extra=0x4711 Repeat gap=66750us Raw-Data=0x56452033 48 bits LSB first
Protocol=Kaseikyo_Denon Address=0x203 Command=0x45 Raw-Data=0x55452030 48 bits LSB first
Send with: IrSender.sendKaseikyo_Denon(0x203, 0x45, <numberOfRepeats>);
Protocol=Kaseikyo_Denon Address=0x203 Command=0x45 Repeat gap=68300us Raw-Data=0x55452030 48 bits LSB first

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -74,7 +74,8 @@
// 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. See also IRremote.hpp line 142.
#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -97,14 +97,13 @@ void loop() {
if (IrReceiver.decode()) { // Grab an IR code
// At 115200 baud, printing takes 200 ms for NEC protocol and 70 ms for NEC repeat
Serial.println(); // blank line between entries
Serial.println(); // 2 blank lines between entries
IrReceiver.printIRResultShort(&Serial);
// Check if the buffer overflowed
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
Serial.println(F("Overflow detected"));
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
// see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
} else {
Serial.println(); // 2 blank lines between entries
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
}

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -123,14 +123,8 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Ready to send IR signals at pin 3"));
#endif
}
void loop() {
@ -165,6 +159,7 @@ void loop() {
* !!!Important!!! Enable receiving of the next value,
* since receiving has stopped after the end of the current received data packet.
*/
IrReceiver.restartAfterSend(); // Is a NOP if sending does not require a timer.
IrReceiver.resume(); // Enable receiving of the next value
}
}

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2021 Armin Joachimsmeyer
* Copyright (c) 2021-2023 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
@ -37,10 +37,12 @@
#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
//#define SEND_PWM_BY_TIMER
//#define USE_NO_SEND_PWM
//#define NO_LED_FEEDBACK_CODE // saves 500 bytes program memory
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
@ -63,14 +65,8 @@ void setup() {
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin 3"));
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
// For esp32 we use PWM generation by ledcWrite() for each pin.
@ -108,6 +104,7 @@ void send_ir_data() {
Serial.print(sAddress, HEX);
Serial.print(sCommand, HEX);
Serial.println(sRepeats, HEX);
Serial.flush(); // To avoid disturbing the software PWM generation by serial output interrupts
// clip repeats at 4
if (sRepeats > 4) {
@ -121,7 +118,7 @@ void receive_ir_data() {
if (IrReceiver.decode()) {
Serial.print(F("Decoded protocol: "));
Serial.print(getProtocolString(IrReceiver.decodedIRData.protocol));
Serial.print(F("Decoded raw data: "));
Serial.print(F(", decoded raw data: "));
#if (__INT_WIDTH__ < 32)
Serial.print(IrReceiver.decodedIRData.decodedRawData, HEX);
#else
@ -149,6 +146,8 @@ void loop() {
Serial.flush();
send_ir_data();
IrReceiver.restartAfterSend(); // Is a NOP if sending does not require a timer.
// wait for the receiver state machine to detect the end of a protocol
delay((RECORD_GAP_MICROS / 1000) + 5);
receive_ir_data();

View File

@ -1,38 +1,39 @@
START SendAndReceive.cpp from Apr 19 2021
Using library version 3.1.1
Ready to receive IR signals at pin D5
Ready to send IR signals at pin D6
Send signal mark duration is 7 us, pulse correction is 600 ns, total period is 26 us
START ../src/SendAndReceive.cpp from Feb 24 2023
Using library version 4.1.0
Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Universal Pulse Distance Width, at pin 2
Send IR signals at pin 3
Send signal mark duration 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
20 us are subtracted from all marks and added to all spaces for decoding
address=0x102 command=0x34 repeats=1
Sending: 0x102341
Decoded protocol: NECDecoded raw data: CB340102, decoded address: 102, decoded command: 34
Decoded protocol: NEC2, decoded raw data: CB340102, decoded address: 102, decoded command: 34
address=0x203 command=0x45 repeats=2
Sending: 0x203452
Decoded protocol: NECDecoded raw data: BA450203, decoded address: 203, decoded command: 45
Decoded protocol: NEC, decoded raw data: BA450203, decoded address: 203, decoded command: 45
address=0x304 command=0x56 repeats=3
Sending: 0x304563
Decoded protocol: NECDecoded raw data: A9560304, decoded address: 304, decoded command: 56
Decoded protocol: NEC, decoded raw data: A9560304, decoded address: 304, decoded command: 56
address=0x405 command=0x67 repeats=4
Sending: 0x405674
Decoded protocol: NECDecoded raw data: 98670405, decoded address: 405, decoded command: 67
Decoded protocol: NEC, decoded raw data: 98670405, decoded address: 405, decoded command: 67
address=0x506 command=0x78 repeats=5
Sending: 0x506785
Decoded protocol: NECDecoded raw data: 87780506, decoded address: 506, decoded command: 78
Decoded protocol: NEC, decoded raw data: 87780506, decoded address: 506, decoded command: 78
address=0x607 command=0x89 repeats=5
Sending: 0x607895
Decoded protocol: NECDecoded raw data: 76890607, decoded address: 607, decoded command: 89
Decoded protocol: NEC, decoded raw data: 76890607, decoded address: 607, decoded command: 89
address=0x708 command=0x9A repeats=5
Sending: 0x7089A5
Decoded protocol: NECDecoded raw data: 659A0708, decoded address: 708, decoded command: 9A
Decoded protocol: NEC, decoded raw data: 659A0708, decoded address: 708, decoded command: 9A
address=0x809 command=0xAB repeats=5
Sending: 0x809AB5
Decoded protocol: NECDecoded raw data: 54AB0809, decoded address: 809, decoded command: AB
Decoded protocol: NEC, decoded raw data: 54AB0809, decoded address: 809, decoded command: AB

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -33,7 +33,7 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>

View File

@ -1,8 +1,9 @@
START ../src/ReceiveDemo.cpp from Oct 17 2022
Using library version 4.0.0
START ../src/ReceiveDemo.cpp from Feb 24 2023
Using library version 4.1.0
Enabling IRin...
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
Debug button pin is 5
Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, FAST, Whynter, Lego Power Functions, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 2
If you connect debug pin 5 to ground, raw data is always printed
5000 us is the (minimum) gap, after which the start of a new IR packet is assumed
20 us are subtracted from all marks and added to all spaces for decoding
@ -12,9 +13,6 @@ Send with: IrSender.sendNEC(0x2, 0x34, <numberOfRepeats>);
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
Protocol=NEC Address=0x2 Command=0x34 Raw-Data=0xCB34FD02 32 bits LSB first
Send with: IrSender.sendNEC(0x2, 0x34, <numberOfRepeats>);
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
@ -27,9 +25,6 @@ Send with: IrSender.sendNEC(0x4, 0x8, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x304, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x304, <numberOfRepeats>);
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
@ -42,13 +37,21 @@ Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
Protocol=PulseDistance Raw-Data=0x3BC3BC 56 bits LSB first
Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first
Send with:
uint32_t tRawData[]={0x43D8613C, 0x3BC3BC};
IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1700, 550, 600, &tRawData[0], 56, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, <millisofRepeatPeriod>, <numberOfRepeats>);
uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x3434 Raw-Data=0x34340102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x3434, <numberOfRepeats>);
Protocol=PulseWidth Raw-Data=0xDCBA9 52 bits LSB first
Send with:
uint32_t tRawData[]={0x87654321, 0xDCBA9};
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 350, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
Send with: IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 350, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
Protocol=Onkyo Address=0x102 Command=0x5634 Raw-Data=0x56340102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x5634, <numberOfRepeats>);
Protocol=Apple Address=0x2 Command=0x34 Raw-Data=0x23487EE 32 bits LSB first
Send with: IrSender.sendApple(0x2, 0x34, <numberOfRepeats>);
@ -62,24 +65,33 @@ Send with: IrSender.sendKaseikyo(0x102, 0x34, <numberOfRepeats>, 0x4711);
Protocol=Kaseikyo_Denon Address=0x102 Command=0x34 Raw-Data=0x4341020 48 bits LSB first
Send with: IrSender.sendKaseikyo_Denon(0x102, 0x34, <numberOfRepeats>);
Protocol=Denon Address=0x2 Command=0x34 Raw-Data=0x8D0 15 bits MSB first
Protocol=Denon Address=0x2 Command=0x34 Raw-Data=0x682 15 bits LSB first
Send with: IrSender.sendDenon(0x2, 0x34, <numberOfRepeats>);
Protocol=Denon Address=0x2 Command=0x34 Auto-Repeat gap=44550us Raw-Data=0xB2F 15 bits MSB first
Protocol=Denon Address=0x2 Command=0x34 Auto-Repeat gap=45650us Raw-Data=0x7962 15 bits LSB first
Protocol=Sharp Address=0x2 Command=0x34 Raw-Data=0x8D2 15 bits MSB first
Protocol=Sharp Address=0x2 Command=0x34 Raw-Data=0x4682 15 bits LSB first
Send with: IrSender.sendSharp(0x2, 0x34, <numberOfRepeats>);
Protocol=Sharp Address=0x2 Command=0x34 Auto-Repeat gap=44550us Raw-Data=0xB2D 15 bits MSB first
Protocol=Sharp Address=0x2 Command=0x34 Auto-Repeat gap=46400us Raw-Data=0x3962 15 bits LSB first
Protocol=Sony Address=0x2 Command=0x34 Raw-Data=0x134 12 bits LSB first
Send with: IrSender.sendSony(0x2, 0x34, <numberOfRepeats>);
Send with: IrSender.sendSony(0x2, 0x34, 2, 12);
Protocol=Sony Address=0x2 Command=0x34 Raw-Data=0x134 15 bits LSB first
Send with: IrSender.sendSony(0x2, 0x34, <numberOfRepeats>);
Send with: IrSender.sendSony(0x2, 0x34, 2, 15);
Protocol=Sony Address=0x102 Command=0x34 Raw-Data=0x8134 20 bits LSB first
Send with: IrSender.sendSony(0x102, 0x34, <numberOfRepeats>);
Send with: IrSender.sendSony(0x102, 0x34, 2, 20);
Protocol=Samsung Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendSamsung(0x102, 0x34, <numberOfRepeats>);
Protocol=Samsung Address=0x102 Command=0x5634 Raw-Data=0x56340102 32 bits LSB first
Send with: IrSender.sendSamsung(0x102, 0x5634, <numberOfRepeats>);
Protocol=Samsung48 Address=0x102 Command=0x5634 Raw-Data=0xA956 48 bits LSB first
Send with: IrSender.sendSamsung48(0x102, 0x5634, <numberOfRepeats>);
Protocol=RC5 Address=0x2 Command=0x34 Raw-Data=0x10B4 13 bits MSB first
Send with: IrSender.sendRC5(0x2, 0x34, <numberOfRepeats>);
@ -96,25 +108,71 @@ Send with: IrSender.sendSamsung(0x102, 0x34, <numberOfRepeats>);
Protocol=JVC Address=0x2 Command=0x34 Raw-Data=0x3402 16 bits LSB first
Send with: IrSender.sendJVC(0x2, 0x34, <numberOfRepeats>);
Protocol=LG Address=0x2 Command=0x3434 Raw-Data=0x23434E 28 bits MSB first
Send with: IrSender.sendLG(0x2, 0x3434, <numberOfRepeats>);
Protocol=Samsung Address=0x102 Command=0x5634 Raw-Data=0x56340102 32 bits LSB first
Send with: IrSender.sendSamsung(0x102, 0x5634, <numberOfRepeats>);
Protocol=LG Address=0x2 Command=0x5634 Raw-Data=0x256342 28 bits MSB first
Send with: IrSender.sendLG(0x2, 0x5634, <numberOfRepeats>);
Protocol=MagiQuest Address=0x102 Command=0x34 Raw-Data=0x6BCD0102 56 bits MSB first
Send with: IrSender.sendMagiQuest(0x6BCD0102, 0x34, <numberOfRepeats>);
Protocol=Bang&Olufsen Address=0x2 Command=0x34 Raw-Data=0x234 16 bits MSB first
Send with: IrSender.sendBang&Olufsen(0x2, 0x34, <numberOfRepeats>);
Protocol=BoseWave Address=0x0 Command=0x34 Raw-Data=0xCB34 16 bits LSB first
Send with: IrSender.sendBoseWave(0x0, 0x34, <numberOfRepeats>);
Protocol=FAST Address=0x0 Command=0x34 Raw-Data=0xCB34 16 bits LSB first
Send with: IrSender.sendFAST(0x0, 0x34, <numberOfRepeats>);
Protocol=Lego Address=0x2 Command=0x14 Raw-Data=0x2148 16 bits MSB first
Send with: IrSender.sendLego(0x2, 0x14, <numberOfRepeats>);
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179100us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=180450us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=178050us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179350us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179050us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179200us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179050us Raw-Data=0x2148 16 bits MSB first
Protocol=Lego Address=0x2 Command=0x14 Auto-Repeat gap=179150us Raw-Data=0x2148 16 bits MSB first
Overflow detected
Try to increase the "RAW_BUFFER_LENGTH" value of 600 in ../src/ReceiveDemo.cpp
Protocol=NEC Address=0x3 Command=0x45 Raw-Data=0xBA45FC03 32 bits LSB first
Send with: IrSender.sendNEC(0x3, 0x45, <numberOfRepeats>);
Protocol=NEC Address=0x3 Command=0x45 Repeat gap=43250us
Protocol=NEC Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Send with: IrSender.sendNEC(0x203, 0x45, <numberOfRepeats>);
Protocol=NEC Address=0x203 Command=0x45 Repeat gap=47550us
Protocol=NEC Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Send with: IrSender.sendNEC(0x203, 0x45, <numberOfRepeats>);
Protocol=NEC2 Address=0x203 Command=0x45 Repeat gap=46500us Raw-Data=0xBA450203 32 bits LSB first
Protocol=Onkyo Address=0x203 Command=0x6745 Raw-Data=0x67450203 32 bits LSB first
Send with: IrSender.sendOnkyo(0x203, 0x6745, <numberOfRepeats>);
Protocol=Onkyo Address=0x203 Command=0x6745 Repeat gap=46550us
Protocol=Apple Address=0x3 Command=0x45 Raw-Data=0x34587EE 32 bits LSB first
Send with: IrSender.sendApple(0x3, 0x45, <numberOfRepeats>);
Protocol=Apple Address=0x3 Command=0x45 Repeat gap=31550us
Protocol=Panasonic Address=0x203 Command=0x45 Raw-Data=0x55452030 48 bits LSB first
Send with: IrSender.sendPanasonic(0x203, 0x45, <numberOfRepeats>);
Protocol=Panasonic Address=0x203 Command=0x45 Repeat gap=72550us Raw-Data=0x55452030 48 bits LSB first
Protocol=Kaseikyo Address=0x203 Command=0x45 Extra=0x4711 Raw-Data=0x56452033 48 bits LSB first
Send with: IrSender.sendKaseikyo(0x203, 0x45, <numberOfRepeats>, 0x4711);
Protocol=Kaseikyo Address=0x203 Command=0x45 Extra=0x4711 Repeat gap=66750us Raw-Data=0x56452033 48 bits LSB first
Protocol=Kaseikyo_Denon Address=0x203 Command=0x45 Raw-Data=0x55452030 48 bits LSB first
Send with: IrSender.sendKaseikyo_Denon(0x203, 0x45, <numberOfRepeats>);
Protocol=Kaseikyo_Denon Address=0x203 Command=0x45 Repeat gap=68300us Raw-Data=0x55452030 48 bits LSB first

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2023 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
@ -34,7 +34,7 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#define DISABLE_CODE_FOR_RECEIVER // Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
@ -119,6 +119,11 @@ void loop() {
IrSender.sendNEC(sAddress, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send NEC2 with 16 bit address"));
Serial.flush();
IrSender.sendNEC2(sAddress, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
if (sRepeats == 0) {
#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
/*
@ -137,7 +142,8 @@ void loop() {
/*
* !!! The next data occupies 136 bytes RAM !!!
*/
Serial.println(F("Send NEC 16 bit address=0xFB04 and command 0x08 with exact timing (16 bit array format)"));
Serial.println(
F("Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)"));
Serial.flush();
const uint16_t irSignal[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690,
@ -147,7 +153,7 @@ void loop() {
1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
delay(DELAY_AFTER_SEND);
#endif
/*
* With sendNECRaw() you can send 32 bit combined codes
*/
@ -156,24 +162,17 @@ void loop() {
IrSender.sendNECRaw(0x03040102, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with sendPulseDistanceWidthData()"));
// Header
IrSender.mark(9000);
IrSender.space(4500);
// LSB first + stop bit
IrSender.sendPulseDistanceWidthData(560, 1680, 560, 560, 0x03040102, 32, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
delay(DELAY_AFTER_SEND);
/*
* 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 positions of each byte.
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
Serial.println(F("Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3)"));
Serial.flush();
Serial.println(F("Send NEC with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first"));
IrSender.sendNECMSB(0x40802CD3, 32, false);
delay(DELAY_AFTER_SEND);
#endif
Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants"));
Serial.flush();
@ -193,11 +192,11 @@ void loop() {
Serial.println(F(" LSB first"));
Serial.flush();
#if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48,
PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
#else
IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
0, NO_REPEATS);
#endif
delay(DELAY_AFTER_SEND);
@ -206,39 +205,45 @@ void loop() {
#if __INT_WIDTH__ < 32
tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first
tRawData[1] = 0x805;
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48,
PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
#else
IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
0, NO_REPEATS);
#endif
delay(DELAY_AFTER_SEND);
Serial.println(F("Send generic 52 bit PulseDistance 0xDCBA9 87654321 LSB first"));
Serial.println(F("Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first"));
Serial.flush();
#if __INT_WIDTH__ < 32
# if __INT_WIDTH__ < 32
tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first
tRawData[1] = 0xDCBA9;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
#else
IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
#endif
tRawData[1] = 0xAFEDCBA9;
tRawData[2] = 0x5A;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
NO_REPEATS);
# else
IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
# endif
delay(DELAY_AFTER_SEND);
Serial.println(F("Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
#if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52,
PROTOCOL_IS_LSB_FIRST, 0, 0);
#else
IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
0, 0);
#endif
delay(DELAY_AFTER_SEND);
Serial.println(F("Send generic 32 bit PulseWidth 0x87654321 LSB first"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0);
delay(DELAY_AFTER_SEND);
}
Serial.println(F("Send Onkyo (NEC with 16 bit command)"));
@ -367,10 +372,10 @@ void loop() {
delay(DELAY_AFTER_SEND);
// Bang&Olufsen must be sent with 455 kHz
Serial.println(F("Send Bang&Olufsen"));
Serial.flush();
IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
// Serial.println(F("Send Bang&Olufsen"));
// Serial.flush();
// IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats);
// delay(DELAY_AFTER_SEND);
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
@ -378,6 +383,13 @@ void loop() {
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
IRSendData.protocol = FAST;
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
/*
* LEGO is difficult to receive because of its short marks and spaces
*/
@ -390,8 +402,8 @@ void loop() {
/*
* Force buffer overflow
*/
Serial.println(F("Force buffer overflow by sending 280 marks and spaces"));
for (unsigned int i = 0; i < 140; ++i) {
Serial.println(F("Force buffer overflow by sending 700 marks and spaces"));
for (unsigned int i = 0; i < 350; ++i) {
// 400 + 400 should be received as 8/8 and sometimes as 9/7 or 7/9 if compensation by MARK_EXCESS_MICROS is optimal.
// 210 + 540 = 750 should be received as 5/10 or 4/11 if compensation by MARK_EXCESS_MICROS is optimal.
IrSender.mark(210); // 8 pulses at 38 kHz

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -42,7 +42,7 @@
//#define USE_LG2_PROTOCOL // Try it if you do not have success with the default LG protocol
#define NUMBER_OF_COMMANDS_BETWEEN_PRINT_OF_MENU 5
#define DISABLE_CODE_FOR_RECEIVER // Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define INFO // Deactivate this to save program memory and suppress info output from the LG-AC driver.
//#define DEBUG // Activate this for more output from the LG-AC driver.
@ -70,17 +70,13 @@ delay(4000); // To be able to connect Serial monitor after reset or power up and
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
/*
* The IR library setup. That's all!
*/
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Ready to send IR signals at pin 3"));
#endif
Serial.println();
MyLG_Aircondition.setType(LG_IS_WALL_TYPE);

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -32,7 +32,7 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>
@ -62,14 +62,9 @@ void setup() {
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin 3"));
#endif
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
}
void loop() {

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -37,7 +37,7 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -50,6 +50,7 @@
//#define DECODE_LEGO_PF
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_FAST
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//#define DECODE_HASH // special decoder for all protocols

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -50,6 +50,7 @@
//#define DECODE_LEGO_PF
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_FAST
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//#define DECODE_HASH // special decoder for all protocols

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -13,7 +13,7 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
@ -27,15 +27,14 @@ void setup() {
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
Serial.print(F("Send IR signals at pin "));
Serial.println(IR_SEND_PIN);
/*
* The IR library setup. That's all!
*/
// IrSender.begin(); // Start with IR_SEND_PIN as send pin and if NO_LED_FEEDBACK_CODE is NOT defined, enable feedback LED at default feedback LED pin
IrSender.begin(DISABLE_LED_FEEDBACK); // Start with IR_SEND_PIN as send pin and disable feedback LED at default feedback LED pin
Serial.print(F("Send IR signals at pin "));
Serial.println(IR_SEND_PIN);
}
/*

View File

@ -11,14 +11,13 @@
* so if you require longer action, save the data (address + command) and handle it in the main loop.
* !!!!!!!!!!!!!!!!!!!!!
*
* FAST protocol is proprietary and a JVC protocol without address and with a shorter header.
* FAST takes 21 ms for sending and can be sent at a 40 ms period. It still supports parity.
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 2) + 1) * 526 = 39 * 560 = 20514 microseconds or 20.5 ms.
* - Repeats are sent as complete frames but in a 40 ms period / with a 19.5 ms distance.
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
@ -114,7 +113,8 @@ void setup() {
#if defined(ESP8266) || defined(ESP32)
Serial.println();
#endif
Serial.println(F("START " __FILE__ " from " __DATE__));
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR));
// Enables the interrupt generation on change of IR input signal
if (!initPCIInterruptForTinyReceiver()) {
Serial.println(F("No interrupt available for pin " STR(IR_RECEIVE_PIN))); // optimized out by the compiler, if not required :-)

View File

@ -6,6 +6,14 @@
* NEC protocol codes are sent in standard format with 8bit address and 8 bit command as in SimpleSender example.
* Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible).
*
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
@ -13,7 +21,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-20232 Armin Joachimsmeyer
* Copyright (c) 2022-2023 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
@ -52,12 +60,7 @@ void setup() {
Serial.begin(115200);
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRTINY));
/*
* The IR library setup. That's all!
*/
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR));
Serial.print(F("Send IR signals at pin "));
Serial.println(IR_SEND_PIN);
}

View File

@ -143,8 +143,8 @@
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 13 // D7
#define APPLICATION_PIN 0 // D3
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()

View File

@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2023 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
@ -39,7 +39,7 @@
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
//#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 140 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 150 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# else
#define RAW_BUFFER_LENGTH 200 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# endif
@ -51,8 +51,9 @@
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
#define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
//#define USE_MSB_DECODING_FOR_DISTANCE_DECODER
// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
#define MARK_EXCESS_MICROS 50 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
//#define TRACE // For internal usage
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@ -89,6 +90,7 @@
//#define DECODE_LEGO_PF
#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
#define DECODE_FAST
#endif
#include <IRremote.hpp>
@ -225,7 +227,7 @@ void checkReceivedRawData(IRRawDataType aRawData) {
}
#if defined(DECODE_DISTANCE_WIDTH)
void checkReceivedArray(uint32_t *aRawDataArrayPointer, uint8_t aArraySize) {
void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize) {
// wait until signal has received
while (!sDataJustReceived) {
};
@ -293,38 +295,36 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
#endif
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
IrReceiver.decodedIRData.flags = false; // yes we have recognized the flag :-)
Serial.println(F("Overflow detected"));
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
// see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
} else {
}
#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);
}
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 == 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);
}
}
@ -370,6 +370,12 @@ void loop() {
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send NEC2 with 16 bit address"));
Serial.flush();
IrSender.sendNEC2(sAddress, sCommand, sRepeats);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
if (sAddress == 0xFFF1) {
@ -400,7 +406,6 @@ void loop() {
IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
checkReceive(0xFB04 & 0xFF, 0x08);
delay(DELAY_AFTER_SEND);
# endif
/*
* With sendNECRaw() you can send 32 bit codes directly, i.e. without parity etc.
@ -422,12 +427,13 @@ void loop() {
IrSender.sendNECMSB(0x40802CD3, 32, false);
checkReceive(0x0102, 0x34);
delay(DELAY_AFTER_SEND);
# endif
# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants"));
Serial.flush();
# if __INT_WIDTH__ < 32
IRRawDataType tRawData[] = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
IRRawDataType tRawData[] = { 0xB02002, 0xA010, 0x0 }; // LSB of tRawData[0] is sent first
IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
checkReceive(0x0B, 0x10);
# else
@ -443,12 +449,12 @@ void loop() {
Serial.println(F(" LSB first"));
Serial.flush();
# if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST, 0,
NO_REPEATS);
checkReceive(0x0B, 0x10);
# else
IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
0, NO_REPEATS);
checkReceivedRawData(0xA010B02002);
# endif
delay(DELAY_AFTER_SEND);
@ -458,31 +464,29 @@ void loop() {
# if __INT_WIDTH__ < 32
tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first
tRawData[1] = 0x805;
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_MSB_FIRST, 0,
NO_REPEATS);
checkReceive(0x0B, 0x10);
# else
IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
checkReceivedRawData(0x40040D000805);
# endif
delay(DELAY_AFTER_SEND);
# endif
# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
# if defined(DECODE_DISTANCE_WIDTH)
# if defined(DISTANCE_DO_MSB_DECODING)
# if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
Serial.println(F("Send generic 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first"));
Serial.flush();
# if __INT_WIDTH__ < 32
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);
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST, 0,
NO_REPEATS);
checkReceivedArray(tRawData, 2);
# else
IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0x43D8613CBC3B, 52, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0x43D8613CBC3B, 52, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
checkReceivedRawData(0x43D8613CBC3B);
# endif
delay(DELAY_AFTER_SEND);
@ -491,28 +495,34 @@ void loop() {
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
# if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST, 0, 0);
checkReceivedArray(tRawData, 2);
# else
IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0x123456789ABC, 52, PROTOCOL_IS_MSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0x123456789ABC, 52, PROTOCOL_IS_MSB_FIRST, 0, 0);
checkReceivedRawData(0x123456789ABC);
# endif
delay(DELAY_AFTER_SEND);
# else // defined(DISTANCE_DO_MSB_DECODING)
Serial.println(F("Send generic 52 bit PulseDistance 0xDCBA9 87654321 LSB first"));
Serial.println(F("Send generic 32 bit PulseWidth 0x43D8613C MSB first"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x43D8613C, 32, PROTOCOL_IS_MSB_FIRST, 0, 0);
checkReceivedRawData(0x43D8613C);
delay(DELAY_AFTER_SEND);
# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
Serial.println(F("Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first"));
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first
tRawData[1] = 0xDCBA9;
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);
tRawData[1] = 0xAFEDCBA9;
tRawData[2] = 0x5A;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
NO_REPEATS);
checkReceivedArray(tRawData, 3);
# else
IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, 0, NO_REPEATS);
checkReceivedRawData(0xDCBA987654321);
IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
checkReceivedArray(tRawData, 2);
# endif
delay(DELAY_AFTER_SEND);
@ -520,16 +530,22 @@ void loop() {
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
# if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
tRawData[1] = 0xDCBA9;
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedArray(tRawData, 2);
# else
IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedRawData(0xDCBA987654321);
# endif
delay(DELAY_AFTER_SEND);
# endif // defined(DISTANCE_DO_MSB_DECODING)
Serial.println(F("Send generic 32 bit PulseWidth 0x87654321 LSB first"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedRawData(0x87654321);
delay(DELAY_AFTER_SEND);
# endif // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
# endif // defined(DECODE_DISTANCE_WIDTH)
# if defined(DECODE_MAGIQUEST)
@ -537,13 +553,11 @@ void loop() {
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left
tRawData[1] = 0x017619; // 9 magnitude and 8 checksum. 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);
tRawData[1] = 0x017619; // We send only 23 instead of 24 bite here! 19 is the checksum
IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData[0], 55, PROTOCOL_IS_MSB_FIRST, 0, 0);
# else
// 0x6BCDFF00 is shifted 1 left
IrSender.sendPulseDistanceWidth(38, 287, 864, 576, 576, 287, 864, 0xD79BFE017619, 55, PROTOCOL_IS_MSB_FIRST,
SEND_NO_STOP_BIT, 0, 0);
// 0xD79BFE00 is 0x6BCDFF00 is shifted 1 left
IrSender.sendPulseDistanceWidth(38, 287, 864, 576, 576, 287, 864, 0xD79BFE017619, 55, PROTOCOL_IS_MSB_FIRST, 0, 0);
# endif
checkReceive(0xFF00, 0x176);
if (IrReceiver.decodedIRData.decodedRawData != 0x6BCDFF00) {
@ -557,7 +571,7 @@ void loop() {
Serial.println();
}
delay(DELAY_AFTER_SEND);
# endif
# endif // defined(DECODE_MAGIQUEST)
}
#endif // if FLASHEND >= 0x3FFF
@ -754,6 +768,16 @@ void loop() {
delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_FAST)
IRSendData.protocol = FAST;
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
checkReceive(0, IRSendData.command & 0xFF);
delay(DELAY_AFTER_SEND);
#endif
/*
* LEGO is skipped, since it is difficult to receive because of its short marks and spaces
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -66,7 +66,7 @@ sendLegoPowerFunctions KEYWORD2
sendMagiQuest KEYWORD2
sendPronto KEYWORD2
sendMagiQuest KEYWORD2
sendFAST KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
@ -97,6 +97,7 @@ BOSEWAVE LITERAL1
LEGO_PF LITERAL1
MAGIQUEST LITERAL1
WHYNTER LITERAL1
FAST LITERAL1
UNKNOWN LITERAL1
IR_RECEIVE_PIN LITERAL1
IR_SEND_PIN LITERAL1

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/z3t0/Arduino-IRremote.git"
},
"version": "4.0.0",
"version": "4.1.0",
"frameworks": "arduino",
"platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"],
"authors" :

View File

@ -1,9 +1,9 @@
name=IRremote
version=4.0.0
version=4.1.0
author=shirriff, z3t0, ArminJo
maintainer=Armin Joachimsmeyer <armin.arduino@gmail.com>
sentence=Send and receive infrared signals with multiple protocols
paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BangOlufsen, BoseWave, Lego, Whynter, MagiQuest.<br/><br/><b>New: </b>Introduced common structure PulseDistanceWidthProtocolConstants. Improved Magiquest protocol.<br/><a href="https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md">Release notes</a><br/>
paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BangOlufsen, BoseWave, Lego, Whynter, FAST, MagiQuest.<br/><br/><b>New: </b>Added FAST Protocol. Changed some function signatures. Improved handling of PULSE_DISTANCE + PULSE_WIDTH protocols.<br/><a href="https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md">Release notes</a><br/>
category=Communication
url=https://github.com/Arduino-IRremote/Arduino-IRremote
architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040

View File

@ -68,23 +68,21 @@ typedef enum {
LEGO_PF,
MAGIQUEST,
WHYNTER,
FAST
} decode_type_t;
struct PulseDistanceWidthProtocolConstants {
decode_type_t ProtocolIndex;
uint_fast8_t FrequencyKHz;
unsigned int HeaderMarkMicros;
unsigned int HeaderSpaceMicros;
unsigned int OneMarkMicros;
unsigned int OneSpaceMicros;
unsigned int ZeroMarkMicros;
unsigned int ZeroSpaceMicros;
bool isMSBFirst;
bool hasStopBit;
unsigned int RepeatPeriodMillis;
void (*SpecialSendRepeatFunction)(); // using non member functions here saves up to 250 bytes for send demo
// void (IRsend::*SpecialSendRepeatFunction)();
#define SIRCS_12_PROTOCOL 12
#define SIRCS_15_PROTOCOL 15
#define SIRCS_20_PROTOCOL 20
struct DistanceWidthTimingInfoStruct {
uint16_t HeaderMarkMicros;
uint16_t HeaderSpaceMicros;
uint16_t OneMarkMicros;
uint16_t OneSpaceMicros;
uint16_t ZeroMarkMicros;
uint16_t ZeroSpaceMicros;
};
/*
@ -95,19 +93,13 @@ struct PulseDistanceWidthProtocolConstants {
#define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 ///< The current repeat frame is a repeat, that is always sent after a regular frame and cannot be avoided. Only specified for protocols DENON, and LEGO.
#define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< The current (autorepeat) frame violated parity check.
#define IRDATA_FLAGS_TOGGLE_BIT 0x08 ///< Is set if RC5 or RC6 toggle bit is set
#define IRDATA_TOGGLE_BIT_MASK 0x08 ///< deprecated -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, or in decodedRawDataArray)
#define IRDATA_FLAGS_WAS_OVERFLOW 0x40 ///< irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag
#define IRDATA_FLAGS_IS_MSB_FIRST 0x80 ///< Value is mainly determined by the (known) protocol
#define IRDATA_FLAGS_IS_LSB_FIRST 0x00
// deprecated
#define IRDATA_TOGGLE_BIT_MASK 0x08 ///< is set if RC5 or RC6 toggle bit is set
#if __INT_WIDTH__ < 32
#define RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / 64) + 1) // The -2 is for initial gap + stop bit mark, 64 mark + spaces for 32 bit.
#else
#define RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / 128) + 1) // The -2 is for initial gap + stop bit mark, 128 mark + spaces for 64 bit.
#endif
#define RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / (2 * BITS_IN_RAW_DATA_TYPE)) + 1) // The -2 is for initial gap + stop bit mark, 128 mark + spaces for 64 bit.
/**
* Data structure for the user application, available as decodedIRData.
* Filled by decoders and read by print functions or user application.
@ -117,17 +109,35 @@ struct IRData {
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
IRRawDataType decodedRawData; ///< Up to 32/64 bit decoded raw data, to be used for send functions.
#if defined(DECODE_DISTANCE_WIDTH)
// This replaces the address, command, extra and decodedRawData in case of protocol == PULSE_DISTANCE or -rather seldom- protocol == PULSE_WIDTH.
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo; // 12 bytes
IRRawDataType decodedRawDataArray[RAW_DATA_ARRAY_SIZE]; ///< 32/64 bit decoded raw data, to be used for send function.
#endif
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
irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by receiving ISR.
};
#define PROTOCOL_IS_LSB_FIRST false
#define PROTOCOL_IS_MSB_FIRST true
struct PulseDistanceWidthProtocolConstants {
decode_type_t ProtocolIndex;
uint_fast8_t FrequencyKHz;
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo;
uint8_t Flags;
unsigned int RepeatPeriodMillis;
void (*SpecialSendRepeatFunction)(); // using non member functions here saves up to 250 bytes for send demo
// void (IRsend::*SpecialSendRepeatFunction)();
};
/*
* Definitions for member PulseDistanceWidthProtocolConstants.Flags
*/
#define SUPPRESS_STOP_BIT_FOR_THIS_DATA 0x20
#define PROTOCOL_IS_MSB_FIRST IRDATA_FLAGS_IS_MSB_FIRST
#define PROTOCOL_IS_LSB_FIRST IRDATA_FLAGS_IS_LSB_FIRST
// 2 definitions for deprecated parameter bool aSendStopBit
#define SEND_STOP_BIT true
#define SEND_NO_STOP_BIT false
/*
* Carrier frequencies for various protocols

View File

@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2022 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
* Copyright (c) 2009-2023 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
@ -77,6 +77,7 @@ const char string_BoseWave[] PROGMEM = "BoseWave";
const char string_Lego[] PROGMEM = "Lego";
const char string_MagiQuest[] PROGMEM = "MagiQuest";
const char string_Whynter[] PROGMEM = "Whynter";
const char string_FAST[] PROGMEM = "FAST";
/*
* !!Must be the same order as in decode_type_t in IRProtocol.h!!!
@ -84,10 +85,10 @@ const char string_Whynter[] PROGMEM = "Whynter";
const char *const ProtocolNames[]
PROGMEM = { string_Unknown, string_PulseWidth, 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_Samsung48, string_SamsungLG, string_Sharp,
string_Sony
string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_Samsung48, 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, string_FAST
#endif
};
@ -164,6 +165,10 @@ namespace PrintULL {
*
*/
void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) {
if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) {
aSerial->println(F("Overflow"));
return;
}
aSerial->print(F("Protocol="));
aSerial->print(getProtocolString(aIRDataPtr->protocol));
if (aIRDataPtr->protocol == UNKNOWN) {

View File

@ -44,7 +44,12 @@
#else
//#define LOCAL_TRACE // This enables debug output only for this file
#endif
/*
* Low level hardware timing measurement
*/
//#define _IR_MEASURE_TIMING // for ISR
//#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start()
//
/*
* Check for additional characteristics of timing like length of mark for a constant mark protocol,
* where space length determines the bit value. Requires up to 194 additional bytes of program memory.
@ -116,8 +121,6 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) {
* => Minimal CPU frequency is 4 MHz
*
**********************************************************************************************************************/
//#define _IR_MEASURE_TIMING
//#define _IR_TIMING_TEST_PIN 10 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start()
#if defined(TIMER_INTR_NAME)
ISR (TIMER_INTR_NAME) // for ISR definitions
#else
@ -348,7 +351,7 @@ void IRrecv::startWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
}
/**
* Restarts receiver after send. Is a NOP if sending does not require a timer
* Restarts receiver after send. Is a NOP if sending does not require a timer.
*/
void IRrecv::restartAfterSend() {
#if defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER)
@ -391,9 +394,6 @@ void IRrecv::resume() {
if (irparams.StateForISR == IR_REC_STATE_STOP) {
irparams.StateForISR = IR_REC_STATE_IDLE;
}
#if defined(SEND_PWM_BY_TIMER)
// TIMER_ENABLE_RECEIVE_INTR; // normally it is stopped by send()
#endif
}
/**
@ -403,9 +403,6 @@ void IRrecv::resume() {
void IRrecv::initDecodedIRData() {
if (irparams.OverflowFlag) {
// Copy overflow flag to decodedIRData.flags and reset it
irparams.OverflowFlag = false;
irparams.rawlen = 0; // otherwise we have OverflowFlag again at next ISR call
decodedIRData.flags = IRDATA_FLAGS_WAS_OVERFLOW;
#if defined(LOCAL_DEBUG)
Serial.print(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of "));
@ -543,6 +540,13 @@ bool IRrecv::decode() {
}
#endif
#if defined(DECODE_FAST)
IR_TRACE_PRINTLN(F("Attempting FAST decode"));
if (decodeFAST()) {
return true;
}
#endif
#if defined(DECODE_WHYNTER)
IR_TRACE_PRINTLN(F("Attempting Whynter decode"));
if (decodeWhynter()) {
@ -626,10 +630,10 @@ bool IRrecv::decode() {
* @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first.
* @return true If decoding was successful
*/
bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
unsigned int aZeroMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroSpaceMicros, bool aMSBfirst) {
bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros,
uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
unsigned int *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
@ -686,15 +690,17 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8
if (aMSBfirst) {
tDecodedData <<= 1;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
bool tBitValue;
if (isPulseDistanceProtocol) {
// Check for variable length space indicating a 1 or 0
tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros);
tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // tSpaceTicks is initialized here, even if some compiler are complaining!
} else {
// Check for variable length mark indicating a 1 or 0
tBitValue = matchMark(tMarkTicks, aOneMarkMicros);
tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // tMarkTicks is initialized here, even if some compiler are complaining!
}
#pragma GCC diagnostic pop
if (tBitValue) {
// It's a 1 -> set the bit
if (aMSBfirst) {
@ -775,20 +781,20 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8
bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
uint_fast8_t aStartOffset) {
return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->OneMarkMicros,
aProtocolConstants->ZeroMarkMicros, aProtocolConstants->OneSpaceMicros, aProtocolConstants->ZeroSpaceMicros,
aProtocolConstants->isMSBFirst);
return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aProtocolConstants->Flags);
}
/*
* Static variables for the getBiphaselevel function
*/
uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array
unsigned int sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing.
uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing.
uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals.
unsigned int sBiphaseTimeUnit;
uint16_t sBiphaseTimeUnit;
void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, unsigned int aBiphaseTimeUnit) {
void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) {
sBiphaseDecodeRawbuffOffset = aRCDecodeRawbuffOffset;
sBiphaseTimeUnit = aBiphaseTimeUnit;
sBiphaseUsedTimingIntervals = 0;
@ -823,10 +829,10 @@ uint_fast8_t IRrecv::getBiphaselevel() {
* Setup data if sUsedTimingIntervals is 0
*/
if (sBiphaseUsedTimingIntervals == 0) {
unsigned int tCurrentTimingWith = decodedIRData.rawDataPtr->rawbuf[sBiphaseDecodeRawbuffOffset];
unsigned int tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS;
uint16_t tCurrentTimingWith = decodedIRData.rawDataPtr->rawbuf[sBiphaseDecodeRawbuffOffset];
uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS;
if (matchTicks(tCurrentTimingWith, (sBiphaseTimeUnit) + tMarkExcessCorrection)) {
if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) {
sBiphaseCurrentTimingIntervals = 1;
} else if (matchTicks(tCurrentTimingWith, (2 * sBiphaseTimeUnit) + tMarkExcessCorrection)) {
sBiphaseCurrentTimingIntervals = 2;
@ -861,7 +867,7 @@ uint_fast8_t IRrecv::getBiphaselevel() {
* Use a tolerance of 20% to enable e.g. 500 and 600 (NEC timing) to be equal
* @return 0 if newval is shorter, 1 if newval is equal, and 2 if newval is longer
*/
uint_fast8_t IRrecv::compare(unsigned int oldval, unsigned int newval) {
uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
if (newval * 10 < oldval * 8) {
return 0;
}
@ -949,14 +955,14 @@ bool IRrecv::decodeHashOld(decode_results *aResults) {
*/
bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants) {
// Check header "mark" and "space"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], aProtocolConstants->HeaderMarkMicros)) {
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros)) {
#if defined(LOCAL_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)) {
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros)) {
#if defined(LOCAL_TRACE)
Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
Serial.println(F(": Header space length is wrong"));
@ -971,7 +977,7 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants
* And if really required, it can be enabled here, or done manually in user program.
* And we have still no RC6 toggle bit check for detecting a second press on the same button.
*/
void IRrecv::checkForRepeatSpaceTicksAndSetFlag(unsigned int aMaximumRepeatSpaceTicks) {
void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks) {
if (decodedIRData.rawDataPtr->rawbuf[0] < aMaximumRepeatSpaceTicks
#if defined(ENABLE_FULL_REPEAT_CHECK)
&& decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 85 bytes program space */
@ -985,7 +991,7 @@ void IRrecv::checkForRepeatSpaceTicksAndSetFlag(unsigned int aMaximumRepeatSpace
* Match function without compensating for marks exceeded or spaces shortened by demodulator hardware
* Currently not used
*/
bool matchTicks(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
#if defined(LOCAL_TRACE)
Serial.print(F("Testing: "));
Serial.print(TICKS_LOW(aMatchValueMicros), DEC);
@ -1005,14 +1011,14 @@ bool matchTicks(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
return passed;
}
bool MATCH(unsigned int measured_ticks, unsigned int desired_us) {
bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
return matchTicks(measured_ticks, desired_us);
}
/**
* Compensate for marks exceeded by demodulator hardware
*/
bool matchMark(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
#if defined(LOCAL_TRACE)
Serial.print(F("Testing mark (actual vs desired): "));
Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
@ -1038,14 +1044,14 @@ bool matchMark(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
return passed;
}
bool MATCH_MARK(unsigned int measured_ticks, unsigned int desired_us) {
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) {
return matchMark(measured_ticks, desired_us);
}
/**
* Compensate for spaces shortened by demodulator hardware
*/
bool matchSpace(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
#if defined(LOCAL_TRACE)
Serial.print(F("Testing space (actual vs desired): "));
Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
@ -1071,7 +1077,7 @@ bool matchSpace(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros) {
return passed;
}
bool MATCH_SPACE(unsigned int measured_ticks, unsigned int desired_us) {
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) {
return matchSpace(measured_ticks, desired_us);
}
@ -1150,6 +1156,9 @@ void printActiveIRProtocols(Print *aSerial) {
#if defined(DECODE_BEO)
aSerial->print(F("Bang & Olufsen, "));
#endif
#if defined(DECODE_FAST)
aSerial->print(F("FAST, "));
#endif
#if defined(DECODE_WHYNTER)
aSerial->print(F("Whynter, "));
#endif
@ -1192,6 +1201,28 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aChec
return false;
}
void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo) {
aSerial->print(aDistanceWidthTimingInfo->HeaderMarkMicros);
aSerial->print(F(", "));
aSerial->print(aDistanceWidthTimingInfo->HeaderSpaceMicros);
aSerial->print(F(", "));
aSerial->print(aDistanceWidthTimingInfo->OneMarkMicros);
aSerial->print(F(", "));
aSerial->print(aDistanceWidthTimingInfo->OneSpaceMicros);
aSerial->print(F(", "));
aSerial->print(aDistanceWidthTimingInfo->ZeroMarkMicros);
aSerial->print(F(", "));
aSerial->print(aDistanceWidthTimingInfo->ZeroSpaceMicros);
}
uint32_t IRrecv::getTotalDurationOfRawData() {
uint16_t tSumOfDurationTicks = 0;
for (uint_fast8_t i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i];
}
return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK;
}
/**
* Function to print values and flags of IrReceiver.decodedIRData in one line.
* Ends with println().
@ -1271,34 +1302,14 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
/*
* Pulse distance or pulse width here
*/
aSerial->print("PulseDistanceWidth");
if(tNumberOfArrayData > 1) {
aSerial->print("PulseDistanceWidthFromArray(38, ");
aSerial->print("FromArray(38, ");
} else {
aSerial->print("PulseDistanceWidth(38, ");
aSerial->print("(38, ");
}
aSerial->print("PulseDistanceWidthFromArray(38, ");
aSerial->print((decodedIRData.extra >> 8) * MICROS_PER_TICK); // aHeaderMarkMicros
aSerial->print(F(", "));
aSerial->print((decodedIRData.extra & 0xFF) * MICROS_PER_TICK);// aHeaderSpaceMicros
aSerial->print(F(", "));
printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo);
// address = tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << 8) | tSpaceTicksLong
// command = tMarkTicksShort << 8) | tSpaceTicksShort
aSerial->print((decodedIRData.address >> 8) * MICROS_PER_TICK);// aOneMarkMicros
aSerial->print(F(", "));
if (decodedIRData.protocol == PULSE_DISTANCE) {
aSerial->print((decodedIRData.address & 0xFF) * MICROS_PER_TICK);// aOneSpaceMicros
} else {
aSerial->print((decodedIRData.command & 0xFF) * MICROS_PER_TICK);// aOneSpaceMicros
}
aSerial->print(F(", "));
aSerial->print((decodedIRData.command >> 8) * MICROS_PER_TICK);// aZeroMarkMicros
aSerial->print(F(", "));
if (decodedIRData.protocol == PULSE_DISTANCE) {
aSerial->print((decodedIRData.command & 0xFF) * MICROS_PER_TICK);// aZeroSpaceMicros
}else {
aSerial->print((decodedIRData.address & 0xFF) * MICROS_PER_TICK);// aZeroSpaceMicros
}
if(tNumberOfArrayData > 1) {
aSerial->print(F(", &tRawData[0], "));
} else {
@ -1311,26 +1322,23 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
aSerial->print(F(", "));
}
aSerial->print(decodedIRData.numberOfBits);// aNumberOfBits
aSerial->print(F(", PROTOCOL_IS_"));
if (decodedIRData.flags & IRDATA_FLAGS_IS_MSB_FIRST) {
aSerial->print(F(", PROTOCOL_IS_MSB_FIRST"));
aSerial->print('M');
} else {
aSerial->print(F(", PROTOCOL_IS_LSB_FIRST"));
aSerial->print('L');
}
if (decodedIRData.protocol == PULSE_DISTANCE) {
aSerial->print(F(", SEND_STOP_BIT"));
} else {
aSerial->print(F(", SEND_NO_STOP_BIT")); // assume no stop bit for pulse width like for Magiquest.
}
aSerial->print(F(", <millisofRepeatPeriod>, <numberOfRepeats>"));
aSerial->print(F("SB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>"));
}
#endif
#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && decodedIRData.protocol == KASEIKYO) {
aSerial->print(F(", 0x"));
aSerial->print(decodedIRData.extra, HEX);
}
#endif
aSerial->print(F(");"));
if (decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) {
aSerial->print(
F(
" Because we have non standard extra data, you may have to use the send function, which accepts raw data like sendNECRaw() or sendRC6Raw(). Extra=0x"));
aSerial->print(decodedIRData.extra, HEX);
}
aSerial->println();
}
}
@ -1386,9 +1394,11 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
* @param aOutputMicrosecondsInsteadOfTicks Output the (rawbuf_values * MICROS_PER_TICK) for better readability.
*/
void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
uint8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Get it once here in order to print quite consistent data, even if ISR is running
// Print Raw data
aSerial->print(F("rawData["));
aSerial->print(decodedIRData.rawDataPtr->rawlen, DEC);
aSerial->print(tRawlen, DEC);
aSerial->println(F("]: "));
/*
@ -1425,7 +1435,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
uint32_t tDuration;
uint16_t tSumOfDurationTicks = 0;
for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
for (i = 1; i < tRawlen; i++) {
auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i];
if (aOutputMicrosecondsInsteadOfTicks) {
tDuration = tCurrentTicks * MICROS_PER_TICK;
@ -1452,7 +1462,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
}
aSerial->print(tDuration, DEC);
if ((i & 1) && (i + 1) < decodedIRData.rawDataPtr->rawlen) {
if ((i & 1) && (i + 1) < tRawlen) {
aSerial->print(','); //',' not required for last one
}
@ -1728,6 +1738,9 @@ bool IRrecv::decode(decode_results *aResults) {
}
/** @}*/
#if defined(_IR_MEASURE_TIMING)
#undef _IR_MEASURE_TIMING
#endif
#if defined(LOCAL_TRACE)
#undef LOCAL_TRACE
#endif

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2022 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
* Copyright (c) 2009-2023 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
@ -44,6 +44,12 @@
//#define LOCAL_TRACE // This enables debug output only for this file
#endif
/*
* Low level hardware timing measurement
*/
//#define _IR_MEASURE_TIMING // for mark()
//#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at begin()
//
/*
* This improves readability of code by avoiding a lot of #if defined clauses
*/
@ -77,6 +83,9 @@ void IRsend::begin(){
# if !defined(NO_LED_FEEDBACK_CODE)
setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
# endif
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
}
/**
@ -146,6 +155,12 @@ void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t
}
#endif // defined(IR_SEND_PIN)
/**
* Interprets and sends a IRData structure.
* @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 if data is no repeat.
* @return 1 if data sent, 0 if no data sent (i.e. for BANG_OLUFSEN, which is currently not supported here)
*/
/**
* Interprets and sends a IRData structure.
* @param aIRSendData The values of protocol, address, command and repeat flag are taken for sending.
@ -261,6 +276,10 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) {
// we have a 32 bit ID/address
sendMagiQuest(aIRSendData->decodedRawData, tCommand);
} else if (tProtocol == FAST) {
// We have only 8 bit command
sendFAST(tCommand, aNumberOfRepeats);
} else if (tProtocol == LEGO_PF) {
sendLegoPowerFunctions(tAddress, tCommand, tCommand >> 4, tIsRepeat); // send 5 autorepeats
#endif
@ -271,6 +290,123 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) {
return 1;
}
/**
* Simple version of write without support for MAGIQUEST and numberOfBits for SONY protocol
* @param aNumberOfRepeats If aNumberOfRepeats < 0 then only a special repeat frame without leading and trailing space
* will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction().
*/
size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) {
// switch (aProtocol) { // 26 bytes bigger than if, else if, else
// case NEC:
// sendNEC(aAddress, aCommand, aNumberOfRepeats, tSendRepeat);
// break;
// case SAMSUNG:
// sendSamsung(aAddress, aCommand, aNumberOfRepeats);
// break;
// case SONY:
// sendSony(aAddress, aCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
// break;
// case PANASONIC:
// sendPanasonic(aAddress, aCommand, aNumberOfRepeats);
// break;
// case DENON:
// sendDenon(aAddress, aCommand, aNumberOfRepeats);
// break;
// case SHARP:
// sendSharp(aAddress, aCommand, aNumberOfRepeats);
// break;
// case JVC:
// sendJVC((uint8_t) aAddress, (uint8_t) aCommand, aNumberOfRepeats); // casts are required to specify the right function
// break;
// case RC5:
// sendRC5(aAddress, aCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
// break;
// case RC6:
// // No toggle for repeats// sendRC6(aAddress, aCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
// break;
// default:
// break;
// }
/*
* Order of protocols is in guessed relevance :-)
*/
if (aProtocol == NEC) {
sendNEC(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SAMSUNG) {
sendSamsung(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SAMSUNG48) {
sendSamsung48(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SAMSUNG_LG) {
sendSamsungLG(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SONY) {
sendSony(aAddress, aCommand, aNumberOfRepeats, SIRCS_12_PROTOCOL);
} else if (aProtocol == PANASONIC) {
sendPanasonic(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == DENON) {
sendDenon(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SHARP) {
sendSharp(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == LG) {
sendLG(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == JVC) {
sendJVC((uint8_t) aAddress, (uint8_t) aCommand, aNumberOfRepeats); // casts are required to specify the right function
} else if (aProtocol == RC5) {
sendRC5(aAddress, aCommand, aNumberOfRepeats, (aNumberOfRepeats > 0)); // No toggle for repeats
} else if (aProtocol == RC6) {
sendRC6(aAddress, aCommand, aNumberOfRepeats, (aNumberOfRepeats > 0)); // No toggle for repeats
} else if (aProtocol == KASEIKYO_JVC) {
sendKaseikyo_JVC(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == KASEIKYO_DENON) {
sendKaseikyo_Denon(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == KASEIKYO_SHARP) {
sendKaseikyo_Sharp(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == KASEIKYO_MITSUBISHI) {
sendKaseikyo_Mitsubishi(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == NEC2) {
sendNEC2(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == ONKYO) {
sendOnkyo(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == APPLE) {
sendApple(aAddress, aCommand, aNumberOfRepeats);
#if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
} else if (aProtocol == BOSEWAVE) {
sendBoseWave(aCommand, aNumberOfRepeats);
} else if (aProtocol == FAST) {
// We have only 8 bit command
sendFAST(aCommand, aNumberOfRepeats);
} else if (aProtocol == LEGO_PF) {
sendLegoPowerFunctions(aAddress, aCommand, aCommand >> 4, (aNumberOfRepeats < 0)); // send 5 autorepeats, except for dedicated repeats
#endif
} else {
return 0; // Not supported by write. E.g for BANG_OLUFSEN
}
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!
@ -290,10 +426,6 @@ void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLe
mark(aBufferWithMicroseconds[i]);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -313,9 +445,6 @@ void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBu
}
}
IRLedOff(); // Always end with the LED off
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -333,7 +462,7 @@ void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t a
* Raw data starts with a mark
*/
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
unsigned int duration = pgm_read_word(&aBufferWithMicroseconds[i]);
auto duration = pgm_read_word(&aBufferWithMicroseconds[i]);
if (i & 1) {
// Odd
space(duration);
@ -341,9 +470,6 @@ void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t a
mark(duration);
}
}
# if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
# endif
#endif
}
@ -359,7 +485,7 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf
enableIROut(aIRFrequencyKilohertz);
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
unsigned int duration = pgm_read_byte(&aBufferWithTicks[i]) * (unsigned int) MICROS_PER_TICK;
uint_fast16_t duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK;
if (i & 1) {
// Odd
space(duration);
@ -368,9 +494,6 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf
}
}
IRLedOff(); // Always end with the LED off
# if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
# endif
#endif
}
@ -380,22 +503,46 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf
* The output always ends with a space
* Stop bit is always sent
*/
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros,
unsigned int aHeaderSpaceMicros, unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
unsigned int aZeroSpaceMicros, IRRawDataType *aDecodedRawDataArray, unsigned int aNumberOfBits, bool aMSBFirst,
bool aSendStopBit, unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit,
uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
uint8_t tFlags = 0;
if (aMSBFirst) {
tFlags = PROTOCOL_IS_MSB_FIRST;
}
(void) aSendStopBit;
sendPulseDistanceWidthFromArray(aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros,
aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, tFlags, aRepeatPeriodMillis, aNumberOfRepeats);
}
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats) {
sendPulseDistanceWidthFromArray(aFrequencyKHz, aDistanceWidthTimingInfo->HeaderMarkMicros,
aDistanceWidthTimingInfo->HeaderSpaceMicros, aDistanceWidthTimingInfo->OneMarkMicros,
aDistanceWidthTimingInfo->OneSpaceMicros, aDistanceWidthTimingInfo->ZeroMarkMicros,
aDistanceWidthTimingInfo->ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis,
aNumberOfRepeats);
}
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats) {
// Set IR carrier frequency
enableIROut(aFrequencyKHz);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
uint_fast8_t tNumberOf32BitChunks = ((aNumberOfBits - 1) / 32) + 1;
uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
#if defined(LOCAL_DEBUG)
// fist data
Serial.print(F("Data[0]=0x"));
Serial.print(aDecodedRawDataArray[0], HEX);
if (tNumberOf32BitChunks > 1) {
if (tNumberOf32Or64BitChunks > 1) {
Serial.print(F(" Data[1]=0x"));
Serial.print(aDecodedRawDataArray[1], HEX);
}
@ -411,27 +558,24 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigne
mark(aHeaderMarkMicros);
space(aHeaderSpaceMicros);
for (uint_fast8_t i = 0; i < tNumberOf32BitChunks; ++i) {
for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
uint8_t tNumberOfBitsForOneSend;
if (aNumberOfBits > 32) {
tNumberOfBitsForOneSend = 32;
} else {
tNumberOfBitsForOneSend = aNumberOfBits;
}
// Manage stop bit
bool tSendStopBit;
if (i == (tNumberOf32BitChunks - 1)) {
uint8_t tFlags;
if (i == (tNumberOf32Or64BitChunks - 1)) {
// End of data
tSendStopBit = aSendStopBit;
tNumberOfBitsForOneSend = aNumberOfBits;
tFlags = aFlags;
} else {
// intermediate data
tSendStopBit = false;
tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
tFlags = aFlags | SUPPRESS_STOP_BIT_FOR_THIS_DATA; // No stop bit for leading data
}
sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray[i],
tNumberOfBitsForOneSend, aMSBFirst, tSendStopBit);
aNumberOfBits -= 32;
tNumberOfBitsForOneSend, tFlags);
aNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
}
tNumberOfCommands--;
@ -446,9 +590,6 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigne
}
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -458,18 +599,25 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigne
* Stop bit is always sent
*/
void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
IRRawDataType *aDecodedRawDataArray, unsigned int aNumberOfBits, int_fast8_t aNumberOfRepeats) {
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
// Calling sendPulseDistanceWidthFromArray() costs 68 bytes program memory compared to the implementation below
// sendPulseDistanceWidthFromArray(aProtocolConstants->FrequencyKHz, aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros,
// aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros,
// aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
// aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros,
// aDecodedRawDataArray, aNumberOfBits, aProtocolConstants->Flags, aProtocolConstants->RepeatPeriodMillis,
// aNumberOfRepeats);
// Set IR carrier frequency
enableIROut(aProtocolConstants->FrequencyKHz);
uint_fast8_t tNumberOf32BitChunks = ((aNumberOfBits - 1) / 32) + 1;
uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
#if defined(LOCAL_DEBUG)
// fist data
Serial.print(F("Data[0]=0x"));
Serial.print(aDecodedRawDataArray[0], HEX);
if (tNumberOf32BitChunks > 1) {
if (tNumberOf32Or64BitChunks > 1) {
Serial.print(F(" Data[1]=0x"));
Serial.print(aDecodedRawDataArray[1], HEX);
}
@ -484,24 +632,30 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants
auto tNumberOfBits = aNumberOfBits; // refresh value for repeats
// Header
mark(aProtocolConstants->HeaderMarkMicros);
space(aProtocolConstants->HeaderSpaceMicros);
bool tHasStopBit = aProtocolConstants->hasStopBit;
mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
uint8_t tOriginalFlags = aProtocolConstants->Flags;
for (uint_fast8_t i = 0; i < tNumberOf32BitChunks; ++i) {
for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
uint8_t tNumberOfBitsForOneSend;
if (i == (tNumberOf32BitChunks - 1)) {
uint8_t tFlags;
if (i == (tNumberOf32Or64BitChunks - 1)) {
// End of data
tNumberOfBitsForOneSend = tNumberOfBits;
aProtocolConstants->hasStopBit = tHasStopBit;
tFlags = tOriginalFlags;
} else {
// intermediate data
tNumberOfBitsForOneSend = 32;
aProtocolConstants->hasStopBit = false;
tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
tFlags = tOriginalFlags | SUPPRESS_STOP_BIT_FOR_THIS_DATA; // No stop bit for leading data
}
sendPulseDistanceWidthData(aProtocolConstants, aDecodedRawDataArray[i], tNumberOfBitsForOneSend);
tNumberOfBits -= 32;
sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aDecodedRawDataArray[i], tNumberOfBitsForOneSend,
tFlags);
tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
}
tNumberOfCommands--;
@ -516,13 +670,10 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants
}
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
* Sends PulseDistance frames and repeats
* Sends PulseDistance frames and repeats and enables receiver again
* @param aProtocolConstants The constants to use for sending this protocol.
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
@ -555,8 +706,8 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
/*
* Send Header and regular frame
*/
mark(aProtocolConstants->HeaderMarkMicros);
space(aProtocolConstants->HeaderSpaceMicros);
mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
sendPulseDistanceWidthData(aProtocolConstants, aData, aNumberOfBits);
}
@ -572,24 +723,34 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
}
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
* Sends PulseDistance frames and repeats.
* @param aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aMSBFirst, aSendStopBit, aRepeatPeriodMillis Values to use for sending this protocol, also contained in the PulseDistanceWidthProtocolConstants of this protocol.
* @param aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aFlags, aRepeatPeriodMillis Values to use for sending this protocol, also contained in the PulseDistanceWidthProtocolConstants of this protocol.
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
* @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified
* then it is called without leading and trailing space.
* @param aSpecialSendRepeatFunction If NULL, the first frame is repeated completely, otherwise this function is used for sending the repeat frame.
*/
void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros, unsigned int aHeaderSpaceMicros,
unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros, unsigned int aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, unsigned int aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)()) {
void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData,
uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
void (*aSpecialSendRepeatFunction)()) {
uint8_t tFlags = 0;
if (aMSBFirst) {
tFlags = PROTOCOL_IS_MSB_FIRST;
}
(void) aSendStopBit;
sendPulseDistanceWidth(aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros,
aZeroSpaceMicros, aData, aNumberOfBits, tFlags, aRepeatPeriodMillis, aNumberOfRepeats, aSpecialSendRepeatFunction);
}
void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData,
uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
void (*aSpecialSendRepeatFunction)()) {
if (aNumberOfRepeats < 0) {
if (aSpecialSendRepeatFunction != NULL) {
@ -615,7 +776,7 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, unsigned int aHe
mark(aHeaderMarkMicros);
space(aHeaderSpaceMicros);
sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits,
aMSBFirst, aSendStopBit);
aFlags);
}
tNumberOfCommands--;
@ -630,9 +791,6 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, unsigned int aHe
}
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -643,17 +801,26 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, unsigned int aHe
void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData,
uint_fast8_t aNumberOfBits) {
sendPulseDistanceWidthData(aProtocolConstants->OneMarkMicros, aProtocolConstants->OneSpaceMicros,
aProtocolConstants->ZeroMarkMicros, aProtocolConstants->ZeroSpaceMicros, aData, aNumberOfBits,
aProtocolConstants->isMSBFirst, aProtocolConstants->hasStopBit);
sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aData, aNumberOfBits, aProtocolConstants->Flags);
}
/**
* 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, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit) {
void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit) {
uint8_t tFlags = 0;
if (aMSBFirst) {
tFlags = PROTOCOL_IS_MSB_FIRST;
}
(void) aSendStopBit;
sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits, tFlags);
}
void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) {
#if defined(LOCAL_DEBUG)
// Even printing this short messages (at 115200) disturbs the send timing :-(
@ -665,7 +832,7 @@ void IRsend::sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned in
// For MSBFirst, send data from MSB to LSB until mask bit is shifted out
IRRawDataType tMask = 1ULL << (aNumberOfBits - 1);
for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
if ((aMSBFirst && (aData & tMask)) || (!aMSBFirst && (aData & 1))) {
if (((aFlags & PROTOCOL_IS_MSB_FIRST) && (aData & tMask)) || (!(aFlags & PROTOCOL_IS_MSB_FIRST) && (aData & 1))) {
#if defined(LOCAL_TRACE)
Serial.print('1');
#endif
@ -678,13 +845,18 @@ void IRsend::sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned in
mark(aZeroMarkMicros);
space(aZeroSpaceMicros);
}
if (aMSBFirst) {
if (aFlags & PROTOCOL_IS_MSB_FIRST) {
tMask >>= 1;
} else {
aData >>= 1;
}
}
if (aSendStopBit) {
/*
* Stop bit is sent for all pulse distance protocols i.e. aOneMarkMicros == aZeroMarkMicros.
* Therefore it is not sent for Sony and Magiquest :-)
*/
if (!(aFlags & SUPPRESS_STOP_BIT_FOR_THIS_DATA) && aOneMarkMicros == aZeroMarkMicros) {
// Send stop bit here
#if defined(LOCAL_TRACE)
Serial.print('S');
#endif
@ -703,7 +875,7 @@ void IRsend::sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned in
* The output always ends with a space
* can only send 31 bit data, since we put the start bit as 32th bit on front
*/
void IRsend::sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
IR_TRACE_PRINT(F("0x"));
IR_TRACE_PRINT(aData, HEX);
@ -754,7 +926,7 @@ void IRsend::sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint
* 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) {
void IRsend::mark(uint16_t aMarkMicros) {
#if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
# if !defined(NO_LED_FEEDBACK_CODE)
@ -835,11 +1007,15 @@ void IRsend::mark(unsigned int aMarkMicros) {
# 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)
/*
* Enable interrupts at start of the longer off period. Required at least to keep micros correct.
* If receive interrupt is still active, it takes 3.4 us from now until receive ISR is active (for 7 us + pop's)
*/
interrupts();
# if !defined(NO_LED_FEEDBACK_CODE)
/*
* Delayed call of setFeedbackLED() to get better timing
* Delayed call of setFeedbackLED() to get better startup timing, especially required for consecutive marks
*/
if (!FeedbackLedIsActive) {
FeedbackLedIsActive = true;
@ -850,11 +1026,27 @@ void IRsend::mark(unsigned int aMarkMicros) {
# endif
/*
* PWM pause timing
* Minimal pause duration is 4.3 us if NO_LED_FEEDBACK_CODE is defined
* Measured delta between pause duration values are 13 us for a 16 MHz UNO (from 13 to 26)
* Minimal pause duration is 5.2 us with NO_LED_FEEDBACK_CODE enabled
* and 8.1 us with NO_LED_FEEDBACK_CODE disabled.
*/
tNextPeriodEnding += periodTimeMicros;
noInterrupts();
do {
tMicros = micros(); // we have only 4 us resolution for AVR @16MHz
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
/*
* For AVR @16MHz we have only 4 us resolution.
* The duration of the micros() call itself is 3 us.
* It takes 0.9 us from signal going low here.
* The rest of the loop takes 1.2 us with NO_LED_FEEDBACK_CODE enabled
* and 3 us with NO_LED_FEEDBACK_CODE disabled.
*/
tMicros = micros(); //
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
#endif
/*
* Exit the forever loop if aMarkMicros has reached
*/
@ -879,6 +1071,7 @@ void IRsend::mark(unsigned int aMarkMicros) {
}
# endif
#endif
interrupts();
return;
}
} while (tMicros < tNextPeriodEnding);
@ -924,7 +1117,7 @@ void IRsend::IRLedOff() {
* Sends an IR space for the specified number of microseconds.
* A space is "no output", so just wait.
*/
void IRsend::space(unsigned int aSpaceMicros) {
void IRsend::space(uint16_t aSpaceMicros) {
customDelayMicroseconds(aSpaceMicros);
}
@ -995,11 +1188,14 @@ void IRsend::enableIROut(uint_fast8_t aFrequencyKHz) {
#endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
}
unsigned int IRsend::getPulseCorrectionNanos() {
uint16_t IRsend::getPulseCorrectionNanos() {
return PULSE_CORRECTION_NANOS;
}
/** @}*/
#if defined(_IR_MEASURE_TIMING)
#undef _IR_MEASURE_TIMING
#endif
#if defined(LOCAL_TRACE)
#undef LOCAL_TRACE
#endif

View File

@ -13,7 +13,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2015-2022 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
* Copyright (c) 2015-2023 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
@ -49,7 +49,7 @@
* - 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, BANG_OLUFSEN, BOSEWAVE, WHYNTER and LEGO_PF are excluded in decode() and in sending with IrSender.write().
* - EXCLUDE_EXOTIC_PROTOCOLS If activated, BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST 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.
@ -65,9 +65,9 @@
#ifndef _IR_REMOTE_HPP
#define _IR_REMOTE_HPP
#define VERSION_IRREMOTE "4.0.0"
#define VERSION_IRREMOTE "4.1.0"
#define VERSION_IRREMOTE_MAJOR 4
#define VERSION_IRREMOTE_MINOR 0
#define VERSION_IRREMOTE_MINOR 1
#define VERSION_IRREMOTE_PATCH 0
/*
@ -81,7 +81,7 @@
//#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN
/*
* If activated, BANG_OLUFSEN, BOSEWAVE, MAGIQUEST,WHYNTER and LEGO_PF are excluded in decoding and in sending with IrSender.write
* If activated, BANG_OLUFSEN, BOSEWAVE, MAGIQUEST, WHYNTER, FAST and LEGO_PF are excluded in decoding and in sending with IrSender.write
*/
//#define EXCLUDE_EXOTIC_PROTOCOLS
/****************************************************
@ -99,7 +99,7 @@
|| defined(DECODE_PANASONIC) || defined(DECODE_LG) || defined(DECODE_NEC) || defined(DECODE_SAMSUNG) \
|| defined(DECODE_SONY) || defined(DECODE_RC5) || defined(DECODE_RC6) \
|| defined(DECODE_DISTANCE_WIDTH) || defined(DECODE_HASH) || defined(DECODE_BOSEWAVE) \
|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_WHYNTER)))
|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_FAST) || defined(DECODE_WHYNTER)))
/*
* If no protocol is explicitly enabled, we enable all protocols
*/
@ -119,6 +119,7 @@
#define DECODE_LEGO_PF
#define DECODE_MAGIQUEST // It modifies the RAW_BUFFER_LENGTH from 100 to 112
#define DECODE_WHYNTER
#define DECODE_FAST
# endif
# if !defined(EXCLUDE_UNIVERSAL_PROTOCOLS)
@ -308,6 +309,7 @@
#include "ir_RC5_RC6.hpp"
#include "ir_Samsung.hpp"
#include "ir_Sony.hpp"
#include "ir_FAST.hpp"
#include "ir_Others.hpp"
#include "ir_Pronto.hpp" // pronto is an universal decoder and encoder
# if defined(DECODE_DISTANCE_WIDTH) // universal decoder for pulse distance width protocols - requires up to 750 bytes additional program memory

View File

@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2015-20232 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
* Copyright (c) 2015-2023 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
@ -110,13 +110,15 @@ struct irparams_struct {
#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
uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command
};
#if (__INT_WIDTH__ < 32)
typedef uint32_t IRRawDataType;
#define BITS_IN_RAW_DATA_TYPE 32
#else
typedef uint64_t IRRawDataType;
#define BITS_IN_RAW_DATA_TYPE 64
#endif
#include "IRProtocol.h"
@ -161,7 +163,7 @@ struct decode_results {
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
uint16_t *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
};
@ -210,11 +212,13 @@ public:
void printIRResultMinimal(Print *aSerial);
void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
void printIRResultAsCVariables(Print *aSerial);
uint32_t getTotalDurationOfRawData();
/*
* Next 4 functions are also available as non member functions
*/
bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap = true, bool aCheckForRecordGapsMicros = true);
void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo);
void printIRSendUsage(Print *aSerial);
#if defined(__AVR__)
const __FlashStringHelper* getProtocolString();
@ -224,13 +228,13 @@ public:
static void printActiveIRProtocols(Print *aSerial);
void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
void compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int frequency = 38000U);
void compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t frequency = 38000U);
/*
* Store the data for further processing
*/
void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr);
size_t compensateAndStorePronto(String *aString, unsigned int frequency = 38000U);
size_t compensateAndStorePronto(String *aString, uint16_t frequency = 38000U);
/*
* The main decoding functions used by the individual decoders
@ -238,13 +242,13 @@ public:
bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
uint_fast8_t aStartOffset = 3);
bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
unsigned int aZeroMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroSpaceMicros, bool aMSBfirst);
bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros,
uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst);
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount,
uint_fast8_t aValueOfSpaceToMarkTransition, unsigned int aBiphaseTimeUnit);
uint_fast8_t aValueOfSpaceToMarkTransition, uint16_t aBiphaseTimeUnit);
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, unsigned int aBiphaseTimeUnit);
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit);
uint_fast8_t getBiphaselevel();
/*
@ -253,6 +257,7 @@ public:
bool decodeBangOlufsen();
bool decodeBoseWave();
bool decodeDenon();
bool decodeFAST();
bool decodeJVC();
bool decodeKaseikyo();
bool decodeLegoPowerFunctions();
@ -297,9 +302,9 @@ public:
* Internal functions
*/
void initDecodedIRData();
uint_fast8_t compare(unsigned int oldval, unsigned int newval);
uint_fast8_t compare(uint16_t oldval, uint16_t newval);
bool checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants);
void checkForRepeatSpaceTicksAndSetFlag(unsigned int aMaximumRepeatSpaceTicks);
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks);
bool checkForRecordGapsMicros(Print *aSerial);
IRData decodedIRData; // New: decoded IR data for the application
@ -317,16 +322,16 @@ 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);
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
bool matchSpace(uint16_t aMeasuredTicks, uint16_t 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);
bool MATCH(uint16_t measured, uint16_t desired);
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us);
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us);
int getMarkExcessMicros();
@ -373,8 +378,8 @@ void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please us
#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))
#define TICKS_LOW(us) ((uint16_t ) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) ))
#define TICKS_HIGH(us) ((uint16_t ) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1))
#endif
/*
@ -390,8 +395,6 @@ extern IRrecv IrReceiver;
* Just for better readability of code
*/
#define NO_REPEATS 0
#define SEND_STOP_BIT true
#define SEND_NO_STOP_BIT false
#define SEND_REPEAT_COMMAND true ///< used for e.g. NEC, where a repeat is different from just repeating the data.
/**
@ -421,30 +424,47 @@ public:
#endif
size_t write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats = NO_REPEATS);
size_t write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats = NO_REPEATS);
void enableIROut(uint_fast8_t aFrequencyKHz);
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros,
unsigned int aHeaderSpaceMicros, unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros,
unsigned int aZeroMarkMicros, unsigned int aZeroSpaceMicros, IRRawDataType *aDecodedRawDataArray,
unsigned int aNumberOfBits, bool aMSBfirst, bool aSendStopBit, unsigned int aRepeatPeriodMillis,
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit,
uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
__attribute__ ((deprecated ("Since version 4.1.0 parameter aSendStopBit is not longer required.")));
void sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
IRRawDataType *aDecodedRawDataArray, unsigned int aNumberOfBits, int_fast8_t aNumberOfRepeats);
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData,
uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData,
uint_fast8_t aNumberOfBits);
void sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros, unsigned int aHeaderSpaceMicros,
unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros, unsigned int aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit, unsigned int aRepeatPeriodMillis,
void sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = NULL);
void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
unsigned int aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit);
void sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);
void sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = NULL)
__attribute__ ((deprecated ("Since version 4.1.0 parameter aSendStopBit is not longer required.")));
void sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags);
void sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit)
__attribute__ ((deprecated ("Since version 4.1.0 last parameter aSendStopBit is not longer required.")));
void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);
void mark(unsigned int aMarkMicros);
static void space(unsigned int aSpaceMicros);
void mark(uint16_t aMarkMicros);
static void space(uint16_t aSpaceMicros);
void IRLedOff();
// 8 Bit array
@ -471,6 +491,7 @@ public:
#if !defined (DOXYGEN)
__attribute__ ((deprecated ("Please use sendDenon(aAddress, aCommand, aNumberOfRepeats).")));
#endif
void sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats);
void sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats);
void sendLG2Repeat();
@ -512,7 +533,7 @@ public:
void sendPronto(const __FlashStringHelper *str, int_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendPronto(const char *prontoHexString, int_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendPronto(const uint16_t *data, unsigned int length, int_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendPronto(const uint16_t *data, uint16_t length, int_fast8_t aNumberOfRepeats = NO_REPEATS);
#if defined(__AVR__)
void sendPronto_PF(uint_farptr_t str, int_fast8_t aNumberOfRepeats = NO_REPEATS);
@ -536,7 +557,9 @@ public:
}
void sendJVCMSB(unsigned long data, int nbits, bool repeat = false);
void sendLG(unsigned long data, int nbits) __attribute__ ((deprecated ("The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).")));
void sendLG(unsigned long data,
int nbits)
__attribute__ ((deprecated ("The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).")));
void sendNEC(uint32_t aRawData,
uint8_t nbits)
@ -552,7 +575,7 @@ public:
void sendRC6(uint64_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC6Raw().")));
;
void sendSharpRaw(unsigned long data, int nbits);
void sendSharp(unsigned int address, unsigned int command);
void sendSharp(uint16_t address, uint16_t command);
void sendSAMSUNG(unsigned long data, int nbits);
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSamsung().")));
void sendSony(unsigned long data,
@ -564,9 +587,9 @@ public:
#if !defined(IR_SEND_PIN)
uint8_t sendPin;
#endif
unsigned int periodTimeMicros;
unsigned int periodOnTimeMicros; // compensated with PULSE_CORRECTION_NANOS for duration of digitalWrite. Around 8 microseconds for 38 kHz.
unsigned int getPulseCorrectionNanos();
uint16_t periodTimeMicros;
uint16_t periodOnTimeMicros; // compensated with PULSE_CORRECTION_NANOS for duration of digitalWrite. Around 8 microseconds for 38 kHz.
uint16_t getPulseCorrectionNanos();
static void customDelayMicroseconds(unsigned long aMicroseconds);
};

View File

@ -34,10 +34,10 @@
* @{
*/
#define VERSION_IRTINY "1.2.0"
#define VERSION_IRTINY_MAJOR 1
#define VERSION_IRTINY_MINOR 2
#define VERSION_IRTINY_PATCH 0
#define VERSION_TINYIR "1.2.0"
#define VERSION_TINYIR_MAJOR 1
#define VERSION_TINYIR_MINOR 2
#define VERSION_TINYIR_PATCH 0
// The change log is at the bottom of the file
/**
@ -46,6 +46,7 @@
* see: https://www.sbprojects.net/knowledge/ir/nec.php
* LSB first, 1 start bit + 16 bit address + 8 bit data + 8 bit inverted data + 1 stop bit.
*/
#if !defined(NEC_ADDRESS_BITS)
#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)
@ -64,15 +65,28 @@
#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_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
#define NEC_MAXIMUM_REPEAT_DISTANCE (NEC_REPEAT_PERIOD - NEC_MINIMAL_DURATION + 10000) // 70 ms
#endif
/**
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST protocol characteristics:
* - Bit timing is like JVC
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 2) + 1) * 526 = 39 * 560 = 20514 microseconds or 20.5 ms.
* - Repeats are sent as complete frames but in a 40 ms period / with a 19.5 ms distance.
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*/
/*
Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
+2100,-1050
+ 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
+ 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
+ 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550
+ 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550
+ 550
Sum: 28900
*/
#define FAST_KHZ 38
#define FAST_ADDRESS_BITS 0 // No address
#define FAST_COMMAND_BITS 16 // Command and inverted command (parity)
#define FAST_BITS (FAST_ADDRESS_BITS + FAST_COMMAND_BITS)
@ -86,9 +100,9 @@
#define FAST_HEADER_MARK (4 * FAST_UNIT) // 2104
#define FAST_HEADER_SPACE (2 * FAST_UNIT) // 1052
#define FAST_REPEAT_PERIOD 40000 // Commands are repeated every 40 ms (measured from start to start) for as long as the key on the remote control is held down.
#define FAST_REPEAT_DISTANCE (FAST_REPEAT_PERIOD - (39 * FAST_UNIT)) // 19.5 ms
#define FAST_MAXIMUM_REPEAT_DISTANCE (FAST_REPEAT_DISTANCE + 5000) // 24.5 ms
#define FAST_REPEAT_PERIOD 50000 // Commands are repeated every 50 ms (measured from start to start) for as long as the key on the remote control is held down.
#define FAST_REPEAT_DISTANCE (FAST_REPEAT_PERIOD - (55 * FAST_UNIT)) // 19 ms
#define FAST_MAXIMUM_REPEAT_DISTANCE (FAST_REPEAT_DISTANCE + 10000) // 29 ms
/*
* Definitions to switch between FAST and NEC/ONKYO timing with the same code.

View File

@ -13,14 +13,13 @@
* !!!!!!!!!!!!!!!!!!!!!
* aFlags can contain one of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED bits
*
* FAST protocol is proprietary and a JVC protocol without address and with a shorter header.
* FAST takes 21 ms for sending and can be sent at a 50 ms period. It still supports parity.
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like JVC
* - The header is shorter, 4000 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (7 + (16 * 2) + 1) * 526 = 40 * 560 = 21040 microseconds or 21 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 29 ms distance.
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
@ -29,7 +28,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-20232 Armin Joachimsmeyer
* Copyright (c) 2022-2023 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
@ -316,7 +315,11 @@ void IRPinChangeInterruptHandler(void) {
* Address is sent first and contained in the lower word
*/
if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) {
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED;
#if defined(ENABLE_NEC2_REPEATS)
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; // here we can have the repeat flag already set
#else
TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; // here we do not check anything, if we have a repeat
#endif
}
#endif
#if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
@ -325,7 +328,11 @@ void IRPinChangeInterruptHandler(void) {
*/
#if (TINY_RECEIVER_ADDRESS_BITS > 0)
if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[3])) {
#if defined(ENABLE_NEC2_REPEATS)
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED;
#else
TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED;
#endif
# if defined(LOCAL_DEBUG)
Serial.print(F("Parity check for command failed. Command="));
Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX);
@ -364,7 +371,7 @@ void IRPinChangeInterruptHandler(void) {
# endif
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
// Here we have 8 bit command
TinyIRReceiverControl.IRRawData.UBytes[3],
TinyIRReceiverControl.IRRawData.UBytes[2],
# else
// Here we have 16 bit command
TinyIRReceiverControl.IRRawData.UWord.HighWord,

View File

@ -4,14 +4,13 @@
* Sends IR protocol data of NEC and FAST protocol using bit banging.
* NEC is the protocol of most cheap remote controls for Arduino.
*
* FAST protocol is proprietary and a JVC protocol without address and with a shorter header.
* FAST takes 21 ms for sending and can be sent at a 50 ms period. It still supports parity.
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like JVC
* - The header is shorter, 4000 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (7 + (16 * 2) + 1) * 526 = 40 * 560 = 21040 microseconds or 21 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 29 ms distance.
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
@ -20,7 +19,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-20232 Armin Joachimsmeyer
* Copyright (c) 2022-2023 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
@ -62,7 +61,7 @@
*/
/*
* Generate IR signal by bit banging
* Generate 38 kHz IR signal by bit banging
*/
void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) {
unsigned long tStartMicros = micros();
@ -248,7 +247,7 @@ void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats
uint16_t tData;
/*
* The compiler is intelligent and removes the code for "(aCommand > 0xFF)" if we are called with an uint8_t command :-).
* Using an uint16_t address requires additional 56 bytes program memory.
* Using an uint16_t command requires additional 56 bytes program memory.
*/
if (aCommand > 0xFF) {
tData = aCommand;

View File

@ -161,10 +161,13 @@ void IRsend::sendBangOlufsenDataLink(uint32_t aHeader, uint8_t aData, int_fast8_
*/
void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBackToBack) {
#if defined(USE_NO_SEND_PWM) || BEO_KHZ == 38 // BEO_KHZ == 38 is for unit test which runs the B&O protocol with 38 kHz
/*
* 455 kHz PWM is currently not supported, maximum is 180 kHz
*/
#if !defined(USE_NO_SEND_PWM)
enableIROut (BEO_KHZ);
#endif
// AGC / Start - 3 bits + first constant 0 header bit described in the official documentation
if (!aBackToBack) {
@ -204,9 +207,6 @@ void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBack
space(BEO_PULSE_LENGTH_TRAILING_BIT - BEO_IR_MARK);
mark(BEO_IR_MARK);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
#else
(void) aRawData;
(void) aBits;
@ -226,7 +226,9 @@ void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bo
/*
* 455 kHz PWM is currently not supported, maximum is 180 kHz
*/
#if !defined(USE_NO_SEND_PWM)
enableIROut (BEO_KHZ);
#endif
// AGC / Start - 3 bits + first constant 0 header bit described in the official documentation
if (!aBackToBack) {
@ -266,9 +268,6 @@ void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bo
space(BEO_PULSE_LENGTH_TRAILING_BIT - tSendBEOMarkLength);
mark(tSendBEOMarkLength);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
#else
(void) aRawData;
(void) aBits;

View File

@ -47,8 +47,8 @@
#define BOSEWAVE_MAXIMUM_REPEAT_DISTANCE 62000
struct PulseDistanceWidthProtocolConstants BoseWaveProtocolConstants = { BOSEWAVE, BOSEWAVE_KHZ, BOSEWAVE_HEADER_MARK,
BOSEWAVE_HEADER_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, (BOSEWAVE_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
BOSEWAVE_HEADER_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST
, (BOSEWAVE_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
/************************************
* Start of send and decode functions

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2023 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
@ -106,8 +106,8 @@
#define DENON_HEADER_SPACE (3 * DENON_UNIT) // 780 // The length of the Header:Space
struct PulseDistanceWidthProtocolConstants DenonProtocolConstants = { DENON, DENON_KHZ, DENON_HEADER_MARK, DENON_HEADER_SPACE,
DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, (DENON_REPEAT_PERIOD
/ MICROS_IN_ONE_MILLI), NULL };
DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
(DENON_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
/************************************
* Start of send and decode functions
@ -146,9 +146,6 @@ void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOf
delay( DENON_AUTO_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
bool IRrecv::decodeSharp() {
@ -212,7 +209,7 @@ bool IRrecv::decodeDenon() {
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
#if defined(LOCAL_DEBUG)
Serial.print(F("Denon: "));
Serial.print(F("Parity check for repeat failed last command="));
Serial.print(F("Parity check for repeat failed. Last command="));
Serial.print(lastDecodedCommand, HEX);
Serial.print(F(" current="));
Serial.println(~decodedIRData.command, HEX);
@ -223,7 +220,7 @@ bool IRrecv::decodeDenon() {
}
// repeated command here
if (tFrameBits == 1 || tFrameBits == 2 ) {
if (tFrameBits == 1 || tFrameBits == 2) {
decodedIRData.protocol = SHARP;
} else {
decodedIRData.protocol = DENON;
@ -270,16 +267,13 @@ void IRsend::sendDenon(unsigned long data, int nbits) {
// Data
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, data, nbits,
PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
PROTOCOL_IS_MSB_FIRST);
}
/*
* Old function without parameter aNumberOfRepeats
*/
void IRsend::sendSharp(unsigned int aAddress, unsigned int aCommand) {
void IRsend::sendSharp(uint16_t aAddress, uint16_t aCommand) {
sendDenon(aAddress, aCommand, true, 0);
}

View File

@ -31,7 +31,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022 Armin Joachimsmeyer
* Copyright (c) 2022-2023 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
@ -55,6 +55,10 @@
#ifndef _IR_DISTANCE_WIDTH_HPP
#define _IR_DISTANCE_WIDTH_HPP
#if !defined(DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS)
#define DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS 100000 // 100 ms, bit it is just a guess
#endif
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#else
@ -65,28 +69,37 @@
#define DURATION_ARRAY_SIZE 50
// Switch the decoding according to your needs
//#define DISTANCE_DO_MSB_DECODING // If active, it resembles the JVC + Denon, otherwise LSB first as e.g. for NEC and Kaseikyo/Panasonic
//#define USE_MSB_DECODING_FOR_DISTANCE_DECODER // If active, it resembles LG, otherwise LSB first as most other protocols e.g. NEC and Kaseikyo/Panasonic
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//=====================================================================================
// DDD III SSS TTTTTT AA N N CCC EEEE W W III DDD TTTTTT H H
// D D I S TT A A NN N C E W W I D D TT H H
// D D I SSS TT AAAA N N N C EEE W W W I D D TT HHHH
// D D I S TT A A N NN C E W W W I D D TT H H
// DDD III SSSS TT A A N N CCC EEEE W W III DDD TT H H
//=====================================================================================
// 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++) {
//Print index at the beginning of a new line
if (i % 10 == 0) {
if (i == 0) {
Serial.print(' '); // indentation for the 0
Serial.print(' '); // indentation for the first index 0
} else {
Serial.println();
Serial.println(); // new line for next indexes 10, 20 etc.
}
Serial.print(i);
Serial.print(F(": "));
}
// Print number of values in array and duration if != 0
Serial.print(aArray[i]);
if (aArray[i] != 0) {
Serial.print(' ');
Serial.print(i * (uint16_t)MICROS_PER_TICK);
Serial.print('x');
Serial.print(i * (uint16_t) MICROS_PER_TICK);
}
Serial.print(F(" | "));
}
@ -171,7 +184,7 @@ bool IRrecv::decodeDistanceWidth() {
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.print(F("Mark "));
Serial.print(tDurationTicks * MICROS_PER_TICK);
Serial.print(F(" is longer than "));
Serial.print(F(" is longer than maximum "));
Serial.print(DURATION_ARRAY_SIZE * MICROS_PER_TICK);
Serial.print(F(" us. Index="));
Serial.println(i);
@ -248,47 +261,38 @@ bool IRrecv::decodeDistanceWidth() {
/*
* Print characteristics of this protocol. Durations are in ticks.
* Number of bits, start bit, start pause, short mark, long mark, short space, long space
* Number of bits, start bit, start pause, long mark, long space, short mark, short 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
* NEC: 32, 180, 90, 0, 34, 11, 11
* Samsung32: 32, 90, 90, 0, 34, 11, 11
* LG: 28, 180, 84, 0, 32, 10, 11
* JVC: 16, 168, 84, 0, 32, 10, 10
* Kaseikyo: 48. 69, 35, 0, 26, 9, 9
* Sony: 12|15|20, 48, 12, 24, 0, 12, 12 // the only known pulse width protocol
*/
#if defined(LOCAL_DEBUG)
Serial.print(F("ProtocolConstants: "));
Serial.print(F("DistanceWidthTimingInfoStruct: "));
Serial.print(decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(tMarkTicksShort * MICROS_PER_TICK);
Serial.print(tMarkTicksLong * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(tSpaceTicksLong * MICROS_PER_TICK);
Serial.print(F(", "));
if (tMarkTicksLong == 0) {
Serial.print(tMarkTicksShort * MICROS_PER_TICK);
} else {
Serial.print(tMarkTicksLong * MICROS_PER_TICK);
}
Serial.print(tMarkTicksShort * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.print(tSpaceTicksShort * MICROS_PER_TICK);
Serial.println();
Serial.println(tSpaceTicksShort * MICROS_PER_TICK);
#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!
// For PULSE_DISTANCE a stop bit is mandatory, for PULSE_WIDTH it is not required!
tNumberOfBits--; // Correct for stop bit
}
decodedIRData.numberOfBits = tNumberOfBits;
#if __INT_WIDTH__ < 32
uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / 32;
#else
uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / 64;
#endif
uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE;
/*
* We can have the following protocol timings
@ -305,36 +309,35 @@ bool IRrecv::decodeDistanceWidth() {
#endif
return false;
}
unsigned int tSpaceMicrosShort;
#if defined DECODE_STRICT_CHECKS
if(tMarkTicksLong > 0 && tSpaceTicksLong > 0) {
// We have different mark and space length here, so signal decodePulseDistanceWidthData() not to check against constant lenght decodePulseDistanceWidthData
tSpaceTicksShort = 0;
// We have different mark and space length here, so signal decodePulseDistanceWidthData() not to check against constant length decodePulseDistanceWidthData
tSpaceMicrosShort = 0;
}
#endif
tSpaceMicrosShort = tSpaceTicksShort * MICROS_PER_TICK;
unsigned int tMarkMicrosShort = tMarkTicksShort * MICROS_PER_TICK;
unsigned int tMarkMicrosLong = tMarkTicksLong * MICROS_PER_TICK;
unsigned int tSpaceMicrosLong = tSpaceTicksLong * MICROS_PER_TICK;
for (uint_fast8_t i = 0; i <= tNumberOfAdditionalArrayValues; ++i) {
uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;
/*
* Decode in 32/64 bit chunks. Only the last chunk can contain less than 32/64 bits
*/
#if __INT_WIDTH__ < 32
if (tNumberOfBitsForOneDecode > 32) {
tNumberOfBitsForOneDecode = 32;
if (tNumberOfBitsForOneDecode > BITS_IN_RAW_DATA_TYPE) {
tNumberOfBitsForOneDecode = BITS_IN_RAW_DATA_TYPE;
}
#else
if (tNumberOfBitsForOneDecode > 64) {
tNumberOfBitsForOneDecode = 64;
}
#endif
bool tResult;
if (tMarkTicksLong > 0) {
/*
* Here short and long mark durations found.
*/
decodedIRData.protocol = PULSE_WIDTH;
tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksLong * MICROS_PER_TICK,
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, 0,
#if defined(DISTANCE_DO_MSB_DECODING)
tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosLong, tMarkMicrosShort,
tSpaceMicrosShort, 0,
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
true
#else
false
@ -345,9 +348,9 @@ bool IRrecv::decodeDistanceWidth() {
* Here short and long space durations found.
*/
decodedIRData.protocol = PULSE_DISTANCE;
tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksShort * MICROS_PER_TICK,
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK,
#if defined(DISTANCE_DO_MSB_DECODING)
tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosShort, tMarkMicrosShort,
tSpaceMicrosLong, tSpaceMicrosShort,
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
true
#else
false
@ -356,41 +359,56 @@ bool IRrecv::decodeDistanceWidth() {
}
if (!tResult) {
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_WIDTH: "));
Serial.println(F("Decode failed"));
Serial.print(F("PULSE_WIDTH: "));
Serial.println(F("Decode failed"));
#endif
return false;
}
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_WIDTH: "));
Serial.print(F("decodedRawData=0x"));
Serial.println(decodedIRData.decodedRawData);
Serial.println(decodedIRData.decodedRawData, HEX);
#endif
// fill array with decoded data
decodedIRData.decodedRawDataArray[i] = decodedIRData.decodedRawData;
#if __INT_WIDTH__ < 32
tStartIndex += 64;
tNumberOfBits -= 32;
#else
tStartIndex += 128;
tNumberOfBits -= 64;
#endif
tStartIndex += (2 * BITS_IN_RAW_DATA_TYPE);
tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
}
#if defined(DISTANCE_DO_MSB_DECODING)
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO;
#else
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO;
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
#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;
// Check for repeat
checkForRepeatSpaceTicksAndSetFlag(DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS / MICROS_PER_TICK);
/*
* Store timing data to reproduce frame for sending
*/
decodedIRData.DistanceWidthTimingInfo.HeaderMarkMicros = (decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
decodedIRData.DistanceWidthTimingInfo.HeaderSpaceMicros = (decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
decodedIRData.DistanceWidthTimingInfo.ZeroMarkMicros = tMarkMicrosShort;
decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosShort;
if (tMarkMicrosLong != 0) {
decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosLong;
decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosShort;
if (tSpaceMicrosLong != 0) {
// Assume long space for zero when we have PulseDistanceWidth -> enables constant bit length
decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosLong;
}
} else {
decodedIRData.address = (tMarkTicksLong << 8) | tSpaceTicksLong;
}
decodedIRData.command = (tMarkTicksShort << 8) | tSpaceTicksShort;
decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosShort;
// Here tMarkMicrosLong is 0 => tSpaceMicrosLong != 0
decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosLong;
}
#if defined(LOCAL_DEBUG)
Serial.print(F("DistanceWidthTimingInfo="));
IrReceiver.printDistanceWidthTimingInfo(&Serial, &decodedIRData.DistanceWidthTimingInfo);
Serial.println();
#endif
return true;
}

154
src/ir_FAST.hpp Normal file
View File

@ -0,0 +1,154 @@
/*
* ir_FAST.hpp
*
* Contains functions for receiving and sending FAST IR protocol with 8 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2023 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_FAST_HPP
#define _IR_FAST_HPP
#include "TinyIR.h"
#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
* @{
*/
// generated with https://patorjk.com/software/taag/#p=display&f=Alphabet&t=FAST
//==============================================================================
// FFFF AA SSS TTTTTT
// F A A S TT
// FFF AAAA SSS TT
// F A A S TT
// F A A SSSS TT
//==============================================================================
#include "TinyIR.h"
/*
Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
+2100,-1050
+ 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
+ 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
+ 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550
+ 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550
+ 550
Sum: 28900
*/
struct PulseDistanceWidthProtocolConstants FASTProtocolConstants = { FAST, FAST_KHZ, FAST_HEADER_MARK, FAST_HEADER_SPACE,
FAST_BIT_MARK, FAST_ONE_SPACE, FAST_BIT_MARK, FAST_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (FAST_REPEAT_PERIOD / MICROS_IN_ONE_MILLI),
NULL };
/************************************
* Start of send and decode functions
************************************/
/**
* The FAST protocol repeats by skipping the header mark and space -> this leads to a poor repeat detection for JVC protocol.
*/
void IRsend::sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
// Set IR carrier frequency
enableIROut(FAST_KHZ); // 38 kHz
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
mark(FAST_HEADER_MARK);
space(FAST_HEADER_SPACE);
sendPulseDistanceWidthData(&FASTProtocolConstants, aCommand | (((uint8_t)(~aCommand)) << 8), FAST_BITS);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a fixed raster
delay(FAST_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
}
}
}
bool IRrecv::decodeFAST() {
// uint_fast8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Using a local variable does not improve code size
// Check we have the right amount of data (36). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != ((2 * FAST_BITS) + 4)) {
IR_DEBUG_PRINT(F("FAST: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 36"));
return false;
}
if (!checkHeader(&FASTProtocolConstants)) {
return false;
}
if (!decodePulseDistanceWidthData(&FASTProtocolConstants, FAST_BITS)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("FAST: "));
Serial.println(F("Decode failed"));
#endif
return false;
}
WordUnion tValue;
tValue.UWord = decodedIRData.decodedRawData;
if (tValue.UByte.LowByte != (uint8_t)~(tValue.UByte.HighByte)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("FAST: "));
Serial.print(F("8 bit parity is not correct. Expected=0x"));
Serial.print((uint8_t)~(tValue.UByte.LowByte), HEX);
Serial.print(F(" received=0x"));
Serial.print(tValue.UByte.HighByte, HEX);
Serial.print(F(" data=0x"));
Serial.println(tValue.UWord, HEX);
#endif
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED;
}
checkForRepeatSpaceTicksAndSetFlag(FAST_MAXIMUM_REPEAT_DISTANCE / MICROS_PER_TICK);
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
decodedIRData.command = tValue.UByte.LowByte;
decodedIRData.address = 0; // No address for this protocol
decodedIRData.numberOfBits = FAST_BITS;
decodedIRData.protocol = FAST;
return true;
}
/** @}*/
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _IR_FAST_HPP

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2022 Kristian Lauszus, Armin Joachimsmeyer
* Copyright (c) 2017-2023 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
@ -55,8 +55,8 @@
+ 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
+ 500,-1600 + 550,-1550 + 550,-1500 + 600,- 500
+ 550
Sum: 40350
*/
Sum: 40350
*/
// 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)+)
@ -80,7 +80,8 @@ Sum: 40350
#define JVC_REPEAT_PERIOD 65000 // assume around 40 ms for a JVC frame
struct PulseDistanceWidthProtocolConstants JVCProtocolConstants = { JVC, JVC_KHZ, JVC_HEADER_MARK, JVC_HEADER_SPACE, JVC_BIT_MARK,
JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, (JVC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (JVC_REPEAT_PERIOD
/ MICROS_IN_ONE_MILLI), NULL };
/************************************
* Start of send and decode functions
@ -114,16 +115,14 @@ void IRsend::sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe
delay(JVC_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
bool IRrecv::decodeJVC() {
// uint_fast8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Using a local variable does not improve code size
// 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. +4 is for first frame, +2 is for repeats
// 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.
// +4 is for first frame, +2 is for repeats
if (decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 4)) {
IR_DEBUG_PRINT(F("JVC: "));
IR_DEBUG_PRINT(F("Data length="));
@ -251,11 +250,8 @@ void IRsend::sendJVCMSB(unsigned long data, int nbits, bool repeat) {
}
// 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);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
sendPulseDistanceWidthData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, data, nbits,
PROTOCOL_IS_MSB_FIRST);
}
/** @}*/

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2023 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
@ -42,6 +42,13 @@
* @{
*/
//==============================================================================
// K K AA SSS EEEE III K K Y Y OOO
// K K A A S E I K K Y Y O O
// KK AAAA SSS EEE I KK Y O O
// K K A A S E I K K Y O O
// K K A A SSSS EEEE III K K Y OOO
//==============================================================================
//==============================================================================
// 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
@ -49,7 +56,7 @@
// P A A N N A A SSSS OOO N N IIIII CCCC
//==============================================================================
/*
Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
+3450,-1700
+ 450,- 400 + 500,-1250 + 450,- 400 + 500,- 400
+ 450,- 400 + 400,- 450 + 500,- 350 + 450,- 450
@ -64,7 +71,7 @@ Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB fi
+ 450,-1250 + 450,- 400 + 450,- 400 + 500,-1250
+ 450,-1250 + 450,- 400 + 500,- 400 + 450,-1250
+ 450
Sum: 64300
Sum: 64300
*/
// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Panasonic
// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Kaseikyo
@ -112,8 +119,8 @@ Sum: 64300
#define JVC_VENDOR_ID_CODE 0x0103
struct PulseDistanceWidthProtocolConstants KaseikyoProtocolConstants = { KASEIKYO, KASEIKYO_KHZ, KASEIKYO_HEADER_MARK,
KASEIKYO_HEADER_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, (KASEIKYO_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
KASEIKYO_HEADER_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST
, (KASEIKYO_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
/************************************
* Start of send and decode functions
@ -263,7 +270,7 @@ bool IRrecv::decodeKaseikyo() {
#if defined(LOCAL_DEBUG)
Serial.print(F("Kaseikyo: "));
Serial.print(F("4 bit VendorID parity is not correct. expected=0x"));
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);
@ -282,7 +289,7 @@ bool IRrecv::decodeKaseikyo() {
#if defined(LOCAL_DEBUG)
Serial.print(F("Kaseikyo: "));
Serial.print(F("8 bit Parity is not correct. expected=0x"));
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);

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2022 Darryl Smith, Armin Joachimsmeyer
* Copyright (c) 2017-2023 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
@ -59,8 +59,8 @@
+ 500,- 550 + 500,-1550 + 500,-1600 + 500,- 550
+ 500,-1550 + 500,- 600 + 450,-1600 + 500,-1550
+ 500
Sum: 62400
*/
Sum: 62400
*/
// LG originally added by Darryl Smith (based on the JVC protocol)
// see: https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/LGAirConditionerSendDemo
@ -115,12 +115,10 @@ Sum: 62400
//#define LG_REPEAT_DISTANCE (LG_REPEAT_PERIOD - LG_AVERAGE_DURATION) // 52 ms
struct PulseDistanceWidthProtocolConstants LGProtocolConstants = { LG, LG_KHZ, LG_HEADER_MARK, LG_HEADER_SPACE, LG_BIT_MARK,
LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI),
&sendNECSpecialRepeat };
LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendNECSpecialRepeat };
struct PulseDistanceWidthProtocolConstants LG2ProtocolConstants = { LG2, LG_KHZ, LG2_HEADER_MARK, LG2_HEADER_SPACE, LG_BIT_MARK,
LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI),
&sendLG2SpecialRepeat };
LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendLG2SpecialRepeat };
/************************************
* Start of send and decode functions
@ -133,9 +131,6 @@ void IRsend::sendLG2Repeat() {
mark(LG2_HEADER_MARK); // + 3000
space(LG_REPEAT_HEADER_SPACE); // - 2250
mark(LG_BIT_MARK); // + 500
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -147,9 +142,6 @@ void sendLG2SpecialRepeat() {
IrSender.mark(LG2_HEADER_MARK); // + 3000
IrSender.space(LG_REPEAT_HEADER_SPACE); // - 2250
IrSender.mark(LG_BIT_MARK); // + 500
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
uint32_t IRsend::computeLGRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand) {
@ -347,11 +339,7 @@ void IRsend::sendLG(unsigned long data, int nbits) {
// 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);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
}
/** @}*/

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2023 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
@ -83,7 +83,7 @@
#define LEGO_MODE_SINGLE 0x4 // here the 2 LSB have meanings like Output A / Output B
struct PulseDistanceWidthProtocolConstants LegoProtocolConstants = { LEGO_PF, 38, LEGO_HEADER_MARK, LEGO_HEADER_SPACE, LEGO_BIT_MARK,
LEGO_ONE_SPACE, LEGO_BIT_MARK, LEGO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, (LEGO_AUTO_REPEAT_PERIOD_MIN
LEGO_ONE_SPACE, LEGO_BIT_MARK, LEGO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (LEGO_AUTO_REPEAT_PERIOD_MIN
/ MICROS_IN_ONE_MILLI), NULL };
/************************************

View File

@ -14,7 +14,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2022 E. Stuart Hicks <ehicks@binarymagi.com>, Armin Joachimsmeyer
* Copyright (c) 2017-2023 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
@ -46,8 +46,12 @@
//
//==============================================================================
//
// M A G I Q U E S T
//
// M M AA GGG III QQQ U U EEEE SSS TTTTTT
// MM MM A A G I Q Q U U E S TT
// M M M AAAA G GG I Q Q U U EEE SSS TT
// M M A A G G I Q QQ U U E S TT
// M M A A GGG III QQQQ UUU EEEE SSSS TT
// Q
//==============================================================================
/*
* https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp
@ -104,8 +108,7 @@
// assume 110 as repeat period
struct PulseDistanceWidthProtocolConstants MagiQuestProtocolConstants = { MAGIQUEST, 38, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE,
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, SEND_NO_STOP_BIT, 110,
NULL };
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 110, NULL };
//+=============================================================================
//
/**
@ -135,9 +138,6 @@ void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) {
Serial.print(F("MagiQuest checksum=0x"));
Serial.println(tChecksum, HEX);
#endif
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
//+=============================================================================

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2023 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
@ -62,12 +62,12 @@
+ 650
Sum: 68000
Protocol=NEC Address=0x8 Command=0x7 Repeat gap=40900us
rawData[4]:
Protocol=NEC Address=0x8 Command=0x7 Repeat gap=40900us
rawData[4]:
-40900
+10450,-2250
+ 700
Sum: 13400
Sum: 13400
*/
// http://www.hifi-remote.com/wiki/index.php/NEC
// https://www.sbprojects.net/knowledge/ir/nec.php
@ -111,13 +111,14 @@ Sum: 13400
#define APPLE_ADDRESS 0x87EE
struct PulseDistanceWidthProtocolConstants NECProtocolConstants = { NEC, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK,
NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI),
&sendNECSpecialRepeat };
struct PulseDistanceWidthProtocolConstants NECProtocolConstants =
{ NEC, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK,
NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI),
&sendNECSpecialRepeat };
// Like NEC but repeats are full frames instead of special NEC repeats
struct PulseDistanceWidthProtocolConstants NEC2ProtocolConstants = { NEC2, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK,
NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
/************************************
* Start of send and decode functions
@ -132,9 +133,6 @@ void IRsend::sendNECRepeat() {
mark(NEC_HEADER_MARK); // + 9000
space(NEC_REPEAT_HEADER_SPACE); // - 2250
mark(NEC_BIT_MARK); // + 560
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -146,9 +144,6 @@ void sendNECSpecialRepeat() {
IrSender.mark(NEC_HEADER_MARK); // + 9000
IrSender.space(NEC_REPEAT_HEADER_SPACE); // - 2250
IrSender.mark(NEC_BIT_MARK); // + 560
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
uint32_t IRsend::computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aCommand) {
@ -417,11 +412,7 @@ void IRsend::sendNECMSB(uint32_t data, uint8_t nbits, bool repeat) {
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);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
}
/** @}*/

View File

@ -59,7 +59,7 @@
#define DISH_REPEAT_SPACE 6200 // really?
struct PulseDistanceWidthProtocolConstants DishProtocolConstants = { UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE,
DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT, 40, NULL };
DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 40, NULL };
void IRsend::sendDish(uint16_t aData) {
sendPulseDistanceWidth(&DishProtocolConstants, aData, DISH_BITS, 4);
@ -85,7 +85,7 @@ void IRsend::sendDish(uint16_t aData) {
#define WHYNTER_ZERO_SPACE 750
struct PulseDistanceWidthProtocolConstants WhynterProtocolConstants = { WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE,
WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT, 110, NULL };
WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 110, NULL };
void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) {
sendPulseDistanceWidth(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfBitsToSend);

View File

@ -48,17 +48,17 @@
// 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 uint16_t bitsInHexadecimal = 4U;
static const uint16_t digitsInProntoNumber = 4U;
static const uint16_t numbersInPreamble = 4U;
static const uint16_t 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) {
static uint16_t toFrequencyKHz(uint16_t code) {
return ((referenceFrequency / code) + 500) / 1000;
}
@ -67,9 +67,9 @@ static unsigned int toFrequencyKHz(uint16_t code) {
* The first number denotes the type of the signal. 0000 denotes a raw IR signal with modulation,
// The second number denotes a frequency code
*/
void IRsend::sendPronto(const uint16_t *data, unsigned int length, int_fast8_t aNumberOfRepeats) {
unsigned int timebase = (microsecondsInSeconds * data[1] + referenceFrequency / 2) / referenceFrequency;
unsigned int khz;
void IRsend::sendPronto(const uint16_t *data, uint16_t length, int_fast8_t aNumberOfRepeats) {
uint16_t timebase = (microsecondsInSeconds * data[1] + referenceFrequency / 2) / referenceFrequency;
uint16_t khz;
switch (data[0]) {
case learnedToken: // normal, "learned"
khz = toFrequencyKHz(data[1]);
@ -80,8 +80,8 @@ void IRsend::sendPronto(const uint16_t *data, unsigned int length, int_fast8_t a
default:
return; // There are other types, but they are not handled yet.
}
unsigned int intros = 2 * data[2];
unsigned int repeats = 2 * data[3];
uint16_t intros = 2 * data[2];
uint16_t repeats = 2 * data[3];
#if defined(LOCAL_DEBUG)
Serial.print(F("sendPronto intros="));
Serial.print(intros);
@ -97,9 +97,9 @@ void IRsend::sendPronto(const uint16_t *data, unsigned int length, int_fast8_t a
* 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++) {
for (uint16_t 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);
durations[i] = (uint16_t) ((duration <= UINT16_MAX) ? duration : UINT16_MAX);
}
/*
@ -151,7 +151,7 @@ void IRsend::sendPronto(const char *str, int_fast8_t aNumberOfRepeats) {
uint16_t data[len];
const char *p = str;
char *endptr[1];
for (unsigned int i = 0; i < len; i++) {
for (uint16_t i = 0; i < len; i++) {
long x = strtol(p, endptr, 16);
if (x == 0 && i >= numbersInPreamble) {
// Alignment error?, bail immediately (often right result).
@ -206,17 +206,17 @@ static uint16_t toFrequencyCode(uint16_t frequency) {
return referenceFrequency / effectiveFrequency(frequency);
}
static char hexDigit(unsigned int x) {
static char hexDigit(uint16_t x) {
return (char) (x <= 9 ? ('0' + x) : ('A' + (x - 10)));
}
static void dumpDigit(Print *aSerial, unsigned int number) {
static void dumpDigit(Print *aSerial, uint16_t 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);
for (uint16_t i = 0; i < digitsInProntoNumber; i++) {
uint16_t shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
dumpDigit(aSerial, (number >> shifts) & hexMask);
}
aSerial->print(' ');
@ -229,7 +229,7 @@ static void dumpDuration(Print *aSerial, uint32_t duration, uint16_t 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) {
static void compensateAndDumpSequence(Print *aSerial, const volatile uint16_t *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) {
@ -251,14 +251,14 @@ static void compensateAndDumpSequence(Print *aSerial, const volatile unsigned in
* @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) {
void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t 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);
uint16_t timebase = toTimebase(aFrequencyHertz);
compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1, timebase); // skip leading space
aSerial->println("\";");
}
@ -268,7 +268,7 @@ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int aFr
* and can lead to resource problems especially on small processors like AVR's
*/
static bool dumpDigit(String *aString, unsigned int number) {
static bool dumpDigit(String *aString, uint16_t number) {
aString->concat(hexDigit(number));
return number;
}
@ -277,8 +277,8 @@ 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);
for (uint16_t i = 0; i < digitsInProntoNumber; i++) {
uint16_t shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
size += dumpDigit(aString, (number >> shifts) & hexMask);
}
aString->concat(' ');
@ -294,7 +294,7 @@ 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) {
static size_t compensateAndDumpSequence(String *aString, const volatile uint16_t *data, size_t length, uint16_t timebase) {
size_t size = 0;
@ -319,10 +319,10 @@ static size_t compensateAndDumpSequence(String *aString, const volatile unsigned
* 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 IRrecv::compensateAndStorePronto(String *aString, uint16_t frequency) {
size_t size = 0;
unsigned int timebase = toTimebase(frequency);
uint16_t timebase = toTimebase(frequency);
size += dumpNumber(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken);
size += dumpNumber(aString, toFrequencyCode(frequency));

View File

@ -138,9 +138,6 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe
delay(RC5_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -309,9 +306,6 @@ void IRsend::sendRC6Raw(uint32_t aRawData, uint8_t aNumberOfBitsToSend) {
mark(t);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -346,9 +340,6 @@ void IRsend::sendRC6Raw(uint64_t aRawData, uint8_t aNumberOfBitsToSend) {
mark(t);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -547,9 +538,6 @@ void IRsend::sendRC5(uint32_t data, uint8_t nbits) {
space(RC5_UNIT);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/*
@ -616,9 +604,6 @@ void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) {
space(RC5_UNIT);
}
}
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/** @}*/

View File

@ -98,7 +98,7 @@
struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK,
SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT, (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat };
(SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat };
/************************************
* Start of send and decode functions
@ -116,9 +116,6 @@ void IRsend::sendSamsungLGRepeat() {
mark(SAMSUNG_BIT_MARK); // + 560
space(SAMSUNG_ZERO_SPACE); // - 560
mark(SAMSUNG_BIT_MARK); // + 560
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/**
@ -132,9 +129,6 @@ void sendSamsungLGSpecialRepeat() {
IrSender.mark(SAMSUNG_BIT_MARK); // + 560
IrSender.space(SAMSUNG_ZERO_SPACE); // - 560
IrSender.mark(SAMSUNG_BIT_MARK); // + 560
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
}
/*
@ -206,7 +200,7 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu
} else {
tSendValue.ULongLong = aAddress | aCommand << 16;
}
IrSender.sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULongLong, SAMSUNG_BITS, aNumberOfRepeats);
IrSender.sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULongLong, SAMSUNG48_BITS, aNumberOfRepeats);
#endif
}
@ -360,10 +354,7 @@ void IRsend::sendSAMSUNG(unsigned long data, int nbits) {
// 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);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
PROTOCOL_IS_MSB_FIRST);
}
/** @}*/

View File

@ -52,14 +52,18 @@
// 7 command bits
+1300,- 450 +1350,- 450 +1300,- 450 + 700,- 450
+ 700,- 450 + 750,- 450 + 700,- 400
// (5,8,) 13 address bits
// (5,8,) 13 address bits
+1300,- 500
+ 700,- 450 + 700,- 450 +1300,- 500 +1300,- 450
+1300,- 450 + 700,- 450 +1350,- 400 + 750,- 450
+ 700,- 450 +1300,- 450 + 700,- 450 + 700
Sum: 31100
*/
/*
* Sony is the only protocol using the pulse width encoding, which requires no stop bit
*/
// see https://www.sbprojects.net/knowledge/ir/sirc.php
// https://www.mikrocontroller.net/articles/IRMP_-_english#SIRCS
// Frames are repeated every 45ms (measured from start to start) for as long as the key on the remote control is held down.
// This leads to a 15 ms gap for a Sony20 protocol!
// Here http://picprojects.org.uk/projects/sirc/ it is claimed, that many Sony remotes send each frame a minimum of 3 times. But 1 repeat (2 sends) has also been seen in real life.
@ -86,12 +90,8 @@
#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_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION_MIN) // 24 ms
#define SIRCS_12_PROTOCOL 12
#define SIRCS_15_PROTOCOL 15
#define SIRCS_20_PROTOCOL 20
struct PulseDistanceWidthProtocolConstants SonyProtocolConstants = { SONY, SONY_KHZ, SONY_HEADER_MARK, SONY_SPACE, SONY_ONE_MARK,
SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_NO_STOP_BIT, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
/************************************
* Start of send and decode functions
@ -222,11 +222,7 @@ void IRsend::sendSony(unsigned long data, int nbits) {
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,
SEND_NO_STOP_BIT);
#if !defined(DISABLE_CODE_FOR_RECEIVER)
IrReceiver.restartAfterSend();
#endif
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
}
/** @}*/

View File

@ -124,7 +124,7 @@
// use BOSEWAVE, we have no SHUZU code
struct PulseDistanceWidthProtocolConstants ShuzuProtocolConstants = { BOSEWAVE, 38, SHUZU_HEADER_MARK, SHUZU_HEADER_SPACE,
SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT, (SHUZU_REPEAT_PERIOD
SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SHUZU_REPEAT_PERIOD
/ MICROS_IN_ONE_MILLI), NULL };
/************************************