IRremote
ir_BangOlufsen.hpp
Go to the documentation of this file.
1 /*
2  * ir_BangOlufsen.hpp
3  *
4  * Contains functions for receiving and sending Bang & Olufsen IR and Datalink '86 protocols
5  * To receive B&O and ENABLE_BEO_WITHOUT_FRAME_GAP is NOT defined, you must set RECORD_GAP_MICROS to
6  * at least 16000 to accommodate the unusually long 3. start space.
7  *
8  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
9  *
10  ************************************************************************************
11  * MIT License
12  *
13  * Copyright (c) 2022-2023 Daniel Wallner and Armin Joachimsmeyer
14  *
15  * Permission is hereby granted, free of charge, to any person obtaining a copy
16  * of this software and associated documentation files (the "Software"), to deal
17  * in the Software without restriction, including without limitation the rights
18  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19  * copies of the Software, and to permit persons to whom the Software is furnished
20  * to do so, subject to the following conditions:
21  *
22  * The above copyright notice and this permission notice shall be included in all
23  * copies or substantial portions of the Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
26  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
27  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
28  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
30  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31  *
32  ************************************************************************************
33  */
34 #ifndef _IR_BANG_OLUFSEN_HPP
35 #define _IR_BANG_OLUFSEN_HPP
36 
37 //==============================================================================
38 //
39 //
40 // Bang & Olufsen
41 //
42 //
43 //==============================================================================
44 // https://www.mikrocontroller.net/attachment/33137/datalink.pdf
45 // https://www.mikrocontroller.net/articles/IRMP_-_english#B&O
46 
47 // This protocol is unusual in two ways:
48 
49 // 1. The carrier frequency is 455 kHz
50 
51 // You can build your own receiver as Bang & Olufsen did (check old schematics) or use a TSOP7000
52 // Vishay stopped producing TSOP7000 since 2009 so you will probably only find counterfeits:
53 // https://www.vishay.com/files/whatsnew/doc/ff_FastFacts_CounterfeitTSOP7000_Dec72018.pdf
54 // It is also likely that you will need an oscilloscope to debug a counterfeit TSOP7000
55 // The specimen used to test this code was very noisy and had a very low output current
56 // A somewhat working fix was to put a 4n7 capacitor across the output and ground followed by a pnp emitter follower
57 // Other examples may require a different treatment
58 // This particular receiver also did receive lower frequencies but rather poorly and with a lower delay than usual
59 // If you need to parallel a receiver with another one you may need to delay the signal to get in phase with the other receiver
60 
61 // 2. A stream of messages can be sent back to back with a new message immediately following the previous stop space
62 
63 // It might be that this only happens over IR and not on the datalink protocol
64 // You can choose to support this or not:
65 
66 // Mode 1: Mode with gaps between frames
67 // Set RECORD_GAP_MICROS to at least 16000 to accept the unusually long 3. start space
68 // Can only receive single messages. Back to back repeats will result in overflow
69 
70 // Mode 2: Break at start mode
71 // Define ENABLE_BEO_WITHOUT_FRAME_GAP and set RECORD_GAP_MICROS to less than 15000
72 // to treat the 3. start space of 15.5 ms as a gap between messages, which makes decoding easier :-).
73 // The receiving of a transmission will then result in a dummy decode of the first 2 start bits with 0 bits data
74 // followed by a 15.5 ms gap and a data frame with one start bit (originally sent as 4. start bit).
75 // If the receiver is not resumed within a ms or so, partial messages will be decoded
76 // Debug printing in the wrong place is very likely to break reception
77 // Make sure to check the number of bits to filter dummy and incomplete messages
78 
79 // !!! We assume that the real implementations never set the official first header bit to anything other than 0 !!!
80 // !!! We therefore use 4 start bits instead of the specified 3 and in turn ignore the first header bit of the specification !!!
81 
82 // IR messages are 16 bits long. Datalink messages have different lengths.
83 // This implementation supports up to 40 bits total length split into 8 bit data/command and a header/address of variable length
84 // Header data with more than 16 bits is stored in decodedIRData.extra
85 
86 // B&O is a pulse distance protocol, but it has 3 bit values 0, 1 and (equal/repeat) as well as a special start and trailing bit.
87 //
88 // MSB first, 4 start bits + 8 to 16? bit address + 8 bit command + 1 special trailing bit + 1 stop bit.
89 // Address can be longer than 8 bit.
90 
91 /*
92  * Options for this decoder
93  *
94  */
95 #define ENABLE_BEO_WITHOUT_FRAME_GAP // Requires additional 30 bytes program memory. Enabled by default, see https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1181
96 //#define SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE // This also supports headers up to 32 bit. Requires additional 150 bytes program memory.
97 #if defined(DECODE_BEO)
98 # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
99 # if RECORD_GAP_MICROS > 15000
100 #warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to <= 15000 by "#define RECORD_GAP_MICROS 12750"
101 # endif
102 # else
103 # if RECORD_GAP_MICROS < 16000
104 #error If not defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to a value >= 16000 by "#define RECORD_GAP_MICROS 16000"
105 # endif
106 # endif
107 #endif
108 
109 #define BEO_DATA_BITS 8 // Command or character
110 
111 #define BEO_UNIT 3125 // All timings are in microseconds
112 
113 #define BEO_IR_MARK 200 // The length of a mark in the IR protocol
114 #define BEO_DATALINK_MARK (BEO_UNIT / 2) // The length of a mark in the Datalink protocol
115 
116 #define BEO_PULSE_LENGTH_ZERO BEO_UNIT // The length of a one to zero transition
117 #define BEO_PULSE_LENGTH_EQUAL (2 * BEO_UNIT) // 6250 The length of an equal bit
118 #define BEO_PULSE_LENGTH_ONE (3 * BEO_UNIT) // 9375 The length of a zero to one transition
119 #define BEO_PULSE_LENGTH_TRAILING_BIT (4 * BEO_UNIT) // 12500 The length of the stop bit
120 #define BEO_PULSE_LENGTH_START_BIT (5 * BEO_UNIT) // 15625 The length of the start bit
121 // It is not allowed to send two ones or zeros, you must send a one or zero and a equal instead.
122 
123 //#define BEO_LOCAL_DEBUG
124 //#define BEO_LOCAL_TRACE
125 
126 #ifdef BEO_LOCAL_DEBUG
127 # define BEO_DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
128 # define BEO_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
129 #else
130 # define BEO_DEBUG_PRINT(...) void()
131 # define BEO_DEBUG_PRINTLN(...) void()
132 #endif
133 
134 #ifdef BEO_LOCAL_TRACE
135 # undef BEO_TRACE_PRINT
136 # undef BEO_TRACE_PRINTLN
137 # define BEO_TRACE_PRINT(...) Serial.print(__VA_ARGS__)
138 # define BEO_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__)
139 #else
140 # define BEO_TRACE_PRINT(...) void()
141 # define BEO_TRACE_PRINTLN(...) void()
142 #endif
143 
144 /************************************
145  * Start of send and decode functions
146  ************************************/
147 
148 /*
149  * TODO aNumberOfRepeats are handled not correctly if ENABLE_BEO_WITHOUT_FRAME_GAP is defined
150  */
151 void IRsend::sendBangOlufsen(uint16_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats, int8_t aNumberOfHeaderBits) {
152  for (int_fast8_t i = 0; i < aNumberOfRepeats + 1; ++i) {
153  sendBangOlufsenRaw((uint32_t(aHeader) << 8) | aData, aNumberOfHeaderBits + 8, i != 0);
154  }
155 }
156 
157 void IRsend::sendBangOlufsenDataLink(uint32_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats, int8_t aNumberOfHeaderBits) {
158  for (int_fast8_t i = 0; i < aNumberOfRepeats + 1; ++i) {
159  sendBangOlufsenRawDataLink((uint64_t(aHeader) << 8) | aData, aNumberOfHeaderBits + 8, i != 0, true);
160  }
161 }
162 
163 /*
164  * @param aBackToBack If true send data back to back, which cannot be decoded if ENABLE_BEO_WITHOUT_FRAME_GAP is NOT defined
165  */
166 void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBackToBack) {
167 #if defined(USE_NO_SEND_PWM) || defined(SEND_PWM_BY_TIMER) || BEO_KHZ == 38 // BEO_KHZ == 38 is for unit test which runs the B&O protocol with 38 kHz
168 
169  /*
170  * 455 kHz PWM is currently only supported with SEND_PWM_BY_TIMER defined, otherwise maximum is 180 kHz
171  */
172 # if !defined(USE_NO_SEND_PWM)
173 # if defined(SEND_PWM_BY_TIMER)
174  enableHighFrequencyIROut (BEO_KHZ);
175 # elif (BEO_KHZ == 38)
176  enableIROut (BEO_KHZ); // currently only for unit test
177 # endif
178 # endif
179 
180 // AGC / Start - 3 bits + first constant 0 header bit described in the official documentation
181  if (!aBackToBack) {
182  mark(BEO_IR_MARK);
183  }
185  mark(BEO_IR_MARK);
187  mark(BEO_IR_MARK);
189 
190 // First bit of header is assumed to be a constant 0 to have a fixed state to begin with the equal decisions.
191 // So this first 0 is treated as the last bit of AGC
192  mark(BEO_IR_MARK);
194  bool tLastBitValueWasOne = false;
195 
196 // Header / Data
197  uint32_t mask = 1UL << (aBits - 1);
198  for (; mask; mask >>= 1) {
199  if (tLastBitValueWasOne && !(aRawData & mask)) {
200  mark(BEO_IR_MARK);
202  tLastBitValueWasOne = false;
203  } else if (!tLastBitValueWasOne && (aRawData & mask)) {
204  mark(BEO_IR_MARK);
206  tLastBitValueWasOne = true;
207  } else {
208  mark(BEO_IR_MARK);
210  }
211  }
212 
213 // Stop
214  mark(BEO_IR_MARK);
216  mark(BEO_IR_MARK);
217 
218 #else
219  (void) aRawData;
220  (void) aBits;
221  (void) aBackToBack;
222 #endif
223 }
224 
225 /*
226  * Version with 64 bit aRawData, which can send both timings, but costs more program memory
227  * @param aBackToBack If true send data back to back, which cannot be decoded if ENABLE_BEO_WITHOUT_FRAME_GAP is NOT defined
228  * @param aUseDatalinkTiming if false it does the same as sendBangOlufsenRaw()
229  */
230 void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bool aBackToBack, bool aUseDatalinkTiming) {
231 #if defined(USE_NO_SEND_PWM) || BEO_KHZ == 38 // BEO_KHZ == 38 is for unit test which runs the B&O protocol with 38 kHz instead 0f 455 kHz
232  uint16_t tSendBEOMarkLength = aUseDatalinkTiming ? BEO_DATALINK_MARK : BEO_IR_MARK;
233 
234  /*
235  * 455 kHz PWM is currently not supported, maximum is 180 kHz
236  */
237 #if !defined(USE_NO_SEND_PWM)
239 #endif
240 
241 // AGC / Start - 3 bits + first constant 0 header bit described in the official documentation
242  if (!aBackToBack) {
243  mark(tSendBEOMarkLength);
244  }
245  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
246  mark(tSendBEOMarkLength);
247  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
248  mark(tSendBEOMarkLength);
249  space(BEO_PULSE_LENGTH_START_BIT - tSendBEOMarkLength);
250 
251 // First bit of header is assumed to be a constant 0 to have a fixed state to begin with the equal decisions.
252 // So this first 0 is treated as the last bit of AGC
253  mark(tSendBEOMarkLength);
254  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
255  bool tLastBitValueWasOne = false;
256 
257 // Header / Data
258  uint32_t mask = 1UL << (aBits - 1);
259  for (; mask; mask >>= 1) {
260  if (tLastBitValueWasOne && !(aRawData & mask)) {
261  mark(tSendBEOMarkLength);
262  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
263  tLastBitValueWasOne = false;
264  } else if (!tLastBitValueWasOne && (aRawData & mask)) {
265  mark(tSendBEOMarkLength);
266  space(BEO_PULSE_LENGTH_ONE - tSendBEOMarkLength);
267  tLastBitValueWasOne = true;
268  } else {
269  mark(tSendBEOMarkLength);
270  space(BEO_PULSE_LENGTH_EQUAL - tSendBEOMarkLength);
271  }
272  }
273 
274 // Stop
275  mark(tSendBEOMarkLength);
276  space(BEO_PULSE_LENGTH_TRAILING_BIT - tSendBEOMarkLength);
277  mark(tSendBEOMarkLength);
278 
279 #else
280  (void) aRawData;
281  (void) aBits;
282  (void) aUseDatalinkTiming;
283  (void) aBackToBack;
284 #endif
285 }
286 
287 #define BEO_MATCH_DELTA (BEO_UNIT / 2 - MICROS_PER_TICK)
288 static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
289  const uint16_t tMeasuredMicros = aMeasuredTicks * MICROS_PER_TICK;
290  return aMatchValueMicros - BEO_MATCH_DELTA < tMeasuredMicros && tMeasuredMicros < aMatchValueMicros + BEO_MATCH_DELTA;
291 }
292 
294 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
295  if (decodedIRData.rawlen != 6 && decodedIRData.rawlen < 36) { // 16 bits minimum
296 #else
297  if (decodedIRData.rawlen < 44) { // 16 bits minimum
298 #endif
299  return false;
300  }
301 
302 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
303  uint16_t protocolMarkLength = 0; // contains BEO_IR_MARK or BEO_DATALINK_MARK depending of 4. mark received
304  uint64_t tDecodedRawData = 0;
305 #else
306  uint32_t tDecodedRawData = 0;
307 #endif
308  uint8_t tLastDecodedBitValue = 0; // the last start bit is assumed to be zero
309  uint8_t tPulseNumber = 0;
310  uint8_t tBitNumber = 0;
311 
312  BEO_TRACE_PRINT(F("Pre gap: "));
314  BEO_TRACE_PRINT(F(" raw len: "));
316 
317 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
318  /*
319  * Check if we have the AGC part of the first frame, i.e. start bit 1 and 2.
320  */
321  if (decodedIRData.rawlen == 6) {
327  BEO_TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected"));
328  } else {
329  return false; // no B&O protocol
330  }
331  } else {
332  /*
333  * Check if leading gap is trailing bit of first frame
334  */
337  BEO_TRACE_PRINTLN(F(": Leading gap is wrong")); // Leading gap is trailing bit of first frame
338  return false; // no B&O protocol
339  }
340 
342 # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
343  protocolMarkLength = BEO_IR_MARK;
345  protocolMarkLength = BEO_DATALINK_MARK;
346 # endif
347  } else {
349  BEO_TRACE_PRINTLN(F(": mark length is wrong"));
350  return false;
351  }
352 
353  // skip first zero header bit
354  for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) {
355 #else
356  for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) {
357 #endif // defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
358 
359  uint16_t markLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex];
360  uint16_t spaceLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex + 1];
361 
362  BEO_TRACE_PRINT(tPulseNumber);
363  BEO_TRACE_PRINT(' ');
364  BEO_TRACE_PRINT(markLength * MICROS_PER_TICK);
365  BEO_TRACE_PRINT(' ');
366  BEO_TRACE_PRINT(spaceLength * MICROS_PER_TICK);
367  BEO_TRACE_PRINT(F(" ("));
368  BEO_TRACE_PRINT((markLength + spaceLength) * MICROS_PER_TICK);
369  BEO_TRACE_PRINTLN(F(") "));
370 
371 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
372  /*
373  * Handle the first 4 start bits
374  * Check if the 3. bit is the long start bit. If we see the long start bit earlier, synchronize bit counter.
375  */
376  if (tPulseNumber < 4) {
377  if (tPulseNumber < 2) {
378  // bit 0 and 1
379  if (matchSpace(spaceLength, BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK)) {
380  BEO_TRACE_PRINTLN(F(": detected long start bit -> synchronize state now"));
381  tPulseNumber = 2;
382  }
383  } else {
384  if (tPulseNumber == 3) {
385  if (matchMark(markLength, BEO_IR_MARK)) {
386 # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
387  protocolMarkLength = BEO_IR_MARK;
388  } else if (matchMark(markLength, BEO_DATALINK_MARK)) {
389  protocolMarkLength = BEO_DATALINK_MARK;
390 # endif
391  } else {
393  BEO_DEBUG_PRINTLN(F(": 4. (start) mark length is wrong"));
394  return false;
395  }
396  }
397  // bit 2 and 3
398  if (!matchBeoLength(markLength + spaceLength,
399  (tPulseNumber == 2) ? BEO_PULSE_LENGTH_START_BIT : BEO_PULSE_LENGTH_ZERO)) {
401  BEO_DEBUG_PRINTLN(F(": Start length is wrong"));
402  return false;
403  }
404  }
405  } else {
406 #endif // !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
407 
408  /*
409  * Decode header / data
410  * First check for length of mark
411  */
412 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
413  if (!matchMark(markLength, protocolMarkLength)) {
414 #else
415  if (!matchMark(markLength, BEO_IR_MARK)) {
416 #endif
418  BEO_DEBUG_PRINTLN(F(": Mark length is wrong"));
419  return false;
420  }
421 
422  /*
423  * Check for stop after receiving at least 8 bits for data and 4 bits for header
424  */
425  if (tBitNumber > BEO_DATA_BITS + 4) {
426  if (matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_TRAILING_BIT)) {
428  BEO_DEBUG_PRINTLN(F(": Trailing bit detected"));
429  break;
430  }
431 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
432  if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of trailing bit mark
434  BEO_DEBUG_PRINTLN(F(": End of buffer, but no trailing bit detected"));
435  return false;
436  }
437 #endif
438  }
439 
440  /*
441  * Decode bit
442  */
443  if (tLastDecodedBitValue == 0 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ONE)) {
444  tLastDecodedBitValue = 1;
445  } else if (tLastDecodedBitValue == 1 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ZERO)) {
446  tLastDecodedBitValue = 0;
447  } else if (!matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_EQUAL)) {
449  BEO_DEBUG_PRINT(F(": Index="));
450  BEO_DEBUG_PRINT(tRawBufferMarkIndex);
451  BEO_DEBUG_PRINT(F(" Length "));
452  BEO_DEBUG_PRINT((markLength + spaceLength) * MICROS_PER_TICK);
453  BEO_DEBUG_PRINTLN(F(" is wrong"));
454  return false;
455  }
456  tDecodedRawData <<= 1;
457  tDecodedRawData |= tLastDecodedBitValue;
458  ++tBitNumber;
459  BEO_TRACE_PRINT(F("Bits "));
460  BEO_TRACE_PRINT(tBitNumber);
461  BEO_TRACE_PRINT(F(" "));
462  BEO_TRACE_PRINT(uint32_t(tDecodedRawData >> BEO_DATA_BITS), HEX);
463  BEO_TRACE_PRINT(F(" "));
464  BEO_TRACE_PRINTLN(uint8_t(tDecodedRawData & ((1 << BEO_DATA_BITS) - 1)), HEX);
465  // End of bit decode
466 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
467  }
468 
469 #else
470  /*
471  * Check for last bit after decoding it
472  */
473  if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of last bit mark
475  BEO_TRACE_PRINTLN(F(": Last bit reached"));
476  break;
477  }
478 #endif
479 
480  ++tPulseNumber;
481  }
482 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
483  }
484 #endif
485 
487  decodedIRData.address = tDecodedRawData >> BEO_DATA_BITS; // lower header tBitNumber
488  decodedIRData.command = tDecodedRawData & ((1 << BEO_DATA_BITS) - 1); // lower 8 tBitNumber
489  decodedIRData.extra = tDecodedRawData >> (BEO_DATA_BITS + 16); // upper header tBitNumber
490  decodedIRData.numberOfBits = tBitNumber;
492  decodedIRData.decodedRawData = tDecodedRawData;
493 
494  return true;
495 }
496 #endif // _IR_BANG_OLUFSEN_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:110
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:250
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:119
IRsend::aNumberOfRepeats
void int_fast8_t aNumberOfRepeats
Definition: IRremoteInt.h:547
IRsend::sendBangOlufsenRaw
void sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBackToBack=false)
Definition: ir_BangOlufsen.hpp:166
BEO_DEBUG_PRINT
#define BEO_DEBUG_PRINT(...)
Definition: ir_BangOlufsen.hpp:130
BEO_PULSE_LENGTH_ONE
#define BEO_PULSE_LENGTH_ONE
Definition: ir_BangOlufsen.hpp:118
IRsend::mark
void mark(uint16_t aMarkMicros)
Sends an IR mark for the specified number of microseconds.
Definition: IRSend.hpp:947
BEO_PULSE_LENGTH_TRAILING_BIT
#define BEO_PULSE_LENGTH_TRAILING_BIT
Definition: ir_BangOlufsen.hpp:119
BEO_PULSE_LENGTH_START_BIT
#define BEO_PULSE_LENGTH_START_BIT
Definition: ir_BangOlufsen.hpp:120
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:131
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:113
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1227
BEO_MATCH_DELTA
#define BEO_MATCH_DELTA
Definition: ir_BangOlufsen.hpp:287
BEO_KHZ
#define BEO_KHZ
Definition: IRProtocol.h:154
IRrecv::decodeBangOlufsen
bool decodeBangOlufsen()
Definition: ir_BangOlufsen.hpp:293
BEO_DATA_BITS
#define BEO_DATA_BITS
Definition: ir_BangOlufsen.hpp:109
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:358
BEO_IR_MARK
#define BEO_IR_MARK
Definition: ir_BangOlufsen.hpp:113
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:120
matchBeoLength
static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Definition: ir_BangOlufsen.hpp:288
IRsend::sendBangOlufsenDataLink
void sendBangOlufsenDataLink(uint32_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats=NO_REPEATS, int8_t aNumberOfHeaderBits=8)
Definition: ir_BangOlufsen.hpp:157
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:111
BANG_OLUFSEN
@ BANG_OLUFSEN
Definition: IRProtocol.h:66
BEO_PULSE_LENGTH_EQUAL
#define BEO_PULSE_LENGTH_EQUAL
Definition: ir_BangOlufsen.hpp:117
BEO_TRACE_PRINTLN
#define BEO_TRACE_PRINTLN(...)
Definition: ir_BangOlufsen.hpp:141
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1193
BEO_PULSE_LENGTH_ZERO
#define BEO_PULSE_LENGTH_ZERO
Definition: ir_BangOlufsen.hpp:116
irparams_struct::rawbuf
IRRawbufType rawbuf[RAW_BUFFER_LENGTH]
raw data / tick counts per mark/space. With 8 bit we can only store up to 12.7 ms....
Definition: IRremoteInt.h:144
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:100
BEO_TRACE_PRINT
#define BEO_TRACE_PRINT(...)
Definition: ir_BangOlufsen.hpp:140
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRProtocol.h:112
BEO_DATALINK_MARK
#define BEO_DATALINK_MARK
Definition: ir_BangOlufsen.hpp:114
IRsend::space
static void space(uint16_t aSpaceMicros)
Sends an IR space for the specified number of microseconds.
Definition: IRSend.hpp:1148
IRData::rawlen
IRRawlenType rawlen
counter of entries in rawbuf of last received frame.
Definition: IRProtocol.h:128
IRsend::sendBangOlufsenRawDataLink
void sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bool aBackToBack=false, bool aUseDatalinkTiming=false)
Definition: ir_BangOlufsen.hpp:230
BEO_DEBUG_PRINTLN
#define BEO_DEBUG_PRINTLN(...)
Definition: ir_BangOlufsen.hpp:131
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:109
IRrecv::getProtocolString
const char * getProtocolString()
Definition: IRReceive.hpp:1835
IRsend::sendBangOlufsen
void sendBangOlufsen(uint16_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats=NO_REPEATS, int8_t aNumberOfHeaderBits=8)
Definition: ir_BangOlufsen.hpp:151
IRData::initialGapTicks
uint16_t initialGapTicks
contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
Definition: IRProtocol.h:129
IRsend::enableIROut
void enableIROut(uint_fast8_t aFrequencyKHz)
Enables IR output.
Definition: IRSend.hpp:1188