34 #ifndef _IR_BANG_OLUFSEN_HPP
35 #define _IR_BANG_OLUFSEN_HPP
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
97 #if defined(DECODE_BEO)
98 # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
99 # if RECORD_GAP_MICROS > 15000 && !defined(SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING)
100 #warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to <= 15000 by "#define RECORD_GAP_MICROS 12750"
103 # if RECORD_GAP_MICROS < 16000 && !defined(SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING)
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"
109 #define BEO_DATA_BITS 8 // Command or character
111 #define BEO_UNIT 3125 // All timings are in microseconds
113 #define BEO_IR_MARK 200 // The length of a mark in the IR protocol
117 #define BEO_IR_MARK_FOR_DECODE 250
118 #define BEO_DATALINK_MARK (BEO_UNIT / 2) // The length of a mark in the Datalink protocol
120 #define BEO_PULSE_LENGTH_ZERO BEO_UNIT // The length of a one to zero transition
121 #define BEO_PULSE_LENGTH_EQUAL (2 * BEO_UNIT) // 6250 The length of an equal bit
122 #define BEO_PULSE_LENGTH_ONE (3 * BEO_UNIT) // 9375 The length of a zero to one transition
123 #define BEO_PULSE_LENGTH_TRAILING_BIT (4 * BEO_UNIT) // 12500 The length of the stop bit
124 #define BEO_PULSE_LENGTH_START_BIT (5 * BEO_UNIT) // 15625 The length of the start bit
130 #ifdef BEO_LOCAL_DEBUG
131 # define BEO_DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
132 # define BEO_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
134 # define BEO_DEBUG_PRINT(...) void()
135 # define BEO_DEBUG_PRINTLN(...) void()
138 #ifdef BEO_LOCAL_TRACE
139 # undef BEO_TRACE_PRINT
140 # undef BEO_TRACE_PRINTLN
141 # define BEO_TRACE_PRINT(...) Serial.print(__VA_ARGS__)
142 # define BEO_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__)
144 # define BEO_TRACE_PRINT(...) void()
145 # define BEO_TRACE_PRINTLN(...) void()
172 #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
177 # if !defined(USE_NO_SEND_PWM)
178 # if defined(SEND_PWM_BY_TIMER)
179 enableHighFrequencyIROut (
BEO_KHZ);
180 # elif (BEO_KHZ == 38)
199 bool tLastBitValueWasOne =
false;
202 uint32_t mask = 1UL << (aBits - 1);
203 for (; mask; mask >>= 1) {
204 if (tLastBitValueWasOne && !(aRawData & mask)) {
207 tLastBitValueWasOne =
false;
208 }
else if (!tLastBitValueWasOne && (aRawData & mask)) {
211 tLastBitValueWasOne =
true;
236 #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
242 #if !defined(USE_NO_SEND_PWM)
248 mark(tSendBEOMarkLength);
251 mark(tSendBEOMarkLength);
253 mark(tSendBEOMarkLength);
258 mark(tSendBEOMarkLength);
260 bool tLastBitValueWasOne =
false;
263 uint32_t mask = 1UL << (aBits - 1);
264 for (; mask; mask >>= 1) {
265 if (tLastBitValueWasOne && !(aRawData & mask)) {
266 mark(tSendBEOMarkLength);
268 tLastBitValueWasOne =
false;
269 }
else if (!tLastBitValueWasOne && (aRawData & mask)) {
270 mark(tSendBEOMarkLength);
272 tLastBitValueWasOne =
true;
274 mark(tSendBEOMarkLength);
280 mark(tSendBEOMarkLength);
282 mark(tSendBEOMarkLength);
287 (void) aUseDatalinkTiming;
292 #define BEO_MATCH_DELTA (BEO_UNIT / 2 - MICROS_PER_TICK)
293 static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
299 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
315 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
316 uint16_t protocolMarkLength = 0;
317 uint64_t tDecodedRawData = 0;
319 uint32_t tDecodedRawData = 0;
321 uint8_t tLastDecodedBitValue = 0;
322 uint8_t tPulseNumber = 0;
323 uint8_t tBitNumber = 0;
330 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
355 # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
366 for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex <
decodedIRData.
rawlen; tRawBufferMarkIndex += 2) {
368 for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex <
decodedIRData.
rawlen; tRawBufferMarkIndex += 2) {
369 #endif // defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
383 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
388 if (tPulseNumber < 4) {
389 if (tPulseNumber < 2) {
396 if (tPulseNumber == 3) {
398 # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
416 #endif // !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
422 #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
423 if (!
matchMark(markLength, protocolMarkLength)) {
439 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
451 tLastDecodedBitValue = 1;
453 tLastDecodedBitValue = 0;
462 tDecodedRawData <<= 1;
463 tDecodedRawData |= tLastDecodedBitValue;
472 #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
487 #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
501 #endif // _IR_BANG_OLUFSEN_HPP