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 // Alt 1: Mode with gaps between frames
67 // Set RECORD_GAP_MICROS to at least 16000 to accommodate the unusually long 3. start space
68 // Can only receive single messages and back to back repeats will result in overflow
69 
70 // Alt 2: Break at start mode
71 // Define ENABLE_BEO_WITHOUT_FRAME_GAP and set RECORD_GAP_MICROS to 13000 to treat the 3. start space as a gap between messages
72 // The start of a transmission will result in a dummy decode with 0 bits data followed by the actual messages
73 // If the receiver is not resumed within a ms or so, partial messages will be decoded
74 // Debug printing in the wrong place is very likely to break reception
75 // Make sure to check the number of bits to filter dummy and incomplete messages
76 
77 // !!! We assume that the real implementations never set the official first header bit to anything other than 0 !!!
78 // !!! We therefore use 4 start bits instead of the specified 3 and in turn ignore the first header bit of the specification !!!
79 
80 // IR messages are 16 bits long. Datalink messages have different lengths.
81 // This implementation supports up to 40 bits total length split into 8 bit data/command and a header/address of variable length
82 // Header data with more than 16 bits is stored in decodedIRData.extra
83 
84 // 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.
85 // MSB first, 4 start bits + 8 to 16? bit address + 8 bit command + 1 special trailing bit + 1 stop bit.
86 // Address can be longer than 8 bit.
87 
88 /*
89  * Options for this decoder
90  *
91  */
92 #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
93 //#define SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE // This also supports headers up to 32 bit. Requires additional 150 bytes program memory.
94 #if defined(DECODE_BEO)
95 # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
96 # if RECORD_GAP_MICROS > 13000
97 #warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to 1300 by "#define RECORD_GAP_MICROS 13000"
98 # endif
99 # else
100 # if RECORD_GAP_MICROS < 16000
101 #error If not defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to a value >= 1600 by "#define RECORD_GAP_MICROS 16000"
102 # endif
103 # endif
104 #endif
105 
106 #define BEO_DATA_BITS 8 // Command or character
107 
108 #define BEO_UNIT 3125 // All timings are in microseconds
109 
110 #define BEO_IR_MARK 200 // The length of a mark in the IR protocol
111 #define BEO_DATALINK_MARK (BEO_UNIT / 2) // The length of a mark in the Datalink protocol
112 
113 #define BEO_PULSE_LENGTH_ZERO BEO_UNIT // The length of a one to zero transition
114 #define BEO_PULSE_LENGTH_EQUAL (2 * BEO_UNIT) // 6250 The length of an equal bit
115 #define BEO_PULSE_LENGTH_ONE (3 * BEO_UNIT) // 9375 The length of a zero to one transition
116 #define BEO_PULSE_LENGTH_TRAILING_BIT (4 * BEO_UNIT) // 12500 The length of the stop bit
117 #define BEO_PULSE_LENGTH_START_BIT (5 * BEO_UNIT) // 15625 The length of the start bit
118 // It is not allowed to send two ones or zeros, you must send a one or zero and a equal instead.
119 
120 //#define BEO_LOCAL_DEBUG
121 //#define BEO_LOCAL_TRACE
122 
123 #ifdef BEO_LOCAL_DEBUG
124 # define BEO_DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
125 # define BEO_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
126 #else
127 # define BEO_DEBUG_PRINT(...) void()
128 # define BEO_DEBUG_PRINTLN(...) void()
129 #endif
130 
131 #ifdef BEO_LOCAL_TRACE
132 # undef BEO_TRACE_PRINT
133 # undef BEO_TRACE_PRINTLN
134 # define BEO_TRACE_PRINT(...) Serial.print(__VA_ARGS__)
135 # define BEO_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__)
136 #else
137 # define BEO_TRACE_PRINT(...) void()
138 # define BEO_TRACE_PRINTLN(...) void()
139 #endif
140 
141 /************************************
142  * Start of send and decode functions
143  ************************************/
144 
145 /*
146  * TODO aNumberOfRepeats are handled not correctly if ENABLE_BEO_WITHOUT_FRAME_GAP is defined
147  */
148 void IRsend::sendBangOlufsen(uint16_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats, int8_t aNumberOfHeaderBits) {
149  for (int_fast8_t i = 0; i < aNumberOfRepeats + 1; ++i) {
150  sendBangOlufsenRaw((uint32_t(aHeader) << 8) | aData, aNumberOfHeaderBits + 8, i != 0);
151  }
152 }
153 
154 void IRsend::sendBangOlufsenDataLink(uint32_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats, int8_t aNumberOfHeaderBits) {
155  for (int_fast8_t i = 0; i < aNumberOfRepeats + 1; ++i) {
156  sendBangOlufsenRawDataLink((uint64_t(aHeader) << 8) | aData, aNumberOfHeaderBits + 8, i != 0, true);
157  }
158 }
159 
160 /*
161  * @param aBackToBack If true send data back to back, which cannot be decoded if ENABLE_BEO_WITHOUT_FRAME_GAP is NOT defined
162  */
163 void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBackToBack) {
164 #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
165 
166  /*
167  * 455 kHz PWM is currently only supported with SEND_PWM_BY_TIMER defined, otherwise maximum is 180 kHz
168  */
169 # if !defined(USE_NO_SEND_PWM)
170 # if defined(SEND_PWM_BY_TIMER)
171  enableHighFrequencyIROut (BEO_KHZ);
172 # elif (BEO_KHZ == 38)
173  enableIROut (BEO_KHZ); // currently only for unit test
174 # endif
175 # endif
176 
177 // AGC / Start - 3 bits + first constant 0 header bit described in the official documentation
178  if (!aBackToBack) {
179  mark(BEO_IR_MARK);
180  }
182  mark(BEO_IR_MARK);
184  mark(BEO_IR_MARK);
186 
187 // First bit of header is assumed to be a constant 0 to have a fixed state to begin with the equal decisions.
188 // So this first 0 is treated as the last bit of AGC
189  mark(BEO_IR_MARK);
191  bool tLastBitValueWasOne = false;
192 
193 // Header / Data
194  uint32_t mask = 1UL << (aBits - 1);
195  for (; mask; mask >>= 1) {
196  if (tLastBitValueWasOne && !(aRawData & mask)) {
197  mark(BEO_IR_MARK);
199  tLastBitValueWasOne = false;
200  } else if (!tLastBitValueWasOne && (aRawData & mask)) {
201  mark(BEO_IR_MARK);
203  tLastBitValueWasOne = true;
204  } else {
205  mark(BEO_IR_MARK);
207  }
208  }
209 
210 // Stop
211  mark(BEO_IR_MARK);
213  mark(BEO_IR_MARK);
214 
215 #else
216  (void) aRawData;
217  (void) aBits;
218  (void) aBackToBack;
219 #endif
220 }
221 
222 /*
223  * Version with 64 bit aRawData, which can send both timings, but costs more program memory
224  * @param aBackToBack If true send data back to back, which cannot be decoded if ENABLE_BEO_WITHOUT_FRAME_GAP is NOT defined
225  * @param aUseDatalinkTiming if false it does the same as sendBangOlufsenRaw()
226  */
227 void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bool aBackToBack, bool aUseDatalinkTiming) {
228 #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
229  uint16_t tSendBEOMarkLength = aUseDatalinkTiming ? BEO_DATALINK_MARK : BEO_IR_MARK;
230 
231  /*
232  * 455 kHz PWM is currently not supported, maximum is 180 kHz
233  */
234 #if !defined(USE_NO_SEND_PWM)
236 #endif
237 
238 // AGC / Start - 3 bits + first constant 0 header bit described in the official documentation
239  if (!aBackToBack) {
240  mark(tSendBEOMarkLength);
241  }
242  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
243  mark(tSendBEOMarkLength);
244  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
245  mark(tSendBEOMarkLength);
246  space(BEO_PULSE_LENGTH_START_BIT - tSendBEOMarkLength);
247 
248 // First bit of header is assumed to be a constant 0 to have a fixed state to begin with the equal decisions.
249 // So this first 0 is treated as the last bit of AGC
250  mark(tSendBEOMarkLength);
251  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
252  bool tLastBitValueWasOne = false;
253 
254 // Header / Data
255  uint32_t mask = 1UL << (aBits - 1);
256  for (; mask; mask >>= 1) {
257  if (tLastBitValueWasOne && !(aRawData & mask)) {
258  mark(tSendBEOMarkLength);
259  space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength);
260  tLastBitValueWasOne = false;
261  } else if (!tLastBitValueWasOne && (aRawData & mask)) {
262  mark(tSendBEOMarkLength);
263  space(BEO_PULSE_LENGTH_ONE - tSendBEOMarkLength);
264  tLastBitValueWasOne = true;
265  } else {
266  mark(tSendBEOMarkLength);
267  space(BEO_PULSE_LENGTH_EQUAL - tSendBEOMarkLength);
268  }
269  }
270 
271 // Stop
272  mark(tSendBEOMarkLength);
273  space(BEO_PULSE_LENGTH_TRAILING_BIT - tSendBEOMarkLength);
274  mark(tSendBEOMarkLength);
275 
276 #else
277  (void) aRawData;
278  (void) aBits;
279  (void) aUseDatalinkTiming;
280  (void) aBackToBack;
281 #endif
282 }
283 
284 #define BEO_MATCH_DELTA (BEO_UNIT / 2 - MICROS_PER_TICK)
285 static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
286  const uint16_t tMeasuredMicros = aMeasuredTicks * MICROS_PER_TICK;
287  return aMatchValueMicros - BEO_MATCH_DELTA < tMeasuredMicros && tMeasuredMicros < aMatchValueMicros + BEO_MATCH_DELTA;
288 }
289 
291 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
292  if (decodedIRData.rawlen != 6 && decodedIRData.rawlen < 36) { // 16 bits minimum
293 #else
294  if (decodedIRData.rawlen < 44) { // 16 bits minimum
295 #endif
296  return false;
297  }
298 
299 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
300  uint16_t protocolMarkLength = 0; // contains BEO_IR_MARK or BEO_DATALINK_MARK depending of 4. mark received
301  uint64_t tDecodedRawData = 0;
302 #else
303  uint32_t tDecodedRawData = 0;
304 #endif
305  uint8_t tLastDecodedBitValue = 0; // the last start bit is assumed to be zero
306  uint8_t tPulseNumber = 0;
307  uint8_t tBitNumber = 0;
308 
309  BEO_TRACE_PRINT(F("Pre gap: "));
311  BEO_TRACE_PRINT(F(" raw len: "));
313 
314 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
315  /*
316  * Check if we have the AGC part of the first frame in a row
317  */
318  if (decodedIRData.rawlen == 6) {
324  BEO_TRACE_PRINTLN(F("B&O: AGC only part detected"));
325  } else {
326  return false; // no B&O protocol
327  }
328  } else {
329  /*
330  * Check if leading gap is trailing bit of first frame
331  */
334  BEO_TRACE_PRINTLN(F(": Leading gap is wrong")); // Leading gap is trailing bit of first frame
335  return false; // no B&O protocol
336  }
337 
339 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
340  protocolMarkLength = BEO_IR_MARK;
342  protocolMarkLength = BEO_DATALINK_MARK;
343 #endif
344  } else {
346  BEO_TRACE_PRINTLN(F(": mark length is wrong"));
347  return false;
348  }
349 
350  // skip first zero header bit
351  for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) {
352 #else
353  for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) {
354 #endif
355 
356  uint16_t markLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex];
357  uint16_t spaceLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex + 1];
358 
359  BEO_TRACE_PRINT(tPulseNumber);
360  BEO_TRACE_PRINT(' ');
361  BEO_TRACE_PRINT(markLength * MICROS_PER_TICK);
362  BEO_TRACE_PRINT(' ');
363  BEO_TRACE_PRINT(spaceLength * MICROS_PER_TICK);
364  BEO_TRACE_PRINT(F(" ("));
365  BEO_TRACE_PRINT((markLength + spaceLength) * MICROS_PER_TICK);
366  BEO_TRACE_PRINTLN(F(") "));
367 
368 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
369  /*
370  * Handle the first 4 start bits
371  * Check if the 3. bit is the long start bit. If we see the long start bit earlier, synchronize bit counter.
372  */
373  if (tPulseNumber < 4) {
374  if (tPulseNumber < 2) {
375  // bit 0 and 1
376  if (matchSpace(spaceLength, BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK)) {
377  BEO_TRACE_PRINTLN(F(": detected long start bit -> synchronize state now"));
378  tPulseNumber = 2;
379  }
380  } else {
381  if (tPulseNumber == 3) {
382  if (matchMark(markLength, BEO_IR_MARK)) {
383 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
384  protocolMarkLength = BEO_IR_MARK;
385  } else if (matchMark(markLength, BEO_DATALINK_MARK)) {
386  protocolMarkLength = BEO_DATALINK_MARK;
387 #endif
388  } else {
390  BEO_DEBUG_PRINTLN(F(": 4. (start) mark length is wrong"));
391  return false;
392  }
393  }
394  // bit 2 and 3
395  if (!matchBeoLength(markLength + spaceLength,
396  (tPulseNumber == 2) ? BEO_PULSE_LENGTH_START_BIT : BEO_PULSE_LENGTH_ZERO)) {
398  BEO_DEBUG_PRINTLN(F(": Start length is wrong"));
399  return false;
400  }
401  }
402  } else {
403 #endif
404 
405  /*
406  * Decode header / data
407  * First check for length of mark
408  */
409 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
410  if (!matchMark(markLength, protocolMarkLength)) {
411 #else
412  if (!matchMark(markLength, BEO_IR_MARK)) {
413 #endif
415  BEO_DEBUG_PRINTLN(F(": Mark length is wrong"));
416  return false;
417  }
418 
419  /*
420  * Check for stop after receiving at least 8 bits for data and 4 bits for header
421  */
422  if (tBitNumber > BEO_DATA_BITS + 4) {
423  if (matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_TRAILING_BIT)) {
425  BEO_DEBUG_PRINTLN(F(": Trailing bit detected"));
426  break;
427  }
428 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
429  if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of trailing bit mark
431  BEO_DEBUG_PRINTLN(F(": End of buffer, but no trailing bit detected"));
432  return false;
433  }
434 #endif
435  }
436 
437  /*
438  * Decode bit
439  */
440  if (tLastDecodedBitValue == 0 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ONE)) {
441  tLastDecodedBitValue = 1;
442  } else if (tLastDecodedBitValue == 1 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ZERO)) {
443  tLastDecodedBitValue = 0;
444  } else if (!matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_EQUAL)) {
446  BEO_DEBUG_PRINT(F(": Index="));
447  BEO_DEBUG_PRINT(tRawBufferMarkIndex);
448  BEO_DEBUG_PRINT(F(" Length "));
449  BEO_DEBUG_PRINT((markLength + spaceLength) * MICROS_PER_TICK);
450  BEO_DEBUG_PRINTLN(F(" is wrong"));
451  return false;
452  }
453  tDecodedRawData <<= 1;
454  tDecodedRawData |= tLastDecodedBitValue;
455  ++tBitNumber;
456  BEO_TRACE_PRINT(F("Bits "));
457  BEO_TRACE_PRINT(tBitNumber);
458  BEO_TRACE_PRINT(F(" "));
459  BEO_TRACE_PRINT(uint32_t(tDecodedRawData >> BEO_DATA_BITS), HEX);
460  BEO_TRACE_PRINT(F(" "));
461  BEO_TRACE_PRINTLN(uint8_t(tDecodedRawData & ((1 << BEO_DATA_BITS) - 1)), HEX);
462  // End of bit decode
463 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
464  }
465 
466 #else
467  /*
468  * Check for last bit after decoding it
469  */
470  if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of last bit mark
472  BEO_TRACE_PRINTLN(F(": Last bit reached"));
473  break;
474  }
475 #endif
476 
477  ++tPulseNumber;
478  }
479 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
480  }
481 #endif
482 
484  decodedIRData.address = tDecodedRawData >> BEO_DATA_BITS; // lower header tBitNumber
485  decodedIRData.command = tDecodedRawData & ((1 << BEO_DATA_BITS) - 1); // lower 8 tBitNumber
486  decodedIRData.extra = tDecodedRawData >> (BEO_DATA_BITS + 16); // upper header tBitNumber
487  decodedIRData.numberOfBits = tBitNumber;
489  decodedIRData.decodedRawData = tDecodedRawData;
490 
491  return true;
492 }
493 #endif // _IR_BANG_OLUFSEN_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:109
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:249
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:118
IRsend::aNumberOfRepeats
void int_fast8_t aNumberOfRepeats
Definition: IRremoteInt.h:520
IRsend::sendBangOlufsenRaw
void sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBackToBack=false)
Definition: ir_BangOlufsen.hpp:163
BEO_DEBUG_PRINT
#define BEO_DEBUG_PRINT(...)
Definition: ir_BangOlufsen.hpp:127
BEO_PULSE_LENGTH_ONE
#define BEO_PULSE_LENGTH_ONE
Definition: ir_BangOlufsen.hpp:115
IRsend::mark
void mark(uint16_t aMarkMicros)
Sends an IR mark for the specified number of microseconds.
Definition: IRSend.hpp:969
IRData::rawlen
uint_fast8_t rawlen
counter of entries in rawbuf
Definition: IRProtocol.h:123
BEO_PULSE_LENGTH_TRAILING_BIT
#define BEO_PULSE_LENGTH_TRAILING_BIT
Definition: ir_BangOlufsen.hpp:116
BEO_PULSE_LENGTH_START_BIT
#define BEO_PULSE_LENGTH_START_BIT
Definition: ir_BangOlufsen.hpp:117
irparams_struct::rawbuf
uint16_t 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::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:129
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:112
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1116
BEO_MATCH_DELTA
#define BEO_MATCH_DELTA
Definition: ir_BangOlufsen.hpp:284
BEO_KHZ
#define BEO_KHZ
Definition: IRProtocol.h:155
IRrecv::decodeBangOlufsen
bool decodeBangOlufsen()
Definition: ir_BangOlufsen.hpp:290
BEO_DATA_BITS
#define BEO_DATA_BITS
Definition: ir_BangOlufsen.hpp:106
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:321
BEO_IR_MARK
#define BEO_IR_MARK
Definition: ir_BangOlufsen.hpp:110
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:119
IRData::initialGap
uint16_t initialGap
rawbuf[0] contains the initial gap of the last frame.
Definition: IRProtocol.h:127
matchBeoLength
static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Definition: ir_BangOlufsen.hpp:285
IRsend::sendBangOlufsenDataLink
void sendBangOlufsenDataLink(uint32_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats=NO_REPEATS, int8_t aNumberOfHeaderBits=8)
Definition: ir_BangOlufsen.hpp:154
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:110
BANG_OLUFSEN
@ BANG_OLUFSEN
Definition: IRProtocol.h:66
BEO_PULSE_LENGTH_EQUAL
#define BEO_PULSE_LENGTH_EQUAL
Definition: ir_BangOlufsen.hpp:114
BEO_TRACE_PRINTLN
#define BEO_TRACE_PRINTLN(...)
Definition: ir_BangOlufsen.hpp:138
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1083
BEO_PULSE_LENGTH_ZERO
#define BEO_PULSE_LENGTH_ZERO
Definition: ir_BangOlufsen.hpp:113
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:99
BEO_TRACE_PRINT
#define BEO_TRACE_PRINT(...)
Definition: ir_BangOlufsen.hpp:137
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRProtocol.h:111
BEO_DATALINK_MARK
#define BEO_DATALINK_MARK
Definition: ir_BangOlufsen.hpp:111
IRsend::space
static void space(uint16_t aSpaceMicros)
Sends an IR space for the specified number of microseconds.
Definition: IRSend.hpp:1165
IRsend::sendBangOlufsenRawDataLink
void sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bool aBackToBack=false, bool aUseDatalinkTiming=false)
Definition: ir_BangOlufsen.hpp:227
BEO_DEBUG_PRINTLN
#define BEO_DEBUG_PRINTLN(...)
Definition: ir_BangOlufsen.hpp:128
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:108
IRrecv::getProtocolString
const char * getProtocolString()
Definition: IRReceive.hpp:1700
IRsend::sendBangOlufsen
void sendBangOlufsen(uint16_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats=NO_REPEATS, int8_t aNumberOfHeaderBits=8)
Definition: ir_BangOlufsen.hpp:148
IRsend::enableIROut
void enableIROut(uint_fast8_t aFrequencyKHz)
Enables IR output.
Definition: IRSend.hpp:1205