Here is a state machine based rotary encoder switch with push button that is interrupt bassed.
you supply the two pins that output the pulses (grey code) and the pin that is used for the push switch, and when the the switch turns the class fires an event based upon the direction of motion, (clockwise or anti clockwise)
here is the code any improvements feel free to point out.
using System; using Microsoft.SPOT.Hardware; namespace RotaryEncoderSwitch { public class RotarySwitch { private static readonly bool[] stateOne = new bool[2] {false, false}; private static readonly bool[] stateTwo = new bool[2] {false, true}; private static readonly bool[] stateThree = new bool[2] {true,true}; private static readonly bool[] stateFour = new bool[2] {true,false}; private static bool[] oldState = new bool[2]; private static bool[] newState = new bool[2]; private static InterruptPort _pinAInterrupt; private static InterruptPort _pinBInterrupt; private static InterruptPort _switchPinInterrupt; public delegate void ClockwiseEventHandler(); public delegate void CounterClockWiseEventHandler(); public delegate void ButtonPushedEventHandler(); public static event ClockwiseEventHandler ClockWise; public static event CounterClockWiseEventHandler CounterClockWise; public static event ButtonPushedEventHandler ButtonPushed; public RotarySwitch(Cpu.Pin pinA, Cpu.Pin pinB, Cpu.Pin switchPin) { _pinAInterrupt = new InterruptPort(pinA, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth); _pinBInterrupt = new InterruptPort(pinB, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth); _switchPinInterrupt = new InterruptPort(switchPin, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh); _pinAInterrupt.OnInterrupt += new NativeEventHandler(_pinAInterrupt_OnInterrupt); _pinBInterrupt.OnInterrupt += new NativeEventHandler(_pinBInterrupt_OnInterrupt); _switchPinInterrupt.OnInterrupt += new NativeEventHandler(_switchPinInterrupt_OnInterrupt); oldState[0] = _pinAInterrupt.Read(); oldState[1] = _pinBInterrupt.Read(); } static void _switchPinInterrupt_OnInterrupt(uint data1, uint data2, DateTime time) { if (ButtonPushed != null) { ButtonPushed(); } } static void _pinAInterrupt_OnInterrupt(uint data1, uint data2, DateTime time) { newState[0] = data2 == 1; newState[1] = _pinBInterrupt.Read(); CheckDirection(); } static void _pinBInterrupt_OnInterrupt(uint data1, uint data2, DateTime time) { newState[0] = _pinBInterrupt.Read(); newState[1] = data2 == 1; CheckDirection(); } private static void CheckDirection() { int newStateInt = 0; int oldStateInt = 0; int direction = 0; if (newState == stateOne) newStateInt = 1; if (newState == stateTwo) newStateInt = 2; if (newState == stateThree) newStateInt = 3; if (newState == stateFour) newStateInt = 4; if (oldState == stateOne) oldStateInt = 1; if (oldState == stateTwo) oldStateInt = 2; if (oldState == stateThree) oldStateInt = 3; if (oldState == stateFour) oldStateInt = 4; direction = newStateInt - oldStateInt; if(direction > 0) { if (ClockWise != null) ClockWise(); } if(direction < 0) { oldState = newState; newState = null; if(CounterClockWise != null) { CounterClockWise(); } } oldState = newState; newState = null; return; } } }