OK for led, brighter led, shorter sample duration for movementsensor
[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 8000
19 #define IR_TRESHOLD 6000
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_MINUS =0x88; //Tuner Prev Station 1-7  (of A1 - E7)
52 const char YAMAHA_TUNER_ABCDE =0x48; //Tuner Next Station Row A-E (of A1 - E7)
53
54 const char YAMAHA_MUTE =0x38;
55 const char YAMAHA_VOLUME_UP =0x58;
56 const char YAMAHA_VOLUME_DOWN =0xD8;
57
58 //const char YAMAHA_FRONT_LEVEL_P =0x01;  //no function
59 //const char YAMAHA_FRONT_LEVEL_M =0x81; //no function
60 //const char YAMAHA_CENTRE_LEVEL_P =0x41;  //no function
61 //const char YAMAHA_CENTRE_LEVEL_M =0xC1; //no function
62 //const char YAMAHA_REAR_LEVEL_P =0x7A; //no function
63 //const char YAMAHA_REAR_LEVEL_M =0xFA; //no function
64 const char YAMAHA_PLUS =0x4A;  //unteres Steuerkreuz: Taste Rechts (Plus)
65 const char YAMAHA_MINUS =0xCA; //unteres Steuerkreuz: Taste Links (Minus)
66 const char YAMAHA_MENU =0x39; // Menu: Settings
67 const char YAMAHA_TEST =0xA1; // Test Sounds
68 const char YAMAHA_TIME_LEVEL =0x19; //Settings for Delay, Subwfs, Right Surround, Left Surround, Center
69 const char YAMAHA_TIME_LEVEL2 =0x61; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
70 const char YAMAHA_TIME_LEVEL3 =0x99; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
71
72 const char YAMAHA_EFFECT_TOGGLE =0x6A; //Effect Toggle On/Off
73 const char YAMAHA_PRG_DOWN =0x9A; //Effect/DSP Programm Toggle in down direction
74 const char YAMAHA_PRG_UP =0x1A; //Effect/DSP Programm Toggle in up direction
75 const char YAMAHA_EFFECT1 =0x31; //Effect TV Sports
76 const char YAMAHA_EFFECT2 =0x71; //Effect Rock Concert
77 const char YAMAHA_EFFECT3 =0xB1;  //Effect Disco
78 const char YAMAHA_EFFECT4 =0xD1;  //Mono Movie
79 const char YAMAHA_EFFECT5 =0x91; //Effect Toggle 70mm Sci-Fi / 70mm Spectacle
80 const char YAMAHA_EFFECT6 =0x51; //Effect Toggle 70mm General / 70mm Adventure
81 const char YAMAHA_P5 =0xFB; //P5 PRT (1 Main Bypass)? (1587674115)
82
83 //********************************************************************//
84
85 typedef struct {
86   byte offset;
87   byte state;
88 } rf_bit_t;
89
90 // offset is number of alphas (0.08ms)
91
92 const rf_bit_t zero_bit[] = { {  4, 1 },
93                               { 16, 0 },
94                               { 20, 1 },
95                               { 32, 0 },
96                               {  0, 0 } };
97
98 const rf_bit_t one_bit[] = { { 12, 1 },
99                              { 16, 0 },
100                              { 28, 1 },
101                              { 32, 0 },
102                              {  0, 0 } };
103
104 const rf_bit_t float_bit[] = { {  4, 1 },
105                                { 16, 0 },
106                                { 28, 1 },
107                                { 32, 0 },
108                                {  0, 0 } };
109
110 const rf_bit_t sync_bit[] = { {   4, 1 },
111                               { 128, 0 },
112                               {   0, 0 } };
113
114 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
115 typedef byte ad_bit_t;
116 #define WORD_LEN 13
117 typedef ad_bit_t word_t[WORD_LEN];
118
119 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
120
121 byte alpha_cnt = 0;
122 byte bit_cnt = 0;
123 byte chunk_cnt = 0;
124 byte word_cnt = 0;
125 const ad_bit_t* current_word;
126 byte volatile frame_finished = 1;
127
128 #define FRAME_LEN 8
129
130 #define A1_ON  0
131 #define A1_OFF 1
132 #define A2_ON  2
133 #define A2_OFF 3
134
135 #define B1_ON  4
136 #define B1_OFF 5
137 #define B2_ON  6
138 #define B2_OFF 7
139
140 #define C1_ON  8
141 #define C1_OFF 9
142 #define C2_ON  10
143 #define C2_OFF 11
144
145 #define D1_ON  12
146 #define D1_OFF 13
147 #define D2_ON  14
148 #define D2_OFF 15
149
150 const word_t words[]  = { 
151 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
152 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A1_OFF
153 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
154 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A2_OFF
155
156 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
157 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B1_OFF
158 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
159 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B2_OFF
160
161 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
162 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C1_OFF
163 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
164 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C2_OFF
165
166 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
167 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // D1_OFF
168 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
169 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }  // D2_OFF
170 };
171
172
173 //********************************************************************//
174
175 void start_timer()
176 {
177   // timer 1: 2 ms
178   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
179   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
180   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
181 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
182   TCNT1 = 0;          // reseting timer
183   TIMSK1 = 1<<OCIE1A; // enable Interrupt
184 }
185
186 void stop_timer() // stop the timer
187 {
188   // timer1
189   TCCR1B = 0; // no clock source
190   TIMSK1 = 0; // disable timer interrupt
191 }
192
193 void init_word(const word_t w)
194 {
195   current_word = w;
196   alpha_cnt = 0;
197   chunk_cnt = 0;
198   bit_cnt = 0;
199
200   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
201     digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
202   else
203     digitalWrite(RF_DATA_OUT_PIN, HIGH);
204
205   start_timer();
206 }
207
208 ISR(TIMER1_COMPA_vect)
209 {
210   alpha_cnt++;
211   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
212     return;
213
214   chunk_cnt++;
215   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
216     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
217       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
218     else
219       digitalWrite(RF_DATA_OUT_PIN, HIGH);
220     return;
221   }
222   
223   bit_cnt++;
224   if(bit_cnt < WORD_LEN) {
225     alpha_cnt = 0;
226     chunk_cnt = 0;
227     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
228       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
229     else
230       digitalWrite(RF_DATA_OUT_PIN, HIGH);
231     return;
232   }
233   stop_timer();
234   digitalWrite(RF_DATA_OUT_PIN, HIGH);
235
236   word_cnt++;
237   if(word_cnt < FRAME_LEN)
238     init_word(current_word);
239   else
240     frame_finished = 2;
241 }
242
243 //***********//
244
245
246 void send_frame(const word_t w)
247 {
248   if (frame_finished != 1)
249     for(;;) //wait until sending of previous frame finishes
250       if (frame_finished)
251       {
252         delay(150);
253         break;
254       }
255   word_cnt = 0;
256   frame_finished = 0;
257   init_word(w);
258 }
259
260 void check_frame_done()
261 {
262   if (frame_finished==2)
263   {
264     Serial.println("Ok");
265     frame_finished=1;
266     delay(120);
267   }
268 }
269
270 //********************************************************************//
271
272 void printTemperature(DeviceAddress deviceAddress)
273 {
274   dallas_sensors.requestTemperatures();
275   float tempC = dallas_sensors.getTempC(deviceAddress);
276   //Serial.print("Temp C: ");
277   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
278   //Serial.print(" Temp F: ");
279   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
280 }
281
282 //********************************************************************//
283
284 unsigned int light_level_mean_ = 0;
285 unsigned int light_sample_time_ = 0;
286
287 void updateLightLevel(unsigned int pin)
288 {
289   light_sample_time_++;
290   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
291     return;
292   light_sample_time_ = 0;
293   
294   unsigned int value = analogRead(pin);
295   if (value == light_level_mean_)
296     return;
297   
298   unsigned int diff = abs(value - light_level_mean_);
299   if (diff > 100)
300     light_level_mean_ = value;
301   else
302       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
303 }
304
305 void printLightLevel()
306 {
307   //Serial.print("Photo: ");
308   Serial.println(light_level_mean_);
309 }
310
311 //********************************************************************//
312
313 unsigned long wm_start_[3]={0,0,0};
314 bool wait_millis(unsigned long *start_time, unsigned long ms)
315 {
316   if (ms == 0)
317     return false;
318   else if (*start_time > 0)
319   {
320     if (millis() < *start_time || millis() > (*start_time) + ms)
321     {
322       *start_time = 0;
323       return false;
324     }
325     else
326       return true;
327   }
328   else
329   {
330     *start_time=millis();
331     return true;
332   }
333 }
334 #define NUM_LEDS 2
335 char flash_led_pins_[NUM_LEDS]={BLUELED_PWM_PIN,PANICLED_PWM_PIN};
336 unsigned int flash_led_time_[3]={0,0,0};
337 unsigned int flash_led_brightness_[3]={255,255,255};
338 unsigned int flash_led_delay_[3]={8,8,8};
339 unsigned int flash_led_initial_delay_[3]={0,0,0};
340 void calculate_led_level()
341 {
342   for (int ledid = 0; ledid < NUM_LEDS; ledid++)
343   {
344     if (flash_led_time_[ledid] == 0)
345       continue;
346     if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
347       continue;
348     flash_led_initial_delay_[ledid]=0;
349     if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
350       continue;
351     flash_led_time_[ledid]--;
352     int c = abs(sin(float(flash_led_time_[ledid]) / 100.0)) * flash_led_brightness_[ledid];
353     //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
354     analogWrite(flash_led_pins_[ledid], 255-c);
355   }
356 }
357
358 // id: id of LED to flash (0,1)
359 // times: # of times the LED should flash
360 // brightness_divisor: 1: full brightness, 2: half brightness, ...
361 // delay_divisor: 1: slow... 8: fastest
362 // phase_divisor: 0.. same phase; 2.. pi/2 phase, 4.. pi phase, 6.. 3pi/2 phase
363 void flash_led(unsigned int id, unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int phase_divisor)
364 {
365   if (id >= NUM_LEDS)
366     return;
367   unsigned int new_flash_led_brightness = 255;
368   unsigned int new_flash_led_delay = 8;
369   if (times == 0)
370   {
371     analogWrite(flash_led_pins_[id],255); //off
372     return;
373   }
374   if (brightness_divisor > 1) //guard against div by zero
375     new_flash_led_brightness /= brightness_divisor;
376   if (delay_divisor > 1)  //guard against div by zero
377     new_flash_led_delay /= delay_divisor;
378   if (flash_led_time_[id] == 0 || new_flash_led_brightness > flash_led_brightness_[id])
379     flash_led_brightness_[id]=new_flash_led_brightness;
380   if (flash_led_time_[id] == 0 || new_flash_led_delay < flash_led_delay_[id])
381     flash_led_delay_[id]=new_flash_led_delay;
382   flash_led_time_[id] += 314*times;
383   flash_led_initial_delay_[id] = flash_led_delay_[id]*314*phase_divisor/8;
384 }
385
386 //********************************************************************//
387
388 int save_tcnt2=0;
389 int save_tccr2a=0;
390 int save_tccr2b=0;
391 void reset_timer2()
392 {
393   TCNT2 = save_tcnt2;
394   TCCR2A = save_tccr2a;  // normal mode
395   TCCR2B = save_tccr2b;
396   //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
397   //TCCR2A = 0;  // normal mode
398   //TCCR2B = 0;
399 }
400
401 void send_yamaha_ir_signal(char codebyte)
402 {
403   unsigned long int code = codebyte & 0xFF;
404   code <<= 8;
405   code |= (0xff ^ codebyte) & 0xFF;
406   code |= YAMAHA_CODE_BASE;
407   
408   //irsend changes PWM Timer Frequency among other things
409   //.. doesn't go well with PWM output using the same timer
410   //.. thus we just set output to 255 so whatever frequency is used, led is off for the duration
411   //analogWrite(BLUELED_PWM_PIN,255); // switch led off
412
413   irsend.sendNEC(code,YAMAHA_CODE_BITS);
414
415   reset_timer2();
416   analogWrite(BLUELED_PWM_PIN,255); // switch off led again to be sure
417                                       //is actually not necessary, since we are not multitasking/using interrupts, but just to be sure in case this might change
418
419   Serial.println("Ok");
420 }
421
422 //********************************************************************//
423
424 void setup()
425 {
426   pinMode(RF_DATA_OUT_PIN, OUTPUT);
427   digitalWrite(RF_DATA_OUT_PIN, HIGH);
428   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
429   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pulldown resistors  
430   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
431   digitalWrite(PANIC_BUTTON_PIN, LOW);  // turn on pulldown resistors 
432   analogWrite(PANICLED_PWM_PIN,255);
433   analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
434   pinMode(IRREMOTE_SEND_PIN, OUTPUT);
435   digitalWrite(IRREMOTE_SEND_PIN, HIGH);
436   
437   Serial.begin(9600);
438   
439   onewire.reset();
440   onewire.reset_search();
441   dallas_sensors.begin();
442   //in case we change temp sensor:
443   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
444     Serial.println("Error: Unable to find address for Device 0"); 
445   dallas_sensors.setResolution(onShieldTemp, 9);  
446
447   //save prev timer states:
448   save_tcnt2 = TCNT2;
449   save_tccr2a = TCCR2A;  // normal mode
450   save_tccr2b = TCCR2B;
451 }
452
453 unsigned int ir_time=IR_SAMPLE_DURATION;
454 unsigned int ir_count=0;
455 boolean pb_last_state=0;
456 boolean pb_state=0;
457 boolean pb_postth_state=0;
458 unsigned int pb_time=0;
459
460 void sensorEchoCommand(char command)
461 {
462   Serial.print("Sensor ");
463   Serial.print(command);
464   Serial.print(": ");
465 }
466
467 void loop()
468 {
469   ir_time--;
470   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
471
472   if (pb_time < PB_TRESHOLD)
473     pb_time++;
474   pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
475   
476   if (ir_time == 0)
477   {
478     if (ir_count >= IR_TRESHOLD)
479     {
480       flash_led(0, 1, 8, 1, 0 );
481       Serial.println("movement");
482     }
483     ir_time=IR_SAMPLE_DURATION;
484     ir_count=0;
485   }
486   
487   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
488   {
489     if (pb_state && ! pb_postth_state)
490     {   
491       pb_postth_state=1;
492       Serial.println("PanicButton");
493       flash_led(0, 28, 1, 4, 0 );
494       flash_led(1, 28, 1, 4, 4 );
495     }
496     else if (!pb_state)
497       pb_postth_state=0;
498   }
499   else if (pb_state != pb_last_state)
500   {
501     pb_time=0;
502     pb_last_state=pb_state;
503   }
504   
505   updateLightLevel(PHOTO_ANALOGPIN);
506   calculate_led_level();
507   check_frame_done();
508   
509   if(Serial.available()) {
510     char command = Serial.read();
511     
512     if(command == 'A')
513       send_frame(words[A1_ON]);
514     else if(command == 'a')
515       send_frame(words[A1_OFF]);
516     else if(command == 'B')
517       send_frame(words[A2_ON]);
518     else if(command == 'b')
519       send_frame(words[A2_OFF]);
520
521     else if(command == 'C')
522       send_frame(words[B1_ON]);
523     else if(command == 'c')
524       send_frame(words[B1_OFF]);
525     else if(command == 'D')
526       send_frame(words[B2_ON]);
527     else if(command == 'd')
528       send_frame(words[B2_OFF]);
529
530     else if(command == 'E')
531       send_frame(words[C1_ON]);
532     else if(command == 'e')
533       send_frame(words[C1_OFF]);
534     else if(command == 'F')
535       send_frame(words[C2_ON]);
536     else if(command == 'f')
537       send_frame(words[C2_OFF]);
538
539     else if(command == 'G')
540       send_frame(words[D1_ON]);
541     else if(command == 'g')
542       send_frame(words[D1_OFF]);
543     else if(command == 'H')
544       send_frame(words[D2_ON]);
545     else if(command == 'h')
546       send_frame(words[D2_OFF]);
547     else if(command == 'T')
548     {
549       sensorEchoCommand(command);
550       printTemperature(onShieldTemp);
551     }
552     else if(command == 'P')
553     {
554       sensorEchoCommand(command);
555       printLightLevel();
556     }
557     else if (command == '^')
558     {
559       //flash_led(1, 1, 2, 1, 0);
560       flash_led(1, 1, 1, 1, 0);
561       Serial.println("Ok");
562     }
563     else if (command == '0')
564       send_yamaha_ir_signal(YAMAHA_POWER_OFF);
565     else if (command == '1')
566       send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
567     else if (command == '2')
568       send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
569     else if (command == '3')
570       send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
571     else if (command == '4')
572       send_yamaha_ir_signal(YAMAHA_MUTE);
573     else if (command == '5')
574       send_yamaha_ir_signal(YAMAHA_CD);
575     else if (command == '6')
576       send_yamaha_ir_signal(YAMAHA_TUNER);
577     else if (command == '7')
578       send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
579     else if (command == '8')
580       send_yamaha_ir_signal(YAMAHA_MENU);
581     else if (command == '+')
582       send_yamaha_ir_signal(YAMAHA_PLUS);
583     else if (command == '-')
584       send_yamaha_ir_signal(YAMAHA_MINUS);
585     else if (command == 0xa7) // §
586       send_yamaha_ir_signal(YAMAHA_TEST);
587     else if (command == '$')
588       send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
589     else if (command == '%')
590       send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
591     else if (command == '&')
592       send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
593     else if (command == '/')
594       send_yamaha_ir_signal(YAMAHA_PRG_UP);
595     else if (command == '(')
596       send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
597     else if (command == '[')
598       send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
599     else if (command == ')')
600       send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
601     else if (command == '9')
602       send_yamaha_ir_signal(YAMAHA_TAPE);
603     else if (command == '?')
604       send_yamaha_ir_signal(YAMAHA_VCR);
605     else if (command == '=')
606       send_yamaha_ir_signal(YAMAHA_EXT51DEC);
607     else
608       Serial.println("Error: unknown command");
609   }
610 }