diff --git a/.gitmodules b/.gitmodules
index d387b1b1378863f0a1bb0f4c3f63429c3057e780..eb7b43a7904380c988eea30091523c337a9e4ef9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "ptp-noposix"]
 	path = ptp-noposix
 	url = git://ohwr.org/white-rabbit/ppsi/ptp-noposix.git
+[submodule "ppsi"]
+	path = ppsi
+	url = git://ohwr.org/white-rabbit/ppsi.git
diff --git a/Kconfig b/Kconfig
index a6b6a6bcade6f40f14d706ae3a7e4428dc773c80..3167d3725a1107d218d8184af3f4c4d3a202ca5a 100644
--- a/Kconfig
+++ b/Kconfig
@@ -10,8 +10,46 @@ config RAMSIZE
 	 more features you may want to adjust the FPGA size and
 	 choose your preferred value here.
 
+choice
+       prompt "Choose your preferred ptp engine"
+       default PTP_NOPOSIX
+
+config PTP_NOPOSIX
+       boolean "ptp-noposix"
+       help
+	 Select this option for the ptp-noposix engine
+
+config PPSI
+       boolean "ppsi"
+       help
+	 Select this option for the ppsi engine. Warning: this option is
+	 work in progress, may not work or not compile at all.
+
+endchoice
+
+config PPSI_VERBOSITY
+	depends on PPSI
+	int "Default verbosity for PPSI"
+	help
+	  This option makes you select the verbosity of PPSI at startup:
+	  0 means silent
+	  1 means normal verbosity messages
+	  2 means more verbose messages
+	default 0
+	range 0 2
+
+config PPSI_RUNTIME_VERBOSITY
+       depends on PPSI
+       boolean "Enable runtime verbosity setting"
+       default n
+       help
+         If set, this option permits to change the verbosity of PPSI engine
+         runtime. This causes a bigger RAM occupation, so it is suggested
+         to set it only for debugging purpose.
+
 config STACKSIZE
        int "Size of the stack area needed by this program"
+       default 3584 if PPSI
        default 2048
        help
          The linker complains if the code doesn't fit into RAM, but
@@ -20,6 +58,7 @@ config STACKSIZE
 
 config MPRINTF
 	boolean "Use the old mprintf implementation for printf"
+	depends on !PPSI
 	default y
 	help
 	  wrpc-sw has traditionally used mprintf as its printf engine.
@@ -97,7 +136,4 @@ config DETERMINISTIC_BINARY
 
 	 If in doubt, say No.
 
-# The following will soon become a choice with ppsi
-config PTP_NOPOSIX
-       boolean
-       default y
\ No newline at end of file
+
diff --git a/Makefile b/Makefile
index 2382db79b3b58b817c78df73cc0b460f503ce2de..8e5438fbc5c317eb7d569df90d5170e96f61169d 100644
--- a/Makefile
+++ b/Makefile
@@ -17,12 +17,13 @@ SIZE =		$(CROSS_COMPILE)size
 AUTOCONF = $(CURDIR)/include/generated/autoconf.h
 
 PTP_NOPOSIX = ptp-noposix
+PPSI = ppsi
 
 # we miss CONFIG_ARCH_LM32 as we have no other archs by now
 obj-y = arch/lm32/crt0.o arch/lm32/irq.o arch/lm32/debug.o
 LDS = arch/lm32/ram.ld
 
-obj-y += wrc_main.o wrc_ptp.o monitor/monitor.o
+obj-y += wrc_main.o
 obj-y += softpll/softpll_ng.o
 
 
@@ -31,13 +32,11 @@ obj-y += softpll/softpll_ng.o
 	$(CC) -include $(AUTOCONF) -E -P $*.ld.S -o $@
 
 
-cflags-y = -include $(AUTOCONF)	-Iinclude -I. -Isoftpll
-
+cflags-y = 	-ffreestanding -include $(AUTOCONF) -Iinclude -I. -Isoftpll
 
 cflags-$(CONFIG_PP_PRINTF) += -I$(CURDIR)/pp_printf
 
 cflags-$(CONFIG_PTP_NOPOSIX) += \
-	-ffreestanding \
 	-DPTPD_FREESTANDING \
 	-DWRPC_EXTRA_SLIM \
 	-DPTPD_MSBF \
@@ -48,11 +47,12 @@ cflags-$(CONFIG_PTP_NOPOSIX) += \
 	-include $(PTP_NOPOSIX)/compat.h \
 	-include $(PTP_NOPOSIX)/PTPWRd/dep/trace.h \
 	-include $(PTP_NOPOSIX)/libposix/ptpd-wrappers.h \
-	-I$(PTP_NOPOSIX)/wrsw_hal \
 	-I$(PTP_NOPOSIX)/libptpnetif \
 	-I$(PTP_NOPOSIX)/PTPWRd
 
-obj-$(CONFIG_PTP_NOPOSIX) += $(PTP_NOPOSIX)/PTPWRd/arith.o \
+obj-$(CONFIG_PTP_NOPOSIX) += wrc_ptp_noposix.o \
+	monitor/monitor.o \
+	$(PTP_NOPOSIX)/PTPWRd/arith.o \
 	$(PTP_NOPOSIX)/PTPWRd/bmc.o \
 	$(PTP_NOPOSIX)/PTPWRd/dep/msg.o \
 	$(PTP_NOPOSIX)/PTPWRd/dep/net.o \
@@ -65,6 +65,27 @@ obj-$(CONFIG_PTP_NOPOSIX) += $(PTP_NOPOSIX)/PTPWRd/arith.o \
 	$(PTP_NOPOSIX)/libposix/freestanding-startup.o \
 	$(PTP_NOPOSIX)/libposix/freestanding-wrapper.o
 
+cflags-$(CONFIG_PPSI) += \
+	-ffreestanding \
+	-include include/ppsi-wrappers.h \
+	-Iinclude \
+	-I$(PPSI)/include \
+	-I$(PPSI)/arch-spec \
+	-I$(PPSI)/arch-spec/include \
+	-I$(PPSI)/proto-ext-whiterabbit \
+	-Iboards/spec
+
+# FIXM: The following it temporary, untile we clean up
+cflags-$(CONFIG_PPSI) += \
+	-I$(PTP_NOPOSIX)/PTPWRd \
+	-include $(PTP_NOPOSIX)/PTPWRd/dep/trace.h \
+
+obj-$(CONFIG_PPSI) += wrc_ptp_ppsi.o \
+	monitor/monitor_ppsi.o \
+	lib/ppsi-wrappers.o \
+	$(PPSI)/ppsi.o \
+	$(PPSI)/arch-spec/libarch.a
+
 CFLAGS_PLATFORM  = -mmultiply-enabled -mbarrel-shift-enabled
 LDFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled \
 	-nostdlib -T $(LDS)
@@ -93,7 +114,11 @@ REVISION=$(shell git describe --dirty --always)
 all: tools $(OUTPUT).ram $(OUTPUT).vhd $(OUTPUT).mif
 
 .PRECIOUS: %.elf %.bin
-.PHONY: all tools clean gitmodules
+.PHONY: all tools clean gitmodules $(PPSI)/ppsi.o
+
+$(PPSI)/ppsi.o:
+	$(MAKE) -C $(PPSI) ARCH=spec PROTO_EXT=whiterabbit HAS_FULL_DIAG=y \
+		CROSS_COMPILE=$(CROSS_COMPILE)
 
 $(OUTPUT).elf: $(LDS) $(AUTOCONF) gitmodules $(OUTPUT).o
 	$(CC) $(CFLAGS) -DGIT_REVISION=\"$(REVISION)\" -c revision.c
@@ -126,6 +151,7 @@ include/board.h:
 
 clean:
 	rm -f $(OBJS) $(OUTPUT).elf $(OUTPUT).bin $(OUTPUT).ram include/board.h
+	$(MAKE) -C $(PPSI) clean
 
 %.o:		%.c
 	${CC} $(CFLAGS) $(PTPD_CFLAGS) $(INCLUDE_DIR) $(LIB_DIR) -c $*.c -o $@
diff --git a/configs/spec_ppsi_defconfig b/configs/spec_ppsi_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..49ed2b8c7343850d3fe2b0a4d606663ae96c816d
--- /dev/null
+++ b/configs/spec_ppsi_defconfig
@@ -0,0 +1,17 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_RAMSIZE=90112
+# CONFIG_PTP_NOPOSIX is not set
+CONFIG_PPSI=y
+CONFIG_PPSI_VERBOSITY=0
+# CONFIG_PPSI_RUNTIME_VERBOSITY is not set
+CONFIG_STACKSIZE=2048
+CONFIG_PP_PRINTF=y
+# CONFIG_PRINTF_FULL is not set
+CONFIG_PRINTF_XINT=y
+# CONFIG_PRINTF_MINI is not set
+# CONFIG_PRINTF_NONE is not set
+CONFIG_PRINT_BUFSIZE=128
+# CONFIG_ETHERBONE is not set
+# CONFIG_DETERMINISTIC_BINARY is not set
diff --git a/include/hal_exports.h b/include/hal_exports.h
new file mode 100644
index 0000000000000000000000000000000000000000..83a6773f105c6d3a8ab3d5fb015412418705457c
--- /dev/null
+++ b/include/hal_exports.h
@@ -0,0 +1,242 @@
+#ifndef __HAL_EXPORTS_H
+#define __HAL_EXPORTS_H
+
+#include <stdint.h>
+
+#define HAL_MAX_PORTS 32
+
+#define WRSW_HAL_SERVER_ADDR "wrsw_hal"
+
+// checks if the calibration unit is idle
+#define HEXP_CAL_CMD_CHECK_IDLE 1
+
+// enables/disables transmission of calibration pattern
+#define HEXP_CAL_CMD_TX_PATTERN 2
+
+// requests a measurement of TX delta
+#define HEXP_CAL_CMD_TX_MEASURE 4
+
+// requests a measurement of RX delta
+#define HEXP_CAL_CMD_RX_MEASURE 5
+
+#define HEXP_CAL_RESP_BUSY 1
+#define HEXP_CAL_RESP_OK 0
+#define HEXP_CAL_RESP_ERROR -1
+
+#define HEXP_LOCK_CMD_START 1
+#define HEXP_LOCK_CMD_CHECK 2
+#define HEXP_LOCK_CMD_ENABLE_TRACKING 3
+
+#define HEXP_LOCK_STATUS_LOCKED 0
+#define HEXP_LOCK_STATUS_BUSY 1
+#define HEXP_LOCK_STATUS_NONE 2
+
+#define HEXP_PPSG_CMD_GET 0
+#define HEXP_PPSG_CMD_ADJUST_PHASE 1
+#define HEXP_PPSG_CMD_ADJUST_SEC 2
+#define HEXP_PPSG_CMD_ADJUST_NSEC 3
+#define HEXP_PPSG_CMD_POLL 4
+#define HEXP_PPSG_CMD_SET_VALID 5
+
+#define HEXP_ON 1
+#define HEXP_OFF 0
+
+#define HEXP_FREQ 0
+#define HEXP_PHASE 1
+
+/////////////////added by ML//////////
+#define HEXP_EXTSRC_CMD_CHECK 0
+
+#define HEXP_EXTSRC_STATUS_LOCKED 0
+#define HEXP_LOCK_STATUS_BUSY	  1
+#define HEXP_EXTSRC_STATUS_NOSRC  2
+/////////////////////////////////////
+
+#define HAL_TIMING_MODE_GRAND_MASTER 0
+#define HAL_TIMING_MODE_FREE_MASTER 1
+#define HAL_TIMING_MODE_BC 2
+
+typedef struct {
+
+	char port_name[16];
+
+	int pps_valid;
+
+	uint32_t current_phase_shift;
+	int32_t adjust_phase_shift;
+
+	int64_t adjust_sec;
+	int32_t adjust_nsec;
+
+	uint64_t current_sec;
+	uint32_t current_nsec;
+
+} hexp_pps_params_t;
+
+/* Port modes (hexp_port_state_t.mode) */
+#define HEXP_PORT_MODE_WR_M_AND_S 4
+#define HEXP_PORT_MODE_WR_MASTER 1
+#define HEXP_PORT_MODE_WR_SLAVE 2
+#define HEXP_PORT_MODE_NON_WR 3
+
+#define FIX_ALPHA_FRACBITS 40
+/*
+#define HEXP_PORT_TSC_RISING 1
+#define HEXP_PORT_TSC_FALLING 2
+*/
+
+typedef struct {
+	/* When non-zero: port state is valid */
+	int valid;
+
+	/* WR-PTP role of the port (Master, Slave, etc.) */
+	int mode;
+
+	/* TX and RX delays (combined, big Deltas from the link model in the spec) */
+	uint32_t delta_tx;
+	uint32_t delta_rx;
+
+	/* DDMTD raw phase value in picoseconds */
+	uint32_t phase_val;
+
+	/* When non-zero: phase_val contains a valid phase readout */
+	int phase_val_valid;
+
+	/* When non-zero: link is up */
+	int up;
+
+	/* When non-zero: TX path is calibrated (delta_tx contains valid value) */
+	int tx_calibrated;
+
+	/* When non-zero: RX path is calibrated (delta_rx contains valid value) */
+	int rx_calibrated;
+	int tx_tstamp_counter;
+	int rx_tstamp_counter;
+	int is_locked;
+	int lock_priority;
+
+	// timestamp linearization paramaters
+
+	uint32_t phase_setpoint;	// DMPLL phase setpoint (picoseconds)
+
+	uint32_t clock_period;	// reference lock period in picoseconds
+	uint32_t t2_phase_transition;	// approximate DMTD phase value (on slave port) at which RX timestamp (T2) counter transistion occurs (picoseconds)
+
+	uint32_t t4_phase_transition;	// approximate phase value (on master port) at which RX timestamp (T4) counter transistion occurs (picoseconds)
+
+	uint8_t hw_addr[6];
+	int hw_index;
+	int32_t fiber_fix_alpha;
+} hexp_port_state_t;
+
+typedef struct {
+	int num_ports;		/* Number of ports in the list */
+	int num_physical_ports;	/* Number of physical ports compiled into the FPGA bitstream */
+	char port_names[HAL_MAX_PORTS][16];
+} hexp_port_list_t;
+
+typedef struct {
+	int timing_mode;	/* Free-running Master/GM/BC */
+	int locked_port;
+
+} hexp_timing_state_t;
+
+/* Prototypes of functions that call on rpc */
+extern int halexp_check_running(void);
+extern int halexp_reset_port(const char *port_name);
+extern int halexp_calibration_cmd(const char *port_name, int command,
+				  int on_off);
+extern int halexp_lock_cmd(const char *port_name, int command, int priority);
+extern int halexp_query_ports(hexp_port_list_t * list);
+extern int halexp_get_port_state(hexp_port_state_t * state,
+				 const char *port_name);
+extern int halexp_pps_cmd(int cmd, hexp_pps_params_t * params);
+extern int halexp_get_timing_state(hexp_timing_state_t * state);
+
+/* Export structures, shared by server and client for argument matching */
+#ifdef HAL_EXPORT_STRUCTURES
+
+//int halexp_check_running();
+struct minipc_pd __rpcdef_check_running = {
+	.name = "check_running",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+	.args = {
+		 MINIPC_ARG_END,
+		 },
+};
+
+//int halexp_reset_port(const char *port_name);
+struct minipc_pd __rpcdef_reset_port = {
+	.name = "reset_port",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+	.args = {
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *),
+		 MINIPC_ARG_END,
+		 },
+};
+
+//int halexp_calibration_cmd(const char *port_name, int command, int on_off);
+struct minipc_pd __rpcdef_calibration_cmd = {
+	.name = "calibration_cmd",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+	.args = {
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *),
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+		 MINIPC_ARG_END,
+		 },
+};
+
+//int halexp_lock_cmd(const char *port_name, int command, int priority);
+struct minipc_pd __rpcdef_lock_cmd = {
+	.name = "lock_cmd",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+	.args = {
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *),
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+		 MINIPC_ARG_END,
+		 },
+};
+
+//int halexp_query_ports(hexp_port_list_t *list);
+struct minipc_pd __rpcdef_query_ports = {
+	.name = "query_ports",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_port_list_t),
+	.args = {
+		 MINIPC_ARG_END,
+		 },
+};
+
+//int halexp_get_port_state(hexp_port_state_t *state, const char *port_name);
+struct minipc_pd __rpcdef_get_port_state = {
+	.name = "get_port_state",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_port_state_t),
+	.args = {
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *),
+		 MINIPC_ARG_END,
+		 },
+};
+
+//int halexp_pps_cmd(int cmd, hexp_pps_params_t *params);
+struct minipc_pd __rpcdef_pps_cmd = {
+	.name = "pps_cmd",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+	.args = {
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
+		 MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_pps_params_t),
+		 MINIPC_ARG_END,
+		 },
+};
+
+struct minipc_pd __rpcdef_get_timing_state = {
+	.name = "get_timing_state",
+	.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_timing_state_t),
+	.args = {
+		 MINIPC_ARG_END,
+		 },
+};
+
+#endif /* HAL_EXPORT_STRUCTURES */
+
+#endif
diff --git a/include/ppsi-wrappers.h b/include/ppsi-wrappers.h
new file mode 100644
index 0000000000000000000000000000000000000000..e269b61382be426a744e30d82509af1d0b12c299
--- /dev/null
+++ b/include/ppsi-wrappers.h
@@ -0,0 +1,22 @@
+/*
+ * This includes stuff that is needed to link ppsi into wrpc-sw
+ *
+ * It is included by the command line (-include) like ptp-noposix's
+ * ptpd-wrappers.h is. It is a subset of that file, with only needed stuff
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifndef __IEEE_BIG_ENDIAN
+#error "Not big endian, or unknown endianness"
+#endif
+
+static inline uint16_t ntohs(uint16_t x) {return x;}
+
+static inline int usleep(useconds_t useconds)
+{
+	while(useconds--)
+		asm volatile("nop");
+	return 0;
+}
diff --git a/include/shell.h b/include/shell.h
index 05203c0859fde1b9ff85d2b680e0c7937329e721..9ff111a8be0897d67c36378fe7a1b07c674f8cc2 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -21,6 +21,7 @@ int cmd_mode(const char *args[]);
 int cmd_calib(const char *args[]);
 int cmd_time(const char *args[]);
 int cmd_ip(const char *args[]);
+int cmd_verbose(const char *args[]);
 int cmd_sdb(const char *args[]);
 int cmd_mac(const char *args[]);
 int cmd_init(const char *args[]);
diff --git a/lib/net.c b/lib/net.c
index 2cce149c08dd93633442176c37f2ce831c6eee61..69d5064eb82c8cce78671e3043000befeca16a5b 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -252,7 +252,7 @@ int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data,
                                                                                                                    from->mac[4],from->mac[5],from->mac[6],from->mac[7],
                                                                                                                    from->mac_dest[0],from->mac_dest[1],from->mac_dest[2],from->mac_dest[3],
                                                                                                                    from->mac_dest[4],from->mac_dest[5],from->mac_dest[6],from->mac_dest[7]);*/
-	return min(size, data_length);
+	return min(size - sizeof(struct ethhdr), data_length);
 	return 0;
 }
 
diff --git a/lib/ppsi-wrappers.c b/lib/ppsi-wrappers.c
new file mode 100644
index 0000000000000000000000000000000000000000..f59b8fa60c5fc538f2d489377a7f31fe603c7e17
--- /dev/null
+++ b/lib/ppsi-wrappers.c
@@ -0,0 +1,69 @@
+#include <stdint.h>
+#include <hal_exports.h>
+#include <wrc_ptp.h>
+#include <syscon.h>
+#include <endpoint.h>
+#include <softpll_ng.h>
+#include <ptpd_netif.h>
+
+/* Following code from ptp-noposix/libposix/freestanding-wrapper.c */
+
+uint64_t ptpd_netif_get_msec_tics(void)
+{
+  return timer_get_tics();
+}
+
+static int read_phase_val(hexp_port_state_t *state)
+{
+  int32_t dmtd_phase;
+
+  if(spll_read_ptracker(0, &dmtd_phase, NULL))
+  {
+    state->phase_val = dmtd_phase;
+    state->phase_val_valid = 1;
+  }
+  else
+  {
+    state->phase_val = 0;
+    state->phase_val_valid = 0;
+  }
+
+  return 0;
+}
+
+extern int32_t cal_phase_transition;
+extern int32_t sfp_alpha;
+
+int halexp_get_port_state(hexp_port_state_t *state, const char *port_name)
+{
+  state->valid         = 1;
+
+  if(wrc_ptp_get_mode()==WRC_MODE_SLAVE)
+    state->mode = HEXP_PORT_MODE_WR_SLAVE;
+  else
+    state->mode = HEXP_PORT_MODE_WR_MASTER;
+
+  ep_get_deltas( &state->delta_tx, &state->delta_rx);
+  read_phase_val(state);
+  state->up            = ep_link_up(NULL);
+  state->tx_calibrated = 1;
+  state->rx_calibrated = 1;
+  state->is_locked     = spll_check_lock(0);
+  state->lock_priority = 0;
+  spll_get_phase_shift(0, NULL, (int32_t *)&state->phase_setpoint);
+  state->clock_period  = 8000;
+  state->t2_phase_transition = cal_phase_transition;
+  state->t4_phase_transition = cal_phase_transition;
+  get_mac_addr(state->hw_addr);
+  state->hw_index      = 0;
+  state->fiber_fix_alpha = sfp_alpha;
+
+  return 0;
+}
+
+int ptpd_netif_get_dmtd_phase(wr_socket_t *sock, int32_t *phase)
+{
+        if(phase)
+                return spll_read_ptracker(0, phase, NULL);
+        return 0;
+}
diff --git a/monitor/monitor_ppsi.c b/monitor/monitor_ppsi.c
new file mode 100644
index 0000000000000000000000000000000000000000..743a93b9fb7db09b4eb5115163d0af7fcd6576f3
--- /dev/null
+++ b/monitor/monitor_ppsi.c
@@ -0,0 +1,216 @@
+/*
+ * This work is part of the White Rabbit project
+ *
+ * Copyright (C) 2011,2012 CERN (www.cern.ch)
+ * Author: Aurelio Colosimo <aurelio@aureliocolosimo.it>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ */
+
+#include <inttypes.h>
+#include <wrc.h>
+#include <ppsi/ppsi.h>
+#include <spec.h>
+#include <wr-api.h>
+#include <minic.h>
+#include <softpll_ng.h>
+#include <syscon.h>
+#include <pps_gen.h>
+#include <onewire.h>
+#include <util.h>
+#include "wrc_ptp.h"
+
+#define UI_REFRESH_PERIOD TICS_PER_SECOND	/* 1 sec */
+
+struct ptpdexp_sync_state_t;
+extern ptpdexp_sync_state_t cur_servo_state;
+extern int wrc_man_phase;
+
+void wrc_mon_gui(void)
+{
+	static uint32_t last = 0;
+	hexp_port_state_t ps;
+	int tx, rx;
+	int aux_stat;
+	uint64_t sec;
+	uint32_t nsec;
+
+	if (timer_get_tics() - last < UI_REFRESH_PERIOD)
+		return;
+
+	last = timer_get_tics();
+
+	term_clear();
+
+	pcprintf(1, 1, C_BLUE, "WR PTP Core Sync Monitor v 1.0");
+	pcprintf(2, 1, C_GREY, "Esc = exit");
+
+	shw_pps_gen_get_time(&sec, &nsec);
+
+	cprintf(C_BLUE, "\n\nTAI Time:                  ");
+	cprintf(C_WHITE, "%s", format_time(sec));
+
+	/*show_ports */
+	halexp_get_port_state(&ps, NULL);
+	pcprintf(4, 1, C_BLUE, "\n\nLink status:");
+
+	pcprintf(6, 1, C_WHITE, "%s: ", "wru1");
+	if (ps.up)
+		cprintf(C_GREEN, "Link up   ");
+	else
+		cprintf(C_RED, "Link down ");
+
+	if (ps.up) {
+		minic_get_stats(&tx, &rx);
+		cprintf(C_GREY, "(RX: %d, TX: %d), mode: ", rx, tx);
+
+		switch (ptp_mode) {
+		case WRC_MODE_GM:
+		case WRC_MODE_MASTER:
+			cprintf(C_WHITE, "WR Master  ");
+			break;
+		case WRC_MODE_SLAVE:
+			cprintf(C_WHITE, "WR Slave   ");
+			break;
+		default:
+			cprintf(C_RED, "WR Unknown   ");
+		}
+
+		if (ps.is_locked)
+			cprintf(C_GREEN, "Locked  ");
+		else
+			cprintf(C_RED, "NoLock  ");
+		if (ps.rx_calibrated && ps.tx_calibrated)
+			cprintf(C_GREEN, "Calibrated  ");
+		else
+			cprintf(C_RED, "Uncalibrated  ");
+
+		/* show_servo */
+		cprintf(C_BLUE, "\n\nSynchronization status:\n\n");
+
+		if (!cur_servo_state.valid) {
+			cprintf(C_RED,
+				"Master mode or sync info not valid\n\n");
+			return;
+		}
+
+		cprintf(C_GREY, "Servo state:               ");
+		cprintf(C_WHITE, "%s\n", cur_servo_state.slave_servo_state);
+		cprintf(C_GREY, "Phase tracking:            ");
+		if (cur_servo_state.tracking_enabled)
+			cprintf(C_GREEN, "ON\n");
+		else
+			cprintf(C_RED, "OFF\n");
+		cprintf(C_GREY, "Synchronization source:    ");
+		cprintf(C_WHITE, "%s\n", cur_servo_state.sync_source);
+
+		cprintf(C_GREY, "Aux clock status:          ");
+
+		aux_stat = spll_get_aux_status(0);
+
+		if (aux_stat & SPLL_AUX_ENABLED)
+			cprintf(C_GREEN, "enabled");
+
+		if (aux_stat & SPLL_AUX_LOCKED)
+			cprintf(C_GREEN, ", locked");
+		mprintf("\n");
+
+		cprintf(C_BLUE, "\nTiming parameters:\n\n");
+
+		cprintf(C_GREY, "Round-trip time (mu):    ");
+		cprintf(C_WHITE, "%9d ps\n", (int32_t) (cur_servo_state.mu));
+		cprintf(C_GREY, "Master-slave delay:      ");
+		cprintf(C_WHITE, "%9d ps\n",
+			(int32_t) (cur_servo_state.delay_ms));
+		cprintf(C_GREY, "Master PHY delays:       ");
+		cprintf(C_WHITE, "TX: %d ps, RX: %d ps\n",
+			(int32_t) cur_servo_state.delta_tx_m,
+			(int32_t) cur_servo_state.delta_rx_m);
+		cprintf(C_GREY, "Slave PHY delays:        ");
+		cprintf(C_WHITE, "TX: %d ps, RX: %d ps\n",
+			(int32_t) cur_servo_state.delta_tx_s,
+			(int32_t) cur_servo_state.delta_rx_s);
+		cprintf(C_GREY, "Total link asymmetry:    ");
+		cprintf(C_WHITE, "%9d ps\n",
+			(int32_t) (cur_servo_state.total_asymmetry));
+		cprintf(C_GREY, "Cable rtt delay:         ");
+		cprintf(C_WHITE, "%9d ps\n",
+			(int32_t) (cur_servo_state.mu) -
+			(int32_t) cur_servo_state.delta_tx_m -
+			(int32_t) cur_servo_state.delta_rx_m -
+			(int32_t) cur_servo_state.delta_tx_s -
+			(int32_t) cur_servo_state.delta_rx_s);
+		cprintf(C_GREY, "Clock offset:            ");
+		cprintf(C_WHITE, "%9d ps\n",
+			(int32_t) (cur_servo_state.cur_offset));
+		cprintf(C_GREY, "Phase setpoint:          ");
+		cprintf(C_WHITE, "%9d ps\n",
+			(int32_t) (cur_servo_state.cur_setpoint));
+		cprintf(C_GREY, "Skew:                    ");
+		cprintf(C_WHITE, "%9d ps\n",
+			(int32_t) (cur_servo_state.cur_skew));
+		cprintf(C_GREY, "Manual phase adjustment: ");
+		cprintf(C_WHITE, "%9d ps\n", (int32_t) (wrc_man_phase));
+
+		cprintf(C_GREY, "Update counter:          ");
+		cprintf(C_WHITE, "%9d \n",
+			(int32_t) (cur_servo_state.update_count));
+
+	}
+
+	pp_printf("--");
+
+	return;
+}
+
+int wrc_log_stats(uint8_t onetime)
+{
+	static uint32_t last = 0;
+	hexp_port_state_t ps;
+	int tx, rx;
+	int aux_stat;
+	uint64_t sec;
+	uint32_t nsec;
+	int16_t brd_temp = 0;
+	int16_t brd_temp_frac = 0;
+
+	if (!onetime && timer_get_tics() - last < UI_REFRESH_PERIOD)
+		return 0;
+
+	last = timer_get_tics();
+
+	shw_pps_gen_get_time(&sec, &nsec);
+	halexp_get_port_state(&ps, NULL);
+	minic_get_stats(&tx, &rx);
+	pp_printf("lnk:%d rx:%d tx:%d ", ps.up, rx, tx);
+	pp_printf("lock:%d ", ps.is_locked ? 1 : 0);
+	pp_printf("sv:%d ", cur_servo_state.valid ? 1 : 0);
+	pp_printf("ss:'%s' ", cur_servo_state.slave_servo_state);
+	aux_stat = spll_get_aux_status(0);
+	pp_printf("aux:%x ", aux_stat);
+	pp_printf("sec:%d nsec:%d ", (uint32_t) sec, nsec);	/* fixme: clock is not always 125 MHz */
+	pp_printf("mu:%d ", (int32_t) cur_servo_state.mu);
+	pp_printf("dms:%d ", (int32_t) cur_servo_state.delay_ms);
+	pp_printf("dtxm:%d drxm:%d ", (int32_t) cur_servo_state.delta_tx_m,
+		(int32_t) cur_servo_state.delta_rx_m);
+	pp_printf("dtxs:%d drxs:%d ", (int32_t) cur_servo_state.delta_tx_s,
+		(int32_t) cur_servo_state.delta_rx_s);
+	pp_printf("asym:%d ", (int32_t) (cur_servo_state.total_asymmetry));
+	pp_printf("crtt:%d ",
+		(int32_t) (cur_servo_state.mu) -
+		(int32_t) cur_servo_state.delta_tx_m -
+		(int32_t) cur_servo_state.delta_rx_m -
+		(int32_t) cur_servo_state.delta_tx_s -
+		(int32_t) cur_servo_state.delta_rx_s);
+	pp_printf("cko:%d ", (int32_t) (cur_servo_state.cur_offset));
+	pp_printf("setp:%d ", (int32_t) (cur_servo_state.cur_setpoint));
+	pp_printf("hd:%d md:%d ad:%d ", spll_get_dac(-1), spll_get_dac(0),
+		spll_get_dac(1));
+	pp_printf("ucnt:%d ", (int32_t) cur_servo_state.update_count);
+
+	own_readtemp(ONEWIRE_PORT, &brd_temp, &brd_temp_frac);
+	pp_printf("temp:%d.%02d C", brd_temp, brd_temp_frac);
+
+	pp_printf("\n");
+	return 0;
+}
diff --git a/ppsi b/ppsi
new file mode 160000
index 0000000000000000000000000000000000000000..d3b860f2d0ca04cd041f08858d0fd1c5ad0f4835
--- /dev/null
+++ b/ppsi
@@ -0,0 +1 @@
+Subproject commit d3b860f2d0ca04cd041f08858d0fd1c5ad0f4835
diff --git a/shell/cmd_verbose.c b/shell/cmd_verbose.c
new file mode 100644
index 0000000000000000000000000000000000000000..8edd6065ac11b6ea40778326ffb6c1cb66d05979
--- /dev/null
+++ b/shell/cmd_verbose.c
@@ -0,0 +1,27 @@
+/*
+ * This work is part of the White Rabbit project
+ *
+ * Copyright (C) 2012 GSI (www.gsi.de)
+ * Author: Wesley W. Terpstra <w.terpstra@gsi.de>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ */
+
+#include <wrc.h>
+
+extern int pp_diag_verbosity;
+
+int cmd_verbose(const char *args[])
+{
+	int v;
+	v = args[0][0] - '0';
+
+	if (v < 0)
+		v = 0;
+	else if (v > 2)
+		v = 2;
+
+	pp_printf("PPSI verbosity set to %d\n", v);
+	pp_diag_verbosity = v;
+	return 0;
+}
diff --git a/shell/shell.c b/shell/shell.c
index 8f3e828bf40f65c9aaf6bd5b310bf1888cd81aa3..004f3f54a3934b53e2027f171a7f43b4f8dc56ee 100644
--- a/shell/shell.c
+++ b/shell/shell.c
@@ -60,6 +60,9 @@ static const struct shell_cmd cmds_list[] = {
 	{"init",	cmd_init},
 #ifdef CONFIG_ETHERBONE
 	{"ip",		cmd_ip},
+#endif
+#if (defined CONFIG_PPSI) && (defined CONFIG_PPSI_RUNTIME_VERBOSITY)
+	{"verbose", 	cmd_verbose},
 #endif
 	{"mac",		cmd_mac},
 	{"sdb",		cmd_sdb},
diff --git a/shell/shell.mk b/shell/shell.mk
index 3cc6111d8f39a521b8dfd64b3c50e9a29efdcfc2..c1c5afa8e531111369d08a205edf1c3e52a7548d 100644
--- a/shell/shell.mk
+++ b/shell/shell.mk
@@ -15,3 +15,4 @@ obj-y += \
 	shell/cmd_init.o
 
 obj-$(CONFIG_ETHERBONE) += shell/cmd_ip.o
+obj-$(CONFIG_PPSI_RUNTIME_VERBOSITY) += shell/cmd_verbose.o
diff --git a/tests/measure_t24p.c b/tests/measure_t24p.c
index 1ee21ab83a095aa9d0ecc7a9cfaa77eccad6b617..3f39fd55c782ea5cf2bc12d04cc6efb89f300501 100644
--- a/tests/measure_t24p.c
+++ b/tests/measure_t24p.c
@@ -24,7 +24,11 @@
 #undef PACKED
 #include "ptpd_netif.h"
 
+#ifdef CONFIG_PPSI
+#include <ppsi/ppsi.h>
+#else
 #include "ptpd.h"
+#endif
 
 #if 0 /* not used, currently */
 static int get_bitslide(int ep)
@@ -50,6 +54,70 @@ static void purge_socket(wr_socket_t *sock, char *buf)
 		update_rx_queues();
 }
 
+#ifdef CONFIG_PPSI
+
+extern struct pp_instance ppi_static;
+static struct pp_instance *ppi = &ppi_static;
+
+static int meas_phase_range(wr_socket_t * sock, int phase_min, int phase_max,
+			    int phase_step, struct meas_entry *results)
+{
+	char buf[128];
+	TimeInternal ts_rx, ts_sync = {0,};
+	MsgHeader *mhdr;
+	int setpoint = phase_min, i = 0, phase;
+
+	mhdr = &ppi->msg_tmp_header;
+
+	spll_set_phase_shift(SPLL_ALL_CHANNELS, phase_min);
+
+	while (spll_shifter_busy(0)) ;
+
+	purge_socket(sock, buf);
+
+	i = 0;
+	while (setpoint <= phase_max) {
+		ptpd_netif_get_dmtd_phase(sock, &phase);
+
+		update_rx_queues();
+		int n = pp_recv_packet(ppi, buf, 128, &ts_rx);
+
+		if (n > 0) {
+			msg_unpack_header(ppi, buf);
+			if (mhdr->messageType == 0)
+				assign_TimeInternal(&ts_sync, &ts_rx);
+			else if (mhdr->messageType == 8 && ts_sync.correct) {
+				MsgFollowUp fup;
+				msg_unpack_follow_up(buf, &fup);
+
+				mprintf("Shift: %d/%dps [step %dps]        \r",
+					setpoint, phase_max, phase_step);
+				results[i].phase = phase;
+				results[i].phase_sync = ts_sync.phase;
+				results[i].ahead = ts_sync.raw_ahead;
+				results[i].delta_ns =
+				    fup.preciseOriginTimestamp.
+				    nanosecondsField - ts_sync.nanoseconds;
+				results[i].delta_ns +=
+				    (fup.preciseOriginTimestamp.secondsField.
+				     lsb - ts_sync.seconds) * 1000000000;
+
+				setpoint += phase_step;
+				spll_set_phase_shift(0, setpoint);
+				while (spll_shifter_busy(0)) ;
+				purge_socket(sock, buf);
+
+				ts_sync.correct = 0;
+				i++;
+			}
+		}
+	}
+	mprintf("\n");
+	return i;
+}
+
+#else
+
 static int meas_phase_range(wr_socket_t * sock, int phase_min, int phase_max,
 			    int phase_step, struct meas_entry *results)
 {
@@ -105,6 +173,8 @@ static int meas_phase_range(wr_socket_t * sock, int phase_min, int phase_max,
 	return i;
 }
 
+#endif /* CONFIG_PPSI else CONFIG_PTPNOPOSIX*/
+
 static int find_transition(struct meas_entry *results, int n, int positive)
 {
 	int i;
@@ -125,6 +195,13 @@ int measure_t24p(int *value)
 	int i, nr;
 	struct meas_entry results[128];
 
+#ifdef CONFIG_PPSI
+	if (!NP(ppi)->inited) {
+		if (pp_net_init(ppi) < 0)
+			return -1;
+		NP(ppi)->inited = 1;
+	}
+#endif
 	spll_enable_ptracker(0, 1);
 
 	sock_addr.family = PTPD_SOCK_RAW_ETHERNET;	// socket type
@@ -181,6 +258,11 @@ int measure_t24p(int *value)
 	mprintf("Verification... \n");
 	nr = meas_phase_range(sock, 0, 16000, 500, results);
 
+#ifdef CONFIG_PPSI
+	pp_net_shutdown(ppi);
+	NP(ppi)->inited = 0;
+#endif
+
 	for (i = 0; i < nr; i++)
 		mprintf("phase_dmtd: %d delta_ns: %d, phase_sync: %d\n",
 			results[i].phase, results[i].delta_ns,
diff --git a/wrc_ptp.h b/wrc_ptp.h
index b9045fb325812d21481bc2aa27a01771c4983491..27aa6bda53c866adba4288a477016eb8a438aefe 100644
--- a/wrc_ptp.h
+++ b/wrc_ptp.h
@@ -5,6 +5,7 @@
 #define WRC_MODE_GM 1
 #define WRC_MODE_MASTER 2
 #define WRC_MODE_SLAVE 3
+extern int ptp_mode;
 
 int wrc_ptp_init();
 int wrc_ptp_set_mode(int mode);
diff --git a/wrc_ptp.c b/wrc_ptp_noposix.c
similarity index 98%
rename from wrc_ptp.c
rename to wrc_ptp_noposix.c
index be1a827847d0e0181e42dc1cf3fbed029fe90344..b0ac1292b81c99b107c6f96b7f1b494fc5aaeeac 100644
--- a/wrc_ptp.c
+++ b/wrc_ptp_noposix.c
@@ -58,7 +58,8 @@ static RunTimeOpts rtOpts = {
 
 static PtpPortDS *ptpPortDS;
 static PtpClockDS ptpClockDS;
-static int ptp_enabled = 0, ptp_mode = WRC_MODE_UNKNOWN;
+int ptp_mode = WRC_MODE_UNKNOWN;
+static int ptp_enabled = 0;
 
 int wrc_ptp_init()
 {
diff --git a/wrc_ptp_ppsi.c b/wrc_ptp_ppsi.c
new file mode 100644
index 0000000000000000000000000000000000000000..672dbfec6be791da64899e4c8f4753116d402138
--- /dev/null
+++ b/wrc_ptp_ppsi.c
@@ -0,0 +1,223 @@
+/*
+ * This work is part of the White Rabbit project
+ *
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Aurelio Colosimo <aurelio@aureliocolosimo.it>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ */
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <wrc.h>
+#include <minic.h>
+#include <spec.h>
+
+#include <ppsi/ppsi.h>
+#include <wr-constants.h>
+#include "syscon.h"
+#include "endpoint.h"
+#include "softpll_ng.h"
+#include "wrc_ptp.h"
+#include "pps_gen.h"
+#include "uart.h"
+
+int ptp_mode = WRC_MODE_UNKNOWN;
+static int ptp_enabled = 0, ptp_forced_stop = 0;
+struct pp_instance ppi_static; /* FIXME: no more static, because used in
+				   tests/measure_t24p.c */
+CONST_VERBOSITY int pp_diag_verbosity = CONFIG_PPSI_VERBOSITY;
+
+/*ppi fields*/
+static UInteger16 sent_seq_id[16];
+static DSDefault  defaultDS;
+static DSCurrent  currentDS;
+static DSParent   parentDS;
+static DSPort     portDS;
+static DSTimeProperties timePropertiesDS;
+static struct pp_net_path net_path;
+static struct pp_servo servo;
+static struct pp_frgn_master frgn_master;
+
+static int delay_ms = PP_DEFAULT_NEXT_DELAY_MS;
+static int start_tics = 0;
+static int last_link_up = 0;
+
+int wrc_ptp_init()
+{
+	struct pp_instance *ppi = &ppi_static; /* no malloc, one instance */
+	sdb_find_devices();
+	uart_init();
+
+	pp_printf("Spec: starting. Compiled on " __DATE__ "\n");
+
+	ppi->sent_seq_id = sent_seq_id;
+	ppi->defaultDS   = &defaultDS;
+	ppi->currentDS   = &currentDS;
+	ppi->parentDS    = &parentDS;
+	ppi->portDS      = &portDS;
+	ppi->timePropertiesDS = &timePropertiesDS;
+	ppi->net_path    = &net_path;
+	ppi->servo       = &servo;
+	ppi->frgn_master = &frgn_master;
+	ppi->arch_data   = NULL;
+
+	return 0;
+}
+
+#define LOCK_TIMEOUT_FM (4 * TICS_PER_SECOND)
+#define LOCK_TIMEOUT_GM (60 * TICS_PER_SECOND)
+
+int wrc_ptp_set_mode(int mode)
+{
+	uint32_t start_tics, lock_timeout = 0;
+	struct pp_instance *ppi = &ppi_static;
+
+	ptp_mode = 0;
+
+	wrc_ptp_stop();
+
+	switch (mode) {
+	case WRC_MODE_GM:
+		/* FIXME multiport rtOpts.primarySource = TRUE; */
+		DSPOR(ppi)->wrConfig = WR_M_ONLY;
+		OPTS(ppi)->master_only = TRUE;
+		OPTS(ppi)->slave_only = FALSE;
+		spll_init(SPLL_MODE_GRAND_MASTER, 0, 1);
+		lock_timeout = LOCK_TIMEOUT_GM;
+		break;
+
+	case WRC_MODE_MASTER:
+		/* FIXME multiport rtOpts.primarySource = FALSE; */
+		DSPOR(ppi)->wrConfig = WR_M_ONLY;
+		OPTS(ppi)->master_only = TRUE;
+		OPTS(ppi)->slave_only = FALSE;
+		spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
+		lock_timeout = LOCK_TIMEOUT_FM;
+		break;
+
+	case WRC_MODE_SLAVE:
+		/* FIXME multiport rtOpts.primarySource = FALSE; */
+		DSPOR(ppi)->wrConfig = WR_S_ONLY;
+		OPTS(ppi)->master_only = FALSE;
+		OPTS(ppi)->slave_only = TRUE;
+		spll_init(SPLL_MODE_SLAVE, 0, 1);
+		break;
+	}
+
+	start_tics = timer_get_tics();
+
+	pp_printf("Locking PLL");
+
+	shw_pps_gen_enable_output(0);
+
+	while (!spll_check_lock(0) && lock_timeout) {
+		timer_delay(TICS_PER_SECOND);
+		pp_printf(".");
+		if (timer_get_tics() - start_tics > lock_timeout) {
+			pp_printf("\nLock timeout.\n");
+			return -ETIMEDOUT;
+		} else if (uart_read_byte() == 27) {
+			pp_printf("\n");
+			return -EINTR;
+		}
+	}
+
+	if (mode == WRC_MODE_MASTER || mode == WRC_MODE_GM)
+		shw_pps_gen_enable_output(1);
+
+	pp_printf("\n");
+	ptp_mode = mode;
+	return 0;
+}
+
+int wrc_ptp_get_mode()
+{
+	return ptp_mode;
+}
+
+int wrc_ptp_start()
+{
+	struct pp_instance *ppi = &ppi_static;
+
+	pp_open_instance(ppi, 0 /* no opts */);
+	OPTS(ppi)->e2e_mode = 1;
+
+	/* Call the state machine. Being it in "Initializing" state, make
+	 * ppsi initialize what is necessary */
+	delay_ms = pp_state_machine(ppi, NULL, 0);
+	start_tics = timer_get_tics();
+
+	DSPOR(ppi)->linkUP = FALSE;
+	wr_servo_reset();
+
+	ptp_enabled = 1;
+	return 0;
+}
+
+int wrc_ptp_stop()
+{
+	ptp_enabled = 0;
+	wr_servo_reset();
+	pp_close_instance(&ppi_static);
+	return 0;
+}
+
+int wrc_ptp_update()
+{
+	int i;
+	struct pp_instance *ppi = &ppi_static;
+
+	int now_link_up;
+
+	now_link_up = ep_link_up(NULL);
+
+	if (last_link_up != now_link_up) {
+		last_link_up = now_link_up;
+		if (ptp_enabled && (!now_link_up)) {
+			wrc_ptp_stop();
+			ptp_forced_stop = 1;
+			pp_printf("Link down: PTP stop\n");
+		}
+		else {
+			if (ptp_forced_stop) {
+				pp_printf("Link up: PTP start\n");
+				ptp_forced_stop = 0;
+				wrc_ptp_start();
+			}
+		}
+	}
+
+	if (ptp_enabled) {
+		static unsigned char packet[500];
+
+		/*
+		 * We got a packet. If it's not ours, continue consuming
+		 * the pending timeout
+		 */
+		i = spec_recv_packet(ppi, packet, sizeof(packet),
+				     &ppi->last_rcv_time);
+		if ((!i) && (timer_get_tics() - start_tics < delay_ms))
+			return 0;
+		if (!i) {
+			/* Nothing received, but timeout elapsed */
+			start_tics = timer_get_tics();
+			delay_ms = pp_state_machine(ppi, NULL, 0);
+			return 0;
+		}
+		if (pp_diag_verbosity > 1) {
+			int j;
+			pp_printf("recvd: %i\n", i);
+			for (j = 0; j < i; j++) {
+				pp_printf("%02x ", packet[j]);
+				if( (j+1)%16==0 )
+					pp_printf("\n");
+			}
+			pp_printf("\n");
+		}
+		/* Warning: PP_ETHERTYPE is endian-agnostic by design */
+
+		delay_ms = pp_state_machine(ppi, packet, i);
+	}
+	return 0;
+}