0,0 → 1,567 |
/***************************************************************************** |
* Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de * |
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net * |
* based on the key handling by Peter Dannegger * |
* see www.mikrocontroller.net * |
* Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net * |
* Copyright (C) 2011 Harald Bongartz * |
* * |
* This program is free software; you can redistribute it and/or modify * |
* it under the terms of the GNU General Public License as published by * |
* the Free Software Foundation; either version 2 of the License. * |
* * |
* This program is distributed in the hope that it will be useful, * |
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
* GNU General Public License for more details. * |
* * |
* You should have received a copy of the GNU General Public License * |
* along with this program; if not, write to the * |
* Free Software Foundation, Inc., * |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
* * |
* * |
* Credits to: * |
* Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN * |
* http://www.mikrokopter.de * |
* Gregor "killagreg" Stobrawa for his version of the MK code * |
* Thomas Kaiser "thkais" for the original project. See * |
* http://www.ft-fanpage.de/mikrokopter/ * |
* http://forum.mikrokopter.de/topic-4061-1.html * |
* Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code * |
* http://www.mylifesucks.de/oss/c-osd/ * |
* Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility* |
*****************************************************************************/ |
|
#include "cpu.h" |
#include <avr/io.h> |
#include <avr/interrupt.h> |
#include <avr/pgmspace.h> |
#include <string.h> |
#include <util/delay.h> |
#include <inttypes.h> |
|
|
#include "main.h" |
#include "timer.h" |
#include "eeprom.h" |
#include "lcd.h" |
#include "uart1.h" |
#include "bluetooth.h" |
#include "setup.h" |
|
|
#if defined HWVERSION1_2W || defined HWVERSION1_2 |
#include "HAL_HW1_2.h" |
#endif |
|
#if defined HWVERSION1_3W || defined HWVERSION1_3 |
#include "HAL_HW1_3.h" |
#endif |
|
#ifdef HWVERSION3_9 |
#include "HAL_HW3_9.h" |
#endif |
|
volatile uint16_t timer; |
volatile uint16_t abo_timer; |
volatile static unsigned int tim_main; |
|
uint8_t key_state = 0; // debounced and inverted key state: |
// bit = 1: key pressed |
uint8_t key_press = 0; // key press detect |
uint8_t key_long = 0; // key long press |
uint8_t key_rpt = 0; // key repeat |
uint8_t key_lrpt = 0; // key long press and repeat |
uint8_t key_rpts = 0; // key long press and speed repeat |
uint8_t repeat_speed = 0; |
|
uint16_t DisplayTime = 0; // Leuchtdauer |
volatile uint16_t IdleTimer = 0; // InaktivitätsTimer |
|
uint16_t WarnCount = 0; // Zähler der LIPO Warnzeit |
uint16_t WarnToggle = 0; // Togglezähler zum blinken |
uint16_t WarnTime = 10; // Länge der LIPO Warnzeit 10 Sek. |
uint16_t PoffTime = 30; // Länge der Wartezeit vor Abschalten 30 Sek. |
//uint8_t servo = 0; |
|
|
|
volatile uint8_t Display_on;// Flag Display on/off |
|
unsigned int BeepTime = 0; |
unsigned int BeepMuster = 0xffff; |
unsigned int BeepPrio = 0; |
|
volatile unsigned int CountMilliseconds = 0; |
|
// Size of Buffer for Converting unsigned int Value to ASCII |
#define STRING_BUFFER_SIZE 5 |
|
// Buffer for Converting unsigned int Value to ASCII |
char String_Buffer[STRING_BUFFER_SIZE]; |
|
|
//-------------------------------------------------------------- |
// |
void Timer1_Init (void) // Timer 1-A |
{ |
// löschen |
TCCR1A = 0; |
TCCR1B = 0; |
TIMSK1 = 0; |
|
// setzen |
TCCR1A |= (1 << COM1A1) | (1 << WGM11); |
TCCR1B |= (1 << CS11) | (1 << CS10) | (1 << WGM13) | (1 << WGM12); |
|
ICR1 = (F_CPU / 64) * 20 / 1000; |
|
OCR1A = 470; // ca. Servomitte |
} |
|
|
//-------------------------------------------------------------- |
void Timer2_Init (void) // Displayhelligkeit |
{ |
DDRD |= (1 << DDD7); // PD7 output |
TCCR2A |= (1 << WGM21) | (1 << WGM20) | (1 << COM2A1); // non invers |
TCCR2B |= (1 << CS20); // Prescaler 1/1 |
TIMSK2 |= (1 << OCIE2A) | (1 << OCIE2B); |
|
OCR2A = 255; |
} |
|
|
#if defined HWVERSION1_2 || defined HWVERSION1_2W |
//-------------------------------------------------------------- |
ISR(TIMER2_COMPA_vect) |
{ |
PORTD &= ~(1 << PD7); |
PORTC &= ~(1 << PC0); |
PORTC &= ~(1 << PC1); |
} |
ISR(TIMER2_COMPB_vect) |
{ |
PORTD |= (1 << PD7); |
PORTC |= (1 << PC0); |
PORTC |= (1 << PC1); |
} |
#endif |
#if defined HWVERSION1_3 || defined HWVERSION1_3W |
//-------------------------------------------------------------- |
ISR(TIMER2_COMPA_vect) |
{ |
PORTD &= ~(1 << PD7); |
PORTD &= ~(1 << PD6); |
PORTC &= ~(1 << PC2); |
} |
ISR(TIMER2_COMPB_vect) |
{ |
PORTD |= (1 << PD7); |
PORTD |= (1 << PD6); |
PORTC |= (1 << PC2); |
} |
#endif |
#ifdef HWVERSION3_9 |
//-------------------------------------------------------------- |
ISR(TIMER2_COMPA_vect) |
{ |
PORTD |= (1 << PIND7); // MartinR: von PD auf PIND geändert |
} |
ISR(TIMER2_COMPB_vect) |
{ |
PORTD &= ~(1 << PIND7); // MartinR: von PD auf PIND geändert |
} |
#endif |
|
|
//-------------------------------------------------------------- |
void Timer0_Init (void) // System (100Hz) |
{ |
timer = 0; |
|
TCCR0A = (1 << WGM01); |
TCCR0B = (1 << CS02) | (1 << CS00); |
OCR0A = (F_CPU / (100L * 1024L)) ; |
|
TIMSK0 |= (1 << OCIE0A); // enable interrupt for OCR |
} |
|
|
//-------------------------------------------------------------- |
ISR(TIMER0_COMPA_vect) // Timer-Interrupt (100 Hz) |
{ |
static uint8_t ct0 = 0; |
static uint8_t ct1 = 0; |
static uint8_t k_time_l = 0; |
static uint8_t k_time_r = 0; |
static uint8_t k_time_lr = 0; |
static uint8_t k_time_rs = 0; |
uint8_t i; |
|
static unsigned char cnt_1ms = 1,cnt = 0; |
unsigned char beeper_ein = 0; |
// unsigned char pieper_ein = 0; |
|
// Key handling by Peter Dannegger |
// see www.mikrocontroller.net |
|
i = key_state ^ ~KEY_PIN; // key changed ? |
ct0 = ~(ct0 & i); // reset or count ct0 |
ct1 = ct0 ^ (ct1 & i); // reset or count ct1 |
i &= (ct0 & ct1); // count until roll over ? |
key_state ^= i; // then toggle debounced state |
key_press |= (key_state & i); // 0->1: key press detect |
|
if (PKT_IdleBeep == 1) |
{ |
IdleTimer ++; // nix zu tun? Timer hochzählen |
if (IdleTimer == 12000) // Warnhinweis |
{ |
set_beep ( 200, 0x0080, BeepNormal); |
IdleTimer = 0; |
} |
} |
|
if (!cnt--) |
{ |
cnt = 9; |
CountMilliseconds++; |
cnt_1ms++; |
} |
|
if (i!=0) |
{ // Displaylicht einschalten, und bzw. Timeoutzählerreset wenn Taste gedrückt wurde |
if (Display_on == 0) |
set_D_LIGHT(); |
|
|
Display_on = 1; // Flag Display on |
DisplayTime = 0; // Timer Reset |
IdleTimer = 0; // Idletimeout Reset |
|
} |
|
if (DisplayTimeout > 0) |
{ |
if (Display_on == 1) |
{ |
DisplayTime++; |
if ((DisplayTime / 100) == DisplayTimeout) // ISR läuft mit 100Hz |
{ // Displaylicht ausschalten |
clr_D_LIGHT(); |
Display_on = 0; // Flag Display off |
|
} |
} |
} |
|
//-------------------------------------------------------------- |
#ifdef HWVERSION3_9 |
if (ADCSRA & ADIE) LipoCheck(); // Lipo prüfen // MartinR nicht wenn Stick aktiv |
//LipoCheck(); // Lipo prüfen // MartinR: soe war es |
#endif |
|
//-------------------------------------------------------------- |
if (BeepTime) |
{ |
if (BeepTime > 10) |
BeepTime -= 10; |
else |
{ |
BeepTime = 0; |
|
} |
|
if (BeepTime & BeepMuster) |
beeper_ein = 1; |
else beeper_ein = 0; |
|
|
} |
else |
{ |
beeper_ein = 0; |
BeepMuster = 0xffff; |
BeepPrio = BeepNormal; |
} |
|
if (beeper_ein==1) |
set_BEEP(); |
else |
clr_BEEP(); |
|
|
//-------------------------------------------------------------- |
if ((key_state & LONG_MASK) == 0) // check long key function |
k_time_l = REPEAT_START; // start delay |
|
if (--k_time_l == 0) // long countdown |
key_long |= (key_state & LONG_MASK); |
|
//-------------------------------------------------------------- |
if ((key_state & REPEAT_MASK) == 0) // check repeat function |
k_time_r = 1; // kein delay |
|
if (--k_time_r == 0) |
{ |
k_time_r = REPEAT_NEXT; // repeat delay |
key_rpt |= (key_state & REPEAT_MASK); |
} |
|
//-------------------------------------------------------------- |
if ((key_state & LONG_REPEAT_MASK) == 0) // check repeat function |
k_time_lr = REPEAT_START; // start delay |
|
if (--k_time_lr == 0) |
{ |
k_time_lr = REPEAT_NEXT; // repeat delay |
key_lrpt |= (key_state & LONG_REPEAT_MASK); |
} |
|
//-------------------------------------------------------------- |
if ((key_state & LONG_REPEAT_SP_MASK) == 0) // check repeatX function |
k_time_rs = REPEAT_START; // start delay |
|
if (--k_time_rs == 0) // repeat countdown |
{ |
if (repeat_speed == 1) |
{ |
k_time_rs = REPEAT_SPEED_1; |
key_rpts |= (key_state & LONG_REPEAT_SP_MASK); |
} |
else if (repeat_speed == 2) |
{ |
k_time_rs = REPEAT_SPEED_2; |
key_rpts |= (key_state & LONG_REPEAT_SP_MASK); |
} |
else if (repeat_speed == 3) |
{ |
k_time_rs = REPEAT_SPEED_3; |
key_rpts |= (key_state & LONG_REPEAT_SP_MASK); |
} |
} |
|
if (timer > 0) |
timer --; |
|
if (abo_timer > 0) |
abo_timer --; |
|
// if (receiveNMEA==true) |
// { |
// if (bt_receiveNMEA()) Tracking_NMEA(); |
// |
// } |
|
|
} |
|
|
//-------------------------------------------------------------- |
#ifdef HWVERSION3_9 |
|
void LipoCheck (void) // Lowbatpin des Spannungswandlers prüfen |
// LBO des LT1308 wechselt zum Ende der Batterielaufzeit häufig seinen Zustand in der Übergangsphase zum LowBat |
// Die Akkuspannung schwankt auch abhängig vom momentanen Stromverbrauch |
{ |
if (WarnToggle == 1) // Beim ersten Auftreten Warnung ausgeben, Rythmus 5/10 Sekunden |
{ |
|
set_beep ( 1000, 0x0020, BeepNormal); |
lcd_printp_at (0, 0, PSTR(" LIPO !!Warnung!! "), 2); |
} |
|
if (WarnToggle == WarnTime * 100) |
WarnToggle = 0; // erstmal bis hier warnen |
|
if (WarnToggle > 0) |
WarnToggle++; // weiter hochzählen |
|
if (PINC & (1 << LowBat)) // Kurzzeitige Unterspannung bearbeiten und Warnung ausgeben |
{ |
WarnCount = 0; |
// if (WarnCount > 0) |
// WarnCount--; // Bei LIPO OK erstmal runterzählen, LT1308 überlegt sich noch genauer ob nun ok oder nicht |
} |
|
if (!(PINC & (1 << LowBat)) ) // LT1308 hat Unterspannung erkannt |
{ |
WarnCount++; // solange LBO low ist Zähler hochzählen |
if (WarnCount == 10 && WarnToggle == 0) // mit "10" etwas unempfindlicher gegen kurze Impulse machen |
WarnToggle = 1; // Warnhinweis starten |
} |
|
if ((WarnCount) == PoffTime * 100) |
clr_V_On(); // Spannung abschalten |
} |
|
#endif |
|
|
//-------------------------------------------------------------- |
unsigned int SetDelay (unsigned int t) |
{ |
return(CountMilliseconds + t + 1); |
} |
|
|
//-------------------------------------------------------------- |
char CheckDelay(unsigned int t) |
{ |
return(((t - CountMilliseconds) & 0x8000) >> 9); |
} |
|
|
//-------------------------------------------------------------- |
void Delay_ms(unsigned int w) |
{ |
unsigned int akt; |
akt = SetDelay(w); |
while (!CheckDelay(akt)); |
} |
|
|
//-------------------------------------------------------------- |
// |
uint8_t get_key_press (uint8_t key_mask) |
{ |
uint8_t sreg = SREG; |
|
// disable all interrupts |
cli(); |
|
key_mask &= key_press; // read key(s) |
key_press ^= key_mask; // clear key(s) |
|
SREG = sreg; // restore status register |
|
return key_mask; |
} |
|
|
//-------------------------------------------------------------- |
// |
uint8_t get_key_short (uint8_t key_mask) |
{ |
uint8_t ret; |
uint8_t sreg = SREG; |
|
// disable all interrupts |
cli(); |
|
ret = get_key_press (~key_state & key_mask); |
|
SREG = sreg; // restore status register |
|
return ret; |
} |
|
|
//-------------------------------------------------------------- |
// |
uint8_t get_key_long (uint8_t key_mask) |
{ |
uint8_t sreg = SREG; |
|
// disable all interrupts |
cli(); |
|
key_mask &= key_long; // read key(s) |
key_long ^= key_mask; // clear key(s) |
|
SREG = sreg; // restore status register |
|
return get_key_press (get_key_rpt (key_mask)); |
} |
|
|
//-------------------------------------------------------------- |
// |
uint8_t get_key_rpt (uint8_t key_mask) |
{ |
uint8_t sreg = SREG; |
|
// disable all interrupts |
cli(); |
|
key_mask &= key_rpt; // read key(s) |
key_rpt ^= key_mask; // clear key(s) |
|
SREG = sreg; // restore status register |
|
return key_mask; |
} |
|
|
//-------------------------------------------------------------- |
// |
uint8_t get_key_long_rpt (uint8_t key_mask) |
{ |
uint8_t sreg = SREG; |
|
// disable all interrupts |
cli(); |
|
key_mask &= key_lrpt; // read key(s) |
key_lrpt ^= key_mask; // clear key(s) |
|
SREG = sreg; // restore status register |
|
return get_key_rpt (~key_press^key_mask); |
} |
|
|
//-------------------------------------------------------------- |
// |
uint8_t get_key_long_rpt_sp (uint8_t key_mask, uint8_t key_speed) |
{ |
uint8_t sreg = SREG; |
|
// disable all interrupts |
cli(); |
|
key_mask &= key_rpts; // read key(s) |
key_rpts ^= key_mask; // clear key(s) |
|
repeat_speed = key_speed; |
|
SREG = sreg; // restore status register |
|
return key_mask; |
} |
|
void set_beep ( uint16_t Time, uint16_t Muster, uint8_t Prio) |
{ |
|
if (Prio == BeepNormal) |
{ |
if (BeepPrio == BeepNormal) // nur setzen wenn keine hohe Prio schon aktiv ist |
{ |
BeepTime = Time; |
BeepMuster = Muster; |
} |
} |
|
if (Prio == BeepSevere) |
{ |
if (!BeepPrio == BeepSevere) |
{ |
BeepPrio = BeepSevere; // hohe Prio setzen |
BeepTime = Time; |
BeepMuster = Muster; |
} |
} |
|
if (Prio == BeepOff) |
{ |
BeepPrio = BeepNormal; // Beep hohe Prio aus |
BeepTime = 0; |
BeepMuster = 0; |
} |
|
|
} |
|
|