led selctor; ^ flashes led
[svn42.git] / rf433ctl / rf433ctl.pde
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <inttypes.h>
4 #include <OneWire.h>
5 #include <DallasTemperature.h>
6 #include <IRremote.h>
7
8 //********************************************************************//
9
10 #define RF_DATA_OUT_PIN 13
11 #define IR_MOVEMENT_PIN 9
12 #define ONE_WIRE_PIN 8
13 #define PANIC_BUTTON_PIN 7
14 #define PANICLED_PWM_PIN 6
15 #define BLUELED_PWM_PIN 11
16 #define PHOTO_ANALOGPIN 0
17 //movement is reported if during IR_SAMPLE_DURATION at least IR_TRESHOLD ir signals are detectd
18 #define IR_SAMPLE_DURATION 12000
19 #define IR_TRESHOLD 10000
20 //duration PanicButton needs to be pressed before status change occurs (i.e. for two PanicButton Reports, the buttons needs to be pressed 1000 cycles, releases 1000 cycles and again pressed 1000 cycles)
21 #define PB_TRESHOLD 1000
22 #define PHOTO_SAMPLE_INTERVAL 4000
23 #define IRREMOTE_SEND_PIN 3   //hardcoded in library
24 //WARNING IRremote Lib uses TCCR2
25
26 OneWire  onewire(ONE_WIRE_PIN);
27 DallasTemperature dallas_sensors(&onewire);
28 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
29 IRsend irsend; 
30 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT 
31
32 //********************************************************************//
33 // IR Codes, 32 bit, NEC
34 const int YAMAHA_CODE_BITS = 32;
35 const unsigned long int YAMAHA_CODE_BASE = 0x0000000005EA10000;
36
37 const char YAMAHA_POWER_TOGGLE =0xF8; //Power On/Off
38 const char YAMAHA_POWER_OFF =0x78; //Power Off !!!
39 const char YAMAHA_SLEEP =0xEA; //Toggle Sleep 120/90/60/30min or Off
40
41 const char YAMAHA_CD =0xA8; //Input CD
42 const char YAMAHA_TUNER =0x68; //Input Tuner
43 const char YAMAHA_TAPE =0x18; //Input Toggle Tape/CD
44 const char YAMAHA_DVD_SPDIF =0xE8; //Input Toggle DVD Auto / DVD Analog
45 const char YAMAHA_SAT_SPDIFF =0x2A; //Input Toggle Sat-DTV Auto / Sat-DTV Analog
46 const char YAMAHA_AUX =0xAA;  //Input AUX (mode)
47 const char YAMAHA_VCR =0xF0; //Input VCR
48 const char YAMAHA_EXT51DEC =0xE1; //Input Ext. Decoder On/Off
49
50 const char YAMAHA_TUNER_PLUS =0x08; //Tuner Next Station 1-7  (of A1 - E7)
51 const char YAMAHA_TUNER_ABCDE =0x48; //Tuner Next Station Row A-E (of A1 - E7)
52
53 const char YAMAHA_MUTE =0x38;
54 const char YAMAHA_VOLUME_UP =0x58;
55 const char YAMAHA_VOLUME_DOWN =0xD8;
56
57 //const char YAMAHA_FRONT_LEVEL_P =0x01;  //no function
58 //const char YAMAHA_FRONT_LEVEL_M =0x81; //no function
59 //const char YAMAHA_CENTRE_LEVEL_P =0x41;  //no function
60 //const char YAMAHA_CENTRE_LEVEL_M =0xC1; //no function
61 //const char YAMAHA_REAR_LEVEL_P =0x7A; //no function
62 //const char YAMAHA_REAR_LEVEL_M =0xFA; //no function
63 const char YAMAHA_PLUS =0x4A;  //unteres Steuerkreuz: Taste Rechts (Plus)
64 const char YAMAHA_MINUS =0xCA; //unteres Steuerkreuz: Taste Links (Minus)
65 const char YAMAHA_MENU =0x39; // Menu: Settings
66 const char YAMAHA_TEST =0xA1; // Test Sounds
67 const char YAMAHA_TIME_LEVEL =0x19; //Settings for Delay, Subwfs, Right Surround, Left Surround, Center
68 const char YAMAHA_TIME_LEVEL2 =0x61; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
69 const char YAMAHA_TIME_LEVEL3 =0x99; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
70
71 const char YAMAHA_EFFECT_TOGGLE =0x6A; //Effect Toggle On/Off
72 const char YAMAHA_PRG_DOWN =0x9A; //Effect/DSP Programm Toggle in down direction
73 const char YAMAHA_PRG_UP =0x1A; //Effect/DSP Programm Toggle in up direction
74 const char YAMAHA_EFFECT1 =0x31; //Effect TV Sports
75 const char YAMAHA_EFFECT2 =0x71; //Effect Rock Concert
76 const char YAMAHA_EFFECT3 =0xB1;  //Effect Disco
77 const char YAMAHA_EFFECT4 =0xD1;  //Mono Movie
78 const char YAMAHA_EFFECT5 =0x91; //Effect Toggle 70mm Sci-Fi / 70mm Spectacle
79 const char YAMAHA_EFFECT6 =0x51; //Effect Toggle 70mm General / 70mm Adventure
80 const char YAMAHA_P5 =0xFB; //P5 PRT (1 Main Bypass)? (1587674115)
81
82
83 void send_yamaha_ir_signal(char codebyte)
84 {
85   unsigned long int code = codebyte & 0xFF;
86   code <<= 8;
87   code |= (0xff ^ codebyte) & 0xFF;
88   code |= YAMAHA_CODE_BASE;
89   irsend.sendNEC(code,YAMAHA_CODE_BITS);
90   Serial.println("Ok");  
91 }
92
93 //********************************************************************//
94
95 typedef struct {
96   byte offset;
97   byte state;
98 } rf_bit_t;
99
100 // offset is number of alphas (0.08ms)
101
102 const rf_bit_t zero_bit[] = { {  4, 1 },
103                               { 16, 0 },
104                               { 20, 1 },
105                               { 32, 0 },
106                               {  0, 0 } };
107
108 const rf_bit_t one_bit[] = { { 12, 1 },
109                              { 16, 0 },
110                              { 28, 1 },
111                              { 32, 0 },
112                              {  0, 0 } };
113
114 const rf_bit_t float_bit[] = { {  4, 1 },
115                                { 16, 0 },
116                                { 28, 1 },
117                                { 32, 0 },
118                                {  0, 0 } };
119
120 const rf_bit_t sync_bit[] = { {   4, 1 },
121                               { 128, 0 },
122                               {   0, 0 } };
123
124 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
125 typedef byte ad_bit_t;
126 #define WORD_LEN 13
127 typedef ad_bit_t word_t[WORD_LEN];
128
129 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
130
131 byte alpha_cnt = 0;
132 byte bit_cnt = 0;
133 byte chunk_cnt = 0;
134 byte word_cnt = 0;
135 const ad_bit_t* current_word;
136 byte volatile frame_finished = 1;
137
138 #define FRAME_LEN 8
139
140 #define A1_ON  0
141 #define A1_OFF 1
142 #define A2_ON  2
143 #define A2_OFF 3
144
145 #define B1_ON  4
146 #define B1_OFF 5
147 #define B2_ON  6
148 #define B2_OFF 7
149
150 #define C1_ON  8
151 #define C1_OFF 9
152 #define C2_ON  10
153 #define C2_OFF 11
154
155 #define D1_ON  12
156 #define D1_OFF 13
157 #define D2_ON  14
158 #define D2_OFF 15
159
160 const word_t words[]  = { 
161 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
162 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A1_OFF
163 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
164 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A2_OFF
165
166 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
167 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B1_OFF
168 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
169 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B2_OFF
170
171 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
172 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C1_OFF
173 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
174 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C2_OFF
175
176 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
177 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // D1_OFF
178 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
179 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }  // D2_OFF
180 };
181
182
183 //********************************************************************//
184
185 void start_timer()
186 {
187   // timer 1: 2 ms
188   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
189   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
190   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
191 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
192   TCNT1 = 0;          // reseting timer
193   TIMSK1 = 1<<OCIE1A; // enable Interrupt
194 }
195
196 void stop_timer() // stop the timer
197 {
198   // timer1
199   TCCR1B = 0; // no clock source
200   TIMSK1 = 0; // disable timer interrupt
201 }
202
203 void init_word(const word_t w)
204 {
205   current_word = w;
206   alpha_cnt = 0;
207   chunk_cnt = 0;
208   bit_cnt = 0;
209
210   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
211     digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
212   else
213     digitalWrite(RF_DATA_OUT_PIN, HIGH);
214
215   start_timer();
216 }
217
218 ISR(TIMER1_COMPA_vect)
219 {
220   alpha_cnt++;
221   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
222     return;
223
224   chunk_cnt++;
225   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
226     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
227       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
228     else
229       digitalWrite(RF_DATA_OUT_PIN, HIGH);
230     return;
231   }
232   
233   bit_cnt++;
234   if(bit_cnt < WORD_LEN) {
235     alpha_cnt = 0;
236     chunk_cnt = 0;
237     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
238       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
239     else
240       digitalWrite(RF_DATA_OUT_PIN, HIGH);
241     return;
242   }
243   stop_timer();
244   digitalWrite(RF_DATA_OUT_PIN, HIGH);
245
246   word_cnt++;
247   if(word_cnt < FRAME_LEN)
248     init_word(current_word);
249   else
250     frame_finished = 2;
251 }
252
253 //***********//
254
255
256 void send_frame(const word_t w)
257 {
258   if (frame_finished == 0)
259     for(;;)
260       if (frame_finished)
261       {
262         delay(150);
263         break;
264       }
265   word_cnt = 0;
266   frame_finished = 0;
267   init_word(w);      
268 }
269
270 void check_frame_done()
271 {
272   if (frame_finished==2)
273   {
274     Serial.println("Ok");
275     frame_finished=1;
276   }
277 }
278
279 //********************************************************************//
280
281 void printTemperature(DeviceAddress deviceAddress)
282 {
283   dallas_sensors.requestTemperatures();
284   float tempC = dallas_sensors.getTempC(deviceAddress);
285   //Serial.print("Temp C: ");
286   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
287   //Serial.print(" Temp F: ");
288   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
289 }
290
291 //********************************************************************//
292
293 unsigned int light_level_mean_ = 0;
294 unsigned int light_sample_time_ = 0;
295
296 void updateLightLevel(unsigned int pin)
297 {
298   light_sample_time_++;
299   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
300     return;
301   light_sample_time_ = 0;
302   
303   unsigned int value = analogRead(pin);
304   if (value == light_level_mean_)
305     return;
306   
307   unsigned int diff = abs(value - light_level_mean_);
308   if (diff > 100)
309     light_level_mean_ = value;
310   else
311       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
312 }
313
314 void printLightLevel()
315 {
316   //Serial.print("Photo: ");
317   Serial.println(light_level_mean_);
318 }
319
320 //********************************************************************//
321
322 unsigned long wm_start_=0;
323 bool wait_millis(unsigned long ms)
324 {
325   if (wm_start_ > 0)
326   {
327     if (millis() < wm_start_ || millis() > wm_start_+ ms)
328     {
329       wm_start_=0;
330       return false;
331     }
332     else
333       return true;
334   }
335   else
336   {
337     wm_start_=millis();
338     return true;
339   }
340 }
341
342 unsigned int flash_led_time_=0;
343 unsigned int flash_led_brightness_=255;
344 unsigned int flash_led_delay_=8;
345 unsigned int flash_led_selected_=0;
346 void calculate_led_level()
347 {
348   if (flash_led_time_ == 0 || flash_led_selected_ == 0)
349     return;
350   if (wait_millis(flash_led_delay_))
351     return;
352   flash_led_time_--;
353   int c = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
354   //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
355   if (flash_led_selected_ && (1 << BLUELED_PWM_PIN))
356     analogWrite(BLUELED_PWM_PIN, 255-c);
357   else
358     analogWrite(BLUELED_PWM_PIN,255); //off
359   if (flash_led_selected_ && (1 << PANICLED_PWM_PIN))
360   {
361     if (flash_led_time_)
362       analogWrite(PANICLED_PWM_PIN, c);
363     else
364       analogWrite(PANICLED_PWM_PIN, 255-c);
365   }
366   else
367     analogWrite(PANICLED_PWM_PIN,255); //off
368 }
369
370 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int led_selector)
371 {
372   unsigned int new_flash_led_brightness = 255;
373   unsigned int new_flash_led_delay = 8;
374   flash_led_selected_=led_selector;
375   if (times == 0 || led_selector == 0)
376   {
377     analogWrite(PANICLED_PWM_PIN,255); //off
378     analogWrite(BLUELED_PWM_PIN,255); //off
379     return;
380   }
381   if (brightness_divisor > 1) //guard against div by zero
382     new_flash_led_brightness /= brightness_divisor;
383   if (delay_divisor > 1)  //guard against div by zero
384     new_flash_led_delay /= delay_divisor;
385   if (flash_led_time_ == 0 || new_flash_led_brightness > flash_led_brightness_)
386     flash_led_brightness_=new_flash_led_brightness;
387   if (flash_led_time_ == 0 || new_flash_led_delay < flash_led_delay_)
388     flash_led_delay_=new_flash_led_delay;
389   flash_led_time_ += 314*times;
390 }
391
392 //********************************************************************//
393
394 void setup()
395 {
396   pinMode(RF_DATA_OUT_PIN, OUTPUT);
397   digitalWrite(RF_DATA_OUT_PIN, HIGH);
398   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
399   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pulldown resistors  
400   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
401   digitalWrite(PANIC_BUTTON_PIN, LOW);  // turn on pulldown resistors 
402   analogWrite(PANICLED_PWM_PIN,255);
403   analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
404   pinMode(IRREMOTE_SEND_PIN, OUTPUT);
405   digitalWrite(IRREMOTE_SEND_PIN, HIGH);
406   
407   Serial.begin(9600);
408   
409   onewire.reset();
410   onewire.reset_search();
411   dallas_sensors.begin();
412   //in case we change temp sensor:
413   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
414     Serial.println("Error: Unable to find address for Device 0"); 
415   dallas_sensors.setResolution(onShieldTemp, 9);  
416 }
417
418 unsigned int ir_time=IR_SAMPLE_DURATION;
419 unsigned int ir_count=0;
420 boolean pb_last_state=0;
421 boolean pb_state=0;
422 boolean pb_postth_state=0;
423 unsigned int pb_time=0;
424
425 void sensorEchoCommand(char command)
426 {
427   Serial.print("Sensor ");
428   Serial.print(command);
429   Serial.print(": ");
430 }
431
432 void loop()
433 {
434   ir_time--;
435   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
436
437   if (pb_time < PB_TRESHOLD)
438     pb_time++;
439   pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
440   
441   if (ir_time == 0)
442   {
443     if (ir_count >= IR_TRESHOLD)
444     {
445       flash_led(1, 8, 1, (1<<BLUELED_PWM_PIN) );
446       Serial.println("movement");
447     }
448     ir_time=IR_SAMPLE_DURATION;
449     ir_count=0;
450   }
451   
452   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
453   {
454     if (pb_state && ! pb_postth_state)
455     {   
456       pb_postth_state=1;
457       Serial.println("PanicButton");
458       flash_led(14, 1, 2, (1<<BLUELED_PWM_PIN)|(1<<PANICLED_PWM_PIN) );
459     }
460     else if (!pb_state)
461       pb_postth_state=0;
462   }
463   else if (pb_state != pb_last_state)
464   {
465     pb_time=0;
466     pb_last_state=pb_state;
467   }
468   
469   updateLightLevel(PHOTO_ANALOGPIN);
470   calculate_led_level();
471   check_frame_done();
472   
473   if(Serial.available()) {
474     char command = Serial.read();
475     
476     if(command == 'A')
477       send_frame(words[A1_ON]);
478     else if(command == 'a')
479       send_frame(words[A1_OFF]);
480     else if(command == 'B')
481       send_frame(words[A2_ON]);
482     else if(command == 'b')
483       send_frame(words[A2_OFF]);
484
485     else if(command == 'C')
486       send_frame(words[B1_ON]);
487     else if(command == 'c')
488       send_frame(words[B1_OFF]);
489     else if(command == 'D')
490       send_frame(words[B2_ON]);
491     else if(command == 'd')
492       send_frame(words[B2_OFF]);
493
494     else if(command == 'E')
495       send_frame(words[C1_ON]);
496     else if(command == 'e')
497       send_frame(words[C1_OFF]);
498     else if(command == 'F')
499       send_frame(words[C2_ON]);
500     else if(command == 'f')
501       send_frame(words[C2_OFF]);
502
503     else if(command == 'G')
504       send_frame(words[D1_ON]);
505     else if(command == 'g')
506       send_frame(words[D1_OFF]);
507     else if(command == 'H')
508       send_frame(words[D2_ON]);
509     else if(command == 'h')
510       send_frame(words[D2_OFF]);
511     else if(command == 'T')
512     {
513       sensorEchoCommand(command);
514       printTemperature(onShieldTemp);
515     }
516     else if(command == 'P')
517     {
518       sensorEchoCommand(command);
519       printLightLevel();
520     }
521     else if (command == '^')
522       flash_led(1, 2, 1, (1 << PANICLED_PWM_PIN));
523     else if (command == '0')
524       send_yamaha_ir_signal(YAMAHA_POWER_OFF);
525     else if (command == '1')
526       send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
527     else if (command == '2')
528       send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
529     else if (command == '3')
530       send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
531     else if (command == '4')
532       send_yamaha_ir_signal(YAMAHA_MUTE);
533     else if (command == '5')
534       send_yamaha_ir_signal(YAMAHA_CD);
535     else if (command == '6')
536       send_yamaha_ir_signal(YAMAHA_TUNER);
537     else if (command == '7')
538       send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
539     else if (command == '8')
540       send_yamaha_ir_signal(YAMAHA_MENU);
541     else if (command == '+')
542       send_yamaha_ir_signal(YAMAHA_PLUS);    
543     else if (command == '-')
544       send_yamaha_ir_signal(YAMAHA_MINUS);    
545     else if (command == '§')
546       send_yamaha_ir_signal(YAMAHA_TEST);    
547     else if (command == '$')
548       send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);    
549     else if (command == '%')
550       send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);    
551     else if (command == '&')
552       send_yamaha_ir_signal(YAMAHA_PRG_DOWN);    
553     else if (command == '/')
554       send_yamaha_ir_signal(YAMAHA_PRG_UP);    
555     else if (command == '(')
556       send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);    
557     else if (command == ')')
558       send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);    
559     else if (command == '9')
560       send_yamaha_ir_signal(YAMAHA_TAPE);    
561     else if (command == '?')
562       send_yamaha_ir_signal(YAMAHA_VCR);    
563     else if (command == '=')
564       send_yamaha_ir_signal(YAMAHA_EXT51DEC);    
565     else
566       Serial.println("Error: unknown command");
567   }
568 }