/*************************************************************
* Attiny25 Dreimpulsgeber Auswertung
*
* Es werden die beiden impulssignale ausgewertet und bei Drehung ein 
* Impuls erzeugt, je nach Drehrichtung an einem anderen Ausgang. 
* 
*
* Interupt Belegung                             wo              warum
* -------------------------------------------------------------------------------------------
* INT0        External Interrupt Request 0
* PCINT0      Pin Change Interrupt Request 0
* PCINT1      Pin Change Interrupt Request 1
* WDT         Watchdog Time-out
* TIM1_CAPT   Timer/Counter1 Capture Event
* TIM1_COMPA  Timer/Counter1 Compare Match A
* TIM1_COMPB  Timer/Counter1 Compare Match B
* TIM1_OVF    Timer/Counter1 Overflow
* TIM0_COMPA  Timer/Counter0 Compare Match A    main.c   5msec Timer
* TIM0_COMPB  Timer/Counter0 Compare Match B
* TIM0_OVF    Timer/Counter0 Overflow
* ANA_COMP    Analog Comparator
* ADC ADC     Conversion Complete
* EE_RDY      EEPROM Ready
* USI_STR     USI START
* USI_OVF     USI Overflow
*
* Prozessor:  ATtiny25
* Frequenz:   8,000 MHz (interner Clock)
*
* -------------------------------------------------------------------------------------------
* Pin Belegung Attiny25
*                                            +----------------+
* Reset ISP      (PCINT5/RESET/ADC0/dW) PB5 -|1     XXX      8|- VCC
*                                            |                |
* OUT1    (PCINT3/XTAL1/CLKI/OC1B/ADC3) PB3 -|2              7|- PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2)   INPUT1
*                                            |                |
* OUT2    (PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 -|3              6|- PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1)      INPUT2
*                                            |                |
*                                       GND -|4              5|- PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A/AREF/PCINT0)
*                                            +----------------+
*--------------------------------------------------------------------------------------------
* FUSE: Attiny25    FF DF E2
*       mit CLKOUT  FF DF A2

* -------------------------------------------------------------------------------------------
* AVR GCC Compiler
*
* 07.09.2011 li OUT1/2 auf 52msek Impuls
* -------------------------------------------------------------------------------------------
*/

#include <avr/io.h>
#include <avr/interrupt.h>
// #include <math.h>
#include "../../abc/basis.h"


unsigned char volatile tim1_event_flag=0;        // 5 msec Trigger


  // ----------------------------------------------
  // INDEX test_switch_x()    0 
  // ----------------------------------------------
unsigned char al_cc[2]  = {    0 ,   0 };        // counters
unsigned char al_bit[2] = { BIT2, BIT1 };        // Bits


static void timer1_init(void);                      // timer 120 Hz
static unsigned char test_switch_B( unsigned char i );
#undef _COUNTR
// #define IMPULS_CNT 64          // 38 = 38 msek 
// #define IMPULS_CNT 87          // 87 = 52 msek
#define IMPULS_CNT 101          // 101 = 60 msek  

/*###########################################################################
 * Main
 */
int main(void)
{ 
   unsigned char ts1 = 0;  
   unsigned char ts2 = 0; 
#ifdef _COUNTR   
   unsigned int countr=0; 
#endif   
                                       // Indikator
                                       // .... ...1    Signal Form zum Eingang A
                                       // .... ..1.    Signal Form zum Eingang B
                                       // ...1 ....    2.fallender Impuls A, B da   
                                       // ..1. ....    2.fallender Impuls A, B da   
                                       // .1.. ....    fallender Impuls A, B da   
                                       // 1... ....    fallender Impuls B, A da
   unsigned char p = 0;  
   unsigned char count1=0, count2=0;
  
   
   timer1_init();                      // 5 msek timer
   DDRB  |= BIT3+BIT4; 
   PORTB |= BIT0+BIT1+BIT2;            // Input mit internem Pullup Widerstand
   PORTB |= BIT3+BIT4;                 // Output auf 1, da negative Impulse gefordert
                       
   
   sei();                              // enable int
   
	
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
	for(;;)
	{
	   if ( tim1_event_flag )            // 5 msek vorbei ?
	   {	      
         tim1_event_flag = 0;           // reset flag
         
         if ( (ts1 = test_switch_B(0)) ) // Input Test +++
         {
            if ( ts1 == 1 )              // 1 wenn laenger als 50 msek
            {               
               p |= BIT0;               
            }
            else if ( ts1 == 2)
            {
               p &= ~BIT0; 
               if ( p & BIT1 )          // der andere auf 1 ?
                  p |= BIT6;            // richtung 
            }
         }  
         
         if ( (ts2 = test_switch_B(1)) ) // Input Test +++
         {
            if ( ts2 == 1 )              // 1 wenn laenger als 50 msek
            {
               p |= BIT1;                
            }
            else if ( ts2 == 2)
            {
               p &= ~BIT1; 
               if ( p & BIT0 )          // der andere auf 1 ?
                  p |= BIT7;            // richtung
            }
         } 
         
                                        // Augangs Impulse erzeugen  
         if ( p & BIT6 )
         {
#ifdef _COUNTR         
            countr = 1024;
#endif
            if ( p & BIT4 )           // 2. Impuls da
            {
               count1 = IMPULS_CNT;     // dauer einstellen
               p &= ~(BIT6+BIT4);       // clear
               PORTB &= ~BIT3;          // Output auf 0
            }
            else
            {
               p |= BIT4;
               p &= ~(BIT6);            // clear
            }   
         }
         
         if ( p & BIT7 )
         {
#ifdef _COUNTR
            countr = 1024;
#endif
            if ( p & BIT5 )           // 2. Impuls da
            {
               count2 = IMPULS_CNT;     // dauer einstellen 
               p &= ~(BIT7+BIT5);       // clear
               PORTB &= ~BIT4;          // Output auf 0
            }
            else
            {
               p |= BIT5;
               p &= ~(BIT7);            // clear
            }   
         }
         
         if ( count1 )                  // end abfrage 
         {
            count1--;
            if ( count1 == 0 )
               PORTB |= BIT3;          // Output auf 0
         }
         
         if ( count2 )                  // end abfrage  
         {
            count2--;
            if ( count2 == 0 )
               PORTB |= BIT4;          // Output auf 0
         } 
#ifdef _COUNTR         
         if ( countr )
         {
            countr--;
            if ( countr == 0 )
               p &= ( BIT4+BIT5);       // nach 200msek löschen 
         }
#endif         
	   }
   }
   return 0;           // dummy
}



/*****************************************************************************
** Abfrage PORTB
** Filtern von Prellungen
** Hier Aufruf alle 5 msek
*/
static unsigned char test_switch_B( unsigned char i )
{
   unsigned char bit;

   bit = al_bit[i];                 // Bit holen

   if ( PINB & bit )                // Signal = 1 ??
   {
      if ( PINB & bit && al_cc[i] < 128 )
      {
         if ( al_cc[i]++ > 10 )     // > 50 msek ?
         {
            al_cc[i] = 128;         // pressed
            return 1;
         }
      }
   }
   else                             // Signal = 0
   {
      if ( al_cc[i] >= 128 )
      {
         if ( !(PINB & bit) )
         {
            if ( al_cc[i]++ > 138 ) // > 50 msek ?
            {
               al_cc[i] = 0;        // no pressed
               return 2;
            }
         }
      }
      else
         al_cc[i] = 0;             // no pressed
   }
   return 0;
}


/*****************************************************************************
**  set Timer1  compareA
*/
static void timer1_init( void )
{
   TCCR1 |= (1<<CTC1) ;                         // CTC mode
   GTCCR |= (1<<PSR1) ;                         // Reset Timer
   TCCR1 |= (1<<CS12) + (1<<CS10);              // prescaler
   OCR1C  = 255;                                // compare match bei 19 + 1 
   TCNT1 = 0;
   TIMSK |= (1<<OCIE1A);
}



/*****************************************************************************
*  8 Bit TIMER0 Compare Match
*  alle ca. 5 msek
*/
ISR ( TIM1_COMPA_vect )
{
   tim1_event_flag++;         // set flag 
}

