diff --git a/software/unb_osy/io2_copy.S b/software/unb_osy/io2_copy.S
new file mode 100644
index 0000000000000000000000000000000000000000..7826c86bbd9606f674c9885b6f728364ab895904
--- /dev/null
+++ b/software/unb_osy/io2_copy.S
@@ -0,0 +1,32 @@
+	.file	"io2_copy.c"
+	.section	.text
+	.align	2
+	.global	io2_copy
+	.type	io2_copy, @function
+io2_copy:
+	andi	r2, r4, 3
+	ldw	r3, 0(sp)
+	bne	r2, zero, .L2
+	andi	r2, r5, 3
+	bne	r2, zero, .L2
+	beq	r6, zero, .L5
+	add	r2, r7, r7
+	add	r3, r3, r3
+	add	r7, r2, r2
+	add	r3, r3, r3
+	mov	r8, zero
+.L7:
+	ldwio	r2, 0(r5)
+	stwio	r2, 0(r4)
+	addi	r8, r8, 1
+	add	r5, r5, r7
+	add	r4, r4, r3
+	bne	r8, r6, .L7
+.L5:
+	movi	r2, 1
+	ret	
+.L2:
+	mov	r2, zero
+	ret	
+	.size	io2_copy, .-io2_copy
+	.ident	"GCC: (Altera 10.1 Build 153) 4.1.2"
diff --git a/software/unb_osy/io2_copy.h b/software/unb_osy/io2_copy.h
new file mode 100644
index 0000000000000000000000000000000000000000..20b3d774b7ed9d5d1d8cf4449aea897fb813e070
--- /dev/null
+++ b/software/unb_osy/io2_copy.h
@@ -0,0 +1,7 @@
+#ifndef IO2_COPY_H
+#define IO2_COPY_H
+#include <alt_types.h>
+// mind you: to + from are taken to be pointers to 32-bit words;
+//  sinc and dinc are increments in *units of words* (ie 4bytes)
+alt_u32 io2_copy(void* to, void* from, unsigned int n, unsigned int sinc, unsigned int dinc);
+#endif
diff --git a/software/unb_osy/main.c b/software/unb_osy/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..78d573621c06db7627497c41cc33d55bd1b8bbb9
--- /dev/null
+++ b/software/unb_osy/main.c
@@ -0,0 +1,130 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+#include "system.h"
+#include "sys/alt_irq.h"
+
+#if defined(COMPILE_FOR_QSYS)
+#  include "altera_nios2_qsys_irq.h"
+#elif defined(COMPILE_FOR_GEN2_UNB2)
+#  include "altera_nios2_gen2_irq.h"
+#else
+#  include "altera_nios2_irq.h"
+#endif
+
+#include "osx_timer.h"
+#include "unbosx_types.h"
+#include "unbos_eth.h"
+#include "unbos_i2c.h"
+#include "packet.h"
+#include "osx_stdio.h"
+#include "altera_avalon_jtag_uart_regs.h"
+/* Compile switches. */
+
+#define BUILD 1
+#undef ATEST
+void main(void) __attribute__((weak, alias("alt_main")));
+
+
+/*-----------------------------------------------------------------------------
+ * Function name:  main
+ * Parameters:     -
+ * Return:         -
+ * Description:    Deal with incoming command packets
+ * Remark:         Use the 1ms system tick to initiate actions in a loop.
+ *                 The tasks in the loop are blocking.
+ *-----------------------------------------------------------------------------
+ */
+#if defined(COMPILE_FOR_QSYS)
+#warning "Compiling for QSYS"
+ALTERA_NIOS2_QSYS_IRQ_INSTANCE ( CPU_0, cpu_0);
+#elif defined(COMPILE_FOR_GEN2_UNB2)
+#warning "Compiling for GEN2_UNB2"
+ALTERA_NIOS2_GEN2_IRQ_INSTANCE ( CPU_0, cpu_0);
+#else
+#warning "Compiling for SOPC"
+ALTERA_NIOS2_IRQ_INSTANCE ( CPU_0, cpu_0);
+#endif
+
+void alt_main(void) {
+	clock_t nof_ticks_wdi;
+#ifdef ATEST
+	alt_u32 atest = 0, oatest = 0;
+#endif
+#if defined(COMPILE_FOR_QSYS)
+    ALTERA_NIOS2_QSYS_IRQ_INIT ( CPU_0, cpu_0);
+#elif defined(COMPILE_FOR_GEN2_UNB2)
+    ALTERA_NIOS2_GEN2_IRQ_INIT ( CPU_0, cpu_0);
+#else
+    ALTERA_NIOS2_IRQ_INIT ( CPU_0, cpu_0);
+#endif
+    alt_irq_cpu_enable_interrupts();
+	OSX_TIMER_INIT ( TIMER_0, timer_0);
+
+	// Clear the AC(cess) bit in the JTAG UART.
+	// If there *is* JTAG activity (ie a host-PC
+	// reading out the JTAG) then it will be set to
+	// '1'. Our output routine will detect activity
+	// (or lack thereof).
+	// We must write '1' to clear the bit.
+	IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(JTAG_UART_0_BASE, ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK);
+
+    osx_printf("unb_osy %d\n", BUILD);
+#ifdef ATEST
+	osx_printf("%x\n", &atest);
+#endif
+
+    // Set up networking environment
+    UNBOSX_NET_Setup();
+
+    // Take care of setting up I2C - works wether we 
+    // have it or not
+    UNBOS_i2c_init();
+
+	// force watchdog reset asap
+	nof_ticks_wdi = osx_clock();
+    // prepare for entering mainloop
+    while( 1 ) {
+        clock_t       now = osx_clock();
+
+        // Reset WDI every 1000 clockticks (1 second)
+        if( (now-nof_ticks_wdi) >= 1000 ) {
+            UNBOSX_ResetWatchdog();
+            nof_ticks_wdi = now;
+        }
+
+		// Task: Ethernet traffic
+        if( RXAVAIL(eth_status) ) {
+			unsigned int replysize;
+            if( (replysize=handlePacket())>0 )
+				UNBOSX_NET_Send(replysize+2);
+			else
+				UNBOSX_NET_Discard();
+        }
+#if ATEST
+		if( oatest!=atest ) {
+			osx_printf("%x -> %x\n", oatest, atest);
+			oatest = atest;
+		}
+#endif
+    }
+}
diff --git a/software/unb_osy/modules/common_types.h b/software/unb_osy/modules/common_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3e562b5abe55e49577c11de7457e6c9642c23d0
--- /dev/null
+++ b/software/unb_osy/modules/common_types.h
@@ -0,0 +1,88 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+#ifndef COMMON_TYPES_H
+#define COMMON_TYPES_H
+
+/* includes */
+#include "alt_types.h"
+
+
+/* public constants */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define HALF_WORD_SZ       2
+#define WORD_SZ            4
+#define LONG_WORD_SZ       8
+#define NIBBLE_W           4
+#define BYTE_W             8
+#define OCTET_W            8
+#define HALF_WORD_W       (BYTE_W * HALF_WORD_SZ)
+#define WORD_W            (BYTE_W * WORD_SZ)
+#define LONG_WORD_W       (BYTE_W * LONG_WORD_SZ)
+
+
+/* public macros */
+
+
+/* public types */
+
+/* Map to
+ * %QUARTUS_ROOTDIR%/../ip/altera/nios2_ip/altera_nios2/HAL/inc/alt_type.h
+ */
+typedef alt_32             TBool;        // b
+typedef alt_8              TInt8;        // c  : signed char
+typedef alt_16             TInt16;       // i  : signed short
+typedef alt_32             TInt32;       // l  : signed long
+typedef alt_64             TInt64;       // h  : signed long long
+typedef alt_u8             TUInt8;       // uc : unsigned char
+typedef alt_u16            TUInt16;      // ui : unsigned short
+typedef alt_u32            TUInt32;      // ul : unsigned long
+typedef alt_u64            TUInt64;      // uh : unsigned long long
+
+typedef float              TFloat32;     // f
+typedef double             TFloat64;     // d
+typedef char               TStr8[9];     // sz
+typedef char               TStr32[33];   // sz
+typedef char               TStr64[65];   // sz
+typedef char               TStr128[129]; // sz
+typedef char               TStr256[257]; // sz
+typedef char               TStr512[513]; // sz
+
+
+/* public variables */
+
+/* public function protos */
+
+#endif
+
diff --git a/software/unb_osy/modules/common_util.c b/software/unb_osy/modules/common_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c2dc782a2ef4a104fa7133d297b1b7eba3f0106
--- /dev/null
+++ b/software/unb_osy/modules/common_util.c
@@ -0,0 +1,94 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+/* Compile switches. */
+
+
+/* includes */
+#include <stdio.h>
+#include "common_types.h"
+#include "common_util.h"
+
+
+/* private constants (#define) */
+
+/* private types */
+
+/* private function protos */
+
+/* private constants (const) */
+
+/* private variables */
+
+/* public variables */
+
+/* public function implements */
+
+/*-----------------------------------------------------------------------------
+ * Function name:  UTIL_swapl
+ * Parameters:     in_dat  = 4 byte long input word
+ * Return:         out_dat = byte swapped word
+ * Description:
+ *-----------------------------------------------------------------------------
+ */
+TUInt32 UTIL_swapl(TUInt32 in_dat)
+{
+  TUInt32  out_dat;
+  TUInt8  *pInByte;
+  TUInt8  *pOutByte;
+
+  pInByte  = (TUInt8 *)&in_dat;
+  pOutByte = (TUInt8 *)&out_dat + 3;
+
+  *pOutByte-- = *pInByte++;
+  *pOutByte-- = *pInByte++;
+  *pOutByte-- = *pInByte++;
+  *pOutByte   = *pInByte;
+
+  return out_dat;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Function name:  UTIL_swaps
+ * Parameters:     in_dat  = 2 byte long input half word
+ * Return:         out_dat = byte swapped half word
+ * Description:
+ *-----------------------------------------------------------------------------
+ */
+TUInt16 UTIL_swaps(TUInt16 in_dat)
+{
+  TUInt16  out_dat;
+  TUInt8  *pInByte;
+  TUInt8  *pOutByte;
+
+  pInByte  = (TUInt8 *)&in_dat;
+  pOutByte = (TUInt8 *)&out_dat + 1;
+
+  *pOutByte-- = *pInByte++;
+  *pOutByte   = *pInByte;
+
+  return out_dat;
+}
+
+
+/* private function implements */
diff --git a/software/unb_osy/modules/common_util.h b/software/unb_osy/modules/common_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..7495831872fc3b9329f2f620783595524bbbebdc
--- /dev/null
+++ b/software/unb_osy/modules/common_util.h
@@ -0,0 +1,78 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+#ifndef COMMON_UTIL_H
+#define COMMON_UTIL_H
+
+
+/* includes */
+#include "common_types.h"
+
+
+/* public constants */
+
+// Define UTIL_HOST_IS_LITTLE_ENDIAN if the host is little endian, comment if
+// the host is big endian.
+// . Network communication is big endian (MSByte is 'big end first').
+// . The Nios II architecture is little endian (LSByte is 'little end first').
+#define UTIL_HOST_IS_LITTLE_ENDIAN
+
+#ifndef UTIL_HOST_IS_LITTLE_ENDIAN
+#define UTIL_HOST_IS_BIG_ENDIAN
+#endif
+
+/* public macros */
+
+// Define host to network big endian 'b' and host 'h' to little endian 'l' for
+// 32 bit 'l' and for 16 bit 's'
+#ifdef UTIL_HOST_IS_LITTLE_ENDIAN
+#define UTIL_htoll(a) (a)
+#define UTIL_htols(a) (a)
+#define UTIL_htobl(a) (UTIL_swapl(a))
+#define UTIL_htobs(a) (UTIL_swaps(a))
+#else
+#define UTIL_htoll(a) (UTIL_swapl(a))
+#define UTIL_htols(a) (UTIL_swaps(a))
+#define UTIL_htobl(a) (a)
+#define UTIL_htobs(a) (a)
+#endif
+// For completeness also define equivalent 'n' to 'h' and 'l' to 'h' for
+// 32 bit and 16 bit
+#define UTIL_ltohl(a) (UTIL_htoll(a))
+#define UTIL_ltohs(a) (UTIL_htols(a))
+#define UTIL_btohl(a) (UTIL_htobl(a))
+#define UTIL_btohs(a) (UTIL_htobs(a))
+
+#define UTIL_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define UTIL_SEL_A_B(sel, a, b) ((sel) ? (a) : (b))
+
+
+/* public types */
+
+/* public variables */
+
+/* public function protos */
+TUInt32 UTIL_swapl(TUInt32 in_dat);
+TUInt16 UTIL_swaps(TUInt16 in_dat);
+
+#endif
+
diff --git a/software/unb_osy/modules/i2c_ltc4260.h b/software/unb_osy/modules/i2c_ltc4260.h
new file mode 100644
index 0000000000000000000000000000000000000000..9431c494b05451777b6b89d83155293114b86a16
--- /dev/null
+++ b/software/unb_osy/modules/i2c_ltc4260.h
@@ -0,0 +1,78 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+// Positive High Voltage Hot Swap Controller with I2C Compatible Monitoring
+
+#ifndef I2C_LTC4260_H
+#define I2C_LTC4260_H
+
+/* includes */
+#include "common_types.h"
+
+/* public constants */
+
+// Mass write address (broadcast)
+#define I2C_LTC4260_ADR_MW                  0x5F
+// Alert response address
+#define I2C_LTC4260_ADR_AR                  0x0C
+// Other addresses
+#define I2C_LTC4260_ADR_LOW_LOW_LOW         0x44
+
+// Use SMBUS Write Byte or Read Byte to access the command registers
+#define I2C_LTC4260_CMD_CONTROL             0
+#define I2C_LTC4260_CMD_ALERT               1
+#define I2C_LTC4260_CMD_STATUS              2
+#define I2C_LTC4260_CMD_FAULT               3
+#define I2C_LTC4260_CMD_SENSE               4
+#define I2C_LTC4260_CMD_SOURCE              5
+#define I2C_LTC4260_CMD_ADIN                6
+  
+// Voltage measurement units, use float for ease and accuracy or int for speed
+// 0.3 mV over Rs (e.g. 10 mOhm) for current sense
+#define I2C_LTC4260_V_UNIT_SENSE            ((TFloat32)0.0003)
+#define I2C_LTC4260_uV_UNIT_SENSE          ((TUInt32)300)
+// 400 mV supply voltage (e.g +48 V)
+#define I2C_LTC4260_V_UNIT_SOURCE           ((TFloat32)0.4)
+#define I2C_LTC4260_mV_UNIT_SOURCE         ((TUInt32)400)
+// 10 mV ADC
+#define I2C_LTC4260_V_UNIT_ADIN             ((TFloat32)0.01)
+#define I2C_LTC4260_mV_UNIT_ADIN            ((TUInt32)10)
+  
+// 0x1B =  00 = power good
+//       &  0 = disable test mode
+//       &  1 = Enable massa write
+//       &  1 = turn FET On
+//       &  0 = Overcurrent Autoretry Disabled
+//       &  1 = Undervoltage Autoretry Enabled
+//       &  1 = Overvoltage Autoretry Enabled
+#define I2C_LTC4260_CONTROL_DEFAULT         0x1B
+
+/* public macros */
+
+/* public types */
+
+/* public variables */
+
+/* public function protos */
+
+#endif
+
diff --git a/software/unb_osy/modules/i2c_max1617.h b/software/unb_osy/modules/i2c_max1617.h
new file mode 100644
index 0000000000000000000000000000000000000000..399f2aa03e4a1fac0688b2e1aafbbf5449081f54
--- /dev/null
+++ b/software/unb_osy/modules/i2c_max1617.h
@@ -0,0 +1,93 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+// This also applies to MAX1618. The adavantage of the MAX1618 over the
+// MAX1617A is that the MAX1618 has a thermostat mode, which changes the
+// function of the ALERT output from a latched interrupt-type output to a
+// selfclearing thermostat for fan control.
+
+#ifndef I2C_MAX1617_H
+#define I2C_MAX1617_H
+
+/* includes */
+
+/* public constants */
+//                      ADD0_ADD1
+#define I2C_MAX1617_ADR_LOW_LOW             0x18
+#define I2C_MAX1617_ADR_LOW_MID             0x19
+#define I2C_MAX1617_ADR_LOW_HIGH            0x1A
+#define I2C_MAX1617_ADR_MID_LOW             0x29
+#define I2C_MAX1617_ADR_MID_MID             0x2A
+#define I2C_MAX1617_ADR_MID_HIGH            0x2B
+#define I2C_MAX1617_ADR_HIGH_LOW            0x4C
+#define I2C_MAX1617_ADR_HIGH_MID            0x4D
+#define I2C_MAX1617_ADR_HIGH_HIGH           0x4E
+
+#define I2C_MAX1617_CMD_READ_LOCAL_TEMP       0
+#define I2C_MAX1617_CMD_READ_REMOTE_TEMP      1
+#define I2C_MAX1617_CMD_READ_STATUS           2
+#define I2C_MAX1617_CMD_READ_CONFIG           3
+#define I2C_MAX1617_CMD_READ_RATE             4
+#define I2C_MAX1617_CMD_READ_LOCAL_HIGH       5
+#define I2C_MAX1617_CMD_READ_LOCAL_LOW        6
+#define I2C_MAX1617_CMD_READ_REMOTE_HIGH      7
+#define I2C_MAX1617_CMD_READ_REMOTE_LOW       8
+
+#define I2C_MAX1617_CMD_WRITE_CONFIG          9
+#define I2C_MAX1617_CMD_WRITE_RATE           10
+#define I2C_MAX1617_CMD_WRITE_LOCAL_HIGH     11
+#define I2C_MAX1617_CMD_WRITE_LOCAL_LOW      12
+#define I2C_MAX1617_CMD_WRITE_REMOTE_HIGH    13
+#define I2C_MAX1617_CMD_WRITE_REMOTE_LOW     14
+
+#define I2C_MAX1617_CMD_ONE_SHOT             15
+
+#define I2C_MAX1617_RATE_0_0625               0
+#define I2C_MAX1617_RATE_0_125                1
+#define I2C_MAX1617_RATE_0_25                 2
+#define I2C_MAX1617_RATE_0_5                  3
+#define I2C_MAX1617_RATE_1                    4
+#define I2C_MAX1617_RATE_2                    5
+#define I2C_MAX1617_RATE_4                    6
+#define I2C_MAX1617_RATE_8                    7
+
+#define I2C_MAX1617_CONFIG_ID               0x08
+#define I2C_MAX1617_CONFIG_THERM            0x10
+#define I2C_MAX1617_CONFIG_POL              0x20
+#define I2C_MAX1617_CONFIG_RUN_STOP         0x40
+#define I2C_MAX1617_CONFIG_MASK             0x80
+
+#define I2C_MAX1617_STATUS_BUSY             0x80
+#define I2C_MAX1617_STATUS_RHIGH            0x10
+#define I2C_MAX1617_STATUS_RLOW             0x08
+#define I2C_MAX1617_STATUS_DIODE            0x04
+
+/* public macros */
+
+/* public types */
+
+/* public variables */
+
+/* public function protos */
+
+#endif
+
diff --git a/software/unb_osy/osx_stdio.c b/software/unb_osy/osx_stdio.c
new file mode 100644
index 0000000000000000000000000000000000000000..a059038d80d77c87ca24749f82df74cfb51550e2
--- /dev/null
+++ b/software/unb_osy/osx_stdio.c
@@ -0,0 +1,217 @@
+/******************************************************************************
+*                                                                             *
+* License Agreement                                                           *
+*                                                                             *
+* Copyright (c) 2006 Altera Corporation, San Jose, California, USA.           *
+* All rights reserved.                                                        *
+*                                                                             *
+* Permission is hereby granted, free of charge, to any person obtaining a     *
+* copy of this software and associated documentation files (the "Software"),  *
+* to deal in the Software without restriction, including without limitation   *
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
+* and/or sell copies of the Software, and to permit persons to whom the       *
+* Software is furnished to do so, subject to the following conditions:        *
+*                                                                             *
+* The above copyright notice and this permission notice shall be included in  *
+* all copies or substantial portions of the Software.                         *
+*                                                                             *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
+* DEALINGS IN THE SOFTWARE.                                                   *
+*                                                                             *
+* This agreement shall be governed in all respects by the laws of the State   *
+* of California and by the laws of the United States of America.              *
+*                                                                             *
+* Altera does not recommend, suggest or require that this reference design    *
+* file be used in conjunction or combination with any other product.          *
+******************************************************************************/
+
+/*
+ * This file provides a very minimal printf implementation for use with very
+ * small applications.  Only the following format strings are supported:
+ *   %x
+ *   %s
+ *   %c
+ *   %%
+ */
+#include <system.h>
+#include <osx_stdio.h>
+#include "altera_avalon_jtag_uart_regs.h"
+
+typedef void (*output_fn)(char , char*);
+
+
+/* soo = start of output */
+int fmt_function(output_fn out, char* soo, const char* fmt, va_list args) {
+    char              c;
+    const char*       w;
+    const char* const p = soo;
+
+    /* Process format string. */
+    w = fmt;
+    while( (c=*w++)!=0 ) {
+        /* If not a format escape character, just print  */
+        /* character.  Otherwise, process format string. */
+        if( c!='%' ) {
+			out(c, soo++);	
+        } else {
+            /* Get format character.  If none     */
+            /* available, processing is complete. */
+			if( (c=*w++)==0 )
+				break;
+			/* Bollox. Need to to woik! */
+			switch( c ) {
+				case '%':
+                    /* Process "%" escape sequence. */
+					out(c, soo++);
+					break;
+
+				case 'c':
+					{
+                    	int v = va_arg(args, int);
+	                    out((char)v, soo++);
+					}
+					break;
+
+				case 'x':
+					{
+						/* Process hexadecimal number format. */
+						int           digit_shift;
+						unsigned long v = va_arg(args, unsigned long);
+						unsigned long digit;
+
+						out('0', soo++);
+						out('x', soo++);
+
+						/* If the number value is zero, just print and continue. */
+						if( v==0 ) {
+							out('0', soo++);
+							break;
+						}
+
+						/* Find first non-zero digit. */
+						digit_shift = 28;
+						while( !(v & (0xF<<digit_shift)) )
+							digit_shift -= 4;
+
+						/* Print digits. */
+						for( ; digit_shift>=0; digit_shift-=4 ) {
+							digit = (v & (0xF << digit_shift)) >> digit_shift;
+							if( digit<=9 )
+								c = '0' + digit;
+							else
+								c = 'a' + digit - 10;
+							out(c, soo++);
+						}
+					}
+					break;
+
+				case 'd':
+					{
+						int   v = va_arg(args, int);
+						char  digitbuf[ ((sizeof(int) * 8)/3) + 1 ];
+						char* dptr = &digitbuf[0];
+
+						/* we must, in this case, print at least one digit */
+						if( v==0 )
+							*dptr++ = '0';
+						/* figure out which digits to print.
+						 * this will only do something if v!=0 yet
+						 */
+						while( v ) {
+							*dptr++ = '0' + (v%10);
+							v /= 10;
+						}
+						/* the digits we must output are now in reverse order
+						 * so we print them starting from the end.
+						 * Note: dptr points one *past* the character to 
+						 * output!
+						 */
+						while( --dptr>=&digitbuf[0] )
+							out(*dptr, soo++);
+					}
+					break;
+
+				case 's':
+					{
+                    	/* Process string format. */
+						char *s = va_arg(args, char *);
+
+						while( *s )
+							out(*s++, soo++);
+					}
+					break;
+
+				default:
+					break;
+			}
+        }
+    }
+	out('\0', soo++);
+    return (int)(soo-p);
+}
+
+/* Put functions: to stdout or to string */
+void osx_putchar(char c, char* _ptr) {
+	unsigned int          ntry = 32;
+	volatile unsigned int control;
+	if( c!='\0' ) {
+		do {
+			control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(JTAG_UART_0_BASE);
+			
+			if( (control&ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK)!=0 ) {
+				IOWR_ALTERA_AVALON_JTAG_UART_DATA(JTAG_UART_0_BASE, c);
+				break;
+			} 
+#if 0
+			else {
+				// buffer was full - apparently - so if we do not
+				// detect JTAG activity since previous I/O we 
+				// do not output this character but carry on
+				// (otherwise the firmware would hang)
+				if( (control&ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK)==0 ) {
+					// AC(tivity) bit NOT set -> no-one is lissnin!
+					break;
+				}
+			}
+#endif
+		} while( --ntry );
+	}
+	// Reset the ACtivity bit (by writing a '1') so we can always detect if someone
+	// starts lissnin
+//	IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(JTAG_UART_0_BASE, ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK);
+	return;
+}
+
+#if 0
+void osx_sputchar(char c, char* ptr) {
+	*ptr = c;
+}
+
+int osx_vsprintf(char* str, const char* fmt, va_list args ) {
+	return fmt_function(osx_sputchar, str, fmt, args);
+}
+
+/* OSX sprintf function */
+int osx_sprintf(char* str, const char* fmt, ... ) {
+	int     r;
+	va_list args;
+	va_start(args, fmt);
+	r = fmt_function(osx_sputchar, str, fmt, args);
+	va_end(args);
+	return r;
+}
+#endif
+int osx_printf(const char* fmt, ...) {
+	int     r;
+	va_list args;
+	va_start(args, fmt);
+	r = fmt_function(osx_putchar, 0, fmt, args);
+	va_end(args);
+	return r;
+}
+
diff --git a/software/unb_osy/osx_stdio.h b/software/unb_osy/osx_stdio.h
new file mode 100644
index 0000000000000000000000000000000000000000..44f30a6e10bc3818c74c9837bdabee7482e1e720
--- /dev/null
+++ b/software/unb_osy/osx_stdio.h
@@ -0,0 +1,7 @@
+#ifndef OSX_STDIO_H
+#define OSX_STDIO_H
+#include <stdarg.h>
+int osx_vsprintf(char* str, const char* fmt, va_list args );
+int osx_sprintf(char* str, const char* fmt, ... );
+int osx_printf(const char* fmt, ...);
+#endif
diff --git a/software/unb_osy/osx_timer.c b/software/unb_osy/osx_timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb42c9930e5e57a2f9e658820178a3f1e7119719
--- /dev/null
+++ b/software/unb_osy/osx_timer.c
@@ -0,0 +1,66 @@
+#include "sys/alt_irq.h"
+//#include "osx_irq.h"
+
+#include "osx_timer.h"
+#include "altera_avalon_timer_regs.h"
+
+#include "alt_types.h"
+#include "unbosx_types.h"
+
+volatile clock_t _osx_nticks = 0;
+
+clock_t osx_clock( void ) {
+	return _osx_nticks;
+}
+/* 
+ * osx_timer_sc_irq() is the interrupt handler used for the system 
+ * clock. This is called periodically when a timer interrupt occurs. The 
+ * function first clears the interrupt condition, and then calls the 
+ * alt_tick() function to notify the system that a timer tick has occurred.
+ *
+ * alt_tick() increments the system tick count, and updates any registered 
+ * alarms, see alt_tick.c for further details.
+ */
+#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+static void osx_timer_sc_irq (void* base)
+#else
+static void osx_timer_sc_irq (void* base, alt_u32 id)
+#endif
+{
+  /* clear the interrupt */
+  IOWR_ALTERA_AVALON_TIMER_STATUS (base, 0);
+  
+  /* 
+   * Dummy read to ensure IRQ is negated before the ISR returns.
+   * The control register is read because reading the status
+   * register has side-effects per the register map documentation.
+   */
+  IORD_ALTERA_AVALON_TIMER_CONTROL (base);
+
+  _osx_nticks++;
+}
+
+/*
+ * osx_timer_sc_init() is called to initialise the timer that will be 
+ * used to provide the periodic system clock. This is called from the 
+ * auto-generated alt_sys_init() function.
+ */
+
+void osx_timer_sc_init (void* base, alt_u32 irq_controller_id, 
+                                alt_u32 irq, alt_u32 freq)
+{
+  /* set to free running mode */
+  
+  IOWR_ALTERA_AVALON_TIMER_CONTROL (base, 
+            ALTERA_AVALON_TIMER_CONTROL_ITO_MSK  |
+            ALTERA_AVALON_TIMER_CONTROL_CONT_MSK |
+            ALTERA_AVALON_TIMER_CONTROL_START_MSK);
+
+  /* register the interrupt handler, and enable the interrupt */
+#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+  alt_ic_isr_register(irq_controller_id, irq, osx_timer_sc_irq, 
+                      base, NULL);
+#else
+  alt_irq_register (irq, base, osx_timer_sc_irq);
+#endif  
+}
diff --git a/software/unb_osy/osx_timer.h b/software/unb_osy/osx_timer.h
new file mode 100644
index 0000000000000000000000000000000000000000..24485163a3c8b25a28c7294b6c088c10147d7bef
--- /dev/null
+++ b/software/unb_osy/osx_timer.h
@@ -0,0 +1,135 @@
+#ifndef OSX_TIMER_H
+#define OSX_TIMER_H
+
+#include "unbosx_types.h"
+#include "sys/alt_warning.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+#define __ALT_COUNTER_SIZE(name) name##_COUNTER_SIZE
+#define _ALT_COUNTER_SIZE(name) __ALT_COUNTER_SIZE(name)
+
+#define ALT_SYS_CLK_COUNTER_SIZE _ALT_COUNTER_SIZE(ALT_SYS_CLK)
+#define ALT_TIMESTAMP_COUNTER_SIZE _ALT_COUNTER_SIZE(ALT_TIMESTAMP_CLK)
+
+#if (ALT_SYS_CLK_COUNTER_SIZE == 64)
+#define alt_sysclk_type alt_u64
+#else
+#define alt_sysclk_type alt_u32
+#endif
+
+typedef alt_sysclk_type clock_t;
+
+clock_t osx_clock( void );
+
+/*
+ * The function alt_avalon_timer_sc_init() is the initialisation function for 
+ * the system clock. It registers the timers interrupt handler, and then calls 
+ * the system clock regestration function, alt_sysclk_init().
+ */
+
+extern void osx_timer_sc_init (void* base, alt_u32 irq_controller_id, 
+                                      alt_u32 irq, alt_u32 freq);
+
+
+/*
+ * ALTERA_AVALON_TIMER_INSTANCE is the macro used by alt_sys_init() to 
+ * allocate any per device memory that may be required. In this case no 
+ * allocation is necessary.
+ */ 
+
+#define ALTERA_AVALON_TIMER_INSTANCE(name, dev) extern int alt_no_storage
+
+/*
+ * Macro used to calculate the timer interrupt frequency. Although this is 
+ * somewhat fearsome, when compiled with -O2 it will be resolved at compile 
+ * time to a constant value.
+ */
+#define OSX_TIMER_FREQ(freq, period, units) \
+  ((units[0]=='s')?(((freq + (period - 1))/period)): \
+	( \
+	  (units[0]=='m')?((1000 + (period - 1))/period):\
+	  	( \
+		  	(units[0]=='u')?((1000000 + (period - 1))/period):1 \
+		) \
+	)\
+   )
+
+/*
+ * Construct macros which contain the base address of the system clock and the
+ * timestamp device. These are used below to determine which driver to use for
+ * a given timer.
+ */
+
+#define __ALT_CLK_BASE(name) name##_BASE
+#define _ALT_CLK_BASE(name) __ALT_CLK_BASE(name)
+
+#define ALT_SYS_CLK_BASE _ALT_CLK_BASE(ALT_SYS_CLK)
+#define ALT_TIMESTAMP_CLK_BASE _ALT_CLK_BASE(ALT_TIMESTAMP_CLK)
+
+/*
+ * If there is no system clock, then the above macro will result in 
+ * ALT_SYS_CLK_BASE being set to none_BASE. We therefore need to provide an
+ * invalid value for this, so that no timer is wrongly identified as the system
+ * clock.
+ */
+
+#define none_BASE 0xffffffff
+
+/*
+ * ALTERA_AVALON_TIMER_INIT is the macro used by alt_sys_init() to provide
+ * the run time initialisation of the device. In this case this translates to
+ * a call to alt_avalon_timer_sc_init() if the device is the system clock, i.e.
+ * if it has the name "sysclk".
+ *
+ * If the device is not the system clock, then it is used to provide the
+ * timestamp facility. 
+ *
+ * To ensure as much as possible is evaluated at compile time, rather than 
+ * compare the name of the device to "/dev/sysclk" using strcmp(), the base
+ * address of the device is compared to SYSCLK_BASE to determine whether it's
+ * the system clock. Since the base address of a device must be unique, these
+ * two aproaches are equivalent.
+ *
+ * This macro performs a sanity check to ensure that the interrupt has been
+ * connected for this device. If not, then an apropriate error message is 
+ * generated at build time.
+ */
+
+
+#define OSX_TIMER_INIT(name, dev)                                   \
+  if (name##_BASE == ALT_SYS_CLK_BASE)                                        \
+  {                                                                           \
+    if (name##_IRQ == ALT_IRQ_NOT_CONNECTED)                                  \
+    {                                                                         \
+      ALT_LINK_ERROR ("Error: Interrupt not connected for " #dev ". "         \
+                      "The system clock driver requires an interrupt to be "  \
+                      "connected. Please select an IRQ for this device in "   \
+                      "SOPC builder.");                                       \
+    }                                                                         \
+    else                                                                      \
+    {                                                                         \
+      osx_timer_sc_init((void*) name##_BASE,                           \
+                               name##_IRQ_INTERRUPT_CONTROLLER_ID,            \
+                               name##_IRQ,                                    \
+                               OSX_TIMER_FREQ(name##_FREQ,          \
+                                                        name##_PERIOD,        \
+                                                        name##_PERIOD_UNITS));\
+    }                                                                         \
+  } else { \
+      ALT_LINK_ERROR ("Not a system timer"); \
+  }
+
+/*
+ *
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ALT_AVALON_TIMER_H__ */
diff --git a/software/unb_osy/packet.c b/software/unb_osy/packet.c
new file mode 100644
index 0000000000000000000000000000000000000000..9aad88bc17c1ff9ff2b4ef0e0978e291861041eb
--- /dev/null
+++ b/software/unb_osy/packet.c
@@ -0,0 +1,422 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+/* Compile switches. */
+
+/* includes */
+#include <system.h>
+#include <packet.h>
+#include <unbos_pps.h>
+#include <unbos_eth.h>
+#include <unbosx_util.h>
+#include <io2_copy.h>
+
+/* Wether or not we actually _have_ flash, for bookeepingssake
+ * we remember wether we tried to initialize it.
+ * 42 is the signal that no-one has tried to init it.
+ * Otherwise it contains the actual initialization result
+ * (0 => OK, -1 => Dang!)
+ */
+static int didInitFlash = 42;
+
+/* Support this on designs that have it */
+#ifdef __ALTERA_AVALON_EPCS_FLASH_CONTROLLER 
+#include <altera_avalon_epcs_flash_controller.h>
+
+static alt_flash_epcs_dev tFlashDev = { 
+{  
+    ALT_LLIST_ENTRY,
+    "flash_dev",
+    NULL,                 /*open*/
+    NULL,                 /*close*/
+    alt_epcs_flash_write, /*write*/
+    alt_epcs_flash_read,  /*read*/
+    alt_epcs_flash_get_info, /*get info*/
+    alt_epcs_flash_erase_block,
+    alt_epcs_flash_write_block,
+    ((void*)EPCS_FLASH_CONTROLLER_0_BASE)
+  },
+  EPCS_FLASH_CONTROLLER_0_REGISTER_OFFSET + EPCS_FLASH_CONTROLLER_0_BASE
+};
+#else
+// No flash in this design - supply default implementations
+// of functions used below: keeps linker happy AND if they
+// would happen to be called, they return error.
+typedef int alt_flash_dev;
+typedef int alt_flash_epcs_dev;
+static alt_flash_epcs_dev tFlashDev;
+
+int alt_epcs_flash_init(alt_flash_epcs_dev* p) {
+    return -1;
+}
+int alt_epcs_flash_query(alt_flash_epcs_dev* p) {
+    return -1;
+}
+int alt_epcs_flash_write_block(alt_flash_dev* p, int notused, int i, const void* s, int l) {
+    return -1;
+}
+int alt_epcs_flash_read(alt_flash_dev* p, int i, const void* s, int l) {
+    return -1;
+}
+int alt_epcs_flash_erase_block(alt_flash_dev* p, int b) {
+    return -1;
+}
+
+#endif
+
+#define PKT_SIZE 1500
+
+// The UniBoard defined opcodes
+#define CONFIGE   ((alt_u32)0x8)
+#define CONFIGR   ((alt_u32)0x7)
+#define CONFIGW   ((alt_u32)0x6)
+#define READN     ((alt_u32)0x1)
+#define WRITEN    ((alt_u32)0x2)
+#define ANDN      ((alt_u32)0x3)
+#define ORN       ((alt_u32)0x4)
+#define XORN      ((alt_u32)0x5)
+#define FREADN    ((alt_u32)0x9)
+#define FWRITEN   ((alt_u32)0xa)
+#define BITWRITEN ((alt_u32)0xb)
+#define WAITPPS   ((alt_u32)0xffffffff)
+
+/* implicit external bitmask for updating bitfields,
+ * used by bit_write_f */
+alt_u32 bitfield_mask;
+
+/* for dealing with flash ... */
+int init_flash();
+alt_u32 init_flash_first_w(void* to, void* from);
+alt_u32 init_flash_first_r(void* to, void* from);
+alt_u32 init_flash_first_e(void* sectoraddr);
+alt_u32 flash_write_page(void* to, void* from);
+alt_u32 flash_read_page(void* to, void* from);
+alt_u32 flash_erase_sector(void* sectoraddr);
+alt_u32 no_flash_available(void* to, void* from);
+alt_u32 no_flash_available1(void* to);
+
+// Function pointer to the actual flash-write function.
+// We let it point at the initialization routine first
+static alt_u32 (*flash_writer)(void*, void*) = init_flash_first_w;
+static alt_u32 (*flash_reader)(void*, void*) = init_flash_first_r;
+static alt_u32 (*flash_eraser)(void*)        = init_flash_first_e;
+
+
+// Packet handler
+unsigned int handlePacket() {
+    if( !NET_IS_CONTROLPKT(eth_frmInfo) ) 
+		return 0;
+
+	TUInt32               tmp;
+	unsigned int          replySz;
+	const unsigned int    hdrSzByte = ((4/*eth*/ + 5/*ip*/ + 2/*udp*/)*4);
+
+	// Start processing commands. They start immediately following
+	// the UDP/IP header. Write the results into the reply packet,
+	// immediately following the UDP header
+	replySz = proc_packet( (alt_u32 volatile*)((unsigned char volatile* const)rx+hdrSzByte),
+			(alt_u32 volatile*)((unsigned char volatile* const)tx+hdrSzByte) );
+	// replySz is now in units of words. We need bytes
+	replySz *= 4;
+
+	// Update the IP and UDP headers with the reply size
+	// IP: TOTAL LENGTH field is lower 16 bits in header word 4
+	//     it is ip hdr + udp hdr + udp payload =
+	//           |---28 bytes --| + payloadsize
+	// UDP: SIZE is upper 16 bits in word 10 of the header
+	//     its value is   udp hdr + udp payload
+	//                  | 8 byte| + udp payload
+
+	// Get word 4 from the header (note: they are still in
+	// network byte order), clear the lower 16bits
+	//        tmp  = ntohl(NET_HDRWORD(ptReply, 4));
+	tmp  = UNBOSX_UTIL_ntohl(tx[4]);
+	tmp &= 0xffff0000;
+	tmp |= ((28+replySz)&0x0000ffff);
+	tx[4] = UNBOSX_UTIL_htonl(tmp);
+
+	// Id. for the UDP header
+	//        tmp  = ntohl(NET_HDRWORD(ptReply, 10));
+	tmp  = UNBOSX_UTIL_ntohl(tx[10]);
+	tmp &= 0x0000ffff;
+	tmp |= (((8+replySz)&0x0000ffff)<<16);
+	tx[10] = UNBOSX_UTIL_htonl(tmp);
+
+	// return the total replysize
+	return (44 + replySz);
+}
+
+
+alt_u32 and_f(alt_u32 l, alt_u32 r) {
+    return (l&r);
+}
+alt_u32 or_f(alt_u32 l, alt_u32 r) {
+    return (l|r);
+}
+alt_u32 xor_f(alt_u32 l, alt_u32 r) {
+    return (l^r);
+}
+
+/* Implicitly make use of the externally provided mask ... */
+alt_u32 bit_write_f(alt_u32 l, alt_u32 r) {
+	/* Clear the bitpositions in the current value */
+	l &= (~bitfield_mask);
+	return (l | (r&bitfield_mask));
+}
+
+alt_u32 apply(alt_u32* dst, alt_u32* src, unsigned int n, alt_u32 (*f)(alt_u32, alt_u32));
+
+static char const* const pps0 = "0PPS";
+static char const* const pps1 = "1PPS";
+/* start processing commands startting at "sop" (start of packet)
+ * building up the reply starting at "reply". 
+ * processing stops when a 0x00 command is encountered
+ * Returns the size of the reply
+ *
+ * As per the revised command format, all fields are by definition
+ * a multiple of four bytes AND the addresses are four-byte aligned.
+ * This makes processing a pakkit of commands mighty simple: we 
+ * do not have to copy field into local storage before we can use 
+ * them, we can create pointers and directly de-reference them!
+ * w00t.
+ */
+alt_u32 proc_packet(alt_u32 volatile* sop, alt_u32 volatile* reply) {
+    alt_u32           nitem;
+    alt_u32           address;
+    alt_u32*          data;
+    alt_u32           sinc, dinc;
+    alt_u32 volatile* begin_of_reply = reply;
+
+    /* Copy over the PSN */
+
+    *reply++ = *sop++;
+    while( *sop ) {
+		/* start with default source-inc and dest-inc of '1' */
+		sinc = dinc = 1;
+        switch( *sop ) {
+
+            case WAITPPS:
+				if( UNBOS_pps_wait() )
+					*((alt_u32*)reply) = *((alt_u32*)&pps1[0]);
+				else
+					*((alt_u32*)reply) = *((alt_u32*)&pps0[0]);
+				reply++;
+				sop++;
+                break;
+
+			case FREADN:
+				/* FIFO Read: do not increment source address */
+				sinc = 0;
+            case READN:
+                /* read n 32bit words, starting at address address */
+                /* N is the word following the READ command, the start address 
+                 * follows after that
+                 *   READN (32bit) N (32bit) ADDRESS (32bit)
+                 */
+                nitem   = *(sop+1);
+                address = *(sop+2);
+                if( io2_copy((void*)(reply+1), (void*)address, nitem, sinc, dinc)==0 ) {
+                    /* indicate failure */
+                    address = ~address;
+                    nitem   = 0;
+                }
+                *reply  = address;
+                reply  += (nitem+1);
+                /* Update pointer to start of next command */
+                sop += 3;
+                break;
+
+            case BITWRITEN:
+                /* modify n 32bit words from the packet to the range starting at address address,
+                 * using mask to update only part of the bits
+                 *   BITWRITEN (32bit) N (32bit) ADDRESS (32bit) MASK(32bit) DATA (N*32bit)
+                 */
+                nitem         = *(sop+1);
+                address       = *(sop+2);
+				/* set global bitfield mask before entering the apply function!*/
+                bitfield_mask = (alt_u32)(*(sop+3));
+                data          = (alt_u32*)(sop+4);
+                if( apply((alt_u32*)address, data, nitem, bit_write_f)==0 )
+                    address = ~address;
+                *reply++  = address;
+                sop      += (4+nitem);
+                break;
+                
+			case FWRITEN:
+				/* FIFO Write: do not increment dest address */
+				dinc = 0;
+            case WRITEN:
+            case ANDN:
+            case ORN:
+            case XORN:
+                /* modify n 32bit words from the packet to the range starting at address address
+                 *   WRITEN (32bit) N (32bit) ADDRESS (32bit) DATA (N*32bit)
+                 */
+                nitem   = *(sop+1);
+                address = *(sop+2);
+                data    =  (alt_u32*)(sop+3);
+                if( ((*sop==WRITEN || *sop==FWRITEN) && io2_copy((void*)address, (void*)data, nitem, sinc, dinc)==0) ||
+                    ((*sop==ANDN) && apply((alt_u32*)address, data, nitem, and_f)==0) ||
+                    ((*sop==ORN) && apply((alt_u32*)address, data, nitem, or_f)==0) ||
+                    ((*sop==XORN) && apply((alt_u32*)address, data, nitem, xor_f)==0) ) {
+                    /* indicate failure */
+                    address = ~address;
+                }
+                *reply++ = address; 
+                sop     += (nitem+3);
+                break;
+
+            case CONFIGW:
+                // write a single page of config data. 
+                // command format is
+                // CONFIGW (32bit) ADDRESS(32bit) DATA(256 bytes)
+                address = *(sop+1);
+                data    = (alt_u32*)(sop+2);
+                if( (*flash_writer)((void*)address, (void*)data)==0 )
+                    address = ~address;
+                *reply++ = address;
+                sop     += (2 + (256/sizeof(alt_u32)));
+                break;
+
+            case CONFIGR:
+                // read a single page of config data. 
+                // command format is
+                // CONFIGR (32bit) ADDRESS(32bit) 
+                // Skip one word in the reply (for the address or
+                // ~address) at which we write the actual data
+                address = *(sop+1);
+                data    =  (alt_u32*)(reply+1);
+                if( (*flash_reader)((void*)data, (void*)address)==0 ) {
+                    *reply++ = ~address;
+                } else {
+                    *reply++  = address;
+                    reply    += (256/sizeof(alt_u32));
+                }
+                // Skip over to the next command in the input sequence
+                sop     += 2;
+                break;
+
+            case CONFIGE:
+                // erase the config sector where the ADDRESS points into
+                // command format is
+                // CONFIGE (32bit) ADDRESS(32bit) 
+                address = *(sop+1);
+                if( (*flash_eraser)((void*)address)==0 )
+                    address = ~address;
+                *reply++ = address;
+                sop     += 2;
+                break;
+                
+            default:
+                break;
+        }
+    }
+    return (alt_u32)(reply - begin_of_reply);
+}
+
+
+
+alt_u32 apply(alt_u32* dst, alt_u32* src, unsigned int n, alt_u32 (*f)(alt_u32, alt_u32)) {
+    alt_u32 tmp;
+
+    if( (((alt_u32)dst) & 0x3) || (((alt_u32)src) & 0x3) )
+		return 0;
+
+    while( n-- ) {
+        tmp = IORD(dst, 0);
+        tmp = f(tmp, *src);
+        IOWR(dst, 0, tmp);
+        dst++; src++;
+    }
+    return 1;
+}
+
+int init_flash() {
+    if( didInitFlash==42 )
+        didInitFlash = alt_epcs_flash_init(&tFlashDev);
+    return didInitFlash;
+}
+
+alt_u32 init_flash_first_w(void* to, void* from) {
+    // depending on wether we succesfully initialized the
+    // flash device, set the actual flash-writer function
+    // and delegate the actual writing to there
+    if( init_flash()<0 ) {
+        flash_writer = no_flash_available;
+    } else {
+        flash_writer = flash_write_page;
+    }
+    return (*flash_writer)(to, from);
+}
+alt_u32 init_flash_first_r(void* to, void* from) {
+    // depending on wether we succesfully initialized the
+    // flash device, set the actual flash-writer function
+    // and delegate the actual writing to there
+    if( init_flash()<0 ) {
+        flash_reader = no_flash_available;
+    } else {
+        flash_reader = flash_read_page;
+    }
+    return (*flash_reader)(to, from);
+}
+alt_u32 init_flash_first_e(void* sectoraddress) {
+    // depending on wether we succesfully initialized the
+    // flash device, set the actual flash-eraser function
+    // and delegate the actual erasing to there
+    if( init_flash()<0 ) {
+        flash_eraser = no_flash_available1;
+    } else {
+        flash_eraser = flash_erase_sector;
+    }
+    return (*flash_eraser)(sectoraddress);
+}
+
+// write one page of flashdata to the FLASH-address "to"
+// the pages are 256 bytes each
+alt_u32 flash_write_page(void* to, void* from) {
+    if( alt_epcs_flash_write_block((alt_flash_dev*)&tFlashDev, 0, (int)to, from, 256)<0 )
+        return 0;
+    return 1;
+}
+// read one page of flashdata from the FLASH-address "from"
+// the pages are 256 bytes each
+alt_u32 flash_read_page(void* to, void* from) {
+    if( alt_epcs_flash_read((alt_flash_dev*)&tFlashDev, (int)from, to, 256)<0 )
+        return 0;
+    return 1;
+}
+// erase the sector that sectoroffset is in
+alt_u32 flash_erase_sector(void* sectoroffset) {
+    if( alt_epcs_flash_erase_block((alt_flash_dev*)&tFlashDev, (int)sectoroffset)<0 )
+        return 0;
+    return 1;
+}
+
+// the design has no flash - indicate failure
+alt_u32 no_flash_available(void* i, void* o) {
+    return 0;
+}
+
+alt_u32 no_flash_available1(void* i) {
+    return no_flash_available(i, (void*)0);
+}
+
diff --git a/software/unb_osy/packet.h b/software/unb_osy/packet.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cf515d8d39e0d422c3618abb3c8d072cd963875
--- /dev/null
+++ b/software/unb_osy/packet.h
@@ -0,0 +1,8 @@
+/* process a network packet */
+#include <alt_types.h>
+
+unsigned int handlePacket();
+
+alt_u32 proc_packet(alt_u32 volatile* sop, alt_u32 volatile* reply);
+
+
diff --git a/software/unb_osy/unbos_eth.c b/software/unb_osy/unbos_eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..bfb8d5611b9ece122fccc539b5edbba817e546e7
--- /dev/null
+++ b/software/unb_osy/unbos_eth.c
@@ -0,0 +1,462 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+/* Compile switches. */
+
+/* includes */
+#include <unbos_eth.h>
+#include <unbos_i2c.h>
+#include <osx_stdio.h>
+#include <sys/alt_irq.h>
+#include <altera_avalon_pio_regs.h>
+#include <unbosx_eth_regs.h>
+#include <io2_copy.h>
+
+TUInt32                 netIP       = 0;
+TUInt32                 netIP_nwbo  = 0;
+volatile TUInt32        eth_status  = 0;
+volatile TUInt32        eth_frmInfo = 0;
+TUInt32 volatile* const rx          = (TUInt32 volatile* const)(AVS_ETH_0_MMS_RAM_BASE+ETH_RX_RAM_BASE);
+TUInt32 volatile* const tx          = (TUInt32 volatile* const)(AVS_ETH_0_MMS_RAM_BASE+ETH_TX_RAM_BASE);
+
+
+void UNBOSX_NET_Send(unsigned int nbyte) {
+	TUInt32      words, empty, ctrl = AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK;
+
+	// assume outsize is already including 2byte padding
+	words = nbyte/4;
+	empty = (4 - nbyte%4);
+
+	// If the packet extends into a word (not filling it)
+	// we must inc the number of words and set the number
+	// of empty bytes accordingly
+	words += ((empty==4)?0:1);
+	empty  = ((empty==4)?0:empty);
+
+	// prepare the new control-register-variable
+	ctrl |= (words << AVS_ETH_REG_CONTROL_TX_NOF_WORDS_BIT_OFST);
+	ctrl |= (empty << AVS_ETH_REG_CONTROL_TX_EMPTY_BIT_OFST);
+	ctrl |= AVS_ETH_REG_CONTROL_TX_EN_BIT_MASK;
+
+    // Now write new value of control register and the continue reg
+    WRREG(AVS_ETH_REG_CONTROL_WI, ctrl);
+	  // clear global status
+  	eth_status  = 0;
+  	eth_frmInfo = 0;
+    WRREG(AVS_ETH_REG_CONTINUE_WI, 0);
+}
+
+void UNBOSX_NET_Discard() {
+    // Now write new value of control register and the continue reg
+    WRREG(AVS_ETH_REG_CONTROL_WI, AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK);
+	  // clear global status
+  	eth_status  = 0;
+  	eth_frmInfo = 0;
+    WRREG(AVS_ETH_REG_CONTINUE_WI, 0);
+}
+
+#if 0
+// IPv4 address is at maximum 4*3 digits + 3 dots + 1 NUL character = 16 characters
+char const* NET_inet_ntoa(const TUInt32 ipv4addr) {
+	static char                buffer[16];
+	unsigned const char* const ip = (unsigned const char* const)(&ipv4addr);
+	osx_sprintf(buffer, "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]);
+	return &buffer[0];
+}
+#endif
+#if 0
+// Return the timedifference in clock_t ticks 
+// between new and old.
+clock_t delta_t(clock_t old_t, clock_t new_t) {
+    const clock_t cClockMax = ~((~(clock_t)0)+1);
+    // if new_t < old_t assume the counter wrapped
+    if( new_t<old_t )
+        return cClockMax - (old_t-new_t);
+    else
+        return new_t - old_t;
+}
+#endif
+
+#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+static void net_isr(void* context);
+#else
+static void net_isr(void* context, alt_u32 id);
+#endif
+
+/* Set up the network card */
+void UNBOSX_NET_Setup() {
+	TUInt32            netMAChi   = UNB_ETH_SRC_MAC_BASE_HI;
+	TUInt32            netMAClo   = (UNB_ETH_SRC_MAC_BASE_LO<<16);
+  TUInt32            base_ip    = (TUInt32)AVS_ETH_REG_RD(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_CONFIG_WI+2); 
+
+#if defined(COMPILE_FOR_GEN2_UNB2)
+#warning "Compiling for UNB2"
+	const TUInt32      node      = UNBOSX_unb2_GetNodeNumber();
+	const TUInt32      backplane = UNBOSX_unb2_GetBackplaneId();
+    osx_printf("backplane %d node %cN %d\n",
+               backplane, 
+               (UNBOSX_unb2_IsBacknode()?'B':'F'),
+	       node);
+#else
+#warning "Compiling for UNB1"
+	const TUInt32      node      = UNBOSX_GetNodeNumber();
+	const TUInt32      backplane = UNBOSX_GetBackplaneId();
+    osx_printf("backplane %d node %cN %d\n",
+               backplane, 
+               (UNBOSX_IsBacknode()?'B':'F'),
+	       node);
+#endif
+
+     /* Use the ip range 10.99.xx.yy where 
+     *               xx = UNB_System_Info.bck_id [backplane ID]
+     *               yy = (UNB_System_Info.id + 1)
+     *                    [0-3] = frontnode
+     *                    [4-7] = backnode
+     */
+    if (base_ip==0) {
+      netIP      = (TUInt32)0x0a630000 + (backplane<<8) + node + 1;
+    } else {
+      netIP      = base_ip + (backplane<<8) + node + 1;
+    }
+
+	  netIP_nwbo = UNBOSX_UTIL_htonl(netIP);
+    netMAClo   = (UNB_ETH_SRC_MAC_BASE_LO<<16) + (backplane<<8) + node;
+
+    /* Now it's time to actually set things up */
+    UNBOSX_ETH_Init_ISR(net_isr, 0);
+    UNBOSX_ETH_Setup(UNBOSX_G_SIM(),
+              netMAChi, netMAClo, ETH_FRAME_LENGTH,
+              netIP, 5000 /*UNB_UDP_PORT_CTRL*/, 0, 0, 0);
+
+    osx_printf("setup_tse: ip=%d.%d.%d.%d\n",
+                netIP>>24, (netIP>>16)&0xff, (netIP>>8)&0xff, netIP&0xff);
+
+    // and switch on rx_enable
+	WRREG(AVS_ETH_REG_CONTROL_WI, AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK);
+	WRREG(AVS_ETH_REG_CONTINUE_WI, 0);
+    return;
+}
+
+/* If it is an IPv4-ARP packet then word 4 in the rx buffer
+ * should look like this in NetworkByteOrder.
+ * This can be precomputed such that the ISR doesn't have
+ * to swap bytes */
+static const TUInt32 IPv4Arp_nwbo   = (UNBOSX_UTIL_htonl(((1<<16)+0x0800)));
+static const TUInt32 ArpReqMsk_nwbo = (UNBOSX_UTIL_htonl(0x0000ffff));
+static const TUInt32 ArpReqOne_nwbo = (UNBOSX_UTIL_htonl(1));
+
+#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+static void net_isr(void* context) {
+#else
+static void net_isr(void* context, alt_u32 id) {
+#endif
+	/*
+	 * If the ctrl reg at some point becomes !0 this indicates
+	 * that WE (the ISR) have handled the packet - so we write
+	 * it back to the hardware
+	 * If the frmInfo != 0 at the end of the ISR, this means
+	 * that that the user has to deal with the packet and 
+	 * we don't do nothing
+	 */
+	TUInt32          ctrl = 0;
+	volatile TUInt32 tmp;
+
+    eth_status  = RDREG(AVS_ETH_REG_STATUS_WI);
+	eth_frmInfo = (TUInt32)RDREG(AVS_ETH_REG_FRAME_WI); 
+	// If there was in incoming packet, check if we deal with it *now*
+    if( RXAVAIL(eth_status) ) {
+        // If someone was looking for US (ARP request with us as target)
+        // then handle it here rather than passing it up the chain
+		TUInt32  isARP   = NET_FLAGCHECK(eth_frmInfo, IS_ARP_BIT_MASK);
+		TUInt32  isICMP  = NET_FLAGCHECK(eth_frmInfo, IS_ICMP_BIT_MASK);
+
+
+        // Only look at IP ARP requests
+        // Note: do not check the MAC_ADDRESS_MATCH_BIT_MASK in the
+        //       status reg - ARP requests are typically eth broadcasts.
+        //       If the ARP-IP-REQUEST-FOR-OUR-IP did not come from
+        //       an ethernet broadcast ... who cares!
+		if( isARP ) {
+            // Check if:
+			// - It *is* an ARP request AND
+			// - Target Protocol == IPv4 AND
+			// - Target Protocol Address == Our IP Address
+          
+		   	// We recognized this packet as ARP - it may or may
+			// not be for us that's not important right now	
+			// We *always* handle these packets - so we *always* must
+			// write the control register since either:
+			//  * we want to send the cooked reply, or,
+			//  * we want to discard it and immediately go back to
+			//    receiving the next packet
+			// This is done by setting the RX_ENABLE bit.
+			// The TX enable bit will be set conditionally
+			ctrl = AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK;
+
+			if( (RDRX(4)==IPv4Arp_nwbo) &&
+				((RDRX(5)&ArpReqMsk_nwbo)==ArpReqOne_nwbo) &&
+				(RDRX(10)==netIP_nwbo) ) {
+                // Great. Someone was loox0ring just for US.
+                // The hardware (thanks Eric!) has prepared the answer
+                // already in the TX buffer. Set it off and let the rest
+                // of the system forget about this pakkit
+                // send whatever is in the TX buffer
+                // The ip arp packet is exactly 11 32bit words long 
+                //   (so make sure the "empty" bit field contains 0)
+				ctrl |= (11 << AVS_ETH_REG_CONTROL_TX_NOF_WORDS_BIT_OFST);
+				ctrl &= ~AVS_ETH_REG_CONTROL_TX_EMPTY_BIT_MASK;
+				ctrl |= AVS_ETH_REG_CONTROL_TX_EN_BIT_MASK;
+            }
+			eth_frmInfo = 0;
+			eth_status  = 0;
+        }
+		
+        // Or ICMP ECHO? directed at us
+		if( isICMP ) {
+			// Packet is ICMP - update stats. It may or may not be for us
+			// but that doesn't matter right now
+			// Indicate we already dealt with this'un
+			
+			// Again, as with the ARP thingy, we *always* tell the h/w
+			// what to do next. Sending the precooked reply is optional.
+			//
+			// Sending the reply depends, critically, on wether it was an ICMP echo request
+			// directed at us
+			ctrl = AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK;
+
+			if( NET_FLAGCHECK(eth_frmInfo, MAC_ADDRESS_MATCH_BIT_MASK) && /* our MAC, so far so good */
+    	        NET_FLAGCHECK(eth_frmInfo, IP_ADDRESS_MATCH_BIT_MASK) && /* our IP! */
+        	    ((UNBOSX_UTIL_ntohl(RDRX(9))>>24)==8) /* ICMP code 8 == "ECHO?" */ ) {
+				// Cool. The request was and ECHO REQUEST directed directly at US
+				// So 'code' becomes 0 (== ECHO REPLY)
+				// But the hardware has already done that.
+				// The hardware has NOT copied the payload across yet so we must do that
+				// (NOTE: it _has_ already copied over the first 11 words)
+				io2_copy(tx+11, rx+11, NWORD(eth_status)-11, 1, 1);
+
+				// All that's left is to make sure that the number of 
+				// bytes in the control reg are set correctly
+				ctrl |= ((NWORD(eth_status)-1) << AVS_ETH_REG_CONTROL_TX_NOF_WORDS_BIT_OFST);
+				ctrl |= (NEMPTY(eth_status) << AVS_ETH_REG_CONTROL_TX_EMPTY_BIT_OFST);
+				ctrl |= AVS_ETH_REG_CONTROL_TX_EN_BIT_MASK;
+			}
+			eth_frmInfo = 0;
+			eth_status  = 0;
+        }
+    }
+
+    // Write a '0' in order to clear the in-tar-upt source
+    WRREG(AVS_ETH_REG_STATUS_WI, 0);
+    // wait until interrupt source has cleared
+    do {
+        tmp = RDREG(AVS_ETH_REG_STATUS_WI);
+    } while( tmp!=0 );
+    // Now write new value of control register and the continue reg
+	// (ctrl != 0 => the h/w should continue)
+	if( eth_frmInfo==0 ) {	
+	    WRREG(AVS_ETH_REG_CONTROL_WI, ctrl|AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK);
+	    WRREG(AVS_ETH_REG_CONTINUE_WI, 0);
+	}
+}
+
+
+/* ... */
+void UNBOSX_ETH_Init_ISR(isr_func_type isr_fn, void *p_isr_context) {
+	// Hook the ISR
+#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+	alt_ic_isr_register(AVS_ETH_0_MMS_REG_IRQ_INTERRUPT_CONTROLLER_ID,
+				AVS_ETH_0_MMS_REG_IRQ,
+				isr_fn,
+				p_isr_context,
+				(void*)0);
+#else
+	alt_irq_register(AVS_ETH_0_MMS_REG_IRQ, p_isr_context, isr_fn);
+#endif
+}
+
+/* announce prototype */
+static void UNBOSX_TSE_Setup(TBool g_sim, TUInt32 src_mac_hi, TUInt32 src_mac_lo, TUInt32 frm_length);
+
+/*------------------------------------------------------------------------------
+ * Function name:  ETH_Setup
+ * Parameters:     g_sim          = When true then running in simulation, else on hardware
+ *                 src_mac_hi     = 0x1234,
+ *                 src_mac_lo     = 0x56789ABC for MAC address 12-34-56-78-9A-BC
+ *                 frm_length     = 1518 octets for ethernet, up to 9000 for jumbo
+ *                 src_ip         = 0x07060504;  -- = 07:06:05:04
+ *                 udp_port_ctrl  = Control UDP port number
+ *                 udp_port_data0 = Streaming data UDP port 0 number + enable bit mask
+ *                 udp_port_data1 = Streaming data UDP port 1 number + enable bit mask
+ *                 udp_port_data2 = Streaming data UDP port 2 number + enable bit mask
+ * Return:         -
+ * Description:    Set up the ETH registers, similar to p_eth_control in
+ *                 modules\tse\src\vhdl\tb_eth.vhd and call TSE_Setup to set up
+ *                 the TSE MAC.
+ *------------------------------------------------------------------------------
+ */
+void UNBOSX_ETH_Setup(TBool   g_sim,
+               TUInt32 src_mac_hi, TUInt32 src_mac_lo, TUInt32 frm_length, TUInt32 src_ip, TUInt32 udp_port_ctrl,
+               TUInt32 udp_port_data0, TUInt32 udp_port_data1, TUInt32 udp_port_data2)
+{
+  // Setup the DEMUX UDP
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_DEMUX_WI+0, udp_port_data0);
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_DEMUX_WI+1, udp_port_data1);
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_DEMUX_WI+2, udp_port_data2);
+  
+  // Setup the RX CONFIG
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_CONFIG_WI+0, src_mac_lo);
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_CONFIG_WI+1, src_mac_hi);
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_CONFIG_WI+2, src_ip);
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_CONFIG_WI+3, udp_port_ctrl);
+  
+  // Enable RX
+  AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, AVS_ETH_REG_CONTROL_WI, AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK);
+  
+  // Setup the TSE MAC
+  UNBOSX_TSE_Setup(g_sim, src_mac_hi, src_mac_lo, frm_length);
+}
+
+/*------------------------------------------------------------------------------
+ * Function name:  TSE_Setup
+ * Parameters:     g_sim      = When true then running in simulation, else on hardware
+ *                 src_mac_hi = 0x1234,
+ *                 src_mac_lo = 0x56789ABC for MAC address 12-34-56-78-9A-BC
+ *                 frm_length = 1518 octets for ethernet, up to 9000 for jumbo
+ * Return:         -
+ * Description:    Set up the TSE MAC, similar to proc_tse_setup in
+ *                 modules\tse\src\vhdl\tb_tse(pkg).vhd. The read accesses
+ *                 are void, because the result is not used further.
+ *------------------------------------------------------------------------------
+ */
+static void UNBOSX_TSE_Setup(TBool g_sim, TUInt32 src_mac_hi, TUInt32 src_mac_lo, TUInt32 frm_length) {
+  TUInt16 pcs_data;
+  TUInt32 mac_data;
+  TUInt32 mac_0;
+  TUInt32 mac_1;
+  
+  // PSC control
+  pcs_data = AVS_ETH_TSE_PCS_RD(AVS_ETH_0_MMS_TSE_BASE, 0x22);  // REV --> 0x0901
+  AVS_ETH_TSE_PCS_WR(AVS_ETH_0_MMS_TSE_BASE, 0x28, 0x0008);     // IF_MODE <-- 0x0008 = Enable 1000BASE-X gigabit mode and gigabit speed
+  pcs_data = AVS_ETH_TSE_PCS_RD(AVS_ETH_0_MMS_TSE_BASE, 0x00);  // CONTROL --> 0x1140 = Gigabit speed and full duplex (RO), auto-negotiation enabled (RW)
+  pcs_data = AVS_ETH_TSE_PCS_RD(AVS_ETH_0_MMS_TSE_BASE, 0x02);  // STATUS --> 0x002D
+  #if ETH_LOOPBACK_PCS == FALSE
+  #define LOOP_PCS  0
+  #else
+  #define LOOP_PCS (0x4000)
+  #endif
+  if (g_sim==FALSE) {
+    AVS_ETH_TSE_PCS_WR(AVS_ETH_0_MMS_TSE_BASE, 0x00, 0x1140 + LOOP_PCS);  // CONTROL <-- Keep auto negotiate enabled (is reset default)
+  } else {
+    AVS_ETH_TSE_PCS_WR(AVS_ETH_0_MMS_TSE_BASE, 0x00, 0x0140 + LOOP_PCS);  // CONTROL <-- In simulation disable auto negotiate
+  }
+  
+  // MAC control
+  mac_data = AVS_ETH_TSE_MAC_RD(AVS_ETH_0_MMS_TSE_BASE, 0x000);   // REV --> CUST_VERSION & 0x0901
+  
+  // COMMAND_CONFIG bits
+  // Only the bits relevant to UniBoard are explained here, others are 0
+  // [    0] = TX_ENA             = 1, enable tx datapath
+  // [    1] = RX_ENA             = 1, enable rx datapath
+  // [    2] = XON_GEN            = 0
+  // [    3] = ETH_SPEED          = 1, enable 1GbE operation
+  // [    4] = PROMIS_EN          = 0, when 1 then receive all frames
+  // [    5] = PAD_EN             = 0, when 1 enable receive padding removal (requires ethertype=payload length)
+  // [    6] = CRC_FWD            = 1, enable receive CRC forward
+  // [    7] = PAUSE_FWD          = 0
+  // [    8] = PAUSE_IGNORE       = 0
+  // [    9] = TX_ADDR_INS        = 0, when 1 then MAX overwrites tx SRC MAC with mac_0,1 or one of the supplemental mac
+  // [   10] = HD_ENA             = 0
+  // [   11] = EXCESS_COL         = 0
+  // [   12] = LATE_COL           = 0
+  // [   13] = SW_RESET           = 0, when 1 MAC disables tx and rx, clear statistics and flushes receive FIFO
+  // [   14] = MHAS_SEL           = 0, select multicast address resolutions hash-code mode
+  // [   15] = LOOP_ENA           = 0
+  // [18-16] = TX_ADDR_SEL[2:0]   = 000, TX_ADDR_INS insert mac_0,1 or one of the supplemental mac
+  // [   19] = MAGIC_EN           = 0
+  // [   20] = SLEEP              = 0
+  // [   21] = WAKEUP             = 0
+  // [   22] = XOFF_GEN           = 0
+  // [   23] = CNT_FRM_ENA        = 0
+  // [   24] = NO_LGTH_CHECK      = 1, when 0 then check payload length of received frames (requires ethertype=payload length)
+  // [   25] = ENA_10             = 0
+  // [   26] = RX_ERR_DISC        = 0, when 1 then discard erroneous frames (requires store and forward mode, so rx_section_full=0)
+  //                                   when 0 then pass on with rx_err[0]=1
+  // [   27] = DISABLE_RD_TIMEOUT = 0
+  // [30-28] = RSVD               = 000
+  // [   31] = CNT_RESET          = 0, when 1 clear statistics
+  #if ETH_LOOPBACK_MAC==FALSE
+  #define LOOP_ENA  0
+  #else
+  #define LOOP_ENA (0x00008000)
+  #endif
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x008, 0x0100004B + LOOP_ENA);  // COMMAND_CONFIG <--
+
+  // The SRC_MAC address for the TSE MAC needs to be in big endian
+  // Example:
+  // - MAC address 12-34-56-78-9A-BC
+  // - Input little endian:
+  //   . src_mac_lo    = 0x56789ABC
+  //   . src_mac_hi    = 0x1234
+  // - Output big endian:
+  //   . mac_0    = 0x78563412
+  //   . mac_1    = 0xBC9A
+  mac_0 = UNBOSX_UTIL_htonl(((src_mac_hi << 16) + (src_mac_lo >> 16)));
+  mac_1 = UNBOSX_UTIL_htonl(src_mac_lo << 16);
+  
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x00C, mac_0);  // MAC_0
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x010, mac_1);  // MAC_1
+  
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x05C, 0x0000000C);  // X_IPG_LENGTH <-- interpacket gap = 12
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x014, frm_length);  // FRM_LENGTH <-- receive max frame length = 1518
+
+  // FIFO legenda:
+  // . Tx section full  = There is enough data in the FIFO to start reading it, when 0 then store and forward.
+  // . Rx section full  = There is enough data in the FIFO to start reading it, when 0 then store and forward.
+  // . Tx section empty = There is not much empty space anymore in the FIFO, warn user via ff_tx_septy
+  // . Rx section empty = There is not much empty space anymore in the FIFO, inform remote device via XOFF flow control
+  // . Tx almost full   = Assert ff_tx_a_full and deassert ff_tx_rdy. Furthermore TX_ALMOST_FULL = c_tx_ready_latency+3,
+  //                      so choose 3 for zero tx ready latency
+  // . Rx almost full   = Assert ff_rx_a_full and if the user is not ready ff_rx_rdy then:
+  //                      --> break off the reception with an error to avoid FIFO overflow
+  // . Tx almost empty  = Assert ff_tx_a_empty and if the FIFO does not contain a eop yet then:
+  //                      --> break off the transmission with an error to avoid FIFO underflow
+  // . Rx almost empty  = Assert ff_rx_a_empty
+  // Typical FIFO values:
+  // . TX_SECTION_FULL  = 16   > 8   = TX_ALMOST_EMPTY
+  // . RX_SECTION_FULL  = 16   > 8   = RX_ALMOST_EMPTY
+  // . TX_SECTION_EMPTY = D-16 < D-3 = Tx FIFO depth - TX_ALMOST_FULL
+  // . RX_SECTION_EMPTY = D-16 < D-8 = Rx FIFO depth - RX_ALMOST_FULL
+  // . c_tse_tx_fifo_depth = 1 M9K = 256*32b = 1k * 8b is sufficient when the Tx user respects ff_tx_rdy, to store a complete
+  //                         ETH packet would require 1518 byte, so 2 M9K = 2k * 8b
+  // . c_tse_rx_fifo_depth = 1 M9K = 256*32b = 1k * 8b is sufficient when the Rx user ff_rx_rdy is sufficiently active
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x01C,   AVS_ETH_TSE_RX_FIFO_DEPTH-16);  // RX_SECTION_EMPTY <-- default FIFO depth - 16, >3
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x020,                             16);  // RX_SECTION_FULL  <-- default 16
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x024,   AVS_ETH_TSE_TX_FIFO_DEPTH-16);  // TX_SECTION_EMPTY <-- default FIFO depth - 16, >3
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x028,                             16);  // TX_SECTION_FULL  <-- default 16, >~ 8 otherwise no tx
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x02C,                              8);  // RX_ALMOST_EMPTY  <-- default 8
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x030,                              8);  // RX_ALMOST_FULL   <-- default 8
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x034,                              8);  // TX_ALMOST_EMPTY  <-- default 8
+  AVS_ETH_TSE_MAC_WR(AVS_ETH_0_MMS_TSE_BASE, 0x038, AVS_ETH_TSE_TX_READY_LATENCY+3);  // TX_ALMOST_FULL   <-- default 3
+
+  mac_data = AVS_ETH_TSE_MAC_RD(AVS_ETH_0_MMS_TSE_BASE, 0x0E8);   // TX_CMD_STAT --> 0x00040000 : [18]=1 TX_SHIFT16, [17]=0 OMIT_CRC
+  mac_data = AVS_ETH_TSE_MAC_RD(AVS_ETH_0_MMS_TSE_BASE, 0x0EC);   // RX_CMD_STAT --> 0x02000000 : [25]=1 RX_SHIFT16
+}
diff --git a/software/unb_osy/unbos_eth.h b/software/unb_osy/unbos_eth.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a16a87f039dfd870d39070b00c804fe7785d5d7
--- /dev/null
+++ b/software/unb_osy/unbos_eth.h
@@ -0,0 +1,131 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+#ifndef UNBOS_ETH_H
+#define UNBOS_ETH_H
+
+/* includes */
+#include <system.h>
+#include <unbosx_types.h>
+#include <unbosx_eth_regs.h>
+#include <unbosx_util.h>
+
+/* We ABSOLUTELY need the AVS_ETH thingamabob so we're not going to
+ * conditionally compile this file */
+
+// Start address of the rx and tx frame in the frame buffer
+#define ETH_RX_RAM_BASE                0
+#define ETH_TX_RAM_BASE                (AVS_ETH_0_MMS_RAM_SPAN/2)
+#define ETH_FRAME_LENGTH               1518
+#define UNB_ETH_SRC_MAC_BASE           ((TUInt32)0x00228608)
+#define UNB_ETH_SRC_MAC_BASE_HI        ((UNB_ETH_SRC_MAC_BASE >> 16) & 0xFFFF)
+#define UNB_ETH_SRC_MAC_BASE_LO        ( UNB_ETH_SRC_MAC_BASE & 0xFFFF)
+
+#if 0
+/* translate an ip number to ASCII 'dotted quad' format */
+char const* NET_inet_ntoa(const TUInt32 ipv4addr);
+#endif
+
+/* Initialize the ETH hardware and this module */
+void UNBOSX_NET_Setup(void);
+
+/* send nbyte from TX buffer to network.
+ * it is YOUR responsibility to make sure there is 
+ * a valid packet there
+ *
+ * NOTE: you HAVE to take into account that the 
+ *       first two bytes in the TX buffer are padding bytes
+ *       so the amount of bytes you wish to send should
+ *       be 2 larger than you actually think
+ */
+void         UNBOSX_NET_Send(unsigned int nbyte);
+
+/* this lets the main loop decide to not send a reply but
+ * discard whatever's in the TX buffer. Reenables RX'ing 
+ * packets. TX buffer contents will be lost.
+ */
+void         UNBOSX_NET_Discard();
+/* Uses the WORDS and EMPTY fields in the status to work out how many
+ * bytes were received */
+//unsigned int NET_BytesReceived(TUInt32 status);
+
+// The AVS ETH has two regs: a control and a status one
+// Upon receipt of a packet eth_frmInfo != 0
+extern volatile TUInt32   eth_status;
+extern volatile TUInt32   eth_frmInfo;
+
+/*
+ * Two buffers: one for RX and one for TX
+ *    * Remember the actual start of the ethernetheader
+ *      (the first header you must write in the
+ *       packetbuffer) starts at byte #2. Byte 0 and 1
+ *       in the buffer are padding bytes in order to
+ *       make, eventually, the IP and/or UDP payloads
+ *       start at a 4-byte-aligned address.
+ *    * When done, set the member to the full
+ *      packetssize + 2 bytes (for the padding, remember).
+ */
+
+extern TUInt32 volatile* const rx;
+extern TUInt32 volatile* const tx;
+
+// Shorthands for inspecting/extracting bits from the status register
+#define TXAVAIL(status) ((status&AVS_ETH_REG_STATUS_TX_AVAIL_BIT_MASK)==AVS_ETH_REG_STATUS_TX_AVAIL_BIT_MASK)
+#define RXAVAIL(status) ((status&AVS_ETH_REG_STATUS_RX_AVAIL_BIT_MASK)==AVS_ETH_REG_STATUS_RX_AVAIL_BIT_MASK)
+#define NWORD(status)   ((status&AVS_ETH_REG_STATUS_RX_NOF_WORDS_BIT_MASK)>>AVS_ETH_REG_STATUS_RX_NOF_WORDS_BIT_OFST)
+#define NEMPTY(status)  ((status&AVS_ETH_REG_STATUS_RX_EMPTY_BIT_MASK)>>AVS_ETH_REG_STATUS_RX_EMPTY_BIT_OFST)
+
+// Shorthands for reading/writing regiters and RAM buffers
+#define RDRX(idx)       ((TUInt32)AVS_ETH_RAM_RD(AVS_ETH_0_MMS_RAM_BASE+ETH_RX_RAM_BASE, idx))
+#define RDTX(idx)       ((TUInt32)AVS_ETH_RAM_RD(AVS_ETH_0_MMS_RAM_BASE+ETH_TX_RAM_BASE, idx))
+#define WRTX(idx, w)    (AVS_ETH_RAM_WR(AVS_ETH_0_MMS_RAM_BASE+ETH_TX_RAM_BASE, idx, w))
+#define RDREG(idx)      ((TUInt32)AVS_ETH_REG_RD(AVS_ETH_0_MMS_REG_BASE, idx))
+#define WRREG(idx, w)   (AVS_ETH_REG_WR(AVS_ETH_0_MMS_REG_BASE, idx, w))
+
+// The AVS_ETH module sets flags in the frameInfo register depending on what kind of
+// packet is received. Use these shorthands for easy access to them.
+#define NET_FLAGCHECK(frameInfo,flag) \
+    ((frameInfo&AVS_ETH_REG_FRAME_##flag)==AVS_ETH_REG_FRAME_##flag)
+#define NET_CHECK(frameInfo,flag) \
+    NET_FLAGCHECK(frameInfo,flag)
+#define NET_IS_ARP(frameInfo)        NET_CHECK(frameInfo, IS_ARP_BIT_MASK)
+#define NET_IS_IP(frameInfo)         NET_CHECK(frameInfo, IS_IP_BIT_MASK)
+#define NET_IPCHECKSUM_OK(frameInfo) NET_CHECK(frameInfo, IP_CHECKSUM_OK_BIT_MASK)
+#define NET_IS_ICMP(frameInfo)       NET_CHECK(frameInfo, IS_ICMP_BIT_MASK)
+#define NET_IS_UDP(frameInfo)        NET_CHECK(frameInfo, IS_UDP_BIT_MASK)
+#define NET_IS_CONTROLPKT(frameInfo) NET_CHECK(frameInfo, IS_UDP_CTRL_PORT_BIT_MASK)
+
+/* depending on what kind of interrupt API we set the type of ISR function pointer we expect */
+#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+typedef void (*isr_func_type)(void*);
+#else
+typedef void (*isr_func_type)(void*, alt_u32);
+#endif
+
+/* Init + install the ISR of your choice */
+void UNBOSX_ETH_Init_ISR(isr_func_type isr_fn, void *p_isr_context);
+
+/* Setup the AVS_ETH module with a MAC address and other IP properties */
+void UNBOSX_ETH_Setup(TBool   g_sim,
+               TUInt32 src_mac_hi, TUInt32 src_mac_lo, TUInt32 frm_length, TUInt32 src_ip, TUInt32 udp_port_ctrl,
+               TUInt32 udp_port_data0, TUInt32 udp_port_data1, TUInt32 udp_port_data2);
+
+#endif // UNBOS_ETH_H
diff --git a/software/unb_osy/unbos_i2c.c b/software/unb_osy/unbos_i2c.c
new file mode 100644
index 0000000000000000000000000000000000000000..fdda6037a875a842f9289ea6613dea309c6a3991
--- /dev/null
+++ b/software/unb_osy/unbos_i2c.c
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+#include <unbos_i2c.h>
+
+/* Compile switches. */
+
+/* includes */
+#include "system.h"
+
+#ifdef __AVS_I2C_MASTER
+    // System has I2C 
+
+    /* private constants (#define) */
+    
+    /* private macros */
+
+    /* private types */
+
+    /* private function protos */
+    #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+    static void i2c_isr(void* p)
+    #else
+    static void i2c_isr(void* p, alt_u32 id)
+    #endif
+    {
+      // Read the control register to clear the in-tar-upt
+      AVS_I2C_MASTER_REG_RD_CONTROL(AVS_I2C_MASTER_SENS_CONTROL_BASE);
+    }
+
+    /* private constants (const) */
+    
+    /* private variables */
+    
+    /* public variables */
+
+    /* public function implements */
+    void UNBOS_i2c_init(void) {
+    #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
+        alt_ic_isr_register(AVS_I2C_MASTER_SENS_CONTROL_IRQ_INTERRUPT_CONTROLLER_ID,
+                            AVS_I2C_MASTER_SENS_CONTROL_IRQ,
+                            i2c_isr,
+                            (void *)0,
+                            (void *)0);
+    #else
+        alt_irq_register(AVS_I2C_MASTER_SENS_CONTROL_IRQ, (void *)0, i2c_isr);
+    #endif
+    }
+
+#endif  // __AVS_I2C_MASTER
+
diff --git a/software/unb_osy/unbos_i2c.h b/software/unb_osy/unbos_i2c.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ddda57a32510bbe349c863c9cdfd4ce8139f62a
--- /dev/null
+++ b/software/unb_osy/unbos_i2c.h
@@ -0,0 +1,61 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+#ifndef UNBOS_I2C_H
+#define UNBOS_I2C_H
+
+/* Compile switches. */
+
+/* includes */
+#include <system.h>
+
+#ifdef __AVS_I2C_MASTER
+    // System has I2C 
+    #include <sys/alt_irq.h>
+//    #include <osx_irq.h>
+    #include <alt_types.h>
+    #include <avs_i2c_master_regs.h>
+
+    /* private constants (#define) */
+    
+    /* private macros */
+
+    /* private types */
+
+    /* private function protos */
+
+    /* private constants (const) */
+    
+    /* private variables */
+    
+    /* public variables */
+
+    /* public function implements */
+    void UNBOS_i2c_init(void);
+
+#else
+
+    /* system does NOT have I2C */
+    #define UNBOS_i2c_init() do { } while( 0 );
+
+#endif
+
+#endif // UNBOS_I2C_H
diff --git a/software/unb_osy/unbos_pps.c b/software/unb_osy/unbos_pps.c
new file mode 100644
index 0000000000000000000000000000000000000000..48df35aaf69572223686876b0ceac773ae5ae956
--- /dev/null
+++ b/software/unb_osy/unbos_pps.c
@@ -0,0 +1,25 @@
+#include <unbos_pps.h>
+#include <osx_timer.h>
+#include <unbosx_util.h>
+
+// Only do an implementation if there is one
+#ifdef PIO_PPS_BASE
+
+// Poll the PPS-level (bit 31) for it
+// to toggle. Do not forget to yank the
+// watchdog every now and then ...
+int UNBOS_pps_wait( void ) {
+	alt_u32    pps_info, pps_level;
+	clock_t    stop = TIMER_0_TICKS_PER_SEC + (TIMER_0_TICKS_PER_SEC>>7);
+
+	pps_info   = IORD_ALTERA_AVALON_PIO_DATA(PIO_PPS_BASE);
+	pps_level  = pps_info & 0x80000000;
+	stop      += osx_clock();
+	do {
+		pps_info  = IORD_ALTERA_AVALON_PIO_DATA(PIO_PPS_BASE);
+		pps_info &= 0x80000000;
+		UNBOSX_ResetWatchdog();
+	} while( (pps_info^pps_level)==0 && osx_clock()<stop );
+	return (pps_info^pps_level);
+}
+#endif
diff --git a/software/unb_osy/unbos_pps.h b/software/unb_osy/unbos_pps.h
new file mode 100644
index 0000000000000000000000000000000000000000..f5874957f5fb0656034674f0f399577a978eca23
--- /dev/null
+++ b/software/unb_osy/unbos_pps.h
@@ -0,0 +1,61 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+#ifndef UNBOS_PPS_H
+#define UNBOS_PPS_H
+
+/* Compile switches. */
+
+/* includes */
+#include <system.h>
+
+/* If "system.h" defines PIO_PPS_BASE it's safe to 
+ * assume the system has the PPS PIO register in it ... */
+#ifdef PIO_PPS_BASE
+    // System has PPS
+    #include <alt_types.h>
+	#include <altera_avalon_pio_regs.h>
+
+    /* private constants (#define) */
+    
+    /* private macros */
+
+    /* private types */
+
+    /* private function protos */
+
+    /* private constants (const) */
+    
+    /* private variables */
+    
+    /* public variables */
+
+    /* public function implements */
+    int UNBOS_pps_wait(void);
+
+#else
+
+    /* system does NOT have a 1PPS */
+    #define UNBOS_pps_wait() 0
+
+#endif
+
+#endif // UNBOS_PPS_H
diff --git a/software/unb_osy/unbosx_eth_regs.h b/software/unb_osy/unbosx_eth_regs.h
new file mode 100644
index 0000000000000000000000000000000000000000..f79e53535f6e2b6112e3b2133df984a53fd94fc6
--- /dev/null
+++ b/software/unb_osy/unbosx_eth_regs.h
@@ -0,0 +1,148 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+#ifndef AVS_ETH_REGS_H
+#define AVS_ETH_REGS_H
+
+/* includes */
+#include "io.h"
+
+/* public constants */
+
+// TSE MAC registers
+#define AVS_ETH_TSE_PCS_ADDR_BASE        (0x200)
+#define AVS_ETH_TSE_RX_FIFO_DEPTH         256
+#define AVS_ETH_TSE_TX_FIFO_DEPTH         256
+#define AVS_ETH_TSE_TX_READY_LATENCY      1
+
+#define AVS_ETH_TSE_PCS_LINK_STATUS_BIT  (0x4)
+
+// ETH registers
+#define AVS_ETH_DEMUX_NOF_UDP_PORTS       4
+
+#define AVS_ETH_REG_DEMUX_NOF_WORDS       AVS_ETH_DEMUX_NOF_UDP_PORTS
+#define AVS_ETH_REG_CONFIG_NOF_WORDS      4
+#define AVS_ETH_REG_CONTROL_NOF_WORDS     1
+#define AVS_ETH_REG_FRAME_NOF_WORDS       1
+#define AVS_ETH_REG_STATUS_NOF_WORDS      1
+  
+#define AVS_ETH_REG_DEMUX_WI              0
+#define AVS_ETH_REG_CONFIG_WI            (AVS_ETH_REG_DEMUX_WI   + AVS_ETH_REG_DEMUX_NOF_WORDS)
+#define AVS_ETH_REG_CONTROL_WI           (AVS_ETH_REG_CONFIG_WI  + AVS_ETH_REG_CONFIG_NOF_WORDS)
+#define AVS_ETH_REG_FRAME_WI             (AVS_ETH_REG_CONTROL_WI + AVS_ETH_REG_CONTROL_NOF_WORDS)
+#define AVS_ETH_REG_STATUS_WI            (AVS_ETH_REG_FRAME_WI   + AVS_ETH_REG_FRAME_NOF_WORDS)
+#define AVS_ETH_REG_CONTINUE_WI          (AVS_ETH_REG_STATUS_WI  + AVS_ETH_REG_STATUS_NOF_WORDS)
+
+// AVS_ETH_REG_DEMUX fields
+#define AVS_ETH_UDP_PORT_MASK            (0xFFFF)
+#define AVS_ETH_UDP_PORT_OFST             0
+#define AVS_ETH_UDP_PORT_EN_BIT_MASK     (0x10000)
+#define AVS_ETH_UDP_PORT_EN_BIT_OFST      16
+
+// AVS_ETH_REG_CONFIG words
+#define AVS_ETH_REG_CONFIG_SRC_MAC_LO                  AVS_ETH_REG_CONFIG_WI
+#define AVS_ETH_REG_CONFIG_SRC_MAC_HI                 (AVS_ETH_REG_CONFIG_WI + 1)
+#define AVS_ETH_REG_CONFIG_SRC_IP                     (AVS_ETH_REG_CONFIG_WI + 2)
+#define AVS_ETH_REG_CONFIG_CTRL                       (AVS_ETH_REG_CONFIG_WI + 3)
+
+// AVS_ETH_REG_CONTROL fields
+#define AVS_ETH_REG_CONTROL_RX_EN_BIT_MASK            (0x1)
+#define AVS_ETH_REG_CONTROL_RX_EN_BIT_OFST             0
+#define AVS_ETH_REG_CONTROL_TX_EN_BIT_MASK            (0x2)
+#define AVS_ETH_REG_CONTROL_TX_EN_BIT_OFST             1
+#define AVS_ETH_REG_CONTROL_TX_REQUEST_BIT_MASK       (0x4)
+#define AVS_ETH_REG_CONTROL_TX_REQUEST_BIT_OFST        2
+#define AVS_ETH_REG_CONTROL_TX_EMPTY_BIT_MASK         (0x30000)
+#define AVS_ETH_REG_CONTROL_TX_EMPTY_BIT_OFST          16
+#define AVS_ETH_REG_CONTROL_TX_NOF_WORDS_BIT_MASK     (0xFFFC0000)
+#define AVS_ETH_REG_CONTROL_TX_NOF_WORDS_BIT_OFST      18
+
+// AVS_ETH_REG_FRAME fields
+#define AVS_ETH_TSE_MAC_ERROR_BIT_MASK                (0x1)
+#define AVS_ETH_TSE_MAC_ERROR_BIT_OFST                 0
+#define AVS_ETH_TSE_MAC_ERROR_LENGTH_BIT_MASK         (0x2)
+#define AVS_ETH_TSE_MAC_ERROR_LENGTH_BIT_OFST          1
+#define AVS_ETH_TSE_MAC_ERROR_CRC_BIT_MASK            (0x4)
+#define AVS_ETH_TSE_MAC_ERROR_CRC_BIT_OFST             2
+#define AVS_ETH_TSE_MAC_ERROR_FIFO_BIT_MASK           (0x8)
+#define AVS_ETH_TSE_MAC_ERROR_FIFO_BIT_OFST            3
+#define AVS_ETH_TSE_MAC_ERROR_PHY_GMII_BIT_MASK       (0x10)
+#define AVS_ETH_TSE_MAC_ERROR_PHY_GMII_BIT_OFST        4
+#define AVS_ETH_TSE_MAC_ERROR_COLLISION_BIT_MASK      (0x20)
+#define AVS_ETH_TSE_MAC_ERROR_COLLISION_BIT_OFST       5
+
+#define AVS_ETH_REG_FRAME_MAC_ADDRESS_MATCH_BIT_MASK  (0x80)
+#define AVS_ETH_REG_FRAME_MAC_ADDRESS_MATCH_BIT_OFST   7
+#define AVS_ETH_REG_FRAME_IS_ARP_BIT_MASK             (0x100)
+#define AVS_ETH_REG_FRAME_IS_ARP_BIT_OFST              8
+#define AVS_ETH_REG_FRAME_IS_IP_BIT_MASK              (0x200)
+#define AVS_ETH_REG_FRAME_IS_IP_BIT_OFST               9
+#define AVS_ETH_REG_FRAME_IP_CHECKSUM_OK_BIT_MASK     (0x400)
+#define AVS_ETH_REG_FRAME_IP_CHECKSUM_OK_BIT_OFST      10
+#define AVS_ETH_REG_FRAME_IP_ADDRESS_MATCH_BIT_MASK   (0x800)
+#define AVS_ETH_REG_FRAME_IP_ADDRESS_MATCH_BIT_OFST    11
+#define AVS_ETH_REG_FRAME_IS_ICMP_BIT_MASK            (0x1000)
+#define AVS_ETH_REG_FRAME_IS_ICMP_BIT_OFST             12
+#define AVS_ETH_REG_FRAME_IS_UDP_BIT_MASK             (0x2000)
+#define AVS_ETH_REG_FRAME_IS_UDP_BIT_OFST              13
+#define AVS_ETH_REG_FRAME_IS_UDP_CTRL_PORT_BIT_MASK   (0x4000)
+#define AVS_ETH_REG_FRAME_IS_UDP_CTRL_PORT_BIT_OFST    14
+
+// AVS_ETH_REG_STATUS fields
+#define AVS_ETH_REG_STATUS_RX_AVAIL_BIT_MASK          (0x1)
+#define AVS_ETH_REG_STATUS_RX_AVAIL_BIT_OFST           0
+#define AVS_ETH_REG_STATUS_TX_DONE_BIT_MASK           (0x2)
+#define AVS_ETH_REG_STATUS_TX_DONE_BIT_OFST            1
+#define AVS_ETH_REG_STATUS_TX_AVAIL_BIT_MASK          (0x4)
+#define AVS_ETH_REG_STATUS_TX_AVAIL_BIT_OFST           2
+#define AVS_ETH_REG_STATUS_RX_EMPTY_BIT_MASK          (0x30000)
+#define AVS_ETH_REG_STATUS_RX_EMPTY_BIT_OFST           16
+#define AVS_ETH_REG_STATUS_RX_NOF_WORDS_BIT_MASK      (0xFFFC0000)
+#define AVS_ETH_REG_STATUS_RX_NOF_WORDS_BIT_OFST       18
+
+// ETH frame
+#define AVS_ETH_TYPE_MASK                             (0xFFFF)
+
+
+/* public macros */
+
+// usage: fill in base address from system.h
+// . pcs_addr half word address as defined in table 4.9 in ug_ethernet.pdf
+// . mac_addr byte address as defined in table 4.17 in ug_ethernet.pdf
+// TSE MAC uses byte unit addressing
+#define AVS_ETH_TSE_PCS_RD(base, pcs_addr)       IORD((base), (AVS_ETH_TSE_PCS_ADDR_BASE + (pcs_addr)*2))
+#define AVS_ETH_TSE_PCS_WR(base, pcs_addr, data) IOWR((base), (AVS_ETH_TSE_PCS_ADDR_BASE + (pcs_addr)*2), (data))
+#define AVS_ETH_TSE_MAC_RD(base, mac_addr)       IORD((base), (mac_addr))
+#define AVS_ETH_TSE_MAC_WR(base, mac_addr, data) IOWR((base), (mac_addr), (data))
+// ETH REG and ETH RAM use word unit addressing
+#define AVS_ETH_REG_RD(base, reg_wi)             IORD((base), (reg_wi))
+#define AVS_ETH_REG_WR(base, reg_wi, data)       IOWR((base), (reg_wi), (data))
+#define AVS_ETH_RAM_RD(base, ram_wi)             IORD((base), (ram_wi))
+#define AVS_ETH_RAM_WR(base, ram_wi, data)       IOWR((base), (ram_wi), (data))
+
+/* public types */
+
+/* public variables */
+
+/* public function protos */
+
+#endif  // AVS_ETH_REGS_H
diff --git a/software/unb_osy/unbosx_types.h b/software/unb_osy/unbosx_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cb41918c7db65580586664b3fce5049dc67a290
--- /dev/null
+++ b/software/unb_osy/unbosx_types.h
@@ -0,0 +1,14 @@
+#ifndef UNBOSX_TYPES_H
+#define UNBOSX_TYPES_H
+
+#include <alt_types.h>
+
+#define FALSE                 0
+#define TRUE                  1
+#define NULL                  ((void*)0)
+#define ALT_IRQ_NOT_CONNECTED (-1)
+typedef alt_32  TBool;
+typedef alt_u16 TUInt16;
+typedef alt_u32 TUInt32;
+
+#endif
diff --git a/software/unb_osy/unbosx_util.h b/software/unb_osy/unbosx_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5b55b2505330405815a4afc30c1fbe9438658fd
--- /dev/null
+++ b/software/unb_osy/unbosx_util.h
@@ -0,0 +1,86 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009
+ * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+ * JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+ * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ---------------------------------------------------------------------------- */
+
+#ifndef UNBOSX_UTIL_H
+#define UNBOSX_UTIL_H
+
+
+/* includes */
+#include <system.h>
+#include <unbosx_types.h>
+#include <altera_avalon_pio_regs.h>
+
+
+/* The NiosII CPU is little endian so we 
+ * must swap going from host -> network and from network -> host byteorder
+ * since networkbyteorder is big endian
+ */
+
+/* 16 bit swap */
+#define UNBOSX_UTIL_ntohs(x)  ((((x) >> 8) & 0xff) | \
+		               (((x) << 8) & 0xff00))
+#define UNBOSX_UTIL_htons(x)  UNBOSX_UTIL_ntohs(x)
+
+/* 32 bit swap */
+#define UNBOSX_UTIL_ntohl(x)  ((((x >> 24) & 0x000000ff)) | \
+		               (((x >>  8) & 0x0000ff00)) | \
+		               (((x) & 0x0000ff00) <<  8) | \
+			       (((x) & 0x000000ff) << 24))
+#define UNBOSX_UTIL_htonl(a)  UNBOSX_UTIL_ntohl(a)
+
+
+
+
+/* UNB1: */
+/* [7:0] = id : UniBoard FPGA node ID in entire multi subrack system:
+ * [2:0] = nodenumber (0 -> 7)
+ * [2]   => if '1' this implies it's a backnode (ie: 4, 5, 6, 7)
+ * [7:3] = backplaneid
+ */
+#define UNBOSX_GetNodeNumber()  (IORD_ALTERA_AVALON_PIO_DATA(PIO_SYSTEM_INFO_BASE)&0x7)
+#define UNBOSX_GetBackplaneId() ((IORD_ALTERA_AVALON_PIO_DATA(PIO_SYSTEM_INFO_BASE)&0xff)>>3)
+#define UNBOSX_IsBacknode()     ((IORD_ALTERA_AVALON_PIO_DATA(PIO_SYSTEM_INFO_BASE)&0x4)==0x4)
+
+
+
+/* UNB2: */
+/* [7:0] = id : UniBoard FPGA node ID in entire multi subrack system:
+ * [1:0] = nodenumber (0 -> 3)
+ * [7:2] = backplaneid
+ */
+#define UNBOSX_unb2_GetNodeNumber()  (IORD_ALTERA_AVALON_PIO_DATA(PIO_SYSTEM_INFO_BASE)&0x3)
+#define UNBOSX_unb2_GetBackplaneId() ((IORD_ALTERA_AVALON_PIO_DATA(PIO_SYSTEM_INFO_BASE)&0xff)>>2)
+#define UNBOSX_unb2_IsBacknode()     (0)
+
+
+
+#define UNBOSX_G_SIM()          ((IORD_ALTERA_AVALON_PIO_DATA(PIO_SYSTEM_INFO_BASE)&0x400)!=0)
+
+#define UNBOSX_ResetWatchdog()  (IOWR_ALTERA_AVALON_PIO_DATA(PIO_WDI_BASE, !((IORD_ALTERA_AVALON_PIO_DATA(PIO_WDI_BASE))&0x1)))
+/* public types */
+
+/* public variables */
+
+/* public function protos */
+
+#endif
+