fix BLACK_A1
[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 IR_MOVEMENT_PIN2 12
13 #define ONE_WIRE_PIN 8
14 #define PANIC_BUTTON_PIN 7
15 #define PANICLED_PWM_PIN 6
16 #define BLUELED_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 8000
20 #define IR_TRESHOLD 7500
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_MINUS =0x88; //Tuner Prev Station 1-7  (of A1 - E7)
53 const char YAMAHA_TUNER_ABCDE =0x48; //Tuner Next Station Row A-E (of A1 - E7)
54
55 const char YAMAHA_MUTE =0x38;
56 const char YAMAHA_VOLUME_UP =0x58;
57 const char YAMAHA_VOLUME_DOWN =0xD8;
58
59 //const char YAMAHA_FRONT_LEVEL_P =0x01;  //no function
60 //const char YAMAHA_FRONT_LEVEL_M =0x81; //no function
61 //const char YAMAHA_CENTRE_LEVEL_P =0x41;  //no function
62 //const char YAMAHA_CENTRE_LEVEL_M =0xC1; //no function
63 //const char YAMAHA_REAR_LEVEL_P =0x7A; //no function
64 //const char YAMAHA_REAR_LEVEL_M =0xFA; //no function
65 const char YAMAHA_PLUS =0x4A;  //unteres Steuerkreuz: Taste Rechts (Plus)
66 const char YAMAHA_MINUS =0xCA; //unteres Steuerkreuz: Taste Links (Minus)
67 const char YAMAHA_MENU =0x39; // Menu: Settings
68 const char YAMAHA_TEST =0xA1; // Test Sounds
69 const char YAMAHA_TIME_LEVEL =0x19; //Settings for Delay, Subwfs, Right Surround, Left Surround, Center
70 const char YAMAHA_TIME_LEVEL2 =0x61; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
71 const char YAMAHA_TIME_LEVEL3 =0x99; //(also) Settings for Delay, Subwfs, Right Surround, Left Surround, Center
72
73 const char YAMAHA_EFFECT_TOGGLE =0x6A; //Effect Toggle On/Off
74 const char YAMAHA_PRG_DOWN =0x9A; //Effect/DSP Programm Toggle in down direction
75 const char YAMAHA_PRG_UP =0x1A; //Effect/DSP Programm Toggle in up direction
76 const char YAMAHA_EFFECT1 =0x31; //Effect TV Sports
77 const char YAMAHA_EFFECT2 =0x71; //Effect Rock Concert
78 const char YAMAHA_EFFECT3 =0xB1;  //Effect Disco
79 const char YAMAHA_EFFECT4 =0xD1;  //Mono Movie
80 const char YAMAHA_EFFECT5 =0x91; //Effect Toggle 70mm Sci-Fi / 70mm Spectacle
81 const char YAMAHA_EFFECT6 =0x51; //Effect Toggle 70mm General / 70mm Adventure
82 const char YAMAHA_P5 =0xFB; //P5 PRT (1 Main Bypass)? (1587674115)
83
84 //********************************************************************//
85
86 typedef struct {
87   byte offset;
88   byte state;
89 } rf_bit_t;
90
91 // offset is number of alphas (0.08ms)
92
93 const rf_bit_t zero_bit[] = { {  4, 1 },
94                               { 16, 0 },
95                               { 20, 1 },
96                               { 32, 0 },
97                               {  0, 0 } };
98
99 const rf_bit_t one_bit[] = { { 12, 1 },
100                              { 16, 0 },
101                              { 28, 1 },
102                              { 32, 0 },
103                              {  0, 0 } };
104
105 const rf_bit_t float_bit[] = { {  4, 1 },
106                                { 16, 0 },
107                                { 28, 1 },
108                                { 32, 0 },
109                                {  0, 0 } };
110
111 const rf_bit_t sync_bit[] = { {   4, 1 },
112                               { 128, 0 },
113                               {   0, 0 } };
114                       
115 // whole word duration: ~46.80 ms
116 // pause duration: ~14.9ms - 1.86ms = ~13ms
117 // bit duration: 1.860 ms
118
119 // in theory better but non-working timings @ alpha=0.0775ms
120 //const rf_bit_t pwm_0_bit[] = {  {6, 1}, {18, 0}, {  0, 0 } };     // 1.86ms gesamt: { 0.46ms HIGH , 1.4ms LOW }
121 //const rf_bit_t pwm_1_bit[] = {  {18, 1}, {6, 0}, {  0, 0 } };  //// 1.86ms gesamt: { 1.4ms HIGH , 0.46ms LOW }
122 //const rf_bit_t pwm_pause_bit[] = {  {167, 0}, {  0, 0 } };  //// 13ms pause 
123
124 // somewhat working timings @ alpha=0.0775ms
125 const rf_bit_t pwm_0_bit[] = {  {7, 1}, {17, 0}, {  0, 0 } };     // 1.86ms gesamt: { 0.46ms HIGH , 1.4ms LOW }
126 const rf_bit_t pwm_1_bit[] = {  {18, 1}, {6, 0}, {  0, 0 } };  //// 1.86ms gesamt: { 1.4ms HIGH , 0.46ms LOW }
127 const rf_bit_t pwm_pause_bit[] = {  {168, 0}, {  0, 0 } };  //// 13ms pause 
128
129 // // exact but non-working timings @ alpha=0.02ms
130 // const rf_bit_t pwm_0_bit[] = {  {23, 1}, {70, 0}, {  0, 0 } };     // 1.86ms gesamt: { 0.46ms HIGH , 1.4ms LOW }
131 // const rf_bit_t pwm_1_bit[] = {  {70, 1}, {23, 0}, {  0, 0 } };  //// 1.86ms gesamt: { 1.4ms HIGH , 0.46ms LOW }
132 // const rf_bit_t pwm_pause_bit[] = {  {215, 0}, {  0, 0 } };  //// 1/3* 12.9ms pause 
133
134 //default:
135 // almost as good somwhat working approximate timings @ alpha=0.08ms
136 //const rf_bit_t pwm_0_bit[] = {  {6, 1}, {17, 0}, {  0, 0 } };     // 1.86ms gesamt: { 0.46ms HIGH , 1.4ms LOW }
137 //const rf_bit_t pwm_1_bit[] = {  {18, 1}, {6, 0}, {  0, 0 } };  //// 1.86ms gesamt: { 1.4ms HIGH , 0.46ms LOW }
138 //const rf_bit_t pwm_pause_bit[] = {  {162, 0}, {  0, 0 } };  //// 13ms pause 
139
140 typedef enum { ZERO = 0, ONE , FLOAT , SYNC , PWM0, PWM1, PWM_PAUSE, WORD_END } adbit_t;
141 typedef byte ad_bit_t;
142 #define WORD_LEN 13
143 #define MAX_WORD_LEN 27
144 typedef ad_bit_t word_t[MAX_WORD_LEN];
145
146 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit, pwm_0_bit, pwm_1_bit, pwm_pause_bit };
147
148 byte alpha_cnt = 0;
149 byte bit_cnt = 0;
150 byte current_word_len = WORD_LEN;
151 byte chunk_cnt = 0;
152 byte word_cnt = 0;
153 const ad_bit_t* current_word;
154 byte volatile frame_finished = 1;
155
156 #define FRAME_LEN 10
157
158 #define A1_ON  0
159 #define A1_OFF 1
160 #define A2_ON  2
161 #define A2_OFF 3
162
163 #define B1_ON  4
164 #define B1_OFF 5
165 #define B2_ON  6
166 #define B2_OFF 7
167
168 #define C1_ON  8
169 #define C1_OFF 9
170 #define C2_ON  10
171 #define C2_OFF 11
172
173 #define D1_ON  12
174 #define D1_OFF 13
175 #define D2_ON  14
176 #define D2_OFF 15
177
178 #define BLACK_A1_ON 16
179 #define BLACK_A1_OFF 17
180 #define BLACK_A2_ON 18
181 #define BLACK_A2_OFF 19
182 #define BLACK_A3_ON 20
183 #define BLACK_A3_OFF 21
184
185 #define BLACK_B1_ON 22
186 #define BLACK_B1_OFF 23
187 #define BLACK_B2_ON 24
188 #define BLACK_B2_OFF 25
189 #define BLACK_B3_ON 26
190 #define BLACK_B3_OFF 27
191
192
193 const word_t words[]  = { 
194 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END}, // A1_ON
195 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END}, // A1_OFF
196 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // A2_ON
197 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END }, // A2_OFF
198
199 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // B1_ON
200 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END }, // B1_OFF
201 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // B2_ON
202 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END }, // B2_OFF
203
204 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // C1_ON
205 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END }, // C1_OFF
206 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // C2_ON
207 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END }, // C2_OFF
208
209 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // D1_ON
210 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END }, // D1_OFF
211 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC, WORD_END, WORD_END,WORD_END }, // D2_ON
212 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC, WORD_END, WORD_END,WORD_END },  // D2_OFF
213
214 {PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0,PWM0,PWM0, PWM_PAUSE, WORD_END}, // BLACK_A1_ON
215 {PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0, PWM_PAUSE, WORD_END}, // BLACK_A1_OFF
216 {PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0,PWM0,PWM0, PWM_PAUSE, WORD_END}, // BLACK_A2_ON
217 {PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0, PWM_PAUSE, WORD_END}, // BLACK_A2_OFF
218 {PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0,PWM0,PWM0, PWM_PAUSE, WORD_END}, // BLACK_A3_ON
219 {PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0, PWM_PAUSE, WORD_END}, // BLACK_A3_OFF
220
221 {PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0,PWM0,PWM0, PWM_PAUSE, WORD_END}, // BLACK_B1_ON  
222 {PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0, PWM_PAUSE, WORD_END}, // BLACK_B1_OFF  
223 {PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0,PWM0,PWM0, PWM_PAUSE, WORD_END}, // BLACK_B2_ON  
224 {PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0, PWM_PAUSE, WORD_END}, // BLACK_B2_OFF  
225 {PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0,PWM0,PWM0, PWM_PAUSE, WORD_END}, // BLACK_B3_ON
226 {PWM0,PWM1,PWM1,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM0,PWM1,PWM1,PWM1,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM0,PWM1,PWM1,PWM0, PWM_PAUSE, WORD_END} // BLACK_B3_OFF
227 };
228
229
230 //********************************************************************//
231
232 void start_timer()
233 {
234   // timer 1: 2 ms
235   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
236   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
237 //  OCR1A = 39;        // (1+39)*8 = 320 -> 0.02ms @ 16 MHz -> 1*alpha
238 //default: alpha=0.08  
239 //  OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
240 OCR1A = 154;        // (1+154)*8 = 1240 -> 0.0775ms @ 16 MHz -> 1*alpha
241 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
242   TCNT1 = 0;          // reseting timer
243   TIMSK1 = 1<<OCIE1A; // enable Interrupt
244 }
245
246 void stop_timer() // stop the timer
247 {
248   // timer1
249   TCCR1B = 0; // no clock source
250   TIMSK1 = 0; // disable timer interrupt
251 }
252
253 void init_word(const word_t w)
254 {
255   current_word = w;
256   alpha_cnt = 0;
257   chunk_cnt = 0;
258   bit_cnt = 0;
259
260   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
261     digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
262   else
263     digitalWrite(RF_DATA_OUT_PIN, HIGH);
264
265   start_timer();
266 }
267
268 ISR(TIMER1_COMPA_vect)
269 {
270   alpha_cnt++;
271   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
272     return;
273
274   chunk_cnt++;
275   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
276     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
277       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
278     else
279       digitalWrite(RF_DATA_OUT_PIN, HIGH);
280     return;
281   }
282   
283   bit_cnt++;
284   if(current_word[bit_cnt] != WORD_END && bit_cnt < MAX_WORD_LEN) {
285     alpha_cnt = 0;
286     chunk_cnt = 0;
287     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
288       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
289     else
290       digitalWrite(RF_DATA_OUT_PIN, HIGH);
291     return;
292   }
293   stop_timer();
294   digitalWrite(RF_DATA_OUT_PIN, HIGH);
295
296   word_cnt++;
297   if(word_cnt < FRAME_LEN)
298     init_word(current_word);
299   else
300     frame_finished = 2;
301 }
302
303 //***********//
304
305
306 void send_frame(const word_t w)
307 {
308   if (frame_finished != 1)
309     for(;;) //wait until sending of previous frame finishes
310       if (frame_finished)
311       {
312         delay(150);
313         break;
314       }
315   word_cnt = 0;
316   frame_finished = 0;
317   init_word(w);
318 }
319
320 void check_frame_done()
321 {
322   if (frame_finished==2)
323   {
324     Serial.println("Ok");
325     frame_finished=1;
326     delay(120);
327   }
328 }
329
330 //********************************************************************//
331
332 void printTemperature(DeviceAddress deviceAddress)
333 {
334   dallas_sensors.requestTemperatures();
335   float tempC = dallas_sensors.getTempC(deviceAddress);
336   //Serial.print("Temp C: ");
337   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
338   //Serial.print(" Temp F: ");
339   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
340 }
341
342 //********************************************************************//
343
344 unsigned int light_level_mean_ = 0;
345 unsigned int light_sample_time_ = 0;
346
347 void updateLightLevel(unsigned int pin)
348 {
349   light_sample_time_++;
350   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
351     return;
352   light_sample_time_ = 0;
353   
354   unsigned int value = analogRead(pin);
355   if (value == light_level_mean_)
356     return;
357   
358   unsigned int diff = abs(value - light_level_mean_);
359   if (diff > 100)
360     light_level_mean_ = value;
361   else
362       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
363 }
364
365 void printLightLevel()
366 {
367   //Serial.print("Photo: ");
368   Serial.println(light_level_mean_);
369 }
370
371 //********************************************************************//
372
373 unsigned long wm_start_[3]={0,0,0};
374 bool wait_millis(unsigned long *start_time, unsigned long ms)
375 {
376   if (ms == 0)
377     return false;
378   else if (*start_time > 0)
379   {
380     if (millis() < *start_time || millis() > (*start_time) + ms)
381     {
382       *start_time = 0;
383       return false;
384     }
385     else
386       return true;
387   }
388   else
389   {
390     *start_time=millis();
391     return true;
392   }
393 }
394 #define NUM_LEDS 2
395 char flash_led_pins_[NUM_LEDS]={BLUELED_PWM_PIN,PANICLED_PWM_PIN};
396 unsigned int flash_led_time_[3]={0,0,0};
397 unsigned int flash_led_brightness_[3]={255,255,255};
398 unsigned int flash_led_delay_[3]={8,8,8};
399 unsigned int flash_led_initial_delay_[3]={0,0,0};
400 void calculate_led_level()
401 {
402   for (int ledid = 0; ledid < NUM_LEDS; ledid++)
403   {
404     if (flash_led_time_[ledid] == 0)
405       continue;
406     if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
407       continue;
408     flash_led_initial_delay_[ledid]=0;
409     if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
410       continue;
411     flash_led_time_[ledid]--;
412     int c = abs(sin(float(flash_led_time_[ledid]) / 100.0)) * flash_led_brightness_[ledid];
413     //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
414     analogWrite(flash_led_pins_[ledid], 255-c);
415   }
416 }
417
418 // id: id of LED to flash (0,1)
419 // times: # of times the LED should flash
420 // brightness_divisor: 1: full brightness, 2: half brightness, ...
421 // delay_divisor: 1: slow... 8: fastest
422 // phase_divisor: 0.. same phase; 2.. pi/2 phase, 4.. pi phase, 6.. 3pi/2 phase
423 void flash_led(unsigned int id, unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int phase_divisor)
424 {
425   if (id >= NUM_LEDS)
426     return;
427   unsigned int new_flash_led_brightness = 255;
428   unsigned int new_flash_led_delay = 8;
429   if (times == 0)
430   {
431     analogWrite(flash_led_pins_[id],255); //off
432     return;
433   }
434   if (brightness_divisor > 1) //guard against div by zero
435     new_flash_led_brightness /= brightness_divisor;
436   if (delay_divisor > 1)  //guard against div by zero
437     new_flash_led_delay /= delay_divisor;
438   if (flash_led_time_[id] == 0 || new_flash_led_brightness > flash_led_brightness_[id])
439     flash_led_brightness_[id]=new_flash_led_brightness;
440   if (flash_led_time_[id] == 0 || new_flash_led_delay < flash_led_delay_[id])
441     flash_led_delay_[id]=new_flash_led_delay;
442   flash_led_time_[id] += 314*times;
443   flash_led_initial_delay_[id] = flash_led_delay_[id]*314*phase_divisor/8;
444 }
445
446 //********************************************************************//
447
448 int save_tcnt2=0;
449 int save_tccr2a=0;
450 int save_tccr2b=0;
451 void reset_timer2()
452 {
453   TCNT2 = save_tcnt2;
454   TCCR2A = save_tccr2a;  // normal mode
455   TCCR2B = save_tccr2b;
456   //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
457   //TCCR2A = 0;  // normal mode
458   //TCCR2B = 0;
459 }
460
461 void send_yamaha_ir_signal(char codebyte)
462 {
463   unsigned long int code = codebyte & 0xFF;
464   code <<= 8;
465   code |= (0xff ^ codebyte) & 0xFF;
466   code |= YAMAHA_CODE_BASE;
467   
468   //irsend changes PWM Timer Frequency among other things
469   //.. doesn't go well with PWM output using the same timer
470   //.. thus we just set output to 255 so whatever frequency is used, led is off for the duration
471   //analogWrite(BLUELED_PWM_PIN,255); // switch led off
472
473   irsend.sendNEC(code,YAMAHA_CODE_BITS);
474
475   reset_timer2();
476   analogWrite(BLUELED_PWM_PIN,255); // switch off led again to be sure
477                                       //is actually not necessary, since we are not multitasking/using interrupts, but just to be sure in case this might change
478
479   Serial.println("Ok");
480 }
481
482 //********************************************************************//
483
484 void setup()
485 {
486   pinMode(RF_DATA_OUT_PIN, OUTPUT);
487   digitalWrite(RF_DATA_OUT_PIN, HIGH);
488   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
489   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors  
490   digitalWrite(IR_MOVEMENT_PIN2, LOW);  // turn off pullup resistors  
491   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
492   digitalWrite(PANIC_BUTTON_PIN, LOW);  // turn of pullup resistors 
493   analogWrite(PANICLED_PWM_PIN,255);
494   analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
495   pinMode(IRREMOTE_SEND_PIN, OUTPUT);
496   digitalWrite(IRREMOTE_SEND_PIN, HIGH);
497   
498   Serial.begin(9600);
499   
500   onewire.reset();
501   onewire.reset_search();
502   dallas_sensors.begin();
503   //in case we change temp sensor:
504   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
505     Serial.println("Error: Unable to find address for Device 0"); 
506   dallas_sensors.setResolution(onShieldTemp, 9);  
507
508   //save prev timer states:
509   save_tcnt2 = TCNT2;
510   save_tccr2a = TCCR2A;  // normal mode
511   save_tccr2b = TCCR2B;
512 }
513
514 unsigned int ir_time=IR_SAMPLE_DURATION;
515 unsigned int ir_count=0;
516 unsigned int ir_count2=0;
517 boolean pb_last_state=0;
518 boolean pb_state=0;
519 boolean pb_postth_state=0;
520 unsigned int pb_time=0;
521
522 void sensorEchoCommand(char command)
523 {
524   Serial.print("Sensor ");
525   Serial.print(command);
526   Serial.print(": ");
527 }
528
529 void loop()
530 {
531   ir_time--;
532   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
533   ir_count2 += (digitalRead(IR_MOVEMENT_PIN2) == HIGH);
534
535   if (pb_time < PB_TRESHOLD)
536     pb_time++;
537   pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
538   
539   if (ir_time == 0)
540   {
541     if (ir_count >= IR_TRESHOLD || ir_count2 >= IR_TRESHOLD)
542     {
543       flash_led(0, 1, 8, 1, 0 );
544       Serial.println("movement");
545     }
546     ir_time=IR_SAMPLE_DURATION;
547     ir_count=0;
548     ir_count2=0;
549   }
550   
551   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
552   {
553     if (pb_state && ! pb_postth_state)
554     {   
555       pb_postth_state=1;
556       Serial.println("PanicButton");
557       flash_led(0, 28, 1, 4, 0 );
558       flash_led(1, 28, 1, 4, 4 );
559     }
560     else if (!pb_state)
561       pb_postth_state=0;
562   }
563   else if (pb_state != pb_last_state)
564   {
565     pb_time=0;
566     pb_last_state=pb_state;
567   }
568   
569   updateLightLevel(PHOTO_ANALOGPIN);
570   calculate_led_level();
571   check_frame_done();
572   
573   if(Serial.available()) {
574     char command = Serial.read();
575     
576     if(command == 'A')
577       send_frame(words[A1_ON]);
578     else if(command == 'a')
579       send_frame(words[A1_OFF]);
580     else if(command == 'B')
581       send_frame(words[A2_ON]);
582     else if(command == 'b')
583       send_frame(words[A2_OFF]);
584
585     else if(command == 'C')
586       send_frame(words[B1_ON]);
587     else if(command == 'c')
588       send_frame(words[B1_OFF]);
589     else if(command == 'D')
590       send_frame(words[B2_ON]);
591     else if(command == 'd')
592       send_frame(words[B2_OFF]);
593
594     else if(command == 'E')
595       send_frame(words[C1_ON]);
596     else if(command == 'e')
597       send_frame(words[C1_OFF]);
598     else if(command == 'F')
599       send_frame(words[C2_ON]);
600     else if(command == 'f')
601       send_frame(words[C2_OFF]);
602
603     else if(command == 'G')
604       send_frame(words[D1_ON]);
605     else if(command == 'g')
606       send_frame(words[D1_OFF]);
607     else if(command == 'H')
608       send_frame(words[D2_ON]);
609     else if(command == 'h')
610       send_frame(words[D2_OFF]);
611     else if(command == 'I')
612       send_frame(words[BLACK_A1_ON]);
613     else if(command == 'i')
614       send_frame(words[BLACK_A1_OFF]);
615     else if(command == 'J')
616       send_frame(words[BLACK_A2_ON]);
617     else if(command == 'j')
618       send_frame(words[BLACK_A2_OFF]);
619     else if(command == 'K')
620       send_frame(words[BLACK_A3_ON]);
621     else if(command == 'k')
622       send_frame(words[BLACK_A3_OFF]);
623     else if(command == 'L')
624       send_frame(words[BLACK_B1_ON]);
625     else if(command == 'l')
626       send_frame(words[BLACK_B1_OFF]);
627     else if(command == 'M')
628       send_frame(words[BLACK_B2_ON]);
629     else if(command == 'm')
630       send_frame(words[BLACK_B2_OFF]);
631     else if(command == 'N')
632       send_frame(words[BLACK_B3_ON]);
633     else if(command == 'n')
634       send_frame(words[BLACK_B3_OFF]);
635     else if(command == 'T')
636     {
637       sensorEchoCommand(command);
638       printTemperature(onShieldTemp);
639     }
640     else if(command == 'P')
641     {
642       sensorEchoCommand(command);
643       printLightLevel();
644     }
645     else if (command == '^')
646     {
647       //flash_led(1, 1, 2, 1, 0);
648       flash_led(1, 1, 1, 1, 0);
649       Serial.println("Ok");
650     }
651     else if (command == '&')
652     {
653       flash_led(0, 1, 2, 1, 0);
654       Serial.println("Ok");
655     }
656     else if (command == '1')
657       send_yamaha_ir_signal(YAMAHA_CD);
658     else if (command == '2')
659       send_yamaha_ir_signal(YAMAHA_TUNER);
660     else if (command == '3')
661       send_yamaha_ir_signal(YAMAHA_TAPE);
662     else if (command == '4')
663       send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
664     else if (command == '5')
665       send_yamaha_ir_signal(YAMAHA_SAT_SPDIFF);
666     else if (command == '6')
667       send_yamaha_ir_signal(YAMAHA_VCR);
668 //    else if (command == '7')
669 //      send_yamaha_ir_signal();
670     else if (command == '8')
671       send_yamaha_ir_signal(YAMAHA_AUX);
672     else if (command == '9')
673       send_yamaha_ir_signal(YAMAHA_EXT51DEC);
674     else if (command == '0')
675       send_yamaha_ir_signal(YAMAHA_TEST);
676     else if (command == '/')
677       send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
678     else if (command == '\\')
679       send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
680     else if (command == '-')
681       send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
682     else if (command == '+')
683       send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
684     else if (command == ':')
685       send_yamaha_ir_signal(YAMAHA_POWER_OFF);
686     else if (command == '.')
687       send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
688     else if (command == ';')
689       send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
690     else if (command == ',')
691       send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
692     else if (command == '_')
693       send_yamaha_ir_signal(YAMAHA_MUTE);
694     else if (command == '#')
695       send_yamaha_ir_signal(YAMAHA_MENU);
696     else if (command == '"')
697       send_yamaha_ir_signal(YAMAHA_PLUS);
698     else if (command == '!')
699       send_yamaha_ir_signal(YAMAHA_MINUS);
700     else if (command == '=')
701       send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
702     else if (command == '$')
703       send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
704     else if (command == '%')
705       send_yamaha_ir_signal(YAMAHA_PRG_UP);
706     else if (command == '(')
707       send_yamaha_ir_signal(YAMAHA_SLEEP);
708     else if (command == ')')
709       send_yamaha_ir_signal(YAMAHA_P5);
710     else
711       Serial.println("Error: unknown command");
712   }
713 }