IRremote
ir_BoseWave.cpp
Go to the documentation of this file.
1 #include "IRremote.h"
2 
3 //==============================================================================
4 // BBBB OOO SSSS EEEEE
5 // B B O O S E
6 // BB B O O SSS EEEE
7 // B B O O S E
8 // BBBB OOO SSSS EEEEE
9 //==============================================================================
10 //
11 // Bose Wave Radio CD Remote Control
12 // |-------------------------------------|
13 // | On/Off Sleep VolUp |
14 // | Play/Pause Stop VolDown |
15 // | FM AM Aux |
16 // | Tune Down Tune Up Mute |
17 // | 1 2 3 |
18 // | 4 5 6 |
19 // |-------------------------------------|
20 //
21 // Support for Bose Wave Radio CD provided by https://github.com/uvotguy.
22 //
23 // This protocol was reverse engineered by capturing IR signals from a working
24 // remote. Multiple signals were captured on my oscilloscope, and the timing
25 // values were averaged.
26 //
27 // IR codes are 8 bits. Transmission starts with a header: a mark and a space.
28 // The header is followed by an 8-bit command, where a bit is a mark and a short
29 // space (1) or a long space (0). The command is followed by the complement of
30 // the command (8 bits). A transmission ends with a short mark.
31 //
32 // As seen on my trusty oscilloscope, there is no repeat code. Instead, when I
33 // press and hold a button on my remote, it sends a command, makes a 51.2ms space,
34 // and resends the command, etc, etc.
35 //
36 // It may be worth noting that these values do NOT match those in the LIRC
37 // remote database (http://lirc.sourceforge.net/remotes/bose/).
38 
39 #define CMD_ON_OFF 0xff
40 #define CMD_MUTE 0xfe
41 #define CMD_VOL_UP 0xfd
42 #define CMD_VOL_DOWN 0xfc
43 #define CMD_PRESET_6 0xfb
44 #define CMD_SLEEP 0xfa
45 #define CMD_FM 0xf9
46 #define CMD_AUX 0xf8
47 #define CMD_AM 0xf7
48 #define CMD_PLAY_PAUSE 0xf6
49 #define CMD_STOP 0xf5
50 #define CMD_TUNE_UP 0xf4
51 #define CMD_TUNE_DOWN 0xf3
52 #define CMD_PRESET_1 0xf2
53 #define CMD_PRESET_2 0xf1
54 #define CMD_PRESET_3 0xf0
55 #define CMD_PRESET_4 0xef
56 #define CMD_PRESET_5 0xee
57 
58 #define BOSEWAVE_BITS 8
59 #define BOSEWAVE_HDR_MARK 1061
60 #define BOSEWAVE_HDR_SPACE 1456
61 #define BOSEWAVE_BIT_MARK 534
62 #define BOSEWAVE_ONE_SPACE 468
63 #define BOSEWAVE_ZERO_SPACE 1447
64 #define BOSEWAVE_END_MARK 614
65 #define BOSEWAVE_RPT_SPACE 51200
66 
67 //+=============================================================================
68 #if SEND_BOSEWAVE
69 unsigned int rawSignal[35];
70 void IRsend::sendBoseWave(unsigned char code) {
71 
72  int index = 0;
73  // Header
74  rawSignal[index++] = BOSEWAVE_HDR_MARK;
75  rawSignal[index++] = BOSEWAVE_HDR_SPACE;
76 
77  // 8 bit command
78  for (unsigned char mask = 0x80; mask; mask >>= 1) {
79  rawSignal[index++] = BOSEWAVE_BIT_MARK;
80  if (code & mask) {
81  rawSignal[index++] = BOSEWAVE_ONE_SPACE;
82  } else {
83  rawSignal[index++] = BOSEWAVE_ZERO_SPACE;
84  }
85  }
86 
87  // 8 bit command complement
88  for (unsigned char mask = 0x80; mask; mask >>= 1) {
89  rawSignal[index++] = BOSEWAVE_BIT_MARK;
90  if (code & mask) {
91  rawSignal[index++] = BOSEWAVE_ZERO_SPACE;
92  } else {
93  rawSignal[index++] = BOSEWAVE_ONE_SPACE;
94  }
95  }
96  // End transmission
97  rawSignal[index++] = BOSEWAVE_END_MARK;
98 
99  // Transmit
100  this->sendRaw(rawSignal, 35, 38);
101 }
102 #endif
103 
104 //+=============================================================================
105 #if DECODE_BOSEWAVE
106 bool IRrecv::decodeBoseWave(decode_results *results) {
107  unsigned char command = 0; // Decoded command
108  unsigned char complement = 0; // Decoded command complement
109 
110  int index = 0; // Index in to results array
111 
112  DBG_PRINTLN("Decoding Bose Wave ...");
113 
114  // Check we have enough data
115  if (irparams.rawlen < (2 * BOSEWAVE_BITS * 2) + 3) {
116  DBG_PRINT("\tInvalid data length found: ");
117  DBG_PRINTLN(results->rawlen);
118  return false;
119  }
120 
121  // Check header "mark"
122  index = 1;
123  if (!MATCH_MARK(results->rawbuf[index], BOSEWAVE_HDR_MARK)) {
124  DBG_PRINT("\tInvalid Header Mark. Expecting ");
126  DBG_PRINT(". Got ");
127  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
128  return false;
129  }
130  index++;
131 
132  // Check header "space"
133  if (!MATCH_SPACE(results->rawbuf[index], BOSEWAVE_HDR_SPACE)) {
134  DBG_PRINT("\tInvalid Header Space. Expecting ");
136  DBG_PRINT(". Got ");
137  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
138  return false;
139  }
140  index++;
141 
142  // Decode the data bits
143  for (int ii = 7; ii >= 0; ii--) {
144  // Check bit "mark". Mark is always the same length.
145  if (!MATCH_MARK(results->rawbuf[index], BOSEWAVE_BIT_MARK)) {
146  DBG_PRINT("\tInvalid command Mark. Expecting ");
148  DBG_PRINT(". Got ");
149  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
150  return false;
151  }
152  index++;
153 
154  // Check bit "space"
155  if (MATCH_SPACE(results->rawbuf[index], BOSEWAVE_ONE_SPACE)) {
156  command |= (0x01 << ii);
157  } else if (MATCH_SPACE(results->rawbuf[index], BOSEWAVE_ZERO_SPACE)) {
158  // Nothing to do for zeroes.
159  } else {
160  DBG_PRINT("\tInvalid command Space. Got ");
161  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
162  return false;
163  }
164  index++;
165  }
166 
167  // Decode the command complement bits. We decode it here as the complement
168  // of the complement (0=1 and 1=0) so we can easily compare it to the command.
169  for (int ii = 7; ii >= 0; ii--) {
170  // Check bit "mark". Mark is always the same length.
171  if (!MATCH_MARK(results->rawbuf[index], BOSEWAVE_BIT_MARK)) {
172  DBG_PRINT("\tInvalid complement Mark. Expecting ");
174  DBG_PRINT(". Got ");
175  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
176  return false;
177  }
178  index++;
179 
180  // Check bit "space"
181  if (MATCH_SPACE(results->rawbuf[index], BOSEWAVE_ONE_SPACE)) {
182  // Nothing to do.
183  } else if (MATCH_SPACE(results->rawbuf[index], BOSEWAVE_ZERO_SPACE)) {
184  complement |= (0x01 << ii);
185  } else {
186  DBG_PRINT("\tInvalid complement Space. Got ");
187  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
188  return false;
189  }
190  index++;
191  }
192 
193  if (command != complement) {
194  DBG_PRINT("\tComplement is not correct. Command=0x");
195  DBG_PRINT(command, HEX);
196  DBG_PRINT(" Complement=0x");
197  DBG_PRINTLN(complement, HEX);
198  return false;
199  } else {
200  DBG_PRINTLN("\tValid command");
201  }
202 
203  // Check end "mark"
204  if (MATCH_MARK(results->rawbuf[index], BOSEWAVE_END_MARK) == 0) {
205  DBG_PRINT("\tInvalid end Mark. Got ");
206  DBG_PRINTLN(results->rawbuf[index] * USECPERTICK);
207  return false;
208  }
209 
210  // Success
211  results->bits = BOSEWAVE_BITS;
212  results->value = command;
213  results->decode_type = BOSEWAVE;
214 
215  return true;
216 }
217 #endif
BOSEWAVE_ONE_SPACE
#define BOSEWAVE_ONE_SPACE
Definition: ir_BoseWave.cpp:62
decode_results
Results returned from the decoder.
Definition: IRremote.h:174
decode_results::bits
int bits
Number of bits in decoded value.
Definition: IRremote.h:179
DBG_PRINTLN
#define DBG_PRINTLN(...)
If DEBUG, print the arguments as a line, otherwise do nothing.
Definition: IRremote.h:155
decode_results::rawbuf
volatile unsigned int * rawbuf
Raw intervals in 50uS ticks.
Definition: IRremote.h:180
BOSEWAVE_END_MARK
#define BOSEWAVE_END_MARK
Definition: ir_BoseWave.cpp:64
decode_results::decode_type
decode_type_t decode_type
UNKNOWN, NEC, SONY, RC5, ...
Definition: IRremote.h:176
DBG_PRINT
#define DBG_PRINT(...)
If DEBUG, print the arguments, otherwise do nothing.
Definition: IRremote.h:151
BOSEWAVE_HDR_MARK
#define BOSEWAVE_HDR_MARK
Definition: ir_BoseWave.cpp:59
MATCH_SPACE
int MATCH_SPACE(int measured_ticks, int desired_us)
Definition: IRremote.cpp:89
irparams
volatile irparams_t irparams
Allow all parts of the code access to the ISR data NB.
IRsend::sendBoseWave
void sendBoseWave(unsigned char code)
Definition: ir_BoseWave.cpp:70
rawSignal
unsigned int rawSignal[35]
Definition: ir_BoseWave.cpp:69
USECPERTICK
#define USECPERTICK
Definition: IRremoteBoardDefs.h:166
BOSEWAVE
@ BOSEWAVE
Definition: IRremote.h:133
BOSEWAVE_ZERO_SPACE
#define BOSEWAVE_ZERO_SPACE
Definition: ir_BoseWave.cpp:63
BOSEWAVE_BIT_MARK
#define BOSEWAVE_BIT_MARK
Definition: ir_BoseWave.cpp:61
BOSEWAVE_HDR_SPACE
#define BOSEWAVE_HDR_SPACE
Definition: ir_BoseWave.cpp:60
BOSEWAVE_BITS
#define BOSEWAVE_BITS
Definition: ir_BoseWave.cpp:58
IRremote.h
Public API to the library.
decode_results::value
unsigned long value
Decoded value [max 32-bits].
Definition: IRremote.h:178
MATCH_MARK
int MATCH_MARK(int measured_ticks, int desired_us)
Definition: IRremote.cpp:63
decode_results::rawlen
unsigned int rawlen
Number of records in rawbuf.
Definition: IRremote.h:181
irparams_t::rawlen
unsigned int rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:45
IRsend::sendRaw
void sendRaw(const unsigned int buf[], unsigned int len, unsigned int hz)
Definition: irSend.cpp:5