#include #include #include #include #define ENCODER_PIN PIND #define PHASE_A (1< DDRx, low byte -> PORTx 0x6040, // LED1 0x6020, // LED2 0x5040, // LED3 0x5010, // LED4 0x4840, // LED5 0x4808, // LED6 0x4440, // LED7 0x4404, // LED8 0x3020, // LED9 0x3010, // LED10 0x2820, // LED11 0x2808, // LED12 0x2420, // LED13 0x2404, // LED14 0x1810, // LED15 0x1808 // LED16 }; uint8_t richtung; int8_t led_state; // read 1, 2, or 4 step encoders int8_t encode_read( uint8_t step ) { int8_t val; // atomic access to enc_delta cli(); val = enc_delta; switch (step) { case 2: enc_delta = val & 1; val >>= 1; break; case 4: enc_delta = val & 3; val >>= 2; break; default: enc_delta = 0; break; } sei(); return val; // counts since last call } void led_refresh(void) { int i, j; // LED Band rotieren if (richtung) { // rechts rotieren led_state++; if (led_state > 14) led_state = 0; } else { // links rotieren led_state--; if (led_state < 0) led_state = 14; } j = led_state; // Charliplexing aktualisieren for (i=0; i 14) j = 0; } } int main(void) { int8_t tmp; // init IOs DDRD = (1< 0) richtung = 1; if (tmp < 0) richtung = 0; led_refresh(); } } } // timer 0 overflow ISR, 488Hz ISR(TIMER0_OVF_vect) { int8_t new, diff, tmp; static int8_t last, cnt, cnt_led; uint16_t tmp1; // decode rotary encoder tmp = ENCODER_PIN; new = 0; if ( tmp & PHASE_A ) new = 3; if ( tmp & PHASE_B ) new ^= 1; // convert gray to binary diff = last - new; // difference last - new if( diff & 1 ) { // bit 0 = value (1) last = new; // store new as next last enc_delta += (diff & 2) - 1; // bit 1 = direction (+/-) } // 10ms flag counter cnt++; if (cnt == 48) { cnt = 0; flag_100ms = 1; } // charlieplexing PORTD = 0x3; // all LEDs off, only pull ups active cnt_led++; if (cnt_led == CHARLIE_CNT) cnt_led = 0; tmp1 = leds[cnt_led]; DDRD = tmp1>>8; // new led code PORTD = tmp1 | 0x3; }