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 8000
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)
83 //********************************************************************//
90 // offset is number of alphas (0.08ms)
92 const rf_bit_t zero_bit[] = { { 4, 1 },
98 const rf_bit_t one_bit[] = { { 12, 1 },
104 const rf_bit_t float_bit[] = { { 4, 1 },
110 const rf_bit_t sync_bit[] = { { 4, 1 },
114 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
115 typedef byte ad_bit_t;
117 typedef ad_bit_t word_t[WORD_LEN];
119 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
125 const ad_bit_t* current_word;
126 byte volatile frame_finished = 1;
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
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
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
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
173 //********************************************************************//
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
186 void stop_timer() // stop the timer
189 TCCR1B = 0; // no clock source
190 TIMSK1 = 0; // disable timer interrupt
193 void init_word(const word_t w)
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 !
203 digitalWrite(RF_DATA_OUT_PIN, HIGH);
208 ISR(TIMER1_COMPA_vect)
211 if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
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 !
219 digitalWrite(RF_DATA_OUT_PIN, HIGH);
224 if(bit_cnt < WORD_LEN) {
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);
234 digitalWrite(RF_DATA_OUT_PIN, HIGH);
237 if(word_cnt < FRAME_LEN)
238 init_word(current_word);
246 void send_frame(const word_t w)
248 if (frame_finished != 1)
249 for(;;) //wait until sending of previous frame finishes
260 void check_frame_done()
262 if (frame_finished==2)
264 Serial.println("Ok");
270 //********************************************************************//
272 void printTemperature(DeviceAddress deviceAddress)
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
282 //********************************************************************//
284 unsigned int light_level_mean_ = 0;
285 unsigned int light_sample_time_ = 0;
287 void updateLightLevel(unsigned int pin)
289 light_sample_time_++;
290 if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
292 light_sample_time_ = 0;
294 unsigned int value = analogRead(pin);
295 if (value == light_level_mean_)
298 unsigned int diff = abs(value - light_level_mean_);
300 light_level_mean_ = value;
302 light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
305 void printLightLevel()
307 //Serial.print("Photo: ");
308 Serial.println(light_level_mean_);
311 //********************************************************************//
313 unsigned long wm_start_[3]={0,0,0};
314 bool wait_millis(unsigned long *start_time, unsigned long ms)
318 else if (*start_time > 0)
320 if (millis() < *start_time || millis() > (*start_time) + ms)
330 *start_time=millis();
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()
342 for (int ledid = 0; ledid < NUM_LEDS; ledid++)
344 if (flash_led_time_[ledid] == 0)
346 if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
348 flash_led_initial_delay_[ledid]=0;
349 if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
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);
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)
367 unsigned int new_flash_led_brightness = 255;
368 unsigned int new_flash_led_delay = 8;
371 analogWrite(flash_led_pins_[id],255); //off
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;
386 //********************************************************************//
394 TCCR2A = save_tccr2a; // normal mode
395 TCCR2B = save_tccr2b;
396 //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
397 //TCCR2A = 0; // normal mode
401 void send_yamaha_ir_signal(char codebyte)
403 unsigned long int code = codebyte & 0xFF;
405 code |= (0xff ^ codebyte) & 0xFF;
406 code |= YAMAHA_CODE_BASE;
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
413 irsend.sendNEC(code,YAMAHA_CODE_BITS);
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
419 Serial.println("Ok");
422 //********************************************************************//
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);
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);
447 //save prev timer states:
449 save_tccr2a = TCCR2A; // normal mode
450 save_tccr2b = TCCR2B;
453 unsigned int ir_time=IR_SAMPLE_DURATION;
454 unsigned int ir_count=0;
455 boolean pb_last_state=0;
457 boolean pb_postth_state=0;
458 unsigned int pb_time=0;
460 void sensorEchoCommand(char command)
462 Serial.print("Sensor ");
463 Serial.print(command);
470 ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
472 if (pb_time < PB_TRESHOLD)
474 pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
478 if (ir_count >= IR_TRESHOLD)
480 flash_led(0, 1, 8, 1, 0 );
481 Serial.println("movement");
483 ir_time=IR_SAMPLE_DURATION;
487 if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
489 if (pb_state && ! pb_postth_state)
492 Serial.println("PanicButton");
493 flash_led(0, 28, 1, 4, 0 );
494 flash_led(1, 28, 1, 4, 4 );
499 else if (pb_state != pb_last_state)
502 pb_last_state=pb_state;
505 updateLightLevel(PHOTO_ANALOGPIN);
506 calculate_led_level();
509 if(Serial.available()) {
510 char command = Serial.read();
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]);
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]);
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]);
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')
549 sensorEchoCommand(command);
550 printTemperature(onShieldTemp);
552 else if(command == 'P')
554 sensorEchoCommand(command);
557 else if (command == '^')
558 flash_led(1, 1, 2, 1, 0);
559 else if (command == '0')
560 send_yamaha_ir_signal(YAMAHA_POWER_OFF);
561 else if (command == '1')
562 send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
563 else if (command == '2')
564 send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
565 else if (command == '3')
566 send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
567 else if (command == '4')
568 send_yamaha_ir_signal(YAMAHA_MUTE);
569 else if (command == '5')
570 send_yamaha_ir_signal(YAMAHA_CD);
571 else if (command == '6')
572 send_yamaha_ir_signal(YAMAHA_TUNER);
573 else if (command == '7')
574 send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
575 else if (command == '8')
576 send_yamaha_ir_signal(YAMAHA_MENU);
577 else if (command == '+')
578 send_yamaha_ir_signal(YAMAHA_PLUS);
579 else if (command == '-')
580 send_yamaha_ir_signal(YAMAHA_MINUS);
581 else if (command == 0xa7) // §
582 send_yamaha_ir_signal(YAMAHA_TEST);
583 else if (command == '$')
584 send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
585 else if (command == '%')
586 send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
587 else if (command == '&')
588 send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
589 else if (command == '/')
590 send_yamaha_ir_signal(YAMAHA_PRG_UP);
591 else if (command == '(')
592 send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
593 else if (command == '[')
594 send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
595 else if (command == ')')
596 send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
597 else if (command == '9')
598 send_yamaha_ir_signal(YAMAHA_TAPE);
599 else if (command == '?')
600 send_yamaha_ir_signal(YAMAHA_VCR);
601 else if (command == '=')
602 send_yamaha_ir_signal(YAMAHA_EXT51DEC);
604 Serial.println("Error: unknown command");