diff --git a/src/energenie/drv/build_mac b/src/energenie/drv/build_mac
index 1ac5cf6..ba60d4a 100755
--- a/src/energenie/drv/build_mac
+++ b/src/energenie/drv/build_mac
@@ -1,5 +1,6 @@
 #! /bin/bash
 
+echo '********************************************************************************'
 # build file for Mac use
 
 # build gpio_test
@@ -34,9 +35,9 @@
 
 
 # build radio_test
-## gcc radio_test.c radio.c hrf69.c spis_rpi.c gpio_rpi.c
-## mv a.out radio_test
-## chmod u+x radio_test
+gcc radio_test.c radio.c hrfm69.c spis.c gpio_rpi.c delay_posix.c
+mv a.out radio_test
+chmod u+x radio_test
 
 
 # build spi .so library on Raspberry Pi
diff --git a/src/energenie/drv/hrfm69_test.c b/src/energenie/drv/hrfm69_test.c
index fdb304b..eaa69b4 100644
--- a/src/energenie/drv/hrfm69_test.c
+++ b/src/energenie/drv/hrfm69_test.c
@@ -8,8 +8,6 @@
 
 /***** INCLUDES *****/
 
-//#include <stdio.h>
-//#include <stdlib.h>
 #include "system.h"
 #include "delay.h"
 #include "gpio.h"
diff --git a/src/energenie/drv/radio.c b/src/energenie/drv/radio.c
index 029959a..68e21e1 100644
--- a/src/energenie/drv/radio.c
+++ b/src/energenie/drv/radio.c
@@ -1,239 +1,50 @@
 /* radio.c  12/04/2016  D.J.Whale
  *
- * An interface to the Energenie radio.
+ * An interface to the Energenie Raspberry Pi Radio.
  */
 
 
-/***** CONFIGURATION TABLES *****/
+/***** INCLUDES *****/
+
+#include "system.h"
+#include "radio.h"
+#include "delay.h"
+#include "gpio.h"
+#include "spi.h"
+#include "hrfm69.h"
+#include "trace.h"
 
 
+/***** CONFIGURATION *****/
+
+// Energenie specific radio config values
+//#define RADIO_VAL_SYNCVALUE1FSK          0x2D	// 1st byte of Sync word
+//#define RADIO_VAL_SYNCVALUE2FSK          0xD4	// 2nd byte of Sync word
+//#define RADIO_VAL_SYNCVALUE1OOK          0x80	// 1nd byte of Sync word
+//#define RADIO_VAL_PACKETCONFIG1FSK       0xA2	// Variable length, Manchester coding, Addr must match NodeAddress
+//#define RADIO_VAL_PACKETCONFIG1FSKNO     0xA0	// Variable length, Manchester coding
+//#define RADIO_VAL_PACKETCONFIG1OOK       0		// Fixed length, no Manchester coding
+//#define RADIO_VAL_PAYLOADLEN_OOK         (13 + 8 * 17)	// Payload Length (WRONG!)
+
+//TODO: Not sure, might pass this in? What about on Arduino?
+//What about if we have multiple chip selects on same SPI?
+//What about if we have multiple spi's on different pins?
+
+/* GPIO assignments for Raspberry Pi using BCM numbering */
+#define RESET     25
+#define LED_GREEN 27   // (not B rev1)
+#define LED_RED   22
+
+#define CS        7    // CE1
+#define SCLK      11
+#define MOSI      10
+#define MISO      9
+
+SPI_CONFIG radioConfig = {CS, SCLK, MOSI, MISO, SPI_SPOL0, SPI_CPOL0, SPI_CPHA0};
+                          //TSETTLE, THOLD, TFREQ};
 
 
-
-
-// //
-// import spi
-// // 
-// def warning(msg):
-//     print("warning:" + str(msg))
-// // 
-// def trace(msg):
-//     print(str(msg))
-// // 
-// 
-// def ashex(p):
-//     line = ""
-//     for b in p:
-//         line += str(hex(b)) + " "
-//     return line
-// // 
-// 
-// #----- HOPERF REGISTER INTERFACE ----------------------------------------------
-// # Precise register descriptions can be found in:
-// # www.hoperf.com/upload/rf/RFM69W-V1.3.pdf
-// # on page 63 - 74
-// // 
-// ADDR_FIFO                   = 0x00
-// ADDR_OPMODE                 = 0x01
-// ADDR_REGDATAMODUL           = 0x02
-// ADDR_BITRATEMSB             = 0x03
-// ADDR_BITRATELSB             = 0x04
-// ADDR_FDEVMSB                = 0x05
-// ADDR_FDEVLSB                = 0x06
-// ADDR_FRMSB                  = 0x07
-// ADDR_FRMID                  = 0x08
-// ADDR_FRLSB                  = 0x09
-// ADDR_AFCCTRL                = 0x0B
-// ADDR_LNA                    = 0x18
-// ADDR_RXBW                   = 0x19
-// ADDR_AFCFEI                 = 0x1E
-// ADDR_IRQFLAGS1              = 0x27
-// ADDR_IRQFLAGS2              = 0x28
-// ADDR_RSSITHRESH             = 0x29
-// ADDR_PREAMBLELSB            = 0x2D
-// ADDR_SYNCCONFIG             = 0x2E
-// ADDR_SYNCVALUE1             = 0x2F
-// ADDR_SYNCVALUE2             = 0x30
-// ADDR_SYNCVALUE3             = 0x31
-// ADDR_SYNCVALUE4             = 0x32
-// ADDR_PACKETCONFIG1          = 0x37
-// ADDR_PAYLOADLEN             = 0x38
-// ADDR_NODEADDRESS            = 0x39
-// ADDR_FIFOTHRESH             = 0x3C
-// // 
-// # HopeRF masks to set and clear bits
-// MASK_REGDATAMODUL_OOK       = 0x08
-// MASK_REGDATAMODUL_FSK       = 0x00
-// MASK_WRITE_DATA             = 0x80
-// MASK_MODEREADY              = 0x80
-// MASK_FIFONOTEMPTY           = 0x40
-// MASK_FIFOLEVEL              = 0x20
-// MASK_FIFOOVERRUN            = 0x10
-// MASK_PACKETSENT             = 0x08
-// MASK_TXREADY                = 0x20
-// MASK_PACKETMODE             = 0x60
-// MASK_MODULATION             = 0x18
-// MASK_PAYLOADRDY             = 0x04
-// // 
-// MODE_STANDBY                = 0x04	# Standby
-// MODE_TRANSMITER             = 0x0C	# Transmiter
-// MODE_RECEIVER               = 0x10	# Receiver
-// VAL_REGDATAMODUL_FSK        = 0x00	# Modulation scheme FSK
-// VAL_REGDATAMODUL_OOK        = 0x08	# Modulation scheme OOK
-// VAL_FDEVMSB30               = 0x01	# frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC
-// VAL_FDEVLSB30               = 0xEC	# frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC
-// VAL_FRMSB434                = 0x6C	# carrier freq -> 434.3MHz 0x6C9333
-// VAL_FRMID434                = 0x93	# carrier freq -> 434.3MHz 0x6C9333
-// VAL_FRLSB434                = 0x33	# carrier freq -> 434.3MHz 0x6C9333
-// VAL_FRMSB433                = 0x6C	# carrier freq -> 433.92MHz 0x6C7AE1
-// VAL_FRMID433                = 0x7A	# carrier freq -> 433.92MHz 0x6C7AE1
-// VAL_FRLSB433                = 0xE1	# carrier freq -> 433.92MHz 0x6C7AE1
-// VAL_AFCCTRLS                = 0x00	# standard AFC routine
-// VAL_AFCCTRLI                = 0x20	# improved AFC routine
-// VAL_LNA50                   = 0x08	# LNA input impedance 50 ohms
-// VAL_LNA50G                  = 0x0E	# LNA input impedance 50 ohms, LNA gain -> 48db
-// VAL_LNA200                  = 0x88	# LNA input impedance 200 ohms
-// VAL_RXBW60                  = 0x43	# channel filter bandwidth 10kHz -> 60kHz  page:26
-// VAL_RXBW120                 = 0x41	# channel filter bandwidth 120kHz
-// VAL_AFCFEIRX                = 0x04	# AFC is performed each time RX mode is entered
-// VAL_RSSITHRESH220           = 0xDC	# RSSI threshold 0xE4 -> 0xDC (220)
-// VAL_PREAMBLELSB3            = 0x03	# preamble size LSB 3
-// VAL_PREAMBLELSB5            = 0x05	# preamble size LSB 5
-// VAL_SYNCCONFIG2             = 0x88	# Size of the Synch word = 2 (SyncSize + 1)
-// VAL_SYNCCONFIG4             = 0x98	# Size of the Synch word = 4 (SyncSize + 1)
-// VAL_SYNCVALUE1FSK           = 0x2D	# 1st byte of Sync word
-// VAL_SYNCVALUE2FSK           = 0xD4	# 2nd byte of Sync word
-// VAL_SYNCVALUE1OOK           = 0x80	# 1nd byte of Sync word
-// VAL_PACKETCONFIG1FSK        = 0xA2	# Variable length, Manchester coding, Addr must match NodeAddress
-// VAL_PACKETCONFIG1FSKNO      = 0xA0	# Variable length, Manchester coding
-// 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
-// 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
-// // 
-// 
-// #----- HOPERF RADIO INTERFACE -------------------------------------------------
-// // 
-// def HRF_writereg(addr, data):
-//     """Write an 8 bit value to a register"""
-//     buf = [addr | MASK_WRITE_DATA, data]
-//     spi.select()
-//     spi.frame(buf)
-//     spi.deselect()
-// // 
-// 
-// def HRF_readreg(addr):
-//     """Read an 8 bit value from a register"""
-//     buf = [addr, 0x00]
-//     spi.select()
-//     res = spi.frame(buf)
-//     spi.deselect()
-//     #print(hex(res[1]))
-//     return res[1] # all registers are 8 bit
-// // 
-// 
-// def HRF_writefifo_burst(buf):
-//     """Write all bytes in buf to the payload FIFO, in a single burst"""
-//     # Don't modify buf, in case caller reuses it
-//     txbuf = [ADDR_FIFO | MASK_WRITE_DATA]
-//     for b in buf:
-//       txbuf.append(b)
-//     #print("write FIFO %s" % ashex(txbuf))
-// // 
-//     spi.select()
-//     spi.frame(txbuf)
-//     spi.deselect()
-// // 
-// 
-// def HRF_readfifo_burst():
-//     """Read bytes from the payload FIFO using burst read"""
-//     #first byte read is the length in remaining bytes
-//     buf = []
-//     spi.select()
-//     spi.frame([ADDR_FIFO])
-//     count = 1 # read at least the length byte
-//     while count > 0:
-//         rx = spi.frame([ADDR_FIFO])
-//         data = rx[0]
-//         if len(buf) == 0:
-//             count = data
-//         else:
-//             count -= 1
-//         buf.append(data)
-//     spi.deselect()
-//     trace("readfifo:" + str(ashex(buf)))
-//     return buf
-// // 
-// 
-// def HRF_checkreg(addr, mask, value):
-//     """Check to see if a register matches a specific value or not"""
-//     regval = HRF_readreg(addr)
-//     #print("addr %d mask %d wanted %d actual %d" % (addr,mask,value,regval))
-//     return (regval & mask) == value
-// // 
-// 
-// def HRF_pollreg(addr, mask, value):
-//     """Poll a register until it meet some criteria"""
-//     while not HRF_checkreg(addr, mask, value):
-//         pass
-// // 
-// 
-// def HRF_wait_ready():
-//     """Wait for HRF to be ready after last command"""
-//     HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY, MASK_MODEREADY)
-// // 
-// 
-// def HRF_wait_txready():
-//     """Wait for HRF to be ready and ready for tx, after last command"""
-//     trace("waiting for transmit ready...")
-//     HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY)
-//     trace("transmit ready")
-// // 
-// 
-// def HRF_change_mode(mode):
-//     HRF_writereg(ADDR_OPMODE, mode)
-// // 
-// 
-// def HRF_clear_fifo():
-//     """Clear any data in the HRF payload FIFO by reading until empty"""
-//     while (HRF_readreg(ADDR_IRQFLAGS2) & MASK_FIFONOTEMPTY) == MASK_FIFONOTEMPTY:
-//         HRF_readreg(ADDR_FIFO)
-// // 
-// 
-// def HRF_check_payload():
-//     """Check if there is a payload in the FIFO waiting to be processed"""
-//     irqflags1 = HRF_readreg(ADDR_IRQFLAGS1)
-//     irqflags2 = HRF_readreg(ADDR_IRQFLAGS2)
-//     #trace("irq1 %s   irq2 %s" % (hex(irqflags1), hex(irqflags2)))
-// // 
-//     return (irqflags2 & MASK_PAYLOADRDY) == MASK_PAYLOADRDY
-// // 
-// 
-// def HRF_receive_payload():
-//     """Receive the whole payload"""
-//     return HRF_readfifo_burst()
-// // 
-// 
-// def HRF_send_payload(payload):
-//     trace("send_payload")
-//     #trace("payload:%s" % ashex(payload))
-//     HRF_writefifo_burst(payload)
-//     trace("  waiting for sent...")
-//     HRF_pollreg(ADDR_IRQFLAGS2, MASK_PACKETSENT, MASK_PACKETSENT)
-//     trace("  sent")
-//     reg = HRF_readreg(ADDR_IRQFLAGS2)
-//     trace("  irqflags2=%s" % hex(reg))
-//     if ((reg & MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0):
-//         warning("Failed to send payload to HRF")
-// // 
-// 
-// 
-// #----- ENERGENIE SPECIFIC CONFIGURATIONS --------------------------------------
-// // 
+//----- ENERGENIE SPECIFIC CONFIGURATIONS --------------------------------------
 // config_FSK = [
 //     [ADDR_REGDATAMODUL,       VAL_REGDATAMODUL_FSK],         # modulation scheme FSK
 //     [ADDR_FDEVMSB,            VAL_FDEVMSB30],                # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC
@@ -246,208 +57,387 @@
 //     [ADDR_RXBW,               VAL_RXBW60],                   # channel filter bandwidth 10kHz -> 60kHz  page:26
 //     [ADDR_BITRATEMSB,         0x1A],                         # 4800b/s
 //     [ADDR_BITRATELSB,         0x0B],                         # 4800b/s
-//     #[ADDR_AFCFEI,             VAL_AFCFEIRX],                 # AFC is performed each time rx mode is entered
-//     #[ADDR_RSSITHRESH,         VAL_RSSITHRESH220],            # RSSI threshold 0xE4 -> 0xDC (220)
-//     #[ADDR_PREAMBLELSB,        VAL_PREAMBLELSB5],             # preamble size LSB set to 5
 //     [ADDR_SYNCCONFIG,         VAL_SYNCCONFIG2],              # Size of the Synch word = 2 (SyncSize + 1)
 //     [ADDR_SYNCVALUE1,         VAL_SYNCVALUE1FSK],            # 1st byte of Sync word
 //     [ADDR_SYNCVALUE2,         VAL_SYNCVALUE2FSK],            # 2nd byte of Sync word
-//     #[ADDR_PACKETCONFIG1,     VAL_PACKETCONFIG1FSK],          # Variable length, Manchester coding, Addr must match NodeAddress
 //     [ADDR_PACKETCONFIG1,      VAL_PACKETCONFIG1FSKNO],       # Variable length, Manchester coding
 //     [ADDR_PAYLOADLEN,         VAL_PAYLOADLEN66],             # max Length in RX, not used in Tx
-//     #[ADDR_NODEADDRESS,       VAL_NODEADDRESS01],            # Node address used in address filtering
-//     [ADDR_NODEADDRESS,        0x06],                         # Node address used in address filtering
+//     [ADDR_NODEADDRESS,        0x06],                         # Node address used in address filtering TODO???
 //     [ADDR_FIFOTHRESH,         VAL_FIFOTHRESH1],              # Condition to start packet transmission: at least one byte in FIFO
 //     [ADDR_OPMODE,             MODE_RECEIVER]                 # Operating mode to Receiver
 // ]
-// // 
-// config_OOK = [
-//     [ADDR_REGDATAMODUL,       VAL_REGDATAMODUL_OOK],	     # modulation scheme OOK
-//     [ADDR_FDEVMSB,            0],                            # frequency deviation -> 0kHz
-//     [ADDR_FDEVLSB,            0],                            # frequency deviation -> 0kHz
-//     [ADDR_FRMSB,              VAL_FRMSB433],                 # carrier freq -> 433.92MHz 0x6C7AE1
-//     [ADDR_FRMID,              VAL_FRMID433],                 # carrier freq -> 433.92MHz 0x6C7AE1
-//     [ADDR_FRLSB,              VAL_FRLSB433],                 # carrier freq -> 433.92MHz 0x6C7AE1
-//     [ADDR_RXBW,               VAL_RXBW120],                  # channel filter bandwidth 120kHz
-//     [ADDR_BITRATEMSB, 	      0x40],                         # 1938b/s
-//     [ADDR_BITRATELSB,         0x80],                         # 1938b/s
-//     [ADDR_PREAMBLELSB, 	      0],                            # preamble size LSB 3
-//     [ADDR_SYNCCONFIG, 	      VAL_SYNCCONFIG4],		         # Size of the Sync word = 4 (SyncSize + 1)
-//     [ADDR_SYNCVALUE1, 	      VAL_SYNCVALUE1OOK],            # sync value 1
-//     [ADDR_SYNCVALUE2, 	      0],                            # sync value 2
-//     [ADDR_SYNCVALUE3, 	      0],                            # sync value 3
-//     [ADDR_SYNCVALUE4, 	      0],                            # sync value 4
-//     [ADDR_PACKETCONFIG1,      VAL_PACKETCONFIG1OOK],	     # Fixed length, no Manchester coding, OOK
-//     [ADDR_PAYLOADLEN, 	      VAL_PAYLOADLEN_OOK],	         # Payload Length
-//     [ADDR_FIFOTHRESH, 	      VAL_FIFOTHRESH30],             # Condition to start packet transmission: wait for 30 bytes in FIFO
-// ]
-// // 
-// 
-// def HRF_config(config):
-//     """Load a table of configuration values into HRF registers"""
-//     for cmd in config:
-//         HRF_writereg(cmd[0], cmd[1])
-//         HRF_wait_ready()
-// // 
-// 
-// #ORIGINAL C CODE
-// #void HRF_send_OOK_msg(uint8_t relayState)
-// #{
-// #	uint8_t buf[17];
-// #	uint8_t i;
-// #
-// #	HRF_config_OOK();
-// #
-// #	buf[1] = 0x80;										// Preambule 32b enclosed in sync words
-// #	buf[2] = 0x00;
-// #	buf[3] = 0x00;
-// #	buf[4] = 0x00;
-// #
-// #	for (i = 5; i <= 14; ++i){
-// #		buf[i] = 8 + (i&1) * 6 + 128 + (i&2) * 48;		// address 20b * 4 = 10 Bytes
-// #	}
-// #
-// #	if (relayState == 1)
-// #	{
-// #		printf("relay ON\n\n");
-// #		buf[15] = 0xEE;		// D0-high, D1-h		// S1 on
-// #		buf[16] = 0xEE;		// D2-h, D3-h
-// #	}
-// #	else
-// #	{
-// #		printf("relay OFF\n\n");
-// #		buf[15] = 0xEE;		// D0-high, D1-h		// S1 off
-// #		buf[16] = 0xE8;		// D2-h, D3-l
-// #	}
-// #
-// #	HRF_wait_for (ADDR_IRQFLAGS1, MASK_MODEREADY | MASK_TXREADY, true);		// wait for ModeReady + TX ready
-// #	HRF_reg_Wn(buf + 4, 0, 12);						// don't include sync word (4 bytes) into data buffer
-// #
-// #	for (i = 0; i < 8; ++i)							// Send the same message few more times
-// #	{
-// #		HRF_wait_for(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, false);
-// #		HRF_reg_Wn(buf, 0, 16);						// with sync word
-// #	}
-// #
-// #	HRF_wait_for (ADDR_IRQFLAGS2, MASK_PACKETSENT, true);		// wait for Packet sent
-// #	HRF_assert_reg_val(ADDR_IRQFLAGS2, MASK_FIFONOTEMPTY | MASK_FIFOOVERRUN, false, "are all bytes sent?");
-// #	HRF_config_FSK();
-// #	HRF_wait_for (ADDR_IRQFLAGS1, MASK_MODEREADY, true);		// wait for ModeReady
-// #}
-// // 
-// 
-// def HRF_send_OOK_payload(payload):
-//     """Send a payload multiple times"""
-// // 
-//     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
-//     #pn = [0x00,0x80,0x00,0x00,0x00] # from the C
-//     # Currently there is no explanation for this.
-//     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):
-//         HRF_pollreg(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, 0)
-//         HRF_writefifo_burst(pn)
-// // 
-//     HRF_pollreg(ADDR_IRQFLAGS2, MASK_PACKETSENT, MASK_PACKETSENT) # wait for Packet sent
-// // 
-//     reg = HRF_readreg(ADDR_IRQFLAGS2)
-//     #trace("  irqflags2=%s" % hex(reg))
-//     if (reg & (MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0):
-//         warning("Failed to send repeated payload to HRF")
-// // 
-// 
-// 
-// #----- RADIO API --------------------------------------------------------------
-// // 
+
+
+static 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},                      // 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 (disabled)
+    {HRF_ADDR_PACKETCONFIG1,  0x00},                      // Fixed length, no Manchester coding
+};
+#define CONFIG_OOK_COUNT (sizeof(config_OOK)/sizeof(HRF_CONFIG_REC))
+
+
+/***** MODULE STATE *****/
+
 // mode = None
 // modulation_fsk = None
-// // 
+
+
+/***** LOCAL FUNCTION PROTOTYPES *****/
+
+static uint8_t read_ver(void);
+static void reset(void);
+
+
+/*---------------------------------------------------------------------------*/
+
+static void reset(void)
+{
+  gpio_high(RESET);
+  delayms(150);
+
+  gpio_low(RESET);
+  delayus(100);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static uint8_t read_ver(void)
+{
+  return HRF_readreg(HRF_ADDR_VERSION);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_init(void)
+{
+#if 0
+
+    TRACE_OUTS("start\n");
+
+    //gpio_init(); done by spi_init at moment
+    spi_init(&radioConfig);
+
+    gpio_setout(RESET);
+    gpio_low(RESET);
+    gpio_setout(LED_RED);
+    gpio_low(LED_RED);
+    gpio_setout(LED_GREEN);
+    gpio_low(LED_GREEN);
+
+    TRACE_OUTS("reset...\n");
+    reset();
+
+    TRACE_OUTS("reading radiover...\n");
+    uint8_t rv = read_ver();
+    TRACE_OUTN(rv);
+    TRACE_NL();
+    if (rv != 36)
+    {
+        TRACE_FAIL("unexpected radio ver, not 36(dec)\n");
+    }
+
+    TRACE_OUTS("standby mode\n");
+    HRF_change_mode(HRF_MODE_STANDBY);
+    HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY);
+
+
+    TRACE_OUTS("testing...\n");
+    //hrf_test_send_ook_tick();
+    hrf_test_send_energenie_ook_switch();
+
+    //spi_finished();
+    gpio_finished();
+
+    return 0;
+#endif
+// //
 // def init():
 //     """Initialise the module ready for use"""
 //     spi.init_defaults()
 //     trace("RESET")
-// // 
+//
 //     # Note that if another program left GPIO pins in a different state
 //     # and did a dirty exit, the reset fails to work and the clear fifo hangs.
 //     # Might have to make the spi.init() set everything to inputs first,
 //     # then set to outputs, to make sure that the
 //     # GPIO registers are in a deterministic start state.
 //     spi.reset() # send a hardware reset to ensure radio in clean state
-// // 
-//     HRF_clear_fifo()
-// // 
-// 
+//
+//     HRF_clear_fifo() // not needed?
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_modulation(RADIO_MODULATION mod)
+{
 // def modulation(fsk=None, ook=None):
 //     """Switch modulation, if needed"""
 //     global modulation_fsk
-// // 
+//
 //     # Handle sensible module defaults for earlier versions of user code
 //     if fsk == None and ook == None:
 //         # Force FSK mode
 //         fsk = True
-// // 
+//
 //     if fsk != None and fsk:
 //         if modulation_fsk == None or modulation_fsk == False:
 //             trace("switch to FSK")
 //             HRF_config(config_FSK)
 //             modulation_fsk = True
-// // 
+//
 //     elif ook != None and ook:
 //         if modulation_fsk == None or modulation_fsk == True:
 //             trace("switch to OOK")
 //             HRF_config(config_OOK)
 //             modulation_fsk = False
-// // 
-// 
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_transmitter(RADIO_MODULATION mod)
+{
 // def transmitter(fsk=None, ook=None):
 //     """Change into transmitter mode"""
 //     global mode
-// // 
+//
 //     trace("transmitter mode")
 //     modulation(fsk, ook)
 //     HRF_change_mode(MODE_TRANSMITER)
 //     mode = "TRANSMITTER"
 //     HRF_wait_txready()
-// // 
-// 
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_transmit(uint8_t* payload, uint8_t len, uint8_t repeats)
+{
+// NOTE: repeats parameter, needs to configure HRF payload sender to repeat
+// packet that number of times.
+// NOTE: Payload should already be bit encoded and preambled by time it gets here
+
 // def transmit(payload):
 //     """Transmit a single payload using the present modulation scheme"""
 //     if not modulation_fsk:
-//         HRF_send_OOK_payload(payload)
+//         HRF_send_OOK_payload(payload, repeats) // might not actually be different
 //     else:
-//         HRF_send_payload(payload)
-// // 
-// 
+//         HRF_send_payload(payload, repeats)
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_receiver(RADIO_MODULATION mod)
+{
 // def receiver(fsk=None, ook=None):
 //     """Change into receiver mode"""
 //     global mode
-// // 
+//
 //     trace("receiver mode")
 //     modulation(fsk, ook)
 //     HRF_change_mode(MODE_RECEIVER)
 //     HRF_wait_ready()
 //     mode = "RECEIVER"
-// // 
-// 
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+RADIO_RESULT radio_isReceiveWaiting(void)
+{
 // def isReceiveWaiting():
 //     """Check to see if a payload is waiting in the receive buffer"""
 //     return HRF_check_payload()
-// // 
-// 
+    return RADIO_RESULT_ERR_UNIMPLEMENTED;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+RADIO_RESULT radio_receive(uint8_t* buf, uint8_t len)
+{
 // def receive():
 //     """Receive a single payload from the buffer using the present modulation scheme"""
 //     return HRF_receive_payload()
-// // 
-// 
+    return RADIO_RESULT_ERR_UNIMPLEMENTED;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_standby(void)
+{
+  //TODO: change radio mode to STANDBY to turn PA off and preserve power.
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_finished(void)
+{
 // def finished():
 //     """Close the library down cleanly when finished"""
-//     spi.finished()
-// // 
-// 
-// # END
+//     radio.standby() ??
+//     spi.finished() ??
+//     gpio.finished() ??
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+// A hard coded test of switching an Energenie switch on and off
+//TODO this is for testing only, will be simplified and moved into radio_transmit.
+//
+//TODO note that we want to change this to use FIFO level rather than PACKETSENT
+//so that we can send arbitrary length packets with arbitrary number of repeats
+//(i.e. not limited by the U8 size of the payloadlen register in HRF)
+
+static void hrf_test_send_energenie_ook_switch(void)
+{
+#if 0
+    // Note, when PA starts up, radio inserts a 01 at start before any user data
+    // we might need to pad away from this by sending a sync of many zero bits
+    // to prevent it being misinterpreted as a preamble, and prevent it causing
+    // the first bit of the preamble being twice the length it should be in the
+    // first packet.
+    // Also need to confirm this bit only occurs when transmit actually starts,
+    // and not on every FIFO load.
+
+    /* manual preamble, 20 bit encoded address, 4 encoded data bits */
+    static uint8_t payload[16] = {
+        0x80, 0x00, 0x00, 0x00, // preamble pulse with timing violation gap
+        // Energenie 'random' 20 bit address is 0x6C6C6
+        // 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
+// Limited by U8 size of PAYLOADLEN reg (15*16=240)
+#define REPEATS 15
+// To get longer repeats, we'll have to design a new 'unlimited'
+// payload sender, and use FIFOEMPTY as a way to detect end of transmit.
+
+    int i;
+    uint8_t irqflags1;
+    uint8_t irqflags2;
+
+    TRACE_OUTS("config\n");
+    HRF_config(config_OOK, CONFIG_OOK_COUNT);
+    // the full packet/burst consists of repeated payloads
+    // packetsent will trigger when this number of bytes have been transmitted
+    HRF_writereg(HRF_ADDR_PAYLOADLEN, sizeof(payload) * REPEATS);
+    // but the FIFO is filled in 1 message (4+10+2=16 byte) sections
+    // level triggers when it 'strictly exceeds' level (i.e. 16 bytes starts tx,
+    // and <=15 bytes triggers fifolevel irqflag to be cleared)
+    HRF_writereg(HRF_ADDR_FIFOTHRESH, sizeof(payload)-1);
+
+    uint8_t last_byte = ON;
+
+    while (1)
+    {
+        /* Bring into transmitter mode and ramp up the PA */
+        TRACE_OUTS("transmitter mode\n");
+        HRF_change_mode(HRF_MODE_TRANSMITTER);
+
+        TRACE_OUTS("wait for modeready,txready in irqflags1\n");
+        HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY|HRF_MASK_TXREADY, HRF_MASK_MODEREADY|HRF_MASK_TXREADY);
+
+        irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1);
+        irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2);
+        TRACE_OUTS("irqflags1,2=");
+        TRACE_OUTN(irqflags1);
+        TRACE_OUTC(',');
+        TRACE_OUTN(irqflags2);
+        TRACE_NL();
+
+        /* Set this as alternate ON or OFF bursts */
+        payload[sizeof(payload)-1] = last_byte;
+
+        TRACE_OUTS("tx repeats in a single burst:");
+        TRACE_OUTN(last_byte);
+        TRACE_NL();
+
+        // send a number of payload repeats for the whole packet burst
+        for (i=0; i<REPEATS; i++)
+        {
+            HRF_writefifo_burst(payload, sizeof(payload));
+            // Tx will auto start when fifolevel is exceeded by loading the payload
+            // so the level register must be correct for the size of the payload
+            // otherwise transmit will never start.
+            /* wait for FIFO to not exceed threshold level */
+            HRF_pollreg(HRF_ADDR_IRQFLAGS2, HRF_MASK_FIFOLEVEL, 0);
+        }
+
+        // wait for packet sent (num bytes tx'ed matches PAYLOADLEN reg)
+        HRF_pollreg(HRF_ADDR_IRQFLAGS2, HRF_MASK_PACKETSENT, HRF_MASK_PACKETSENT);
+
+        // Check final flags in case of overruns etc
+        irqflags1 = HRF_readreg(HRF_ADDR_IRQFLAGS1);
+        irqflags2 = HRF_readreg(HRF_ADDR_IRQFLAGS2);
+
+        TRACE_OUTS("irqflags1,2=");
+        TRACE_OUTN(irqflags1);
+        TRACE_OUTC(',');
+        TRACE_OUTN(irqflags2);
+        TRACE_NL();
+
+        // Read back PAYLOADLENGTH to confirm chip doesn't use it as a counter itself
+        uint8_t pl = HRF_readreg(HRF_ADDR_PAYLOADLEN);
+        TRACE_OUTS("payloadlen reg at end:");
+        TRACE_OUTN(pl);
+        TRACE_NL();
+
+        /* Back to STANDBY, this clears packetsent flag */
+        // always back to standby, regardless of errors above
+        // otherwise PA/carrier might be left permanently on.
+
+        TRACE_OUTS("standby mode\n");
+        HRF_change_mode(HRF_MODE_STANDBY);
+        HRF_pollreg(HRF_ADDR_IRQFLAGS1, HRF_MASK_MODEREADY, HRF_MASK_MODEREADY);
+
+        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");
+        }
+
+        /* Inter-burst delay */
+        delaysec(1);
+
+        /* Toggle next switch state */
+        if (last_byte == OFF)
+        {
+            last_byte = ON;
+        }
+        else
+        {
+            last_byte = OFF;
+        }
+    }
+#endif
+}
+
+
+
+/***** END OF FILE *****/
diff --git a/src/energenie/drv/radio.h b/src/energenie/drv/radio.h
index 37719c7..b865d4d 100644
--- a/src/energenie/drv/radio.h
+++ b/src/energenie/drv/radio.h
@@ -3,43 +3,33 @@
  * Energenie radio interface
  */
 
+
 #ifndef _RADIO_H
 #define _RADIO_H
 
 typedef uint8_t RADIO_RESULT;
+#define RADIO_RESULT_ERR_UNIMPLEMENTED 0x81
 
-typedef uint8_t RADIO_MODULATION
+typedef uint8_t RADIO_MODULATION;
 #define RADIO_MODULATION_OOK 0
 #define RADIO_MODULATION_FSK 1
 
 
-// Energenie specific Values
-#define RADIO_VAL_SYNCVALUE1FSK          0x2D	// 1st byte of Sync word
-#define RADIO_VAL_SYNCVALUE2FSK          0xD4	// 2nd byte of Sync word
-#define RADIO_VAL_SYNCVALUE1OOK          0x80	// 1nd byte of Sync word
-#define RADIO_VAL_PACKETCONFIG1FSK       0xA2	// Variable length, Manchester coding, Addr must match NodeAddress
-#define RADIO_VAL_PACKETCONFIG1FSKNO     0xA0	// Variable length, Manchester coding
-#define RADIO_VAL_PACKETCONFIG1OOK       0		// Fixed length, no Manchester coding
-#define RADIO_VAL_PAYLOADLEN_OOK         (13 + 8 * 17)	// Payload Length
-//#define RADIO_VAL_NODEADDRESS01          0x01	// Node address used in address filtering
-//#define RADIO_VAL_NODEADDRESS04          0x04	// Node address used in address filtering
-
-
 extern void radio_init(void);
 
 extern void radio_modulation(RADIO_MODULATION mod);
 
 extern void radio_transmitter(RADIO_MODULATION mod);
 
-extern void radio_transmit(uint8_t* payload, uint8_t len);
-
-extern void radio_send_OOK_payload(uint8_t* payload, uint8_t len);
+extern void radio_transmit(uint8_t* payload, uint8_t len, uint8_t repeats);
 
 extern void radio_receiver(RADIO_MODULATION mod);
 
 extern RADIO_RESULT radio_isReceiveWaiting(void);
 
-extern uint8_t* radio_receive(uint8_t maxlen);
+extern RADIO_RESULT radio_receive(uint8_t* buf, uint8_t len);
+
+extern void radio_standby(void);
 
 extern void radio_finished(void);
 
diff --git a/src/energenie/drv/radio_test.c b/src/energenie/drv/radio_test.c
index 9dc8084..125158d 100644
--- a/src/energenie/drv/radio_test.c
+++ b/src/energenie/drv/radio_test.c
@@ -10,21 +10,99 @@
 
 #include "system.h"
 #include "radio.h"
-#include "gpio.h"
-#include "spi.h"
-#include "hrf69.h"
+#include "delay.h"
+#include "trace.h"
 
 
 /***** CONSTANTS *****/
 
+#define REPEATS 8
+
+
+/***** FORWARD FUNCTION PROTOTYPES *****/
+
+void radio_test_ook(void);
+void radio_test_fsk(void);
+
+
+/*---------------------------------------------------------------------------*/
 
 int main(int argc, char **argv)
 {
-  gpio_init();
-  spi_init_defaults();
+    radio_test_ook();
+    //TODO: radio_test_fsk();
+}
 
-  //TODO
-  return 0;
+
+/*---------------------------------------------------------------------------*/
+
+void radio_test_ook(void)
+{
+    //gpio_init();
+    //spi_init(&spi_config);
+
+    radio_init();
+    radio_transmitter(RADIO_MODULATION_OOK);
+
+    /* The 'radio' module knows nothing about the Energenie (HS1527) bit encoding,
+     * so this test code manually encodes the bits.
+     * For the full Python stack, there is an encoder module that can generate
+     * specific payloads. Repeats are done in radio_transmitter.
+     * The HRF preamble feature is no longer used, it's more predictable to
+     * put the preamble in the payload.
+     */
+
+    /* manual preamble, 20 bit encoded address, 4 encoded data bits */
+    static uint8_t enc_1on[16] = {
+        0x80, 0x00, 0x00, 0x00, // preamble pulse with timing violation gap
+        // Energenie 'random' 20 bit address is 0x6C6C6
+        // 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
+    };
+
+    static uint8_t enc_1off[16] = {
+        0x80, 0x00, 0x00, 0x00, // preamble pulse with timing violation gap
+        // Energenie 'random' 20 bit address is 0x6C6C6
+        // 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
+    };
+
+
+    while (1)
+    {
+        /* Turn switch 1 on */
+        TRACE_OUTS("Switch 1 ON\n");
+        radio_transmit(enc_1on, sizeof(enc_1on), REPEATS);
+        radio_standby(); //TODO put this here? move out from radio_transmit??
+        delaysec(1);
+
+        TRACE_OUTS("Switch 1 OFF\n");
+        radio_transmit(enc_1off, sizeof(enc_1off), REPEATS);
+        radio_standby(); //TODO put this here? move out from radio_transmit??
+        delaysec(1);
+    }
+
+    radio_finished();
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void radio_test_fsk(void)
+{
+    //TODO
 }