diff --git a/src/energenie/drv/hrfm69.c b/src/energenie/drv/hrfm69.c
index 2f89775..1a85575 100644
--- a/src/energenie/drv/hrfm69.c
+++ b/src/energenie/drv/hrfm69.c
@@ -9,6 +9,9 @@
 #include "spi.h"
 #include "trace.h"
 
+
+/***** LOW LEVEL REGISTER INTERFACE ******************************************/
+
 // Write an 8 bit value to a register
 void HRF_writereg(uint8_t addr, uint8_t data)
 {
@@ -48,11 +51,7 @@
 }
 
 
-//TODO: where is the buffer memory defined?
-//perhaps pass in buffer memory and maxlen
-//how do we know the actual length of buffer written to?
-//pass in ptr to len variable
-uint8_t* HRF_readfifo_burst(void)
+void HRF_readfifo_burst(uint8_t* buf, uint8_t len)
 {
 //def HRF_readfifo_burst():
 //    """Read bytes from the payload FIFO using burst read"""
@@ -71,7 +70,6 @@
 //        buf.append(data)
 //    spi.deselect()
 //    return buf
-    return (void*)0; // TODO
 }
 
 
@@ -93,19 +91,17 @@
 }
 
 
-// Wait for HRF to be ready after last command
-void HRF_wait_ready(void)
+// Clear any data in the HRF payload FIFO, by reading until empty
+void HRF_clear_fifo(void)
 {
-    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY);
+    while ((HRF_readreg(HRF_ADDR_IRQFLAGS2) & HRF_MASK_FIFONOTEMPTY) == HRF_MASK_FIFONOTEMPTY)
+    {
+        HRF_readreg(HRF_ADDR_FIFO);
+    }
 }
 
 
-// Wait for the HRF to be ready, and ready for tx, after last command
-void HRF_wait_txready(void)
-{
-    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY);
-}
-
+/***** HIGH LEVEL PAYLOAD INTERFACE ******************************************/
 
 // Change the operating mode of the HRF radi
 void HRF_change_mode(uint8_t mode)
@@ -114,16 +110,31 @@
 }
 
 
-// Clear any data in the HRF payload FIFO, by reading until empty
-void HRF_clear_fifo(void)
+// Wait for HRF to be ready after last command
+void HRF_wait_ready(void)
 {
-    while ((HRF_readreg(HRF_ADDR_IRQFLAGS2) & HRF_MASK_FIFONOTEMPTY) == HRF_MASK_FIFONOTEMPTY)
+    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY);
+}
+
+
+// Load a table of configuration values into HRF registers
+void HRF_config(HRF_CONFIG_REC* config, uint8_t count)
+{
+    while (count-- != 0)
     {
-        HRF_readreg(HRF_ADDR_FIFO);
+        HRF_writereg(config->addr, config->value);
+        config++;
     }
 }
 
 
+// Wait for the HRF to be ready, and ready for tx, after last command
+void HRF_wait_txready(void)
+{
+    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY);
+}
+
+
 // Check if there is a payload in the FIFO waiting to be processed
 HRF_RESULT HRF_check_payload(void)
 {
@@ -135,14 +146,9 @@
 }
 
 
-//TODO: unnecessary level of runtime indirection?
-//TODO: where is the buffer memory defined?
-//perhaps pass in buffer memory and maxlen
-//how do we know the actual length of buffer written to?
-//pass in ptr to len variable
-uint8_t* HRF_receive_payload(void)
+void HRF_receive_payload(uint8_t* buf, uint8_t len)
 {
-    return HRF_readfifo_burst();
+    return HRF_readfifo_burst(buf, len);
 }
 
 
@@ -159,15 +165,5 @@
 }
 
 
-// Load a table of configuration values into HRF registers
-void HRF_config(HRF_CONFIG_REC* config, uint8_t count)
-{
-    while (count-- != 0)
-    {
-        HRF_writereg(config->addr, config->value);
-        config++;
-    }
-}
+/***** END OF FILE *****/
 
-
-//# END
diff --git a/src/energenie/drv/hrfm69.h b/src/energenie/drv/hrfm69.h
index 253dfa9..986d4d3 100644
--- a/src/energenie/drv/hrfm69.h
+++ b/src/energenie/drv/hrfm69.h
@@ -103,44 +103,39 @@
 #define HRF_VAL_FIFOTHRESH30           0x1E	// Condition to start packet transmission: wait for 30 bytes in FIFO
 
 
+/* Low level register interface */
+
 extern void HRF_writereg(uint8_t addr, uint8_t data);
 
 extern uint8_t HRF_readreg(uint8_t addr);
 
 extern void HRF_writefifo_burst(uint8_t* buf, uint8_t len);
 
-//TODO unnecessary level of runtime indirection?
-//TODO where is the buffer memory defined?
-//perhaps pass in buffer memory and maxlen
-//how do we know the actual length of buffer written to?
-//pass in ptr to len variable
-extern uint8_t* HRF_readfifo_burst(void);
+extern void HRF_readfifo_burst(uint8_t* buf, uint8_t len);
 
 extern HRF_RESULT HRF_checkreg(uint8_t addr, uint8_t mask, uint8_t value);
 
 extern void HRF_pollreg(uint8_t addr, uint8_t mask, uint8_t value);
 
+extern void HRF_clear_fifo(void);
+
+
+/* High level payload interface */
+
+extern void HRF_change_mode(uint8_t mode);
+
 extern void HRF_wait_ready(void);
 
 extern void HRF_wait_txready(void);
 
-extern void HRF_change_mode(uint8_t mode);
-
-extern void HRF_clear_fifo(void);
+extern void HRF_config(HRF_CONFIG_REC* config, uint8_t len);
 
 extern HRF_RESULT HRF_check_payload(void);
 
-
-//TODO unnecessary level of runtime indirection?
-//TODO where is the buffer memory defined?
-//perhaps pass in buffer memory and maxlen
-//how do we know the actual length of buffer written to?
-//pass in ptr to len variable
-extern uint8_t* HRF_receive_payload(void);
+extern void HRF_receive_payload(uint8_t* buf, uint8_t len);
 
 extern void HRF_send_payload(uint8_t* payload, uint8_t len);
 
-extern void HRF_config(HRF_CONFIG_REC* config, uint8_t len);
 
 #endif
 
diff --git a/src/energenie/drv/hrfm69_test.c b/src/energenie/drv/hrfm69_test.c
index 452a3f3..3a99674 100644
--- a/src/energenie/drv/hrfm69_test.c
+++ b/src/energenie/drv/hrfm69_test.c
@@ -54,7 +54,9 @@
 
 static uint8_t read_ver(void);
 static void reset(void);
+
 void hrf_test_send_ook_tone(void);
+void hrf_test_send_energenie_ook_switch(void);
 
 
 #if defined(HRFM69_TEST)
@@ -86,8 +88,9 @@
 
     TRACE_OUTS("testing...\n");
     hrf_test_send_ook_tone();
-    //spi_finished();
+    //hrf_test_send_energenie_ook_switch();
 
+    //spi_finished();
     gpio_finished();
 
     return 0;
@@ -115,30 +118,32 @@
 
 
 HRF_CONFIG_REC config_OOK[] = {
-    {HRF_ADDR_REGDATAMODUL,       HRF_VAL_REGDATAMODUL_OOK},	 // modulation scheme OOK
-    {HRF_ADDR_FDEVMSB,            0},                            // frequency deviation -> 0kHz
-    {HRF_ADDR_FDEVLSB,            0},                            // frequency deviation -> 0kHz
-    {HRF_ADDR_FRMSB,              HRF_VAL_FRMSB433},             // carrier freq -> 433.92MHz 0x6C7AE1
-    {HRF_ADDR_FRMID,              HRF_VAL_FRMID433},             // carrier freq -> 433.92MHz 0x6C7AE1
-    {HRF_ADDR_FRLSB,              HRF_VAL_FRLSB433},             // carrier freq -> 433.92MHz 0x6C7AE1
-    {HRF_ADDR_RXBW,               HRF_VAL_RXBW120},              // channel filter bandwidth 120kHz
-    {HRF_ADDR_BITRATEMSB, 	  0x1A},                         // 4800b/s
-    {HRF_ADDR_BITRATELSB,         0x0B},                         // 4800b/s
-    {HRF_ADDR_PREAMBLELSB, 	  0},                            // preamble size LSB 0
-    {HRF_ADDR_SYNCCONFIG, 	  HRF_VAL_SYNCCONFIG0},		 // Size of the Sync word
-    //{HRF_ADDR_SYNCVALUE1,         0x81},
-    //{HRF_ADDR_SYNCVALUE2,         0x00},
-    //{HRF_ADDR_SYNCVALUE3,         0x00},
-    //{HRF_ADDR_SYNCVALUE4,         0x00}, 
-    {HRF_ADDR_PACKETCONFIG1,      0x00},	                 // Fixed length, no Manchester coding
-    {HRF_ADDR_PAYLOADLEN, 	  2},	                         // Payload Length
-    {HRF_ADDR_FIFOTHRESH, 	  1}                             // Condition to start packet transmission: exceeds 7 bytes in FIFO
+    {HRF_ADDR_REGDATAMODUL,   HRF_VAL_REGDATAMODUL_OOK},  // modulation scheme OOK
+    {HRF_ADDR_FDEVMSB,        0},                         // frequency deviation:0kHz
+    {HRF_ADDR_FDEVLSB,        0},                         // frequency deviation:0kHz
+    {HRF_ADDR_FRMSB,          HRF_VAL_FRMSB433},          // carrier freq:433.92MHz 0x6C7AE1
+    {HRF_ADDR_FRMID,          HRF_VAL_FRMID433},          // carrier freq:433.92MHz 0x6C7AE1
+    {HRF_ADDR_FRLSB,          HRF_VAL_FRLSB433},          // carrier freq:433.92MHz 0x6C7AE1
+    {HRF_ADDR_RXBW,           HRF_VAL_RXBW120},           // channel filter bandwidth:120kHz
+    {HRF_ADDR_BITRATEMSB,     0x1A},                      // bitrate:4800b/s
+    {HRF_ADDR_BITRATELSB,     0x0B},                      // bitrate:4800b/s
+    {HRF_ADDR_PREAMBLELSB, 	  0},                         // preamble size LSB
+    {HRF_ADDR_SYNCCONFIG,     HRF_VAL_SYNCCONFIG0},       // Size of sync word
+    {HRF_ADDR_PACKETCONFIG1,  0x00},                      // Fixed length, no Manchester coding
+    //{HRF_ADDR_PAYLOADLEN,     2},                         // Payload Length
+    //{HRF_ADDR_FIFOTHRESH,     1}                          // Start tx when this is exceeded
 };
 #define CONFIG_OOK_COUNT (sizeof(config_OOK)/sizeof(HRF_CONFIG_REC))
 
+
 // Send a test tone using OOK modulation
 void hrf_test_send_ook_tone(void)
 {
+    /* two blips, to help prove the 01 at start */
+    static uint8_t payload[] = {
+        0x41, 0x40
+    };
+
     int i;
 
     TRACE_OUTS("standby mode\n");
@@ -147,6 +152,8 @@
 
     TRACE_OUTS("config\n");
     HRF_config(config_OOK, CONFIG_OOK_COUNT);
+    HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload));
+    HRF_writereg(HRF_ADDR_FIFOTHRESH, sizeof(payload)-1);
 
     TRACE_OUTS("transmitter mode\n");
     HRF_change_mode(HRF_MODE_TRANSMITTER);
@@ -165,20 +172,24 @@
     TRACE_OUTS("wait for txready in irqflags1\n");
     HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY);
 
-    /* A regular tone */
-    static uint8_t payload[] = {
-        0x81, 0x00 //0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
-    };
 
+    //NOTE: This uses a payloadlen of 2, and polls PACKETSENT in the repeat loop.
+    //A better way to do it would be to set payloadlen to the total length,
+    //check FIFOLEVEL < limit before putting more into FIFO
+    //and check PACKETSENT at the end. That's how the original C code does it,
+    //but there seems to be an error in the payload length calculation.
     while (1)
     {
         for (i=0; i<1; i++)
         {
             TRACE_OUTS("tx\n");
             HRF_writefifo_burst(payload, sizeof(payload));
+            //TODO: should check FIFO level here??
             HRF_pollreg(HRF_ADDR_IRQFLAGS2, HRF_MASK_PACKETSENT, HRF_MASK_PACKETSENT); // wait for Packet sent
         }
 
+        //TODO: should check PACKETSENT here??
+
         uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1);
         uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2);
 
@@ -196,6 +207,130 @@
         }
         delaysec(1);
     }
+
+    //NOTE: packetsent is only cleared when exiting TX (i.e. to STANDBY or RECEIVE)
+}
+
+
+/* Note, D0123 are transmitted as D3210
+    # Coded as per the (working) C code would be:
+    # b 3210
+    #   0000 UNUSED         0
+    #   0001 UNUSED         1
+    #   0010 socket 4 off   2
+    #   0011 socket 4 on    3
+    #   0100 UNUSED         4
+    #   0101 UNUSED         5
+    #   0110 socket 2 off   6
+    #   0111 socket 2 on    7
+    #   1000 UNUSED         8
+    #   1001 UNUSED         9
+    #   1010 socket 3 off   A
+    #   1011 socket 3 on    B
+    #   1100 all off        C
+    #   1101 all on         D
+    #   1110 socket 1 off   E
+    #   1111 socket 1 on    F
+*/
+
+
+// A hard coded test of switching an Energenie switch on and off
+void hrf_test_send_energenie_ook_switch(void)
+{
+    /* manual preamble, 20 bit encoded address, 4 encoded data bits */
+    static uint8_t payload[17] = {
+        0x00,                   // pad away from the radio inserted 01 at start
+        0x80, 0x00, 0x00, 0x00, // preamble pulse with timing violation gap
+        // Energenie 'random' 20 bit address is 6C6C6
+        // 0110 1100 0110 1100 0110
+        // 0 encoded as 8 (1000)
+        // 1 encoded as E (1110)
+        0x8E, 0xE8,  0xEE, 0x88,  0x8E, 0xE8,  0xEE, 0x88,  0x8E, 0xE8,
+        // Energenie 'switch 1 ON' command  F 1111  (0xEE, 0xEE)
+        0xEE, 0xEE
+        // Energenie 'switch 1 OFF' command E 1110  (0xEE, 0xE8)
+        //0xEE, 0xE8
+    };
+/* Last byte of the payload for switch 1 */
+#define ON  0xEE
+#define OFF 0xE8
+#define REPEATS 1
+
+    int i;
+
+    TRACE_OUTS("standby mode\n");
+    HRF_change_mode(HRF_MODE_STANDBY);
+    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY);
+
+    TRACE_OUTS("config\n");
+    HRF_config(config_OOK, CONFIG_OOK_COUNT);
+    HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload));
+    HRF_writereg(HRF_ADDR_FIFOTHRESH, sizeof(payload)-1);
+
+    TRACE_OUTS("transmitter mode\n");
+    HRF_change_mode(HRF_MODE_TRANSMITTER);
+    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY);
+
+    uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1);
+    uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2);
+    TRACE_OUTS("irqflags1,2=");
+    TRACE_OUTN(irqflags1);
+    TRACE_OUTC(',');
+    TRACE_OUTN(irqflags2);
+    TRACE_NL();
+
+    TRACE_OUTS("wait for txready in irqflags1\n");
+    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY);
+
+
+    uint8_t last_byte = ON;
+
+    while (1)
+    {
+        payload[sizeof(payload)-1] = last_byte;
+        TRACE_OUTS("tx:");
+        TRACE_OUTN(last_byte);
+        TRACE_NL();
+
+        for (i=0; i<REPEATS; i++)
+        {
+            HRF_writefifo_burst(payload, sizeof(payload));
+            //TODO: should check FIFO level here?
+            //if so, calculate payloadlen based on repeat count and payload size
+            HRF_pollreg(HRF_ADDR_IRQFLAGS2, HRF_MASK_PACKETSENT, HRF_MASK_PACKETSENT); // wait for Packet sent
+        }
+
+        //TODO: should check packetsent here?
+
+        uint8_t irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1);
+        uint8_t irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2);
+
+        TRACE_OUTS("irqflags1,2=");
+        TRACE_OUTN(irqflags1);
+        TRACE_OUTC(',');
+        TRACE_OUTN(irqflags2);
+        TRACE_NL();
+
+        if (((irqflags2 & HRF_MASK_FIFONOTEMPTY) != 0) || ((irqflags2 & HRF_MASK_FIFOOVERRUN) != 0))
+        {
+            TRACE_OUTN(irqflags2);
+            TRACE_NL();
+            TRACE_FAIL("FIFO not empty or overrun at end of burst");
+        }
+
+        delaysec(1);
+
+        /* Toggle next switch state */
+        if (last_byte == OFF)
+        {
+            last_byte = ON;
+        }
+        else
+        {
+            last_byte = OFF;
+        }
+    }
+    //NOTE: packetsent is only cleared when exiting TX (i.e. to STANDBY or RECEIVE)
 }
 
 
diff --git a/src/energenie/radio.py b/src/energenie/radio.py
index 562e720..30c5193 100644
--- a/src/energenie/radio.py
+++ b/src/energenie/radio.py
@@ -105,11 +105,13 @@
 VAL_PACKETCONFIG1OOK        = 0		# Fixed length, no Manchester coding
 VAL_PAYLOADLEN255           = 0xFF	# max Length in RX, not used in Tx
 VAL_PAYLOADLEN66            = 66	# max Length in RX, not used in Tx
+##TODO: This calculation looks wrong, inherited from the original C code.
+#It accounts for the 'magic' byte that C used for the SPI address.
 VAL_PAYLOADLEN_OOK          = (13 + 8 * 17)	# Payload Length
 VAL_NODEADDRESS01           = 0x01	# Node address used in address filtering
 VAL_NODEADDRESS04           = 0x04	# Node address used in address filtering
-VAL_FIFOTHRESH1             = 0x81	# Condition to start packet transmission: at least one byte in FIFO
-VAL_FIFOTHRESH30            = 0x1E	# Condition to start packet transmission: wait for 30 bytes in FIFO
+VAL_FIFOTHRESH1             = 0x81	# Condition to start packet transmission: at least two? bytes in FIFO
+VAL_FIFOTHRESH30            = 0x1E	# Condition to start packet transmission: wait for >30 bytes in FIFO
 
 
 #----- HOPERF RADIO INTERFACE -------------------------------------------------
@@ -332,21 +334,42 @@
 #}
 
 
+# first payload
+# (radio sync 4 bytes, not counted)
+# address 10 bytes
+# command 2 bytes
+# i.e. 12 bytes
+# so, >30 is 2 and a bit payloads loaded.
+# 66 byte FIFO size
+# so that means FIFO roughly half full before starts tx,
+# FIFO at or below half full before another payload will be added
+
+# packetsent is based on the fixed payload length
+# which is (13 + 8 * 17) = 149
+# This maths looks wrong.
+# 10 bytes of address, two bytes of command = 12
+# 13 includes the dummy byte at the start, but that is for the SPI address and not counted
+
 def HRF_send_OOK_payload(payload):
     """Send a payload multiple times"""
 
+    #TODO: note the zero at the start was the C method of reserving space for address byte
     p1 = [0x00] + payload
     # This sync pattern does not match C code, but it works.
     # The sync pattern from the C code does not work here
     # Note that buf[0] in the C is undefined due to being uninitialised
+    # but it is a space for the address byte in the C fifo burst routine
     pn = [0x00,0x80,0x00,0x00,0x00] + payload # from the C
-    # Currently there is no explanation for this. (looks like baud rate was wrong)
+    #TODO: note the zero at the start was the C method of reserving space for address byte
+    # which is not needed here in this python.
+    # This is old test data due to wrong baud rate - deprecated
     #pn = [0x80,0x80,0x80,0x80,0x80] + payload
 
     HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY)
     HRF_writefifo_burst(p1)
     
     for i in range(8):
+        # waits for <31 bytes in FIFO
         HRF_pollreg(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, 0)
         HRF_writefifo_burst(pn)
 
@@ -357,6 +380,8 @@
     if (reg & (MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0):
         warning("Failed to send repeated payload to HRF")
 
+    # Note: packetsent is only cleared on exit from TX (i.e to STANDBY or RECEIVE)
+
 
 
 #----- RADIO API --------------------------------------------------------------