Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1734 | - | 1 | /***************************************************************************** |
2 | * Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de * |
||
3 | * Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net * |
||
4 | * based on the key handling by Peter Dannegger * |
||
5 | * see www.mikrocontroller.net * |
||
6 | * Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net * |
||
7 | * Copyright (C) 2011 Harald Bongartz * |
||
8 | * * |
||
9 | * This program is free software; you can redistribute it and/or modify * |
||
10 | * it under the terms of the GNU General Public License as published by * |
||
11 | * the Free Software Foundation; either version 2 of the License. * |
||
12 | * * |
||
13 | * This program is distributed in the hope that it will be useful, * |
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
||
16 | * GNU General Public License for more details. * |
||
17 | * * |
||
18 | * You should have received a copy of the GNU General Public License * |
||
19 | * along with this program; if not, write to the * |
||
20 | * Free Software Foundation, Inc., * |
||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
||
22 | * * |
||
23 | * * |
||
24 | * Credits to: * |
||
25 | * Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN * |
||
26 | * http://www.mikrokopter.de * |
||
27 | * Gregor "killagreg" Stobrawa for his version of the MK code * |
||
28 | * Thomas Kaiser "thkais" for the original project. See * |
||
29 | * http://www.ft-fanpage.de/mikrokopter/ * |
||
30 | * http://forum.mikrokopter.de/topic-4061-1.html * |
||
31 | * Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code * |
||
32 | * http://www.mylifesucks.de/oss/c-osd/ * |
||
33 | * Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility* |
||
34 | *****************************************************************************/ |
||
35 | |||
36 | #include "cpu.h" |
||
37 | #include <avr/io.h> |
||
38 | #include <avr/interrupt.h> |
||
39 | #include <avr/pgmspace.h> |
||
40 | #include <string.h> |
||
41 | #include <util/delay.h> |
||
42 | #include <inttypes.h> |
||
43 | |||
44 | |||
45 | #include "main.h" |
||
46 | #include "timer.h" |
||
47 | #include "eeprom.h" |
||
48 | #include "lcd.h" |
||
49 | #include "uart1.h" |
||
50 | #include "bluetooth.h" |
||
51 | #include "setup.h" |
||
52 | |||
53 | |||
54 | #if defined HWVERSION1_2W || defined HWVERSION1_2 |
||
55 | #include "HAL_HW1_2.h" |
||
56 | #endif |
||
57 | |||
58 | #if defined HWVERSION1_3W || defined HWVERSION1_3 |
||
59 | #include "HAL_HW1_3.h" |
||
60 | #endif |
||
61 | |||
62 | #ifdef HWVERSION3_9 |
||
63 | #include "HAL_HW3_9.h" |
||
64 | #endif |
||
65 | |||
66 | volatile uint16_t timer; |
||
67 | volatile uint16_t abo_timer; |
||
68 | volatile static unsigned int tim_main; |
||
69 | |||
70 | uint8_t key_state = 0; // debounced and inverted key state: |
||
71 | // bit = 1: key pressed |
||
72 | uint8_t key_press = 0; // key press detect |
||
73 | uint8_t key_long = 0; // key long press |
||
74 | uint8_t key_rpt = 0; // key repeat |
||
75 | uint8_t key_lrpt = 0; // key long press and repeat |
||
76 | uint8_t key_rpts = 0; // key long press and speed repeat |
||
77 | uint8_t repeat_speed = 0; |
||
78 | |||
79 | uint16_t DisplayTime = 0; // Leuchtdauer |
||
80 | volatile uint16_t IdleTimer = 0; // InaktivitätsTimer |
||
81 | |||
82 | uint16_t WarnCount = 0; // Zähler der LIPO Warnzeit |
||
83 | uint16_t WarnToggle = 0; // Togglezähler zum blinken |
||
84 | uint16_t WarnTime = 10; // Länge der LIPO Warnzeit 10 Sek. |
||
85 | uint16_t PoffTime = 30; // Länge der Wartezeit vor Abschalten 30 Sek. |
||
86 | //uint8_t servo = 0; |
||
87 | |||
88 | |||
89 | |||
90 | volatile uint8_t Display_on;// Flag Display on/off |
||
91 | |||
92 | unsigned int BeepTime = 0; |
||
93 | unsigned int BeepMuster = 0xffff; |
||
94 | unsigned int BeepPrio = 0; |
||
95 | |||
96 | volatile unsigned int CountMilliseconds = 0; |
||
97 | |||
98 | // Size of Buffer for Converting unsigned int Value to ASCII |
||
99 | #define STRING_BUFFER_SIZE 5 |
||
100 | |||
101 | // Buffer for Converting unsigned int Value to ASCII |
||
102 | char String_Buffer[STRING_BUFFER_SIZE]; |
||
103 | |||
104 | |||
105 | //-------------------------------------------------------------- |
||
106 | // |
||
107 | void Timer1_Init (void) // Timer 1-A |
||
108 | { |
||
109 | // löschen |
||
110 | TCCR1A = 0; |
||
111 | TCCR1B = 0; |
||
112 | TIMSK1 = 0; |
||
113 | |||
114 | // setzen |
||
115 | TCCR1A |= (1 << COM1A1) | (1 << WGM11); |
||
116 | TCCR1B |= (1 << CS11) | (1 << CS10) | (1 << WGM13) | (1 << WGM12); |
||
117 | |||
118 | ICR1 = (F_CPU / 64) * 20 / 1000; |
||
119 | |||
120 | OCR1A = 470; // ca. Servomitte |
||
121 | } |
||
122 | |||
123 | |||
124 | //-------------------------------------------------------------- |
||
125 | void Timer2_Init (void) // Displayhelligkeit |
||
126 | { |
||
127 | DDRD |= (1 << DDD7); // PD7 output |
||
128 | TCCR2A |= (1 << WGM21) | (1 << WGM20) | (1 << COM2A1); // non invers |
||
129 | TCCR2B |= (1 << CS20); // Prescaler 1/1 |
||
130 | TIMSK2 |= (1 << OCIE2A) | (1 << OCIE2B); |
||
131 | |||
132 | OCR2A = 255; |
||
133 | } |
||
134 | |||
135 | |||
136 | #if defined HWVERSION1_2 || defined HWVERSION1_2W |
||
137 | //-------------------------------------------------------------- |
||
138 | ISR(TIMER2_COMPA_vect) |
||
139 | { |
||
140 | PORTD &= ~(1 << PD7); |
||
141 | PORTC &= ~(1 << PC0); |
||
142 | PORTC &= ~(1 << PC1); |
||
143 | } |
||
144 | ISR(TIMER2_COMPB_vect) |
||
145 | { |
||
146 | PORTD |= (1 << PD7); |
||
147 | PORTC |= (1 << PC0); |
||
148 | PORTC |= (1 << PC1); |
||
149 | } |
||
150 | #endif |
||
151 | #if defined HWVERSION1_3 || defined HWVERSION1_3W |
||
152 | //-------------------------------------------------------------- |
||
153 | ISR(TIMER2_COMPA_vect) |
||
154 | { |
||
155 | PORTD &= ~(1 << PD7); |
||
156 | PORTD &= ~(1 << PD6); |
||
157 | PORTC &= ~(1 << PC2); |
||
158 | } |
||
159 | ISR(TIMER2_COMPB_vect) |
||
160 | { |
||
161 | PORTD |= (1 << PD7); |
||
162 | PORTD |= (1 << PD6); |
||
163 | PORTC |= (1 << PC2); |
||
164 | } |
||
165 | #endif |
||
166 | #ifdef HWVERSION3_9 |
||
167 | //-------------------------------------------------------------- |
||
168 | ISR(TIMER2_COMPA_vect) |
||
169 | { |
||
170 | PORTD |= (1 << PIND7); // MartinR: von PD auf PIND geändert |
||
171 | } |
||
172 | ISR(TIMER2_COMPB_vect) |
||
173 | { |
||
174 | PORTD &= ~(1 << PIND7); // MartinR: von PD auf PIND geändert |
||
175 | } |
||
176 | #endif |
||
177 | |||
178 | |||
179 | //-------------------------------------------------------------- |
||
180 | void Timer0_Init (void) // System (100Hz) |
||
181 | { |
||
182 | timer = 0; |
||
183 | |||
184 | TCCR0A = (1 << WGM01); |
||
185 | TCCR0B = (1 << CS02) | (1 << CS00); |
||
186 | OCR0A = (F_CPU / (100L * 1024L)) ; |
||
187 | |||
188 | TIMSK0 |= (1 << OCIE0A); // enable interrupt for OCR |
||
189 | } |
||
190 | |||
191 | |||
192 | //-------------------------------------------------------------- |
||
193 | ISR(TIMER0_COMPA_vect) // Timer-Interrupt (100 Hz) |
||
194 | { |
||
195 | static uint8_t ct0 = 0; |
||
196 | static uint8_t ct1 = 0; |
||
197 | static uint8_t k_time_l = 0; |
||
198 | static uint8_t k_time_r = 0; |
||
199 | static uint8_t k_time_lr = 0; |
||
200 | static uint8_t k_time_rs = 0; |
||
201 | uint8_t i; |
||
202 | |||
203 | static unsigned char cnt_1ms = 1,cnt = 0; |
||
204 | unsigned char beeper_ein = 0; |
||
205 | // unsigned char pieper_ein = 0; |
||
206 | |||
207 | // Key handling by Peter Dannegger |
||
208 | // see www.mikrocontroller.net |
||
209 | |||
210 | i = key_state ^ ~KEY_PIN; // key changed ? |
||
211 | ct0 = ~(ct0 & i); // reset or count ct0 |
||
212 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
||
213 | i &= (ct0 & ct1); // count until roll over ? |
||
214 | key_state ^= i; // then toggle debounced state |
||
215 | key_press |= (key_state & i); // 0->1: key press detect |
||
216 | |||
217 | if (PKT_IdleBeep == 1) |
||
218 | { |
||
219 | IdleTimer ++; // nix zu tun? Timer hochzählen |
||
220 | if (IdleTimer == 12000) // Warnhinweis |
||
221 | { |
||
222 | set_beep ( 200, 0x0080, BeepNormal); |
||
223 | IdleTimer = 0; |
||
224 | } |
||
225 | } |
||
226 | |||
227 | if (!cnt--) |
||
228 | { |
||
229 | cnt = 9; |
||
230 | CountMilliseconds++; |
||
231 | cnt_1ms++; |
||
232 | } |
||
233 | |||
234 | if (i!=0) |
||
235 | { // Displaylicht einschalten, und bzw. Timeoutzählerreset wenn Taste gedrückt wurde |
||
236 | if (Display_on == 0) |
||
237 | set_D_LIGHT(); |
||
238 | |||
239 | |||
240 | Display_on = 1; // Flag Display on |
||
241 | DisplayTime = 0; // Timer Reset |
||
242 | IdleTimer = 0; // Idletimeout Reset |
||
243 | |||
244 | } |
||
245 | |||
246 | if (DisplayTimeout > 0) |
||
247 | { |
||
248 | if (Display_on == 1) |
||
249 | { |
||
250 | DisplayTime++; |
||
251 | if ((DisplayTime / 100) == DisplayTimeout) // ISR läuft mit 100Hz |
||
252 | { // Displaylicht ausschalten |
||
253 | clr_D_LIGHT(); |
||
254 | Display_on = 0; // Flag Display off |
||
255 | |||
256 | } |
||
257 | } |
||
258 | } |
||
259 | |||
260 | //-------------------------------------------------------------- |
||
261 | #ifdef HWVERSION3_9 |
||
262 | if (ADCSRA & ADIE) LipoCheck(); // Lipo prüfen // MartinR nicht wenn Stick aktiv |
||
263 | //LipoCheck(); // Lipo prüfen // MartinR: soe war es |
||
264 | #endif |
||
265 | |||
266 | //-------------------------------------------------------------- |
||
267 | if (BeepTime) |
||
268 | { |
||
269 | if (BeepTime > 10) |
||
270 | BeepTime -= 10; |
||
271 | else |
||
272 | { |
||
273 | BeepTime = 0; |
||
274 | |||
275 | } |
||
276 | |||
277 | if (BeepTime & BeepMuster) |
||
278 | beeper_ein = 1; |
||
279 | else beeper_ein = 0; |
||
280 | |||
281 | |||
282 | } |
||
283 | else |
||
284 | { |
||
285 | beeper_ein = 0; |
||
286 | BeepMuster = 0xffff; |
||
287 | BeepPrio = BeepNormal; |
||
288 | } |
||
289 | |||
290 | if (beeper_ein==1) |
||
291 | set_BEEP(); |
||
292 | else |
||
293 | clr_BEEP(); |
||
294 | |||
295 | |||
296 | //-------------------------------------------------------------- |
||
297 | if ((key_state & LONG_MASK) == 0) // check long key function |
||
298 | k_time_l = REPEAT_START; // start delay |
||
299 | |||
300 | if (--k_time_l == 0) // long countdown |
||
301 | key_long |= (key_state & LONG_MASK); |
||
302 | |||
303 | //-------------------------------------------------------------- |
||
304 | if ((key_state & REPEAT_MASK) == 0) // check repeat function |
||
305 | k_time_r = 1; // kein delay |
||
306 | |||
307 | if (--k_time_r == 0) |
||
308 | { |
||
309 | k_time_r = REPEAT_NEXT; // repeat delay |
||
310 | key_rpt |= (key_state & REPEAT_MASK); |
||
311 | } |
||
312 | |||
313 | //-------------------------------------------------------------- |
||
314 | if ((key_state & LONG_REPEAT_MASK) == 0) // check repeat function |
||
315 | k_time_lr = REPEAT_START; // start delay |
||
316 | |||
317 | if (--k_time_lr == 0) |
||
318 | { |
||
319 | k_time_lr = REPEAT_NEXT; // repeat delay |
||
320 | key_lrpt |= (key_state & LONG_REPEAT_MASK); |
||
321 | } |
||
322 | |||
323 | //-------------------------------------------------------------- |
||
324 | if ((key_state & LONG_REPEAT_SP_MASK) == 0) // check repeatX function |
||
325 | k_time_rs = REPEAT_START; // start delay |
||
326 | |||
327 | if (--k_time_rs == 0) // repeat countdown |
||
328 | { |
||
329 | if (repeat_speed == 1) |
||
330 | { |
||
331 | k_time_rs = REPEAT_SPEED_1; |
||
332 | key_rpts |= (key_state & LONG_REPEAT_SP_MASK); |
||
333 | } |
||
334 | else if (repeat_speed == 2) |
||
335 | { |
||
336 | k_time_rs = REPEAT_SPEED_2; |
||
337 | key_rpts |= (key_state & LONG_REPEAT_SP_MASK); |
||
338 | } |
||
339 | else if (repeat_speed == 3) |
||
340 | { |
||
341 | k_time_rs = REPEAT_SPEED_3; |
||
342 | key_rpts |= (key_state & LONG_REPEAT_SP_MASK); |
||
343 | } |
||
344 | } |
||
345 | |||
346 | if (timer > 0) |
||
347 | timer --; |
||
348 | |||
349 | if (abo_timer > 0) |
||
350 | abo_timer --; |
||
351 | |||
352 | // if (receiveNMEA==true) |
||
353 | // { |
||
354 | // if (bt_receiveNMEA()) Tracking_NMEA(); |
||
355 | // |
||
356 | // } |
||
357 | |||
358 | |||
359 | } |
||
360 | |||
361 | |||
362 | //-------------------------------------------------------------- |
||
363 | #ifdef HWVERSION3_9 |
||
364 | |||
365 | void LipoCheck (void) // Lowbatpin des Spannungswandlers prüfen |
||
366 | // LBO des LT1308 wechselt zum Ende der Batterielaufzeit häufig seinen Zustand in der Übergangsphase zum LowBat |
||
367 | // Die Akkuspannung schwankt auch abhängig vom momentanen Stromverbrauch |
||
368 | { |
||
369 | if (WarnToggle == 1) // Beim ersten Auftreten Warnung ausgeben, Rythmus 5/10 Sekunden |
||
370 | { |
||
371 | |||
372 | set_beep ( 1000, 0x0020, BeepNormal); |
||
373 | lcd_printp_at (0, 0, PSTR(" LIPO !!Warnung!! "), 2); |
||
374 | } |
||
375 | |||
376 | if (WarnToggle == WarnTime * 100) |
||
377 | WarnToggle = 0; // erstmal bis hier warnen |
||
378 | |||
379 | if (WarnToggle > 0) |
||
380 | WarnToggle++; // weiter hochzählen |
||
381 | |||
382 | if (PINC & (1 << LowBat)) // Kurzzeitige Unterspannung bearbeiten und Warnung ausgeben |
||
383 | { |
||
384 | WarnCount = 0; |
||
385 | // if (WarnCount > 0) |
||
386 | // WarnCount--; // Bei LIPO OK erstmal runterzählen, LT1308 überlegt sich noch genauer ob nun ok oder nicht |
||
387 | } |
||
388 | |||
389 | if (!(PINC & (1 << LowBat)) ) // LT1308 hat Unterspannung erkannt |
||
390 | { |
||
391 | WarnCount++; // solange LBO low ist Zähler hochzählen |
||
392 | if (WarnCount == 10 && WarnToggle == 0) // mit "10" etwas unempfindlicher gegen kurze Impulse machen |
||
393 | WarnToggle = 1; // Warnhinweis starten |
||
394 | } |
||
395 | |||
396 | if ((WarnCount) == PoffTime * 100) |
||
397 | clr_V_On(); // Spannung abschalten |
||
398 | } |
||
399 | |||
400 | #endif |
||
401 | |||
402 | |||
403 | //-------------------------------------------------------------- |
||
404 | unsigned int SetDelay (unsigned int t) |
||
405 | { |
||
406 | return(CountMilliseconds + t + 1); |
||
407 | } |
||
408 | |||
409 | |||
410 | //-------------------------------------------------------------- |
||
411 | char CheckDelay(unsigned int t) |
||
412 | { |
||
413 | return(((t - CountMilliseconds) & 0x8000) >> 9); |
||
414 | } |
||
415 | |||
416 | |||
417 | //-------------------------------------------------------------- |
||
418 | void Delay_ms(unsigned int w) |
||
419 | { |
||
420 | unsigned int akt; |
||
421 | akt = SetDelay(w); |
||
422 | while (!CheckDelay(akt)); |
||
423 | } |
||
424 | |||
425 | |||
426 | //-------------------------------------------------------------- |
||
427 | // |
||
428 | uint8_t get_key_press (uint8_t key_mask) |
||
429 | { |
||
430 | uint8_t sreg = SREG; |
||
431 | |||
432 | // disable all interrupts |
||
433 | cli(); |
||
434 | |||
435 | key_mask &= key_press; // read key(s) |
||
436 | key_press ^= key_mask; // clear key(s) |
||
437 | |||
438 | SREG = sreg; // restore status register |
||
439 | |||
440 | return key_mask; |
||
441 | } |
||
442 | |||
443 | |||
444 | //-------------------------------------------------------------- |
||
445 | // |
||
446 | uint8_t get_key_short (uint8_t key_mask) |
||
447 | { |
||
448 | uint8_t ret; |
||
449 | uint8_t sreg = SREG; |
||
450 | |||
451 | // disable all interrupts |
||
452 | cli(); |
||
453 | |||
454 | ret = get_key_press (~key_state & key_mask); |
||
455 | |||
456 | SREG = sreg; // restore status register |
||
457 | |||
458 | return ret; |
||
459 | } |
||
460 | |||
461 | |||
462 | //-------------------------------------------------------------- |
||
463 | // |
||
464 | uint8_t get_key_long (uint8_t key_mask) |
||
465 | { |
||
466 | uint8_t sreg = SREG; |
||
467 | |||
468 | // disable all interrupts |
||
469 | cli(); |
||
470 | |||
471 | key_mask &= key_long; // read key(s) |
||
472 | key_long ^= key_mask; // clear key(s) |
||
473 | |||
474 | SREG = sreg; // restore status register |
||
475 | |||
476 | return get_key_press (get_key_rpt (key_mask)); |
||
477 | } |
||
478 | |||
479 | |||
480 | //-------------------------------------------------------------- |
||
481 | // |
||
482 | uint8_t get_key_rpt (uint8_t key_mask) |
||
483 | { |
||
484 | uint8_t sreg = SREG; |
||
485 | |||
486 | // disable all interrupts |
||
487 | cli(); |
||
488 | |||
489 | key_mask &= key_rpt; // read key(s) |
||
490 | key_rpt ^= key_mask; // clear key(s) |
||
491 | |||
492 | SREG = sreg; // restore status register |
||
493 | |||
494 | return key_mask; |
||
495 | } |
||
496 | |||
497 | |||
498 | //-------------------------------------------------------------- |
||
499 | // |
||
500 | uint8_t get_key_long_rpt (uint8_t key_mask) |
||
501 | { |
||
502 | uint8_t sreg = SREG; |
||
503 | |||
504 | // disable all interrupts |
||
505 | cli(); |
||
506 | |||
507 | key_mask &= key_lrpt; // read key(s) |
||
508 | key_lrpt ^= key_mask; // clear key(s) |
||
509 | |||
510 | SREG = sreg; // restore status register |
||
511 | |||
512 | return get_key_rpt (~key_press^key_mask); |
||
513 | } |
||
514 | |||
515 | |||
516 | //-------------------------------------------------------------- |
||
517 | // |
||
518 | uint8_t get_key_long_rpt_sp (uint8_t key_mask, uint8_t key_speed) |
||
519 | { |
||
520 | uint8_t sreg = SREG; |
||
521 | |||
522 | // disable all interrupts |
||
523 | cli(); |
||
524 | |||
525 | key_mask &= key_rpts; // read key(s) |
||
526 | key_rpts ^= key_mask; // clear key(s) |
||
527 | |||
528 | repeat_speed = key_speed; |
||
529 | |||
530 | SREG = sreg; // restore status register |
||
531 | |||
532 | return key_mask; |
||
533 | } |
||
534 | |||
535 | void set_beep ( uint16_t Time, uint16_t Muster, uint8_t Prio) |
||
536 | { |
||
537 | |||
538 | if (Prio == BeepNormal) |
||
539 | { |
||
540 | if (BeepPrio == BeepNormal) // nur setzen wenn keine hohe Prio schon aktiv ist |
||
541 | { |
||
542 | BeepTime = Time; |
||
543 | BeepMuster = Muster; |
||
544 | } |
||
545 | } |
||
546 | |||
547 | if (Prio == BeepSevere) |
||
548 | { |
||
549 | if (!BeepPrio == BeepSevere) |
||
550 | { |
||
551 | BeepPrio = BeepSevere; // hohe Prio setzen |
||
552 | BeepTime = Time; |
||
553 | BeepMuster = Muster; |
||
554 | } |
||
555 | } |
||
556 | |||
557 | if (Prio == BeepOff) |
||
558 | { |
||
559 | BeepPrio = BeepNormal; // Beep hohe Prio aus |
||
560 | BeepTime = 0; |
||
561 | BeepMuster = 0; |
||
562 | } |
||
563 | |||
564 | |||
565 | } |
||
566 | |||
567 |