diff --git a/configreader.py b/configreader.py
index b63ff30..ddee9e1 100644
--- a/configreader.py
+++ b/configreader.py
@@ -1,9 +1,8 @@
-
 import csv
 import ConfigParser
 import apparatinterface
 import phoneinterface
-import fetapd
+import statemachine
 
 class ConfigurationReader(object):
     DEFAULTS = {
@@ -82,7 +81,7 @@ class ConfigurationReader(object):
             invert_gs = self.__get_global_val_bool('invert_gs'),
         )
 
-        self.__dialconfig = fetapd.DialConfiguration(
+        self.__dialconfig = statemachine.DialConfiguration(
             self.__get_global_val_int('dial_timeout'),
             self.__read_shortcuts(),
             self.__read_blacklist(),
diff --git a/fetapd.py b/fetapd.py
index 5680c9d..b3da7c8 100644
--- a/fetapd.py
+++ b/fetapd.py
@@ -1,370 +1,43 @@
 import time
-import threading
-import Queue as queue
 from phoneinterface import PhoneInterface, PhoneEvent
 from apparatinterface import FeApPinConfiguration, FeApUserInterface
 import configreader
+import statemachine
 
 
-class DialConfiguration(object):
-    def __init__(self, dial_timeout, shortcuts, blacklist):
-        self.dial_timeout = dial_timeout
-        self.shortcuts = shortcuts
-        self.blacklist = blacklist
+controller = None
 
-class IllegalEventError(Exception):
-    pass
-
-
-"""
-An abstract state, needed to define all possible events.
-
-"""
-class AbstractState(object):
-    def on_registration_in_progress(self):
-        raise IllegalEventError()
-
-    def on_registration_successful(self):
-        raise IllegalEventError()
-
-    def on_registration_lost(self):
-        raise IllegalEventError()
-
-    def on_gabelschalter_up(self):
-        raise IllegalEventError()
-
-    def on_gabelschalter_down(self):
-        raise IllegalEventError()
-
-    def on_incoming_call(self):
-        raise IllegalEventError()
-
-    def on_call_ended(self):
-        raise IllegalEventError()
-
-    def on_call_accepted(self):
-        raise IllegalEventError()
-
-    def on_call_ringing(self):
-        raise IllegalEventError()
-
-    def on_invalid_number(self):
-        raise IllegalEventError()
-
-    def on_nummernschalter_active(self):
-        raise IllegalEventError()
-
-    def on_nummernschalter_input(self, num):
-        raise IllegalEventError()
-
-    def on_timeout(self):
-        raise IllegalEventError()
-
-    def leave(self):
-        return None
-
-
-"""
-The basic state that every other state inherits from. It defines default
-behaviour for some events (overriden if necessary).
-
-"""
-class BaseState(AbstractState):
-    def __init__(self, controller):
-        self._controller = controller
-
-    def on_registration_lost(self):
-        return InitState
-
-    def on_gabelschalter_up(self):
-        return None
-
-    def on_gabelschalter_down(self):
-        return None
-
-    def on_incoming_call(self):
-        self._controller.phone.decline_call()
-
-    def on_call_ended(self):
-        # When an incoming call is declined, a call_ended event occurs, which
-        # needs to be ignored, here.
-        return None
-
-    def on_nummernschalter_active(self):
-        return None
-
-    def on_nummernschalter_input(self, num):
-        return None
-
-
-class InitState(BaseState):
-    def __init__(self, controller):
-        super(InitState, self).__init__(controller)
-        self._controller.feap.set_schauzeichen(True)
-
-    def on_registration_in_progress(self):
-        print('registration in progress')
-        return RegisteringState
-
-class RegisteringState(BaseState):
-    def __init__(self, controller):
-        super(RegisteringState, self).__init__(controller)
-
-    def on_registration_successful(self):
-        print('registration successful')
-        self._controller.feap.set_schauzeichen(False)
-        return IdleState
-
-class IdleState(BaseState):
-    def on_incoming_call(self):
-        print('incomfing call')
-        caller = self._controller.phone.get_remote_number()
-        print('From: %s' % caller)
-        if caller in self._controller.dialconfig.blacklist:
-            print('Caller on blacklist - declining')
-            self._controller.phone.decline_call()
-            return CallTerminatingState
-        else:
-            return SchelltState
-
-    def on_gabelschalter_up(self):
-        print('gabel up')
-        return DialingState
-
-class SchelltState(BaseState):
-    def __init__(self, controller):
-        super(SchelltState, self).__init__(controller)
-        self._controller.feap.set_wecker(True)
-
-    def leave(self):
-        self._controller.feap.set_wecker(False)
-
-    def on_gabelschalter_up(self):
-        return AcceptingState
-
-    def on_call_ended(self):
-        return IdleState
-
-class AcceptingState(BaseState):
-    def __init__(self, controller):
-        super(AcceptingState, self).__init__(controller)
-        self._controller.phone.accept_call()
-
-    def on_call_accepted(self):
-        return CallRunningState
-
-class CallTerminatingState(BaseState):
-    def __init__(self, controller):
-        super(CallTerminatingState, self).__init__(controller)
-        self._controller.phone.end_call()
-
-    def on_call_ended(self):
-        return IdleState
-
-    def on_call_accepted(self):
-        return None
-
-class ForgottenState(BaseState):
-    def on_gabelschalter_down(self):
-        return IdleState
-
-class BusyBeepingState(BaseState):
-    def __init__(self, controller):
-        super(BusyBeepingState, self).__init__(controller)
-        self._controller.phone.play_busy_tone()
-
-    def leave(self):
-        self._controller.phone.stop_playing()
-
-    def on_timeout(self):
-        return ForgottenState
-
-    def on_gabelschalter_down(self):
-        return IdleState
-
-class CallRunningState(BaseState):
-    def on_gabelschalter_down(self):
-        return CallTerminatingState
-
-    def on_call_ended(self):
-        return BusyBeepingState
-
-class WecktState(BaseState):
-    def __init__(self, controller):
-        super(WecktState, self).__init__(controller)
-        self._controller.phone.play_ringback_tone()
-
-    def leave(self):
-        self._controller.phone.stop_playing()
-
-    def on_gabelschalter_down(self):
-        return CallTerminatingState
-
-    def on_call_ended(self):
-        return BusyBeepingState
-
-    def on_call_accepted(self):
-        return CallRunningState
-
-class ConnectingState(BaseState):
-    def on_gabelschalter_down(self):
-        return CallTerminatingState
-
-    def on_call_ringing(self):
-        return WecktState
-
-    def on_call_accepted(self):
-        return CallRunningState
-
-    def on_invalid_number(self):
-        # TODO: play sound
-        return BusyBeepingState
-
-    def on_call_ended(self):
-        return BusyBeepingState
-
-class DialingState(BaseState):
-    def __init__(self, controller):
-        super(DialingState, self).__init__(controller)
-        self._controller.phone.play_dial_tone()
-        self.__dial_tone = True
-        self.__number = ''
-
-    def leave(self):
-        if self.__dial_tone:
-            self._controller.phone.stop_playing()
-        self._controller.abort_timeout()
-
-    def on_gabelschalter_down(self):
-        return IdleState
-
-    def on_nummernschalter_active(self):
-        self._controller.abort_timeout()
-        if self.__dial_tone:
-            self._controller.phone.stop_playing()
-
-    def on_nummernschalter_input(self, num):
-        print('nummernschalter: %d' % (num))
-        if self.__dial_tone:
-            self._controller.phone.stop_playing()
-        self.__number += str(num)
-        self._controller.abort_timeout()
-        self._controller.set_timeout(self._controller.dialconfig.dial_timeout * 1000)
-        self._controller.phone.read_text(str(num))
-
-    def on_timeout(self):
-        number = self.__number
-        print 'Dialing number:', number
-        if number in self._controller.dialconfig.shortcuts:
-            number = self._controller.dialconfig.shortcuts[number]
-            print 'shortcut resolved:', number
-        self._controller.phone.call(number)
-        return ConnectingState
-
-
-class StateMachineController(object):
-    def __init__(self, phone, feap, dialconfig):
-        self.__phone = phone
-        self.__feap = feap
-        self.__dialconfig = dialconfig
-
-        self.__state = InitState(self)
-
-        self.__timeout = None
-
-        self.__running = True
-        self.__evqueue = queue.Queue()
-        self.__evthread = threading.Thread(target=self.__event_dispatcher)
-        self.__evthread.start()
-
-    def __event_dispatcher(self):
-        while self.__running:
-            (evname, evargs, evkwargs) = self.__evqueue.get()
-            if not evname:
-                return
-
-            print('!!! event: %s' % (evname))
-            handler = getattr(self.__state, 'on_%s' % (evname))
-            try:
-                newstate = handler(*evargs, **evkwargs)
-            except IllegalEventError:
-                print('illegal event occured!!!!!!!!!!!!!!!!!!!!', self.__state.__class__.__name__)
-            if not newstate:
-                continue
-
-            self.__state.leave()
-            self.abort_timeout()
-
-            oldstate = self.__state.__class__
-            print('%s -> %s' % (oldstate.__name__, newstate.__name__))
-            self.__state = newstate(self)
-
-    def queue_event(self, evname, *evargs, **evkwargs):
-        if not hasattr(AbstractState, 'on_%s' % (evname)):
-            raise ValueError('Illegal event name: %s' % (evname))
-        self.__evqueue.put((evname, evargs, evkwargs))
-
-    def set_timeout(self, timeout):
-        self.__timeout = threading.Timer(timeout/1000, self.queue_event, args=['timeout'])
-        self.__timeout.start()
-
-    def abort_timeout(self):
-        if self.__timeout:
-            self.__timeout.cancel()
-        self.__timeout = None
-
-    @property
-    def phone(self):
-        return self.__phone
-
-    @property
-    def feap(self):
-        return self.__feap
-
-    @property
-    def dialconfig(self):
-        return self.__dialconfig
-
-    def stop(self, hard=False):
-        if hard:
-            self.__running = False
-        self.__evqueue.put((None, None, None))
-
-c = None
 def gabelschalter_cb(state):
-    global c
     if state == 1:
-        c.queue_event('gabelschalter_up')
+        controller.queue_event('gabelschalter_up')
     else:
-        c.queue_event('gabelschalter_down')
+        controller.queue_event('gabelschalter_down')
 
 def nummernschalter_active_cb():
-    global c
-    c.queue_event('nummernschalter_active')
+    controller.queue_event('nummernschalter_active')
 
 def nummernschalter_done_cb(digit):
-    global c
-    c.queue_event('nummernschalter_input', digit)
+    controller.queue_event('nummernschalter_input', digit)
 
 def phone_cb(event):
     if event == PhoneEvent.RegInProgress:
-        c.queue_event('registration_in_progress')
+        controller.queue_event('registration_in_progress')
     elif event == PhoneEvent.RegSuccessfull:
-        c.queue_event('registration_successful')
+        controller.queue_event('registration_successful')
     elif event == PhoneEvent.RegLost:
-        c.queue_event('registration_lost')
+        controller.queue_event('registration_lost')
     elif event == PhoneEvent.CallIncoming:
-        c.queue_event('incoming_call')
+        controller.queue_event('incoming_call')
     elif event == PhoneEvent.CallAccepted:
-        c.queue_event('call_accepted')
+        controller.queue_event('call_accepted')
     elif event == PhoneEvent.CallEnded:
-        c.queue_event('call_ended')
+        controller.queue_event('call_ended')
     elif event == PhoneEvent.CallRinging:
-        c.queue_event('call_ringing')
+        controller.queue_event('call_ringing')
     elif event == PhoneEvent.CallBusy:
-        c.queue_event('call_ended')
+        controller.queue_event('call_ended')
     elif event == PhoneEvent.CallInvalidNumber:
-        c.queue_event('invalid_number')
+        controller.queue_event('invalid_number')
 
 if __name__ == '__main__':
     cfg = configreader.ConfigurationReader()
@@ -372,34 +45,13 @@ if __name__ == '__main__':
 
     phone = PhoneInterface(cfg.phoneconfig)
     feap = FeApUserInterface(cfg.pinconfig)
-    c = StateMachineController(phone, feap, cfg.dialconfig)
-
-    feap.add_gabelschalter_callback(gabelschalter_cb)
-    feap.add_nummernschalter_active_callback(nummernschalter_active_cb)
-    feap.add_nummernschalter_done_callback(nummernschalter_done_cb)
-    phone.add_event_cb(phone_cb)
+    controller = statemachine.StateMachineController(phone, feap, cfg.dialconfig)
 
     phone.start()
-
     try:
         while True:
             time.sleep(1)
 
-        '''
-        c.queue_event('gabelschalter_up')
-        c.queue_event('nummernschalter_input', 4)
-        c.queue_event('nummernschalter_input', 2)
-        #c.queue_event('gabelschalter_down')
-        #c.queue_event('call_accepted')
-        c.queue_event('timeout')
-        c.queue_event('call_ringing')
-        #c.queue_event('gabelschalter_down')
-        c.queue_event('call_accepted')
-        c.queue_event('call_ended')
-        c.queue_event('timeout')
-        c.queue_event('gabelschalter_down')
-        '''
-
     except KeyboardInterrupt:
         phone.stop()
         feap.set_wecker(False)
diff --git a/statemachine.py b/statemachine.py
new file mode 100644
index 0000000..0b1373a
--- /dev/null
+++ b/statemachine.py
@@ -0,0 +1,327 @@
+import threading
+import Queue as queue
+
+class DialConfiguration(object):
+    def __init__(self, dial_timeout, shortcuts, blacklist):
+        self.dial_timeout = dial_timeout
+        self.shortcuts = shortcuts
+        self.blacklist = blacklist
+
+class IllegalEventError(Exception):
+    pass
+
+
+"""
+An abstract state, needed to define all possible events.
+
+"""
+class AbstractState(object):
+    def on_registration_in_progress(self):
+        raise IllegalEventError()
+
+    def on_registration_successful(self):
+        raise IllegalEventError()
+
+    def on_registration_lost(self):
+        raise IllegalEventError()
+
+    def on_gabelschalter_up(self):
+        raise IllegalEventError()
+
+    def on_gabelschalter_down(self):
+        raise IllegalEventError()
+
+    def on_incoming_call(self):
+        raise IllegalEventError()
+
+    def on_call_ended(self):
+        raise IllegalEventError()
+
+    def on_call_accepted(self):
+        raise IllegalEventError()
+
+    def on_call_ringing(self):
+        raise IllegalEventError()
+
+    def on_invalid_number(self):
+        raise IllegalEventError()
+
+    def on_nummernschalter_active(self):
+        raise IllegalEventError()
+
+    def on_nummernschalter_input(self, num):
+        raise IllegalEventError()
+
+    def on_timeout(self):
+        raise IllegalEventError()
+
+    def leave(self):
+        return None
+
+
+"""
+The basic state that every other state inherits from. It defines default
+behaviour for some events (overriden if necessary).
+
+"""
+class BaseState(AbstractState):
+    def __init__(self, controller):
+        self._controller = controller
+
+    def on_registration_lost(self):
+        return InitState
+
+    def on_gabelschalter_up(self):
+        return None
+
+    def on_gabelschalter_down(self):
+        return None
+
+    def on_incoming_call(self):
+        self._controller.phone.decline_call()
+
+    def on_call_ended(self):
+        # When an incoming call is declined, a call_ended event occurs, which
+        # needs to be ignored, here.
+        return None
+
+    def on_nummernschalter_active(self):
+        return None
+
+    def on_nummernschalter_input(self, num):
+        return None
+
+
+class InitState(BaseState):
+    def __init__(self, controller):
+        super(InitState, self).__init__(controller)
+        self._controller.feap.set_schauzeichen(True)
+
+    def on_registration_in_progress(self):
+        print('registration in progress')
+        return RegisteringState
+
+class RegisteringState(BaseState):
+    def __init__(self, controller):
+        super(RegisteringState, self).__init__(controller)
+
+    def on_registration_successful(self):
+        print('registration successful')
+        self._controller.feap.set_schauzeichen(False)
+        return IdleState
+
+class IdleState(BaseState):
+    def on_incoming_call(self):
+        print('incomfing call')
+        caller = self._controller.phone.get_remote_number()
+        print('From: %s' % caller)
+        if caller in self._controller.dialconfig.blacklist:
+            print('Caller on blacklist - declining')
+            self._controller.phone.decline_call()
+            return CallTerminatingState
+        else:
+            return SchelltState
+
+    def on_gabelschalter_up(self):
+        print('gabel up')
+        return DialingState
+
+class SchelltState(BaseState):
+    def __init__(self, controller):
+        super(SchelltState, self).__init__(controller)
+        self._controller.feap.set_wecker(True)
+
+    def leave(self):
+        self._controller.feap.set_wecker(False)
+
+    def on_gabelschalter_up(self):
+        return AcceptingState
+
+    def on_call_ended(self):
+        return IdleState
+
+class AcceptingState(BaseState):
+    def __init__(self, controller):
+        super(AcceptingState, self).__init__(controller)
+        self._controller.phone.accept_call()
+
+    def on_call_accepted(self):
+        return CallRunningState
+
+class CallTerminatingState(BaseState):
+    def __init__(self, controller):
+        super(CallTerminatingState, self).__init__(controller)
+        self._controller.phone.end_call()
+
+    def on_call_ended(self):
+        return IdleState
+
+    def on_call_accepted(self):
+        return None
+
+class ForgottenState(BaseState):
+    def on_gabelschalter_down(self):
+        return IdleState
+
+class BusyBeepingState(BaseState):
+    def __init__(self, controller):
+        super(BusyBeepingState, self).__init__(controller)
+        self._controller.phone.play_busy_tone()
+
+    def leave(self):
+        self._controller.phone.stop_playing()
+
+    def on_timeout(self):
+        return ForgottenState
+
+    def on_gabelschalter_down(self):
+        return IdleState
+
+class CallRunningState(BaseState):
+    def on_gabelschalter_down(self):
+        return CallTerminatingState
+
+    def on_call_ended(self):
+        return BusyBeepingState
+
+class WecktState(BaseState):
+    def __init__(self, controller):
+        super(WecktState, self).__init__(controller)
+        self._controller.phone.play_ringback_tone()
+
+    def leave(self):
+        self._controller.phone.stop_playing()
+
+    def on_gabelschalter_down(self):
+        return CallTerminatingState
+
+    def on_call_ended(self):
+        return BusyBeepingState
+
+    def on_call_accepted(self):
+        return CallRunningState
+
+class ConnectingState(BaseState):
+    def on_gabelschalter_down(self):
+        return CallTerminatingState
+
+    def on_call_ringing(self):
+        return WecktState
+
+    def on_call_accepted(self):
+        return CallRunningState
+
+    def on_invalid_number(self):
+        # TODO: play sound
+        return BusyBeepingState
+
+    def on_call_ended(self):
+        return BusyBeepingState
+
+class DialingState(BaseState):
+    def __init__(self, controller):
+        super(DialingState, self).__init__(controller)
+        self._controller.phone.play_dial_tone()
+        self.__dial_tone = True
+        self.__number = ''
+
+    def leave(self):
+        if self.__dial_tone:
+            self._controller.phone.stop_playing()
+        self._controller.abort_timeout()
+
+    def on_gabelschalter_down(self):
+        return IdleState
+
+    def on_nummernschalter_active(self):
+        self._controller.abort_timeout()
+        if self.__dial_tone:
+            self._controller.phone.stop_playing()
+
+    def on_nummernschalter_input(self, num):
+        print('nummernschalter: %d' % (num))
+        if self.__dial_tone:
+            self._controller.phone.stop_playing()
+        self.__number += str(num)
+        self._controller.abort_timeout()
+        self._controller.set_timeout(self._controller.dialconfig.dial_timeout * 1000)
+        self._controller.phone.read_text(str(num))
+
+    def on_timeout(self):
+        number = self.__number
+        print 'Dialing number:', number
+        if number in self._controller.dialconfig.shortcuts:
+            number = self._controller.dialconfig.shortcuts[number]
+            print 'shortcut resolved:', number
+        self._controller.phone.call(number)
+        return ConnectingState
+
+
+class StateMachineController(object):
+    def __init__(self, phone, feap, dialconfig):
+        self.__phone = phone
+        self.__feap = feap
+        self.__dialconfig = dialconfig
+
+        self.__state = InitState(self)
+
+        self.__timeout = None
+
+        self.__running = True
+        self.__evqueue = queue.Queue()
+        self.__evthread = threading.Thread(target=self.__event_dispatcher)
+        self.__evthread.start()
+
+    def __event_dispatcher(self):
+        while self.__running:
+            (evname, evargs, evkwargs) = self.__evqueue.get()
+            if not evname:
+                return
+
+            print('!!! event: %s' % (evname))
+            handler = getattr(self.__state, 'on_%s' % (evname))
+            try:
+                newstate = handler(*evargs, **evkwargs)
+            except IllegalEventError:
+                print('illegal event occured!!!!!!!!!!!!!!!!!!!!', self.__state.__class__.__name__)
+            if not newstate:
+                continue
+
+            self.__state.leave()
+            self.abort_timeout()
+
+            oldstate = self.__state.__class__
+            print('%s -> %s' % (oldstate.__name__, newstate.__name__))
+            self.__state = newstate(self)
+
+    def queue_event(self, evname, *evargs, **evkwargs):
+        if not hasattr(AbstractState, 'on_%s' % (evname)):
+            raise ValueError('Illegal event name: %s' % (evname))
+        self.__evqueue.put((evname, evargs, evkwargs))
+
+    def set_timeout(self, timeout):
+        self.__timeout = threading.Timer(timeout/1000, self.queue_event, args=['timeout'])
+        self.__timeout.start()
+
+    def abort_timeout(self):
+        if self.__timeout:
+            self.__timeout.cancel()
+        self.__timeout = None
+
+    @property
+    def phone(self):
+        return self.__phone
+
+    @property
+    def feap(self):
+        return self.__feap
+
+    @property
+    def dialconfig(self):
+        return self.__dialconfig
+
+    def stop(self, hard=False):
+        if hard:
+            self.__running = False
+        self.__evqueue.put((None, None, None))
+