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 BLUELED_PWM_PIN 5
15 #define PANICLED_PWM_PIN 6
16 #define BLUELED2_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 12000
20 #define IR_TRESHOLD 10000
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_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 == 0)
271 void check_frame_done()
273 if (frame_finished==2)
275 Serial.println("Ok");
280 //********************************************************************//
282 void printTemperature(DeviceAddress deviceAddress)
284 dallas_sensors.requestTemperatures();
285 float tempC = dallas_sensors.getTempC(deviceAddress);
286 //Serial.print("Temp C: ");
287 Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
288 //Serial.print(" Temp F: ");
289 //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
292 //********************************************************************//
294 unsigned int light_level_mean_ = 0;
295 unsigned int light_sample_time_ = 0;
297 void updateLightLevel(unsigned int pin)
299 light_sample_time_++;
300 if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
302 light_sample_time_ = 0;
304 unsigned int value = analogRead(pin);
305 if (value == light_level_mean_)
308 unsigned int diff = abs(value - light_level_mean_);
310 light_level_mean_ = value;
312 light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
315 void printLightLevel()
317 //Serial.print("Photo: ");
318 Serial.println(light_level_mean_);
321 //********************************************************************//
323 unsigned long wm_start_=0;
324 bool wait_millis(unsigned long ms)
328 if (millis() < wm_start_ || millis() > wm_start_+ ms)
343 unsigned int flash_led_time_=0;
344 unsigned int flash_led_brightness_=255;
345 unsigned int flash_led_delay_=8;
346 void calculate_led_level(unsigned int pwm_pin)
348 if (flash_led_time_ == 0)
350 if (wait_millis(flash_led_delay_))
353 int c = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
354 //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
355 analogWrite(BLUELED2_PWM_PIN, 255-c);
356 if (flash_led_brightness_ == 255)
359 analogWrite(PANICLED_PWM_PIN, c);
361 analogWrite(PANICLED_PWM_PIN, 255-c);
365 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor)
367 unsigned int new_flash_led_brightness = 255 / brightness_divisor;
368 unsigned int new_flash_led_delay = 8 / delay_divisor;
369 if (flash_led_time_ == 0 || new_flash_led_brightness > flash_led_brightness_)
370 flash_led_brightness_=new_flash_led_brightness;
371 if (flash_led_time_ == 0 || new_flash_led_delay < flash_led_delay_)
372 flash_led_delay_=new_flash_led_delay;
373 flash_led_time_ += 314*times;
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 pulldown resistors
384 pinMode(PANIC_BUTTON_PIN, INPUT); // set pin to input
385 digitalWrite(PANIC_BUTTON_PIN, LOW); // turn on pulldown resistors
386 analogWrite(BLUELED_PWM_PIN,255);
387 analogWrite(PANICLED_PWM_PIN,255);
388 analogWrite(BLUELED2_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);
403 unsigned int ir_time=IR_SAMPLE_DURATION;
404 unsigned int ir_count=0;
405 boolean pb_last_state=0;
407 boolean pb_postth_state=0;
408 unsigned int pb_time=0;
410 void sensorEchoCommand(char command)
412 Serial.print("Sensor ");
413 Serial.print(command);
420 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
422 if (pb_time < PB_TRESHOLD)
424 pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
428 if (ir_count >= IR_TRESHOLD)
431 Serial.println("movement");
433 ir_time=IR_SAMPLE_DURATION;
437 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
439 if (pb_state && ! pb_postth_state)
442 Serial.println("PanicButton");
448 else if (pb_state != pb_last_state)
451 pb_last_state=pb_state;
454 updateLightLevel(PHOTO_ANALOGPIN);
455 calculate_led_level(PANICLED_PWM_PIN);
458 if(Serial.available()) {
459 char command = Serial.read();
462 send_frame(words[A1_ON]);
463 else if(command == 'a')
464 send_frame(words[A1_OFF]);
465 else if(command == 'B')
466 send_frame(words[A2_ON]);
467 else if(command == 'b')
468 send_frame(words[A2_OFF]);
470 else if(command == 'C')
471 send_frame(words[B1_ON]);
472 else if(command == 'c')
473 send_frame(words[B1_OFF]);
474 else if(command == 'D')
475 send_frame(words[B2_ON]);
476 else if(command == 'd')
477 send_frame(words[B2_OFF]);
479 else if(command == 'E')
480 send_frame(words[C1_ON]);
481 else if(command == 'e')
482 send_frame(words[C1_OFF]);
483 else if(command == 'F')
484 send_frame(words[C2_ON]);
485 else if(command == 'f')
486 send_frame(words[C2_OFF]);
488 else if(command == 'G')
489 send_frame(words[D1_ON]);
490 else if(command == 'g')
491 send_frame(words[D1_OFF]);
492 else if(command == 'H')
493 send_frame(words[D2_ON]);
494 else if(command == 'h')
495 send_frame(words[D2_OFF]);
496 else if(command == 'T')
498 sensorEchoCommand(command);
499 printTemperature(onShieldTemp);
501 else if(command == 'P')
503 sensorEchoCommand(command);
506 else if (command == '0')
507 send_yamaha_ir_signal(YAMAHA_POWER_OFF);
508 else if (command == '1')
509 send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
510 else if (command == '2')
511 send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
512 else if (command == '3')
513 send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
514 else if (command == '4')
515 send_yamaha_ir_signal(YAMAHA_MUTE);
516 else if (command == '5')
517 send_yamaha_ir_signal(YAMAHA_CD);
518 else if (command == '6')
519 send_yamaha_ir_signal(YAMAHA_TUNER);
520 else if (command == '7')
521 send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
522 else if (command == '8')
523 send_yamaha_ir_signal(YAMAHA_MENU);
524 else if (command == '+')
525 send_yamaha_ir_signal(YAMAHA_PLUS);
526 else if (command == '-')
527 send_yamaha_ir_signal(YAMAHA_MINUS);
528 else if (command == '§')
529 send_yamaha_ir_signal(YAMAHA_TEST);
530 else if (command == '$')
531 send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
532 else if (command == '%')
533 send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
534 else if (command == '&')
535 send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
536 else if (command == '/')
537 send_yamaha_ir_signal(YAMAHA_PRG_UP);
538 else if (command == '(')
539 send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
540 else if (command == ')')
541 send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
542 else if (command == '9')
543 send_yamaha_ir_signal(YAMAHA_TAPE);
544 else if (command == '?')
545 send_yamaha_ir_signal(YAMAHA_VCR);
546 else if (command == '=')
547 send_yamaha_ir_signal(YAMAHA_EXT51DEC);
549 Serial.println("Error: unknown command");