LG2 protocol

This commit is contained in:
Armin 2021-06-16 01:02:18 +02:00
parent 0b16ba4fdb
commit 39eec4c5ca
15 changed files with 135 additions and 69 deletions

View File

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

View File

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

View File

@ -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() {

View File

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

View File

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

View File

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

View File

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

BIN
pictures/LGRemote.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

BIN
pictures/LGRemote1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -44,6 +44,7 @@ typedef enum {
DISH,
JVC,
LG,
LG2,
NEC,
PANASONIC,
KASEIKYO,

View File

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

View File

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

View File

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

View File

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

View File

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