1 | void query()
|
2 | //Diese Funktion fragt das Touchscreen sowie die angeschlossenen Taster zyklisch ab.
|
3 |
|
4 | {
|
5 | int index = 0;
|
6 | static char enc_last = 0x01;
|
7 | static char bargraph = VENTIL;
|
8 | char buffer_info[] = {0,0};
|
9 | int buffer_size = 0;
|
10 | char strng[4];
|
11 | char i = 0;
|
12 | static int upper_limit;
|
13 | static int lower_limit;
|
14 | static char toggle_seq=0;
|
15 | static char toggle_valve=0;
|
16 | char buffer_array[63];
|
17 | long out;
|
18 |
|
19 |
|
20 | //********************** Abfrage Drehgeber ****************************
|
21 | i ^= 3;
|
22 |
|
23 | i -= enc_last;
|
24 |
|
25 | if ( !(PINB & (1<<PINB3)) )
|
26 | {
|
27 | //buffer_array initialisieren
|
28 | for (index = 0; index < 63; index ++)
|
29 | {
|
30 | buffer_array[index] = 0;
|
31 | }
|
32 |
|
33 | //************************* Daten vom Touchscreen holen ******************************
|
34 |
|
35 | //Buffergröße etc. abfragen
|
36 | get_buffer_info(buffer_info);
|
37 |
|
38 | //Bufferdaten holen
|
39 | get_buffer_data(buffer_array, buffer_info[0]);
|
40 |
|
41 | //Dekodierung der empfangenen Daten
|
42 | for (index = 7; index < buffer_info[0] + 8; index ++)
|
43 | {
|
44 |
|
45 | if (buffer_array[index] == 0x1B)
|
46 | {
|
47 | index++;
|
48 | switch (buffer_array[index])
|
49 | {
|
50 | case 'A': //Touch-Schalter/Taster betätigt
|
51 | index++;
|
52 | index++;
|
53 | switch (buffer_array[index])
|
54 | {
|
55 | case VENTIL:
|
56 | bargraph = VENTIL;
|
57 | break;
|
58 |
|
59 | case ZUENDUNG:
|
60 | bargraph = ZUENDUNG;
|
61 | break;
|
62 |
|
63 | case LASER:
|
64 | bargraph = LASER;
|
65 | break;
|
66 | }
|
67 | break;
|
68 | }
|
69 | }
|
70 | }
|
71 | }
|
72 |
|
73 | if( i & 1 )
|
74 | { // bit 0 = value (1)
|
75 | enc_last += i; // store new as next last
|
76 | //Abhängig vom im Touchscreen ausgewählten Bargraphen werden die Eingabewerte
|
77 | //unterschiedlichen Variablen zugeordnet
|
78 | switch(bargraph)
|
79 | {
|
80 | case VENTIL:
|
81 | bar_val_ventil += (i & 2) - 1;
|
82 | //Der Drehgeber liefert pro Raste 4 Impulse. Daher ist der einglesene Wert immer um Faktor 4 zu groß,
|
83 | //entsprechend müssen die Grenzen ebenfalls um Faktor 4 größer gewählt werden.
|
84 | if (bar_val_ventil > 1200)
|
85 | bar_val_ventil = 0;
|
86 |
|
87 | if (bar_val_ventil < 0)
|
88 | bar_val_ventil = 1200;
|
89 | //Ausgabe in msec
|
90 | out = (bar_val_ventil)/6;
|
91 | update_bargraph(VENTIL, out);
|
92 | out = bar_val_ventil/4;
|
93 | sprintf(strng, "%3d", out);
|
94 | print_string(strng, 'R', 226,9);
|
95 | break;
|
96 |
|
97 | case ZUENDUNG:
|
98 |
|
99 | if ((bar_val_zuendung < 400) || ((bar_val_zuendung == 400) && ((i & 2) - 1)<0))
|
100 | bar_val_zuendung += (i & 2) - 1; // bit 1 = direction (+/-)
|
101 | else if ((bar_val_zuendung < 4000) || ((bar_val_zuendung == 4000) && ((i & 2) - 1)<0)) // && ((bar_val_zuendung/4 - 10) >= 100))
|
102 | bar_val_zuendung += 10*((i & 2) - 1); // bit 1 = direction (+/-)
|
103 | //else if ((bar_val_zuendung <= 4000) && ((bar_val_zuendung/4 - 10) < 100))
|
104 | // bar_val_zuendung += (i & 2) - 1; // bit 1 = direction (+/-)
|
105 | else //if (bar_val_zuendung <=40000)
|
106 | bar_val_zuendung += 100*((i & 2) - 1); // bit 1 = direction (+/-)
|
107 |
|
108 | if (bar_val_zuendung >= 200400)
|
109 | bar_val_zuendung = 0;
|
110 |
|
111 | if (bar_val_zuendung <= -4)
|
112 | bar_val_zuendung = 200000;
|
113 |
|
114 | out = bar_val_zuendung/1000;
|
115 | //out = bar_val_zuendung/6;
|
116 | update_bargraph(ZUENDUNG, out);
|
117 | out = bar_val_zuendung/4;
|
118 | sprintf(strng, "%5ld", out);
|
119 | print_string(strng, 'R', 226,49);
|
120 | sprintf(strng, "%6ld", bar_val_zuendung);
|
121 | print_string(strng, 'R', 226,69);
|
122 | break;
|
123 |
|
124 | case LASER:
|
125 | bar_val_laser += (i & 2) - 1; // bit 1 = direction (+/-)
|
126 |
|
127 | if (bar_val_laser > 800)
|
128 | bar_val_laser = 0;
|
129 |
|
130 | if (bar_val_laser < 0)
|
131 | bar_val_laser = 800;
|
132 | out = bar_val_laser/4;
|
133 | update_bargraph(LASER, out);
|
134 | sprintf(strng, "%3d", out);
|
135 | print_string(strng, 'R', 226,29);
|
136 | break;
|
137 | }
|
138 | }
|
139 |
|
140 | //Abfrage der Angeschlossenen Taster; es gibt folgene Taster:
|
141 | // * Einzelzündung auslösen * Ventil öffnen/schließen * Laser auslösen * Einzelsequenz abfahren * Sequenz zyklisch fahren
|
142 |
|
143 | //Sequenzstart
|
144 | if (!(PINA & (1<<PINA0))) //Taster für Sequenzstart abfragen
|
145 | {
|
146 | _delay_ms(30);
|
147 | _delay_ms(30);
|
148 | _delay_ms(30);
|
149 | _delay_ms(30);
|
150 | if (toggle_seq == 0)
|
151 | {
|
152 | if (toggle_valve == 1)
|
153 | {
|
154 | delete_area(0,64,240,80);
|
155 | print_string("Sequenzstart bei geöffnetem", 'R', 0,64);
|
156 | print_string("Fahrventil nicht möglich.", 'R', 0,72);
|
157 | }
|
158 | else
|
159 | {
|
160 | toggle_seq = 1;
|
161 | print_sequence_running(BLINKEN);
|
162 | while (!(PINA & (1<<PINA0)));
|
163 | }
|
164 | }
|
165 | else
|
166 | {
|
167 | toggle_seq = 0;
|
168 | delete_area(0,64,240,125);
|
169 | print_ready();
|
170 | while (!(PINA & (1<<PINA0)));
|
171 | }
|
172 | }
|
173 |
|
174 | //************************ Hier fangen die Probleme an... ******************************
|
175 |
|
176 | //Einzelsequenz
|
177 | if (!(PINA & (1<<PINA1))) //Taster für Einzelsequenz abfragen
|
178 | {
|
179 | //Prellzeit abwarten
|
180 | _delay_ms(30);
|
181 | _delay_ms(30);
|
182 | _delay_ms(30);
|
183 | _delay_ms(30);
|
184 |
|
185 | //Keine Ausführung bei offenenm Fahrventil
|
186 | if (toggle_valve)
|
187 | {
|
188 | delete_area(0,64,240,80);
|
189 | print_string("Einzelsequenz bei geöffnetem", 'R', 0,64);
|
190 | print_string("Fahrventil nicht möglich.", 'R', 0,72);
|
191 | _delay_ms(30);
|
192 | _delay_ms(30);
|
193 | }
|
194 |
|
195 | //Keine Ausführung bei bereits laufender Sequenz
|
196 | else if (toggle_seq)
|
197 | {
|
198 | delete_area(0,64,240,80);
|
199 | print_string("Einzelsequenz bei laufender", 'R', 0,64);
|
200 | print_string("Sequenz nicht möglich.", 'R', 0,72);
|
201 | }
|
202 | //Einzelsequenz abfahren
|
203 | else
|
204 | {
|
205 | print_sequence_running(NORMAL);
|
206 | print_ready();
|
207 |
|
208 | //Timer 0 zurücksetzen
|
209 | TCNT0 = 0;
|
210 |
|
211 | //OCR1A mit Eingabewert vom Touch laden (= Zeit, die von Ventilschluss bis Zündung vergehen soll)
|
212 | //Der Timer wird zwar erst später benötigt, aber das Register kann bereits hier (=außerhalb der ISRn)
|
213 | //geladen werden
|
214 | //OCR1A = (bar_val_zuendung*10)/12;
|
215 | //Das Register wird zu Testzwecken mit einem Festwert geladen
|
216 | OCR1A = (4*10)/12;
|
217 |
|
218 | //Compare Interrupt Timer 0 aktivieren
|
219 | TIMSK |= (1<<OCIE0);
|
220 | }
|
221 | }
|
222 | //Zündung
|
223 | if (!(PINA & (1<<PINA2)))
|
224 | {
|
225 | _delay_ms(30);
|
226 | _delay_ms(30);
|
227 | _delay_ms(30);
|
228 | _delay_ms(30);
|
229 | if (toggle_seq)
|
230 | {
|
231 | delete_area(0,64,240,80);
|
232 | print_string("Einzelzündung bei laufender", 'R', 0,64);
|
233 | print_string("Sequenz nicht möglich.", 'R', 0,72);
|
234 | }
|
235 | else
|
236 | {
|
237 | beep(2);
|
238 | if (toggle_valve)
|
239 | {
|
240 | delete_area(0,64,240,80);
|
241 | print_string("Zündung erfolgt", 'R', 0,64);
|
242 | //single_shot();
|
243 | while (!(PINA & (1<<PINA2)));
|
244 | delete_area(0,64,240,80);
|
245 | }
|
246 | else
|
247 | {
|
248 | print_done();
|
249 | //single_shot();
|
250 | while (!(PINA & (1<<PINA2)));
|
251 | delete_area(0,64,240,80);
|
252 | print_ready();
|
253 | }
|
254 | }
|
255 | }
|
256 |
|
257 | //Laser
|
258 | if (!(PINA & (1<<PINA3)))
|
259 | {
|
260 | _delay_ms(30);
|
261 | _delay_ms(30);
|
262 | _delay_ms(30);
|
263 | _delay_ms(30);
|
264 | if (toggle_seq)
|
265 | {
|
266 | delete_area(0,64,240,80);
|
267 | print_string("Laser auslösen bei laufender", 'R', 0,64);
|
268 | print_string("Sequenz nicht möglich.", 'R', 0,72);
|
269 | }
|
270 | else
|
271 | {
|
272 | beep(2);
|
273 | if (toggle_valve)
|
274 | {
|
275 | delete_area(0,64,240,80);
|
276 | print_string("Laser ausgelöst", 'R', 0,64);
|
277 | while (!(PINA & (1<<PINA3)));
|
278 | _delay_ms(100);
|
279 | delete_area(0,64,240,80);
|
280 | }
|
281 | else
|
282 | {
|
283 | print_activate();
|
284 | while (!(PINA & (1<<PINA3)));
|
285 | delete_area(0,64,240,80);
|
286 | print_ready();
|
287 | }
|
288 | }
|
289 | }
|
290 |
|
291 | //Fahrventil
|
292 | if (!(PINA & (1<<PINA4)))
|
293 | {
|
294 | _delay_ms(30);
|
295 | _delay_ms(30);
|
296 | _delay_ms(30);
|
297 | _delay_ms(30);
|
298 | if (toggle_valve == 0)
|
299 | {
|
300 | if (toggle_seq == 1)
|
301 | {
|
302 | delete_area(0,64,240,80);
|
303 | print_string("Fahrventil öffnen bei laufen-", 'R', 0,64);
|
304 | print_string("der Sequenz nicht möglich.", 'R', 0,72);
|
305 | }
|
306 | else
|
307 | {
|
308 | toggle_valve = 1;
|
309 | print_valve_open(BLINKEN);
|
310 | while (!(PINA & (1<<PINA4)));
|
311 | }
|
312 | }
|
313 | else
|
314 | {
|
315 | toggle_valve = 0;
|
316 | delete_area(0,64,240,125);
|
317 | print_ready();
|
318 | while (!(PINA & (1<<PINA4)));
|
319 |
|
320 | }
|
321 | }
|
322 | }
|
323 |
|
324 | SIGNAL (SIG_OUTPUT_COMPARE0)
|
325 | {
|
326 |
|
327 | //Diese Funktion zählt die Überläufe von Timer 0 hoch; pro Überlauf vergehen 250usec incl. der Abarbeitung
|
328 | //dieser Funktion, solange "counter" hochgezählt wird.
|
329 | //Dieser etwas umständliche Weg ist nötig, da Timer 0 mit seinen 8 Bit die geforderte Zeitspanne zwischen
|
330 | // 0 und 300ms nicht abdecken kann und Timer 1 mit seiner höheren Auflösung für andere Zwecke benötigt wird.
|
331 |
|
332 | //"counter" zählt die Funktionsaufrufe
|
333 | static uint16_t counter = 0;
|
334 |
|
335 | if (counter == 0)
|
336 | {
|
337 |
|
338 | //Fahrventil Open Command
|
339 | PORTD |= (1<<PD0);
|
340 | }
|
341 |
|
342 | counter++;
|
343 |
|
344 | // Wenn "counter den Vorgabewert erreicht hat, wird die Schleife verlassen.
|
345 | //if (counter == (bar_val_ventil-2))
|
346 |
|
347 | //"counter" wird zu Testzwecken mit einem Festwert verglichen
|
348 | if (counter == (6-2))
|
349 | //if (counter == 6)
|
350 | {
|
351 |
|
352 | //"counter" zurücksetzen
|
353 | counter = 0;
|
354 |
|
355 | //Fahrventil Close Command
|
356 | PORTD &= ~(1<<PD0);
|
357 | PORTD |= (1<<PD1);
|
358 |
|
359 |
|
360 |
|
361 | //Compare-Interrupt Timer 0 deaktivieren
|
362 |
|
363 | TIMSK &= ~ (1<<OCIE0);
|
364 |
|
365 | //Interrupt-Flags zurücksetzen; im Moment ist nicht klar, warum dies nötig ist. Wurde durch Versuch festgestellt.
|
366 | TIFR = 0xFF;
|
367 |
|
368 | //Timer 1 zurücksetzen
|
369 | TCNT1 = 0; //Timer zurücksetzen.
|
370 |
|
371 | //Compare-Interrupt A/Timer 1 aktivieren.
|
372 | TIMSK |= (1<<OCIE1A);
|
373 |
|
374 | //Timer 1 starten.
|
375 | TCCR1B |= (1<<CS12)|(1<<WGM12);
|
376 |
|
377 | //Mit "gezuendet" wird die Information, daß die folgende ISR fertig ist, übergeben.
|
378 | //Aus Präzisionsgründen soll zwischen dieser und der Folgenden ISR nicht in andere PRogrammteile gewechselt werden.
|
379 | gezuendet = 1;
|
380 |
|
381 | //Interrupts aktivieren
|
382 | sei();
|
383 |
|
384 | //Auf zweite ISR warten.
|
385 | while(gezuendet) {} //Warten, bist der andere Timer-Interrupt fertig ist.
|
386 |
|
387 | }
|
388 | }
|
389 |
|
390 | void __attribute__ ((naked))
|
391 | SIG_OUTPUT_COMPARE1A (void)
|
392 | {
|
393 | //Diese Funktion setzt den Ausgang, der die Zündung auslöst.
|
394 |
|
395 | //Flag zur Bestätigung der Ausführung zurücksetzen
|
396 | gezuendet = 0;
|
397 |
|
398 |
|
399 | //Impuls an PortD/Pin2 ausgeben
|
400 | asm volatile("sbi 0x12,0x2\n\t" //PD2
|
401 | "nop\n\t"
|
402 | "nop\n\t"
|
403 | "nop\n\t"
|
404 | "nop\n\t"
|
405 | "cbi 0x12,0x2\n\t"
|
406 | //"cbi 0x39,0x4\n\t"
|
407 | "PUSH R24\n\t"
|
408 | "LDS R24,0x0059\n\t"
|
409 | "ANDI R24,0xEF\n\t"
|
410 | "STS 0x0059,R24\n\t"
|
411 | "LDS R24,0x004E\n\t"
|
412 | "ANDI R24,0xFD\n\t"
|
413 | "STS 0x004E,R24\n\t"
|
414 | "POP R24\n\t"
|
415 | "reti\n\t"
|
416 | );
|
417 |
|
418 | //Timer 1 anhalten.
|
419 | TCCR1B &= ~(1<<CS12);
|
420 | }
|
421 |
|
422 |
|
423 | void init()
|
424 | {
|
425 | spi_init();
|
426 | DDRA = 0x00; //Port A als Eingang
|
427 | PORTA = 0xFF; //Interne Pull-Ups für Port A aktivieren
|
428 |
|
429 | TCCR1A |= (1<<COM1A0)|(1<<COM1B0); //Normal Mode mit TOP=ICR1
|
430 | TCCR1A &= ~((1<<COM1A1)|(1<<COM1B1)); //Compare Match toggled die Ausgänge
|
431 | DDRD = 0xFF; //Port D als Ausgang; Compare-Ausgänge liegen auf PD4 und PD5
|
432 | MCUCR |= (1<<ISC01)|(1<<ISC00);//INT0(PD1) bei steigender Flanke
|
433 | OCR0 = 250; //Timer 0 alle 250 Taktzyklen löschen
|
434 |
|
435 | //Das setzen der Taktrate in TCCR0 startet Timer 0
|
436 | TCCR0 |= (1<<CS01)|(1<<WGM01); //CLK/8 (1us/Taktzyklus), CTC
|
437 |
|
438 | }
|
439 |
|
440 | void setup_display()
|
441 | {
|
442 |
|
443 | cursor_off();
|
444 | clear_screen();
|
445 |
|
446 | touch_on(EIN);
|
447 | touch_inv(EIN);
|
448 | touch_beep(EIN);
|
449 | touch_style(17);
|
450 |
|
451 | set_touch_font(FGENEVA10PROP);
|
452 |
|
453 | open_radio_group(1);
|
454 | define_touch_switch("Ventil", 1, 20, 40, 15, 1, 4);
|
455 | define_touch_switch("Laser", 1, 40, 40, 15, 3, 5);
|
456 | define_touch_switch("Zündung", 1, 60, 40, 15, 2, 6);
|
457 | close_radio_group();
|
458 |
|
459 | define_bargraph(VENTIL, RECHTS, 45, 20, 203, 1, 0, 200, BALKEN, 1);
|
460 | define_bargraph(LASER, RECHTS, 45, 41, 230, 21, 0, 200, STRICH, 1);
|
461 | define_bargraph(ZUENDUNG, RECHTS, 45, 61, 230, 42, 0, 200, STRICH, 1);
|
462 |
|
463 | update_bargraph(1, 0);
|
464 | update_bargraph(2, 0);
|
465 | update_bargraph(3, 0);
|
466 |
|
467 | print_string("0", 'R', 226,9);
|
468 | print_string("0", 'R', 226,29);
|
469 | print_string("0", 'R', 226,49);
|
470 | print_ready();
|
471 | }
|
472 |
|
473 | int main()
|
474 | {
|
475 | init();
|
476 | setup_display();
|
477 | set_protocol_params();
|
478 | sei();
|
479 | while(1)
|
480 | {
|
481 | query();
|
482 | }
|
483 | }
|