Version 1.2.0 of TinyIR. Closes #1097

This commit is contained in:
Armin 2023-02-20 03:22:15 +01:00
parent 970f228027
commit 920fa30303
12 changed files with 384 additions and 194 deletions

View File

@ -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

View File

@ -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 }}

View File

@ -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.<br/>Must be greater than any space of a protocol e.g. the NEC header space of 4500 &micro;s.<br/>Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.<br/>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 <IRCommandDispatcher.hpp>` 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. |

View File

@ -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).

View File

@ -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
}
/*

View File

@ -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 <http://www.gnu.org/licenses/gpl.html>.
* 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>
@ -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

View File

@ -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 <Arduino.h>
//#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

View File

@ -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(", <millisofRepeatPeriod>, <numberOfRepeats>"));
}

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/gpl.html>.
* 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

View File

@ -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 <http://www.gnu.org/licenses/gpl.html>.
* 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 <Arduino.h>
//#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);
}
}
}

View File

@ -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