+aref .... PanicButton....Panic-Led
[svn42.git] / rf433ctl / rf433ctl.pde
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <inttypes.h>
4 #include <OneWire.h>
5 #include <DallasTemperature.h>
6 #include <IRremote.h>
7
8 //********************************************************************//
9
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
26
27 OneWire  onewire(ONE_WIRE_PIN);
28 DallasTemperature dallas_sensors(&onewire);
29 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
30 IRsend irsend; 
31 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT 
32
33 //********************************************************************//
34 // IR Codes, 32 bit, NEC
35 const int YAMAHA_CODE_BITS = 32;
36 const unsigned long int YAMAHA_CODE_BASE = 0x0000000005EA10000;
37
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
41
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
50
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)
53
54 const char YAMAHA_MUTE =0x38;
55 const char YAMAHA_VOLUME_UP =0x58;
56 const char YAMAHA_VOLUME_DOWN =0xD8;
57
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
71
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)
82
83
84 void send_yamaha_ir_signal(char codebyte)
85 {
86   unsigned long int code = codebyte & 0xFF;
87   code <<= 8;
88   code |= (0xff ^ codebyte) & 0xFF;
89   code |= YAMAHA_CODE_BASE;
90   irsend.sendNEC(code,YAMAHA_CODE_BITS);
91   Serial.println("Ok");  
92 }
93
94 //********************************************************************//
95
96 typedef struct {
97   byte offset;
98   byte state;
99 } rf_bit_t;
100
101 // offset is number of alphas (0.08ms)
102
103 const rf_bit_t zero_bit[] = { {  4, 1 },
104                               { 16, 0 },
105                               { 20, 1 },
106                               { 32, 0 },
107                               {  0, 0 } };
108
109 const rf_bit_t one_bit[] = { { 12, 1 },
110                              { 16, 0 },
111                              { 28, 1 },
112                              { 32, 0 },
113                              {  0, 0 } };
114
115 const rf_bit_t float_bit[] = { {  4, 1 },
116                                { 16, 0 },
117                                { 28, 1 },
118                                { 32, 0 },
119                                {  0, 0 } };
120
121 const rf_bit_t sync_bit[] = { {   4, 1 },
122                               { 128, 0 },
123                               {   0, 0 } };
124
125 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
126 typedef byte ad_bit_t;
127 #define WORD_LEN 13
128 typedef ad_bit_t word_t[WORD_LEN];
129
130 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
131
132 byte alpha_cnt = 0;
133 byte bit_cnt = 0;
134 byte chunk_cnt = 0;
135 byte word_cnt = 0;
136 const ad_bit_t* current_word;
137 byte volatile frame_finished = 1;
138
139 #define FRAME_LEN 8
140
141 #define A1_ON  0
142 #define A1_OFF 1
143 #define A2_ON  2
144 #define A2_OFF 3
145
146 #define B1_ON  4
147 #define B1_OFF 5
148 #define B2_ON  6
149 #define B2_OFF 7
150
151 #define C1_ON  8
152 #define C1_OFF 9
153 #define C2_ON  10
154 #define C2_OFF 11
155
156 #define D1_ON  12
157 #define D1_OFF 13
158 #define D2_ON  14
159 #define D2_OFF 15
160
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
166
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
171
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
176
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
181 };
182
183
184 //********************************************************************//
185
186 void start_timer()
187 {
188   // timer 1: 2 ms
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
195 }
196
197 void stop_timer() // stop the timer
198 {
199   // timer1
200   TCCR1B = 0; // no clock source
201   TIMSK1 = 0; // disable timer interrupt
202 }
203
204 void init_word(const word_t w)
205 {
206   current_word = w;
207   alpha_cnt = 0;
208   chunk_cnt = 0;
209   bit_cnt = 0;
210
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 !
213   else
214     digitalWrite(RF_DATA_OUT_PIN, HIGH);
215
216   start_timer();
217 }
218
219 ISR(TIMER1_COMPA_vect)
220 {
221   alpha_cnt++;
222   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
223     return;
224
225   chunk_cnt++;
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 !
229     else
230       digitalWrite(RF_DATA_OUT_PIN, HIGH);
231     return;
232   }
233   
234   bit_cnt++;
235   if(bit_cnt < WORD_LEN) {
236     alpha_cnt = 0;
237     chunk_cnt = 0;
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 !
240     else
241       digitalWrite(RF_DATA_OUT_PIN, HIGH);
242     return;
243   }
244   stop_timer();
245   digitalWrite(RF_DATA_OUT_PIN, HIGH);
246
247   word_cnt++;
248   if(word_cnt < FRAME_LEN)
249     init_word(current_word);
250   else
251     frame_finished = 2;
252 }
253
254 //***********//
255
256
257 void send_frame(const word_t w)
258 {
259   if (frame_finished == 0)
260     for(;;)
261       if (frame_finished)
262       {
263         delay(150);
264         break;
265       }
266   word_cnt = 0;
267   frame_finished = 0;
268   init_word(w);      
269 }
270
271 void check_frame_done()
272 {
273   if (frame_finished==2)
274   {
275     Serial.println("Ok");
276     frame_finished=1;
277   }
278 }
279
280 //********************************************************************//
281
282 void printTemperature(DeviceAddress deviceAddress)
283 {
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
290 }
291
292 //********************************************************************//
293
294 unsigned int light_level_mean_ = 0;
295 unsigned int light_sample_time_ = 0;
296
297 void updateLightLevel(unsigned int pin)
298 {
299   light_sample_time_++;
300   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
301     return;
302   light_sample_time_ = 0;
303   
304   unsigned int value = analogRead(pin);
305   if (value == light_level_mean_)
306     return;
307   
308   unsigned int diff = abs(value - light_level_mean_);
309   if (diff > 100)
310     light_level_mean_ = value;
311   else
312       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
313 }
314
315 void printLightLevel()
316 {
317   //Serial.print("Photo: ");
318   Serial.println(light_level_mean_);
319 }
320
321 //********************************************************************//
322
323 unsigned long wm_start_=0;
324 bool wait_millis(unsigned long ms)
325 {
326   if (wm_start_ > 0)
327   {
328     if (millis() < wm_start_ || millis() > wm_start_+ ms)
329     {
330       wm_start_=0;
331       return false;
332     }
333     else
334       return true;
335   }
336   else
337   {
338     wm_start_=millis();
339     return true;
340   }
341 }
342
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)
347 {
348   if (flash_led_time_ == 0)
349     return;
350   if (wait_millis(flash_led_delay_))
351     return;
352   flash_led_time_--;
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)
357   {
358     if (flash_led_time_)
359       analogWrite(PANICLED_PWM_PIN, c);
360     else
361       analogWrite(PANICLED_PWM_PIN, 255-c);
362   }
363 }
364
365 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor)
366 {
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;
374 }
375
376 //********************************************************************//
377
378 void setup()
379 {
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);
391   
392   Serial.begin(9600);
393   
394   onewire.reset();
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);  
401 }
402
403 unsigned int ir_time=IR_SAMPLE_DURATION;
404 unsigned int ir_count=0;
405 boolean pb_last_state=0;
406 boolean pb_state=0;
407 boolean pb_postth_state=0;
408 unsigned int pb_time=0;
409
410 void sensorEchoCommand(char command)
411 {
412   Serial.print("Sensor ");
413   Serial.print(command);
414   Serial.print(": ");
415 }
416
417 void loop()
418 {
419   ir_time--;
420   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
421
422   if (pb_time < PB_TRESHOLD)
423     pb_time++;
424   pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
425   
426   if (ir_time == 0)
427   {
428     if (ir_count >= IR_TRESHOLD)
429     {
430       flash_led(1,8,1);
431       Serial.println("movement");
432     }
433     ir_time=IR_SAMPLE_DURATION;
434     ir_count=0;
435   }
436   
437   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
438   {
439     if (pb_state && ! pb_postth_state)
440     {   
441       pb_postth_state=1;
442       Serial.println("PanicButton");
443       flash_led(14,1,2);
444     }
445     else if (!pb_state)
446       pb_postth_state=0;
447   }
448   else if (pb_state != pb_last_state)
449   {
450     pb_time=0;
451     pb_last_state=pb_state;
452   }
453   
454   updateLightLevel(PHOTO_ANALOGPIN);
455   calculate_led_level(PANICLED_PWM_PIN);
456   check_frame_done();
457   
458   if(Serial.available()) {
459     char command = Serial.read();
460     
461     if(command == 'A')
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]);
469
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]);
478
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]);
487
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')
497     {
498       sensorEchoCommand(command);
499       printTemperature(onShieldTemp);
500     }
501     else if(command == 'P')
502     {
503       sensorEchoCommand(command);
504       printLightLevel();
505     }
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);    
548     else
549       Serial.println("Error: unknown command");
550   }
551 }