diff --git a/src/Logger.py b/src/Logger.py
new file mode 100644
index 0000000..46c5129
--- /dev/null
+++ b/src/Logger.py
@@ -0,0 +1,85 @@
+# Logger.py  14/05/2016  D.J.Whale
+#
+# A simple logger - logs to file.
+
+
+from energenie import OpenThings
+import os, time
+
+LOG_FILENAME = "energenie.csv"
+HEADINGS = 'timestamp,mfrid,prodid,sensorid,flags,switch,voltage,freq,reactive,real'
+
+
+log_file = None
+
+def trace(msg):
+    print(str(msg))
+
+
+def logMessage(msg):
+    global log_file
+
+    if log_file == None:
+        if not os.path.isfile(LOG_FILENAME):
+            log_file = open(LOG_FILENAME, 'w')
+            log_file.write(HEADINGS + '\n')
+        else:
+            log_file = open(LOG_FILENAME, 'a') # append
+
+    # get the header
+    header    = msg['header']
+    timestamp = time.time()
+    mfrid     = header['mfrid']
+    productid = header['productid']
+    sensorid  = header['sensorid']
+
+    # set defaults for any data that doesn't appear in this message
+    # but build flags so we know which ones this contains
+    flags = [0 for i in range(7)]
+    switch = None
+    voltage = None
+    freq = None
+    reactive = None
+    real = None
+    apparent = None
+    current = None
+
+    # capture any data that we want
+    #print(msg)
+    for rec in msg['recs']:
+        paramid = rec['paramid']
+        try:
+            value = rec['value']
+        except:
+            value = None
+
+        if   paramid == OpenThings.PARAM_SWITCH_STATE:
+            switch = value
+            flags[0] = 1
+        elif paramid == OpenThings.PARAM_VOLTAGE:
+            flags[1] = 1
+            voltage = value
+        elif paramid == OpenThings.PARAM_FREQUENCY:
+            flags[2] = 1
+            freq = value
+        elif paramid == OpenThings.PARAM_REACTIVE_POWER:
+            flags[3] = 1
+            reactive = value
+        elif paramid == OpenThings.PARAM_REAL_POWER:
+            flags[4] = 1
+            real = value
+        elif paramid == OpenThings.PARAM_APPARENT_POWER:
+            flags[5] = 1
+            apparent = value
+        elif paramid == OpenThings.PARAM_CURRENT:
+            flags[6] = 1
+            current = value
+
+    # generate a line of CSV
+    flags = "".join([str(a) for a in flags])
+    csv = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" % (timestamp, mfrid, productid, sensorid, flags, switch, voltage, freq, reactive, real, apparent, current)
+    log_file.write(csv + '\n')
+    log_file.flush()
+    #trace(csv) # testing
+
+# END
diff --git a/src/energenie/Messages.py b/src/energenie/Messages.py
index 7dddd3f..aaac787 100644
--- a/src/energenie/Messages.py
+++ b/src/energenie/Messages.py
@@ -42,4 +42,16 @@
 }
 
 
+def send_join_ack(radio, mfrid, productid, sensorid):
+    # send back a JOIN ACK, so that join light stops flashing
+    response = OpenThings.alterMessage(JOIN_ACK,
+        header_mfrid=mfrid,
+        header_productid=productid,
+        header_sensorid=sensorid)
+    p = OpenThings.encode(response)
+    radio.transmitter()
+    radio.transmit(p)
+    radio.receiver()
+
+
 # END
diff --git a/src/energenie/Registry.py b/src/energenie/Registry.py
new file mode 100644
index 0000000..eba308b
--- /dev/null
+++ b/src/energenie/Registry.py
@@ -0,0 +1,50 @@
+# Registry.py  14/05/2016  D.J.Whale
+#
+# A simple registry of connected devices.
+#
+# NOTE: This is an initial, non persisted implementation only
+
+import time
+import Devices
+
+directory = {}
+
+def allkeys(d):
+    result = ""
+    for k in d:
+        if len(result) != 0:
+            result += ','
+        result += str(k)
+    return result
+
+
+def updateDirectory(message):
+    """Update the local directory with information about this device"""
+    now      = time.time()
+    header   = message["header"]
+    sensorId = header["sensorid"]
+
+    if not directory.has_key(sensorId):
+        # new device discovered
+        desc = Devices.getDescription(header["mfrid"], header["productid"])
+        print("ADD device:%s %s" % (hex(sensorId), desc))
+        directory[sensorId] = {"header": message["header"]}
+        #trace(allkeys(directory))
+
+    directory[sensorId]["time"] = now
+    #TODO would be good to keep recs, but need to iterate through all and key by paramid,
+    #not as a list index, else merging will be hard.
+
+
+def size():
+    return len(directory)
+
+
+def get_sensorids():
+    return directory.keys()
+
+
+def get_info(sensor_id):
+    return directory[sensor_id]
+
+# END
diff --git a/src/energenie/drv/radio.c b/src/energenie/drv/radio.c
index b8ea7ec..495a556 100644
--- a/src/energenie/drv/radio.c
+++ b/src/energenie/drv/radio.c
@@ -5,6 +5,22 @@
  * https://energenie4u.co.uk/index.phpcatalogue/product/ENER314-RT
  */
 
+/* TODO
+
+push the FSK configuration into radio.c
+remove radio.py (the old version of the radio interface)
+implement FSK transmit in radio.c and test with switch.py and hard coded ID number
+radio_modulation fix for FSK
+move radio.py modulation to radio2.py modulation as it is better?
+
+contrive a switch.py that only transmits
+hard code device address into the dictionary
+disable the call to the receive check
+run the code, it should turn the switch on and off repeatedly.
+
+
+*/
+
 
 /***** INCLUDES *****/
 
diff --git a/src/legacy.py b/src/legacy.py
index 0e7b7b2..f92e06c 100644
--- a/src/legacy.py
+++ b/src/legacy.py
@@ -145,6 +145,5 @@
     finally:
         radio.finished()
 
-
 # END
 
diff --git a/src/monitor.py b/src/monitor.py
index 43ed0ee..8ac2945 100644
--- a/src/monitor.py
+++ b/src/monitor.py
@@ -9,133 +9,21 @@
 # However, it will log all messages from MiHome monitor, adaptor plus and house monitor
 # to a CSV log file, so could be the basis for a non-controlling energy logging app.
 
-import time
+from energenie import Registry, Devices, Messages, OpenThings
+from energenie import radio
 
-from energenie import OpenThings
-from energenie import Devices, Messages, radio
-import os
-
-LOG_FILENAME = "energenie.csv"
+import Logger
 
 def warning(msg):
     print("warning:%s" % str(msg))
 
+
 def trace(msg):
     print("monitor:%s" % str(msg))
 
-log_file = None
-
-def logMessage(msg):
-    HEADINGS = 'timestamp,mfrid,prodid,sensorid,flags,switch,voltage,freq,reactive,real'
-
-    global log_file
-    if log_file == None:
-        if not os.path.isfile(LOG_FILENAME):
-            log_file = open(LOG_FILENAME, 'w')
-            log_file.write(HEADINGS + '\n')
-        else:
-            log_file = open(LOG_FILENAME, 'a') # append
-
-    # get the header
-    header    = msg['header']
-    timestamp = time.time()
-    mfrid     = header['mfrid']
-    productid = header['productid']
-    sensorid  = header['sensorid']
-
-    # set defaults for any data that doesn't appear in this message
-    # but build flags so we know which ones this contains
-    flags = [0 for i in range(7)]
-    switch = None
-    voltage = None
-    freq = None
-    reactive = None
-    real = None
-    apparent = None
-    current = None
-
-    # capture any data that we want
-    #print(msg)
-    for rec in msg['recs']:
-        paramid = rec['paramid']
-        try:
-            value = rec['value']
-        except:
-            value = None
-            
-        if   paramid == OpenThings.PARAM_SWITCH_STATE:
-            switch = value
-            flags[0] = 1
-        elif paramid == OpenThings.PARAM_VOLTAGE:
-            flags[1] = 1
-            voltage = value
-        elif paramid == OpenThings.PARAM_FREQUENCY:
-            flags[2] = 1
-            freq = value
-        elif paramid == OpenThings.PARAM_REACTIVE_POWER:
-            flags[3] = 1
-            reactive = value
-        elif paramid == OpenThings.PARAM_REAL_POWER:
-            flags[4] = 1
-            real = value
-        elif paramid == OpenThings.PARAM_APPARENT_POWER:
-            flags[5] = 1
-            apparent = value
-        elif paramid == OpenThings.PARAM_CURRENT:
-            flags[6] = 1
-            current = value
-
-    # generate a line of CSV
-    flags = "".join([str(a) for a in flags])
-    csv = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" % (timestamp, mfrid, productid, sensorid, flags, switch, voltage, freq, reactive, real, apparent, current)
-    log_file.write(csv + '\n')
-    log_file.flush()
-    trace(csv) # testing
-
 
 #----- TEST APPLICATION -------------------------------------------------------
 
-directory = {}
-
-def allkeys(d):
-    result = ""
-    for k in d:
-        if len(result) != 0:
-            result += ','
-        result += str(k)
-    return result
-
-        
-def updateDirectory(message):
-    """Update the local directory with information about this device"""
-    now      = time.time()
-    header   = message["header"]
-    sensorId = header["sensorid"]
-
-    if not directory.has_key(sensorId):
-        # new device discovered
-        desc = Devices.getDescription(header["mfrid"], header["productid"])
-        print("ADD device:%s %s" % (hex(sensorId), desc))
-        directory[sensorId] = {"header": message["header"]}
-        #trace(allkeys(directory))
-
-    directory[sensorId]["time"] = now
-    #TODO would be good to keep recs, but need to iterate through all and key by paramid,
-    #not as a list index, else merging will be hard.
-
-
-def send_join_ack(mfrid, productid, sensorid):
-    # send back a JOIN ACK, so that join light stops flashing
-    response = OpenThings.alterMessage(Messages.JOIN_ACK,
-        header_mfrid=mfrid,
-        header_productid=productid,
-        header_sensorid=sensorid)
-    p = OpenThings.encode(response)
-    radio.transmitter()
-    radio.transmit(p)
-    radio.receiver()
-
-
 def monitor_loop():
     """Capture any incoming messages and log to CSV file"""
 
@@ -154,9 +42,9 @@
                       
             OpenThings.showMessage(decoded)
             # Any device that reports will be added to the non-persistent directory
-            updateDirectory(decoded)
+            Registry.update(decoded)
             #trace(decoded)
-            logMessage(decoded)
+            Logger.logMessage(decoded)
 
             # Process any JOIN messages by sending back a JOIN-ACK to turn the LED off
             if len(decoded["recs"]) == 0:
@@ -170,8 +58,7 @@
                     mfrid     = header["mfrid"]
                     productid = header["productid"]
                     sensorid  = header["sensorid"]
-                    send_join_ack(mfrid, productid, sensorid)
-
+                    Messages.send_join_ack(radio, mfrid, productid, sensorid)
 
 
 if __name__ == "__main__":
diff --git a/src/switch.py b/src/switch.py
index f283936..9a19a39 100644
--- a/src/switch.py
+++ b/src/switch.py
@@ -10,130 +10,88 @@
 # Don't expect this to be a good starting point for an application.
 # Consider waiting for me to finish developing the device object interface first.
 
-import time
-
-from energenie import OpenThings
-from energenie import Devices, Messages, radio
+from energenie import Devices, Messages, Registry, OpenThings
+from energenie import radio
 from Timer import Timer
 
+
 # Increase this if you have lots of switches, so that the receiver has enough
 # time to receive update messages, otherwise your devices won't make it into
 # the device directory.
 TX_RATE = 10 # seconds between each switch change cycle
 
+
 def warning(msg):
     print("warning:%s" % str(msg))
 
+
 def trace(msg):
     print("monitor:%s" % str(msg))
 
 
 #----- TEST APPLICATION -------------------------------------------------------
 
-directory = {}
+def switch_sniff_loop():
+    """Listen to sensor messages and add them to the Registry"""
 
-def allkeys(d):
-    result = ""
-    for k in d:
-        if len(result) != 0:
-            result += ','
-        result += str(k)
-    return result
+    # See if there is a payload, and if there is, process it
+    if radio.isReceiveWaiting():
+        #trace("receiving payload")
+        payload = radio.receive()
+        try:
+            decoded = OpenThings.decode(payload)
+        except OpenThings.OpenThingsException as e:
+            warning("Can't decode payload:" + str(e))
+            return
 
-        
-def updateDirectory(message):
-    """Update the local directory with information about this device"""
-    now      = time.time()
-    header   = message["header"]
-    sensorId = header["sensorid"]
+        OpenThings.showMessage(decoded)
+        # Any device that reports will be added to the non-persistent directory
+        Registry.update(decoded)
+        #trace(decoded)
 
-    if not directory.has_key(sensorId):
-        # new device discovered
-        desc = Devices.getDescription(header["mfrid"], header["productid"])
-        print("ADD device:%s %s" % (hex(sensorId), desc))
-        directory[sensorId] = {"header": message["header"]}
-        #trace(allkeys(directory))
-
-    directory[sensorId]["time"] = now
-    #TODO would be good to keep recs, but need to iterate through all and key by paramid,
-    #not as a list index, else merging will be hard.
-
-
-def send_join_ack(mfrid, productid, sensorid):
-    # send back a JOIN ACK, so that join light stops flashing
-    response = OpenThings.alterMessage(Messages.JOIN_ACK,
-        header_mfrid=mfrid,
-        header_productid=productid,
-        header_sensorid=sensorid)
-    p = OpenThings.encode(response)
-    radio.transmitter()
-    radio.transmit(p)
-    radio.receiver()
-
-
-def switch_loop():
-    """Listen to sensor messages, and turn switches on and off every few seconds"""
-
-    # Define the schedule of message polling
-    sendSwitchTimer    = Timer(TX_RATE, 1)   # every n seconds offset by initial 1
-    switch_state       = 0             # OFF
-    radio.receiver()
-
-    while True:
-        # See if there is a payload, and if there is, process it
-        if radio.isReceiveWaiting():
-            #trace("receiving payload")
-            payload = radio.receive()
-            try:
-                decoded = OpenThings.decode(payload)
-            except OpenThings.OpenThingsException as e:
-                warning("Can't decode payload:" + str(e))
-                continue
-                      
-            OpenThings.showMessage(decoded)
-            # Any device that reports will be added to the non-persistent directory
-            updateDirectory(decoded)
-            #trace(decoded)
-
-            # Process any JOIN messages by sending back a JOIN-ACK to turn the LED off
-            if len(decoded["recs"]) == 0:
-                # handle messages with zero recs in them silently
-                print("Empty record:%s" % decoded)
-            else:
-                # assume only 1 rec in a join, for now
-                #TODO: use OpenThings.getFromMessage("header_mfrid")
-                if decoded["recs"][0]["paramid"] == OpenThings.PARAM_JOIN:
-                    header    = decoded["header"]
-                    mfrid     = header["mfrid"]
-                    productid = header["productid"]
-                    sensorid  = header["sensorid"]
-                    send_join_ack(mfrid, productid, sensorid)
-
-
-        # Toggle the switch on all devices in the directory
-        if len(directory) > 0 and sendSwitchTimer.check():
-            print("transmit")
-            radio.transmitter()
-
-            for sensorid in directory.keys():
-                # Only try to toggle the switch for devices that actually have a switch
-                header = directory[sensorid]["header"]
-                mfrid = header["mfrid"]
+        # Process any JOIN messages by sending back a JOIN-ACK to turn the LED off
+        if len(decoded["recs"]) == 0:
+            # handle messages with zero recs in them silently
+            print("Empty record:%s" % decoded)
+        else:
+            # assume only 1 rec in a join, for now
+            #TODO: use OpenThings.getFromMessage("header_mfrid")
+            if decoded["recs"][0]["paramid"] == OpenThings.PARAM_JOIN:
+                header    = decoded["header"]
+                mfrid     = header["mfrid"]
                 productid = header["productid"]
+                sensorid  = header["sensorid"]
+                Messages.send_join_ack(radio, mfrid, productid, sensorid)
 
-                if Devices.hasSwitch(mfrid, productid):
-                    request = OpenThings.alterMessage(Messages.SWITCH,
-                        header_sensorid=sensorid,
-                        recs_0_value=switch_state)
-                    p = OpenThings.encode(request)
-                    print("Sending switch message to %s %s" % (hex(productid), hex(sensorid)))
-                    # Transmit multiple times, hope one of them gets through
-                    for i in range(4):
-                        radio.transmit(p)
 
-            radio.receiver()
-            print("receive")
-            switch_state = (switch_state+1) % 2 # toggle
+def switch_toggle_loop():
+    """Toggle the switch on all devices in the directory"""
+
+    global switch_state
+
+    if len(Registry.size()) > 0 and sendSwitchTimer.check():
+        print("transmit")
+        radio.transmitter()
+
+        for sensorid in Registry.get_sensorids():
+            # Only try to toggle the switch for devices that actually have a switch
+            header = Registry.get_info(sensorid)["header"]
+            mfrid = header["mfrid"]
+            productid = header["productid"]
+
+            if Devices.hasSwitch(mfrid, productid):
+                request = OpenThings.alterMessage(Messages.SWITCH,
+                    header_sensorid=sensorid,
+                    recs_0_value=switch_state)
+                p = OpenThings.encode(request)
+                print("Sending switch message to %s %s" % (hex(productid), hex(sensorid)))
+                # Transmit multiple times, hope one of them gets through
+                for i in range(4):
+                    radio.transmit(p)
+
+        radio.receiver()
+        print("receive")
+        switch_state = (switch_state+1) % 2 # toggle
         
 
 if __name__ == "__main__":
@@ -142,8 +100,14 @@
     radio.init()
     OpenThings.init(Devices.CRYPT_PID)
 
+    sendSwitchTimer    = Timer(TX_RATE, 1)   # every n seconds offset by initial 1
+    switch_state       = 0 # OFF
+    radio.receiver()
+
     try:
-        switch_loop()
+        while True:
+            switch_sniff_loop()
+            switch_toggle_loop()
 
     finally:
         radio.finished()