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