IRRemote fuer Yamaha Reciever
[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
351   Serial.begin(9600);
352   
353   onewire.reset();
354   onewire.reset_search();
355   dallas_sensors.begin();
356   //in case we change temp sensor:
357   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
358     Serial.println("Error: Unable to find address for Device 0"); 
359   dallas_sensors.setResolution(onShieldTemp, 9);  
360 }
361
362 unsigned int ir_time=IR_SAMPLE_DURATION;
363 unsigned int ir_count=0;
364 boolean pb_last_state=0;
365 boolean pb_state=0;
366 boolean pb_postth_state=0;
367 unsigned int pb_time=0;
368
369 void sensorEchoCommand(char command)
370 {
371   Serial.print("Sensor ");
372   Serial.print(command);
373   Serial.print(": ");
374 }
375
376 void loop()
377 {
378   ir_time--;
379   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
380
381   if (pb_time < PB_TRESHOLD)
382     pb_time++;
383   pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
384   
385   if (ir_time == 0)
386   {
387     if (ir_count >= IR_TRESHOLD)
388     {
389       flash_led(1,8,1);
390       Serial.println("movement");
391     }
392     ir_time=IR_SAMPLE_DURATION;
393     ir_count=0;
394   }
395   
396   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
397   {
398     if (pb_state && ! pb_postth_state)
399     {   
400       pb_postth_state=1;
401       Serial.println("PanicButton");
402       flash_led(7,1,2);
403     }
404     else if (!pb_state)
405       pb_postth_state=0;
406   }
407   else if (pb_state != pb_last_state)
408   {
409     pb_time=0;
410     pb_last_state=pb_state;
411   }
412   
413   updateLightLevel(PHOTO_ANALOGPIN);
414   calculate_led_level(BLUELED_PWM_PIN);
415   check_frame_done();
416   
417   if(Serial.available()) {
418     char command = Serial.read();
419     
420     if(command == 'A')
421       send_frame(words[A1_ON]);
422     else if(command == 'a')
423       send_frame(words[A1_OFF]);
424     else if(command == 'B')
425       send_frame(words[A2_ON]);
426     else if(command == 'b')
427       send_frame(words[A2_OFF]);
428
429     else if(command == 'C')
430       send_frame(words[B1_ON]);
431     else if(command == 'c')
432       send_frame(words[B1_OFF]);
433     else if(command == 'D')
434       send_frame(words[B2_ON]);
435     else if(command == 'd')
436       send_frame(words[B2_OFF]);
437
438     else if(command == 'E')
439       send_frame(words[C1_ON]);
440     else if(command == 'e')
441       send_frame(words[C1_OFF]);
442     else if(command == 'F')
443       send_frame(words[C2_ON]);
444     else if(command == 'f')
445       send_frame(words[C2_OFF]);
446
447     else if(command == 'G')
448       send_frame(words[D1_ON]);
449     else if(command == 'g')
450       send_frame(words[D1_OFF]);
451     else if(command == 'H')
452       send_frame(words[D2_ON]);
453     else if(command == 'h')
454       send_frame(words[D2_OFF]);
455     else if(command == 'T')
456     {
457       sensorEchoCommand(command);
458       printTemperature(onShieldTemp);
459     }
460     else if(command == 'P')
461     {
462       sensorEchoCommand(command);
463       printLightLevel();
464     }
465     else if (command == '1')
466     {
467       irsend.sendNEC(YAMAHA_POWER,YAMAHA_CODE_BITS);
468       Serial.println("Ok");
469     }
470     else if (command == '2')
471     {
472       irsend.sendNEC(YAMAHA_CD,YAMAHA_CODE_BITS);
473       Serial.println("Ok");
474     }
475     else if (command == '3')
476     {
477       irsend.sendNEC(YAMAHA_DVD_SPDIF,YAMAHA_CODE_BITS);
478       Serial.println("Ok");
479     }
480     else if (command == '4')
481     {
482       irsend.sendNEC(YAMAHA_TUNER,YAMAHA_CODE_BITS);
483       Serial.println("Ok");
484     }    
485     else if (command == '5')
486     {
487       irsend.sendNEC(YAMAHA_VOLUME_UP,YAMAHA_CODE_BITS);
488       Serial.println("Ok");
489     }
490     else if (command == '6')
491     {
492       irsend.sendNEC(YAMAHA_VOLUME_DOWN,YAMAHA_CODE_BITS);
493       Serial.println("Ok");
494     }
495     else if (command == '7')
496     {
497       irsend.sendNEC(YAMAHA_MUTE,YAMAHA_CODE_BITS);
498       Serial.println("Ok");
499     }
500     else
501       Serial.println("Error: unknown command");
502   }
503 }