IR Tweaks (inverted + higher power cycle)
[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 6
15 #define BLUELED2_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
25
26 OneWire  onewire(ONE_WIRE_PIN);
27 DallasTemperature dallas_sensors(&onewire);
28 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
29 IRsend irsend; 
30 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT 
31
32 //********************************************************************//
33 // IR Codes, 32 bit, NEC
34 const int YAMAHA_CODE_BITS=32;
35 const unsigned long int YAMAHA_POWER = 0x000000005EA1F807;
36 const unsigned long int YAMAHA_CD = 0x000000005EA1A857;
37 const unsigned long int YAMAHA_TUNER = 0x000000005EA16897;
38 const unsigned long int YAMAHA_SAT = 0x000000005EA19867;
39 const unsigned long int YAMAHA_DVD = 0x000000005EA118E7;
40 const unsigned long int YAMAHA_DVD_SPDIF = 0x000000005EA1E817;
41 const unsigned long int YAMAHA_VCR_1 = 0x000000005EA1F00F;
42 const unsigned long int YAMAHA_TUNER_PLUS = 0x000000005EA108F7;
43 const unsigned long int YAMAHA_TUNER_ABCDE = 0x000000005EA148B7;
44 const unsigned long int YAMAHA_FRONT_LEVEL_P = 0x000000005EA101FE;
45 const unsigned long int YAMAHA_FRONT_LEVEL_M = 0x000000005EA1817E;
46 const unsigned long int YAMAHA_CENTRE_LEVEL_P = 0x000000005EA141BE;
47 const unsigned long int YAMAHA_CENTRE_LEVEL_M = 0x000000005EA1C13E;
48 const unsigned long int YAMAHA_REAR_LEVEL_P = 0x000000005EA17A85;
49 const unsigned long int YAMAHA_REAR_LEVEL_M = 0x000000005EA1FA05;
50 const unsigned long int YAMAHA_DELAY_TIME_P = 0x000000005EA14AB5;
51 const unsigned long int YAMAHA_DELAY_TIME_M = 0x000000005EA1CA35;
52 const unsigned long int YAMAHA_MUTE = 0x000000005EA138C7;
53 const unsigned long int YAMAHA_VOLUME_UP = 0x000000005EA158A7;
54 const unsigned long int YAMAHA_VOLUME_DOWN = 0x000000005EA1D827;
55
56 //********************************************************************//
57
58 typedef struct {
59   byte offset;
60   byte state;
61 } rf_bit_t;
62
63 // offset is number of alphas (0.08ms)
64
65 const rf_bit_t zero_bit[] = { {  4, 1 },
66                               { 16, 0 },
67                               { 20, 1 },
68                               { 32, 0 },
69                               {  0, 0 } };
70
71 const rf_bit_t one_bit[] = { { 12, 1 },
72                              { 16, 0 },
73                              { 28, 1 },
74                              { 32, 0 },
75                              {  0, 0 } };
76
77 const rf_bit_t float_bit[] = { {  4, 1 },
78                                { 16, 0 },
79                                { 28, 1 },
80                                { 32, 0 },
81                                {  0, 0 } };
82
83 const rf_bit_t sync_bit[] = { {   4, 1 },
84                               { 128, 0 },
85                               {   0, 0 } };
86
87 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
88 typedef byte ad_bit_t;
89 #define WORD_LEN 13
90 typedef ad_bit_t word_t[WORD_LEN];
91
92 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
93
94 byte alpha_cnt = 0;
95 byte bit_cnt = 0;
96 byte chunk_cnt = 0;
97 byte word_cnt = 0;
98 const ad_bit_t* current_word;
99 byte volatile frame_finished = 1;
100
101 #define FRAME_LEN 8
102
103 #define A1_ON  0
104 #define A1_OFF 1
105 #define A2_ON  2
106 #define A2_OFF 3
107
108 #define B1_ON  4
109 #define B1_OFF 5
110 #define B2_ON  6
111 #define B2_OFF 7
112
113 #define C1_ON  8
114 #define C1_OFF 9
115 #define C2_ON  10
116 #define C2_OFF 11
117
118 #define D1_ON  12
119 #define D1_OFF 13
120 #define D2_ON  14
121 #define D2_OFF 15
122
123 const word_t words[]  = { 
124 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
125 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A1_OFF
126 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
127 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A2_OFF
128
129 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
130 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B1_OFF
131 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
132 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B2_OFF
133
134 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
135 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C1_OFF
136 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
137 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C2_OFF
138
139 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
140 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // D1_OFF
141 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
142 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }  // D2_OFF
143 };
144
145
146 //********************************************************************//
147
148 void start_timer()
149 {
150   // timer 1: 2 ms
151   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
152   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
153   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
154 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
155   TCNT1 = 0;          // reseting timer
156   TIMSK1 = 1<<OCIE1A; // enable Interrupt
157 }
158
159 void stop_timer() // stop the timer
160 {
161   // timer1
162   TCCR1B = 0; // no clock source
163   TIMSK1 = 0; // disable timer interrupt
164 }
165
166 void init_word(const word_t w)
167 {
168   current_word = w;
169   alpha_cnt = 0;
170   chunk_cnt = 0;
171   bit_cnt = 0;
172
173   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
174     digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
175   else
176     digitalWrite(RF_DATA_OUT_PIN, HIGH);
177
178   start_timer();
179 }
180
181 ISR(TIMER1_COMPA_vect)
182 {
183   alpha_cnt++;
184   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
185     return;
186
187   chunk_cnt++;
188   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
189     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
190       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
191     else
192       digitalWrite(RF_DATA_OUT_PIN, HIGH);
193     return;
194   }
195   
196   bit_cnt++;
197   if(bit_cnt < WORD_LEN) {
198     alpha_cnt = 0;
199     chunk_cnt = 0;
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 !
202     else
203       digitalWrite(RF_DATA_OUT_PIN, HIGH);
204     return;
205   }
206   stop_timer();
207   digitalWrite(RF_DATA_OUT_PIN, HIGH);
208
209   word_cnt++;
210   if(word_cnt < FRAME_LEN)
211     init_word(current_word);
212   else
213     frame_finished = 2;
214 }
215
216 //***********//
217
218
219 void send_frame(const word_t w)
220 {
221   if (frame_finished == 0)
222     for(;;)
223       if (frame_finished)
224       {
225         delay(150);
226         break;
227       }
228   word_cnt = 0;
229   frame_finished = 0;
230   init_word(w);      
231 }
232
233 void check_frame_done()
234 {
235   if (frame_finished==2)
236   {
237     Serial.println("Ok");
238     frame_finished=1;
239   }
240 }
241
242 //********************************************************************//
243
244 void printTemperature(DeviceAddress deviceAddress)
245 {
246   dallas_sensors.requestTemperatures();
247   float tempC = dallas_sensors.getTempC(deviceAddress);
248   //Serial.print("Temp C: ");
249   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
250   //Serial.print(" Temp F: ");
251   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
252 }
253
254 //********************************************************************//
255
256 unsigned int light_level_mean_ = 0;
257 unsigned int light_sample_time_ = 0;
258
259 void updateLightLevel(unsigned int pin)
260 {
261   light_sample_time_++;
262   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
263     return;
264   light_sample_time_ = 0;
265   
266   unsigned int value = analogRead(pin);
267   if (value == light_level_mean_)
268     return;
269   
270   unsigned int diff = abs(value - light_level_mean_);
271   if (diff > 100)
272     light_level_mean_ = value;
273   else
274       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
275 }
276
277 void printLightLevel()
278 {
279   //Serial.print("Photo: ");
280   Serial.println(light_level_mean_);
281 }
282
283 //********************************************************************//
284
285 unsigned long wm_start_=0;
286 bool wait_millis(unsigned long ms)
287 {
288   if (wm_start_ > 0)
289   {
290     if (millis() < wm_start_ || millis() > wm_start_+ ms)
291     {
292       wm_start_=0;
293       return false;
294     }
295     else
296       return true;
297   }
298   else
299   {
300     wm_start_=millis();
301     return true;
302   }
303 }
304
305 unsigned int flash_led_time_=0;
306 unsigned int flash_led_brightness_=255;
307 unsigned int flash_led_delay_=8;
308 void calculate_led_level(unsigned int pwm_pin)
309 {
310   if (flash_led_time_ == 0)
311     return;
312   if (wait_millis(flash_led_delay_))
313     return;
314   flash_led_time_--;
315   int c = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
316   //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
317   analogWrite(BLUELED2_PWM_PIN, 255-c);
318   if (flash_led_brightness_ == 255)
319   {
320     if (flash_led_time_)
321       analogWrite(BLUELED_PWM_PIN, 255-c);
322     else
323       analogWrite(BLUELED_PWM_PIN, c);
324   }
325 }
326
327 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor)
328 {
329   unsigned int new_flash_led_brightness = 255 / brightness_divisor;
330   unsigned int new_flash_led_delay = 8 / delay_divisor;
331   if (flash_led_time_ == 0 || new_flash_led_brightness > flash_led_brightness_)
332     flash_led_brightness_=new_flash_led_brightness;
333   if (flash_led_time_ == 0 || new_flash_led_delay < flash_led_delay_)
334     flash_led_delay_=new_flash_led_delay;
335   flash_led_time_ += 314*times;
336 }
337
338 //********************************************************************//
339
340 void setup()
341 {
342   pinMode(RF_DATA_OUT_PIN, OUTPUT);
343   digitalWrite(RF_DATA_OUT_PIN, HIGH);
344   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
345   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors  
346   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
347   digitalWrite(PANIC_BUTTON_PIN, HIGH);  // turn on pullup resistors 
348   analogWrite(BLUELED_PWM_PIN,0);
349   analogWrite(BLUELED2_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
350   pinMode(IRREMOTE_SEND_PIN, OUTPUT);
351   digitalWrite(IRREMOTE_SEND_PIN, HIGH);
352   
353   Serial.begin(9600);
354   
355   onewire.reset();
356   onewire.reset_search();
357   dallas_sensors.begin();
358   //in case we change temp sensor:
359   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
360     Serial.println("Error: Unable to find address for Device 0"); 
361   dallas_sensors.setResolution(onShieldTemp, 9);  
362 }
363
364 unsigned int ir_time=IR_SAMPLE_DURATION;
365 unsigned int ir_count=0;
366 boolean pb_last_state=0;
367 boolean pb_state=0;
368 boolean pb_postth_state=0;
369 unsigned int pb_time=0;
370
371 void sensorEchoCommand(char command)
372 {
373   Serial.print("Sensor ");
374   Serial.print(command);
375   Serial.print(": ");
376 }
377
378 void loop()
379 {
380   ir_time--;
381   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
382
383   if (pb_time < PB_TRESHOLD)
384     pb_time++;
385   pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
386   
387   if (ir_time == 0)
388   {
389     if (ir_count >= IR_TRESHOLD)
390     {
391       flash_led(1,8,1);
392       Serial.println("movement");
393     }
394     ir_time=IR_SAMPLE_DURATION;
395     ir_count=0;
396   }
397   
398   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
399   {
400     if (pb_state && ! pb_postth_state)
401     {   
402       pb_postth_state=1;
403       Serial.println("PanicButton");
404       flash_led(7,1,2);
405     }
406     else if (!pb_state)
407       pb_postth_state=0;
408   }
409   else if (pb_state != pb_last_state)
410   {
411     pb_time=0;
412     pb_last_state=pb_state;
413   }
414   
415   updateLightLevel(PHOTO_ANALOGPIN);
416   calculate_led_level(BLUELED_PWM_PIN);
417   check_frame_done();
418   
419   if(Serial.available()) {
420     char command = Serial.read();
421     
422     if(command == 'A')
423       send_frame(words[A1_ON]);
424     else if(command == 'a')
425       send_frame(words[A1_OFF]);
426     else if(command == 'B')
427       send_frame(words[A2_ON]);
428     else if(command == 'b')
429       send_frame(words[A2_OFF]);
430
431     else if(command == 'C')
432       send_frame(words[B1_ON]);
433     else if(command == 'c')
434       send_frame(words[B1_OFF]);
435     else if(command == 'D')
436       send_frame(words[B2_ON]);
437     else if(command == 'd')
438       send_frame(words[B2_OFF]);
439
440     else if(command == 'E')
441       send_frame(words[C1_ON]);
442     else if(command == 'e')
443       send_frame(words[C1_OFF]);
444     else if(command == 'F')
445       send_frame(words[C2_ON]);
446     else if(command == 'f')
447       send_frame(words[C2_OFF]);
448
449     else if(command == 'G')
450       send_frame(words[D1_ON]);
451     else if(command == 'g')
452       send_frame(words[D1_OFF]);
453     else if(command == 'H')
454       send_frame(words[D2_ON]);
455     else if(command == 'h')
456       send_frame(words[D2_OFF]);
457     else if(command == 'T')
458     {
459       sensorEchoCommand(command);
460       printTemperature(onShieldTemp);
461     }
462     else if(command == 'P')
463     {
464       sensorEchoCommand(command);
465       printLightLevel();
466     }
467     else if (command == '1')
468     {
469       irsend.sendNEC(YAMAHA_POWER,YAMAHA_CODE_BITS);
470       Serial.println("Ok");
471     }
472     else if (command == '2')
473     {
474       irsend.sendNEC(YAMAHA_CD,YAMAHA_CODE_BITS);
475       Serial.println("Ok");
476     }
477     else if (command == '3')
478     {
479       irsend.sendNEC(YAMAHA_DVD_SPDIF,YAMAHA_CODE_BITS);
480       Serial.println("Ok");
481     }
482     else if (command == '4')
483     {
484       irsend.sendNEC(YAMAHA_TUNER,YAMAHA_CODE_BITS);
485       Serial.println("Ok");
486     }    
487     else if (command == '5')
488     {
489       irsend.sendNEC(YAMAHA_VOLUME_UP,YAMAHA_CODE_BITS);
490       Serial.println("Ok");
491     }
492     else if (command == '6')
493     {
494       irsend.sendNEC(YAMAHA_VOLUME_DOWN,YAMAHA_CODE_BITS);
495       Serial.println("Ok");
496     }
497     else if (command == '7')
498     {
499       irsend.sendNEC(YAMAHA_MUTE,YAMAHA_CODE_BITS);
500       Serial.println("Ok");
501     }
502     else
503       Serial.println("Error: unknown command");
504   }
505 }