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 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
26 OneWire onewire(ONE_WIRE_PIN);
27 DallasTemperature dallas_sensors(&onewire);
28 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
30 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT
32 //********************************************************************//
33 // IR Codes, 32 bit, NEC
34 const int YAMAHA_CODE_BITS = 32;
35 const unsigned long int YAMAHA_CODE_BASE = 0x0000000005EA10000;
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
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
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)
54 const char YAMAHA_MUTE =0x38;
55 const char YAMAHA_VOLUME_UP =0x58;
56 const char YAMAHA_VOLUME_DOWN =0xD8;
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
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)
84 void send_yamaha_ir_signal(char codebyte)
86 unsigned long int code = codebyte & 0xFF;
88 code |= (0xff ^ codebyte) & 0xFF;
89 code |= YAMAHA_CODE_BASE;
90 irsend.sendNEC(code,YAMAHA_CODE_BITS);
94 //********************************************************************//
101 // offset is number of alphas (0.08ms)
103 const rf_bit_t zero_bit[] = { { 4, 1 },
109 const rf_bit_t one_bit[] = { { 12, 1 },
115 const rf_bit_t float_bit[] = { { 4, 1 },
121 const rf_bit_t sync_bit[] = { { 4, 1 },
125 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
126 typedef byte ad_bit_t;
128 typedef ad_bit_t word_t[WORD_LEN];
130 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
136 const ad_bit_t* current_word;
137 byte volatile frame_finished = 1;
161 const word_t words[] = {
162 { ZERO, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
163 { ZERO, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // A1_OFF
164 { ZERO, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
165 { ZERO, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // A2_OFF
167 { FLOAT, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
168 { FLOAT, ZERO, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // B1_OFF
169 { FLOAT, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
170 { FLOAT, ZERO, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // B2_OFF
172 { ZERO, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
173 { ZERO, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // C1_OFF
174 { ZERO, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
175 { ZERO, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // C2_OFF
177 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
178 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC }, // D1_OFF
179 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
180 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, SYNC } // D2_OFF
184 //********************************************************************//
189 TCCR1A = 0; // prescaler 1:8, WGM = 4 (CTC)
190 TCCR1B = 1<<WGM12 | 1<<CS11; //
191 OCR1A = 159; // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
192 // OCR1A = 207; // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
193 TCNT1 = 0; // reseting timer
194 TIMSK1 = 1<<OCIE1A; // enable Interrupt
197 void stop_timer() // stop the timer
200 TCCR1B = 0; // no clock source
201 TIMSK1 = 0; // disable timer interrupt
204 void init_word(const word_t w)
211 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
212 digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
214 digitalWrite(RF_DATA_OUT_PIN, HIGH);
219 ISR(TIMER1_COMPA_vect)
222 if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
226 if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 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 !
230 digitalWrite(RF_DATA_OUT_PIN, HIGH);
235 if(bit_cnt < WORD_LEN) {
238 if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
239 digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
241 digitalWrite(RF_DATA_OUT_PIN, HIGH);
245 digitalWrite(RF_DATA_OUT_PIN, HIGH);
248 if(word_cnt < FRAME_LEN)
249 init_word(current_word);
257 void send_frame(const word_t w)
259 if (frame_finished != 1)
260 for(;;) //wait until sending of previous frame finishes
271 void check_frame_done()
273 if (frame_finished==2)
275 Serial.println("Ok");
281 //********************************************************************//
283 void printTemperature(DeviceAddress deviceAddress)
285 dallas_sensors.requestTemperatures();
286 float tempC = dallas_sensors.getTempC(deviceAddress);
287 //Serial.print("Temp C: ");
288 Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
289 //Serial.print(" Temp F: ");
290 //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
293 //********************************************************************//
295 unsigned int light_level_mean_ = 0;
296 unsigned int light_sample_time_ = 0;
298 void updateLightLevel(unsigned int pin)
300 light_sample_time_++;
301 if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
303 light_sample_time_ = 0;
305 unsigned int value = analogRead(pin);
306 if (value == light_level_mean_)
309 unsigned int diff = abs(value - light_level_mean_);
311 light_level_mean_ = value;
313 light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
316 void printLightLevel()
318 //Serial.print("Photo: ");
319 Serial.println(light_level_mean_);
322 //********************************************************************//
324 unsigned long wm_start_=0;
325 bool wait_millis(unsigned long ms)
329 if (millis() < wm_start_ || millis() > wm_start_+ ms)
344 unsigned int flash_led_time_=0;
345 unsigned int flash_led_brightness_=255;
346 unsigned int flash_led_delay_=8;
347 unsigned int flash_led_selected_=0;
348 void calculate_led_level()
350 if (flash_led_time_ == 0 || flash_led_selected_ == 0)
352 if (wait_millis(flash_led_delay_))
355 int c = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
356 //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
357 if (flash_led_selected_ && (1 << BLUELED_PWM_PIN))
358 analogWrite(BLUELED_PWM_PIN, 255-c);
360 analogWrite(BLUELED_PWM_PIN,255); //off
361 if (flash_led_selected_ && (1 << PANICLED_PWM_PIN))
364 analogWrite(PANICLED_PWM_PIN, c);
366 analogWrite(PANICLED_PWM_PIN, 255-c);
369 analogWrite(PANICLED_PWM_PIN,255); //off
372 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int led_selector)
374 unsigned int new_flash_led_brightness = 255;
375 unsigned int new_flash_led_delay = 8;
376 flash_led_selected_=led_selector;
377 if (times == 0 || led_selector == 0)
379 analogWrite(PANICLED_PWM_PIN,255); //off
380 analogWrite(BLUELED_PWM_PIN,255); //off
383 if (brightness_divisor > 1) //guard against div by zero
384 new_flash_led_brightness /= brightness_divisor;
385 if (delay_divisor > 1) //guard against div by zero
386 new_flash_led_delay /= delay_divisor;
387 if (flash_led_time_ == 0 || new_flash_led_brightness > flash_led_brightness_)
388 flash_led_brightness_=new_flash_led_brightness;
389 if (flash_led_time_ == 0 || new_flash_led_delay < flash_led_delay_)
390 flash_led_delay_=new_flash_led_delay;
391 flash_led_time_ += 314*times;
394 //********************************************************************//
398 pinMode(RF_DATA_OUT_PIN, OUTPUT);
399 digitalWrite(RF_DATA_OUT_PIN, HIGH);
400 pinMode(IR_MOVEMENT_PIN, INPUT); // set pin to input
401 digitalWrite(IR_MOVEMENT_PIN, LOW); // turn off pulldown resistors
402 pinMode(PANIC_BUTTON_PIN, INPUT); // set pin to input
403 digitalWrite(PANIC_BUTTON_PIN, LOW); // turn on pulldown resistors
404 analogWrite(PANICLED_PWM_PIN,255);
405 analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
406 pinMode(IRREMOTE_SEND_PIN, OUTPUT);
407 digitalWrite(IRREMOTE_SEND_PIN, HIGH);
412 onewire.reset_search();
413 dallas_sensors.begin();
414 //in case we change temp sensor:
415 if (!dallas_sensors.getAddress(onShieldTemp, 0))
416 Serial.println("Error: Unable to find address for Device 0");
417 dallas_sensors.setResolution(onShieldTemp, 9);
420 unsigned int ir_time=IR_SAMPLE_DURATION;
421 unsigned int ir_count=0;
422 boolean pb_last_state=0;
424 boolean pb_postth_state=0;
425 unsigned int pb_time=0;
427 void sensorEchoCommand(char command)
429 Serial.print("Sensor ");
430 Serial.print(command);
437 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
439 if (pb_time < PB_TRESHOLD)
441 pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
445 if (ir_count >= IR_TRESHOLD)
447 flash_led(1, 8, 1, (1<<BLUELED_PWM_PIN) );
448 Serial.println("movement");
450 ir_time=IR_SAMPLE_DURATION;
454 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
456 if (pb_state && ! pb_postth_state)
459 Serial.println("PanicButton");
460 flash_led(14, 1, 2, (1<<BLUELED_PWM_PIN)|(1<<PANICLED_PWM_PIN) );
465 else if (pb_state != pb_last_state)
468 pb_last_state=pb_state;
471 updateLightLevel(PHOTO_ANALOGPIN);
472 calculate_led_level();
475 if(Serial.available()) {
476 char command = Serial.read();
479 send_frame(words[A1_ON]);
480 else if(command == 'a')
481 send_frame(words[A1_OFF]);
482 else if(command == 'B')
483 send_frame(words[A2_ON]);
484 else if(command == 'b')
485 send_frame(words[A2_OFF]);
487 else if(command == 'C')
488 send_frame(words[B1_ON]);
489 else if(command == 'c')
490 send_frame(words[B1_OFF]);
491 else if(command == 'D')
492 send_frame(words[B2_ON]);
493 else if(command == 'd')
494 send_frame(words[B2_OFF]);
496 else if(command == 'E')
497 send_frame(words[C1_ON]);
498 else if(command == 'e')
499 send_frame(words[C1_OFF]);
500 else if(command == 'F')
501 send_frame(words[C2_ON]);
502 else if(command == 'f')
503 send_frame(words[C2_OFF]);
505 else if(command == 'G')
506 send_frame(words[D1_ON]);
507 else if(command == 'g')
508 send_frame(words[D1_OFF]);
509 else if(command == 'H')
510 send_frame(words[D2_ON]);
511 else if(command == 'h')
512 send_frame(words[D2_OFF]);
513 else if(command == 'T')
515 sensorEchoCommand(command);
516 printTemperature(onShieldTemp);
518 else if(command == 'P')
520 sensorEchoCommand(command);
523 else if (command == '^')
524 flash_led(1, 2, 1, (1 << PANICLED_PWM_PIN));
525 else if (command == '0')
526 send_yamaha_ir_signal(YAMAHA_POWER_OFF);
527 else if (command == '1')
528 send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
529 else if (command == '2')
530 send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
531 else if (command == '3')
532 send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
533 else if (command == '4')
534 send_yamaha_ir_signal(YAMAHA_MUTE);
535 else if (command == '5')
536 send_yamaha_ir_signal(YAMAHA_CD);
537 else if (command == '6')
538 send_yamaha_ir_signal(YAMAHA_TUNER);
539 else if (command == '7')
540 send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
541 else if (command == '8')
542 send_yamaha_ir_signal(YAMAHA_MENU);
543 else if (command == '+')
544 send_yamaha_ir_signal(YAMAHA_PLUS);
545 else if (command == '-')
546 send_yamaha_ir_signal(YAMAHA_MINUS);
547 else if (command == 0xa7) // §
548 send_yamaha_ir_signal(YAMAHA_TEST);
549 else if (command == '$')
550 send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
551 else if (command == '%')
552 send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
553 else if (command == '&')
554 send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
555 else if (command == '/')
556 send_yamaha_ir_signal(YAMAHA_PRG_UP);
557 else if (command == '(')
558 send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
559 else if (command == '[')
560 send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
561 else if (command == ')')
562 send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
563 else if (command == '9')
564 send_yamaha_ir_signal(YAMAHA_TAPE);
565 else if (command == '?')
566 send_yamaha_ir_signal(YAMAHA_VCR);
567 else if (command == '=')
568 send_yamaha_ir_signal(YAMAHA_EXT51DEC);
570 Serial.println("Error: unknown command");