Subversion Repositories Projects

Rev

Go to most recent revision | 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*
 *****************************************************************************/


//############################################################################
//# HISTORY  timer.c
//#
//# 09.03.2013 OG
//# - add: timer2 (auch in timer.h)
//############################################################################


#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/timer.h"
#include "../eeprom/eeprom.h"
#include "../lcd/lcd.h"
#include "../uart/uart1.h"
#include "../bluetooth/bluetooth.h"
#include "../setup/setup.h"
#include"../tracking/tracking.h"
#include "../sound/pwmsine8bit.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 timer2;
volatile uint16_t abo_timer;
volatile uint16_t sound_timer;
volatile uint16_t soundpause_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


//uint8_t       servo = 0;
volatile uint16_t WarnCount = 0;         // Zähler der LIPO Warnzeit
volatile uint16_t WarnToggle = 0;        // Togglezähler zum blinken
volatile uint16_t WarnTime = 10;         // Länge der LIPO Warnzeit 10 Sek.
volatile uint16_t PoffTime = 30;         // Länge der Wartezeit vor Abschalten 30 Sek.


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 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
}
//--------------------------------------------------------------
//
//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
//}




//--------------------------------------------------------------
ISR(TIMER2_COMPA_vect)
{
        PORTD |= (1 << PD7);
}
ISR(TIMER2_COMPB_vect)
{
        PORTD &= ~(1 << PD7);
}

//--------------------------------------------------------------

////*****************************************************************************
void Timer2_Init (void)
{
  if (Config.HWSound == 1)
    {                                                   /*Sound PWM*/
      TCCR2A = 0x00; //stop
      ASSR  = 0x00; //set async mode
      TCNT2 = 0x00; //setup
      OCR2A  = 0xff;
      //Fast PWM 0xFF BOTTOM MAX
      //Set OC2A on Compare Match
      //clkT2S/8 (From prescaler)
      TCCR2A |=   (1 << WGM20) | (1 << WGM21) |(1 << COM2A1) | (1 << COM2A0);
      TCCR2B |=   (1 << CS20);
    }
  else
    {                                                   /* 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;
    }


}
//*****************************************************************************
//--------------------------------------------------------------
void Timer3_Init (void)  // Sound, Timer CTC
{

  TCCR3A = 0x00; //stop
  TCNT3H = 0xF8; //set count
  TCNT3L = 0x00; //set count
  OCR3AH = 0x07; //set compare
  OCR3AL = 0xFF; //set compare
  TCCR3A |=   (1 << WGM31);
  TCCR3B |=   (1 << CS30);
  TIMSK3 |= (1 << OCIE3A); //timer interrupt sources  2=t0 compare
}


ISR(TIMER3_COMPA_vect)  // Sound
{
//void timer0_comp_isr(void){
//was 8 KHz 125usec  sampling rate
//now 12 KHz 83usec  sampling rate
unsigned char oldfpart;
signed char fullsamp;
signed int tmp;

  TCNT3=0;
//  tics++; //8 bit... atomic

  if(generate){

    DDRD |= (1<<DDD7);            // Port aus Ausgang
    oldfpart=waveptfpart;         //remember fractional part
    waveptfpart+=freqincfpart;    //add frac part of freq inc to wave pointer
    if(waveptfpart < oldfpart){   //did it walk off the end?
      waveptipart++;              //yes, bump integer part
    }
    waveptipart+=freqincipart;    //add int part of freq increment to wave pointer
    fullsamp=sindat[waveptipart]; //get 8 bit sin sample from table (signed)
        tmp=fullsamp*iattenfac;       //cvt 7 bit x 8 = 15 bit
          OCR2A=(tmp >> 8)+128;        //cvt 15 bit signed to 8 bit unsigned
  }
  else

      DDRD &= ~(1 << DDD7);       //Port auf Eingang, sperrt das Rauschen


}



//--------------------------------------------------------------
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 (((Config.HWBeeper==1)&&(PCB_Version == PKT39m))||((Config.HWBeeper==0)&&(PCB_Version == PKT39x)))                              // entweder Beeper oder Display ein/aus
              {
                if (Display_on == 0)
                  set_D_LIGHT();


                Display_on = 1;         // Flag Display on
                DisplayTime = 0;        // Timer Reset
                IdleTimer = 0;          // Idletimeout Reset
              }
        }

        if (Config.DisplayTimeout > 0)
        {
            if (((Config.HWBeeper==1)&&(PCB_Version == PKT39m))||((Config.HWBeeper==0)&&(PCB_Version == PKT39x)))                                // entweder Beeper oder Display ein/aus
              {
                if (Display_on == 1)
                {
                        DisplayTime++;
                        if ((DisplayTime / 100) == Config.DisplayTimeout)       // ISR läuft mit 100Hz
                        {                                               // Displaylicht ausschalten
                            clr_D_LIGHT();
                            Display_on = 0;                             // Flag Display off

                        }
                }
              }
        }

//--------------------------------------------------------------
#ifdef HWVERSION3_9
//      LipoCheck();    // Lipo prüfen
#endif

//--------------------------------------------------------------
        if (Config.HWBeeper==1)
          {
            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();
          }

        //Tonausgabe ***********************************************************************************************

        if (sound_timer > 0)            // Ton spielen
        {
          sound_timer --;
        }

        else
          {
//            TIMSK2 &= ~_BV(TOIE2);      // Interrupt sperren, verhindert Störgeräusche
//            TCCR2A = 0x00; //stop
            generate=0;                 // Sound aus
            tone_handler();
            if (soundpause_timer > 0)
            {
              soundpause_timer --;        // Ton pause
            }
          }

        //***********************************************************************************************
//--------------------------------------------------------------
        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 (timer2 > 0)
                timer2 --;

        if (abo_timer > 0)
                abo_timer --;

        //24.8.2012
//              if (receiveNMEA==true)
//                {
//                  if (bt_receiveNMEA()) Tracking_NMEA();
//                  else receiveNMEA = false;
//
//                }

}


#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 (Config.HWBeeper==1)
     {
      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;
        }
     }
   else
     {

       if (Prio == BeepNormal)
         {
           if (BeepPrio == BeepNormal)        // nur setzen wenn keine hohe Prio schon aktiv ist
             {
               playTone(900,Time/10,0);
             }
         }

       if (Prio == BeepSevere)
         {
           if (!BeepPrio == BeepSevere)
             {
               playTone(1200,Time/10,0);
               playTone(1100,Time/10,0);
             }
         }

       if (Prio == BeepOff)
         {
           playTone(0,0,0);
         }

     }




}