#include /************************************************************************/ /* */ /* Reading rotary encoder */ /* one, two and four step encoders supported */ /* */ /* Author: Peter Dannegger */ /* target: ATmega16 */ /************************************************************************/ #include #include #include //#define XTAL 8e6 // 8MHz #define F_TIMER1 100 // Timer 1 frequency /Hz //////////////////////////////////////////////////////////////////////////////// // Tastenentprellung // #define KEY_DDR DDRC #define KEY_PORT PORTC #define KEY_PIN PINC #define KEY1 1 #define ALL_KEYS 0xFF #define REPEAT_MASK ( 1< SM_MIN ) taktgeber_wert = SM_MIN; if( taktgeber_wert <= SM_MAX ) taktgeber_wert = SM_MAX; OCR3A = taktgeber_wert; // An Taktgeber Wert Uebergeben } LEDS = taktgeber_wert; // Nur untere 8-Bit } // Ende void loop() //////////////////////////////////////////////////////////////////////////////// // Interrupt Service Routine Timer1 Output Compare Match A // Hand-encoder auswerten und Tastenentprellung ISR( TIMER1_COMPA_vect ) { // 1ms for manual movement int8_t neu, diff, tmp; tmp = H_ENCODER_PIN; neu = 0; if ( tmp & H_ENCODER_A ) neu = 3; if ( tmp & H_ENCODER_B ) neu ^= 1; // convert gray to binary diff = h_encoder_alt - neu; // difference last - new if( diff & 1 ) { // bit 0 = value (1) h_encoder_alt = neu; // store new as next last h_encoder_delta += (diff & 2) - 1; // bit 1 = direction (+/-) } //////////////////////////////////////////////////////////////////////////////// // Tastenentprellung // static uint8_t ct0 = 0xFF, ct1 = 0xFF, rpt; uint8_t i; 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 ( (key_state & REPEAT_MASK) == 0 ) { // check repeat function rpt = REPEAT_START; // start delay } if ( --rpt == 0 ) { rpt = REPEAT_NEXT; // repeat delay key_rpt |= key_state & REPEAT_MASK; } } // Ende ISR( TIMER1_COMPA_vect ) //////////////////////////////////////////////////////////////////////////////// // Zaehler an Hand-Encoder-Typ anpassen ( Rueckgabewert 0, 1 oder -1 ) // read 1, 2, or 4 step encoders int8_t h_encode_read( uint8_t klicks ) { // atomic access to enc_delta cli( ); h_encoder_wert = h_encoder_delta; switch( klicks ) { case 2: h_encoder_delta = h_encoder_wert & 1; h_encoder_wert >>= 1; break; case 4: h_encoder_delta = h_encoder_wert & 3; h_encoder_wert >>= 2; break; default: h_encoder_delta = 0; break; } sei( ); return h_encoder_wert; // counts since last call } //////////////////////////////////////////////////////////////////////////////// // Hand-Encoder mit Timer1 Output Compare A initialisieren // void h_encoder_init( void ) { int8_t neu, tmp; // init encoder tmp = H_ENCODER_PIN; neu = 0; if( tmp & H_ENCODER_A ) neu = 3; if( tmp & H_ENCODER_B ) neu ^= 1; // convert gray to binary h_encoder_alt = neu; // power on state h_encoder_delta = 0; // interne Pull Ups einschalten H_ENCODER_DDR &= ~(H_ENCODER_A | H_ENCODER_B); H_ENCODER_PORT |= (H_ENCODER_A | H_ENCODER_B); // Timer 1, CTC mode 4, prescaler 64 TCCR1A = 0; TCCR1B = (1<