to github
[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 IR_MOVEMENT_PIN2 12
13 #define ONE_WIRE_PIN 8
14 #define PANIC_BUTTON_PIN 7
15 #define PANICLED_PWM_PIN 6
16 #define BLUELED_PWM_PIN 11
17 #define PHOTO_ANALOGPIN 0
18 //movement is reported if during IR_SAMPLE_DURATION at least IR_TRESHOLD ir signals are detectd
19 #define IR_SAMPLE_DURATION 6000
20 #define IR_TRESHOLD 5900
21 //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)
22 #define PB_TRESHOLD 1000
23 #define PHOTO_SAMPLE_INTERVAL 4000
24 #define IRREMOTE_SEND_PIN 3   //hardcoded in library
25 //WARNING IRremote Lib uses TCCR2
26
27 OneWire  onewire(ONE_WIRE_PIN);
28 DallasTemperature dallas_sensors(&onewire);
29 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
30 IRsend irsend;
31 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT
32
33 //********************************************************************//
34 // IR Codes, 32 bit, NEC
35 const int YAMAHA_CODE_BITS = 32;
36 const unsigned long int YAMAHA_CODE_BASE = 0x0000000005EA10000;
37
38 const char YAMAHA_POWER_TOGGLE =0xF8; //Power On/Off
39 const char YAMAHA_POWER_OFF =0x78; //Power Off !!!
40 const char YAMAHA_SLEEP =0xEA; //Toggle Sleep 120/90/60/30min or Off
41
42 const char YAMAHA_CD =0xA8; //Input CD
43 const char YAMAHA_TUNER =0x68; //Input Tuner
44 const char YAMAHA_TAPE =0x18; //Input Toggle Tape/CD
45 const char YAMAHA_DVD_SPDIF =0xE8; //Input Toggle DVD Auto / DVD Analog
46 const char YAMAHA_SAT_SPDIFF =0x2A; //Input Toggle Sat-DTV Auto / Sat-DTV Analog
47 const char YAMAHA_AUX =0xAA;  //Input AUX (mode)
48 const char YAMAHA_VCR =0xF0; //Input VCR
49 const char YAMAHA_EXT51DEC =0xE1; //Input Ext. Decoder On/Off
50
51 const char YAMAHA_TUNER_PLUS =0x08; //Tuner Next Station 1-7  (of A1 - E7)
52 const char YAMAHA_TUNER_MINUS =0x88; //Tuner Prev Station 1-7  (of A1 - E7)
53 const char YAMAHA_TUNER_ABCDE =0x48; //Tuner Next Station Row A-E (of A1 - E7)
54
55 const char YAMAHA_MUTE =0x38;
56 const char YAMAHA_VOLUME_UP =0x58;
57 const char YAMAHA_VOLUME_DOWN =0xD8;
58
59 //const char YAMAHA_FRONT_LEVEL_P =0x01;  //no function
60 //const char YAMAHA_FRONT_LEVEL_M =0x81; //no function
61 //const char YAMAHA_CENTRE_LEVEL_P =0x41;  //no function
62 //const char YAMAHA_CENTRE_LEVEL_M =0xC1; //no function
63 //const char YAMAHA_REAR_LEVEL_P =0x7A; //no function
64 //const char YAMAHA_REAR_LEVEL_M =0xFA; //no function
65 const char YAMAHA_PLUS =0x4A;  //unteres Steuerkreuz: Taste Rechts (Plus)
66 const char YAMAHA_MINUS =0xCA; //unteres Steuerkreuz: Taste Links (Minus)
67 const char YAMAHA_MENU =0x39; // Menu: Settings
68 const char YAMAHA_TEST =0xA1; // Test Sounds
69 const char YAMAHA_TIME_LEVEL =0x19; //Settings for Delay, Subwfs, Right Surround, Left Surround, Center
70 const char YAMAHA_TIME_LEVEL2 =0x61; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
71 const char YAMAHA_TIME_LEVEL3 =0x99; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
72
73 const char YAMAHA_EFFECT_TOGGLE =0x6A; //Effect Toggle On/Off
74 const char YAMAHA_PRG_DOWN =0x9A; //Effect/DSP Programm Toggle in down direction
75 const char YAMAHA_PRG_UP =0x1A; //Effect/DSP Programm Toggle in up direction
76 const char YAMAHA_EFFECT1 =0x31; //Effect TV Sports
77 const char YAMAHA_EFFECT2 =0x71; //Effect Rock Concert
78 const char YAMAHA_EFFECT3 =0xB1;  //Effect Disco
79 const char YAMAHA_EFFECT4 =0xD1;  //Mono Movie
80 const char YAMAHA_EFFECT5 =0x91; //Effect Toggle 70mm Sci-Fi / 70mm Spectacle
81 const char YAMAHA_EFFECT6 =0x51; //Effect Toggle 70mm General / 70mm Adventure
82 const char YAMAHA_P5 =0xFB; //P5 PRT (1 Main Bypass)? (1587674115)
83
84 //********************************************************************//
85
86 #define TIMER_RUNNING (TIMSK1 & (1<<OCIE1A))
87
88 void start_timer()
89 {
90   // timer 1: 2 ms
91   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
92   TCCR1B = 1<<WGM12 | 1<<CS11;   //
93 //  OCR1A = 39;        // (1+39)*8 = 320 -> 0.02ms @ 16 MHz -> 1*alpha
94 //default: alpha=0.08
95   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
96 //  OCR1A = 154;        // (1+154)*8 = 1240 -> 0.0775ms @ 16 MHz -> 1*alpha
97 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
98   TCNT1 = 0;          // reseting timer
99   TIMSK1 = 1<<OCIE1A; // enable Interrupt
100 }
101
102 void stop_timer() // stop the timer
103 {
104   // timer1
105   TCCR1B = 0; // no clock source
106   TIMSK1 = 0; // disable timer interrupt
107 }
108
109 #define NUM_REPEAT_SIGNAL 8
110 #define RF_SIGNAL_BYTES 3
111 #define RF_SIGNAL_BITS RF_SIGNAL_BYTES * 8
112
113 typedef struct {
114   byte duration_short_pulse;  //mulitple of 0.08ms, should be === 0 (mod 4)
115   byte short_mult;
116   byte long_mult;
117   byte sync_mult;
118   byte signal[RF_SIGNAL_BYTES];  //24bit signal info, excluding sync signal (short 1 followed by long pause (~128*0.08ms))
119                             //for each bit: 0 means 1/4 Tau high followed by 3/4 Tau low;    1 means 3/4 Tau high followed by 1/4 Tau low
120 } rf_signal;
121
122 rf_signal current_signal = {6, 1, 3, 31, {0,0,0}};
123
124 typedef struct {
125   byte atime; // time counter
126   byte bit;  //index for current bit
127   byte repeatc; //downward couner of repetition
128   byte state; // current output to RF Pin (position within the bit)
129 } rf_state;
130
131 rf_state current_state = { 0, 0, 0, 0};
132 int rf_num_transmissions_to_acknowledge = 0;
133
134 #define CURRENT_BIT_CNT (RF_SIGNAL_BITS - current_state.bit - 1)
135 #define CURRENT_BIT (( current_signal.signal[ CURRENT_BIT_CNT/8] >> (CURRENT_BIT_CNT % 8)  )& 1)
136 #define RF_TIME_SHORT (current_signal.short_mult * current_signal.duration_short_pulse)
137 #define RF_TIME_LONG (current_signal.long_mult * current_signal.duration_short_pulse)
138 #define RF_TIME_SNYC (current_signal.sync_mult * current_signal.duration_short_pulse)
139 #define RF_OFF digitalWrite(RF_DATA_OUT_PIN, HIGH)
140 #define RF_ON digitalWrite(RF_DATA_OUT_PIN, LOW)
141 ISR(TIMER1_COMPA_vect)
142 {
143   if ( current_state.state || current_state.bit || current_state.repeatc || current_state.atime)
144   {
145     if (current_state.atime)
146     {
147        current_state.atime--;
148     }
149     //atime ran out
150     else if (current_state.state) //was in state 1 or 2
151     {
152       RF_OFF;  //stop sending
153       if (current_state.state == 2) //aka sync
154         current_state.atime=RF_TIME_SNYC;
155       else
156         current_state.atime=CURRENT_BIT?
157            RF_TIME_SHORT
158           :RF_TIME_LONG;
159       current_state.state=0;
160     } 
161     else if  (current_state.bit)  //still more than 0 bits to do
162     {
163       current_state.bit--;
164       current_state.state=1;
165       current_state.atime=CURRENT_BIT?
166            RF_TIME_LONG
167           :RF_TIME_SHORT;
168       RF_ON;  //start sending
169     }
170     else if (current_state.repeatc) 
171     {
172       current_state.bit=RF_SIGNAL_BITS;
173       current_state.repeatc--;
174       current_state.state=2;
175       //start sync (short pulse followed by long pause)
176       RF_ON;
177       current_state.atime=RF_TIME_SHORT;
178     }
179   }
180   else
181   {
182     stop_timer();
183     RF_OFF;
184     rf_num_transmissions_to_acknowledge++;
185   }
186 }
187 //********************************************************************//
188
189 void serial_read_send_rf_cmd()
190 {
191   while (TIMER_RUNNING)
192   {}
193   for (byte chr=0; chr < 3; chr++)
194   {
195     while (!Serial.available())
196     {}
197     current_signal.signal[chr]=Serial.read();
198   }
199   current_state.repeatc=NUM_REPEAT_SIGNAL;
200   start_timer();
201 }
202
203 void send_rf_cmd(const char sr[])
204 {
205   while (TIMER_RUNNING)
206   {}
207   for (byte chr=0; chr < 3; chr++)
208   {
209     current_signal.signal[chr]=sr[chr];
210   }
211   current_state.repeatc=NUM_REPEAT_SIGNAL;
212   start_timer();
213 }
214
215 void check_frame_done()
216 {
217   while (rf_num_transmissions_to_acknowledge > 0)
218   {
219     rf_num_transmissions_to_acknowledge--;
220     Serial.println("Ok");
221   }
222 }
223
224 //********************************************************************//
225
226 void printTemperature(DeviceAddress deviceAddress)
227 {
228   dallas_sensors.requestTemperatures();
229   float tempC = dallas_sensors.getTempC(deviceAddress);
230   //Serial.print("Temp C: ");
231   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
232   //Serial.print(" Temp F: ");
233   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
234 }
235
236 //********************************************************************//
237
238 unsigned int light_level_mean_ = 0;
239 unsigned int light_sample_time_ = 0;
240
241 void updateLightLevel(unsigned int pin)
242 {
243   light_sample_time_++;
244   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
245     return;
246   light_sample_time_ = 0;
247
248   unsigned int value = analogRead(pin);
249   if (value == light_level_mean_)
250     return;
251
252   unsigned int diff = abs(value - light_level_mean_);
253   if (diff > 100)
254     light_level_mean_ = value;
255   else
256       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
257 }
258
259 void printLightLevel()
260 {
261   //Serial.print("Photo: ");
262   Serial.println(light_level_mean_);
263 }
264
265 //********************************************************************//
266
267 unsigned long wm_start_[3]={0,0,0};
268 bool wait_millis(unsigned long *start_time, unsigned long ms)
269 {
270   if (ms == 0)
271     return false;
272   else if (*start_time > 0)
273   {
274     if (millis() < *start_time || millis() > (*start_time) + ms)
275     {
276       *start_time = 0;
277       return false;
278     }
279     else
280       return true;
281   }
282   else
283   {
284     *start_time=millis();
285     return true;
286   }
287 }
288 #define NUM_LEDS 2
289 char flash_led_pins_[NUM_LEDS]={BLUELED_PWM_PIN,PANICLED_PWM_PIN};
290 unsigned int flash_led_time_[3]={0,0,0};
291 unsigned int flash_led_brightness_[3]={255,255,255};
292 unsigned int flash_led_delay_[3]={8,8,8};
293 unsigned int flash_led_initial_delay_[3]={0,0,0};
294 void calculate_led_level()
295 {
296   for (int ledid = 0; ledid < NUM_LEDS; ledid++)
297   {
298     if (flash_led_time_[ledid] == 0)
299       continue;
300     if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
301       continue;
302     flash_led_initial_delay_[ledid]=0;
303     if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
304       continue;
305     flash_led_time_[ledid]--;
306     int c = abs(sin(float(flash_led_time_[ledid]) / 100.0)) * flash_led_brightness_[ledid];
307     //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
308     analogWrite(flash_led_pins_[ledid], 255-c);
309   }
310 }
311
312 // id: id of LED to flash (0,1)
313 // times: # of times the LED should flash
314 // brightness_divisor: 1: full brightness, 2: half brightness, ...
315 // delay_divisor: 1: slow... 8: fastest
316 // phase_divisor: 0.. same phase; 2.. pi/2 phase, 4.. pi phase, 6.. 3pi/2 phase
317 void flash_led(unsigned int id, unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int phase_divisor)
318 {
319   if (id >= NUM_LEDS)
320     return;
321   unsigned int new_flash_led_brightness = 255;
322   unsigned int new_flash_led_delay = 8;
323   if (times == 0)
324   {
325     analogWrite(flash_led_pins_[id],255); //off
326     return;
327   }
328   if (brightness_divisor > 1) //guard against div by zero
329     new_flash_led_brightness /= brightness_divisor;
330   if (delay_divisor > 1)  //guard against div by zero
331     new_flash_led_delay /= delay_divisor;
332   if (flash_led_time_[id] == 0 || new_flash_led_brightness > flash_led_brightness_[id])
333     flash_led_brightness_[id]=new_flash_led_brightness;
334   if (flash_led_time_[id] == 0 || new_flash_led_delay < flash_led_delay_[id])
335     flash_led_delay_[id]=new_flash_led_delay;
336   flash_led_time_[id] += 314*times;
337   flash_led_initial_delay_[id] = flash_led_delay_[id]*314*phase_divisor/8;
338 }
339
340 //********************************************************************//
341
342 int save_tcnt2=0;
343 int save_tccr2a=0;
344 int save_tccr2b=0;
345 void reset_timer2()
346 {
347   TCNT2 = save_tcnt2;
348   TCCR2A = save_tccr2a;  // normal mode
349   TCCR2B = save_tccr2b;
350   //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
351   //TCCR2A = 0;  // normal mode
352   //TCCR2B = 0;
353 }
354
355 void send_yamaha_ir_signal(char codebyte)
356 {
357   unsigned long int code = codebyte & 0xFF;
358   code <<= 8;
359   code |= (0xff ^ codebyte) & 0xFF;
360   code |= YAMAHA_CODE_BASE;
361
362   //irsend changes PWM Timer Frequency among other things
363   //.. doesn't go well with PWM output using the same timer
364   //.. thus we just set output to 255 so whatever frequency is used, led is off for the duration
365   //analogWrite(BLUELED_PWM_PIN,255); // switch led off
366
367   irsend.sendNEC(code,YAMAHA_CODE_BITS);
368
369   reset_timer2();
370   analogWrite(BLUELED_PWM_PIN,255); // switch off led again to be sure
371                                       //is actually not necessary, since we are not multitasking/using interrupts, but just to be sure in case this might change
372
373   Serial.println("Ok");
374 }
375
376 //********************************************************************//
377
378 void setup()
379 {
380   pinMode(RF_DATA_OUT_PIN, OUTPUT);
381   digitalWrite(RF_DATA_OUT_PIN, HIGH);
382   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
383   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors
384   digitalWrite(IR_MOVEMENT_PIN2, LOW);  // turn off pullup resistors
385   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
386   digitalWrite(PANIC_BUTTON_PIN, LOW);  // turn of pullup resistors
387   analogWrite(PANICLED_PWM_PIN,255);
388   analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
389   pinMode(IRREMOTE_SEND_PIN, OUTPUT);
390   digitalWrite(IRREMOTE_SEND_PIN, HIGH);
391
392   Serial.begin(9600);
393
394   onewire.reset();
395   onewire.reset_search();
396   dallas_sensors.begin();
397   //in case we change temp sensor:
398   if (!dallas_sensors.getAddress(onShieldTemp, 0))
399     Serial.println("Error: Unable to find address for Device 0");
400   dallas_sensors.setResolution(onShieldTemp, 9);
401
402   //save prev timer states:
403   save_tcnt2 = TCNT2;
404   save_tccr2a = TCCR2A;  // normal mode
405   save_tccr2b = TCCR2B;
406 }
407
408 unsigned int ir_time=IR_SAMPLE_DURATION;
409 unsigned int ir_count=0;
410 unsigned int ir_count2=0;
411 boolean pb_last_state=0;
412 boolean pb_state=0;
413 boolean pb_postth_state=0;
414 unsigned int pb_time=0;
415
416 void sensorEchoCommand(char command)
417 {
418   Serial.print("Sensor ");
419   Serial.print(command);
420   Serial.print(": ");
421 }
422
423 void loop()
424 {
425   ir_time--;
426   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
427   ir_count2 += (digitalRead(IR_MOVEMENT_PIN2) == HIGH);
428
429   if (pb_time < PB_TRESHOLD)
430     pb_time++;
431   pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
432
433   if (ir_time == 0)
434   {
435     if (ir_count >= IR_TRESHOLD || ir_count2 >= IR_TRESHOLD)
436     {
437       flash_led(0, 1, 8, 1, 0 );
438       Serial.println("movement");
439     }
440     ir_time=IR_SAMPLE_DURATION;
441     ir_count=0;
442     ir_count2=0;
443   }
444
445   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
446   {
447     if (pb_state && ! pb_postth_state)
448     {
449       pb_postth_state=1;
450       Serial.println("PanicButton");
451       flash_led(0, 28, 1, 4, 0 );
452       flash_led(1, 28, 1, 4, 4 );
453     }
454     else if (!pb_state)
455       pb_postth_state=0;
456   }
457   else if (pb_state != pb_last_state)
458   {
459     pb_time=0;
460     pb_last_state=pb_state;
461   }
462
463   updateLightLevel(PHOTO_ANALOGPIN);
464   calculate_led_level();
465   check_frame_done();
466   if(Serial.available()) {
467     char command = Serial.read();
468
469     if (command == '>')
470     {
471       serial_read_send_rf_cmd();
472     }
473     else if(command == 'A')  
474       send_rf_cmd("\x8a\xa0\x8a"); // pollin 00101 a 1
475     else if(command == 'a')
476       send_rf_cmd("\x8a\xa0\x2a");  // pollin 00101 a 0
477     else if(command == 'B')
478       send_rf_cmd("\xa0\xa2\xa8"); //white remote A 2 on
479     else if(command == 'b')
480       send_rf_cmd("\xa0\xa2\x28"); //white remote A 2 off    
481     else if(command == 'C')
482       send_rf_cmd("\xa2\xa0\xa8"); //white remote B 1 on
483     else if(command == 'c')
484       send_rf_cmd("\xa2\xa0\x28"); //white remote B 1 off
485     else if(command == 'D')
486       send_rf_cmd("\x8a\x88\x8a"); //pollin 00101 b 1
487     else if(command == 'd')
488       send_rf_cmd("\x8a\x88\x2a"); //pollin 00101 b 0
489     else if(command == 'E')
490       send_rf_cmd("\xa8\xa0\xa8"); //white remote C 1 on
491     else if(command == 'e')    
492       send_rf_cmd("\xa8\xa0\x28"); //white remote C 1 off
493     else if(command == 'F')
494       send_rf_cmd("\xa8\xa2\xa8");
495     else if(command == 'f')
496       send_rf_cmd("\xa8\xa2\x28");
497     else if(command == 'G')
498       send_rf_cmd("\xaa\xa0\xa8");
499     else if(command == 'g')
500       send_rf_cmd("\xaa\xa0\x28");
501     else if(command == 'H')
502       send_rf_cmd("\xaa\xa2\xa8");
503     else if(command == 'h')
504       send_rf_cmd("\xaa\xa2\x28");
505     else if(command == 'I')
506       send_rf_cmd("\x8a\x28\x8a"); //pollin 00101 c 1
507     else if(command == 'i')
508       send_rf_cmd("\x8a\x28\x2a"); //pollin 00101 c 0
509     else if(command == 'J')
510       send_rf_cmd("\x8a\xa8\x88"); //pollin 00101 d 1
511     else if(command == 'j')
512       send_rf_cmd("\x8a\xa8\x28"); //pollin 00101 d 0
513     else if(command == 'L')
514       send_rf_cmd("\xae\x2b\x30");
515     else if(command == 'l')
516       send_rf_cmd("\xae\x2b\xc0");
517     else if(command == 'M')
518       send_rf_cmd("\xae\x2e\x30");
519     else if(command == 'm')
520       send_rf_cmd("\xae\x2e\xc0");      
521     else if(command == 'N')
522       send_rf_cmd("\xae\x3a\x30");
523     else if(command == 'n')
524       send_rf_cmd("\xae\x3a\xc0");
525     else if(command == 'Z')
526       send_rf_cmd("\xa2\xa2\xaa");
527     else if(command == 'z')
528       send_rf_cmd("\xa2\xa2\x2a");
529     else if(command == '*')
530     {
531       sensorEchoCommand(command);
532       printTemperature(onShieldTemp);
533     }
534     else if(command == '?')
535     {
536       sensorEchoCommand(command);
537       printLightLevel();
538     }
539     else if (command == '^')
540     {
541       //flash_led(1, 1, 2, 1, 0);
542       flash_led(1, 1, 1, 1, 0);
543       Serial.println("Ok");
544     }
545     else if (command == '&')
546     {
547       flash_led(0, 1, 2, 1, 0);
548       Serial.println("Ok");
549     }
550     else if (command == '1')
551       send_yamaha_ir_signal(YAMAHA_CD);
552     else if (command == '2')
553       send_yamaha_ir_signal(YAMAHA_TUNER);
554     else if (command == '3')
555       send_yamaha_ir_signal(YAMAHA_TAPE);
556     else if (command == '4')
557       send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
558     else if (command == '5')
559       send_yamaha_ir_signal(YAMAHA_SAT_SPDIFF);
560     else if (command == '6')
561       send_yamaha_ir_signal(YAMAHA_VCR);
562 //    else if (command == '7')
563 //      send_yamaha_ir_signal();
564     else if (command == '8')
565       send_yamaha_ir_signal(YAMAHA_AUX);
566     else if (command == '9')
567       send_yamaha_ir_signal(YAMAHA_EXT51DEC);
568     else if (command == '0')
569       send_yamaha_ir_signal(YAMAHA_TEST);
570     else if (command == '/')
571       send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
572     else if (command == '\\')
573       send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
574     else if (command == '-')
575       send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
576     else if (command == '+')
577       send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
578     else if (command == ':')
579       send_yamaha_ir_signal(YAMAHA_POWER_OFF);
580     else if (command == '.')
581       send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
582     else if (command == ';')
583       send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
584     else if (command == ',')
585       send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
586     else if (command == '_')
587       send_yamaha_ir_signal(YAMAHA_MUTE);
588     else if (command == '#')
589       send_yamaha_ir_signal(YAMAHA_MENU);
590     else if (command == '"')
591       send_yamaha_ir_signal(YAMAHA_PLUS);
592     else if (command == '!')
593       send_yamaha_ir_signal(YAMAHA_MINUS);
594     else if (command == '=')
595       send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
596     else if (command == '$')
597       send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
598     else if (command == '%')
599       send_yamaha_ir_signal(YAMAHA_PRG_UP);
600     else if (command == '(')
601       send_yamaha_ir_signal(YAMAHA_SLEEP);
602     else if (command == ')')
603       send_yamaha_ir_signal(YAMAHA_P5);
604     else
605       Serial.println("Error: unknown command");
606   }
607 }