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 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
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 //********************************************************************//
86 #define TIMER_RUNNING (TIMSK1 & (1<<OCIE1A))
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
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
102 void stop_timer() // stop the timer
105 TCCR1B = 0; // no clock source
106 TIMSK1 = 0; // disable timer interrupt
109 #define NUM_REPEAT_SIGNAL 8
110 #define RF_SIGNAL_BYTES 3
111 #define RF_SIGNAL_BITS RF_SIGNAL_BYTES * 8
114 byte duration_short_pulse; //mulitple of 0.08ms, should be === 0 (mod 4)
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
122 rf_signal current_signal = {6, 1, 3, 31, {0,0,0}};
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)
131 rf_state current_state = { 0, 0, 0, 0};
132 int rf_num_transmissions_to_acknowledge = 0;
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)
143 if ( current_state.state || current_state.bit || current_state.repeatc || current_state.atime)
145 if (current_state.atime)
147 current_state.atime--;
150 else if (current_state.state) //was in state 1 or 2
152 RF_OFF; //stop sending
153 if (current_state.state == 2) //aka sync
154 current_state.atime=RF_TIME_SNYC;
156 current_state.atime=CURRENT_BIT?
159 current_state.state=0;
161 else if (current_state.bit) //still more than 0 bits to do
164 current_state.state=1;
165 current_state.atime=CURRENT_BIT?
168 RF_ON; //start sending
170 else if (current_state.repeatc)
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)
177 current_state.atime=RF_TIME_SHORT;
184 rf_num_transmissions_to_acknowledge++;
187 //********************************************************************//
189 void serial_read_send_rf_cmd()
191 while (TIMER_RUNNING)
193 for (byte chr=0; chr < 3; chr++)
195 while (!Serial.available())
197 current_signal.signal[chr]=Serial.read();
199 current_state.repeatc=NUM_REPEAT_SIGNAL;
203 void send_rf_cmd(const char sr[])
205 while (TIMER_RUNNING)
207 for (byte chr=0; chr < 3; chr++)
209 current_signal.signal[chr]=sr[chr];
211 current_state.repeatc=NUM_REPEAT_SIGNAL;
215 void check_frame_done()
217 while (rf_num_transmissions_to_acknowledge > 0)
219 rf_num_transmissions_to_acknowledge--;
220 Serial.println("Ok");
224 //********************************************************************//
226 void printTemperature(DeviceAddress deviceAddress)
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
236 //********************************************************************//
238 unsigned int light_level_mean_ = 0;
239 unsigned int light_sample_time_ = 0;
241 void updateLightLevel(unsigned int pin)
243 light_sample_time_++;
244 if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
246 light_sample_time_ = 0;
248 unsigned int value = analogRead(pin);
249 if (value == light_level_mean_)
252 unsigned int diff = abs(value - light_level_mean_);
254 light_level_mean_ = value;
256 light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
259 void printLightLevel()
261 //Serial.print("Photo: ");
262 Serial.println(light_level_mean_);
265 //********************************************************************//
267 unsigned long wm_start_[3]={0,0,0};
268 bool wait_millis(unsigned long *start_time, unsigned long ms)
272 else if (*start_time > 0)
274 if (millis() < *start_time || millis() > (*start_time) + ms)
284 *start_time=millis();
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()
296 for (int ledid = 0; ledid < NUM_LEDS; ledid++)
298 if (flash_led_time_[ledid] == 0)
300 if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
302 flash_led_initial_delay_[ledid]=0;
303 if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
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);
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)
321 unsigned int new_flash_led_brightness = 255;
322 unsigned int new_flash_led_delay = 8;
325 analogWrite(flash_led_pins_[id],255); //off
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;
340 //********************************************************************//
348 TCCR2A = save_tccr2a; // normal mode
349 TCCR2B = save_tccr2b;
350 //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
351 //TCCR2A = 0; // normal mode
355 void send_yamaha_ir_signal(char codebyte)
357 unsigned long int code = codebyte & 0xFF;
359 code |= (0xff ^ codebyte) & 0xFF;
360 code |= YAMAHA_CODE_BASE;
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
367 irsend.sendNEC(code,YAMAHA_CODE_BITS);
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
373 Serial.println("Ok");
376 //********************************************************************//
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);
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);
402 //save prev timer states:
404 save_tccr2a = TCCR2A; // normal mode
405 save_tccr2b = TCCR2B;
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;
413 boolean pb_postth_state=0;
414 unsigned int pb_time=0;
416 void sensorEchoCommand(char command)
418 Serial.print("Sensor ");
419 Serial.print(command);
426 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
427 ir_count2 += (digitalRead(IR_MOVEMENT_PIN2) == HIGH);
429 if (pb_time < PB_TRESHOLD)
431 pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
435 if (ir_count >= IR_TRESHOLD || ir_count2 >= IR_TRESHOLD)
437 flash_led(0, 1, 8, 1, 0 );
438 Serial.println("movement");
440 ir_time=IR_SAMPLE_DURATION;
445 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
447 if (pb_state && ! pb_postth_state)
450 Serial.println("PanicButton");
451 flash_led(0, 28, 1, 4, 0 );
452 flash_led(1, 28, 1, 4, 4 );
457 else if (pb_state != pb_last_state)
460 pb_last_state=pb_state;
463 updateLightLevel(PHOTO_ANALOGPIN);
464 calculate_led_level();
466 if(Serial.available()) {
467 char command = Serial.read();
471 serial_read_send_rf_cmd();
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");
479 else if(command == 'b')
480 send_rf_cmd("\xa0\xa2\x28");
481 else if(command == 'C')
482 send_rf_cmd("\xa2\xa0\xa8");
483 else if(command == 'c')
484 send_rf_cmd("\xa2\xa0\x28");
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");
491 else if(command == 'e')
492 send_rf_cmd("\xa8\xa0\x28");
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 == '*')
531 sensorEchoCommand(command);
532 printTemperature(onShieldTemp);
534 else if(command == '?')
536 sensorEchoCommand(command);
539 else if (command == '^')
541 //flash_led(1, 1, 2, 1, 0);
542 flash_led(1, 1, 1, 1, 0);
543 Serial.println("Ok");
545 else if (command == '&')
547 flash_led(0, 1, 2, 1, 0);
548 Serial.println("Ok");
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);
605 Serial.println("Error: unknown command");