IRremote
ir_Denon.hpp
Go to the documentation of this file.
1 /*
2  * ir_Denon.cpp
3  *
4  * Contains functions for receiving and sending Denon/Sharp IR Protocol
5  *
6  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
7  *
8  ************************************************************************************
9  * MIT License
10  *
11  * Copyright (c) 2020-2022 Armin Joachimsmeyer
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is furnished
18  * to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in all
21  * copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
24  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
28  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  *
30  ************************************************************************************
31  */
32 #ifndef _IR_DENON_HPP
33 #define _IR_DENON_HPP
34 
35 #if defined(DEBUG) && !defined(LOCAL_DEBUG)
36 #define LOCAL_DEBUG
37 #else
38 //#define LOCAL_DEBUG // This enables debug output only for this file
39 #endif
40 
44 //==============================================================================
45 // DDDD EEEEE N N OOO N N
46 // D D E NN N O O NN N
47 // D D EEE N N N O O N N N
48 // D D E N NN O O N NN
49 // DDDD EEEEE N N OOO N N
50 //==============================================================================
51 // SSSS H H AAA RRRR PPPP
52 // S H H A A R R P P
53 // SSS HHHHH AAAAA RRRR PPPP
54 // S H H A A R R P
55 // SSSS H H A A R R P
56 //==============================================================================
57 /*
58  Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first
59  + 200,-1800 + 300,- 750 + 300,- 800 + 200,- 800
60  + 250,-1800 + 250,- 800 + 250,-1800 + 300,-1750
61  + 300,- 750 + 300,-1800 + 250,-1800 + 250,-1850
62  + 250,- 750 + 300,- 800 + 250,- 800 + 250
63  Sum: 23050
64 
65  Denon/Sharp variant
66  Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first
67  + 200,-1800 + 300,- 750 + 250,- 800 + 250,- 750
68  + 300,-1800 + 250,- 800 + 250,-1800 + 300,-1750
69  + 300,- 750 + 300,-1800 + 250,-1800 + 250,-1800
70  + 300,- 750 + 300,- 750 + 300,-1800 + 250
71  Sum: 23050
72  */
73 /*
74  * https://www.mikrocontroller.net/articles/IRMP_-_english#DENON
75  * Denon published all their IR codes:
76  * http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls
77  * Example:
78  * 0000 006D 0000 0020 000A 001E 000A 0046 000A 001E 000A 001E 000A 001E // 5 address bits
79  * 000A 001E 000A 001E 000A 0046 000A 0046 000A 0046 000A 001E 000A 0046 000A 0046 // 8 command bits
80  * 000A 001E 000A 001E 000A 0679 // 2 frame bits 0,0 + stop bit + space for AutoRepeat
81  * 000A 001E 000A 0046 000A 001E 000A 001E 000A 001E // 5 address bits
82  * 000A 0046 000A 0046 000A 001E 000A 001E 000A 001E 000A 0046 000A 001E 000A 001E // 8 inverted command bits
83  * 000A 0046 000A 0046 000A 0679 // 2 frame bits 1,1 + stop bit + space for Repeat
84  * From analyzing the codes for Tuner preset 1 to 8 in tab Main Zone ID#1 it is obvious, that the protocol is LSB first at least for command.
85  * All Denon codes with 32 as 3. value use the Kaseyikyo Denon variant.
86  */
87 // LSB first, no start bit, 5 address + 8 command + 2 frame (0,0) + 1 stop bit - each frame 2 times
88 // Every frame is auto repeated with a space period of 45 ms and the command and frame inverted to (1,1) or (0,1) for SHARP.
89 //
90 #define DENON_ADDRESS_BITS 5
91 #define DENON_COMMAND_BITS 8
92 #define DENON_FRAME_BITS 2 // 00/10 for 1. frame Denon/Sharp, inverted for autorepeat frame
93 
94 #define DENON_BITS (DENON_ADDRESS_BITS + DENON_COMMAND_BITS + DENON_FRAME_BITS) // 15 - The number of bits in the command
95 #define DENON_UNIT 260
96 
97 #define DENON_BIT_MARK DENON_UNIT // The length of a Bit:Mark
98 #define DENON_ONE_SPACE (7 * DENON_UNIT) // 1820 // The length of a Bit:Space for 1's
99 #define DENON_ZERO_SPACE (3 * DENON_UNIT) // 780 // The length of a Bit:Space for 0's
100 
101 #define DENON_AUTO_REPEAT_DISTANCE 45000 // Every frame is auto repeated with a space period of 45 ms and the command and frame inverted.
102 #define DENON_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
103 
104 // for old decoder
105 #define DENON_HEADER_MARK DENON_UNIT // The length of the Header:Mark
106 #define DENON_HEADER_SPACE (3 * DENON_UNIT) // 780 // The length of the Header:Space
107 
110  / MICROS_IN_ONE_MILLI), NULL };
111 
112 /************************************
113  * Start of send and decode functions
114  ************************************/
115 
116 void IRsend::sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
117  sendDenon(aAddress, aCommand, aNumberOfRepeats, true);
118 }
119 
120 void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aSendSharp) {
121  // Set IR carrier frequency
122  enableIROut (DENON_KHZ); // 38 kHz
123 
124  // Add frame marker for sharp
125  uint16_t tCommand = aCommand;
126  if (aSendSharp) {
127  tCommand |= 0x0200; // the 2 upper bits are 00 for Denon and 10 for Sharp
128  }
129  uint16_t tData = aAddress | ((uint16_t) tCommand << DENON_ADDRESS_BITS);
130  uint16_t tInvertedData = (tData ^ 0x7FE0); // Command and frame (upper 10 bits) are inverted
131 
132  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
133  while (tNumberOfCommands > 0) {
134 
135  // Data
137 
138  // Inverted autorepeat frame
141 
142  tNumberOfCommands--;
143  // skip last delay!
144  if (tNumberOfCommands > 0) {
145  // send repeated command with a fixed space gap
147  }
148  }
149 #if !defined(DISABLE_CODE_FOR_RECEIVER)
151 #endif
152 }
153 
155  return decodeDenon();
156 }
157 
159 
160  // we have no start bit, so check for the exact amount of data bits
161  // Check we have the right amount of data (32). The + 2 is for initial gap + stop bit mark
162  if (decodedIRData.rawDataPtr->rawlen != (2 * DENON_BITS) + 2) {
163  IR_DEBUG_PRINT(F("Denon: "));
164  IR_DEBUG_PRINT(F("Data length="));
166  IR_DEBUG_PRINTLN(F(" is not 32"));
167  return false;
168  }
169 
170  // Try to decode as Denon protocol
172 #if defined(LOCAL_DEBUG)
173  Serial.print(F("Denon: "));
174  Serial.println(F("Decode failed"));
175 #endif
176  return false;
177  }
178 
179  // Check for stop mark
181 #if defined(LOCAL_DEBUG)
182  Serial.print(F("Denon: "));
183  Serial.println(F("Stop bit mark length is wrong"));
184 #endif
185  return false;
186  }
187 
188  // Success
191  uint8_t tFrameBits = (decodedIRData.command >> 8) & 0x03;
192  decodedIRData.command &= 0xFF;
193 
194  // Check for (auto) repeat
196  repeatCount++;
197  if (repeatCount > 1) { // skip first auto repeat
199  }
200 
201  if (tFrameBits & 0x01) {
202  /*
203  * Here we are in the auto repeated frame with the inverted command
204  */
205 #if defined(LOCAL_DEBUG)
206  Serial.print(F("Denon: "));
207  Serial.println(F("Autorepeat received="));
208 #endif
210  // Check parity of consecutive received commands. There is no parity in one data set.
211  if ((uint8_t) lastDecodedCommand != (uint8_t)(~decodedIRData.command)) {
213 #if defined(LOCAL_DEBUG)
214  Serial.print(F("Denon: "));
215  Serial.print(F("Parity check for repeat failed last command="));
216  Serial.print(lastDecodedCommand, HEX);
217  Serial.print(F(" current="));
218  Serial.println(~decodedIRData.command, HEX);
219 #endif
220  }
221  // always take non inverted command
223  }
224 
225  // repeated command here
226  if (tFrameBits == 1 || tFrameBits == 2 ) {
228  } else {
230  }
231  } else {
232  repeatCount = 0;
233  // first command here
234  if (tFrameBits == 2) {
236  } else {
238  }
239  }
240 
242 
243  return true;
244 }
245 
246 /*********************************************************************************
247  * Old deprecated functions, kept for backward compatibility to old 2.0 tutorials
248  *********************************************************************************/
249 /*
250  * Only for backwards compatibility
251  */
252 void IRsend::sendDenonRaw(uint16_t aRawData, int_fast8_t aNumberOfRepeats) {
253  sendDenon(aRawData >> (DENON_COMMAND_BITS + DENON_FRAME_BITS), (aRawData >> DENON_FRAME_BITS) & 0xFF, aNumberOfRepeats);
254 }
255 
256 /*
257  * Old function with parameter data
258  */
259 void IRsend::sendDenon(unsigned long data, int nbits) {
260  // Set IR carrier frequency
262 #if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))
263  Serial.println(
264  "The function sendDenon(data, nbits) is deprecated and may not work as expected! Use sendDenonRaw(data, NumberOfRepeats) or better sendDenon(Address, Command, NumberOfRepeats).");
265 #endif
266 
267  // Header
270 
271  // Data
274 #if !defined(DISABLE_CODE_FOR_RECEIVER)
276 #endif
277 }
278 
279 /*
280  * Old function without parameter aNumberOfRepeats
281  */
282 void IRsend::sendSharp(unsigned int aAddress, unsigned int aCommand) {
283  sendDenon(aAddress, aCommand, true, 0);
284 }
285 
287 
288  // Check we have the right amount of data
289  if (decodedIRData.rawDataPtr->rawlen != 1 + 2 + (2 * DENON_BITS) + 1) {
290  return false;
291  }
292 
293  // Check initial Mark+Space match
294  if (!matchMark(aResults->rawbuf[1], DENON_HEADER_MARK)) {
295  return false;
296  }
297 
298  if (!matchSpace(aResults->rawbuf[2], DENON_HEADER_SPACE)) {
299  return false;
300  }
301 
302  // Try to decode as Denon protocol
304  return false;
305  }
306 
307  // Success
308  aResults->value = decodedIRData.decodedRawData;
309  aResults->bits = DENON_BITS;
310  aResults->decode_type = DENON;
312  return true;
313 }
314 
316 #if defined(LOCAL_DEBUG)
317 #undef LOCAL_DEBUG
318 #endif
319 #endif // _IR_DENON_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:117
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:258
DENON_COMMAND_BITS
#define DENON_COMMAND_BITS
Definition: ir_Denon.hpp:91
decode_results
Results returned from old decoders !!!deprecated!!!
Definition: IRremoteInt.h:155
PROTOCOL_IS_MSB_FIRST
#define PROTOCOL_IS_MSB_FIRST
Definition: IRProtocol.h:130
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:120
IRsend::aNumberOfRepeats
void uint8_t int_fast8_t aNumberOfRepeats
Definition: IRremoteInt.h:474
MICROS_IN_ONE_MILLI
#define MICROS_IN_ONE_MILLI
Definition: IRremote.hpp:263
DENON_FRAME_BITS
#define DENON_FRAME_BITS
Definition: ir_Denon.hpp:92
DenonProtocolConstants
struct PulseDistanceWidthProtocolConstants DenonProtocolConstants
Definition: ir_Denon.hpp:108
IRsend::mark
void mark(unsigned int aMarkMicros)
Sends an IR mark for the specified number of microseconds.
Definition: IRSend.hpp:757
IRDATA_FLAGS_IS_REPEAT
#define IRDATA_FLAGS_IS_REPEAT
Definition: IRProtocol.h:94
IRrecv::restartAfterSend
void restartAfterSend()
Restarts receiver after send.
Definition: IRReceive.hpp:346
IRrecv::decodeSharp
bool decodeSharp()
Definition: ir_Denon.hpp:154
decode_results::rawbuf
unsigned int * rawbuf
Definition: IRremoteInt.h:166
IRData::rawDataPtr
irparams_struct * rawDataPtr
Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by r...
Definition: IRProtocol.h:126
IRDATA_FLAGS_IS_AUTO_REPEAT
#define IRDATA_FLAGS_IS_AUTO_REPEAT
Definition: IRProtocol.h:95
decode_results::bits
uint8_t bits
Definition: IRremoteInt.h:161
decode_results::decode_type
decode_type_t decode_type
Definition: IRremoteInt.h:158
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:122
DENON_HEADER_MARK
#define DENON_HEADER_MARK
Definition: ir_Denon.hpp:105
IR_DEBUG_PRINT
#define IR_DEBUG_PRINT(...)
If DEBUG, print the arguments, otherwise do nothing.
Definition: IRremoteInt.h:133
DENON_REPEAT_PERIOD
#define DENON_REPEAT_PERIOD
Definition: ir_Denon.hpp:102
DENON_ZERO_SPACE
#define DENON_ZERO_SPACE
Definition: ir_Denon.hpp:99
irparams_struct::rawlen
uint_fast8_t rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:109
IRrecv::decodePulseDistanceWidthData
bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset=3)
Decode pulse distance protocols for PulseDistanceWidthProtocolConstants.
Definition: IRReceive.hpp:768
DENON_HEADER_SPACE
#define DENON_HEADER_SPACE
Definition: ir_Denon.hpp:106
IRDATA_FLAGS_PARITY_FAILED
#define IRDATA_FLAGS_PARITY_FAILED
the current (autorepeat) frame violated parity check
Definition: IRProtocol.h:96
decode_results::value
uint32_t value
Definition: IRremoteInt.h:160
PulseDistanceWidthProtocolConstants
Definition: IRProtocol.h:74
DENON_ONE_SPACE
#define DENON_ONE_SPACE
Definition: ir_Denon.hpp:98
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:305
matchSpace
bool matchSpace(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1033
SEND_STOP_BIT
#define SEND_STOP_BIT
Definition: IRremoteInt.h:393
IRData::flags
uint8_t flags
See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:121
PROTOCOL_IS_LSB_FIRST
#define PROTOCOL_IS_LSB_FIRST
Definition: IRProtocol.h:129
IRsend::sendSharp
void sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats)
Definition: ir_Denon.hpp:116
irparams_struct::rawbuf
unsigned int rawbuf[RAW_BUFFER_LENGTH]
raw data / tick counts per mark/space, first entry is the length of the gap between previous and curr...
Definition: IRremoteInt.h:113
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:118
IRsend::sendDenon
void sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aSendSharp=false)
Definition: ir_Denon.hpp:120
IRrecv::decodeDenonOld
bool decodeDenonOld(decode_results *aResults)
Definition: ir_Denon.hpp:286
DENON
@ DENON
Definition: IRProtocol.h:45
IRrecv::lastDecodedCommand
uint32_t lastDecodedCommand
Definition: IRremoteInt.h:310
IRsend::space
static void space(unsigned int aSpaceMicros)
Sends an IR space for the specified number of microseconds.
Definition: IRSend.hpp:927
DENON_AUTO_REPEAT_DISTANCE
#define DENON_AUTO_REPEAT_DISTANCE
Definition: ir_Denon.hpp:101
DENON_BITS
#define DENON_BITS
Definition: ir_Denon.hpp:94
IRsend::sendDenonRaw
void sendDenonRaw(uint16_t aRawData, int_fast8_t aNumberOfRepeats=NO_REPEATS) void sendJVC(uint8_t aAddress
Definition: ir_Denon.hpp:252
DENON_ADDRESS_BITS
#define DENON_ADDRESS_BITS
Definition: ir_Denon.hpp:90
IRrecv::decodeDenon
bool decodeDenon()
Definition: ir_Denon.hpp:158
IRsend::sendPulseDistanceWidthData
void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, uint_fast8_t aNumberOfBits)
Sends PulseDistance data The output always ends with a space Each additional call costs 16 bytes prog...
Definition: IRSend.hpp:643
DENON_BIT_MARK
#define DENON_BIT_MARK
Definition: ir_Denon.hpp:97
IR_DEBUG_PRINTLN
#define IR_DEBUG_PRINTLN(...)
If DEBUG, print the arguments as a line, otherwise do nothing.
Definition: IRremoteInt.h:137
DENON_KHZ
#define DENON_KHZ
Definition: IRProtocol.h:140
matchMark
bool matchMark(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1000
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:116
IRsend::aCommand
void uint8_t aCommand
Definition: IRremoteInt.h:474
IrReceiver
IRrecv IrReceiver
The receiver instance.
Definition: IRReceive.hpp:59
IRsend::enableIROut
void enableIROut(uint_fast8_t aFrequencyKHz)
Enables IR output.
Definition: IRSend.hpp:961
SHARP
@ SHARP
Definition: IRProtocol.h:63
IRrecv::repeatCount
uint8_t repeatCount
Definition: IRremoteInt.h:312