added Error string for unknown command
[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 //movement is reported if during IR_SAMPLE_DURATION at least IR_TRESHOLD ir signals are detectd
14 #define IR_SAMPLE_DURATION 20000
15 #define IR_TRESHOLD 13000
16 //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)
17 #define PB_TRESHOLD 1000
18
19 OneWire  onewire(ONE_WIRE_PIN);
20 DallasTemperature dallas_sensors(&onewire);
21 DeviceAddress onShieldTemp = { 0x10, 0xE7, 0x77, 0xD3, 0x01, 0x08, 0x00, 0x3F };
22
23 typedef struct {
24   byte offset;
25   byte state;
26 } rf_bit_t;
27
28 // offset is number of alphas (0.08ms)
29
30 const rf_bit_t zero_bit[] = { {  4, 1 },
31                               { 16, 0 },
32                               { 20, 1 },
33                               { 32, 0 },
34                               {  0, 0 } };
35
36 const rf_bit_t one_bit[] = { { 12, 1 },
37                              { 16, 0 },
38                              { 28, 1 },
39                              { 32, 0 },
40                              {  0, 0 } };
41
42 const rf_bit_t float_bit[] = { {  4, 1 },
43                                { 16, 0 },
44                                { 28, 1 },
45                                { 32, 0 },
46                                {  0, 0 } };
47
48 const rf_bit_t sync_bit[] = { {   4, 1 },
49                               { 128, 0 },
50                               {   0, 0 } };
51
52 typedef enum { ZERO = 0, ONE , FLOAT , SYNC } adbit_t;
53 typedef byte ad_bit_t;
54 #define WORD_LEN 13
55 typedef ad_bit_t word_t[WORD_LEN];
56
57 const rf_bit_t* bit_defs[] = { zero_bit, one_bit, float_bit, sync_bit };
58
59 byte alpha_cnt = 0;
60 byte bit_cnt = 0;
61 byte chunk_cnt = 0;
62 byte word_cnt = 0;
63 const ad_bit_t* current_word;
64 byte volatile frame_finished = 1;
65
66 #define FRAME_LEN 8
67
68 #define A1_ON  0
69 #define A1_OFF 1
70 #define A2_ON  2
71 #define A2_OFF 3
72
73 #define B1_ON  4
74 #define B1_OFF 5
75 #define B2_ON  6
76 #define B2_OFF 7
77
78 #define C1_ON  8
79 #define C1_OFF 9
80 #define C2_ON  10
81 #define C2_OFF 11
82
83 #define D1_ON  12
84 #define D1_OFF 13
85 #define D2_ON  14
86 #define D2_OFF 15
87
88 const word_t words[]  = { 
89 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A1_ON
90 { ZERO,  ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A1_OFF
91 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // A2_ON
92 { ZERO,  ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // A2_OFF
93
94 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B1_ON
95 { FLOAT, ZERO,  FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B1_OFF
96 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // B2_ON
97 { FLOAT, ZERO,  FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // B2_OFF
98
99 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C1_ON
100 { ZERO,  FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C1_OFF
101 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // C2_ON
102 { ZERO,  FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // C2_OFF
103
104 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D1_ON
105 { FLOAT, FLOAT, FLOAT, FLOAT, ZERO,  ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }, // D1_OFF
106 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, FLOAT, SYNC }, // D2_ON
107 { FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO, FLOAT, FLOAT, ZERO,  SYNC }  // D2_OFF
108 };
109
110
111 //********************************************************************//
112
113 void start_timer()
114 {
115   // timer 1: 2 ms
116   TCCR1A = 0;                    // prescaler 1:8, WGM = 4 (CTC)
117   TCCR1B = 1<<WGM12 | 1<<CS11;   // 
118   OCR1A = 159;        // (1+159)*8 = 1280 -> 0.08ms @ 16 MHz -> 1*alpha
119 //  OCR1A = 207;        // (1+207)*8 = 1664 -> 0.104ms @ 16 MHz -> 1*alpha
120   TCNT1 = 0;          // reseting timer
121   TIMSK1 = 1<<OCIE1A; // enable Interrupt
122 }
123
124 void stop_timer() // stop the timer
125 {
126   // timer1
127   TCCR1B = 0; // no clock source
128   TIMSK1 = 0; // disable timer interrupt
129 }
130
131 void init_word(const word_t w)
132 {
133   current_word = w;
134   alpha_cnt = 0;
135   chunk_cnt = 0;
136   bit_cnt = 0;
137
138   if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
139     digitalWrite(RF_DATA_OUT_PIN, HIGH);
140   else
141     digitalWrite(RF_DATA_OUT_PIN, LOW);
142
143   start_timer();
144 }
145
146 ISR(TIMER1_COMPA_vect)
147 {
148   alpha_cnt++;
149   if(alpha_cnt < bit_defs[current_word[bit_cnt]][chunk_cnt].offset)
150     return;
151
152   chunk_cnt++;
153   if(bit_defs[current_word[bit_cnt]][chunk_cnt].offset != 0) {
154     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
155       digitalWrite(RF_DATA_OUT_PIN, HIGH);
156     else
157       digitalWrite(RF_DATA_OUT_PIN, LOW);
158     return;
159   }
160   
161   bit_cnt++;
162   if(bit_cnt < WORD_LEN) {
163     alpha_cnt = 0;
164     chunk_cnt = 0;
165     if(bit_defs[current_word[bit_cnt]][chunk_cnt].state)
166       digitalWrite(RF_DATA_OUT_PIN, HIGH);
167     else
168       digitalWrite(RF_DATA_OUT_PIN, LOW);
169     return;
170   }
171   stop_timer();
172   digitalWrite(RF_DATA_OUT_PIN, LOW);
173
174   word_cnt++;
175   if(word_cnt < FRAME_LEN)
176     init_word(current_word);
177
178   frame_finished = 1;
179 }
180
181 //***********//
182
183
184 void send_frame(const word_t w)
185 {
186   word_cnt = 0;
187   frame_finished = 0;
188   init_word(w);
189
190   for(;;)
191     if(frame_finished)
192       break;
193
194   Serial.println("Ok");
195 }
196
197 //********************************************************************//
198
199 void printTemperature(DeviceAddress deviceAddress)
200 {
201   dallas_sensors.requestTemperatures();
202   float tempC = dallas_sensors.getTempC(deviceAddress);
203   Serial.print("Temp C: ");
204   Serial.println(tempC);
205   //Serial.print(" Temp F: ");
206   //Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
207 }
208
209 //********************************************************************//
210
211 void setup()
212 {
213   pinMode(RF_DATA_OUT_PIN, OUTPUT);
214   digitalWrite(RF_DATA_OUT_PIN, LOW);
215   pinMode(IR_MOVEMENT_PIN, INPUT);      // set pin to input
216   digitalWrite(IR_MOVEMENT_PIN, LOW);  // turn off pullup resistors  
217   pinMode(PANIC_BUTTON_PIN, INPUT);      // set pin to input
218   digitalWrite(PANIC_BUTTON_PIN, HIGH);  // turn on pullup resistors 
219   
220   onewire.reset();
221   onewire.reset_search();
222   dallas_sensors.begin();
223   //in case we change temp sensor:
224   if (!dallas_sensors.getAddress(onShieldTemp, 0)) 
225     Serial.println("Unable to find address for Device 0"); 
226   dallas_sensors.setResolution(onShieldTemp, 9);
227   
228   Serial.begin(9600);
229 }
230
231 unsigned int ir_time=IR_SAMPLE_DURATION;
232 unsigned int ir_count=0;
233 boolean pb_last_state=0;
234 boolean pb_state=0;
235 boolean pb_postth_state=0;
236 unsigned int pb_time=0;
237
238 void loop()
239 {
240   ir_time--;
241   ir_count += (digitalRead(IR_MOVEMENT_PIN) == HIGH);
242
243   if (pb_time < PB_TRESHOLD)
244     pb_time++;
245   pb_state=(digitalRead(PANIC_BUTTON_PIN) == LOW);
246   
247   if (ir_time == 0)
248   {
249     if (ir_count >= IR_TRESHOLD)
250       Serial.println("movement");
251     ir_time=IR_SAMPLE_DURATION;
252     ir_count=0;
253   }
254   
255   if (pb_state == pb_last_state && pb_time >= PB_TRESHOLD)
256   {
257     if (pb_state && ! pb_postth_state)
258     {   
259       pb_postth_state=1;
260       Serial.println("PanicButton");
261     }
262     else if (!pb_state)
263       pb_postth_state=0;
264   }
265   else if (pb_state != pb_last_state)
266   {
267     pb_time=0;
268     pb_last_state=pb_state;
269   }
270     
271   if(Serial.available()) {
272     char command = Serial.read();
273     
274     if(command == 'q')
275       send_frame(words[A1_ON]);
276     else if(command == 'a')
277       send_frame(words[A1_OFF]);
278     else if(command == 'w')
279       send_frame(words[A2_ON]);
280     else if(command == 's')
281       send_frame(words[A2_OFF]);
282
283     else if(command == 'e')
284       send_frame(words[B1_ON]);
285     else if(command == 'd')
286       send_frame(words[B1_OFF]);
287     else if(command == 'r')
288       send_frame(words[B2_ON]);
289     else if(command == 'f')
290       send_frame(words[B2_OFF]);
291
292     else if(command == 't')
293       send_frame(words[C1_ON]);
294     else if(command == 'g')
295       send_frame(words[C1_OFF]);
296     else if(command == 'z')
297       send_frame(words[C2_ON]);
298     else if(command == 'h')
299       send_frame(words[C2_OFF]);
300
301     else if(command == 'u')
302       send_frame(words[D1_ON]);
303     else if(command == 'j')
304       send_frame(words[D1_OFF]);
305     else if(command == 'i')
306       send_frame(words[D2_ON]);
307     else if(command == 'k')
308       send_frame(words[D2_OFF]);
309     else if(command == 'T')
310       printTemperature(onShieldTemp);
311
312     else
313       Serial.println("Error: unknown command");
314   }
315 }