some experimental tweaks, still does not work good. needs further measurements. old...
[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 {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_A1_ON
215 {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_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
233 void start_timer()
234 {
235   // timer 1: 2 ms
236   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
237   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
238 //  OCR1A = 39;        // (1+39)*8 = 320 -> 0.02ms @ 16 MHz -> 1*alpha
239 //default: alpha=0.08  
240 //  OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
241 OCR1A = 154;        // (1+154)*8 = 1240 -> 0.0775ms @ 16 MHz -> 1*alpha
242 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
243   TCNT1 = 0;          // reseting timer
244   TIMSK1 = 1<<OCIE1A; // enable Interrupt
245 }
246
247 void stop_timer() // stop the timer
248 {
249   // timer1
250   TCCR1B = 0; // no clock source
251   TIMSK1 = 0; // disable timer interrupt
252 }
253
254 void init_word(const word_t w)
255 {
256   current_word = w;
257   alpha_cnt = 0;
258   chunk_cnt = 0;
259   bit_cnt = 0;
260
261   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
262     digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
263   else
264     digitalWrite(RF_DATA_OUT_PIN, HIGH);
265
266   start_timer();
267 }
268
269 ISR(TIMER1_COMPA_vect)
270 {
271   alpha_cnt++;
272   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
273     return;
274
275   chunk_cnt++;
276   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
277     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
278       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
279     else
280       digitalWrite(RF_DATA_OUT_PIN, HIGH);
281     return;
282   }
283   
284   bit_cnt++;
285   if(current_word[bit_cnt] != WORD_END && bit_cnt < MAX_WORD_LEN) {
286     alpha_cnt = 0;
287     chunk_cnt = 0;
288     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
289       digitalWrite(RF_DATA_OUT_PIN, LOW); //neue 12V MosFET Verstärkung invertiert Logik !
290     else
291       digitalWrite(RF_DATA_OUT_PIN, HIGH);
292     return;
293   }
294   stop_timer();
295   digitalWrite(RF_DATA_OUT_PIN, HIGH);
296
297   word_cnt++;
298   if(word_cnt < FRAME_LEN)
299     init_word(current_word);
300   else
301     frame_finished = 2;
302 }
303
304 //***********//
305
306
307 void send_frame(const word_t w)
308 {
309   if (frame_finished != 1)
310     for(;;) //wait until sending of previous frame finishes
311       if (frame_finished)
312       {
313         delay(150);
314         break;
315       }
316   word_cnt = 0;
317   frame_finished = 0;
318   init_word(w);
319 }
320
321 void check_frame_done()
322 {
323   if (frame_finished==2)
324   {
325     Serial.println("Ok");
326     frame_finished=1;
327     delay(120);
328   }
329 }
330
331 //********************************************************************//
332
333 void printTemperature(DeviceAddress deviceAddress)
334 {
335   dallas_sensors.requestTemperatures();
336   float tempC = dallas_sensors.getTempC(deviceAddress);
337   //Serial.print("Temp C: ");
338   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
339   //Serial.print(" Temp F: ");
340   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
341 }
342
343 //********************************************************************//
344
345 unsigned int light_level_mean_ = 0;
346 unsigned int light_sample_time_ = 0;
347
348 void updateLightLevel(unsigned int pin)
349 {
350   light_sample_time_++;
351   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
352     return;
353   light_sample_time_ = 0;
354   
355   unsigned int value = analogRead(pin);
356   if (value == light_level_mean_)
357     return;
358   
359   unsigned int diff = abs(value - light_level_mean_);
360   if (diff > 100)
361     light_level_mean_ = value;
362   else
363       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.90 + ((float)value)*0.10 );
364 }
365
366 void printLightLevel()
367 {
368   //Serial.print("Photo: ");
369   Serial.println(light_level_mean_);
370 }
371
372 //********************************************************************//
373
374 unsigned long wm_start_[3]={0,0,0};
375 bool wait_millis(unsigned long *start_time, unsigned long ms)
376 {
377   if (ms == 0)
378     return false;
379   else if (*start_time > 0)
380   {
381     if (millis() < *start_time || millis() > (*start_time) + ms)
382     {
383       *start_time = 0;
384       return false;
385     }
386     else
387       return true;
388   }
389   else
390   {
391     *start_time=millis();
392     return true;
393   }
394 }
395 #define NUM_LEDS 2
396 char flash_led_pins_[NUM_LEDS]={BLUELED_PWM_PIN,PANICLED_PWM_PIN};
397 unsigned int flash_led_time_[3]={0,0,0};
398 unsigned int flash_led_brightness_[3]={255,255,255};
399 unsigned int flash_led_delay_[3]={8,8,8};
400 unsigned int flash_led_initial_delay_[3]={0,0,0};
401 void calculate_led_level()
402 {
403   for (int ledid = 0; ledid < NUM_LEDS; ledid++)
404   {
405     if (flash_led_time_[ledid] == 0)
406       continue;
407     if (wait_millis(wm_start_ + ledid, flash_led_initial_delay_[ledid]))
408       continue;
409     flash_led_initial_delay_[ledid]=0;
410     if (wait_millis(wm_start_ + ledid, flash_led_delay_[ledid]))
411       continue;
412     flash_led_time_[ledid]--;
413     int c = abs(sin(float(flash_led_time_[ledid]) / 100.0)) * flash_led_brightness_[ledid];
414     //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
415     analogWrite(flash_led_pins_[ledid], 255-c);
416   }
417 }
418
419 // id: id of LED to flash (0,1)
420 // times: # of times the LED should flash
421 // brightness_divisor: 1: full brightness, 2: half brightness, ...
422 // delay_divisor: 1: slow... 8: fastest
423 // phase_divisor: 0.. same phase; 2.. pi/2 phase, 4.. pi phase, 6.. 3pi/2 phase
424 void flash_led(unsigned int id, unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor, unsigned int phase_divisor)
425 {
426   if (id >= NUM_LEDS)
427     return;
428   unsigned int new_flash_led_brightness = 255;
429   unsigned int new_flash_led_delay = 8;
430   if (times == 0)
431   {
432     analogWrite(flash_led_pins_[id],255); //off
433     return;
434   }
435   if (brightness_divisor > 1) //guard against div by zero
436     new_flash_led_brightness /= brightness_divisor;
437   if (delay_divisor > 1)  //guard against div by zero
438     new_flash_led_delay /= delay_divisor;
439   if (flash_led_time_[id] == 0 || new_flash_led_brightness > flash_led_brightness_[id])
440     flash_led_brightness_[id]=new_flash_led_brightness;
441   if (flash_led_time_[id] == 0 || new_flash_led_delay < flash_led_delay_[id])
442     flash_led_delay_[id]=new_flash_led_delay;
443   flash_led_time_[id] += 314*times;
444   flash_led_initial_delay_[id] = flash_led_delay_[id]*314*phase_divisor/8;
445 }
446
447 //********************************************************************//
448
449 int save_tcnt2=0;
450 int save_tccr2a=0;
451 int save_tccr2b=0;
452 void reset_timer2()
453 {
454   TCNT2 = save_tcnt2;
455   TCCR2A = save_tccr2a;  // normal mode
456   TCCR2B = save_tccr2b;
457   //TCNT2 = 256 - (50*(16000000/8/1000000)) + 5;
458   //TCCR2A = 0;  // normal mode
459   //TCCR2B = 0;
460 }
461
462 void send_yamaha_ir_signal(char codebyte)
463 {
464   unsigned long int code = codebyte & 0xFF;
465   code <<= 8;
466   code |= (0xff ^ codebyte) & 0xFF;
467   code |= YAMAHA_CODE_BASE;
468   
469   //irsend changes PWM Timer Frequency among other things
470   //.. doesn't go well with PWM output using the same timer
471   //.. thus we just set output to 255 so whatever frequency is used, led is off for the duration
472   //analogWrite(BLUELED_PWM_PIN,255); // switch led off
473
474   irsend.sendNEC(code,YAMAHA_CODE_BITS);
475
476   reset_timer2();
477   analogWrite(BLUELED_PWM_PIN,255); // switch off led again to be sure
478                                       //is actually not necessary, since we are not multitasking/using interrupts, but just to be sure in case this might change
479
480   Serial.println("Ok");
481 }
482
483 //********************************************************************//
484
485 void setup()
486 {
487   pinMode(RF_DATA_OUT_PIN, OUTPUT);
488   digitalWrite(RF_DATA_OUT_PIN, HIGH);
489   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
490   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors  
491   digitalWrite(IR_MOVEMENT_PIN2, LOW);  // turn off pullup resistors  
492   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
493   digitalWrite(PANIC_BUTTON_PIN, LOW);  // turn of pullup resistors 
494   analogWrite(PANICLED_PWM_PIN,255);
495   analogWrite(BLUELED_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
496   pinMode(IRREMOTE_SEND_PIN, OUTPUT);
497   digitalWrite(IRREMOTE_SEND_PIN, HIGH);
498   
499   Serial.begin(9600);
500   
501   onewire.reset();
502   onewire.reset_search();
503   dallas_sensors.begin();
504   //in case we change temp sensor:
505   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
506     Serial.println("Error: Unable to find address for Device 0"); 
507   dallas_sensors.setResolution(onShieldTemp, 9);  
508
509   //save prev timer states:
510   save_tcnt2 = TCNT2;
511   save_tccr2a = TCCR2A;  // normal mode
512   save_tccr2b = TCCR2B;
513 }
514
515 unsigned int ir_time=IR_SAMPLE_DURATION;
516 unsigned int ir_count=0;
517 unsigned int ir_count2=0;
518 boolean pb_last_state=0;
519 boolean pb_state=0;
520 boolean pb_postth_state=0;
521 unsigned int pb_time=0;
522
523 void sensorEchoCommand(char command)
524 {
525   Serial.print("Sensor ");
526   Serial.print(command);
527   Serial.print(": ");
528 }
529
530 void loop()
531 {
532   ir_time--;
533   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
534   ir_count2 += (digitalRead(IR_MOVEMENT_PIN2) == HIGH);
535
536   if (pb_time < PB_TRESHOLD)
537     pb_time++;
538   pb_state=(digitalRead(PANIC_BUTTON_PIN) == HIGH);
539   
540   if (ir_time == 0)
541   {
542     if (ir_count >= IR_TRESHOLD || ir_count2 >= IR_TRESHOLD)
543     {
544       flash_led(0, 1, 8, 1, 0 );
545       Serial.println("movement");
546     }
547     ir_time=IR_SAMPLE_DURATION;
548     ir_count=0;
549     ir_count2=0;
550   }
551   
552   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
553   {
554     if (pb_state && ! pb_postth_state)
555     {   
556       pb_postth_state=1;
557       Serial.println("PanicButton");
558       flash_led(0, 28, 1, 4, 0 );
559       flash_led(1, 28, 1, 4, 4 );
560     }
561     else if (!pb_state)
562       pb_postth_state=0;
563   }
564   else if (pb_state != pb_last_state)
565   {
566     pb_time=0;
567     pb_last_state=pb_state;
568   }
569   
570   updateLightLevel(PHOTO_ANALOGPIN);
571   calculate_led_level();
572   check_frame_done();
573   
574   if(Serial.available()) {
575     char command = Serial.read();
576     
577     if(command == 'A')
578       send_frame(words[A1_ON]);
579     else if(command == 'a')
580       send_frame(words[A1_OFF]);
581     else if(command == 'B')
582       send_frame(words[A2_ON]);
583     else if(command == 'b')
584       send_frame(words[A2_OFF]);
585
586     else if(command == 'C')
587       send_frame(words[B1_ON]);
588     else if(command == 'c')
589       send_frame(words[B1_OFF]);
590     else if(command == 'D')
591       send_frame(words[B2_ON]);
592     else if(command == 'd')
593       send_frame(words[B2_OFF]);
594
595     else if(command == 'E')
596       send_frame(words[C1_ON]);
597     else if(command == 'e')
598       send_frame(words[C1_OFF]);
599     else if(command == 'F')
600       send_frame(words[C2_ON]);
601     else if(command == 'f')
602       send_frame(words[C2_OFF]);
603
604     else if(command == 'G')
605       send_frame(words[D1_ON]);
606     else if(command == 'g')
607       send_frame(words[D1_OFF]);
608     else if(command == 'H')
609       send_frame(words[D2_ON]);
610     else if(command == 'h')
611       send_frame(words[D2_OFF]);
612     else if(command == 'I')
613       send_frame(words[BLACK_A1_ON]);
614     else if(command == 'i')
615       send_frame(words[BLACK_A1_OFF]);
616     else if(command == 'J')
617       send_frame(words[BLACK_A2_ON]);
618     else if(command == 'j')
619       send_frame(words[BLACK_A2_OFF]);
620     else if(command == 'K')
621       send_frame(words[BLACK_A3_ON]);
622     else if(command == 'k')
623       send_frame(words[BLACK_A3_OFF]);
624     else if(command == 'L')
625       send_frame(words[BLACK_B1_ON]);
626     else if(command == 'l')
627       send_frame(words[BLACK_B1_OFF]);
628     else if(command == 'M')
629       send_frame(words[BLACK_B2_ON]);
630     else if(command == 'm')
631       send_frame(words[BLACK_B2_OFF]);
632     else if(command == 'N')
633       send_frame(words[BLACK_B3_ON]);
634     else if(command == 'n')
635       send_frame(words[BLACK_B3_OFF]);
636     else if(command == 'T')
637     {
638       sensorEchoCommand(command);
639       printTemperature(onShieldTemp);
640     }
641     else if(command == 'P')
642     {
643       sensorEchoCommand(command);
644       printLightLevel();
645     }
646     else if (command == '^')
647     {
648       //flash_led(1, 1, 2, 1, 0);
649       flash_led(1, 1, 1, 1, 0);
650       Serial.println("Ok");
651     }
652     else if (command == '&')
653     {
654       flash_led(0, 1, 2, 1, 0);
655       Serial.println("Ok");
656     }
657     else if (command == '1')
658       send_yamaha_ir_signal(YAMAHA_CD);
659     else if (command == '2')
660       send_yamaha_ir_signal(YAMAHA_TUNER);
661     else if (command == '3')
662       send_yamaha_ir_signal(YAMAHA_TAPE);
663     else if (command == '4')
664       send_yamaha_ir_signal(YAMAHA_DVD_SPDIF);
665     else if (command == '5')
666       send_yamaha_ir_signal(YAMAHA_SAT_SPDIFF);
667     else if (command == '6')
668       send_yamaha_ir_signal(YAMAHA_VCR);
669 //    else if (command == '7')
670 //      send_yamaha_ir_signal();
671     else if (command == '8')
672       send_yamaha_ir_signal(YAMAHA_AUX);
673     else if (command == '9')
674       send_yamaha_ir_signal(YAMAHA_EXT51DEC);
675     else if (command == '0')
676       send_yamaha_ir_signal(YAMAHA_TEST);
677     else if (command == '/')
678       send_yamaha_ir_signal(YAMAHA_TUNER_ABCDE);
679     else if (command == '\\')
680       send_yamaha_ir_signal(YAMAHA_EFFECT_TOGGLE);
681     else if (command == '-')
682       send_yamaha_ir_signal(YAMAHA_TUNER_MINUS);
683     else if (command == '+')
684       send_yamaha_ir_signal(YAMAHA_TUNER_PLUS);
685     else if (command == ':')
686       send_yamaha_ir_signal(YAMAHA_POWER_OFF);
687     else if (command == '.')
688       send_yamaha_ir_signal(YAMAHA_POWER_TOGGLE);
689     else if (command == ';')
690       send_yamaha_ir_signal(YAMAHA_VOLUME_UP);
691     else if (command == ',')
692       send_yamaha_ir_signal(YAMAHA_VOLUME_DOWN);
693     else if (command == '_')
694       send_yamaha_ir_signal(YAMAHA_MUTE);
695     else if (command == '#')
696       send_yamaha_ir_signal(YAMAHA_MENU);
697     else if (command == '"')
698       send_yamaha_ir_signal(YAMAHA_PLUS);
699     else if (command == '!')
700       send_yamaha_ir_signal(YAMAHA_MINUS);
701     else if (command == '=')
702       send_yamaha_ir_signal(YAMAHA_TIME_LEVEL);
703     else if (command == '$')
704       send_yamaha_ir_signal(YAMAHA_PRG_DOWN);
705     else if (command == '%')
706       send_yamaha_ir_signal(YAMAHA_PRG_UP);
707     else if (command == '(')
708       send_yamaha_ir_signal(YAMAHA_SLEEP);
709     else if (command == ')')
710       send_yamaha_ir_signal(YAMAHA_P5);
711     else
712       Serial.println("Error: unknown command");
713   }
714 }