diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 0a7c7f0..904c984 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -80,44 +80,49 @@ jobs: ############################################################################################################# include: - arduino-boards-fqbn: arduino:avr:uno - sketches-exclude: IR2Keyboard build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 - arduino-boards-fqbn: arduino:avr:uno|DEBUG - sketches-exclude: IR2Keyboard build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 All: -DEBUG - arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM - sketches-exclude: IR2Keyboard build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 + TinyReceiver: -DUSE_FAST_PROTOCOL + TinySender: -DUSE_FAST_PROTOCOL All: -DUSE_NO_SEND_PWM - arduino-boards-fqbn: arduino:avr:uno|SEND_PWM_BY_TIMER - sketches-exclude: IR2Keyboard,UnitTest + sketches-exclude: UnitTest build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 -DSEND_PWM_BY_TIMER + TinyReceiver: -DUSE_ONKYO_PROTOCOL + TinySender: -DUSE_ONKYO_PROTOCOL All: -DSEND_PWM_BY_TIMER - arduino-boards-fqbn: arduino:avr:uno|USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN - sketches-exclude: IR2Keyboard build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN SimpleSender: -DSEND_PWM_BY_TIMER + TinyReceiver: -DENABLE_NEC2_REPEATS + TinySender: -DENABLE_NEC2_REPEATS All: -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN - arduino-boards-fqbn: arduino:avr:mega:cpu=atmega2560 - sketches-exclude: IR2Keyboard build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 SimpleSender: -DSEND_PWM_BY_TIMER + TinyReceiver: -DDISABLE_PARITY_CHECKS + TinySender: -DDISABLE_PARITY_CHECKS - arduino-boards-fqbn: arduino:avr:leonardo build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 + TinyReceiver: -DNO_LED_FEEDBACK_CODE + TinySender: -DNO_LED_FEEDBACK_CODE # sketches-exclude: ReceiveAndSend # Not enough RAM for default RAW_BUFFER_LENGTH - arduino-boards-fqbn: arduino:megaavr:nona4809:mode=off @@ -125,6 +130,8 @@ jobs: build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 SimpleSender: -DSEND_PWM_BY_TIMER + TinyReceiver: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE + TinySender: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE - arduino-boards-fqbn: arduino:samd:arduino_zero_native sketches-exclude: TinyReceiver,IRDispatcherDemo diff --git a/.github/workflows/PlatformIoPublish.yml b/.github/workflows/PlatformIoPublish.yml index 8f0fa1e..cc9b32a 100644 --- a/.github/workflows/PlatformIoPublish.yml +++ b/.github/workflows/PlatformIoPublish.yml @@ -1,7 +1,7 @@ # PlatformIoPublish.yml # Github workflow script to publish a release to PlatformIo. # -# Copyright (C) 2021-2022 Armin Joachimsmeyer +# Copyright (C) 2021-2023 Armin Joachimsmeyer # https://github.com/ArminJo/Github-Actions # @@ -18,15 +18,20 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + + - name: Checkout + uses: actions/checkout@master + - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@master with: python-version: '3.x' + - name: Install dependencies run: | python -m pip install --upgrade pip pip install platformio + - name: Build and publish env: PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_TOKEN }} diff --git a/README.md b/README.md index 76e8042..2c99480 100644 --- a/README.md +++ b/README.md @@ -392,13 +392,13 @@ 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 **50 ms period**. It still supports full 8 bit parity for error detection! +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! ### FAST protocol characteristics: - Bit timing is like JVC -- The header is shorter, 4000 µs vs. 12500 µs -- 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. +- The header is shorter, 3156 µs vs. 12500 µ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. ### TinyIRSender with FAST protocol ```c++ @@ -605,7 +605,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `MARK_EXCESS_MICROS` | 20 | 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. | | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | | `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | -| `IR_SEND_PIN` | disabled | If specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this macro. | +| `IR_SEND_PIN` | disabled | If specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | | `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). | | `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Overrides `SEND_PWM_BY_TIMER` definition. | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | @@ -626,7 +626,9 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. | | `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. | -| `USE_FAST_PROTOCOL` | disabled | Receives a special fast protocol instead of NEC. | +| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | +| `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. | +| `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. | The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect. | `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. | diff --git a/changelog.md b/changelog.md index 6f6af42..5d68724 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,13 @@ 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 +- 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. + ## 4.0.0 - Added decoding of PulseDistanceWidth protocols and therfore changed function decodeDistance() to decodeDistanceWidth() and filename ir_DistanceProtocol.hpp to ir_DistanceWidthProtocol.hpp. - Removed static function printIRSendUsage(), but kept class function printIRSendUsage(). @@ -32,9 +39,6 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Improved SHARP repeat decoding. - Replaced macros TIMER_EN/DISABLE_RECEIVE_INTR and EN/DISABLE_SEND_PWM_BY_TIMER by functions. - Added SAMSUNG48 protocol and sendSamsung48() function. -- Fixed bug in printing durations > 64535 in printIRResultRawFormatted(). -- Narrowed constraints for RC5 RC6 number of bits. -- Changed the first parameter of printTinyReceiverResultMinimal() to &Serial. ## 3.9.0 - Improved documentation with the help of [ElectronicsArchiver}(https://github.com/ElectronicsArchiver). diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index be32373..2b79d36 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -56,14 +56,9 @@ void setup() { #endif // 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 } /* diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 944fc44..d23ddeb 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -12,34 +12,41 @@ * !!!!!!!!!!!!!!!!!!!!! * * 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. + * FAST takes 21 ms for sending and can be sent at a 40 ms period. It still supports parity. * FAST Protocol characteristics: * - Bit timing is like JVC - * - The header is shorter, 4000 vs. 12500 + * - 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 (7 + (16 * 2) + 1) * 526 = 40 * 560 = 21040 microseconds or 21 ms. - * - Repeats are sent as complete frames but in a 50 ms period. + * 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. * * - * Copyright (C) 2020-2023 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com - * * 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. * - * TinyIRReceiver is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + ************************************************************************************ + * MIT License * - * 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. + * Copyright (c) 2022-2023 Armin Joachimsmeyer * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 @@ -82,7 +89,10 @@ /* * Second: include the code and compile it. */ -//#define USE_FAST_PROTOCOL // Use short protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command +//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. +//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. +//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. #include "TinyIRReceiver.hpp" /* @@ -150,6 +160,8 @@ IRAM_ATTR #if defined(USE_FAST_PROTOCOL) void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags) +#elif defined(USE_ONKYO_PROTOCOL) +void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags) #else void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) #endif diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 364d9f9..226c9a0 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -1,20 +1,47 @@ /* * TinySender.cpp * - * Sending NEC protocol codes in standard format with 8bit address and 8 bit command as in SimpleSender example. + * Example for sending FAST or NEC protocol using TinyIR. + * + * 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). - * An extended example for sending can be found as SendDemo. * - * Copyright (C) 2022 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * + * 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. * - * MIT License + ************************************************************************************ + * MIT License + * + * Copyright (c) 2022-20232 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 -//#define USE_FAST_PROTOCOL // Use short protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command +//#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command +//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. +//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. +//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. + #include "TinyIRSender.hpp" #define IR_SEND_PIN 3 @@ -37,12 +64,13 @@ void setup() { /* * Set up the data to be sent. - * For most protocols, the data is build up with a constant 8 (or 16 byte) address - * and a variable 8 bit command. - * There are exceptions like Sony and Denon, which have 5 bit address. + * The compiler is intelligent and removes the code for 16 bit address handling if we call it with an uint8_t address :-). + * Using an uint16_t address or data requires additional 28 bytes program memory for NEC and 56 bytes program memory for FAST. */ uint8_t sAddress = 0x02; +//uint16_t sAddress = 0x02; uint8_t sCommand = 0x34; +//uint16_t sCommand = 0x34; uint8_t sRepeats = 0; void loop() { @@ -64,11 +92,15 @@ void loop() { #if defined(USE_FAST_PROTOCOL) Serial.println(F("Send FAST with 8 bit address")); Serial.flush(); - sendFast8BitAndParity(IR_SEND_PIN, sCommand, sRepeats); + sendFAST(IR_SEND_PIN, sCommand, sRepeats); +#elif defined(USE_ONKYO_PROTOCOL) + Serial.println(F("Send ONKYO with 16 bit address and command")); + Serial.flush(); + sendONKYO(IR_SEND_PIN, sAddress, sCommand, sRepeats); #else Serial.println(F("Send NEC with 8 bit address")); Serial.flush(); - sendNECMinimal(IR_SEND_PIN, sAddress, sCommand, sRepeats); + sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); #endif /* * Increment send values diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index d33039e..9c44207 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -153,7 +153,7 @@ ISR() * So we change the code to if / else if */ // switch (irparams.StateForISR) { -//...................................................................... +// if (irparams.StateForISR == IR_REC_STATE_IDLE) { /* * Here we are just resumed and maybe in the middle of a transmission @@ -186,7 +186,7 @@ ISR() #endif irparams.rawbuf[irparams.rawlen++] = irparams.TickCounterForISR; // record mark irparams.StateForISR = IR_REC_STATE_SPACE; - irparams.TickCounterForISR = 0; // This resets the tick counter also at end of frame :-) + irparams.TickCounterForISR = 0;// This resets the tick counter also at end of frame :-) } } else if (irparams.StateForISR == IR_REC_STATE_SPACE) { // Timing space @@ -1268,6 +1268,9 @@ void IRrecv::printIRSendUsage(Print *aSerial) { #if defined(DECODE_DISTANCE_WIDTH) } else { + /* + * Pulse distance or pulse width here + */ if(tNumberOfArrayData > 1) { aSerial->print("PulseDistanceWidthFromArray(38, "); } else { @@ -1316,7 +1319,7 @@ void IRrecv::printIRSendUsage(Print *aSerial) { if (decodedIRData.protocol == PULSE_DISTANCE) { aSerial->print(F(", SEND_STOP_BIT")); } else { - aSerial->print(F(", SEND_NO_STOP_BIT")); // assume no stop bit like for Magiquest. + aSerial->print(F(", SEND_NO_STOP_BIT")); // assume no stop bit for pulse width like for Magiquest. } aSerial->print(F(", , ")); } diff --git a/src/TinyIR.h b/src/TinyIR.h index d793397..9eb2122 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -34,13 +34,11 @@ * @{ */ -#define VERSION_IRTINY "1.1.0" +#define VERSION_IRTINY "1.2.0" #define VERSION_IRTINY_MAJOR 1 -#define VERSION_IRTINY_MINOR 1 +#define VERSION_IRTINY_MINOR 2 #define VERSION_IRTINY_PATCH 0 - - -//#define SUPPORT_ONKYO_16_BIT_COMMAND // If activated take the 16 bit (NEC) command as one 16 bit value and not as 8 bit data and 8 bit inverted data +// The change log is at the bottom of the file /** * Timing for NEC protocol @@ -70,79 +68,80 @@ /** * FAST protocol characteristics: * - Bit timing is like JVC - * - The header is shorter, 4000 vs. 12500 + * - 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 (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. + * 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. */ -#define FAST_PARITY_ADDRESS_BITS 0 // No address -#define FAST_PARITY_COMMAND_BITS 16 // Command and inverted command (parity) -#define FAST_PARITY_BITS (FAST_PARITY_ADDRESS_BITS + FAST_PARITY_COMMAND_BITS) +#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) -#define FAST_PARITY_UNIT 526 // 20 periods of 38 kHz (526.315789) +#define FAST_UNIT 526 // 20 periods of 38 kHz (526.315789) -#define FAST_PARITY_BIT_MARK FAST_PARITY_UNIT -#define FAST_PARITY_ONE_SPACE (3 * FAST_PARITY_UNIT) // 1578 -> bit period = 2104 -#define FAST_PARITY_ZERO_SPACE FAST_PARITY_UNIT // 526 -> bit period = 1052 +#define FAST_BIT_MARK FAST_UNIT +#define FAST_ONE_SPACE (3 * FAST_UNIT) // 1578 -> bit period = 2104 +#define FAST_ZERO_SPACE FAST_UNIT // 526 -> bit period = 1052 -#define FAST_PARITY_HEADER_MARK (4 * FAST_PARITY_UNIT) // 2104 -#define FAST_PARITY_HEADER_SPACE (FAST_PARITY_ONE_SPACE) // 1578 +#define FAST_HEADER_MARK (4 * FAST_UNIT) // 2104 +#define FAST_HEADER_SPACE (2 * FAST_UNIT) // 1052 -#define FAST_PARITY_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_PARITY_REPEAT_DISTANCE (FAST_PARITY_REPEAT_PERIOD - (40 * FAST_PARITY_UNIT)) // 29 ms -#define FAST_PARITY_MAXIMUM_REPEAT_DISTANCE (FAST_PARITY_REPEAT_DISTANCE + 10000) // 47.5 ms +#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 /* * Definitions to switch between FAST and NEC/ONKYO timing with the same code. */ #if defined(USE_FAST_PROTOCOL) -#define TINY_ADDRESS_BITS FAST_PARITY_ADDRESS_BITS -#define TINY_COMMAND_BITS FAST_PARITY_COMMAND_BITS -#if !defined(TINY_COMMAND_HAS_8_BIT_PARITY) -#define TINY_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity -//#define TINY_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity - not tested +#define ENABLE_NEC2_REPEATS // Disables detection of special short frame NEC repeats. Saves 40 bytes program memory. + +#define TINY_RECEIVER_ADDRESS_BITS FAST_ADDRESS_BITS +#define TINY_RECEIVER_COMMAND_BITS FAST_COMMAND_BITS +#if !defined(TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY) +#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity +//#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity - not tested #endif -#define TINY_BITS FAST_PARITY_BITS -#define TINY_UNIT FAST_PARITY_UNIT +#define TINY_RECEIVER_BITS FAST_BITS +#define TINY_RECEIVER_UNIT FAST_UNIT -#define TINY_HEADER_MARK FAST_PARITY_HEADER_MARK -#define TINY_HEADER_SPACE FAST_PARITY_HEADER_SPACE +#define TINY_RECEIVER_HEADER_MARK FAST_HEADER_MARK +#define TINY_RECEIVER_HEADER_SPACE FAST_HEADER_SPACE -#define TINY_BIT_MARK FAST_PARITY_BIT_MARK -#define TINY_ONE_SPACE FAST_PARITY_ONE_SPACE -#define TINY_ZERO_SPACE FAST_PARITY_ZERO_SPACE +#define TINY_RECEIVER_BIT_MARK FAST_BIT_MARK +#define TINY_RECEIVER_ONE_SPACE FAST_ONE_SPACE +#define TINY_RECEIVER_ZERO_SPACE FAST_ZERO_SPACE -#define TINY_MAXIMUM_REPEAT_DISTANCE FAST_PARITY_MAXIMUM_REPEAT_DISTANCE // for repeat detection +#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE FAST_MAXIMUM_REPEAT_DISTANCE // for repeat detection #else -#define ENABLE_NEC_REPEAT_SUPPORT // Activating this, enables detection of special short frame NEC repeats. Requires 40 bytes program memory. -#define TINY_ADDRESS_BITS NEC_ADDRESS_BITS // the address bits + parity -# if !defined(TINY_ADDRESS_HAS_8_BIT_PARITY) -#define TINY_ADDRESS_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity +#define TINY_RECEIVER_ADDRESS_BITS NEC_ADDRESS_BITS // the address bits + parity +# if defined(USE_ONKYO_PROTOCOL) +#define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity +# else +#define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity # endif -#define TINY_COMMAND_BITS NEC_COMMAND_BITS // the command bits + parity -# if !defined(TINY_COMMAND_HAS_8_BIT_PARITY) -# if defined(SUPPORT_ONKYO_16_BIT_COMMAND) -#define TINY_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity -# else -#define TINY_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity -# endif +#define TINY_RECEIVER_COMMAND_BITS NEC_COMMAND_BITS // the command bits + parity +# if defined(USE_ONKYO_PROTOCOL) +#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity +# else +#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity # endif -#define TINY_BITS NEC_BITS -#define TINY_UNIT NEC_UNIT +#define TINY_RECEIVER_BITS NEC_BITS +#define TINY_RECEIVER_UNIT NEC_UNIT -#define TINY_HEADER_MARK NEC_HEADER_MARK -#define TINY_HEADER_SPACE NEC_HEADER_SPACE +#define TINY_RECEIVER_HEADER_MARK NEC_HEADER_MARK +#define TINY_RECEIVER_HEADER_SPACE NEC_HEADER_SPACE -#define TINY_BIT_MARK NEC_BIT_MARK -#define TINY_ONE_SPACE NEC_ONE_SPACE -#define TINY_ZERO_SPACE NEC_ZERO_SPACE +#define TINY_RECEIVER_BIT_MARK NEC_BIT_MARK +#define TINY_RECEIVER_ONE_SPACE NEC_ONE_SPACE +#define TINY_RECEIVER_ZERO_SPACE NEC_ZERO_SPACE -#define TINY_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE +#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE #endif /* @@ -150,18 +149,18 @@ * The parameter size is dependent of the code variant used in order to save program memory. * We have 6 cases: 0, 8 bit or 16 bit address, each with 8 or 16 bit command */ -#if (TINY_ADDRESS_BITS > 0) -# if TINY_ADDRESS_HAS_8_BIT_PARITY +#if (TINY_RECEIVER_ADDRESS_BITS > 0) +# if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY // 8 bit address here -# if TINY_COMMAND_HAS_8_BIT_PARITY +# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY extern void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags); // Standard NEC callback # else extern void handleReceivedTinyIRData(uint8_t aAddress, uint16_t aCommand, uint8_t aFlags); // If SUPPORT_ONKYO_16_BIT_COMMAND is defined # endif -# else // TINY_ADDRESS_HAS_8_BIT_PARITY +# else // TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY // 16 bit address here -# if TINY_COMMAND_HAS_8_BIT_PARITY +# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY extern void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, uint8_t aFlags); # else extern void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags); @@ -170,10 +169,10 @@ extern void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8 #else // FAST protocol - No address here -# if TINY_COMMAND_HAS_8_BIT_PARITY +# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY extern void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags); // Standard FAST callback # else -extern void handleReceivedTinyIRData(uint16_t aCommand, uint8_t aFlags); // If "TINY_COMMAND_HAS_8_BIT_PARITY false" is defined. 16 bit without parity. +extern void handleReceivedTinyIRData(uint16_t aCommand, uint8_t aFlags); // If "TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false" is defined. 16 bit without parity. # endif #endif @@ -215,7 +214,7 @@ struct TinyIRReceiverStruct { /* * Data */ -#if (TINY_BITS > 16) +#if (TINY_RECEIVER_BITS > 16) uint32_t IRRawDataMask; ///< The corresponding bit mask for IRRawDataBitCounter. LongUnion IRRawData; ///< The current raw data. LongUnion helps with decoding of address and command. #else @@ -239,15 +238,15 @@ struct TinyIRReceiverStruct { * E.g. with volatile struct TinyIRReceiverCallbackDataStruct sCallbackData; */ struct TinyIRReceiverCallbackDataStruct { -#if (TINY_ADDRESS_BITS > 0) -# if (TINY_ADDRESS_BITS == 16) && !TINY_ADDRESS_HAS_8_BIT_PARITY +#if (TINY_RECEIVER_ADDRESS_BITS > 0) +# if (TINY_RECEIVER_ADDRESS_BITS == 16) && !TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY uint16_t Address; # else uint8_t Address; # endif #endif -# if (TINY_COMMAND_BITS == 16) && !TINY_COMMAND_HAS_8_BIT_PARITY +# if (TINY_RECEIVER_COMMAND_BITS == 16) && !TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY uint16_t Command; #else uint8_t Command; @@ -266,8 +265,21 @@ void printTinyReceiverResultMinimal(Print *aSerial, uint16_t aCommand, uint8_t a void printTinyReceiverResultMinimal(Print *aSerial, uint8_t aAddress, uint8_t aCommand, uint8_t aFlags); #endif +void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); -void sendNECMinimal(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); +void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); // Send NEC with 16 bit command, even if aCommand < 0x100 +void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0) + __attribute__ ((deprecated ("Renamed to sendNEC()."))); +void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); + +/* + * Version 1.2.0 - 01/2023 + * - Added ONKYO protocol, NEC with 16 bit address and command, instead of 8 bit + 8 bit parity address and command. + * - Renamed functions and macros. + * + * Version 1.1.0 - 01/2023 + * - FAST protocol added. + */ /** @}*/ #endif // _TINY_IR_H diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 1a8f5d7..d2bfc83 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -23,35 +23,45 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 29 ms distance. * * - * Copyright (C) 2021-2023 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com - * * 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. * - * TinyIRReceiver is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + ************************************************************************************ + * MIT License * - * 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. + * Copyright (c) 2022-20232 Armin Joachimsmeyer * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * + ************************************************************************************ */ /* * This library can be configured at compile time by the following options / macros: * For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library (scroll down) * - * - IR_RECEIVE_PIN The pin number for TinyIRReceiver IR input. + * - IR_RECEIVE_PIN The pin number for TinyIRReceiver IR input. * - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED. * - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory. - * + * - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory. + * - USE_ONKYO_PROTOCOL Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. + * - USE_FAST_PROTOCOL Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. + * - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. */ #ifndef _TINY_IR_RECEIVER_HPP @@ -66,7 +76,10 @@ #endif //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. -//#define USE_FAST_PROTOCOL // Use short protocol +//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC. +//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. + #include "TinyIR.h" // If not defined, it defines IR_RECEIVE_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT #include "digitalWriteFast.h" @@ -180,7 +193,7 @@ void IRPinChangeInterruptHandler(void) { /* * We have a mark here */ - if (tMicrosOfMarkOrSpace > 2 * TINY_HEADER_MARK) { + if (tMicrosOfMarkOrSpace > 2 * TINY_RECEIVER_HEADER_MARK) { // timeout -> must reset state machine tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } @@ -191,35 +204,35 @@ void IRPinChangeInterruptHandler(void) { #if defined(LOCAL_TRACE) sMicrosOfGap = tMicrosOfMarkOrSpace32; #endif -#if !defined(ENABLE_NEC_REPEAT_SUPPORT) - // Check for repeat, where full frame is sent again after TINY_REPEAT_PERIOD ms +#if defined(ENABLE_NEC2_REPEATS) + // Check for repeat, where full frame is sent again after TINY_RECEIVER_REPEAT_PERIOD ms // Not required for NEC, where repeats are detected by a special header space duration // Must use 32 bit arithmetic here! - if (tMicrosOfMarkOrSpace32 < TINY_MAXIMUM_REPEAT_DISTANCE) { + if (tMicrosOfMarkOrSpace32 < TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE) { TinyIRReceiverControl.Flags = IRDATA_FLAGS_IS_REPEAT; } #endif } else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) { - if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_HEADER_SPACE) - && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_HEADER_SPACE)) { + if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_SPACE) + && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_SPACE)) { /* * We have a valid data header space here -> initialize data */ TinyIRReceiverControl.IRRawDataBitCounter = 0; -#if (TINY_BITS > 16) +#if (TINY_RECEIVER_BITS > 16) TinyIRReceiverControl.IRRawData.ULong = 0; #else TinyIRReceiverControl.IRRawData.UWord = 0; #endif TinyIRReceiverControl.IRRawDataMask = 1; tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE; -#if defined(ENABLE_NEC_REPEAT_SUPPORT) +#if !defined(ENABLE_NEC2_REPEATS) // Check for NEC repeat header } else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE) && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE) - && TinyIRReceiverControl.IRRawDataBitCounter >= TINY_BITS) { + && TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS) { /* * We have a repeat header here and no broken receive before -> set repeat flag */ @@ -235,13 +248,13 @@ void IRPinChangeInterruptHandler(void) { else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) { // Check data space length - if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_ZERO_SPACE) - && tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_ONE_SPACE)) { + if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_ZERO_SPACE) + && tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_ONE_SPACE)) { // We have a valid bit here tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE; - if (tMicrosOfMarkOrSpace >= 2 * TINY_UNIT) { + if (tMicrosOfMarkOrSpace >= 2 * TINY_RECEIVER_UNIT) { // we received a 1 -#if (TINY_BITS > 16) +#if (TINY_RECEIVER_BITS > 16) TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask; #else TinyIRReceiverControl.IRRawData.UWord |= TinyIRReceiverControl.IRRawDataMask; @@ -270,8 +283,8 @@ void IRPinChangeInterruptHandler(void) { /* * Check length of header mark here */ - if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_HEADER_MARK) - && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_HEADER_MARK)) { + if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_MARK) + && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_MARK)) { tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK; } else { // Wrong length of header mark -> reset state @@ -281,23 +294,23 @@ void IRPinChangeInterruptHandler(void) { else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) { // Check data mark length - if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_BIT_MARK) - && tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_BIT_MARK)) { + if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_BIT_MARK) + && tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_BIT_MARK)) { /* * We have a valid mark here, check for transmission complete, i.e. the mark of the stop bit */ - if (TinyIRReceiverControl.IRRawDataBitCounter >= TINY_BITS -#if defined(ENABLE_NEC_REPEAT_SUPPORT) + if (TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS +#if !defined(ENABLE_NEC2_REPEATS) || (TinyIRReceiverControl.Flags & IRDATA_FLAGS_IS_REPEAT) // Do not check for full length received, if we have a short repeat frame #endif ) { /* - * Code complete -> call callback, no parity check! + * Code complete -> optionally check parity */ // Reset state for new start tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; -#if !defined(DISABLE_PARITY_CHECKS) && (TINY_ADDRESS_BITS == 16) && TINY_ADDRESS_HAS_8_BIT_PARITY +#if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY /* * Check address parity * Address is sent first and contained in the lower word @@ -306,11 +319,11 @@ void IRPinChangeInterruptHandler(void) { TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; } #endif -#if !defined(DISABLE_PARITY_CHECKS) && (TINY_COMMAND_BITS == 16) && TINY_COMMAND_HAS_8_BIT_PARITY +#if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY /* * Check command parity */ -#if (TINY_ADDRESS_BITS > 0) +#if (TINY_RECEIVER_ADDRESS_BITS > 0) if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[3])) { TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; # if defined(LOCAL_DEBUG) @@ -341,15 +354,15 @@ void IRPinChangeInterruptHandler(void) { interrupts(); // enable interrupts, so delay() etc. works in callback #endif handleReceivedTinyIRData( -#if (TINY_ADDRESS_BITS > 0) -# if TINY_ADDRESS_HAS_8_BIT_PARITY +#if (TINY_RECEIVER_ADDRESS_BITS > 0) +# if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY // Here we have 8 bit address TinyIRReceiverControl.IRRawData.UBytes[0], # else // Here we have 16 bit address TinyIRReceiverControl.IRRawData.UWord.LowWord, # endif -# if TINY_COMMAND_HAS_8_BIT_PARITY +# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY // Here we have 8 bit command TinyIRReceiverControl.IRRawData.UBytes[3], # else @@ -359,7 +372,7 @@ void IRPinChangeInterruptHandler(void) { #else // Here we have NO address -# if TINY_COMMAND_HAS_8_BIT_PARITY +# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY // Here we have 8 bit command TinyIRReceiverControl.IRRawData.UBytes[0], # else diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 942f058..e35e261 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -14,25 +14,32 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 29 ms distance. * * - * Copyright (C) 2022-2023 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com - * * 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. * - * TinyIRReceiver is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + ************************************************************************************ + * MIT License * - * 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. + * Copyright (c) 2022-20232 Armin Joachimsmeyer * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 _TINY_IR_SENDER_HPP @@ -40,6 +47,8 @@ #include +//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. + #if defined(DEBUG) && !defined(LOCAL_DEBUG) #define LOCAL_DEBUG #else @@ -92,7 +101,13 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { } while (true); } -void sendNECMinimal(uint8_t aSendPin, uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) { +/* + * Send NEC with 16 bit command, even if aCommand < 0x100 + * @param aAddress - The 16 bit address to send. + * @param aCommand - The 16 bit command to send. + * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. + */ +void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -100,17 +115,88 @@ void sendNECMinimal(uint8_t aSendPin, uint8_t aAddress, uint8_t aCommand, uint_f unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); +#if !defined(ENABLE_NEC2_REPEATS) if (tNumberOfCommands < aNumberOfRepeats + 1) { // send the NEC special repeat delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 - } else { + } else +#endif + { // send header delayMicroseconds(NEC_HEADER_SPACE); LongUnion tData; - tData.UByte.LowByte = aAddress; // LSB first - tData.UByte.MidLowByte = ~aAddress; - tData.UByte.MidHighByte = aCommand; - tData.UByte.HighByte = ~aCommand; // LSB first + tData.UWord.LowWord = aAddress; + tData.UWord.HighWord = aCommand; + // Send data + for (uint_fast8_t i = 0; i < NEC_BITS; ++i) { + sendMark(aSendPin, NEC_BIT_MARK); // constant mark length + if (tData.ULong & 1) { + delayMicroseconds(NEC_ONE_SPACE); + } else { + delayMicroseconds(NEC_ZERO_SPACE); + } + tData.ULong >>= 1; // shift command for next bit + } + } // send stop bit + sendMark(aSendPin, NEC_BIT_MARK); + + tNumberOfCommands--; + // skip last delay! + if (tNumberOfCommands > 0) { + /* + * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. + */ + auto tFrameDurationMillis = millis() - tStartOfFrameMillis; + if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { + delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis); + } + } + } +} + +/* + * Send NEC with 8 or 16 bit address or data depending on the values of aAddress and aCommand. + * @param aAddress - If aAddress < 0x100 send 8 bit address and 8 bit inverted address, else send 16 bit address. + * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. + * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. + */ +void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { + sendNEC(aSendPin, aAddress, aCommand, aNumberOfRepeats); // sendNECMinimal() is deprecated +} +void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { + pinModeFast(aSendPin, OUTPUT); + + uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; + while (tNumberOfCommands > 0) { + unsigned long tStartOfFrameMillis = millis(); + + sendMark(aSendPin, NEC_HEADER_MARK); +#if !defined(ENABLE_NEC2_REPEATS) + if (tNumberOfCommands < aNumberOfRepeats + 1) { + // send the NEC special repeat + delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 + } else +#endif + { + // send header + delayMicroseconds(NEC_HEADER_SPACE); + LongUnion tData; + /* + * The compiler is intelligent and removes the code for "(aAddress > 0xFF)" if we are called with an uint8_t address :-). + * Using an uint16_t address requires additional 28 bytes program memory. + */ + if (aAddress > 0xFF) { + tData.UWord.LowWord = aAddress; + } else { + tData.UByte.LowByte = aAddress; // LSB first + tData.UByte.MidLowByte = ~aAddress; + } + if (aCommand > 0xFF) { + tData.UWord.HighWord = aCommand; + } else { + tData.UByte.MidHighByte = aCommand; + tData.UByte.HighByte = ~aCommand; // LSB first + } // Send data for (uint_fast8_t i = 0; i < NEC_BITS; ++i) { sendMark(aSendPin, NEC_BIT_MARK); // constant mark length @@ -143,6 +229,13 @@ void sendNECMinimal(uint8_t aSendPin, uint8_t aAddress, uint8_t aCommand, uint_f * LSB first, send header, command, inverted command and stop bit */ void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) { + sendFAST(aSendPin, aCommand, aNumberOfRepeats); +} + +/* + * LSB first, send header, 16 bit command or 8 bit command, inverted command and stop bit + */ +void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -150,22 +243,31 @@ void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNum unsigned long tStartOfFrameMillis = millis(); // send header - sendMark(aSendPin, FAST_PARITY_HEADER_MARK); - delayMicroseconds(FAST_PARITY_HEADER_SPACE); - uint16_t tData = aCommand | (((uint8_t) (~aCommand)) << 8); // LSB first + sendMark(aSendPin, FAST_HEADER_MARK); + delayMicroseconds(FAST_HEADER_SPACE); + 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. + */ + if (aCommand > 0xFF) { + tData = aCommand; + } else { + tData = aCommand | (((uint8_t) (~aCommand)) << 8); // LSB first + } // Send data - for (uint_fast8_t i = 0; i < FAST_PARITY_BITS; ++i) { - sendMark(aSendPin, FAST_PARITY_BIT_MARK); // constant mark length + for (uint_fast8_t i = 0; i < FAST_BITS; ++i) { + sendMark(aSendPin, FAST_BIT_MARK); // constant mark length if (tData & 1) { - delayMicroseconds(FAST_PARITY_ONE_SPACE); + delayMicroseconds(FAST_ONE_SPACE); } else { - delayMicroseconds(FAST_PARITY_ZERO_SPACE); + delayMicroseconds(FAST_ZERO_SPACE); } tData >>= 1; // shift command for next bit } // send stop bit - sendMark(aSendPin, FAST_PARITY_BIT_MARK); + sendMark(aSendPin, FAST_BIT_MARK); tNumberOfCommands--; // skip last delay! @@ -174,8 +276,8 @@ void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNum * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. */ auto tFrameDurationMillis = millis() - tStartOfFrameMillis; - if (FAST_PARITY_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { - delay(FAST_PARITY_REPEAT_PERIOD / 1000 - tFrameDurationMillis); + if (FAST_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { + delay(FAST_REPEAT_PERIOD / 1000 - tFrameDurationMillis); } } } diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index acc8ca1..f3e4c8c 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -75,7 +75,10 @@ Sum: 13400 // ONKYO like NEC but 16 independent command bits // PIONEER (not implemented) is NEC2 with 40 kHz // LSB first, 1 start bit + 16 bit address (or 8 bit address and 8 bit inverted address) + 8 bit command + 8 bit inverted command + 1 stop bit. -// Standard NEC (or NEC1) sends a special fixed repeat frame, but I have a DVD remote with NEC2, which send the same full frame after the 110 ms. +// Standard NEC sends a special fixed repeat frame. +// NEC2 sends the same full frame after the 110 ms. I have a DVD remote with NEC2. +// NEC and NEC 2 only differ in the repeat frames, so the protocol can only be detected correctly after the first repeat. +// // IRP: NEC {38.0k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108m,(16,-4,1,^108m)*) ==> "*" means send special repeat frames o ore more times // IRP: NEC2 {38.0k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108m)+ ==> "+" means send frame 1 or more times (special repeat is missing here!) // {38.0k,564} ==> 38.0k -> Frequency , 564 -> unit in microseconds (we use 560), no "msb", so "lsb" is assumed