LG2 protocol
This commit is contained in:
parent
0b16ba4fdb
commit
39eec4c5ca
39
README.md
39
README.md
|
@ -1,7 +1,7 @@
|
|||
# IRremote Arduino Library
|
||||
Available as Arduino library "IRremote"
|
||||
|
||||
### [Version 3.3.1](https://github.com/Arduino-IRremote/Arduino-IRremote/archive/master.zip) - work in progress
|
||||
### [Version 3.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/archive/master.zip) - work in progress
|
||||
|
||||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
||||
[![Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremote/Arduino-IRremote/latest)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master)
|
||||
|
@ -43,13 +43,11 @@ This is a quite old but maybe useful wiki for this library.
|
|||
- Ability to generate a non PWM signal to just simulate an active low receiver signal for direct connect to existent receiving devices without using IR.
|
||||
- Easy configuration of protocols required, directly in your [source code[(https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L18-L34). This reduces the memory footprint and increases decoding time.
|
||||
|
||||
# Converting your program to the 3.1 version
|
||||
This must be done also for all versions > 3.0.1 if `USE_NO_SEND_PWM` is defined.<br/>
|
||||
Starting with this version, **the generation of PWM is done by software**, thus saving the hardware timer and **enabling arbitrary output pins**.<br/>
|
||||
Therefore you must change all `IrSender.begin(true);` by `IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);`.
|
||||
If you use a core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, if you get false error messages regarding begin() during compilation.
|
||||
|
||||
# Converting your 2.x program to the 3.x version
|
||||
Starting with the 3.1 version, **the generation of PWM is done by software**, thus saving the hardware timer and **enabling arbitrary output pins**.<br/>
|
||||
If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, if you get false error messages regarding begin() during compilation.
|
||||
|
||||
- Now there is an **IRreceiver** and **IRsender** object like the well known Arduino **Serial** object.
|
||||
- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program, and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver`.
|
||||
- Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar.
|
||||
|
@ -59,8 +57,9 @@ If you use a core that does not use the `-flto` flag for compile, you can activa
|
|||
- Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.h#L126).
|
||||
- Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`.
|
||||
|
||||
# Running your 2.x program with the 3.x library version
|
||||
If you program is like:
|
||||
# Do not convert your 2.x program and use the 3.x library version
|
||||
The 3.x versions try to be backwards compatible, so you can easily run your old examples. But some functions like e.g. `sendNEC()` -see below- could not made backwards compatible, so in this cases you must revisit your code and adapt it to the 3.x library.<br/>
|
||||
If you program look like:
|
||||
```
|
||||
IRrecv irrecv(RECV_PIN);
|
||||
decode_results results;
|
||||
|
@ -80,17 +79,19 @@ void loop() {
|
|||
...
|
||||
}
|
||||
```
|
||||
it should run on the 3.1.1 version as before. The following decoders are available: Denon, JVC, LG, NEC, Panasonic, RC5, RC6, Samsung, Sony.
|
||||
The `results.value` is set by the decoders for **NEC, Panasonic, Sony, Samsung and JVC** as MSB first like in 2.x.<br/>
|
||||
it runs on the 3.x version as before. But only the following decoders are available then: Denon, JVC, LG, NEC, Panasonic, RC5, RC6, Samsung, Sony.
|
||||
The `results.value` is set by the decoders for **NEC, Panasonic, Sony, Samsung and JVC** as MSB first like in 2.x!<br/>
|
||||
- The old functions `sendNEC()` and `sendJVC()` are deprecated and renamed to `sendNECMSB()` and `sendJVCMSB()` to make it clearer that they send data with MSB first, which is not the standard for NEC and JVC. Use them to send your **old MSB-first 32 bit IR data codes**.
|
||||
In the new version you will send NEC commands not by 32 bit codes but by a (constant) 8 bit address and an 8 bit command.
|
||||
In the new version you will send NEC (and other) commands not by 32 bit codes but by a (constant) 8 bit address and an 8 bit command.
|
||||
|
||||
# Convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes
|
||||
The new decoders for **NEC, Panasonic, Sony, Samsung and JVC** `IrReceiver.decodedIRData.decodedRawData` is now LSB-first, as the definition of these protocols suggests!
|
||||
To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte or write it as one binary string and reverse/mirror it.<br/>
|
||||
Example:<br/>
|
||||
0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.<br/>
|
||||
0xCB340102 is binary 11001011001101000000000100000010.<br/>
|
||||
# How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes
|
||||
For the new decoders for **NEC, Panasonic, Sony, Samsung and JVC**, the result `IrReceiver.decodedIRData.decodedRawData` is now **LSB-first**, as the definition of these protocols suggests!<br/>
|
||||
To convert one into the other, you must reverse the byte/nibble positions and then reverse all bit positions of each byte/nibble or write it as one binary string and reverse/mirror it.<br/><br/>
|
||||
Example:
|
||||
- 0xCB340102 byte reverse -> 02 01 34 CB. Bit reverse of byte -> 40 80 2C D3.
|
||||
- 0xCB340102 nibble reverse -> 201043BC. Bit reverse of nibble -> 40802CD3.<br/>
|
||||
Nibble reverse map: | 1->8 | 2->4 | 3->C | 4->2 | 5->A | 6->6 | 7->E | 8->1 | 9->9 | A->5 | B->D | C->3 | D->B | E->7 | F->F |
|
||||
- 0xCB340102 is binary 11001011001101000000000100000010.<br/>
|
||||
0x40802CD3 is binary 01000000100000000010110011010011.<br/>
|
||||
If you read the first binary sequence backwards (right to left), you get the second sequence.
|
||||
|
||||
|
@ -165,7 +166,7 @@ MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/proj
|
|||
Click on the receiver while simulation is running to specify individual IR codes.
|
||||
|
||||
### IRDispatcherDemo
|
||||
Framework for calling different functions for different IR codes.
|
||||
Framework for calling different functions of **your program** for different IR codes.
|
||||
|
||||
### IRrelay
|
||||
Control a relay (connected to an output pin) with your remote.
|
||||
|
@ -178,7 +179,7 @@ This example analyzes the signal delivered by your IR receiver module.
|
|||
Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.<br/>
|
||||
It also computes the MARK_EXCESS_MICROS value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.<br/>
|
||||
It can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299033930562011656).
|
||||
Click on the receiver while simulation is running to specify individual IR codes.
|
||||
Click on the receiver while simulation is running to specify individual NEC IR codes.
|
||||
|
||||
# Compile options / macros for this library
|
||||
To customize the library to different requirements, there are some compile options / macros available.<br/>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Changelog
|
||||
The latest version may not be released!
|
||||
## 3.3.1
|
||||
## 3.4.0
|
||||
- Added LG2 protocol.
|
||||
|
||||
## 3.3.0
|
||||
- Fix errors if LED_BUILTIN is not defined.
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
// to compensate for the signal forming of different IR receiver modules.
|
||||
#define MARK_EXCESS_MICROS 20 // 20 is recommended for the cheap VS1838 modules
|
||||
|
||||
//#define RECORD_GAP_MICROS 12000 // Activate it for some LG air conditioner protocols
|
||||
#define RECORD_GAP_MICROS 12000 // Activate it for some LG air conditioner protocols
|
||||
|
||||
/*
|
||||
* First define macros for input and output pin etc.
|
||||
|
@ -111,13 +111,14 @@ void setup() {
|
|||
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program space of ATtiny85 etc.
|
||||
Serial.print(F("Debug button pin is "));
|
||||
Serial.println(DEBUG_BUTTON_PIN);
|
||||
#endif
|
||||
|
||||
// infos for receive
|
||||
Serial.print(RECORD_GAP_MICROS);
|
||||
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
|
||||
Serial.print(MARK_EXCESS_MICROS);
|
||||
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
*/
|
||||
#include <Arduino.h>
|
||||
|
||||
#define USE_LG2_PROTOCOL // Try it if you do not have success with the default LG protocol
|
||||
|
||||
/*
|
||||
* Define macros for input and output pin etc.
|
||||
*/
|
||||
|
@ -59,13 +61,32 @@ uint8_t ACRequestedTemperature = 25; // temperature : 18 ~ 30
|
|||
const int AC_FAN_TOWER[3] = { 0, 4, 6 };
|
||||
const int AC_FAN_WALL[4] = { 0, 2, 4, 5 }; // 5 -> cycle
|
||||
|
||||
// from https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h
|
||||
union LGProtocol{
|
||||
uint32_t raw; ///< The state of the IR remote in IR code form.
|
||||
struct {
|
||||
uint32_t Sum :4;
|
||||
uint32_t Fan :3;
|
||||
uint32_t FanExt :1;
|
||||
uint32_t Temp :4;
|
||||
uint32_t Mode :3;
|
||||
uint32_t :3;
|
||||
uint32_t Power :2;
|
||||
uint32_t Signature :8; /*=0x88*/
|
||||
};
|
||||
};
|
||||
|
||||
void ACSendCode(uint16_t aCommand) {
|
||||
Serial.print(F("Send code="));
|
||||
Serial.print(aCommand, HEX);
|
||||
Serial.print(F(" | "));
|
||||
Serial.println(aCommand, BIN);
|
||||
Serial.flush();
|
||||
IrSender.sendLG((uint8_t) 0x88, aCommand, 0);
|
||||
#if defined(USE_LG2_PROTOCOL)
|
||||
IrSender.sendLG((uint8_t) 0x88, aCommand, 0, true);
|
||||
#else
|
||||
IrSender.sendLG((uint8_t) 0x88, aCommand, 0, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sendCommand(uint8_t aTemperature, uint8_t aFanIntensity) {
|
||||
|
@ -81,7 +102,7 @@ void sendCommand(uint8_t aTemperature, uint8_t aFanIntensity) {
|
|||
// heating
|
||||
tCommand.UByte.HighByte = 0x4; // maybe cooling is 0x08????
|
||||
}
|
||||
tCommand.UByte.LowByte = ((aTemperature - 15) << 4); // 18 -> 3, 30 -> F
|
||||
tCommand.UByte.LowByte = ((aTemperature - 15) << 4); // 16 -> 0, 18 -> 3, 30 -> F
|
||||
|
||||
if (ACIsWallType) {
|
||||
tCommand.UByte.LowByte |= AC_FAN_WALL[aFanIntensity];
|
||||
|
@ -115,7 +136,7 @@ void sendAirSwing(bool aSwing) {
|
|||
|
||||
void SendPowerDown() {
|
||||
Serial.println(F("Send power down"));
|
||||
IrSender.sendLGRaw(0x88C0051);
|
||||
ACSendCode(0xC005);
|
||||
ACPowerIsOn = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#define DECODE_RC5
|
||||
#define DECODE_RC6
|
||||
#define DECODE_PANASONIC // the same as DECODE_KASEIKYO
|
||||
#define DECODE_LG
|
||||
|
||||
#define DECODE_DISTANCE // universal decoder for pulse width or pulse distance protocols
|
||||
#define DECODE_HASH // special decoder for all protocols
|
||||
|
@ -60,6 +59,7 @@
|
|||
|
||||
#if FLASHEND >= 0x7FFF // For 32k flash or more, like ATmega328
|
||||
#define DECODE_SAMSUNG
|
||||
#define DECODE_LG
|
||||
|
||||
#define DECODE_BOSEWAVE
|
||||
#define DECODE_LEGO_PF
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"type": "git",
|
||||
"url": "https://github.com/z3t0/Arduino-IRremote.git"
|
||||
},
|
||||
"version": "3.3.0",
|
||||
"version": "3.4.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"],
|
||||
"authors" :
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
name=IRremote
|
||||
version=3.3.0
|
||||
version=3.4.0
|
||||
author=shirriff, z3t0 <zetoslab@gmail.com>, ArminJo
|
||||
maintainer=Armin Joachimsmeyer <armin.arduino@gmail.com>
|
||||
sentence=Send and receive infrared signals with multiple protocols
|
||||
paragraph=Currently included protocols: Denon / Sharp, JVC, LG, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BoseWave, Lego, Whynter, MagiQuest.<br/><br/><b>New: </b><a href="https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-program-to-the-31-version">3.x upgrade instructions</a><br/>Added universal decoder for pulse width or pulse distance protocols.<br/>For all 3.x: Generation of PWM is now done by software by default, thus saving the hardware timer and enabling abitrary output pins. Removed decode_results results. Renamed most irparams_struct values. The macros FEEDBACK_LED, SYSCLOCK, SENDPIN_ON and SENDPIN_OFF are not longer used / evaluated. Major refactoring of CPU dependent and feedback LED code. Support for more CPU's.<br/>
|
||||
paragraph=Currently included protocols: Denon / Sharp, JVC, LG, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BoseWave, Lego, Whynter, MagiQuest.<br/><br/><b>New: </b><a href="https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-program-to-the-31-version">3.x upgrade instructions</a><br/>Added LG2 protocol.<br/>For all 3.x: Generation of PWM is now done by software by default, thus saving the hardware timer and enabling abitrary output pins. Removed decode_results results. Renamed most irparams_struct values. The macros FEEDBACK_LED, SYSCLOCK, SENDPIN_ON and SENDPIN_OFF are not longer used / evaluated. Major refactoring of CPU dependent and feedback LED code. Support for more CPU's.<br/>
|
||||
category=Communication
|
||||
url=https://github.com/Arduino-IRremote/Arduino-IRremote
|
||||
architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 336 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -44,6 +44,7 @@ typedef enum {
|
|||
DISH,
|
||||
JVC,
|
||||
LG,
|
||||
LG2,
|
||||
NEC,
|
||||
PANASONIC,
|
||||
KASEIKYO,
|
||||
|
|
|
@ -1174,6 +1174,9 @@ const __FlashStringHelper* getProtocolString(decode_type_t aProtocol) {
|
|||
case LG:
|
||||
return (F("LG"));
|
||||
break;
|
||||
case LG2:
|
||||
return (F("LG2"));
|
||||
break;
|
||||
case NEC:
|
||||
return (F("NEC"));
|
||||
break;
|
||||
|
|
|
@ -129,7 +129,7 @@
|
|||
*/
|
||||
#if !defined(RECORD_GAP_MICROS)
|
||||
// To change this value, you simply can add a line #define "RECORD_GAP_MICROS <My_new_value>" in your ino file before the line "#include <IRremote.h>"
|
||||
#define RECORD_GAP_MICROS 5000 // FREDRICH28AC header space is 9700, NEC header space is 4500
|
||||
#define RECORD_GAP_MICROS 5000 // FREDRICH28AC / LG2 header space is 9700, NEC header space is 4500
|
||||
#endif
|
||||
/**
|
||||
* Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value.
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#define MARK 1
|
||||
#define SPACE 0
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
|
||||
//#define TRACE // Activate this for more debug output.
|
||||
|
||||
/**
|
||||
* For better readability of code
|
||||
*/
|
||||
|
@ -85,8 +88,6 @@ struct irparams_struct {
|
|||
uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command
|
||||
};
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
|
||||
//#define TRACE // Activate this for more debug output.
|
||||
/*
|
||||
* Debug directives
|
||||
*/
|
||||
|
@ -430,9 +431,10 @@ public:
|
|||
__attribute__ ((deprecated ("Please use sendDenon(aAddress, aCommand, aNumberOfRepeats).")));
|
||||
void sendJVC(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);
|
||||
|
||||
void sendLGRepeat();
|
||||
void sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
|
||||
void sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false);
|
||||
void sendLGRepeat(bool aUseLG2Protocol = false);
|
||||
void sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false, bool aUseLG2Protocol =
|
||||
false);
|
||||
void sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false, bool aUseLG2Protocol = false);
|
||||
|
||||
void sendNECRepeat();
|
||||
void sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
#define DURATION_ARRAY_SIZE 50
|
||||
|
||||
// Switch the decoding according to your needs
|
||||
#define MSB_LSB_DECODING PROTOCOL_IS_LSB_FIRST // this results in the same decodedRawData as e.g. the NEC and Kaseikyo/Panasonic decoder
|
||||
//#define MSB_LSB_DECODING PROTOCOL_IS_MSB_FIRST // this resembles the JVC, Denon
|
||||
#define DISTANCE_DO_MSB_DECODING PROTOCOL_IS_LSB_FIRST // this results in the same decodedRawData as e.g. the NEC and Kaseikyo/Panasonic decoder
|
||||
//#define DISTANCE_DO_MSB_DECODING PROTOCOL_IS_MSB_FIRST // this resembles the JVC, Denon
|
||||
|
||||
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
|
||||
#include "IRremoteInt.h" // evaluates the DEBUG for DEBUG_PRINT
|
||||
|
@ -95,7 +95,11 @@ bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIn
|
|||
}
|
||||
|
||||
/*
|
||||
* First analyze all spaces and marks
|
||||
* Try to decode a pulse width or pulse distance protocol.
|
||||
* 1. analyze all space and mark length
|
||||
* 2. decide if we have an pulse width or distance protocol
|
||||
* 3. try to decode with the mark and space data found in step 1.
|
||||
* No data and address, only raw data as result.
|
||||
*/
|
||||
bool IRrecv::decodeDistance() {
|
||||
uint8_t tDurationArray[DURATION_ARRAY_SIZE];
|
||||
|
@ -178,6 +182,9 @@ bool IRrecv::decodeDistance() {
|
|||
tStartIndex = decodedIRData.rawDataPtr->rawlen - 65;
|
||||
}
|
||||
|
||||
/*
|
||||
* decide, if we have an pulse width or distance protocol
|
||||
*/
|
||||
if (tSpaceTicksLong == 0) {
|
||||
if (tMarkTicksLong == 0) {
|
||||
DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
|
@ -186,12 +193,12 @@ bool IRrecv::decodeDistance() {
|
|||
}
|
||||
// // check if last bit can be decoded as data or not, in this case take it as a stop bit
|
||||
// if (decodePulseWidthData(1, decodedIRData.rawDataPtr->rawlen - 3, tMarkTicksLong * MICROS_PER_TICK,
|
||||
// tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, MSB_LSB_DECODING)) {
|
||||
// tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
// tNumberOfBits++;
|
||||
// }
|
||||
// decode without leading start bit. Currently only seen for sony protocol
|
||||
// decode without leading start bit. Currently only seen for sony protocol
|
||||
if (!decodePulseWidthData(tNumberOfBits, tStartIndex, tMarkTicksLong * MICROS_PER_TICK,
|
||||
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, MSB_LSB_DECODING)) {
|
||||
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
DEBUG_PRINT(F("PULSE_WIDTH: "));
|
||||
DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
|
@ -209,13 +216,13 @@ bool IRrecv::decodeDistance() {
|
|||
} else {
|
||||
// // check if last bit can be decoded as data or not, in this case take it as a stop bit
|
||||
// if (decodePulseDistanceData(1, decodedIRData.rawDataPtr->rawlen - 3, tMarkTicksShort * MICROS_PER_TICK,
|
||||
// tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, MSB_LSB_DECODING)) {
|
||||
// tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
// Serial.print(F("tNumberOfBits++ "));
|
||||
// tNumberOfBits++;
|
||||
// }
|
||||
|
||||
if (!decodePulseDistanceData(tNumberOfBits, tStartIndex, tMarkTicksShort * MICROS_PER_TICK,
|
||||
tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, MSB_LSB_DECODING)) {
|
||||
tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
|
||||
DEBUG_PRINT(F("PULSE_DISTANCE: "));
|
||||
DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
|
@ -232,7 +239,7 @@ bool IRrecv::decodeDistance() {
|
|||
decodedIRData.protocol = PULSE_DISTANCE;
|
||||
}
|
||||
|
||||
if (MSB_LSB_DECODING) {
|
||||
if (DISTANCE_DO_MSB_DECODING) {
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,8 @@
|
|||
// see: https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/LGAirConditionerSendDemo
|
||||
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#LGAIR
|
||||
// MSB first, timing and repeat is like NEC but 28 data bits
|
||||
// MSB! first, 1 start bit + 8 bit address + 16 bit command + 4 bit parity + 1 stop bit.
|
||||
// In https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/755 we saw no key repetition
|
||||
// and a intended parity error, or something I do not understand.
|
||||
// MSB! first, 1 start bit + 8 bit address + 16 bit command + 4 bit checksum + 1 stop bit.
|
||||
// LG 32bit protocol is near identical to Samsung except for repeats.
|
||||
#define LG_ADDRESS_BITS 8
|
||||
#define LG_COMMAND_BITS 16
|
||||
#define LG_CHECKSUM_BITS 4
|
||||
|
@ -61,6 +60,11 @@
|
|||
#define LG_HEADER_MARK (16 * LG_UNIT) // 9000
|
||||
#define LG_HEADER_SPACE (8 * LG_UNIT) // 4500
|
||||
|
||||
// used for some LG air conditioners e.g. AKB75215403
|
||||
#define LG2_UNIT 500
|
||||
#define LG2_HEADER_MARK (6 * LG2_UNIT) // 3000
|
||||
#define LG2_HEADER_SPACE (19 * LG2_UNIT) // 9500
|
||||
|
||||
#define LG_BIT_MARK LG_UNIT
|
||||
#define LG_ONE_SPACE (3 * LG_UNIT) // 1690
|
||||
#define LG_ZERO_SPACE LG_UNIT
|
||||
|
@ -76,9 +80,13 @@
|
|||
* Send repeat
|
||||
* Repeat commands should be sent in a 110 ms raster.
|
||||
*/
|
||||
void IRsend::sendLGRepeat() {
|
||||
void IRsend::sendLGRepeat(bool aUseLG2Protocol) {
|
||||
enableIROut(38);
|
||||
mark(LG_HEADER_MARK);
|
||||
if (aUseLG2Protocol) {
|
||||
mark(LG2_HEADER_MARK);
|
||||
} else {
|
||||
mark(LG_HEADER_MARK);
|
||||
}
|
||||
space(LG_REPEAT_HEADER_SPACE);
|
||||
mark(LG_BIT_MARK);
|
||||
}
|
||||
|
@ -87,10 +95,11 @@ void IRsend::sendLGRepeat() {
|
|||
* Repeat commands should be sent in a 110 ms raster.
|
||||
* There is NO delay after the last sent repeat!
|
||||
*/
|
||||
void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
|
||||
void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat, bool aUseLG2Protocol) {
|
||||
uint32_t tRawData = ((uint32_t) aAddress << (LG_COMMAND_BITS + LG_CHECKSUM_BITS)) | ((uint32_t) aCommand << LG_CHECKSUM_BITS);
|
||||
/*
|
||||
* My guess of the checksum
|
||||
* My guess of the 4 bit checksum
|
||||
* Addition of all 4 nibbles of the 16 bit command
|
||||
*/
|
||||
uint8_t tChecksum = 0;
|
||||
uint16_t tTempForChecksum = aCommand;
|
||||
|
@ -99,13 +108,13 @@ void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfR
|
|||
tTempForChecksum >>= 4; // shift by a nibble
|
||||
}
|
||||
tRawData |= (tChecksum & 0xF);
|
||||
sendLGRaw(tRawData, aNumberOfRepeats, aIsRepeat);
|
||||
sendLGRaw(tRawData, aNumberOfRepeats, aIsRepeat, aUseLG2Protocol);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here you can put your raw data, even one with "wrong" parity
|
||||
* Here you can put your raw data, even one with "wrong" checksum
|
||||
*/
|
||||
void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
|
||||
void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aIsRepeat, bool aUseLG2Protocol) {
|
||||
if (aIsRepeat) {
|
||||
sendLGRepeat();
|
||||
return;
|
||||
|
@ -114,8 +123,13 @@ void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aI
|
|||
enableIROut(38);
|
||||
|
||||
// Header
|
||||
mark(LG_HEADER_MARK);
|
||||
space(LG_HEADER_SPACE);
|
||||
if (aUseLG2Protocol) {
|
||||
mark(LG2_HEADER_MARK);
|
||||
space(LG2_HEADER_SPACE);
|
||||
} else {
|
||||
mark(LG_HEADER_MARK);
|
||||
space(LG_HEADER_SPACE);
|
||||
}
|
||||
|
||||
// MSB first
|
||||
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, aRawData, LG_BITS, PROTOCOL_IS_MSB_FIRST,
|
||||
|
@ -129,7 +143,7 @@ void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aI
|
|||
delay((LG_REPEAT_PERIOD - LG_REPEAT_DURATION) / 1000);
|
||||
}
|
||||
// send repeat
|
||||
sendLGRepeat();
|
||||
sendLGRepeat(aUseLG2Protocol);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,8 +157,11 @@ void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aI
|
|||
* Last check stop bit
|
||||
*/
|
||||
bool IRrecv::decodeLG() {
|
||||
decode_type_t tProtocol = LG;
|
||||
uint16_t tHeaderSpace = LG_HEADER_SPACE;
|
||||
uint16_t tUnit = LG_UNIT;
|
||||
|
||||
// Check we have the right amount of data (60). The +4 is for initial gap, start bit mark and space + stop bit mark.
|
||||
// Check we have the right amount of data (60). The +4 is for initial gap, start bit mark and space + stop bit mark.
|
||||
if (decodedIRData.rawDataPtr->rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINT("Data length=");
|
||||
|
@ -153,12 +170,20 @@ bool IRrecv::decodeLG() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check header "mark" this must be done for repeat and data
|
||||
// Check header "mark" this must be done for repeat and data
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG_HEADER_MARK)) {
|
||||
return false;
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) {
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINTLN("Header mark is wrong");
|
||||
return false;
|
||||
} else {
|
||||
tProtocol = LG2;
|
||||
tHeaderSpace = LG2_HEADER_SPACE;
|
||||
tUnit = LG2_UNIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for repeat - here we have another header space length
|
||||
// Check for repeat - here we have another header space length
|
||||
if (decodedIRData.rawDataPtr->rawlen == 4) {
|
||||
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_REPEAT_HEADER_SPACE)
|
||||
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], LG_BIT_MARK)) {
|
||||
|
@ -168,30 +193,34 @@ bool IRrecv::decodeLG() {
|
|||
decodedIRData.protocol = lastDecodedProtocol;
|
||||
return true;
|
||||
}
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINT("Repeat header space is wrong");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check command header space
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_HEADER_SPACE)) {
|
||||
// Check command header space
|
||||
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], tHeaderSpace)) {
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINTLN(F("Header space length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!decodePulseDistanceData(LG_BITS, 3, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
// if (!decodePulseDistanceData(LG_BITS, 3, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
|
||||
if (!decodePulseDistanceData(LG_BITS, 3, tUnit, 3 * tUnit, tUnit, PROTOCOL_IS_MSB_FIRST)) { // costs 20 bytes program space, compared with using constants
|
||||
Serial.print("jgkjkj");
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINTLN(F("Decode failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LG_BITS)], LG_BIT_MARK)) {
|
||||
// Stop bit
|
||||
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LG_BITS)], tUnit)) {
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
// Success
|
||||
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
|
||||
decodedIRData.command = (decodedIRData.decodedRawData >> LG_CHECKSUM_BITS) & 0xFFFF;
|
||||
decodedIRData.address = decodedIRData.decodedRawData >> (LG_COMMAND_BITS + LG_CHECKSUM_BITS); // first 8 bit
|
||||
|
@ -205,7 +234,7 @@ bool IRrecv::decodeLG() {
|
|||
tChecksum += tTempForChecksum & 0xF; // add low nibble
|
||||
tTempForChecksum >>= 4; // shift by a nibble
|
||||
}
|
||||
// Parity check
|
||||
// Checksum check
|
||||
if ((tChecksum & 0xF) != (decodedIRData.decodedRawData & 0xF)) {
|
||||
DEBUG_PRINT(F("LG: "));
|
||||
DEBUG_PRINT("4 bit checksum is not correct. expected=0x");
|
||||
|
@ -217,7 +246,7 @@ bool IRrecv::decodeLG() {
|
|||
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
|
||||
}
|
||||
|
||||
decodedIRData.protocol = LG;
|
||||
decodedIRData.protocol = tProtocol; // LG or LG2
|
||||
decodedIRData.numberOfBits = LG_BITS;
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue