#include "IRremote.h" //============================================================================== // BBBB OOO SSSS EEEEE // B B O O S E // BB B O O SSS EEEE // B B O O S E // BBBB OOO SSSS EEEEE //============================================================================== // // Bose Wave Radio CD Remote Control // |-------------------------------------| // | On/Off Sleep VolUp | // | Play/Pause Stop VolDown | // | FM AM Aux | // | Tune Down Tune Up Mute | // | 1 2 3 | // | 4 5 6 | // |-------------------------------------| // // Support for Bose Wave Radio CD provided by https://github.com/uvotguy. // // This protocol was reverse engineered by capturing IR signals from a working // remote. Multiple signals were captured on my oscilloscope, and the timing // values were averaged. // // IR codes are 8 bits. Transmission starts with a header: a mark and a space. // The header is followed by an 8-bit command, where a bit is a mark and a short // space (1) or a long space (0). The command is followed by the complement of // the command (8 bits). A transmission ends with a short mark. // // As seen on my trusty oscilloscope, there is no repeat code. Instead, when I // press and hold a button on my remote, it sends a command, makes a 51.2ms space, // and resends the command, etc, etc. // // It may be worth noting that these values do NOT match those in the LIRC // remote database (http://lirc.sourceforge.net/remotes/bose/). #define CMD_ON_OFF 0xff #define CMD_MUTE 0xfe #define CMD_VOL_UP 0xfd #define CMD_VOL_DOWN 0xfc #define CMD_PRESET_6 0xfb #define CMD_SLEEP 0xfa #define CMD_FM 0xf9 #define CMD_AUX 0xf8 #define CMD_AM 0xf7 #define CMD_PLAY_PAUSE 0xf6 #define CMD_STOP 0xf5 #define CMD_TUNE_UP 0xf4 #define CMD_TUNE_DOWN 0xf3 #define CMD_PRESET_1 0xf2 #define CMD_PRESET_2 0xf1 #define CMD_PRESET_3 0xf0 #define CMD_PRESET_4 0xef #define CMD_PRESET_5 0xee #define BOSEWAVE_BITS 8 #define BOSEWAVE_HEADER_MARK 1061 #define BOSEWAVE_HEADER_SPACE 1456 #define BOSEWAVE_BIT_MARK 534 #define BOSEWAVE_ONE_SPACE 468 #define BOSEWAVE_ZERO_SPACE 1447 #define BOSEWAVE_END_MARK 614 #define BOSEWAVE_REPEAT_SPACE 51200 //+============================================================================= #if SEND_BOSEWAVE unsigned int rawSignal[35]; void IRsend::sendBoseWave(unsigned char code) { int index = 0; // Header rawSignal[index++] = BOSEWAVE_HEADER_MARK; rawSignal[index++] = BOSEWAVE_HEADER_SPACE; // 8 bit command for (unsigned char mask = 0x80; mask; mask >>= 1) { rawSignal[index++] = BOSEWAVE_BIT_MARK; if (code & mask) { rawSignal[index++] = BOSEWAVE_ONE_SPACE; } else { rawSignal[index++] = BOSEWAVE_ZERO_SPACE; } } // 8 bit command complement for (unsigned char mask = 0x80; mask; mask >>= 1) { rawSignal[index++] = BOSEWAVE_BIT_MARK; if (code & mask) { rawSignal[index++] = BOSEWAVE_ZERO_SPACE; } else { rawSignal[index++] = BOSEWAVE_ONE_SPACE; } } // End transmission rawSignal[index++] = BOSEWAVE_END_MARK; // Transmit this->sendRaw(rawSignal, 35, 38); } #endif //+============================================================================= #if DECODE_BOSEWAVE bool IRrecv::decodeBoseWave() { unsigned char command = 0; // Decoded command unsigned char complement = 0; // Decoded command complement int index = 0; // Index in to results array DBG_PRINTLN("Decoding Bose Wave ..."); // Check we have enough data if (irparams.rawlen < (2 * BOSEWAVE_BITS * 2) + 3) { DBG_PRINT("\tInvalid data length found: "); DBG_PRINTLN(results.rawlen); return false; } // Check header "mark" index = 1; if (!MATCH_MARK(results.rawbuf[index], BOSEWAVE_HEADER_MARK)) { DBG_PRINT("\tInvalid Header Mark. Expecting "); DBG_PRINT(BOSEWAVE_HEADER_MARK); DBG_PRINT(". Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } index++; // Check header "space" if (!MATCH_SPACE(results.rawbuf[index], BOSEWAVE_HEADER_SPACE)) { DBG_PRINT("\tInvalid Header Space. Expecting "); DBG_PRINT(BOSEWAVE_HEADER_SPACE); DBG_PRINT(". Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } index++; // Decode the data bits for (int ii = 7; ii >= 0; ii--) { // Check bit "mark". Mark is always the same length. if (!MATCH_MARK(results.rawbuf[index], BOSEWAVE_BIT_MARK)) { DBG_PRINT("\tInvalid command Mark. Expecting "); DBG_PRINT(BOSEWAVE_BIT_MARK); DBG_PRINT(". Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } index++; // Check bit "space" if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ONE_SPACE)) { command |= (0x01 << ii); } else if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ZERO_SPACE)) { // Nothing to do for zeroes. } else { DBG_PRINT("\tInvalid command Space. Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } index++; } // Decode the command complement bits. We decode it here as the complement // of the complement (0=1 and 1=0) so we can easily compare it to the command. for (int ii = 7; ii >= 0; ii--) { // Check bit "mark". Mark is always the same length. if (!MATCH_MARK(results.rawbuf[index], BOSEWAVE_BIT_MARK)) { DBG_PRINT("\tInvalid complement Mark. Expecting "); DBG_PRINT(BOSEWAVE_BIT_MARK); DBG_PRINT(". Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } index++; // Check bit "space" if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ONE_SPACE)) { // Nothing to do. } else if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ZERO_SPACE)) { complement |= (0x01 << ii); } else { DBG_PRINT("\tInvalid complement Space. Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } index++; } if (command != complement) { DBG_PRINT("\tComplement is not correct. Command=0x"); DBG_PRINT(command, HEX); DBG_PRINT(" Complement=0x"); DBG_PRINTLN(complement, HEX); return false; } else { DBG_PRINTLN("\tValid command"); } // Check end "mark" if (MATCH_MARK(results.rawbuf[index], BOSEWAVE_END_MARK) == 0) { DBG_PRINT("\tInvalid end Mark. Got "); DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); return false; } // Success results.bits = BOSEWAVE_BITS; results.value = command; results.decode_type = BOSEWAVE; return true; } bool IRrecv::decodeBoseWave(decode_results *aResults) { bool aReturnValue = decodeBoseWave(); *aResults = results; return aReturnValue; } #endif