Blame |
Last modification |
View Log
| RSS feed
/*****************************************************************************
* 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;
}
}