2 #include <avr/interrupt.h>
5 #include <DallasTemperature.h>
8 //********************************************************************//
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 8000
20 #define IR_TRESHOLD 7500
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
27 OneWire onewire(ONE_WIRE_PIN);
28 DallasTemperature dallas_sensors(&onewire);
29 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
31 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT
33 //********************************************************************//
34 // IR Codes, 32 bit, NEC
35 const int YAMAHA_CODE_BITS = 32;
36 const unsigned long int YAMAHA_CODE_BASE = 0x0000000005EA10000;
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
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
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)
55 const char YAMAHA_MUTE =0x38;
56 const char YAMAHA_VOLUME_UP =0x58;
57 const char YAMAHA_VOLUME_DOWN =0xD8;
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
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)
84 //********************************************************************//
91 // offset is number of alphas (0.08ms)
93 const rf_bit_t zero_bit[] = { { 4, 1 },
99 const rf_bit_t one_bit[] = { { 12, 1 },
105 const rf_bit_t float_bit[] = { { 4, 1 },
111 const rf_bit_t sync_bit[] = { { 4, 1 },
115 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
116 typedef byte ad_bit_t;
118 typedef ad_bit_t word_t[WORD_LEN];
120 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
126 const ad_bit_t* current_word;
127 byte volatile frame_finished = 1;
151 const word_t words[] = {
152 { ZERO, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
153 { ZERO, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // A1_OFF
154 { ZERO, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
155 { ZERO, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // A2_OFF
157 { FLOAT, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
158 { FLOAT, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // B1_OFF
159 { FLOAT, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
160 { FLOAT, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // B2_OFF
162 { ZERO, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
163 { ZERO, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // C1_OFF
164 { ZERO, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
165 { ZERO, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // C2_OFF
167 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
168 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // D1_OFF
169 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
170 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC } // D2_OFF
174 //********************************************************************//
179 TCCR1A = 0; // prescaler 1:8, WGM = 4 (CTC)
180 TCCR1B = 1<<WGM12 | 1<<CS11; //
181 OCR1A = 159; // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
182 // OCR1A = 207; // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
183 TCNT1 = 0; // reseting timer
184 TIMSK1 = 1<<OCIE1A; // enable Interrupt
187 void stop_timer() // stop the timer
190 TCCR1B = 0; // no clock source
191 TIMSK1 = 0; // disable timer interrupt
194 void init_word(const word_t w)
201 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
202 digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
204 digitalWrite(RF_DATA_OUT_PIN, HIGH);
209 ISR(TIMER1_COMPA_vect)
212 if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
216 if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
217 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
218 digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
220 digitalWrite(RF_DATA_OUT_PIN, HIGH);
225 if(bit_cnt < WORD_LEN) {
228 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
229 digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
231 digitalWrite(RF_DATA_OUT_PIN, HIGH);
235 digitalWrite(RF_DATA_OUT_PIN, HIGH);
238 if(word_cnt < FRAME_LEN)
239 init_word(current_word);
247 void send_frame(const word_t w)
249 if (frame_finished != 1)
250 for(;;) //wait until sending of previous frame finishes
261 void check_frame_done()
263 if (frame_finished==2)
265 Serial.println("Ok");
271 //********************************************************************//
273 void printTemperature(DeviceAddress deviceAddress)
275 dallas_sensors.requestTemperatures();
276 float tempC = dallas_sensors.getTempC(deviceAddress);
277 //Serial.print("Temp C: ");
278 Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
279 //Serial.print(" Temp F: ");
280 //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
283 //********************************************************************//
285 unsigned int light_level_mean_ = 0;
286 unsigned int light_sample_time_ = 0;
288 void updateLightLevel(unsigned int pin)
290 light_sample_time_++;
291 if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
293 light_sample_time_ = 0;
295 unsigned int value = analogRead(pin);
296 if (value == light_level_mean_)
299 unsigned int diff = abs(value - light_level_mean_);
301 light_level_mean_ = value;
303 light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
306 void printLightLevel()
308 //Serial.print("Photo: ");
309 Serial.println(light_level_mean_);
312 //********************************************************************//
314 unsigned long wm_start_[3]={0,0,0};
315 bool wait_millis(unsigned long *start_time, unsigned long ms)
319 else if (*start_time > 0)
321 if (millis() < *start_time || millis() > (*start_time) + ms)
331 *start_time=millis();
336 char flash_led_pins_[NUM_LEDS]={BLUELED_PWM_PIN,PANICLED_PWM_PIN};
337 unsigned int flash_led_time_[3]={0,0,0};
338 unsigned int flash_led_brightness_[3]={255,255,255};
339 unsigned int flash_led_delay_[3]={8,8,8};
340 unsigned int flash_led_initial_delay_[3]={0,0,0};
341 void calculate_led_level()
343 for (int ledid = 0; ledid < NUM_LEDS; ledid++)
345 if (flash_led_time_[ledid] == 0)
347 if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
349 flash_led_initial_delay_[ledid]=0;
350 if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
352 flash_led_time_[ledid]--;
353 int c = abs(sin(float(flash_led_time_[ledid]) / 100.0)) * flash_led_brightness_[ledid];
354 //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
355 analogWrite(flash_led_pins_[ledid], 255-c);
359 // id: id of LED to flash (0,1)
360 // times: # of times the LED should flash
361 // brightness_divisor: 1: full brightness, 2: half brightness, ...
362 // delay_divisor: 1: slow... 8: fastest
363 // phase_divisor: 0.. same phase; 2.. pi/2 phase, 4.. pi phase, 6.. 3pi/2 phase
364 void flash_led(unsigned int id, unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int phase_divisor)
368 unsigned int new_flash_led_brightness = 255;
369 unsigned int new_flash_led_delay = 8;
372 analogWrite(flash_led_pins_[id],255); //off
375 if (brightness_divisor > 1) //guard against div by zero
376 new_flash_led_brightness /= brightness_divisor;
377 if (delay_divisor > 1) //guard against div by zero
378 new_flash_led_delay /= delay_divisor;
379 if (flash_led_time_[id] == 0 || new_flash_led_brightness > flash_led_brightness_[id])
380 flash_led_brightness_[id]=new_flash_led_brightness;
381 if (flash_led_time_[id] == 0 || new_flash_led_delay < flash_led_delay_[id])
382 flash_led_delay_[id]=new_flash_led_delay;
383 flash_led_time_[id] += 314*times;
384 flash_led_initial_delay_[id] = flash_led_delay_[id]*314*phase_divisor/8;
387 //********************************************************************//
395 TCCR2A = save_tccr2a; // normal mode
396 TCCR2B = save_tccr2b;
397 //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
398 //TCCR2A = 0; // normal mode
402 void send_yamaha_ir_signal(char codebyte)
404 unsigned long int code = codebyte & 0xFF;
406 code |= (0xff ^ codebyte) & 0xFF;
407 code |= YAMAHA_CODE_BASE;
409 //irsend changes PWM Timer Frequency among other things
410 //.. doesn't go well with PWM output using the same timer
411 //.. thus we just set output to 255 so whatever frequency is used, led is off for the duration
412 //analogWrite(BLUELED_PWM_PIN,255); // switch led off
414 irsend.sendNEC(code,YAMAHA_CODE_BITS);
417 analogWrite(BLUELED_PWM_PIN,255); // switch off led again to be sure
418 //is actually not necessary, since we are not multitasking/using interrupts, but just to be sure in case this might change
420 Serial.println("Ok");
423 //********************************************************************//
427 pinMode(RF_DATA_OUT_PIN, OUTPUT);
428 digitalWrite(RF_DATA_OUT_PIN, HIGH);
429 pinMode(IR_MOVEMENT_PIN, INPUT); // set pin to input
430 digitalWrite(IR_MOVEMENT_PIN, LOW); // turn off pullup resistors
431 digitalWrite(IR_MOVEMENT_PIN2, LOW); // turn off pullup resistors
432 pinMode(PANIC_BUTTON_PIN, INPUT); // set pin to input
433 digitalWrite(PANIC_BUTTON_PIN, LOW); // turn of pullup resistors
434 analogWrite(PANICLED_PWM_PIN,255);
435 analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
436 pinMode(IRREMOTE_SEND_PIN, OUTPUT);
437 digitalWrite(IRREMOTE_SEND_PIN, HIGH);
442 onewire.reset_search();
443 dallas_sensors.begin();
444 //in case we change temp sensor:
445 if (!dallas_sensors.getAddress(onShieldTemp, 0))
446 Serial.println("Error: Unable to find address for Device 0");
447 dallas_sensors.setResolution(onShieldTemp, 9);
449 //save prev timer states:
451 save_tccr2a = TCCR2A; // normal mode
452 save_tccr2b = TCCR2B;
455 unsigned int ir_time=IR_SAMPLE_DURATION;
456 unsigned int ir_count=0;
457 unsigned int ir_count2=0;
458 boolean pb_last_state=0;
460 boolean pb_postth_state=0;
461 unsigned int pb_time=0;
463 void sensorEchoCommand(char command)
465 Serial.print("Sensor ");
466 Serial.print(command);
473 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
474 ir_count2 += (digitalRead(IR_MOVEMENT_PIN2) == HIGH);
476 if (pb_time < PB_TRESHOLD)
478 pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
482 if (ir_count >= IR_TRESHOLD || ir_count2 >= IR_TRESHOLD)
484 flash_led(0, 1, 8, 1, 0 );
485 Serial.println("movement");
487 ir_time=IR_SAMPLE_DURATION;
492 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
494 if (pb_state && ! pb_postth_state)
497 Serial.println("PanicButton");
498 flash_led(0, 28, 1, 4, 0 );
499 flash_led(1, 28, 1, 4, 4 );
504 else if (pb_state != pb_last_state)
507 pb_last_state=pb_state;
510 updateLightLevel(PHOTO_ANALOGPIN);
511 calculate_led_level();
514 if(Serial.available()) {
515 char command = Serial.read();
518 send_frame(words[A1_ON]);
519 else if(command == 'a')
520 send_frame(words[A1_OFF]);
521 else if(command == 'B')
522 send_frame(words[A2_ON]);
523 else if(command == 'b')
524 send_frame(words[A2_OFF]);
526 else if(command == 'C')
527 send_frame(words[B1_ON]);
528 else if(command == 'c')
529 send_frame(words[B1_OFF]);
530 else if(command == 'D')
531 send_frame(words[B2_ON]);
532 else if(command == 'd')
533 send_frame(words[B2_OFF]);
535 else if(command == 'E')
536 send_frame(words[C1_ON]);
537 else if(command == 'e')
538 send_frame(words[C1_OFF]);
539 else if(command == 'F')
540 send_frame(words[C2_ON]);
541 else if(command == 'f')
542 send_frame(words[C2_OFF]);
544 else if(command == 'G')
545 send_frame(words[D1_ON]);
546 else if(command == 'g')
547 send_frame(words[D1_OFF]);
548 else if(command == 'H')
549 send_frame(words[D2_ON]);
550 else if(command == 'h')
551 send_frame(words[D2_OFF]);
552 else if(command == 'T')
554 sensorEchoCommand(command);
555 printTemperature(onShieldTemp);
557 else if(command == 'P')
559 sensorEchoCommand(command);
562 else if (command == '^')
564 //flash_led(1, 1, 2, 1, 0);
565 flash_led(1, 1, 1, 1, 0);
566 Serial.println("Ok");
568 else if (command == '&')
570 flash_led(0, 1, 2, 1, 0);
571 Serial.println("Ok");
573 else if (command == '1')
574 send_yamaha_ir_signal(YAMAHA_CD);
575 else if (command == '2')
576 send_yamaha_ir_signal(YAMAHA_TUNER);
577 else if (command == '3')
578 send_yamaha_ir_signal(YAMAHA_TAPE);
579 else if (command == '4')
580 send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
581 else if (command == '5')
582 send_yamaha_ir_signal(YAMAHA_SAT_SPDIFF);
583 else if (command == '6')
584 send_yamaha_ir_signal(YAMAHA_VCR);
585 // else if (command == '7')
586 // send_yamaha_ir_signal();
587 else if (command == '8')
588 send_yamaha_ir_signal(YAMAHA_AUX);
589 else if (command == '9')
590 send_yamaha_ir_signal(YAMAHA_EXT51DEC);
591 else if (command == '0')
592 send_yamaha_ir_signal(YAMAHA_TEST);
593 else if (command == '/')
594 send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
595 else if (command == '\\')
596 send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
597 else if (command == '-')
598 send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
599 else if (command == '+')
600 send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
601 else if (command == ':')
602 send_yamaha_ir_signal(YAMAHA_POWER_OFF);
603 else if (command == '.')
604 send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
605 else if (command == ';')
606 send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
607 else if (command == ',')
608 send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
609 else if (command == '_')
610 send_yamaha_ir_signal(YAMAHA_MUTE);
611 else if (command == '#')
612 send_yamaha_ir_signal(YAMAHA_MENU);
613 else if (command == '"')
614 send_yamaha_ir_signal(YAMAHA_PLUS);
615 else if (command == '!')
616 send_yamaha_ir_signal(YAMAHA_MINUS);
617 else if (command == '=')
618 send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
619 else if (command == '$')
620 send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
621 else if (command == '%')
622 send_yamaha_ir_signal(YAMAHA_PRG_UP);
623 else if (command == '(')
624 send_yamaha_ir_signal(YAMAHA_SLEEP);
625 else if (command == ')')
626 send_yamaha_ir_signal(YAMAHA_P5);
628 Serial.println("Error: unknown command");