
#include <avr/io.h>
#include <avr/interrupt.h>

#define Schalter_A PIND1 // Schalter A im Drehgeber 
#define Schalter_B PIND0 // Schalter B im Drehgeber
#define Taster_P   PIND2 // Taster im Drehgeber
#define Geber      PIND  // Drehgeber Port
#define Ausgabe    PORTB // Ausgabe Port zum Testen

volatile unsigned char richtung = 0;  // 0 ... 255

// **************************************************************************************
ISR(TIMER0_OVF_vect)
{
  static unsigned char alter_status = 0,step = 0;
  unsigned char        neuer_status;

      neuer_status = Geber & (_BV(Schalter_A) | _BV(Schalter_B)); // Änderung einlesen
  if ((neuer_status ^ step)==(_BV(Schalter_A) | _BV(Schalter_B)))
  {
    if ((neuer_status ^ alter_status)==_BV(Schalter_A))
      richtung +=1;                  // Es war nach rechts
    else
      richtung -=1;                  // Es war nach links
    step = neuer_status;
  }
  alter_status = neuer_status;
}

// **************************************************************************************
int main(void)
{
  // Drehgeber Anschluß 
	DDRD  &= ~(_BV(PD1) | _BV(PD0)); // Pin's als Eingang
	PORTD  =  (_BV(PD1) | _BV(PD0)); // PullUp's ein
	DDRB   = 0xFF;                   // Port  als Ausgang

  // Timer0 einstellen                
//	TCCR0B = 1<<CS01 | 1<<CS00;   // Teilung durch 256 *  64 Int. alle   2ms bei 8MHz CLK
	TCCR0B = 1<<CS02;             // Teilung durch 256 * 256 Int. alle 8,2ms bei 8MHz CLK
	TIMSK  = 1<<TOIE0;            // enable timer interrupt
	sei();

	for(;;)                       // Hauptschleife
//	Ausgabe  = richtung;
	Ausgabe  = ~richtung;         // Nur beim STK500
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++





















//************************************************
//* Matrix keyboard decoder
//* Main driver source file
//*
//* Filename:  keymatrix.c
//* Version:   1.0
//*
//* Device:    ATmega162
//* Clock:     Internal 1.000 MHz RC oscillator
//*
//************************************************
/* keyboard Interface:
 * 3 rows x 8 columns: P0.0 - P0.2 * P2
 * support multiple keys pressed simultaniously
 * if more than two keys pressed, then every key need a decoupling diode
 *
 * 0x00         = no key changed
 * 0x01 .. 0x18 = key released
 * 0x81 .. 0x98 = key pressed
 */
/*
//#pragma cd pl(9999)
//#include <reg51.h>
#include <io.h>

#define KEY_PRESS_MASK  0x80

       unsigned char n_keys_pressed;		// 0, 1 or 2
static unsigned char idata valid_keys[3];	// last returned values
static unsigned char idata last_keys[3];	// t - 1


void InitKeyboard( void )
{
  unsigned char i;

  for( i = 0; i < 3; ++i )
  {
    valid_keys[i] = 0xFF;		// low active
    last_keys[i]  = 0xFF;
  }
  n_keys_pressed = 0;
}


unsigned char GetKey( void )	// call with debouncing time (10..200msec)
{
  unsigned char i, j;
  unsigned char mask;
  unsigned char key;
  unsigned char column;
  unsigned char key_nr = 0;
  unsigned char code ROW[] = { ~0x01, ~0x02, ~0x04 };	// low active

  for( i = 0; i < 3;  ++i )
  {

    P0 |= ~0x07;
    P0 &= ROW[i];					// set rows
    column = P2;					// read column

    if( column != valid_keys[i] && key_nr == 0 )
	{
      for( mask = 1, j = 0; j < 8; mask <<= 1, j++ )
	  {

        key = column & mask;				// check bitwise

        if( key == (last_keys[i] & mask) )	// debouncing
		{		

			if( key != (valid_keys[i] & mask) )	// key not handled
			{		

				valid_keys[i] = valid_keys[i] & ~mask | key;
				key_nr = 8 * i + j + 1;			// 0x01 ... 0x18

				if( key == 0 )	// low active
				{				
					n_keys_pressed++;
					key_nr |= KEY_PRESS_MASK;	// 0x81 ... 0x98
				}
				else
				{
					n_keys_pressed--;
				}
				break;
			}
        }
      }
    }
    last_keys[i] = column;				// for next debouncing
  }
  return key_nr;
}

*/
/*
Hier jetzt eine Entprellroutine, wie ich sie schon in vielen Geräten eingesetzt habe.

Diesmal ist das Programm in C geschrieben.

Sie funktioniert im Prinzip genau so, wie die 8-Tasten-Routine. D.h. das
Entprellen erfolgt durch Vergleich zweier aufeinanderfolgender Tastenzustände.

Auch das gleichzeitige Drücken mehrerer Tasten wird unterstützt, um z.B.
Shift-Tasten zu realisieren.
Bei mehr als 2 gedrückten Tasten, müssen jedoch die Tasten durch Dioden
entkoppelt werden, da sonst in der Matrix keine eindeutige Erkenung mehr
möglich ist.

Um auch das gleichzeitige Betätigen mehrerer Tasten zu erkennen, kann
diese Routine mehrmals aufgerufen werden, wenn ein Tastencode ungleich 0
zurückgeliefert wurde. Es werden unterschiedliche Kodes beim Drücken
bzw. Loslassen erzeugt. Somit ist eine Auswertung von Shift-Tasten oder
Repeatfunktion möglich.
*/
