diff --git a/README.md b/README.md
index 7acdafa..83dbc98 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,92 @@
# IRsmallDecoder
-## A small, fast and reliable infrared signals decoder to control Arduino projects with remotes.
+## A small, fast and reliable infrared signals decoder, for controlling Arduino projects with remote controls.
+
This is a Library for receiving and decoding IR signals from remote controls. Perfect for your Arduino projects that need a fast, simple and reliable decoder, but don't require the usage of multiple different protocols at the same time and don't need to send IR signals.
## Table of Contents
-* [Main features](#main-features)
-* [Supported Protocols](#supported-protocols)
-* [Supported Boards](#supported-boards)
-* [Connecting the IR sensor](#connecting-the-ir-sensor)
-* [Installing the library](#installing-the-library)
-* [Using the library](#using-the-library)
-* [Possible improvements](#possible-improvements)
-* [Contributions](#contributions)
-* [Contact information](#contact-information)
-* [License](#license)
-* [Appendix A - Details about this library](#appendix-a---details-about-this-library)
-* [Appendix B - IR sensor connection details](#appendix-b---ir-sensor-connection-details)
+- [Main features](#main-features)
+- [Supported protocols](#supported-protocols)
+- [Supported boards](#supported-boards)
+- [Connecting the IR receiver](#connecting-the-ir-receiver)
+- [Installing the library](#installing-the-library)
+- [Using the library](#using-the-library)
+ - [A full example](#a-full-example)
+ - [Address check](#address-check)
+ - [The multifunctional *dataAvailable()* method](#the-multifunctional-dataavailable-method)
+ - [Disabling the decoder](#disabling-the-decoder)
+ - [Protocol data structures](#protocol-data-structures)
+ - [Notes](#notes)
+- [Possible improvements](#possible-improvements)
+- [Contributions](#contributions)
+- [Contact information](#contact-information)
+- [License](#license)
+- [Appendix A - Details about this library](#appendix-a---details-about-this-library)
+- [Appendix B - IR receiver connection details](#appendix-b---ir-receiver-connection-details)
## Main features
-* It fully decodes the signals and separates the data;
-* It ignores unwanted initial repetition codes;
-* It offers an easier way to handle held keys;
-* Very loose signal tolerances;
-* It uses error detection (when possible);
-* Low SRAM and Flash memory usage;
-* The decoding is done asynchronously, no timers required, so you can use them for other things;
-* No conflicts with timer-related functionalities such as tone(), servos, analogWrite(), etc.;
-* It uses one hardware (external) interrupt;
-* No hardware specific instructions are used.
-
-
-## Supported Protocols
-* NEC
-* NECx
-* Philips RC5 and RC5x (simultaneously)
-* Sony SIRC 12, 15 and 20 bits (individually or simultaneously)
-* SAMSUNG old standard
-* SAMSUNG 32 bits (16 of which are for error detection)
-
-
-## Supported Boards
+- The signals are fully decoded and the data is divided into separate variables;
+- The initial repetition codes are ignored, effectively reducing the possibility of getting several codes when we just want one;
+- Held Keys (or buttons) are detected and processed in a more useful way;
+- The signal's tolerances are very loose, allowing a high detection rate without compromising the reliability;
+- The signal's redundant data is only used for error detection (if the protocol has it);
+- SRAM and Flash memory usage is very low;
+- The decoding is done asynchronously, no timers required, so you can use them for other things;
+- No conflicts with timer-related functionalities such as *tone()*, servos, *analogWrite()*, etc.;
+- The signal acquisition and processing is done by a hardware (external) interrupt;
+- This library is compatible with a wide range of the Arduino boards.
+
+
+## Supported protocols
+- NEC
+- NECx
+- Philips RC5 and RC5x (simultaneously)
+- Sony SIRC 12, 15 and 20 bits (individually or simultaneously)
+- SAMSUNG old standard
+- SAMSUNG 32 bits (16 of which are for error detection)
+
+
+## Supported boards
Because no hardware specific instructions are used, it probably works on all Arduino boards (and possibly others, I'm not quite sure, I've only tested it thoroughly on an Arduino Uno and a Mega).
ATtiny 25/45/85/24/44/84 microcontrollers are supported.
-If you have problems with this library on some board, please submit an issue here: https://github.com/LuisMiCa/IRSmallDecoder/issues or [contact me](#contact-information).
+If you have problems with this library on some board, please submit an issue [here](https://github.com/LuisMiCa/IRSmallDecoder/issues) or [contact me](#contact-information).
+
+## Connecting the IR receiver
+The receiver's output must be connected to one of the Arduino's digital pin that is usable for interrupts and it also must work with the CHANGE mode if the intended protocol uses that mode. One example of a board that does not have CHANGE mode on some of the interrupt pins is the Arduino 101 and one protocol that uses that mode is the RC5 (you can find the modes [here](#speed)).
-## Connecting the IR sensor
-The sensor's output must be connected to one of the Arduino's digital pin that is usable for interrupts and, also, it must work with the CHANGE mode if the intended protocol uses this mode. (One example of a board that does not have CHANGE mode on some of the interrupt pins is the Arduino 101; and one protocol that uses that mode is the [RC5](#speed)).
+The following table (adapted from the [Arduino Reference](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/)) contains the digital pins that can be use to connect the IR receiver to the Arduino board:
-| Board or microcontroller | Usable digital pins numbers |
-|-------------------------------------|--------------------------------|
-| Uno, Nano, Mini, other 328-based | 2, 3 |
-| Uno WiFi Rev.2 | all digital pins |
-| Mega, Mega2560, MegaADK | 2, 3, 18, 19, 20, 21 |
-| Micro, Leonardo, other 32u4-based | 0, 1, 2, 3, 7 |
-| Zero | all digital pins, except 4 |
-| MKR Family boards | 0, 1, 4, 5, 6, 7, 8, 9, A1, A2 |
-| Due | all digital pins |
-| 101 with CHANGE mode | 2, 5, 7, 8, 10, 11, 12, 13 |
-| 101 with other modes | all digital pins |
-| ATtiny 25/45/85 | 2* |
-| ATtiny 24/44/84 | 8* |
+
-[*] - Assuming you're using _damellis' ATtiny core_ (high-low tech) or _SpenceKonde's ATtinyCore_. (Other cores may have different pin assignments).
+| Board or microcontroller | Digital pins usable for interrupts|
+|-------------------------------------|-----------------------------------|
+| Uno, Nano, Mini, other 328-based | 2, 3 |
+| Uno WiFi Rev.2, Nano Every | all digital pins |
+| Mega, Mega2560, MegaADK | 2, 3, 18, 19, 20, 21\* |
+| Micro, Leonardo, other 32u4-based | 0, 1, 2, 3, 7 |
+| Zero | all digital pins, except 4 |
+| MKR Family boards | 0, 1, 4, 5, 6, 7, 8, 9, A1, A2 |
+| Nano 33 IoT | 2, 3, 9, 10, 11, 13, A1, A5, A7 |
+| Nano 33 BLE, Nano 33 BLE Sense | all pins |
+| Due | all digital pins |
+| 101 with CHANGE mode | 2, 5, 7, 8, 10, 11, 12, 13 |
+| 101 with other modes | all digital pins |
+| ATtiny 25/45/85 | 2\*\* |
+| ATtiny 24/44/84 | 8\*\* |
+
-(Sources: ; and )
+> [\*] - In the Mega family, pins 20 & 21 are not available to use for interrupts while they are used for I2C communication.
+> [\*\*] - Assuming you're using
+ [damellis' ATtiny core](https://github.com/damellis/attiny) or
+ [SpenceKonde's ATTinyCore](https://github.com/SpenceKonde/ATTinyCore).
+ Other cores may have different pin assignments.
-If you're not sure about how to connect the IR Sensor to the Arduino, go to: [IR sensor connection details](#appendix-b---ir-sensor-connection-details) at the end of this document.
+If you're not sure about how to connect the IR receiver to the Arduino, go to: [IR receiver connection details](#appendix-b---ir-receiver-connection-details) at the end of this document.
## Installing the library
@@ -105,10 +121,11 @@ before the
#include
```
-Then you need to create **one** decoder object with the correct interrupt pin:
+Then you need to create **one** decoder object with the correct digital pin:
```ino
-IRsmallDecoder irDecoder(2); //IR sensor connected to pin 2 in this example
+IRsmallDecoder irDecoder(2); //IR receiver connected to pin 2 in this example
```
+
And also a decoder data structure:
```ino
@@ -147,22 +164,62 @@ void loop() {
Serial.println(irData.cmd,HEX);
}
}
+```
+
+### Address check
+if you are using multiple remotes, with different addresses, in the vicinity of your project, you should also verify the address. You can do something like this:
+
+```ino
+if (irData.addr == theRightAddr) {
+ switch (irData.cmd) {
+ case someCmd:
+ // do something here
+ break;
+ case someOtherCmd:
+ // do some other things
+ break;
+ //etc.
+ }
+}
```
+
+
+### The multifunctional *dataAvailable()* method
+The ```dataAvailable(irData)``` method combines the functionalities of 3 "fictitious" functions: *isDataAvailable()*, *getData()* and *setDataUnavailable()*. If there is some data available, already decoded, when ```irDecoder.dataAvailable(irData)``` is called:
+- The data is copied to the selected data structure ```irData```;
+- The original data is marked as unavailable;
+- And, finally, it returns true.
+
+If there's no new data, it just returns false.
+
+**Note**: this library does not use data buffering, if a new signal is received before the available data is retrieved, that previous data is discarded. This may happen if the loop takes to long to check for new data. So, if you want to use repetition codes, try to keep the loop duration below 100ms (for NEC and RC5) and don't use delays. They don't interfere with the decoding, but I don't recommend their usage.
+
+If you want to check if any key was pressed and don't care about the data, you can use the ```dataAvailable()``` method without any parameters. Keep in mind that, if there's new data available, this method will discard that data, before returning true. The [ToggleLED](https://github.com/LuisMiCa/IRsmallDecoder/blob/master/examples/ToggleLED/ToggleLED.ino) example demonstrates this functionality.
+
+
+### Disabling the decoder
+If you don't want to receive IR codes when they are not needed or if you want to prevent possible interferences in time critical functions by the decoders' interrupts, you can use the ```disable()``` and ```enable()``` methods. The [TemporaryDisable](https://github.com/LuisMiCa/IRsmallDecoder/blob/master/examples/ToggleLED/TemporaryDisable.ino) example demonstrates a possible usage for these methods.
+
+The ```enable()``` method also resets the decoder after reenabling it. This is useful if you have to temporarily disable all interrupts or need to use a library that does that. If you don't reset the decoder after re-enabling all interrupts, the next IR signal may not be recognized if the IR receiver detected some signal while the interrupts where disabled.
+
### Protocol data structures
-The protocol data structure is not the same for all protocols, but they all have two things in common:
+The protocol data structure is not the same for all protocols, but they all have two member variables in common:
- **cmd** - the button command code (one byte);
-- **addr** - the address code (usually the same for most of the buttons on one single remote).
+- **addr** - the address code (usually the same for all buttons on one single remote).
-Most of the decoders have the **keyHeld** variable, which is set to _true_ when a button is being held.
-The SIRC protocol has the **ext** variable which holds extended data.
+Most of the decoders have the **keyHeld** variable (which is set to *true* when a button is being held) and two of the SIRC decoders have the **ext** variable (see [notes](#notes) for more details);
The following table shows the number of bits used by each protocol and the datatypes of the data structure member variables:
+
+
+
+
| Protocol | keyHeld | cmd | addr | ext |
-|-----------|:-------:|:----------:|:-----------:|:----------:|
+|:----------|:-------:|:----------:|:-----------:|:----------:|
| NEC | bool | 8/uint8_t | 8/uint8_t | -- |
| NECx | bool | 8/uint8_t | 16/uint16_t | -- |
| RC5 | bool | 7/uint8_t | 5/uint8_t | -- |
@@ -172,39 +229,40 @@ The following table shows the number of bits used by each protocol and the datat
| SIRC | bool | 7/uint8_t | 8/uint8_t | 8/uint8_t |
| SAMSUNG | bool | 8/uint8_t | 12/uint16_t | -- |
| SAMSUNG32 | bool | 8/uint8_t | 8/uint8_t | -- |
+
### Notes
- Only one protocol can be compiled at a time, however:
- - NECx also decodes NEC, but without the address error check;
- - The RC5 implementation also decodes the extended protocol version, which as a field bit that is used as an extra command bit (making a total of 7 bits);
- - SIRC handles 12, 15 and 20 bits at the same time, by taking advantage of the fact that most Sony remotes send three signal frames each time one button is pressed. It uses triple frame verification, checks if a key was held and adds a delay to prevent unwanted keyHeld codes;
- - SIRC12, SIRC15 and SIRC20 use a basic (smaller and faster) implementation, without the triple frame verification and without the keyHeld check;
-
-- If there is some data available, when ```irDecoder.dataAvailable(irData)``` is called: that data is copied to the selected data structure; it marks the received data as unavailable and then returns true.
-
-- If a new signal is received before the available data is retrieved, that previous data is discarded. This may happen if the loop takes to long to recheck if there's new data available, especially if delays are used. (They do not interfere with the decoding but I wouldn't recommended their use).
+ - NECx also decodes NEC, but the address will have redundant data;
+ - The RC5 implementation also decodes the extended protocol version, which has a field bit that is used as an extra command bit (making a total of 7 bits);
+ - SIRC12 will detect signals from SIRC15 and SIRC20, but the codes will not be correct;
+ - Similarly, SIRC15 will also detect signals from SIRC20, but not from SIRC12.
+- SIRC handles 12, 15 and 20 bits at the same time, by taking advantage of the fact that most Sony remotes send three signal frames each time one button is pressed. It uses triple frame verification, checks if a key was held and ignores the initial repetition codes.
+- SIRC12, SIRC15 and SIRC20 use a basic (smaller and faster) implementation, without the triple frame verification and without the **keyHeld** check.
+- The SIRC20 protocol has the **ext** variable which holds extended data.
+- The SIRC decoder also has the **ext** variable, but it's only used when a 20-bit code is detected, otherwise it's set to 0.
## Possible improvements
-- More protocols! That's obvious;
-- Support for more "non-standard" boards;
+- I might add a few more IR protocols to this library (there are a lot of them out there);
- The keyHeld initial delay is hard-coded, I could make it configurable (in constructor) or even changeable (with method);
-- I could add methods to disable/re-enable the decoder, to temporarily allow the usage of other time critical interruptions (or to simply disable it when not needed);
-- The _dataAvailable(irData)_ method could be overloaded with a version without irData;
-- For now, it's not easy for anyone to add other protocols;
-- I believe it may be possible to increase the number of usable pins, by using NicoHood's PinChangeInterrupt Library.
-- SIRC12, SIRC15 and SIRC20 do not have the keyHeld feature. SIRC fills that gap but requires 3 frames for each keypress.
+- I believe it may be possible to increase the number of usable pins, by using NicoHood's PinChangeInterrupt Library;
+- SIRC12, SIRC15 and SIRC20 do not have the keyHeld feature. SIRC fills that gap, but requires 3 signal frames for each keypress;
+- The SIRC decoder could also return the number of detected bits (12, 15 or 20).
+- I have not finished redrawing the IR signals' graphs that would better explain the protocols' timings.
+
+
## Contributions
-The first release was made without any contribution from other developers, but I do have to say that this work was inspired by some of the existing IR Arduino Libraries:
-[Arduino-IRremote](https://github.com/z3t0/Arduino-IRremote),
-[IRLib2](https://github.com/cyborg5/IRLib2),
-[IRReadOnlyRemote](https://github.com/otryti/IRReadOnlyRemote),
-[Infrared4Arduino](https://github.com/bengtmartensson/Infrared4Arduino),
-and especially the [IRLremote](https://github.com/NicoHood/IRLremote), which was almost what I was looking for, but not quite... so I decided to make my own NEC decoder and then an RC5 and a SIRC, practically from scratch. Finally I decided to put these decoders in a library, hoping that it will be useful to someone.
-Possible future contributions will be mentioned here if they are significant.
+So far, these releases were made without any significant contribution from other developers, but I do have to say that this work was inspired by some of the existing IR Libraries: [Arduino-IRremote][1], [IRLib2][2], [IRReadOnlyRemote][3], [Infrared4Arduino][4] and especially the [IRLremote][5], which was almost what I was looking for, but not quite... So I decided to make my own NEC decoder and then an RC5 and a SIRC. Finally I decided to put these decoders in a library, hoping that it will be useful to someone.
+
+[1]:
+[2]:
+[3]:
+[4]:
+[5]:
## Contact information
@@ -216,43 +274,48 @@ Copyright (c) 2020 Luis Carvalho
This library is licensed under the MIT license.
See the LICENSE file for details.
-
---
+
## Appendix A - Details about this library
+
### Size
The size of this library is, as the name implies, small (about 900 bytes on average, for the Arduino UNO board) and the memory usage is also reduced (around 30 bytes). Keep in mind that these values vary depending on the selected protocol and the board used.
**Program memory and static data used (in SRAM) on an Arduino UNO (in bytes):**
+
+
| Protocol | Program memory | Static data |
|-----------|:--------------:|:-----------:|
-| NEC | 858 | 28 |
-| NECx | 854 | 30 |
-| RC5 | 1062 | 31 |
-| SIRC12 | 706 | 22 |
-| SIRC15 | 682 | 22 |
-| SIRC20 | 764 | 26 |
-| SIRC | 1262 | 37 |
-| SAMSUNG | 880 | 29 |
-| SAMSUNG32 | 852 | 29 |
-
-To keep track of the sizes of this library, I used the ToggleLED example as a reference to determine the actual sizes, by compiling a version without the IRsmallDecoder and comparing it to the full version, for each of the supported protocols.
-
-
+| NEC | 862 | 29 |
+| NECx | 858 | 31 |
+| RC5 | 1066 | 32 |
+| SIRC12 | 710 | 23 |
+| SIRC15 | 686 | 23 |
+| SIRC20 | 768 | 27 |
+| SIRC | 1266 | 38 |
+| SAMSUNG | 884 | 30 |
+| SAMSUNG32 | 856 | 30 |
+
+
+
+To keep track of the sizes of this library, I used a sketch, similar to the ToggleLED example, with and without the library. By compiling each of the supported protocols and comparing their sizes with the reference sketch we get the memory used by the library.
+
+
-```c++
+```ino
#define IR_SMALLD_NEC
#include
IRsmallDecoder irDecoder(2);
@@ -292,8 +355,8 @@ void loop() {
}
// On Arduino UNO, with NEC protocol,
-// Sketch uses 1624 bytes
-// Global variables use 39 bytes
+// Sketch uses 1628 bytes
+// Global variables use 40 bytes
```
@@ -302,11 +365,11 @@ void loop() {
### Speed
-Despite the fact that my main goals were functionality and small size, I believe this library is reasonably fast. I haven't compared it to other libraries, (its not easy to do so) but I did manage to compare the speed of the different protocols I've implemented so far:
+Although my main goals are functionality and small size, I believe this library is reasonably fast. I haven't compared it to other libraries (it's not easy to do so), but I was able to compare the speed of the different protocols that I've implemented so far:
**Protocol Speed comparisons:**
-
+
Protocol
@@ -321,16 +384,16 @@ Despite the fact that my main goals were functionality and small size, I believe
NEC
FALLING
-
11.9 µs
-
14 µs
+
11.4 µs
+
13 µs
34
67.5ms
NECx
FALLING
-
11.4 µs
-
14 µs
+
10.9 µs
+
13 µs
34
67.5ms
@@ -345,7 +408,7 @@ Despite the fact that my main goals were functionality and small size, I believe
SIRC12
RISING
-
11.0 µs
+
10.3 µs
13 µs
3*13
3*(17.4 to 24.6)ms
@@ -353,7 +416,7 @@ Despite the fact that my main goals were functionality and small size, I believe
SIRC15
RISING
-
10.9 µs
+
10.5 µs
12 µs
3*16
3*(21 to 30)ms
@@ -388,41 +451,37 @@ Despite the fact that my main goals were functionality and small size, I believe
11.0 µs
14 µs
34
-
54.6 to 72.6
+
(54.6 to 72.6)ms
Notes:
-- Signal Duration is the effective signal duration, not the signal period.
+- Signal Duration is the effective signal duration, not the signal period;
- Tested on an Arduino Uno @ 16MHz;
-- To get the number of the clock cycles used by an interruption, multiply the time (in μs) by 16;
-- The decoding is partially done while the signal is being received. When one signal is fully received, the final stage of the decoding is executed and that's when the interruption takes more time to run.
-
-
-### Asynchronous?
-The decoding is done asynchronously, meaning it does not rely on a timer to receive and process the signals. but it still uses a hardware interrupt to drive the Finite State Machines that perform the decoding. Actually, they are Statechart Machines (David Harel type) working in asynchronous mode.
-
-Most of the protocols' Statechart Machines are implemented using _switch cases_, but I also use the "labels as values" GCC extension (AKA "computed gotos") to implement some of the more complex machines. It's not a C++ standard but it should work with all IDEs that use the GCC (like Arduino IDE).
-
-If you have problems compiling any of the protocols that use the "labels as values" extension, please submit an issue here: or [contact me](#contact-information).
+- To get the number of the clock cycles used by an interrupt, multiply the time (in μs) by 16;
+- The decoding is done partially while the signal is being received. When a signal is fully received, the final stage of the decoding is executed and that's when the interrupt takes more time to run.
### Unwanted initial repetition codes
-Remote control keys do not "bounce", but the remotes do tend to send more codes than we wish for, when we press a button. That's because, after a very short interval, they start to send repeat codes. To avoid those unwanted initial repetitions, this library ignores a few of those repetition codes before confirming that the button is really being held.
+Remote control keys do not "bounce", but the remotes do tend to send more codes than we wish for when we press a button. That's because, after a very short interval, they start sending repeat codes. To avoid those unwanted initial repetitions, this library ignores a few of those repetition codes before confirming that the button is actually being held.
### Data separation
-The data sent by the remotes is decoded according to the protocols' specifications and separated into different variables. In most remotes only the 8 bit command matters, so you don't have to work with 16 or 32 bit codes, reducing code size and memory usage.
+The data sent by the remotes is decoded according to the protocols' specifications and separated into different variables. On most remotes only the 8-bit command matters, so you don't have to work with 16-bit or 32-bit codes, reducing code size and memory usage.
### Simplicity
-As you've probably seen above, or if you've tried out any of the "Hello..." examples, this library is very simple to use and it's not full of rarely needed features. That's what makes it small and why it uses very few resources. Additional features may be included in the future, but only if they are requested and do not affect the size and/or speed significantly.
+As you've probably seen above, or if you've already tried one of the "Hello..." examples, this library is very simple to use and it's not full of rarely needed features. That's what makes it small and why it uses few resources. Additional features may be added in the future, but only if requested and do not significantly affect the size and/or speed.
### How it works
-I can't say that it's simple to understand how the decoders work, some of the Statechart Machines I've designed turned out to be a bit convoluted. But if you still would like to take a look at the statechart diagrams, they can be found here . Please note that they may not be an exact representation of what I've effectively implemented, but they are a good starting point.
+The decoding is done asynchronously, which means that it doesn't rely on a timer to receive and process signals, but it uses a hardware interrupt to drive the Finite State Machines that perform the decoding. In fact, they are Statechart Machines (David Harel type) working in a asynchronous mode.
+
+Most of the protocols' Statechart Machines are implemented using *switch cases*, but I also use the "labels as values" GCC extension (AKA "computed gotos") to implement some of the more complex statecharts. It's not a C++ standard but it should work with all IDEs that use the GCC (like Arduino IDE). If you have problems compiling any of the protocols that use the "labels as values" extension, please submit an issue [here](https://github.com/LuisMiCa/IRsmallDecoder/issues) or [contact me](#contact-information).
+
+I can't say that it's easy to understand how these decoders work, some of the Statechart Machines I designed turned out to be a bit tricky. But if you still want to take a look at the statechart diagrams, they can be found [here](https://github.com/LuisMiCa/IRsmallDecoder/tree/master/extras/Statecharts). Note that they may not be an exact representation of what I actually implemented, but they are a good starting point.
### No hardware specific instructions
@@ -432,42 +491,44 @@ In order to make this library compatible with most of the Arduino boards, I didn
---
-## Appendix B - IR sensor connection details
-If you are using a simple IR Receiver module the pinout order will be, most likely, `Vout Gnd Vcc` like in the the following examples:
+## Appendix B - IR receiver connection details
-| ![](extras/IRsensors/PIC12043S.jpg) | ![](extras/IRsensors/TSOP48xx.jpg) |
-|-------------------------------------|------------------------------------|
+If you are using a simple IR receiver module, the pinout order will most likely be ```Out Gnd Vcc```, as in the following examples:
-But beware, there are other IR Receivers with different pinouts, like these examples:
+
+
The connection to the Arduino is very straightforward, just connect:
-- OUT (or DAT or S) to one of the Arduino's digital pin that has interrupt capability[1];
-- VCC to the Arduino's +5V or (+3.3V if you are using a board with lower operating voltage[2]);
+- OUT (or DAT or S) to one of the Arduino's digital pin that has interrupt capability\[1];
+- VCC to the Arduino's +5V or (+3.3V if you are using a board with a lower operating voltage\[2]);
- GND to one of the Arduino's Ground connector.
- [1] Go to [Connecting the IR sensor](#connecting-the-ir-sensor) for more information.
- [2] Note that not all IR Sensors can operate at low voltages.
+ > 1. Go to [Connecting the IR receiver](#connecting-the-ir-receiver) for more information.
+ > 2. Keep in mind that not all IR receivers can operate at low voltages.
-Nearly all IR Sensor's datashets recommend the usage of an RC filter (R1, C1) at the power input, but it's not really necessary, (it's meant to suppress power supply disturbances):
-
-![](extras/IRsensors/IR%20Receiver%20Connections.jpg)
+Nearly all IR receiver's datasheets recommend the usage of an RC filter (R1, C1) at the power input, but it's not absolutely necessary, (it's meant to suppress power supply disturbances):
-Note that most IR Receiver Test Modules already have that RC filter.
+
+Note that most IR receiver test modules already have that RC filter.
diff --git a/changelog.txt b/changelog.txt
index 1c04913..ec5e248 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,24 +1,37 @@
IRsmallDecoder
==============
-Release 1.1.0 - 08/02/2020
---------------------------
+v1.2.0 (2022-01-16)
+-------------------
+ * Added the dataAvailable() overload method
+ * Added methods to enable/disable the decoder
+ * Added an example for the enable/disable methods
+ * Fixed the possibility of needlessly dismissed codes (issue #5)
+ * Improved the NEC/NECx and SIRC12/15 decoders (small improvement)
+ * Improved some of the examples
+ * Formatted the code in a more normalized way
+ * Corrected and added code comments
+ * Corrected and updated the documentation
+
+
+v1.1.0 (2020-02-08)
+-------------------
* Added SAMSUNG protocol (old standard)
* Added SAMSUNG32 protocol
* Added Samsung example sketch
* Added support for ATtiny 24/44/84/25/45/85
-Release 1.0.0 - 24/01/2020
---------------------------
+v1.0.0 (2020-01-24)
+-------------------
This is the first public release
Main features:
- * NEC, RC5 and SIRC protocols are supported;
- * IR Codes' data is separated;
- * Unwanted initial repetitions are ignored;
- * Held keys signalization is standardized;
- * Signal tolerances are very loose;
- * SRAM and Flash memory usage is low;
- * No timers required;
- * Uses one hardware interrupt.
\ No newline at end of file
+ * NEC, RC5 and SIRC protocols are supported
+ * IR Codes' data is separated
+ * Unwanted initial repetitions are ignored
+ * Held keys are signalized by a boolean variable
+ * Signal tolerances are very loose
+ * SRAM and Flash memory usage is low
+ * No timers required
+ * Uses one hardware interrupt
\ No newline at end of file
diff --git a/examples/HelloNEC/HelloNEC.ino b/examples/HelloNEC/HelloNEC.ino
index c2d07e9..eb598a1 100644
--- a/examples/HelloNEC/HelloNEC.ino
+++ b/examples/HelloNEC/HelloNEC.ino
@@ -3,18 +3,20 @@
*
* Note: for the NEC extended protocol, just define IR_SMALLD_NECx instead of IR_SMALLD_NEC
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
+ * In this example it's assumed that the IR receiver is connected to digital pin 2 and
* the pin is usable for external interrupts.
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
*/
-
-#define IR_SMALLD_NEC //1st: define which protocol to use and then,
-#include //2nd: include the library;
-IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
-irSmallD_t irData; //4th: declare one decoder data structure;
-
+
+#define IR_SMALLD_NEC //1st: define which protocol to use and then,
+//#define IR_SMALLD_NECx
+#include //2nd: include the library;
+IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
+irSmallD_t irData; //4th: declare one decoder data structure;
+
void setup() {
Serial.begin(250000);
Serial.println("Waiting for a NEC remote control IR signal...");
@@ -22,12 +24,11 @@ void setup() {
}
void loop() {
- if(irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
- Serial.print(irData.keyHeld,HEX); //6th: do something with the data.
+ if (irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
+ Serial.print(irData.keyHeld, HEX); //6th: do something with the data.
Serial.print("\t ");
- Serial.print(irData.addr,HEX);
+ Serial.print(irData.addr, HEX);
Serial.print("\t ");
- Serial.println(irData.cmd,HEX);
+ Serial.println(irData.cmd, HEX);
}
-}
-
+}
\ No newline at end of file
diff --git a/examples/HelloRC5/HelloRC5.ino b/examples/HelloRC5/HelloRC5.ino
index e40ead3..6485d52 100644
--- a/examples/HelloRC5/HelloRC5.ino
+++ b/examples/HelloRC5/HelloRC5.ino
@@ -3,18 +3,19 @@
*
* Note: this works for both RC5 and RC5 extended.
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
+ * In this example it's assumed that the IR receiver is connected to digital pin 2 and
* the pin is usable for external interrupts (that work with the CHANGE mode).
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
*/
-#define IR_SMALLD_RC5 //1st: define which protocol to use and then,
-#include //2nd: include the library;
-IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
-irSmallD_t irData; //4th: declare one decoder data structure;
-
+#define IR_SMALLD_RC5 //1st: define which protocol to use and then,
+#include //2nd: include the library;
+IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
+irSmallD_t irData; //4th: declare one decoder data structure;
+
void setup() {
Serial.begin(250000);
Serial.println("Waiting for a RC5 remote control IR signal...");
@@ -22,11 +23,11 @@ void setup() {
}
void loop() {
- if(irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
- Serial.print(irData.keyHeld,HEX); //6th: do something with the data.
+ if (irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
+ Serial.print(irData.keyHeld, HEX); //6th: do something with the data.
Serial.print("\t ");
- Serial.print(irData.addr,HEX);
+ Serial.print(irData.addr, HEX);
Serial.print("\t ");
- Serial.println(irData.cmd,HEX);
+ Serial.println(irData.cmd, HEX);
}
}
\ No newline at end of file
diff --git a/examples/HelloSAMSUNG/HelloSAMSUNG.ino b/examples/HelloSAMSUNG/HelloSAMSUNG.ino
index c52d74e..1d78ab0 100644
--- a/examples/HelloSAMSUNG/HelloSAMSUNG.ino
+++ b/examples/HelloSAMSUNG/HelloSAMSUNG.ino
@@ -8,18 +8,19 @@
* - The SAMSUNG32 protocol corresponds to the standard described in this application note:
* http://elektrolab.wz.cz/katalog/samsung_protocol.pdf
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
+ * In this example it's assumed that the IR receiver is connected to digital pin 2 and
* the pin is usable for external interrupts.
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
*/
-
-#define IR_SMALLD_SAMSUNG //1st: define which protocol to use and then,
-#include //2nd: include the library;
-IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct interrupt pin;
-irSmallD_t irData; //4th: declare one decoder data structure;
-
+
+#define IR_SMALLD_SAMSUNG //1st: define which protocol to use and then,
+#include //2nd: include the library;
+IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct interrupt pin;
+irSmallD_t irData; //4th: declare one decoder data structure;
+
void setup() {
Serial.begin(250000);
Serial.println("Waiting for a SAMSUNG remote control IR signal...");
@@ -27,11 +28,11 @@ void setup() {
}
void loop() {
- if(irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
- Serial.print(irData.keyHeld,HEX); //6th: do something with the data.
+ if (irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
+ Serial.print(irData.keyHeld, HEX); //6th: do something with the data.
Serial.print("\t ");
- Serial.print(irData.addr,HEX);
+ Serial.print(irData.addr, HEX);
Serial.print("\t ");
- Serial.println(irData.cmd,HEX);
+ Serial.println(irData.cmd, HEX);
}
}
diff --git a/examples/HelloSIRC/HelloSIRC.ino b/examples/HelloSIRC/HelloSIRC.ino
index 7eb9579..27d1370 100644
--- a/examples/HelloSIRC/HelloSIRC.ino
+++ b/examples/HelloSIRC/HelloSIRC.ino
@@ -1,38 +1,45 @@
/* A simple example, using the IRsmallDecoder library,
* for testing remote controls that use the Sony SIRC protocol.
*
- * Note: this example uses an advanced implementation of the SIRC decoder which
+ *
+ * This example uses an advanced implementation of the SIRC decoder which
* takes advantage of the fact that most SIRC remotes will send three signal frames
* every time one key is pressed. That allows the decoder to:
- * - identify the number of bits of the protocol;
+ * - identify the number of bits of the protocol (12, 15 or 20);
* - ignore the two additional repetitions;
* - use the repetitions to check for errors;
* - determine if a key is being held.
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
+ * If the decoder detects 12 or 15 bits, the ext data member is set to 0.
+ * If it detects a 20-bit code, it will save the extended data in the ext member.
+ *
+ * In this example it's assumed that the IR receiver is connected to digital pin 2 and
* the pin is usable for external interrupts.
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
*/
-#define IR_SMALLD_SIRC //1st: define which protocol to use and then,
-#include //2nd: include the library;
-IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
-irSmallD_t irData; //4th: declare one decoder data structure;
-
+#define IR_SMALLD_SIRC //1st: define which protocol to use and then,
+#include //2nd: include the library;
+IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
+irSmallD_t irData; //4th: declare one decoder data structure;
+
void setup() {
Serial.begin(250000);
Serial.println("Waiting for a SIRC remote control IR signal...");
- Serial.println("held\t addr\t cmd");
+ Serial.println("held\taddr\tcmd \tExt");
}
void loop() {
- if(irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
- Serial.print(irData.keyHeld,HEX); //6th: do something with the data.
- Serial.print("\t ");
- Serial.print(irData.addr,HEX);
- Serial.print("\t ");
- Serial.println(irData.cmd,HEX);
+ if (irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
+ Serial.print(irData.keyHeld, HEX); //6th: do something with the data.
+ Serial.print(" \t");
+ Serial.print(irData.addr, HEX);
+ Serial.print(" \t");
+ Serial.print(irData.cmd, HEX);
+ Serial.print(" \t");
+ Serial.println(irData.ext, HEX);
}
}
\ No newline at end of file
diff --git a/examples/HelloSIRC12/HelloSIRC12.ino b/examples/HelloSIRC12/HelloSIRC12.ino
deleted file mode 100644
index 5d61c23..0000000
--- a/examples/HelloSIRC12/HelloSIRC12.ino
+++ /dev/null
@@ -1,39 +0,0 @@
-/* A simple example, using the IRsmallDecoder library,
- * for testing remote controls that use the Sony SIRC12 protocol.
- *
- * Notes:
- * - For the SIRC15 or SIRC20 protocols, use IR_SMALLD_SIRC15 or IR_SMALLD_SIRC20
- * instead of IR_SMALLD_SIRC12 (in the #define ...);
- * - Unlike IR_SMALLD_SIRC, IR_SMALLD_SIRC12/15/20 does not have the keyHeld data member;
- * - IR_SMALLD_SIRC20 has an additional data member (ext);
- * - Each keypress on a SIRC remote, usually sends three signal frames. (The two additional
- * signal repetitions are ignored in the IR_SMALLD_SIRC, but not in the IR_SMALLD_SIRC12/15/20);
- * - IR_SMALLD_SIRC12 will receive signals from SIRC15 and SIRC20
- * but the codes will not be correct;
- * - In a similar way, IR_SMALLD_SIRC15 will receive signals from SIRC20, but not from SIRC12.
- *
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
- * the pin is usable for external interrupts.
- * For more information on the boards' usable pins, see the library documentation at:
- * https://github.com/LuisMiCa/IRsmallDecoder
- * or the README.pdf file in the extras folder of this library.
- */
-
-#define IR_SMALLD_SIRC12 //1st: define which protocol to use and then,
-#include //2nd: include the library;
-IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
-irSmallD_t irData; //4th: declare one decoder data structure;
-
-void setup() {
- Serial.begin(250000);
- Serial.println("Waiting for a SIRC12 remote control IR signal...");
- Serial.println("Addr\t Cmd");
-}
-
-void loop() {
- if(irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
- Serial.print(irData.addr,HEX); //6th: do something with the data.
- Serial.print("\t ");
- Serial.println(irData.cmd,HEX);
- }
-}
diff --git a/examples/HelloSIRCbasic/HelloSIRCbasic.ino b/examples/HelloSIRCbasic/HelloSIRCbasic.ino
new file mode 100644
index 0000000..b91ddfa
--- /dev/null
+++ b/examples/HelloSIRCbasic/HelloSIRCbasic.ino
@@ -0,0 +1,55 @@
+/* A simple example, using the IRsmallDecoder library, for testing remote controls
+ * that use the Sony SIRC12, SIRC15 or SIRC20 protocols.
+ *
+ * Notes:
+ * - Unlike IR_SMALLD_SIRC, IR_SMALLD_SIRC12/15/20 do not have the keyHeld data member;
+ * - IR_SMALLD_SIRC20 has an additional data member (ext);
+ * - Each keypress on a SIRC remote, usually sends three signal frames. The two additional
+ * signal repetitions are ignored in the IR_SMALLD_SIRC, but not in the IR_SMALLD_SIRC12/15/20;
+ * - IR_SMALLD_SIRC12 will receive signals from SIRC15 and SIRC20, but the codes will not be correct;
+ * - In a similar way, IR_SMALLD_SIRC15 will receive signals from SIRC20, but not from SIRC12.
+ *
+ * In this example it's assumed that the IR receiver is connected to digital pin 2 and
+ * the pin is usable for external interrupts.
+ *
+ * For more information on the boards' usable pins, see the library documentation at:
+ * https://github.com/LuisMiCa/IRsmallDecoder
+ * or the README.pdf file in the extras folder of this library.
+ */
+
+
+#define IR_SMALLD_SIRC12 //1st: define which protocol to use;
+//#define IR_SMALLD_SIRC15
+//#define IR_SMALLD_SIRC20
+
+#include //2nd: include the library;
+IRsmallDecoder irDecoder(2); //3rd: create one decoder object with the correct digital pin;
+irSmallD_t irData; //4th: declare one decoder data structure;
+
+void setup() {
+ Serial.begin(250000);
+ #if defined(IR_SMALLD_SIRC12)
+ Serial.println("Waiting for a SIRC12 remote control IR signal...");
+ Serial.println("Addr\tCmd");
+ #elif defined(IR_SMALLD_SIRC15)
+ Serial.println("Waiting for a SIRC15 remote control IR signal...");
+ Serial.println("Addr\tCmd");
+ #elif defined(IR_SMALLD_SIRC20)
+ Serial.println("Waiting for a SIRC20 remote control IR signal...");
+ Serial.println("Addr\tCmd \tExt");
+ #endif
+}
+
+void loop() {
+ if (irDecoder.dataAvailable(irData)) { //5th: if the decoder has some new data available,
+ Serial.print(irData.addr, HEX); //6th: do something with the data.
+ Serial.print(" \t");
+ #if defined(IR_SMALLD_SIRC12) || defined(IR_SMALLD_SIRC15)
+ Serial.println(irData.cmd, HEX);
+ #else
+ Serial.print(irData.cmd, HEX);
+ Serial.print(" \t");
+ Serial.println(irData.ext, HEX);
+ #endif
+ }
+}
diff --git a/examples/KeyHeldNEC/KeyHeldNEC.ino b/examples/KeyHeldNEC/KeyHeldNEC.ino
index 1143392..cf27494 100644
--- a/examples/KeyHeldNEC/KeyHeldNEC.ino
+++ b/examples/KeyHeldNEC/KeyHeldNEC.ino
@@ -1,85 +1,83 @@
/* keyHeld with NEC
*
- * This example is part of the the IRfastDecoder library and is intended to demonstrate
+ * This example is part of the the IRsmallDecoder library and is intended to demonstrate
* a possible usage for the keyHeld data member.
*
* How to use this sketch:
- * - Connect the sensor (see library documentation);
- * - Upload the sketch and open serial Monitor;
+ * - Connect the IR receiver (see library documentation);
+ * - Upload the sketch and open the Serial Monitor;
* - "Teach the Arduino" which keys you want to use to increase or decrease a value:
- * point the NEC remote to the IR sensor and press any key of your choosing then press a different key;
+ * point the NEC remote to the receiver and press any key of your choosing then press a different key;
* - Use the selected keys to increase/decrease the value, one unit at a time for each keypress,
* or, if you hold the key:
* 1 unit for each of the first 9 repeat codes;
* 5 units for each of the next 18 repeat codes;
* 25 units for each of the subsequent repeat codes.
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
+ * In this example it's assumed that the IR receiver is connected to digital pin 2 and
* the pin is usable for external interrupts.
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
*/
-
-
+
#define IR_SMALLD_NEC
#include
-IRsmallDecoder irDecoder(2); //assuming that the IR sensor is connected to digital pin 2
+IRsmallDecoder irDecoder(2); //assuming that the IR receiver is connected to digital pin 2
irSmallD_t irData;
-int value=0;
+int value = 0;
int keyInc, keyDec;
int rptCounter = 0;
int increment = 1;
-
void setup() {
Serial.begin(250000);
-
- Serial.print(F("Press the \"UP\" key on the remote "));
- while(!irDecoder.dataAvailable(irData)); //waiting for one keypress
- keyInc=irData.cmd;
- Serial.print(F("(key cmd="));
+
+ Serial.print("Press the \"UP\" key on the remote ");
+ while (!irDecoder.dataAvailable(irData)) ; //waiting for one keypress
+ keyInc = irData.cmd;
+ Serial.print("(key cmd=");
Serial.print(keyInc, HEX);
- Serial.println(F(")"));
-
- Serial.print(F("Press the \"DOWN\" key on the remote "));
- do{
- while(!irDecoder.dataAvailable(irData)); //waiting for another keypress
- }while(irData.cmd == keyInc); //if it's the same key, go back and wait for another
- keyDec=irData.cmd;
- Serial.print(F("(key cmd="));
+ Serial.println(")");
+
+ Serial.print("Press the \"DOWN\" key on the remote ");
+ do {
+ while (!irDecoder.dataAvailable(irData)) ; //waiting for another keypress
+ } while (irData.cmd == keyInc); //if it's the same key, go back and wait for another
+ keyDec = irData.cmd;
+ Serial.print("(key cmd=");
Serial.print(keyDec, HEX);
- Serial.println(F(")"));
-
+ Serial.println(")");
+
Serial.println();
- Serial.println(F("Press the \"UP\" key to increase the value;"));
- Serial.println(F("Press and hold it to increase faster and faster;"));
- Serial.println(F("Press the \"DOWN\" key to decrease the value;"));
- Serial.println(F("Press and hold it to decrease faster and faster."));
+ Serial.println("Press the \"UP\" key to increase the value;");
+ Serial.println("Press and hold it to increase faster and faster;");
+ Serial.println("Press the \"DOWN\" key to decrease the value;");
+ Serial.println("Press and hold it to decrease faster and faster.");
Serial.println();
}
-
void loop() {
- if(irDecoder.dataAvailable(irData)) {
- if (irData.keyHeld && ((irData.cmd == keyInc) || (irData.cmd == keyDec))){
+ if (irDecoder.dataAvailable(irData)) {
+ if (irData.keyHeld && ((irData.cmd == keyInc) || (irData.cmd == keyDec))) {
rptCounter++;
- if (rptCounter < 10) increment=1;
- else if (rptCounter < 28) increment=5;
- else increment=25;
- }
- else{
+ if (rptCounter < 10) increment = 1;
+ else if (rptCounter < 28)
+ increment = 5;
+ else
+ increment = 25;
+ } else {
rptCounter = 0;
increment = 1;
}
-
- if(irData.cmd == keyInc){
+
+ if (irData.cmd == keyInc) {
value += increment;
if (value > 1000) value = 1000;
Serial.println(value);
- }
- else if(irData.cmd == keyDec){
+ } else if (irData.cmd == keyDec) {
value -= increment;
if (value < 0) value = 0;
Serial.println(value);
diff --git a/examples/SingleHold/SingleHold.ino b/examples/SingleHold/SingleHold.ino
index fb55111..4df2100 100644
--- a/examples/SingleHold/SingleHold.ino
+++ b/examples/SingleHold/SingleHold.ino
@@ -1,25 +1,25 @@
/* Single Hold
*
- * This example is part of the the IRfastDecoder library and is intended to demonstrate
+ * This example is part of the the IRsmallDecoder library and is intended to demonstrate
* a possible usage for the keyHeld data member.
*
* How to use this sketch:
- * - Connect the sensor (see library documentation);
+ * - Connect the IR receiver (see library documentation);
* - Uncomment the #define for the desired protocol,
* (leave the others as comments, only one is allowed);
- * - Upload the sketch and open serial Monitor;
+ * - Upload the sketch and open the Serial Monitor;
* - "Teach the Arduino" which keys you want to use;
* - Hold the selected keys to turn on/off the built-in LED.
* If you keep holding, it won't do anything else.
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
- * the pin is usable for external interrupts.
+ * In this example it's assumed that the board has a builtin LED and the IR receiver is
+ * connected to digital pin 2, which must be usable for external interrupts.
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
*/
-
-
+
#define IR_SMALLD_NEC
//#define IR_SMALLD_NECx
//#define IR_SMALLD_RC5
@@ -29,54 +29,51 @@
#include
-IRsmallDecoder irDecoder(2); //assuming that the IR sensor is connected to digital pin 2
+IRsmallDecoder irDecoder(2); //assuming that the IR receiver is connected to digital pin 2
irSmallD_t irData;
int keyOn, keyOff;
-bool keyReleased=true;
+bool keyReleased = true;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(250000);
-
- Serial.print(F("Press the key that will turn \"ON\" the LED "));
- while(!irDecoder.dataAvailable(irData)); //waiting for one keypress
- keyOn=irData.cmd;
- Serial.print(F("(key cmd="));
+
+ Serial.print("Press the key that will turn \"ON\" the LED ");
+ while (!irDecoder.dataAvailable(irData)) ; //waiting for one keypress
+ keyOn = irData.cmd;
+ Serial.print("(key cmd=");
Serial.print(keyOn, HEX);
- Serial.println(F(")"));
-
- Serial.print(F("Press the key that will turn \"OFF\" the LED "));
- do{
- while(!irDecoder.dataAvailable(irData)); //waiting for another keypress
- }while(irData.cmd == keyOn); //if it's the same key, go back and wait for another
- keyOff=irData.cmd;
- Serial.print(F("(key cmd="));
+ Serial.println(")");
+
+ Serial.print("Press the key that will turn \"OFF\" the LED ");
+ do {
+ while (!irDecoder.dataAvailable(irData)) ; //waiting for another keypress
+ } while (irData.cmd == keyOn); //if it's the same key, go back and wait for another
+ keyOff = irData.cmd;
+ Serial.print("(key cmd=");
Serial.print(keyOff, HEX);
- Serial.println(F(")"));
-
+ Serial.println(")");
+
Serial.println();
- Serial.println(F("Hold the \"ON\" key to turn on the Built-in LED;"));
- Serial.println(F("Hold the \"OFF\" key to turn off the Built-in LED;"));
+ Serial.println("Hold the \"ON\" key to turn on the Built-in LED;");
+ Serial.println("Hold the \"OFF\" key to turn off the Built-in LED;");
Serial.println();
}
void loop() {
- if(irDecoder.dataAvailable(irData)) {
+ if (irDecoder.dataAvailable(irData)) {
if (irData.keyHeld) {
if (keyReleased) {
if (irData.cmd == keyOn) {
Serial.print("ON ");
digitalWrite(LED_BUILTIN, HIGH);
- }
- else if (irData.cmd == keyOff) {
+ } else if (irData.cmd == keyOff) {
Serial.print("OFF ");
digitalWrite(LED_BUILTIN, LOW);
}
- keyReleased=false;
+ keyReleased = false;
}
- }
- else keyReleased=true;
+ } else keyReleased = true;
}
}
-
diff --git a/examples/TemporaryDisable/TemporaryDisable.ino b/examples/TemporaryDisable/TemporaryDisable.ino
new file mode 100644
index 0000000..e9e91a7
--- /dev/null
+++ b/examples/TemporaryDisable/TemporaryDisable.ino
@@ -0,0 +1,79 @@
+/* Temporarily disable the decoder
+ *
+ * This example is part of the the IRsmallDecoder library and is intended to demonstrate
+ * a possible usage for the enable and disable methods of the decoder.
+ *
+ * How to use this sketch:
+ * - Connect the IR receiver (see library documentation);
+ * - Uncomment the #define for the desired protocol,
+ * (leave the others as comments, only one is allowed);
+ * - Upload the sketch and open the Serial Monitor;
+ * - "Teach the Arduino" which key you want to use to disable the decoder;
+ * - The selected key will temporarily disable the decoder;
+ * - Any other key on the remote will toggle the builtin LED;
+ *
+ * In this example it's assumed that the board has a builtin LED and the IR receiver is
+ * connected to digital pin 2, which must be usable for external interrupts.
+ *
+ * For more information on the boards' usable pins, see the library documentation at:
+ * https://github.com/LuisMiCa/IRsmallDecoder
+ * or the README.pdf file in the extras folder of this library.
+ */
+
+#define IR_SMALLD_NEC
+//#define IR_SMALLD_NECx
+//#define IR_SMALLD_RC5
+//#define IR_SMALLD_SIRC12
+//#define IR_SMALLD_SIRC15
+//#define IR_SMALLD_SIRC20
+//#define IR_SMALLD_SIRC
+//#define IR_SMALLD_SAMSUNG
+//#define IR_SMALLD_SAMSUNG32
+
+#include
+#define TIMEOUT 8
+
+IRsmallDecoder irDecoder(2); //assuming that the IR receiver is connected to digital pin 2
+irSmallD_t irData;
+int ledState = LOW;
+int keyDisable;
+int timer = 0;
+unsigned long previousMillis = 0;
+unsigned long currentMillis;
+
+void setup() {
+ pinMode(LED_BUILTIN, OUTPUT);
+ Serial.begin(250000);
+ Serial.println("Press the remote key that will temporarily disable the IR decoder.");
+ while (!irDecoder.dataAvailable(irData)) ; //waiting for one keypress
+ keyDisable = irData.cmd;
+ Serial.print("(Key Cmd=");
+ Serial.print(keyDisable, HEX);
+ Serial.println(")");
+ Serial.println("When the decoder is enabled, any other key will toggle the onboard LED.");
+}
+
+void loop() {
+ currentMillis = millis();
+ if ((timer > 0) && (currentMillis - previousMillis >= 1000)) {
+ previousMillis = currentMillis;
+ timer = timer - 1;
+ Serial.println(timer);
+ if (timer == 0) {
+ irDecoder.enable();
+ Serial.println("IR Decoder enabled");
+ }
+ }
+ if (irDecoder.dataAvailable(irData)) {
+ if (irData.cmd == keyDisable) {
+ irDecoder.disable();
+ timer = TIMEOUT;
+ Serial.print("IR Decoder disabled for ");
+ Serial.print(timer);
+ Serial.println(" seconds.");
+ } else {
+ ledState = (ledState == LOW) ? HIGH : LOW;
+ digitalWrite(LED_BUILTIN, ledState);
+ }
+ }
+}
\ No newline at end of file
diff --git a/examples/ToggleLED/ToggleLED.ino b/examples/ToggleLED/ToggleLED.ino
index f2190d7..27f5824 100644
--- a/examples/ToggleLED/ToggleLED.ino
+++ b/examples/ToggleLED/ToggleLED.ino
@@ -3,11 +3,12 @@
* How to use this sketch:
* - Uncomment the #define for the desired protocol,
* leave the others as comments (only one is allowed).
- * - Upload to the Arduino board, connect the IR sensor and
+ * - Upload to the Arduino board, connect the IR receiver and
* - press any key on the remote to toggle the builtin LED
*
- * In this example it's assumed that the IR sensor is connected to digital pin 2 and
- * the pin is usable for external interrupts.
+ * In this example it's assumed that the board has a builtin LED and the IR receiver is
+ * connected to digital pin 2, which must be usable for external interrupts.
+ *
* For more information on the boards' usable pins, see the library documentation at:
* https://github.com/LuisMiCa/IRsmallDecoder
* or the README.pdf file in the extras folder of this library.
@@ -25,17 +26,16 @@
#include
-IRsmallDecoder irDecoder(2); //assuming that the IR sensor is connected to digital pin 2
-irSmallD_t irData;
-int ledState=LOW;
+IRsmallDecoder irDecoder(2); //assuming that the IR receiver is connected to digital pin 2
+int ledState = LOW;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
- if(irDecoder.dataAvailable(irData)){
- ledState = (ledState == LOW)? HIGH : LOW; //toggle with conditional operator
+ if (irDecoder.dataAvailable()) {
+ ledState = (ledState == LOW) ? HIGH : LOW; //toggle with conditional operator
digitalWrite(LED_BUILTIN, ledState);
}
}
diff --git a/extras/IR receivers/IR receiver connections.jpg b/extras/IR receivers/IR receiver connections.jpg
new file mode 100644
index 0000000..7707b1a
Binary files /dev/null and b/extras/IR receivers/IR receiver connections.jpg differ
diff --git a/extras/IR receivers/IRModule.jpg b/extras/IR receivers/IRModule.jpg
new file mode 100644
index 0000000..70d467c
Binary files /dev/null and b/extras/IR receivers/IRModule.jpg differ
diff --git a/extras/IR receivers/IRModuleS.jpg b/extras/IR receivers/IRModuleS.jpg
new file mode 100644
index 0000000..9abf8b2
Binary files /dev/null and b/extras/IR receivers/IRModuleS.jpg differ
diff --git a/extras/IR receivers/PIC12043S.jpg b/extras/IR receivers/PIC12043S.jpg
new file mode 100644
index 0000000..bf26d16
Binary files /dev/null and b/extras/IR receivers/PIC12043S.jpg differ
diff --git a/extras/IR receivers/SFH505A.jpg b/extras/IR receivers/SFH505A.jpg
new file mode 100644
index 0000000..e2ca9ec
Binary files /dev/null and b/extras/IR receivers/SFH505A.jpg differ
diff --git a/extras/IR receivers/TSOP17xx.jpg b/extras/IR receivers/TSOP17xx.jpg
new file mode 100644
index 0000000..b6e9e34
Binary files /dev/null and b/extras/IR receivers/TSOP17xx.jpg differ
diff --git a/extras/IR receivers/TSOP48xx.jpg b/extras/IR receivers/TSOP48xx.jpg
new file mode 100644
index 0000000..acd68b6
Binary files /dev/null and b/extras/IR receivers/TSOP48xx.jpg differ
diff --git a/extras/IRsensors/IR Receiver Connections.jpg b/extras/IRsensors/IR Receiver Connections.jpg
deleted file mode 100644
index 10c2b56..0000000
Binary files a/extras/IRsensors/IR Receiver Connections.jpg and /dev/null differ
diff --git a/extras/IRsensors/IRModule.jpg b/extras/IRsensors/IRModule.jpg
deleted file mode 100644
index b807aeb..0000000
Binary files a/extras/IRsensors/IRModule.jpg and /dev/null differ
diff --git a/extras/IRsensors/PIC12043S.jpg b/extras/IRsensors/PIC12043S.jpg
deleted file mode 100644
index 84457c1..0000000
Binary files a/extras/IRsensors/PIC12043S.jpg and /dev/null differ
diff --git a/extras/IRsensors/SFH505A.jpg b/extras/IRsensors/SFH505A.jpg
deleted file mode 100644
index 1f278d0..0000000
Binary files a/extras/IRsensors/SFH505A.jpg and /dev/null differ
diff --git a/extras/IRsensors/TSOP17xx.jpg b/extras/IRsensors/TSOP17xx.jpg
deleted file mode 100644
index d1d8687..0000000
Binary files a/extras/IRsensors/TSOP17xx.jpg and /dev/null differ
diff --git a/extras/IRsensors/TSOP48xx.jpg b/extras/IRsensors/TSOP48xx.jpg
deleted file mode 100644
index 9c380b6..0000000
Binary files a/extras/IRsensors/TSOP48xx.jpg and /dev/null differ
diff --git a/extras/README.pdf b/extras/README.pdf
index 546aac2..d8a7bc8 100644
Binary files a/extras/README.pdf and b/extras/README.pdf differ
diff --git a/extras/Statecharts/NEC.jpg b/extras/Statecharts/NEC.jpg
deleted file mode 100644
index 0c572cf..0000000
Binary files a/extras/Statecharts/NEC.jpg and /dev/null differ
diff --git a/extras/Statecharts/NEC.svg b/extras/Statecharts/NEC.svg
new file mode 100644
index 0000000..f14c696
--- /dev/null
+++ b/extras/Statecharts/NEC.svg
@@ -0,0 +1,150 @@
+
diff --git a/extras/Statecharts/RC5.jpg b/extras/Statecharts/RC5.jpg
deleted file mode 100644
index 51c3745..0000000
Binary files a/extras/Statecharts/RC5.jpg and /dev/null differ
diff --git a/extras/Statecharts/RC5.svg b/extras/Statecharts/RC5.svg
new file mode 100644
index 0000000..6df3777
--- /dev/null
+++ b/extras/Statecharts/RC5.svg
@@ -0,0 +1,326 @@
+
diff --git a/extras/Statecharts/SAMSUNG.jpg b/extras/Statecharts/SAMSUNG.jpg
deleted file mode 100644
index 25cce6d..0000000
Binary files a/extras/Statecharts/SAMSUNG.jpg and /dev/null differ
diff --git a/extras/Statecharts/SAMSUNG.svg b/extras/Statecharts/SAMSUNG.svg
new file mode 100644
index 0000000..0747455
--- /dev/null
+++ b/extras/Statecharts/SAMSUNG.svg
@@ -0,0 +1,153 @@
+
diff --git a/extras/Statecharts/SAMSUNG32.jpg b/extras/Statecharts/SAMSUNG32.jpg
deleted file mode 100644
index cbfb02d..0000000
Binary files a/extras/Statecharts/SAMSUNG32.jpg and /dev/null differ
diff --git a/extras/Statecharts/SAMSUNG32.svg b/extras/Statecharts/SAMSUNG32.svg
new file mode 100644
index 0000000..e182e36
--- /dev/null
+++ b/extras/Statecharts/SAMSUNG32.svg
@@ -0,0 +1,160 @@
+
diff --git a/extras/Statecharts/SIRC_basic.jpg b/extras/Statecharts/SIRC_basic.jpg
deleted file mode 100644
index 00bf37f..0000000
Binary files a/extras/Statecharts/SIRC_basic.jpg and /dev/null differ
diff --git a/extras/Statecharts/SIRC_basic.svg b/extras/Statecharts/SIRC_basic.svg
new file mode 100644
index 0000000..055ee8c
--- /dev/null
+++ b/extras/Statecharts/SIRC_basic.svg
@@ -0,0 +1,93 @@
+
diff --git a/extras/Statecharts/SIRC_multi.jpg b/extras/Statecharts/SIRC_multi.jpg
deleted file mode 100644
index fc59dfd..0000000
Binary files a/extras/Statecharts/SIRC_multi.jpg and /dev/null differ
diff --git a/extras/Statecharts/SIRC_multi.svg b/extras/Statecharts/SIRC_multi.svg
new file mode 100644
index 0000000..88afa69
--- /dev/null
+++ b/extras/Statecharts/SIRC_multi.svg
@@ -0,0 +1,180 @@
+
diff --git a/keywords.txt b/keywords.txt
index 7d7d4c1..c27383a 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -15,6 +15,8 @@ irSmallD_t KEYWORD1
IRsmallDecoder KEYWORD2
dataAvailable KEYWORD2
+disable KEYWORD2
+enable KEYWORD2
#########################################
diff --git a/library.properties b/library.properties
index f23341f..f640f9c 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=IRsmallDecoder
-version=1.1.0
+version=1.2.0
author=Luis Carvalho
maintainer=Luis Carvalho
sentence=Allows the reception and decoding of infrared signals from remote controls.
diff --git a/src/IRsmallDDebug.h b/src/IRsmallDDebug.h
index ee0b21b..f1574cf 100644
--- a/src/IRsmallDDebug.h
+++ b/src/IRsmallDDebug.h
@@ -10,40 +10,43 @@
* IRSMALLD_DEBUG_TIME - Prints ISR execution time
*
* NOTES:
+ * - The usage of debuging functionalities requires a Serial.begin in the setup;
+ * - The serial communication speed must be high, to avoid timing errors;
+ * A Baud Rate of 250000 seems to work;
+ * - The usage of Serial communications inside an interrupt is not recommended, but
+ * in this case, it's just a few prints for debuging purposes.
* - IRSMALLD_DEBUG_TIME mode uses AVR 328p Timer1 hardware specific code;
- * Results are in Micro Seconds assuming 16MHz clock (Clk Count is divided by 16 to get µs);
- * - The serial communication speed must be high, to avoid timing errors.
+ * Results are in micro seconds, assuming a 16MHz clock (Clk Count is divided by 16 to get µs);
*/
-
-
+
+
#ifndef IRsmallD_Debug_h
#define IRsmallD_Debug_h
-
+
#ifdef IRSMALLD_DEBUG_STATE
- #define DBG_PRINT_STATE(...) Serial.print(__VA_ARGS__);
+ #define DBG_PRINT_STATE(...) Serial.print(__VA_ARGS__);
#else
#define DBG_PRINT_STATE(...) //nothing
#endif
-
+
#ifdef IRSMALLD_DEBUG_DURATION
- #define DBG_PRINTLN_DUR(...) {Serial.print("d="); Serial.print(__VA_ARGS__); Serial.println("µ");}
+ #define DBG_PRINTLN_DUR(...) {Serial.print("d="); Serial.print(__VA_ARGS__); Serial.println("µ");}
#else
#define DBG_PRINTLN_DUR(...) //nothing
#endif
-
+
#ifdef IRSMALLD_DEBUG_TIME
#if defined(IRSMALLD_DEBUG_STATE) || defined(IRSMALLD_DEBUG_DURATION)
#warning Do not use IRSMALLD_DEBUG_TIME with IRSMALLD_DEBUG_STATE or IRSMALLD_DEBUG_DURATION if you want accurate measurements of execution time
#endif
- #define DBG_RESTART_TIMER() { TCCR1A = 0; TCCR1B = 1; TCNT1=0; } //set mode to count clock cycles and reset
- #define DBG_PRINTLN_TIMER() { uint16_t elapsedTime=TCNT1; Serial.print("t="); Serial.print(elapsedTime>>4); Serial.println("µ");}
+ #define DBG_RESTART_TIMER() { TCCR1A = 0; TCCR1B = 1; TCNT1=0; } //set mode to count clock cycles and reset
+ #define DBG_PRINTLN_TIMER() { uint16_t elapsedTime=TCNT1; Serial.print("t="); Serial.print(elapsedTime>>4); Serial.println("µ");}
#else
- #define DBG_RESTART_TIMER() //nothing
- #define DBG_PRINTLN_TIMER() //nothing
+ #define DBG_RESTART_TIMER() //nothing
+ #define DBG_PRINTLN_TIMER() //nothing
#endif
#endif
-
//instead of variadic macros, the following syntax could be used:
@@ -52,4 +55,4 @@
//Call Serial.flush() after every Serial.print() if you need to see the output before the code continues with buffered data
//do{}while(false) can be used to prevent some problems with more complex macros
-// #define DBG_SERIALBEGIN(...) do {Serial.begin(__VA_ARGS__); Serial.println("Serial Port Ready!");} while ( false )
+// #define DBG_SERIALBEGIN(...) do {Serial.begin(__VA_ARGS__); Serial.println("Serial Port Ready!");} while ( false )
\ No newline at end of file
diff --git a/src/IRsmallDProtocolStructs.h b/src/IRsmallDProtocolStructs.h
index ac89e59..bd93673 100644
--- a/src/IRsmallDProtocolStructs.h
+++ b/src/IRsmallDProtocolStructs.h
@@ -3,45 +3,45 @@
* This file is part of the IRsmallDecoder library for Arduino
* Copyright (c) 2020 Luis Carvalho
*/
-
+
#ifndef IRsmallD_ProtocolStructs_h
#define IRsmallD_ProtocolStructs_h
#if IR_SMALLD_NEC || IR_SMALLD_RC5 || IR_SMALLD_SAMSUNG32
- struct irSmallD_t{
+ struct irSmallD_t {
uint8_t addr;
uint8_t cmd;
bool keyHeld;
};
#elif IR_SMALLD_NECx || IR_SMALLD_SAMSUNG
- struct irSmallD_t{
+ struct irSmallD_t {
uint16_t addr;
uint8_t cmd;
bool keyHeld;
};
#elif IR_SMALLD_SIRC12 || IR_SMALLD_SIRC15
- struct irSmallD_t{
+ struct irSmallD_t {
uint8_t addr;
uint8_t cmd;
};
#elif IR_SMALLD_SIRC20
- struct irSmallD_t{
+ struct irSmallD_t {
uint8_t ext; //extended data
uint8_t addr;
uint8_t cmd;
};
#elif IR_SMALLD_SIRC
- struct irSmallD_t{
+ struct irSmallD_t {
uint8_t ext;
uint8_t addr;
uint8_t cmd;
bool keyHeld;
};
-
+
#else
#error Protocol data structure not defined.
#endif
diff --git a/src/IRsmallD_NEC.h b/src/IRsmallD_NEC.h
index 1336bd4..264ecc6 100644
--- a/src/IRsmallD_NEC.h
+++ b/src/IRsmallD_NEC.h
@@ -22,6 +22,9 @@
* low Address high address 8bit command inverted command
* LSB ... MSB LSB ... MSB LSB ... MSB LSB ... MSB
*
+ *
+ * The signal ends with an extra 560µs pulse, which is required to determine the value of the last bit.
+ *
* Notes:
* - Inverted bytes have 1s instead of 0s and vice-versa;
* - Extended NEC protocol sacrifices the address redundancy to extend
@@ -33,89 +36,88 @@
*/
-void IRsmallDecoder::irISR() { //executed every time the IR signal goes up (actually it's on FALL)
+void IRsmallDecoder::irISR() { //executed every time the IR signal goes up (but it's actually FALLING @ ReceiverOutput)
// NEC timings in micro seconds:
// Minimum Gap length = repeatPeriod - SignalFrame = 108000 - 67500 = 40500
- const uint16_t c_GapMin = 32400; // = 40500 * 0.8 (20% less)
+ const uint16_t c_GapMin = 32400; // = 40500 * 0.8 (20% less)
// Leading Mark Length = Leading pulse + leading space = 9000 + 4500 = 13500
// Repeat Mark Length = Repeat Pulse + Repeat Space = 9000 + 2250 = 11250
// max tolerance = (13500 - 11250)/2 = 1125
- const uint16_t c_LMmax = 14625; // = 13500 + 1125 (it could be more)
- const uint16_t c_LMmin = 12375; // = 13500 - 1125
- const uint16_t c_RMmax = 12374; // = 11250 + 1125 - 1
- const uint16_t c_RMmin = 10125; // = 11250 - 1125 (it could be less)
+ const uint16_t c_LMmax = 14625; // = 13500 + 1125 (it could be more)
+ const uint16_t c_LMmin = 12375; // = 13500 - 1125
+ const uint16_t c_RMmax = 12374; // = 11250 + 1125 - 1
+ const uint16_t c_RMmin = 10125; // = 11250 - 1125 (it could be less)
//Bit 0 Mark length = 562.5µs pulse + 562.5µs space = 1125
//Bit 1 Mark length = 562.5µs pulse + 3 * 562.5µs space = 2250
//max tolerance = (2250 - 1125)/2 = 562.5 = bit pulse
- const uint16_t c_M1max = 2812; // = 2250 + 562 (it could be more)
- const uint16_t c_M1min = 1688; // = 2250 - 562
- //const uint16_t c_M0max = 1687; // = 1125 + 562 //not needed...
- const uint16_t c_M0min = 563; // = 1125 - 562 (it could be less)
- const uint32_t c_GapMax= 106425;//= (108000-11250) * 1.1; // 10% above gap between 2 consecutive repeat marks
+ const uint16_t c_M1max = 2812; // = 2250 + 562 (it could be more)
+ const uint16_t c_M1min = 1688; // = 2250 - 562
+ //const uint16_t c_M0max = 1687; // = 1125 + 562 //not needed...
+ const uint16_t c_M0min = 563; // = 1125 - 562 (it could be less)
+ const uint32_t c_GapMax = 106425; //= (108000-11250) * 1.1; // 10% above gap between 2 consecutive repeat marks
//number of initial repeats to be ignored:
- const uint8_t c_RptCount = 2;
-
+ const uint8_t c_RptCount = 2;
+
// FSM variables:
static uint32_t duration;
- static uint8_t bitCount;
- static uint32_t startTime = -1; //FFFF... (by two's complement)
- static union {//received bits are stored in reversed order (11000101... -> ...10100011)
- uint32_t all=0; //Arduino uses Little Endian so, if all=ABCDEF89 then in memory it's 89EFCDAB (hex format)
- uint8_t byt[4]; //then we get byt[0]=89, byt[1]=EF, byt[2]=CD and byt[3]=AB (type punning with a union...)
+ static uint8_t bitCount;
+ static uint32_t startTime = -1; //FFFF... (by two's complement)
+ static union { //received bits are stored in reversed order (11000101... -> ...10100011)
+ uint32_t all = 0; //Arduino uses Little Endian so, if all=ABCDEF89 then in memory it's 89EFCDAB (hex format)
+ uint8_t byt[4]; //then we get byt[0]=89, byt[1]=EF, byt[2]=CD and byt[3]=AB (type punning with a union...)
} irSignal;
- static uint8_t repeatCount=0;
- static uint8_t state=0;
- static bool possiblyHeld=false;
+ static uint8_t repeatCount = 0;
+ static uint8_t state = 0;
+ static bool possiblyHeld = false;
DBG_PRINT_STATE(state);
DBG_RESTART_TIMER();
-
- duration = micros() - startTime; //note: micros() has a 4μs resolution (multiples of 4) @16MHz and 8μs @8MHz
+
+ duration = micros() - startTime; //note: micros() has a 4μs resolution (multiples of 4) @ 16MHz or 8μs @ 8MHz
startTime = micros();
DBG_PRINTLN_DUR(duration);
- switch(state){ //asynchronous (event-driven) Finite State Machine
- case 0: //standby:
- if(duration > c_GapMin){
+ switch (state) { //asynchronous (event-driven) Finite State Machine
+ case 0: //standby:
+ if (duration > c_GapMin) {
if (duration > c_GapMax) possiblyHeld = false;
- state=1;
- }
+ state = 1;
+ }
else possiblyHeld = false;
break;
-
- case 1: //startPulse:
- if (duration >= c_LMmin && duration <= c_LMmax){ //its a Leading Mark
- bitCount=0;
- repeatCount=0;
- state=2;
- }
- else {
- if (possiblyHeld && duration >= c_RMmin && duration <= c_RMmax) { //its a Repeat Mark
- if (repeatCount < c_RptCount) repeatCount++; //first repeat signals will be ignored
- else if (!_irCopyingData){ //if not interrupting a copy...
+
+ case 1: //startPulse:
+ if (duration >= c_LMmin && duration <= c_LMmax) { //its a Leading Mark
+ bitCount = 0;
+ repeatCount = 0;
+ state = 2;
+ } else {
+ if (possiblyHeld && duration >= c_RMmin && duration <= c_RMmax) { //its a Repeat Mark
+ if (repeatCount < c_RptCount) repeatCount++; //first repeat signals will be ignored
+ else if (!_irCopyingData) { //if not interrupting a copy...
_irData.keyHeld = true;
- _irDataAvailable= true;
+ _irDataAvailable = true;
}
}
- state=0;
+ state = 0;
}
break;
-
+
case 2: //receiving:
- if(duration < c_M0min || duration > c_M1max) state=0; //error, not a bit mark
- else { // it's M0 or M1
+ if (duration < c_M0min || duration > c_M1max) state = 0; //error, not a bit mark
+ else { // it's M0 or M1
irSignal.all >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
- if(duration >= c_M1min) irSignal.byt[3] |= 0x80; //it's M1, change MSB to 1
+ if (duration >= c_M1min) irSignal.byt[3] |= 0x80; //it's M1, change MSB to 1
bitCount++;
#if defined(IR_SMALLD_NEC) //Conditional code inclusion (at compile time)
- if (bitCount==16) { //Address and Reversed Address received
- if (irSignal.byt[2] != (uint8_t)~irSignal.byt[3]) state=0; //address error
- else state=2; //Address OK, continue with command reception
+ if (bitCount == 16) { //Address and Reversed Address received
+ if (irSignal.byt[2] != (uint8_t)~irSignal.byt[3]) state = 0; //address error
+ // else state = 2; //Address OK, continue with command reception //(redundant assignment)
}
- else
+ else // that's right, a loose else...
#endif
- if (bitCount==32) { //all bits received
- if(!_irCopyingData && (irSignal.byt[2] == (uint8_t)~irSignal.byt[3])){ //if not interrupting a copy and command OK, finish decoding
+ if (bitCount == 32) { //all bits received
+ if (!_irCopyingData && (irSignal.byt[2] == (uint8_t)~irSignal.byt[3])) { //if not interrupting a copy and command OK, finish decoding
#if defined(IR_SMALLD_NEC) //NEC address has 8 bits
_irData.addr = irSignal.byt[0];
#else //it must be IR_SMALLD_NECx (16 bits)
@@ -125,15 +127,15 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes up (actu
#endif
_irData.cmd = irSignal.byt[2];
_irData.keyHeld = false;
- _irDataAvailable= true;
- possiblyHeld=true; //will remain true if the next gap is OK
+ _irDataAvailable = true;
+ possiblyHeld = true; //will remain true if the next gap is OK
}
- state=0;
+ state = 0;
}
- else state=2; //continue receiving
+ // else state = 2; //continue receiving //(redundant assignment)
}
break;
}
-
+
DBG_PRINTLN_TIMER();
}
diff --git a/src/IRsmallD_RC5.h b/src/IRsmallD_RC5.h
index 7757d50..f42165a 100644
--- a/src/IRsmallD_RC5.h
+++ b/src/IRsmallD_RC5.h
@@ -8,12 +8,13 @@
* ------------------------
* Modulation type: Manchester code (bi-phase) - LOW to HIGH for ACE (1), HIGH to LOW for ZERO (0)
* Carrier frequency: 36 KHz
- * Bit period: 1.778 ms (signal high for 889 μs (or double); low for 889 μs (or double))
+ * Bit period: 1.778 ms (HIGH for 889μs then LOW for 889μs or vice-versa)
+ * When the bits are combined, the signal pulses' durations are 889μs or 1778μs, and the same goes for the spaces;
* Total signal duration: 24.892 ms
* Signal repetition interval: 100 ms
*
* 14 bit signal (in order of transmission):
- * 2 Start bits ; 1 Toggle bit; 5 Address bits(MSB to LSB); 6 Command bits (MSB to LSB)
+ * 2 Start bits; 1 Toggle bit; 5 Address bits(MSB to LSB); 6 Command bits (MSB to LSB)
*
* In RC5 extended, the second Start bit is the Field bit. It indicates whether the command sent is in the
* lower field (bit 1: cmd=[0..63]) or the upper field (bit 0: cmd=[64..127]).
@@ -25,26 +26,26 @@
*/
-void IRsmallDecoder::irISR() { //executed every time the IR signal changes
+void IRsmallDecoder::irISR() { //executed every time the IR signal changes (caution, it's reversed because of the INPUT_PULLUP mode)
// RC5 timings in micro secs:
- const uint32_t c_rptPmax = 113792*1.2; //Repetition period upper threshold (20% above standard)
- const uint32_t c_gapMin = 88900*0.8; //Lower threshold of the gap between 2 signals (20% below standard)
- const uint16_t c_bitPeriod= 1778;
- const uint16_t c_tolerance= 444; //max. tolerance is 1778/4 = 444.5
- const uint16_t c_longMax = c_bitPeriod + c_tolerance; // 1778 + 444 = 2222
- const uint16_t c_shortMax = c_bitPeriod/2 + c_tolerance; // 1778/2+444 = 1333
- const uint16_t c_shortMin = c_bitPeriod/2 - c_tolerance; // 1778/2-444 = 445
+ const uint32_t c_rptPmax = 113792 * 1.2; //Repetition period upper threshold (20% above standard)
+ const uint32_t c_gapMin = 88900 * 0.8; //Lower threshold of the gap between 2 signals (20% below standard)
+ const uint16_t c_bitPeriod = 1778;
+ const uint16_t c_tolerance = 444; //max. tolerance is 1778/4 = 444.5
+ const uint16_t c_longMax = c_bitPeriod + c_tolerance; // 1778 + 444 = 2222
+ const uint16_t c_shortMax = c_bitPeriod / 2 + c_tolerance; // 1778/2+444 = 1333
+ const uint16_t c_shortMin = c_bitPeriod / 2 - c_tolerance; // 1778/2-444 = 445
//number of initial repeats to be ignored:
- const uint8_t c_rptCount = 2;
+ const uint8_t c_rptCount = 2;
// FSM variables:
static uint32_t duration;
static uint8_t bitCount;
- static uint32_t startTime = -1;//FFFF... solves problem with initial unknown toggle state (50% chance of starting with held)
- static uint16_t irSignal; //only 14 bits used
- static bool prevToggle = false; //used to convert Toggle to Held
- static uint8_t repeatCount= 0;
- static uint32_t lastBitTime= 0; //for the repeat code confirmation
-
+ static uint32_t startTime = -1; //FFFF... solves problem with initial unknown toggle state (50% chance of starting with held)
+ static uint16_t irSignal; //only 14 bits used
+ static bool prevToggle = false; //used to convert Toggle to Held
+ static uint8_t repeatCount = 0;
+ static uint32_t lastBitTime = 0; //for the repeat code confirmation
+
FSM_INITIALIZE(st_standby);
DBG_RESTART_TIMER();
@@ -56,9 +57,9 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal changes
//====== States: st_standby, st_roseInSync, st_roseOffSync, st_fellInSync, st_fellOffSync
st_standby:
DBG_PRINT_STATE(0);
- if(duration >= c_gapMin) { //start pulse detected. It's very unlikely that a pulse will be longer than c_gapMin
- bitCount=0;
- irSignal=0;
+ if (duration >= c_gapMin) { //start pulse detected. It's very unlikely that a pulse will be longer than c_gapMin
+ bitCount = 0;
+ irSignal = 0;
FSM_NEXT(st_roseInSync);
}
break;
@@ -74,63 +75,62 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal changes
st_roseOffSync:
DBG_PRINT_STATE(2);
- if(duration < c_shortMin || duration > c_shortMax) FSM_NEXT(st_standby); //error
- else FSM_DIRECTJUMP(ps_roseChoice); //it's Short
+ if (duration < c_shortMin || duration > c_shortMax) FSM_NEXT(st_standby); //error
+ else FSM_DIRECTJUMP(ps_roseChoice); //it's Short
break;
st_fellInSync:
DBG_PRINT_STATE(3);
irSignal <<= 1; // push Bit 0 (from right to left)
bitCount++;
- if(duration < c_shortMin || duration > c_longMax) FSM_NEXT(st_standby); //error
- else if(duration <= c_shortMax) FSM_NEXT(st_roseOffSync); //it's Short
- else FSM_DIRECTJUMP(ps_fellChoice); //it's Long
+ if (duration < c_shortMin || duration > c_longMax) FSM_NEXT(st_standby); //error
+ else if (duration <= c_shortMax) FSM_NEXT(st_roseOffSync); //it's Short
+ else FSM_DIRECTJUMP(ps_fellChoice); //it's Long
break;
st_fellOffSync:
DBG_PRINT_STATE(4);
- if(duration < c_shortMin || duration > c_shortMax) FSM_NEXT(st_standby); //error
- else FSM_DIRECTJUMP(ps_fellChoice); //it's Short
+ if (duration < c_shortMin || duration > c_shortMax) FSM_NEXT(st_standby); //error
+ else FSM_DIRECTJUMP(ps_fellChoice); //it's Short
break;
//======= Pseudo-states: ps_roseChoice, ps_fellChoice, ps_decode
ps_roseChoice:
DBG_PRINT_STATE("r");
- if(bitCount==13) { //all 14 bits received
- irSignal <<= 1; //push bit 0 from right to left
- FSM_DIRECTJUMP(ps_decode); //ps_decode will handle the rest...
+ if (bitCount==13) { //all 14 bits received
+ irSignal <<= 1; //push bit 0 from right to left
+ FSM_DIRECTJUMP(ps_decode); //ps_decode will handle the rest...
}
else FSM_NEXT(st_fellInSync);
break;
ps_fellChoice:
DBG_PRINT_STATE("f");
- if(bitCount==13) { //all 14 bits received
- irSignal <<= 1; irSignal += 1; //push bit 1 from right to left
- FSM_DIRECTJUMP(ps_decode); //ps_decode will handle the rest...
+ if (bitCount==13) { //all 14 bits received
+ irSignal <<= 1; irSignal += 1; //push bit 1 from right to left
+ FSM_DIRECTJUMP(ps_decode); //ps_decode will handle the rest...
}
else FSM_NEXT(st_roseInSync);
break;
ps_decode:
DBG_PRINT_STATE("d");
- if (!_irCopyingData){ //if not interrupting a copy, decode (else, discard this signal)
- if (startTime-lastBitTime < c_rptPmax && (prevToggle == bool(irSignal & 0x0800))){ //if period OK and toggle bit did not change, then the key was held
- if (repeatCount < c_rptCount ) repeatCount++;
- else { // initial repetitions already ignored
+ if (!_irCopyingData) { //if not interrupting a copy, decode (else, discard this signal)
+ if (startTime - lastBitTime < c_rptPmax && (prevToggle == bool(irSignal & 0x0800))) { //if period OK and toggle bit did not change, then the key was held
+ if (repeatCount < c_rptCount) repeatCount++;
+ else { // initial repetitions already ignored
_irData.keyHeld = true;
- _irDataAvailable= true;
+ _irDataAvailable = true;
}
- }
- else { //key was not held, decode
+ } else { //key was not held, decode
_irData.addr = (irSignal & 0x7C0) >> 6;
- _irData.cmd = (irSignal & 0x3F) | ((irSignal & 0x1000)? 0 : 0x40); //extract cmd and add field bit (inverted)
+ _irData.cmd = (irSignal & 0x3F) | ((irSignal & 0x1000) ? 0 : 0x40); //extract cmd and add field bit (inverted)
_irData.keyHeld = false;
- _irDataAvailable= true;
- repeatCount=0;
+ _irDataAvailable = true;
+ repeatCount = 0;
}
prevToggle = bool(irSignal & 0x0800);
- lastBitTime = startTime; //last bit transition time (for keyHeld confirmation)
+ lastBitTime = startTime; //last bit transition time (for keyHeld confirmation)
}
FSM_NEXT(st_standby);
break;
diff --git a/src/IRsmallD_SAMSUNG.h b/src/IRsmallD_SAMSUNG.h
index 1582d93..8c9f59b 100644
--- a/src/IRsmallD_SAMSUNG.h
+++ b/src/IRsmallD_SAMSUNG.h
@@ -39,29 +39,29 @@
#define STOP_SPACE_MAX 27938 //27937.5 to be more precise
-void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but FALLING @SensorOutput)
+void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but it's actually FALLING @ ReceiverOutput)
// SAMSUNG timing thresholds:
- const uint16_t c_LMmax = LEADING_MARK * 1.1; // 10% more = 9900
- const uint16_t c_LMmin = LEADING_MARK * 0.9; // 10% less = 8100
- const uint16_t c_M1max = BIT_1_MARK + BIT_TOLERANCE; //2550+712=3262
- const uint16_t c_M1min = BIT_1_MARK - BIT_TOLERANCE; //2550-712=1838
- //const uint16_t c_M0max = BIT_0_MARK + BIT_TOLERANCE; //1125+712=1837 //NOT USED
- const uint16_t c_M0min = BIT_0_MARK - BIT_TOLERANCE; //1125-712= 413
+ const uint16_t c_LMmax = LEADING_MARK * 1.1; // 10% more = 9900
+ const uint16_t c_LMmin = LEADING_MARK * 0.9; // 10% less = 8100
+ const uint16_t c_M1max = BIT_1_MARK + BIT_TOLERANCE; // 2550+712=3262
+ const uint16_t c_M1min = BIT_1_MARK - BIT_TOLERANCE; // 2550-712=1838
+ //const uint16_t c_M0max = BIT_0_MARK + BIT_TOLERANCE; // 1125+712=1837 //NOT USED
+ const uint16_t c_M0min = BIT_0_MARK - BIT_TOLERANCE; // 1125-712= 413
const uint32_t c_GapMax = STOP_SPACE_MAX + 6 * BIT_TOLERANCE; // bigger tolerance
const uint16_t c_GapMin = STOP_SPACE_MIN - 6 * BIT_TOLERANCE; // 6*712 = 4272
-
+
//number of initial repeats to be ignored:
const uint8_t c_RptCount = 3;
-
+
// FSM variables:
static uint32_t duration;
static uint8_t bitCount;
- static uint32_t startTime = -1; //FFFF... (by two's complement)
- static uint8_t signal_Cmd; //starts as an auxiliary Byte for address decoding
+ static uint32_t startTime = -1; //FFFF... (by two's complement)
+ static uint8_t signal_Cmd; //starts as an auxiliary Byte for address decoding
static uint16_t signal_Addr16;
- static uint8_t state=0;
- static uint8_t repeatCount=0;
- static bool possiblyHeld=false;
+ static uint8_t state = 0;
+ static uint8_t repeatCount = 0;
+ static bool possiblyHeld = false;
DBG_PRINT_STATE(state);
DBG_RESTART_TIMER();
@@ -70,57 +70,55 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but
startTime = micros();
DBG_PRINTLN_DUR(duration);
- switch(state){ //asynchronous (event-driven) Finite State Machine
+ switch (state) { //asynchronous (event-driven) Finite State Machine
case 0: //standby:
- if(duration > c_GapMin){
+ if (duration > c_GapMin) {
if (duration > c_GapMax) possiblyHeld = false;
- state=1;
+ state = 1;
}
else possiblyHeld = false;
break;
case 1: //startPulse:
- if (duration >= c_LMmin && duration <= c_LMmax){ //its a Leading Mark
- bitCount=0;
- state=2;
+ if (duration >= c_LMmin && duration <= c_LMmax) { //its a Leading Mark
+ bitCount = 0;
+ state = 2;
}
- else state=0;
+ else state = 0;
break;
case 2: //receiving:
- if(duration < c_M0min || duration > c_M1max) state=0; //error, not a bit mark
- else { // it's M0 or M1
- signal_Cmd >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
- if(duration >= c_M1min) signal_Cmd |= 0x80; //it's M1, change MSB to 1
+ if (duration < c_M0min || duration > c_M1max) state = 0; //error, not a bit mark
+ else { //it's M0 or M1
+ signal_Cmd >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
+ if (duration >= c_M1min) signal_Cmd |= 0x80; //it's M1, change MSB to 1
bitCount++;
- if (bitCount==8) signal_Addr16 = signal_Cmd; //set address low byte (and stay in same state)
- else if (bitCount==12) {
- signal_Cmd >>= 4; // Push 4 '0' bits to the right
- signal_Addr16 |= signal_Cmd << 8; //set address high byte (and stay in same state)
- }
- else if (bitCount==20) { //all bits received,
- if (possiblyHeld && signal_Cmd == _irData.cmd){ //keyHeld confirmed (addr shouldn't have changed)
- if (repeatCount < c_RptCount) repeatCount++; //first repeat signals will be ignored
- else if (!_irCopyingData){ //repetitions ignored; if not interrupting a copy...
+ if (bitCount == 8) signal_Addr16 = signal_Cmd; //set address low byte (and stay in same state)
+ else if (bitCount == 12) {
+ signal_Cmd >>= 4; //Push 4 '0' bits to the right
+ signal_Addr16 |= signal_Cmd << 8; //set address high byte (and stay in same state)
+ } else if (bitCount == 20) { //all bits received,
+ if (possiblyHeld && signal_Cmd == _irData.cmd) { //keyHeld confirmed (addr shouldn't have changed)
+ if (repeatCount < c_RptCount) repeatCount++; //first repeat signals will be ignored
+ else if (!_irCopyingData) { //repetitions ignored; if not interrupting a copy...
_irData.keyHeld = true;
- _irDataAvailable= true;
+ _irDataAvailable = true;
}
- }
- else if (!_irCopyingData){ //key was not held; if allowed, update data
+ } else if (!_irCopyingData) { //key was not held; if allowed, update data
_irData.addr = signal_Addr16;
- _irData.cmd = signal_Cmd;
+ _irData.cmd = signal_Cmd;
_irData.keyHeld = false;
- _irDataAvailable= true;
- possiblyHeld=true; //will remain true if the next gap is OK
- repeatCount=0;
- }
- state=0; //done
- }
- //else state=2; //stay in same state
+ _irDataAvailable = true;
+ possiblyHeld = true; //will remain true if the next gap is OK
+ repeatCount = 0;
+ }
+ state = 0; //done
+ }
+ //else state=2; //stay in same state
}
break;
}
-
+
DBG_PRINTLN_TIMER();
}
@@ -135,5 +133,4 @@ Decoding process using command byte as an auxiliary byte to decode the address:
Push 4 '0' bits to the right: 0 0 0 0 Ab Aa A9 A8
set address high byte to signal_Cmd: signal_Addr16 |= signal_Cmd << 8
Store C0 to C7 in signal_Cmd: C7 C6 C5 C4 C3 C2 C1 C0
-
- */
+ */
\ No newline at end of file
diff --git a/src/IRsmallD_SAMSUNG32.h b/src/IRsmallD_SAMSUNG32.h
index fc6e1c3..159a69b 100644
--- a/src/IRsmallD_SAMSUNG32.h
+++ b/src/IRsmallD_SAMSUNG32.h
@@ -30,34 +30,34 @@
#define LEADING_MARK 9000
#define BIT_0_MARK 1125
#define BIT_1_MARK 2550
-#define BIT_TOLERANCE ((BIT_1_MARK - BIT_0_MARK)/2) // = 712
+#define BIT_TOLERANCE ((BIT_1_MARK - BIT_0_MARK) / 2) // = 712
#define STOP_SPACE_MIN 35437 //35437.5 to be more precise
#define STOP_SPACE_MAX 72563 //72562.5 to be more precise
-void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but FALLING @SensorOutput)
+void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but it's actually FALLING @ ReceiverOutput)
// SAMSUNG32 timing thresholds:
- const uint16_t c_LMmax = LEADING_MARK * 1.1; // 10% more = 9900
- const uint16_t c_LMmin = LEADING_MARK * 0.9; // 10% less = 8100
- const uint16_t c_M1max = BIT_1_MARK + BIT_TOLERANCE; //2550+712=3262
- const uint16_t c_M1min = BIT_1_MARK - BIT_TOLERANCE; //2550-712=1838
-//const uint16_t c_M0max = BIT_0_MARK + BIT_TOLERANCE; //1125+712=1837 //NOT USED
- const uint16_t c_M0min = BIT_0_MARK - BIT_TOLERANCE; //1125-712= 413
+ const uint16_t c_LMmax = LEADING_MARK * 1.1; // 10% more = 9900
+ const uint16_t c_LMmin = LEADING_MARK * 0.9; // 10% less = 8100
+ const uint16_t c_M1max = BIT_1_MARK + BIT_TOLERANCE; // 2550+712=3262
+ const uint16_t c_M1min = BIT_1_MARK - BIT_TOLERANCE; // 2550-712=1838
+ //const uint16_t c_M0max = BIT_0_MARK + BIT_TOLERANCE;// 1125+712=1837 //NOT USED
+ const uint16_t c_M0min = BIT_0_MARK - BIT_TOLERANCE; // 1125-712= 413
const uint32_t c_GapMax = STOP_SPACE_MAX + 6 * BIT_TOLERANCE; // bigger tolerance
const uint16_t c_GapMin = STOP_SPACE_MIN - 6 * BIT_TOLERANCE; // 6*712 = 4272
//Number of initial repeats to be ignored:
const uint8_t c_RptCount = 2;
-
+
// FSM variables:
static uint32_t duration;
static uint8_t bitCount;
- static uint32_t startTime = -1; //FFFF... (by two's complement)
+ static uint32_t startTime = -1; //FFFF... (by two's complement)
static uint8_t irSignal[4];
static uint8_t byteIndex = 0;
- static uint8_t state=0;
- static uint8_t repeatCount=0;
- static bool possiblyHeld=false;
+ static uint8_t state = 0;
+ static uint8_t repeatCount = 0;
+ static bool possiblyHeld = false;
DBG_PRINT_STATE(state);
@@ -68,48 +68,45 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but
DBG_PRINTLN_DUR(duration);
- switch(state){ //asynchronous (event-driven) Finite State Machine
- case 0: //standby:
- if(duration > c_GapMin){
+ switch (state) { //asynchronous (event-driven) Finite State Machine
+ case 0: //standby:
+ if (duration > c_GapMin) {
if (duration > c_GapMax) possiblyHeld = false;
- state=1;
- }
- else possiblyHeld = false;
+ state = 1;
+ } else possiblyHeld = false;
break;
-
- case 1: //startPulse:
- if (duration >= c_LMmin && duration <= c_LMmax){ //its a Leading Mark
- bitCount=0;
- byteIndex=0;
- state=2;
- }
- else state=0;
+
+ case 1: //startPulse:
+ if (duration >= c_LMmin && duration <= c_LMmax) { //its a Leading Mark
+ bitCount = 0;
+ byteIndex = 0;
+ state = 2;
+ } else state = 0;
break;
-
+
case 2: //receiving:
- if(duration < c_M0min || duration > c_M1max) state=0; //error, not a bit mark
- else { // it's M0 or M1
- irSignal[byteIndex] >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
- if(duration >= c_M1min) irSignal[byteIndex] |= 0x80; //it's M1, change MSB to 1
+ if (duration < c_M0min || duration > c_M1max) state = 0; //error, not a bit mark
+ else { //it's M0 or M1
+ irSignal[byteIndex] >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
+ if (duration >= c_M1min) irSignal[byteIndex] |= 0x80; //it's M1, change MSB to 1
bitCount++;
- if (bitCount==8 || bitCount==16 || bitCount==24) byteIndex++; //byte full, got to next one (stay in same state)
- else if (bitCount==32) { //all bits received,
- state=0; //all paths lead to the standby state...
- if (irSignal[0] == irSignal[1] && irSignal[2] == (uint8_t)~irSignal[3] ){ //address OK && command OK,
- if (possiblyHeld && (irSignal[2] == _irData.cmd)){ //keyHeld confirmed (cmd didn't changed)
- if (repeatCount < c_RptCount) repeatCount++; //first repeat signals will be ignored
- else if (!_irCopyingData){ //repetitions ignored; if not interrupting a copy, update data
+ if (bitCount == 8 || bitCount == 16 || bitCount == 24) byteIndex++; //byte full, proceed to the next one (stay in same state)
+ else if (bitCount == 32) { //all bits received,
+ state = 0; //all paths lead to the standby state...
+ if (irSignal[0] == irSignal[1] && irSignal[2] == (uint8_t)~irSignal[3]) { //address OK && command OK,
+ if (possiblyHeld && (irSignal[2] == _irData.cmd)) { //keyHeld confirmed (cmd didn't changed)
+ if (repeatCount < c_RptCount) repeatCount++; //first repeat signals will be ignored
+ else if (!_irCopyingData) { //repetitions ignored; if not interrupting a copy, update data
_irData.keyHeld = true;
- _irDataAvailable= true;
+ _irDataAvailable = true;
}
- }
- else if (!_irCopyingData){ //key was not held; if allowed, update data
+ } else if (!_irCopyingData) { //key was not held; if allowed, update data
_irData.addr = irSignal[0];
_irData.cmd = irSignal[2];
_irData.keyHeld = false;
- _irDataAvailable= true;
- possiblyHeld=true; //will remain true if the next gap is OK
- repeatCount=0;
+ _irDataAvailable = true;
+ possiblyHeld = true; //will remain true if the next gap is OK
+ repeatCount = 0;
}
}
}
@@ -117,7 +114,7 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes UP (but
}
break;
}
-
+
DBG_PRINTLN_TIMER();
}
diff --git a/src/IRsmallD_SIRC_basic.h b/src/IRsmallD_SIRC_basic.h
index 6ca2d1f..6020102 100644
--- a/src/IRsmallD_SIRC_basic.h
+++ b/src/IRsmallD_SIRC_basic.h
@@ -45,7 +45,7 @@
*/
-void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (actually it's on RISING)
+void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (but it's actually RISING @ ReceiverOutput)
#if defined(IR_SMALLD_SIRC12) //Conditional code inclusion (at compile time)
const uint8_t c_NumberOfBits = 12;
#elif defined(IR_SMALLD_SIRC15)
@@ -53,7 +53,7 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (ac
#else //it must be IR_SMALLD_SIRC20
const uint8_t c_NumberOfBits = 20;
#endif
-
+
// SIRC timings' thresholds in micro secs:
//Bit 0 Mark length = 600µs space + 600µs pulse = 1200µs
//Bit 1 Mark length = 600µs space + 1200µs pulse = 1800µs
@@ -64,71 +64,70 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (ac
const uint16_t c_M0min = 900; // = 1200 - 300 (it could be less)
// Minimum standard Gap length = (75 -(4 + 3 * c_NumberOfBits)) * 600
const uint16_t c_GapMin = (75 -(4 + 3 * c_NumberOfBits)) * 600 * 0.8; //20% below standard value
-
+
// FSM variables:
static uint32_t duration;
static uint8_t bitCount;
- static unsigned long startTime=-1; //FFFF...
- static union {//received bits are stored in reversed order (11000101... -> ...10100011)
+ static unsigned long startTime = -1; //FFFF...
+ static union { //received bits are stored in reversed order (11000101... -> ...10100011)
#if (IR_SMALLD_SIRC12 || IR_SMALLD_SIRC15)
- uint16_t all=0; //Arduino uses Little Endian so, if all=ABCD then in memory it's CDAB (hex format)
- uint8_t byt[2]; //then we get byt[0]=CD and byt[1]=AB (type punning with a union...)
- #else //it must be IR_SMALLD_SIRC20
- uint32_t all=0; //if all=ABCDEF00 then in memory it's 00EFCDAB (hex format)
- uint8_t byt[4]; // byt[0]=00; byt[1]=EF; byt[2]=CD; byt[3]=AB
+ uint16_t all = 0; //Arduino uses Little Endian so, if all=ABCD then in memory it's CDAB (hex format)
+ uint8_t byt[2]; //then we get byt[0]=CD and byt[1]=AB (type punning with a union...)
+ #else //it must be IR_SMALLD_SIRC20
+ uint32_t all = 0; //if all=ABCDEF00 then in memory it's 00EFCDAB (hex format)
+ uint8_t byt[4]; //byt[0]=00; byt[1]=EF; byt[2]=CD; byt[3]=AB
#endif
} irSignal;
- static uint8_t state=0;
-
+ static uint8_t state = 0;
+
DBG_PRINT_STATE(state);
DBG_RESTART_TIMER();
-
+
duration = micros() - startTime;
startTime = micros();
DBG_PRINTLN_DUR(duration)
-
- switch(state){ //asynchronous (event-driven) Finite State Machine
- case 0: //Standby
- if((duration > c_GapMin)){ //only starts after a GAP without signals
- bitCount=0;
- state=1; //leading pulse detected
+
+ switch (state) { //asynchronous (event-driven) Finite State Machine
+ case 0: //Standby
+ if (duration > c_GapMin) { //only starts after a GAP without signals
+ bitCount = 0;
+ state = 1; //leading pulse detected
}
break;
-
+
case 1: //Receiving
- if(duration < c_M0min || duration > c_M1max) state=0; //not a Mark duration
- else { //its M0 or M1
+ if (duration < c_M0min || duration > c_M1max) state = 0; //not a Mark duration
+ else { //its M0 or M1
irSignal.all >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
bitCount++;
- if(duration >= c_M1min){ //it's a bit 1 mark, change Most Significant bit to 1
+ if (duration >= c_M1min) { //it's a bit 1 mark, change Most Significant bit to 1
#if (IR_SMALLD_SIRC12 || IR_SMALLD_SIRC15)
irSignal.byt[1] |= 0x80;
#else //IR_SMALLD_SIRC20 uses 4 bytes
irSignal.byt[3] |= 0x80;
#endif
}
- if (bitCount==c_NumberOfBits) { //all bits received
- if (!_irCopyingData){ //if not interrupting a copy, decode signal (else, discard it)
+ if (bitCount == c_NumberOfBits) { //all bits received
+ if (!_irCopyingData) { //if not interrupting a copy, decode signal (else, discard it)
#if defined(IR_SMALLD_SIRC12)
- irSignal.all >>= 3; //adjust address in the high byte (SIRC15/20 do not need this)
+ irSignal.all >>= 3; //adjust address in the high byte (SIRC15/20 don't need this)
#endif
#if (IR_SMALLD_SIRC12 || IR_SMALLD_SIRC15)
- irSignal.byt[0] >>= 1; //adjust command in the low byte
- _irData.addr = irSignal.byt[1]; //Little-Endian puts high byte in the array's second position
+ irSignal.byt[0] >>= 1; //adjust command in the low byte
+ _irData.addr = irSignal.byt[1]; //Little-Endian puts high byte in the array's second position
_irData.cmd = irSignal.byt[0];
- #else // it's IR_SMALLD_SIRC20
+ #else // it's IR_SMALLD_SIRC20
_irData.ext = irSignal.byt[3];
- irSignal.byt[3]=0;
+ irSignal.byt[3] = 0;
irSignal.all >>= 3;
irSignal.byt[1] >>= 1;
_irData.addr = irSignal.byt[2];
_irData.cmd = irSignal.byt[1];
#endif
- _irDataAvailable=true;
+ _irDataAvailable = true;
}
state = 0; //done
- }
- else state = 1; //continue Receiving
+ } // else state = 1; //continue Receiving //(redundant assignment)
}
break;
}
diff --git a/src/IRsmallD_SIRC_multi.h b/src/IRsmallD_SIRC_multi.h
index 7af9377..58423cb 100644
--- a/src/IRsmallD_SIRC_multi.h
+++ b/src/IRsmallD_SIRC_multi.h
@@ -3,14 +3,13 @@
* This file is part of the IRsmallDecoder library for Arduino
* Copyright (c) 2020 Luis Carvalho
*
- *
- * Additional Features:
- * --------------------
+ *
+ * Additional Features (not included in the basic versions):
+ * ---------------------------------------------------------
* - Bit number auto-detection (12, 15 or 20 bits);
* - Triple frame verification;
* - KeyHeld check/delay.
*
- *
* Protocol specifications:
* ------------------------
* Modulation type: pulse width.
@@ -43,9 +42,7 @@
*/
-
-
-void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (actually it's on RISE)
+void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (but it's actually RISING @ ReceiverOutput)
// SIRC timings' thresholds in micro secs:
//Minimum standard Gap length = (75-(4+3*20))*600 --> assuming 20 bit 1s, which has the smallest gapMin
//Maximum standard Gap length = (75-(4+2*12))*600 --> assuming 12 bit 0s, which has the biggest gapMax
@@ -58,23 +55,23 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (ac
const uint16_t c_M1min = 1500; // = 1800 - 300
//const uint16_t c_M0max = 1499; // = 1200 + 300 - 1 //unused const
const uint16_t c_M0min = 900; // = 1200 - 300 (it could be less)
- //number of initial repeats to be ignored:
+ //number of initial repeats to be ignored:
const uint8_t c_RptCount = 5;
// FSM variables:
static uint32_t duration;
static uint8_t bitCount;
- static unsigned long startTime=-1;//FFFF...
- static union {//received bits are stored in reversed order (11000101... -> ...10100011)
- uint32_t all=0; // if all=ABCDEF00 then in memory it's 00EFCDAB (hex format)
- uint8_t byt[4]; // byt[0]=00; byt[1]=EF; byt[2]=CD; byt[3]=AB
+ static unsigned long startTime=-1; //FFFF...
+ static union { // received bits are stored in reversed order (11000101... -> ...10100011)
+ uint32_t all = 0; // if all=ABCDEF00 then in memory it's 00EFCDAB (hex format)
+ uint8_t byt[4]; // byt[0]=00; byt[1]=EF; byt[2]=CD; byt[3]=AB
} irSignal;
- static uint8_t state=0;
+ static uint8_t state = 0;
static uint8_t frameCount;
- static uint8_t firstBitCount=20;
+ static uint8_t firstBitCount = 20;
static uint32_t firstCode;
- static bool possiblyHeld=false;
- static uint8_t repeatCount=0;
+ static bool possiblyHeld = false;
+ static uint8_t repeatCount = 0;
DBG_PRINT_STATE(state);
DBG_RESTART_TIMER();
@@ -83,66 +80,59 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (ac
startTime = micros();
DBG_PRINTLN_DUR(duration)
- switch(state){ //asynchronous (event-driven) Finite State Machine
- case 0: //Standby
- if (duration >= c_GapMin){ //only starts after a GAP without signals
+ switch (state) { //asynchronous (event-driven) Finite State Machine
+ case 0: //Standby
+ if (duration >= c_GapMin) { //only starts after a GAP without signals
if (duration > c_GapMax) possiblyHeld = false;
- bitCount=0;
- irSignal.all=0;
- frameCount=1;
- state=1;
- }
- else possiblyHeld = false;
+ bitCount = 0;
+ irSignal.all = 0;
+ frameCount = 1;
+ state = 1;
+ } else possiblyHeld = false;
break;
case 1: //Receiving
- if(duration < c_M0min || duration > c_M1max){ //not a Bit Mark duration
- if (frameCount==3) state=0; //duration error in frame 3
- else { //not a Bit Mark duration, possibly a Gap @ frame 1 or frame 2
- if(duration < c_GapMin || duration > c_GapMax) state=0; //duration error
- else { //it's a Gap at the end of frame 1 or frame 2
- if (frameCount==1){ //frame 1 received
- if (bitCount==12 || bitCount==15 || bitCount==20) { //bitCount confirmed, prep for frame 2
- firstBitCount=bitCount;
+ if (duration < c_M0min || duration > c_M1max) { //not a Bit Mark duration
+ if (frameCount == 3) state = 0; //duration error in frame 3
+ else { //not a Bit Mark duration, possibly a Gap @ frame 1 or frame 2
+ if (duration < c_GapMin || duration > c_GapMax) state = 0; //duration error
+ else { //it's a Gap at the end of frame 1 or frame 2
+ if (frameCount == 1) { //frame 1 received
+ if (bitCount == 12 || bitCount == 15 || bitCount == 20) { //bitCount confirmed, prep for frame 2
+ firstBitCount = bitCount;
bitCount = 0;
firstCode = irSignal.all;
irSignal.all = 0;
frameCount = 2;
- }
- else state=0; //bitCount error
- }
- else{ //frame 2 received
- if (irSignal.all == firstCode){ //code OK, prep for frame 3
+ } else state = 0; //bitCount error
+ } else { //frame 2 received
+ if (irSignal.all == firstCode) { //code OK, prep for frame 3
bitCount = 0;
irSignal.all = 0;
frameCount = 3;
- }
- else state=0; //code error @ end of frame 2
+ } else state = 0; //code error @ end of frame 2
}
}
}
- }
- else {//it's a Bit Mark duration
- irSignal.all >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
- if(duration >= c_M1min) irSignal.byt[3] |= 0x80; //it's M1, change MSB to 1
+ } else { //it's a Bit Mark duration
+ irSignal.all >>= 1; //push a 0 from left to right (will be left at 0 if it's M0)
+ if (duration >= c_M1min) irSignal.byt[3] |= 0x80; //it's M1, change MSB to 1
bitCount++;
- if (frameCount==3){
- if (bitCount==firstBitCount) { //all bits, of frame 3, received
- if (!_irCopyingData && (irSignal.all == firstCode)){ //if not interrupting a copy and code OK, decode (else, discard it)
- if (bitCount==12){
+ if (frameCount == 3) {
+ if (bitCount == firstBitCount) { //all bits, of frame 3, received
+ if (!_irCopyingData && (irSignal.all == firstCode)) { //if not interrupting a copy and code OK, decode (else, discard it)
+ if (bitCount == 12) {
irSignal.all >>= 3;
irSignal.byt[2] >>= 1;
_irData.addr = irSignal.byt[3];
_irData.cmd = irSignal.byt[2];
_irData.ext = 0;
- }
- else if (bitCount==15){
+ } else if (bitCount == 15) {
irSignal.byt[2] >>= 1;
_irData.addr = irSignal.byt[3];
_irData.cmd = irSignal.byt[2];
_irData.ext = 0;
- }
- else { // it's 20 bits
+ } else { // it's 20 bits
_irData.ext = irSignal.byt[3];
irSignal.byt[3] = 0;
irSignal.all >>= 3;
@@ -151,21 +141,20 @@ void IRsmallDecoder::irISR() { //executed every time the IR signal goes down (ac
_irData.cmd = irSignal.byt[1];
}
_irData.keyHeld = false;
- _irDataAvailable= true;
- possiblyHeld = true; //will remain true if the next gap is OK
+ _irDataAvailable = true;
+ possiblyHeld = true; //will remain true if the next gap is OK
}
- repeatCount=0;
- state = 0; //done
- } //else continue Receiving frame 3 (no need to set state)
- }
- else { //frame 1 or 2. Check if key held
- if (frameCount==1 && possiblyHeld && bitCount==firstBitCount && irSignal.all==firstCode){ //keyHeld
- if (repeatCount < c_RptCount) repeatCount++; //first repetitions will be ignored
- else if (!_irCopyingData) { //if not interrupting a copy then keyHeld...
+ repeatCount = 0;
+ state = 0; //done
+ } //else continue Receiving frame 3 (no need to set state)
+ } else { //it's frame 1 or 2. Check if key held
+ if (frameCount == 1 && possiblyHeld && bitCount == firstBitCount && irSignal.all == firstCode) { //keyHeld
+ if (repeatCount < c_RptCount) repeatCount++; //first repetitions will be ignored
+ else if (!_irCopyingData) { //if not interrupting a copy then keyHeld...
_irData.keyHeld = true;
- _irDataAvailable= true;
+ _irDataAvailable = true;
}
- state=0;
+ state = 0;
}
}
}
diff --git a/src/IRsmallDecoder.h b/src/IRsmallDecoder.h
index 5801d19..60d3d11 100644
--- a/src/IRsmallDecoder.h
+++ b/src/IRsmallDecoder.h
@@ -1,4 +1,4 @@
-/* IRsmallDecoder v1.1.0
+/* IRsmallDecoder v1.2.0
*
* This is a Library for Arduino and it allows the reception and decoding of infrared signals from remote controls.
* It uses small, fast and reliable decoders that don't require timers.
@@ -24,8 +24,8 @@
*
* - RC5 works for both normal and extended versions;
* - SIRC12, SIRC15 and SIRC20 use a basic (smaller and faster) implementation but without some features...
- * - SIRC handles SIRC 12, 15 and 20 bits, by taking advantage of the fact that most Sony remotes;
- * send three frames each time one button is pressed. It uses triple frame verification and checks if keyHeld;
+ * - SIRC handles SIRC 12, 15 and 20 bits, by taking advantage of the fact that most Sony remotes send
+ * three frames each time one button is pressed. It uses triple frame verification and checks if keyHeld;
*/
#ifndef IRsmallDecoder_h
@@ -43,7 +43,9 @@
#include "IRsmallDProtocolStructs.h"
#include "IRsmallDDebug.h"
-// IR_ISR_MODE *****************************************************************
+
+// ****************************************************************************
+// IR_ISR_MODE definition based on protocol:
#if IR_SMALLD_NEC || IR_SMALLD_NECx || IR_SMALLD_SAMSUNG || IR_SMALLD_SAMSUNG32
#define IR_ISR_MODE FALLING
#elif IR_SMALLD_SIRC || IR_SMALLD_SIRC12 || IR_SMALLD_SIRC15 || IR_SMALLD_SIRC20
@@ -54,56 +56,112 @@
#error IR_ISR_MODE not defined.
#endif
-//*****************************************************************************
+
+// ****************************************************************************
+// Decoder class's forward declaration/definition:
+/** InfraRed Signals Decoder's Class */
class IRsmallDecoder {
private:
- static volatile bool _irDataAvailable; //will be updated by the ISR
- static volatile irSmallD_t _irData; //will be updated by the ISR
- static bool _irCopyingData; //not changed by the ISR, no need for volatile
static void irISR();
+ static volatile bool _irDataAvailable; //will be updated by the ISR
+ static volatile irSmallD_t _irData; //will be updated by the ISR
+ static bool _irCopyingData; //used by the ISR but not changed by it, no need for volatile
+ uint8_t _irInterruptNum; //used by enable/disable Decoder methods
public:
IRsmallDecoder(uint8_t interruptPin);
+ void disable();
+ void enable();
bool dataAvailable(irSmallD_t &irData);
+ bool dataAvailable();
};
-//*****************************************************************************
+
+// ****************************************************************************
//static variables from a class must be re-declared/initialized
-//outside the class' forward declaration/definition (usually on the cpp file not the header)
+//outside the class' forward declaration/definition (usually in the cpp file not the header)
volatile bool IRsmallDecoder::_irDataAvailable = false;
volatile irSmallD_t IRsmallDecoder::_irData;
-bool IRsmallDecoder::_irCopyingData = false; //to avoid volatile _irData corruption by the ISR
+bool IRsmallDecoder::_irCopyingData = false; //to avoid volatile _irData corruption by the ISR
-IRsmallDecoder::IRsmallDecoder(uint8_t interruptPin){
- pinMode(interruptPin,INPUT_PULLUP); //active low
+
+// ****************************************************************************
+// Decoder's Methods Implementation
+/**
+ * IRsmallDecoder object costructor
+ *
+ * @param interruptPin is the digital pin where the IR receiver is connected. That pin must be is usable for external interrupts
+ */
+IRsmallDecoder::IRsmallDecoder(uint8_t interruptPin) {
+ pinMode(interruptPin,INPUT_PULLUP); //active low
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || \
defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
- attachInterrupt(0, irISR, IR_ISR_MODE);
- #else
- attachInterrupt(digitalPinToInterrupt(interruptPin), irISR, IR_ISR_MODE);
+ _irInterruptNum=0;
+ #else
+ _irInterruptNum = digitalPinToInterrupt(interruptPin);
#endif
+ attachInterrupt(_irInterruptNum, irISR, IR_ISR_MODE);
+}
+
+
+/**
+ * Enables the decoder by reattaching the ISR to the hardware interrupt
+ */
+void IRsmallDecoder::enable() {
+ attachInterrupt(_irInterruptNum, irISR, IR_ISR_MODE); //interrupt flag may already be set
+ //if so, ISR will be immediately executed and the FSM jumps out of standby state
+ this->irISR(); // two consecutive calls will place any of the FSMs in standby
+ this->irISR();
+}
+
+
+/**
+ * Disables the decoder without interfering with other interrupts
+ */
+void IRsmallDecoder::disable() {
+ detachInterrupt(_irInterruptNum);
}
-bool IRsmallDecoder::dataAvailable(irSmallD_t &irData){
+
+/**
+ * Informs if there is new decoded data and retrieves it if so.
+ *
+ * @param irData If there is new data available, it is "moved" to this data structure.
+ * @return true if new data was decoded and retrieved; false if not.
+ */
+bool IRsmallDecoder::dataAvailable(irSmallD_t &irData) {
if (_irDataAvailable) {
- _irCopyingData=true; //Let the ISR know that it cannot change the data while it's being copied
- memcpy(&irData, (void*)&_irData, sizeof(_irData));
- _irCopyingData=false; //an ATOMIC_BLOCK would be better, but it's not supported on many boards
- _irDataAvailable=false;
+ _irCopyingData = true; //Let the ISR know that it cannot change the data while it's being copied
+ memcpy(&irData, (void*)&_irData, sizeof(_irData));
+ _irDataAvailable = false;
+ _irCopyingData = false; //an ATOMIC_BLOCK would be better, but it's not supported on many boards
return true;
- }
- else return false;
+ } else return false;
}
-//*****************************************************************************
+/**
+ * Informs if there is new decoded data and DISCARDS it if so.
+ *
+ * @return true if new data was decoded; false if not.
+ */
+bool IRsmallDecoder::dataAvailable() {
+ if (_irDataAvailable) {
+ _irDataAvailable = false;
+ return true;
+ } else return false;
+}
+
+
+// ----------------------------------------------------------------------------
// Computed GOTOs (labels as values) FSM control:
#define FSM_INITIALIZE(initialState) static void* fsm_state = &&initialState
#define FSM_SWITCH() goto *fsm_state; while(false)
#define FSM_NEXT(nextState) fsm_state = &&nextState
#define FSM_DIRECTJUMP(label) goto label
-//*****************************************************************************
+
+// ----------------------------------------------------------------------------
// Conditional inclusion of protocol specific ISR implementations:
#if IR_SMALLD_NEC || IR_SMALLD_NECx
#include "IRsmallD_NEC.h"