2021-01-04 09:54:10 +08:00
/*
2022-12-27 23:59:32 +08:00
* TinyReceiver . cpp
2021-01-04 09:54:10 +08:00
*
2021-01-28 00:28:44 +08:00
* Small memory footprint and no timer usage !
*
2021-01-04 09:54:10 +08:00
* Receives IR protocol data of NEC protocol using pin change interrupts .
2022-11-12 02:53:54 +08:00
* On complete received IR command the function handleReceivedIRData ( uint16_t aAddress , uint8_t aCommand , uint8_t aFlags )
2021-01-04 09:54:10 +08:00
* is called in Interrupt context but with interrupts being enabled to enable use of delay ( ) etc .
* ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
* Functions called in interrupt context should be running as short as possible ,
2021-03-02 22:25:39 +08:00
* so if you require longer action , save the data ( address + command ) and handle it in the main loop .
2021-01-04 09:54:10 +08:00
* ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
*
2023-02-24 09:40:21 +08:00
* The FAST protocol is a proprietary modified JVC protocol without address , with parity and with a shorter header .
2023-02-12 07:23:11 +08:00
* FAST Protocol characteristics :
2023-02-24 09:40:21 +08:00
* - Bit timing is like NEC or JVC
* - The header is shorter , 3156 vs . 12500
* - No address and 16 bit data , interpreted as 8 bit command and 8 bit inverted command ,
* leading to a fixed protocol length of ( 6 + ( 16 * 3 ) + 1 ) * 526 = 55 * 526 = 28930 microseconds or 29 ms .
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance .
2021-01-04 09:54:10 +08:00
*
2023-02-12 07:23:11 +08:00
*
2022-08-17 16:54:56 +08:00
* This file is part of IRMP https : //github.com/IRMP-org/IRMP.
2021-03-03 02:59:41 +08:00
* This file is part of Arduino - IRremote https : //github.com/Arduino-IRremote/Arduino-IRremote.
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* MIT License
*
* Copyright ( c ) 2022 - 2023 Armin Joachimsmeyer
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* 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 :
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* 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 .
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2021-01-04 09:54:10 +08:00
*/
# include <Arduino.h>
/*
2021-02-19 06:43:11 +08:00
* Set sensible receive pin for different CPU ' s
2021-01-04 09:54:10 +08:00
*/
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
2023-02-11 18:55:44 +08:00
/*
* This program runs on 1 MHz CPU clock : - ) and is requires only 1550 bytes program memory using ATTiny core
*/
# include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut" - Saves up to 700 bytes program memory and 70 bytes RAM for ATtinyCore
2021-01-04 09:54:10 +08:00
# if defined(ARDUINO_AVR_DIGISPARKPRO)
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
2021-01-04 09:54:10 +08:00
# else
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 0 // PCINT0
2021-01-04 09:54:10 +08:00
# endif
2021-01-18 20:44:30 +08:00
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 10
2022-07-30 16:26:04 +08:00
# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 21 // INT0
2022-01-27 23:33:27 +08:00
# elif defined(ESP8266)
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 14 // D5
2022-11-12 02:53:54 +08:00
# elif defined(CONFIG_IDF_TARGET_ESP32C3)
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 8
2022-01-27 23:33:27 +08:00
# elif defined(ESP32)
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 15
2022-01-27 11:11:54 +08:00
# elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO)
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
2022-01-27 11:11:54 +08:00
# elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
2021-01-18 20:44:30 +08:00
# else
2023-02-12 07:23:11 +08:00
# define IR_RECEIVE_PIN 2 // INT0
2022-04-05 10:47:32 +08:00
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
2021-01-04 09:54:10 +08:00
# endif
2021-12-02 04:45:53 +08:00
//#define DEBUG // to see if attachInterrupt is used
//#define TRACE // to see the state of the ISR state machine
2021-11-29 20:41:03 +08:00
2021-01-04 09:54:10 +08:00
/*
* Second : include the code and compile it .
*/
2023-02-20 10:22:15 +08:00
//#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.
2021-09-09 21:53:50 +08:00
# include "TinyIRReceiver.hpp"
2021-01-04 09:54:10 +08:00
/*
* Helper macro for getting a macro definition as string
*/
2021-12-02 04:45:53 +08:00
# if !defined(STR_HELPER)
2021-01-04 09:54:10 +08:00
# define STR_HELPER(x) #x
# define STR(x) STR_HELPER(x)
2021-12-02 04:45:53 +08:00
# endif
2021-01-04 09:54:10 +08:00
2022-01-27 23:33:27 +08:00
volatile struct TinyIRReceiverCallbackDataStruct sCallbackData ;
2022-11-12 02:53:54 +08:00
void setup ( ) {
2021-01-04 09:54:10 +08:00
Serial . begin ( 115200 ) ;
2022-04-05 10:47:32 +08:00
# if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/ || defined(USBCON) /*STM32_stm32*/ || defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
2021-04-08 07:51:03 +08:00
delay ( 4000 ) ; // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
2021-01-04 09:54:10 +08:00
# endif
// Just to know which program is running on my Arduino
2022-11-12 02:53:54 +08:00
# if defined(ESP8266) || defined(ESP32)
2021-01-04 09:54:10 +08:00
Serial . println ( ) ;
# endif
2023-02-24 09:40:21 +08:00
Serial . println ( F ( " START " __FILE__ " from " __DATE__ " \r \n Using library version " VERSION_TINYIR ) ) ;
2023-02-12 07:23:11 +08:00
// Enables the interrupt generation on change of IR input signal
2022-11-12 02:53:54 +08:00
if ( ! initPCIInterruptForTinyReceiver ( ) ) {
2023-02-12 07:23:11 +08:00
Serial . println ( F ( " No interrupt available for pin " STR ( IR_RECEIVE_PIN ) ) ) ; // optimized out by the compiler, if not required :-)
2022-07-30 16:26:04 +08:00
}
2023-02-12 07:23:11 +08:00
# if defined(USE_FAST_PROTOCOL)
Serial . println ( F ( " Ready to receive Fast IR signals at pin " STR ( IR_RECEIVE_PIN ) ) ) ;
2022-11-12 02:53:54 +08:00
# else
2023-02-12 07:23:11 +08:00
Serial . println ( F ( " Ready to receive NEC IR signals at pin " STR ( IR_RECEIVE_PIN ) ) ) ;
2022-11-12 02:53:54 +08:00
# endif
2021-01-04 09:54:10 +08:00
}
2022-11-12 02:53:54 +08:00
void loop ( ) {
if ( sCallbackData . justWritten ) {
2022-01-27 23:33:27 +08:00
sCallbackData . justWritten = false ;
2023-02-12 07:23:11 +08:00
# if defined(USE_FAST_PROTOCOL)
2022-11-12 02:53:54 +08:00
Serial . print ( F ( " Command=0x " ) ) ;
# else
2022-01-27 23:33:27 +08:00
Serial . print ( F ( " Address=0x " ) ) ;
Serial . print ( sCallbackData . Address , HEX ) ;
Serial . print ( F ( " Command=0x " ) ) ;
2022-11-12 02:53:54 +08:00
# endif
2022-01-27 23:33:27 +08:00
Serial . print ( sCallbackData . Command , HEX ) ;
2022-11-12 02:53:54 +08:00
if ( sCallbackData . Flags = = IRDATA_FLAGS_IS_REPEAT ) {
2022-01-27 23:33:27 +08:00
Serial . print ( F ( " Repeat " ) ) ;
}
2022-11-12 02:53:54 +08:00
if ( sCallbackData . Flags = = IRDATA_FLAGS_PARITY_FAILED ) {
Serial . print ( F ( " Parity failed " ) ) ;
}
2022-01-27 23:33:27 +08:00
Serial . println ( ) ;
}
2021-01-04 09:54:10 +08:00
/*
* Put your code here
*/
}
/*
* This is the function is called if a complete command was received
2023-02-12 07:23:11 +08:00
* It runs in an ISR context with interrupts enabled , so functions like delay ( ) etc . should work here
2021-01-04 09:54:10 +08:00
*/
2022-05-30 05:01:38 +08:00
# if defined(ESP8266) || defined(ESP32)
2022-11-12 02:53:54 +08:00
IRAM_ATTR
2021-01-04 09:54:10 +08:00
# endif
2022-01-27 23:33:27 +08:00
2023-02-12 07:23:11 +08:00
# if defined(USE_FAST_PROTOCOL)
2022-11-12 02:53:54 +08:00
void handleReceivedTinyIRData ( uint8_t aCommand , uint8_t aFlags )
2023-02-20 10:22:15 +08:00
# elif defined(USE_ONKYO_PROTOCOL)
void handleReceivedTinyIRData ( uint16_t aAddress , uint16_t aCommand , uint8_t aFlags )
2022-11-12 02:53:54 +08:00
# else
void handleReceivedTinyIRData ( uint8_t aAddress , uint8_t aCommand , uint8_t aFlags )
# endif
{
2022-01-29 17:44:14 +08:00
# if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
// Copy data for main loop, this is the recommended way for handling a callback :-)
2023-02-12 07:23:11 +08:00
# if !defined(USE_FAST_PROTOCOL)
2022-01-27 23:33:27 +08:00
sCallbackData . Address = aAddress ;
2022-11-12 02:53:54 +08:00
# endif
2022-01-27 23:33:27 +08:00
sCallbackData . Command = aCommand ;
2022-11-12 02:53:54 +08:00
sCallbackData . Flags = aFlags ;
2022-01-27 23:33:27 +08:00
sCallbackData . justWritten = true ;
# else
2022-01-29 17:44:14 +08:00
/*
2022-11-12 02:53:54 +08:00
* Printing is not allowed in ISR context for any kind of RTOS
2022-01-29 17:44:14 +08:00
* For Mbed we get a kernel panic and " Error Message: Semaphore: 0x0, Not allowed in ISR context " for Serial . print ( )
* for ESP32 we get a " Guru Meditation Error: Core 1 panic'ed " ( we also have an RTOS running ! )
*/
// Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
2023-02-12 07:23:11 +08:00
# if defined(USE_FAST_PROTOCOL)
printTinyReceiverResultMinimal ( & Serial , aCommand , aFlags ) ;
2022-11-12 02:53:54 +08:00
# else
2023-02-12 07:23:11 +08:00
printTinyReceiverResultMinimal ( & Serial , aAddress , aCommand , aFlags ) ;
2022-11-12 02:53:54 +08:00
# endif
2022-01-27 11:11:54 +08:00
# endif
2021-01-04 09:54:10 +08:00
}