2021-01-04 09:54:10 +08:00
/*
2022-11-14 22:00:43 +08:00
* TinyIR . h
2021-01-04 09:54:10 +08:00
*
*
2022-07-27 07:19:00 +08:00
* Copyright ( C ) 2021 - 2022 Armin Joachimsmeyer
2021-01-04 09:54:10 +08:00
* armin . joachimsmeyer @ gmail . com
*
2022-08-09 04:39:52 +08:00
* This file is part of IRMP https : //github.com/IRMP-org/IRMP.
2021-03-23 01:04:04 +08:00
* This file is part of Arduino - IRremote https : //github.com/Arduino-IRremote/Arduino-IRremote.
2021-01-04 09:54:10 +08:00
*
2021-03-23 01:04:04 +08:00
* TinyIRReceiver is free software : you can redistribute it and / or modify
2021-01-04 09:54:10 +08:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2022-04-05 10:47:32 +08:00
* along with this program . If not , see < http : //www.gnu.org/licenses/gpl.html>.
2021-01-04 09:54:10 +08:00
*
*/
2022-11-14 22:00:43 +08:00
# ifndef _TINY_IR_H
# define _TINY_IR_H
2021-01-20 05:27:07 +08:00
2021-01-04 09:54:10 +08:00
# include <Arduino.h>
# include "LongUnion.h"
2022-12-30 01:46:09 +08:00
/** \addtogroup TinyReceiver Minimal receiver for NEC and FAST protocol
2021-03-18 04:52:41 +08:00
* @ {
*/
2021-01-18 20:44:30 +08:00
2022-11-14 22:00:43 +08:00
# define VERSION_IRTINY "1.0.0"
# define VERSION_IRTINY_MAJOR 1
# define VERSION_IRTINY_MINOR 0
# define VERSION_IRTINY_PATCH 0
2022-11-12 02:53:54 +08:00
/**
* Timing for NEC protocol
*
* see : https : //www.sbprojects.net/knowledge/ir/nec.php
* LSB first , 1 start bit + 16 bit address + 8 bit data + 8 bit inverted data + 1 stop bit .
2021-01-04 09:54:10 +08:00
*/
# define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
# define NEC_COMMAND_BITS 16 // Command and inverted command
# define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
2022-11-14 22:00:43 +08:00
2021-01-04 09:54:10 +08:00
# define NEC_UNIT 560
# define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000
# define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500
# define NEC_BIT_MARK NEC_UNIT
# define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690
# define NEC_ZERO_SPACE NEC_UNIT
# define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250
2022-11-12 02:53:54 +08:00
2022-07-27 07:19:00 +08:00
# define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
2022-11-12 02:53:54 +08:00
# define NEC_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
# define NEC_MAXIMUM_REPEAT_DISTANCE (NEC_REPEAT_PERIOD - NEC_MINIMAL_DURATION + 10000) // 70 ms
/**
* FAST_8_BIT_CS Protocol characteristics :
2022-11-14 22:00:43 +08:00
* - Bit timing is like JVC
* - The header is shorter , 4000 vs . 12500
2022-11-12 02:53:54 +08:00
* - No address and 16 bit data , interpreted as 8 bit command and 8 bit inverted command ,
2022-11-14 22:00:43 +08:00
* leading to a fixed protocol length of ( 7 + ( 16 * 2 ) + 1 ) * 526 = 40 * 560 = 21040 microseconds or 21 ms .
2022-11-12 02:53:54 +08:00
* - Repeats are sent as complete frames but in a 50 ms period .
*/
# define FAST_8_BIT_PARITY_ADDRESS_BITS 0 // No address
# define FAST_8_BIT_PARITY_COMMAND_BITS 16 // Command and inverted command
# define FAST_8_BIT_PARITY_BITS (FAST_8_BIT_PARITY_ADDRESS_BITS + FAST_8_BIT_PARITY_COMMAND_BITS)
2022-11-14 22:00:43 +08:00
# define FAST_8_BIT_PARITY_UNIT 526 // 20 periods of 38 kHz (526.315789)
2022-11-12 02:53:54 +08:00
# define FAST_8_BIT_PARITY_BIT_MARK FAST_8_BIT_PARITY_UNIT
2022-11-14 22:00:43 +08:00
# define FAST_8_BIT_PARITY_ONE_SPACE (3 * FAST_8_BIT_PARITY_UNIT) // 1578 -> bit period = 2104
# define FAST_8_BIT_PARITY_ZERO_SPACE FAST_8_BIT_PARITY_UNIT // 526 -> bit period = 1052
2022-11-12 02:53:54 +08:00
2022-11-14 22:00:43 +08:00
# define FAST_8_BIT_PARITY_HEADER_MARK (4 * FAST_8_BIT_PARITY_UNIT) // 2104
# define FAST_8_BIT_PARITY_HEADER_SPACE (FAST_8_BIT_PARITY_ONE_SPACE) // 1578
2022-11-12 02:53:54 +08:00
# define FAST_8_BIT_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.
2022-11-14 22:00:43 +08:00
# define FAST_8_BIT_PARITY_REPEAT_DISTANCE (FAST_8_BIT_PARITY_REPEAT_PERIOD - (40 * FAST_8_BIT_PARITY_UNIT)) // 29 ms
2022-11-12 02:53:54 +08:00
# define FAST_8_BIT_PARITY_MAXIMUM_REPEAT_DISTANCE (FAST_8_BIT_PARITY_REPEAT_DISTANCE + 10000) // 47.5 ms
# if defined(USE_FAST_8_BIT_AND_PARITY_TIMING)
# define TINY_ADDRESS_BITS FAST_8_BIT_PARITY_ADDRESS_BITS
# define TINY_COMMAND_BITS FAST_8_BIT_PARITY_COMMAND_BITS
# define TINY_COMMAND_HAS_8_BIT_PARITY true
# define TINY_BITS FAST_8_BIT_PARITY_BITS
# define TINY_UNIT FAST_8_BIT_PARITY_UNIT
# define TINY_HEADER_MARK FAST_8_BIT_PARITY_HEADER_MARK
# define TINY_HEADER_SPACE FAST_8_BIT_PARITY_HEADER_SPACE
# define TINY_BIT_MARK FAST_8_BIT_PARITY_BIT_MARK
# define TINY_ONE_SPACE FAST_8_BIT_PARITY_ONE_SPACE
# define TINY_ZERO_SPACE FAST_8_BIT_PARITY_ZERO_SPACE
2022-11-14 22:00:43 +08:00
# define TINY_MAXIMUM_REPEAT_DISTANCE FAST_8_BIT_PARITY_MAXIMUM_REPEAT_DISTANCE // for repeat detection
2022-11-12 02:53:54 +08:00
# 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
# define TINY_COMMAND_BITS NEC_COMMAND_BITS // the command bits + parity
# define TINY_ADDRESS_HAS_8_BIT_PARITY true
# define TINY_COMMAND_HAS_8_BIT_PARITY true
# define TINY_BITS NEC_BITS
# define TINY_UNIT NEC_UNIT
# define TINY_HEADER_MARK NEC_HEADER_MARK
# define TINY_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_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE
# endif
/*
* This function is called if a complete command was received and must be implemented by the including file ( user code )
* 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
// 8 bit address here
# if TINY_COMMAND_HAS_8_BIT_PARITY
extern void handleReceivedTinyIRData ( uint8_t aAddress , uint8_t aCommand , uint8_t aFlags ) ;
# else
extern void handleReceivedTinyIRData ( uint8_t aAddress , uint16_t aCommand , uint8_t aFlags ) ;
# endif
# else // TINY_ADDRESS_HAS_8_BIT_PARITY
// 16 bit address here
# if TINY_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 ) ;
# endif
# endif
# else
// No address here
# if TINY_COMMAND_HAS_8_BIT_PARITY
extern void handleReceivedTinyIRData ( uint8_t aCommand , uint8_t aFlags ) ;
# else
extern void handleReceivedTinyIRData ( uint16_t aCommand , uint8_t aFlags ) ;
# endif
# endif
# if !defined(MICROS_IN_ONE_SECOND)
# define MICROS_IN_ONE_SECOND 1000000L
# endif
# if !defined(MICROS_IN_ONE_MILLI)
# define MICROS_IN_ONE_MILLI 1000L
# endif
2021-01-04 09:54:10 +08:00
/*
* Macros for comparing timing values
*/
# define lowerValue25Percent(aDuration) (aDuration - (aDuration / 4))
# define upperValue25Percent(aDuration) (aDuration + (aDuration / 4))
2022-06-09 03:23:20 +08:00
# define lowerValue50Percent(aDuration) (aDuration / 2) // (aDuration - (aDuration / 2))
# define upperValue50Percent(aDuration) (aDuration + (aDuration / 2))
2021-01-04 09:54:10 +08:00
/*
* The states for the state machine
*/
# define IR_RECEIVER_STATE_WAITING_FOR_START_MARK 0
# define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE 1
# define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK 2
# define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE 3
# define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4
# define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5
2021-03-18 04:52:41 +08:00
/**
* Control and data variables of the state machine for TinyReceiver
2021-01-04 09:54:10 +08:00
*/
2021-01-05 00:15:03 +08:00
struct TinyIRReceiverStruct {
2021-01-04 09:54:10 +08:00
/*
* State machine
*/
2022-08-06 20:39:28 +08:00
uint32_t LastChangeMicros ; ///< Microseconds of last Pin Change Interrupt.
uint8_t IRReceiverState ; ///< The state of the state machine.
uint8_t IRRawDataBitCounter ; ///< How many bits are currently contained in raw data.
2021-01-04 09:54:10 +08:00
/*
* Data
*/
2022-11-12 02:53:54 +08:00
# if (TINY_BITS > 16)
2022-08-06 20:39:28 +08:00
uint32_t IRRawDataMask ; ///< The corresponding bit mask for IRRawDataBitCounter.
LongUnion IRRawData ; ///< The current raw data. LongUnion helps with decoding of address and command.
2022-11-12 02:53:54 +08:00
# else
uint16_t IRRawDataMask ; ///< The corresponding bit mask for IRRawDataBitCounter.
WordUnion IRRawData ; ///< The current raw data. WordUnion helps with decoding of command.
2022-07-27 07:19:00 +08:00
# endif
2022-11-12 02:53:54 +08:00
uint8_t Flags ; ///< One of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT, and IRDATA_FLAGS_PARITY_FAILED
2021-01-04 09:54:10 +08:00
} ;
2022-11-12 02:53:54 +08:00
/*
* Definitions for member TinyIRReceiverCallbackDataStruct . Flags
* From IRremoteInt . h
*/
# define IRDATA_FLAGS_EMPTY 0x00
# define IRDATA_FLAGS_IS_REPEAT 0x01
# define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 // not used here, overwritten with _IRDATA_FLAGS_IS_SHORT_REPEAT
# define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check
2022-08-06 20:39:28 +08:00
/**
* Can be used by the callback to transfer received data to main loop for further processing .
2022-01-27 23:33:27 +08:00
* E . g . with volatile struct TinyIRReceiverCallbackDataStruct sCallbackData ;
*/
struct TinyIRReceiverCallbackDataStruct {
2022-11-12 02:53:54 +08:00
# if (TINY_ADDRESS_BITS > 0)
# if (TINY_ADDRESS_BITS == 16) && !TINY_ADDRESS_HAS_8_BIT_PARITY
2022-01-27 23:33:27 +08:00
uint16_t Address ;
2022-11-12 02:53:54 +08:00
# else
uint8_t Address ;
# endif
# endif
# if (TINY_COMMAND_BITS == 16) && !TINY_COMMAND_HAS_8_BIT_PARITY
uint16_t Command ;
# else
2022-01-27 23:33:27 +08:00
uint8_t Command ;
2022-11-12 02:53:54 +08:00
# endif
uint8_t Flags ; // Bit coded flags. Can contain one of the bits: IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED
bool justWritten ; ///< Is set true if new data is available. Used by the main loop, to avoid multiple evaluations of the same IR frame.
2022-01-27 23:33:27 +08:00
} ;
2022-07-30 16:26:04 +08:00
bool initPCIInterruptForTinyReceiver ( ) ;
bool enablePCIInterruptForTinyReceiver ( ) ;
2021-08-08 03:25:44 +08:00
void disablePCIInterruptForTinyReceiver ( ) ;
2021-10-07 15:25:36 +08:00
bool isTinyReceiverIdle ( ) ;
2022-11-12 02:53:54 +08:00
# if defined(USE_FAST_8_BIT_AND_PARITY_TIMING)
void printTinyReceiverResultMinimal ( uint16_t aCommand , uint8_t aFlags , Print * aSerial ) ;
# else
void printTinyReceiverResultMinimal ( uint8_t aAddress , uint8_t aCommand , uint8_t aFlags , Print * aSerial ) ;
# endif
void sendFast8BitAndParity ( uint8_t aSendPin , uint8_t aCommand , uint_fast8_t aNumberOfRepeats = 0 ) ;
2022-11-14 22:00:43 +08:00
void sendNECMinimal ( uint8_t aSendPin , uint8_t aCommand , uint_fast8_t aNumberOfRepeats = 0 ) ;
2021-03-18 04:52:41 +08:00
/** @}*/
2022-11-14 22:00:43 +08:00
# endif // _TINY_IR_H