Elliminate superflous messages
[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
7 //********************************************************************//
8
9 #define RF_DATA_OUT_PIN 13
10 #define IR_MOVEMENT_PIN 9
11 #define ONE_WIRE_PIN 8
12 #define PANIC_BUTTON_PIN 7
13 #define BLUELED_PWM_PIN 6
14 #define BLUELED2_PWM_PIN 11
15 #define PHOTO_ANALOGPIN 0
16 //movement is reported if during IR_SAMPLE_DURATION at least IR_TRESHOLD ir signals are detectd
17 #define IR_SAMPLE_DURATION 15000
18 #define IR_TRESHOLD 10000
19 //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)
20 #define PB_TRESHOLD 1000
21 #define PHOTO_SAMPLE_INTERVAL 4000
22
23 OneWire  onewire(ONE_WIRE_PIN);
24 DallasTemperature dallas_sensors(&onewire);
25 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
26 #define TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT -4.0
27
28 typedef struct {
29   byte offset;
30   byte state;
31 } rf_bit_t;
32
33 // offset is number of alphas (0.08ms)
34
35 const rf_bit_t zero_bit[] = { {  4, 1 },
36                               { 16, 0 },
37                               { 20, 1 },
38                               { 32, 0 },
39                               {  0, 0 } };
40
41 const rf_bit_t one_bit[] = { { 12, 1 },
42                              { 16, 0 },
43                              { 28, 1 },
44                              { 32, 0 },
45                              {  0, 0 } };
46
47 const rf_bit_t float_bit[] = { {  4, 1 },
48                                { 16, 0 },
49                                { 28, 1 },
50                                { 32, 0 },
51                                {  0, 0 } };
52
53 const rf_bit_t sync_bit[] = { {   4, 1 },
54                               { 128, 0 },
55                               {   0, 0 } };
56
57 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
58 typedef byte ad_bit_t;
59 #define WORD_LEN 13
60 typedef ad_bit_t word_t[WORD_LEN];
61
62 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
63
64 byte alpha_cnt = 0;
65 byte bit_cnt = 0;
66 byte chunk_cnt = 0;
67 byte word_cnt = 0;
68 const ad_bit_t* current_word;
69 byte volatile frame_finished = 1;
70
71 #define FRAME_LEN 8
72
73 #define A1_ON  0
74 #define A1_OFF 1
75 #define A2_ON  2
76 #define A2_OFF 3
77
78 #define B1_ON  4
79 #define B1_OFF 5
80 #define B2_ON  6
81 #define B2_OFF 7
82
83 #define C1_ON  8
84 #define C1_OFF 9
85 #define C2_ON  10
86 #define C2_OFF 11
87
88 #define D1_ON  12
89 #define D1_OFF 13
90 #define D2_ON  14
91 #define D2_OFF 15
92
93 const word_t words[]  = { 
94 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
95 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A1_OFF
96 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
97 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A2_OFF
98
99 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
100 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B1_OFF
101 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
102 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B2_OFF
103
104 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
105 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C1_OFF
106 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
107 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C2_OFF
108
109 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
110 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // D1_OFF
111 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
112 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }  // D2_OFF
113 };
114
115
116 //********************************************************************//
117
118 void start_timer()
119 {
120   // timer 1: 2 ms
121   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
122   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
123   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
124 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
125   TCNT1 = 0;          // reseting timer
126   TIMSK1 = 1<<OCIE1A; // enable Interrupt
127 }
128
129 void stop_timer() // stop the timer
130 {
131   // timer1
132   TCCR1B = 0; // no clock source
133   TIMSK1 = 0; // disable timer interrupt
134 }
135
136 void init_word(const word_t w)
137 {
138   current_word = w;
139   alpha_cnt = 0;
140   chunk_cnt = 0;
141   bit_cnt = 0;
142
143   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
144     digitalWrite(RF_DATA_OUT_PIN, HIGH);
145   else
146     digitalWrite(RF_DATA_OUT_PIN, LOW);
147
148   start_timer();
149 }
150
151 ISR(TIMER1_COMPA_vect)
152 {
153   alpha_cnt++;
154   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
155     return;
156
157   chunk_cnt++;
158   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
159     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
160       digitalWrite(RF_DATA_OUT_PIN, HIGH);
161     else
162       digitalWrite(RF_DATA_OUT_PIN, LOW);
163     return;
164   }
165   
166   bit_cnt++;
167   if(bit_cnt < WORD_LEN) {
168     alpha_cnt = 0;
169     chunk_cnt = 0;
170     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
171       digitalWrite(RF_DATA_OUT_PIN, HIGH);
172     else
173       digitalWrite(RF_DATA_OUT_PIN, LOW);
174     return;
175   }
176   stop_timer();
177   digitalWrite(RF_DATA_OUT_PIN, LOW);
178
179   word_cnt++;
180   if(word_cnt < FRAME_LEN)
181     init_word(current_word);
182
183   frame_finished = 1;
184 }
185
186 //***********//
187
188
189 void send_frame(const word_t w)
190 {
191   word_cnt = 0;
192   frame_finished = 0;
193   init_word(w);
194
195   for(;;)
196     if(frame_finished)
197       break;
198
199   Serial.println("Ok");
200 }
201
202 //********************************************************************//
203
204 void printTemperature(DeviceAddress deviceAddress)
205 {
206   dallas_sensors.requestTemperatures();
207   float tempC = dallas_sensors.getTempC(deviceAddress);
208   //Serial.print("Temp C: ");
209   Serial.println(tempC TEMPC_OFFSET_ARDUINO_GENEREATED_HEAT);
210   //Serial.print(" Temp F: ");
211   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
212 }
213
214 //********************************************************************//
215
216 unsigned int light_level_mean_ = 0;
217 unsigned int light_sample_time_ = 0;
218
219 void updateLightLevel(unsigned int pin)
220 {
221   light_sample_time_++;
222   if (light_sample_time_ < PHOTO_SAMPLE_INTERVAL)
223     return;
224   light_sample_time_ = 0;
225   
226   unsigned int value = analogRead(pin);
227   if (value == light_level_mean_)
228     return;
229   
230   unsigned int diff = abs(value - light_level_mean_);
231   if (light_level_mean_ < 6 || diff > 250)
232     light_level_mean_ = value;
233   else
234       light_level_mean_=(unsigned int) ( ((float) light_level_mean_) * 0.98 + ((float)value)*0.02 );
235 }
236
237 void printLightLevel()
238 {
239   //Serial.print("Photo: ");
240   Serial.println(light_level_mean_);
241 }
242
243 //********************************************************************//
244
245 unsigned long wm_start_=0;
246 bool wait_millis(unsigned long ms)
247 {
248   if (wm_start_ > 0)
249   {
250     if (millis() < wm_start_ || millis() > wm_start_+ ms)
251     {
252       wm_start_=0;
253       return false;
254     }
255     else
256       return true;
257   }
258   else
259   {
260     wm_start_=millis();
261     return true;
262   }
263 }
264
265 unsigned int flash_led_time_=0;
266 unsigned int flash_led_brightness_=255;
267 unsigned int flash_led_delay_=8;
268 void calculate_led_level(unsigned int pwm_pin)
269 {
270   if (flash_led_time_ == 0)
271     return;
272   if (wait_millis(flash_led_delay_))
273     return;
274   flash_led_time_--;
275   int c = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
276   //int d = abs(sin(float(flash_led_time_) / 100.0)) * flash_led_brightness_;
277   analogWrite(BLUELED2_PWM_PIN, 255-c);
278   if (flash_led_brightness_ == 255)
279   {
280     if (flash_led_time_)
281       analogWrite(BLUELED_PWM_PIN, 255-c);
282     else
283       analogWrite(BLUELED_PWM_PIN, c);
284   }
285 }
286
287 void flash_led(unsigned int times, unsigned int brightness_divisor, unsigned int delay_divisor)
288 {
289   unsigned int new_flash_led_brightness = 255 / brightness_divisor;
290   unsigned int new_flash_led_delay = 8 / delay_divisor;
291   if (flash_led_time_ == 0 || new_flash_led_brightness > flash_led_brightness_)
292     flash_led_brightness_=new_flash_led_brightness;
293   if (flash_led_time_ == 0 || new_flash_led_delay < flash_led_delay_)
294     flash_led_delay_=new_flash_led_delay;
295   flash_led_time_ += 314*times;
296 }
297
298 //********************************************************************//
299
300 void setup()
301 {
302   pinMode(RF_DATA_OUT_PIN, OUTPUT);
303   digitalWrite(RF_DATA_OUT_PIN, LOW);
304   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
305   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors  
306   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
307   digitalWrite(PANIC_BUTTON_PIN, HIGH);  // turn on pullup resistors 
308   analogWrite(BLUELED_PWM_PIN,0);
309   analogWrite(BLUELED2_PWM_PIN,255); //pwm sink(-) instead of pwm + (better for mosfets)
310
311   Serial.begin(9600);
312   
313   onewire.reset();
314   onewire.reset_search();
315   dallas_sensors.begin();
316   //in case we change temp sensor:
317   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
318     Serial.println("Error: Unable to find address for Device 0"); 
319   dallas_sensors.setResolution(onShieldTemp, 9);  
320 }
321
322 unsigned int ir_time=IR_SAMPLE_DURATION;
323 unsigned int ir_count=0;
324 boolean pb_last_state=0;
325 boolean pb_state=0;
326 boolean pb_postth_state=0;
327 unsigned int pb_time=0;
328
329 void sensorEchoCommand(char command)
330 {
331   Serial.print("Sensor ");
332   Serial.print(command);
333   Serial.print(": ");
334 }
335
336 void loop()
337 {
338   ir_time--;
339   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
340
341   if (pb_time < PB_TRESHOLD)
342     pb_time++;
343   pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
344   
345   if (ir_time == 0)
346   {
347     if (ir_count >= IR_TRESHOLD)
348     {
349       flash_led(1,8,1);
350       Serial.println("movement");
351     }
352     ir_time=IR_SAMPLE_DURATION;
353     ir_count=0;
354   }
355   
356   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
357   {
358     if (pb_state && ! pb_postth_state)
359     {   
360       pb_postth_state=1;
361       Serial.println("PanicButton");
362       flash_led(7,1,2);
363     }
364     else if (!pb_state)
365       pb_postth_state=0;
366   }
367   else if (pb_state != pb_last_state)
368   {
369     pb_time=0;
370     pb_last_state=pb_state;
371   }
372   
373   updateLightLevel(PHOTO_ANALOGPIN);
374   calculate_led_level(BLUELED_PWM_PIN);
375   
376   if(Serial.available()) {
377     char command = Serial.read();
378     
379     if(command == 'A')
380       send_frame(words[A1_ON]);
381     else if(command == 'a')
382       send_frame(words[A1_OFF]);
383     else if(command == 'B')
384       send_frame(words[A2_ON]);
385     else if(command == 'b')
386       send_frame(words[A2_OFF]);
387
388     else if(command == 'C')
389       send_frame(words[B1_ON]);
390     else if(command == 'c')
391       send_frame(words[B1_OFF]);
392     else if(command == 'D')
393       send_frame(words[B2_ON]);
394     else if(command == 'd')
395       send_frame(words[B2_OFF]);
396
397     else if(command == 'E')
398       send_frame(words[C1_ON]);
399     else if(command == 'e')
400       send_frame(words[C1_OFF]);
401     else if(command == 'F')
402       send_frame(words[C2_ON]);
403     else if(command == 'f')
404       send_frame(words[C2_OFF]);
405
406     else if(command == 'G')
407       send_frame(words[D1_ON]);
408     else if(command == 'g')
409       send_frame(words[D1_OFF]);
410     else if(command == 'H')
411       send_frame(words[D2_ON]);
412     else if(command == 'h')
413       send_frame(words[D2_OFF]);
414     else if(command == 'T')
415     {
416       sensorEchoCommand(command);
417       printTemperature(onShieldTemp);
418     }
419     else if(command == 'P')
420     {
421       sensorEchoCommand(command);
422       printLightLevel();
423     }
424     else
425       Serial.println("Error: unknown command");
426   }
427 }